├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── LICENSE ├── README.md ├── config.ini ├── data ├── background.png ├── bouncy_ball.png ├── bouncy_ball2.png ├── bouncy_ball3.png ├── icon.png ├── lightOverShapeShader.frag ├── lightOverShapeShader.vert ├── noise.png ├── penumbraTexture.png ├── pointLightTexture.png ├── sansation.ttf ├── unshadowShader.frag ├── unshadowShader.vert ├── wood_01_b.jpg ├── wood_crate_02.jpg ├── wood_crate_03.bmp ├── wood_crate_10.jpg └── wood_crate_12.jpg ├── sdl2d3_0.jpg ├── sdl2d3_1.jpg └── src ├── CMakeLists.txt ├── cmake ├── FindSFGUI.cmake └── FindSFML.cmake ├── extlibs └── CMakeLists.txt ├── main.cpp ├── sdl2d3 ├── components.h ├── events.h └── systems │ ├── Box2DSystem.cpp │ ├── Box2DSystem.h │ ├── LTBLSystem.cpp │ ├── LTBLSystem.h │ ├── SFGUISystem.cpp │ ├── SFGUISystem.h │ ├── TextureSystem.cpp │ └── TextureSystem.h └── utility ├── SFMLDebugDraw.cpp ├── SFMLDebugDraw.h ├── keyvalues.cpp ├── keyvalues.h ├── utility.cpp └── utility.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | 30 | #Backup files 31 | *~ 32 | 33 | #QT Creator 34 | *.pro.user 35 | 36 | #VsCode 37 | .vscode/ 38 | 39 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "src/extlibs/Box2D"] 2 | path = src/extlibs/Box2D 3 | url = https://github.com/erincatto/Box2D.git 4 | 5 | [submodule "src/extlibs/LTBL2"] 6 | path = src/extlibs/LTBL2 7 | url = https://github.com/222464/LTBL2.git 8 | 9 | [submodule "src/extlibs/entityx"] 10 | path = src/extlibs/entityx 11 | url = https://github.com/alecthomas/entityx.git 12 | 13 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #SDL2D3 CMake File 2 | cmake_minimum_required(VERSION 2.8) 3 | project(SDL2D3) 4 | 5 | if(CMAKE_VERSION VERSION_LESS "3.1") 6 | if(CMAKE_COMPILER_IS_GNUCXX) 7 | set(CMAKE_CXX_FLAGS "--std=c++14 ${CMAKE_CXX_FLAGS}") 8 | elseif(MSVC) 9 | #TODO 10 | else() 11 | message(Warning: Unknown compiler; Please set C++14 support in CMake) 12 | endif() 13 | else() 14 | set (CMAKE_CXX_STANDARD 14) 15 | endif() 16 | 17 | add_subdirectory(src) 18 | 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SDL2D3 2 | A project combining SFML Box2D LTBL2 SFGUI and EntityX. 3 | The primary purpose of this project is an example of combining the libraries in a small sandbox. 4 | 5 | ![Alt Text](sdl2d3_0.jpg) 6 | ================== 7 | ![Alt Text](sdl2d3_1.jpg) 8 | 9 | ## Requirements 10 | SFML and SFGUI are requred to be installed beforehand, while EntityX, Box2D and LTBL2 are included as submodules. 11 | - SFML 2.2+ (http://www.sfml-dev.org/download.php) 12 | - SFGUI 0.30+ (https://github.com/TankOs/SFGUI) 13 | 14 | ## Included Libraries 15 | - EntityX (https://github.com/alecthomas/entityx) 16 | - Box2D (https://github.com/erincatto/Box2D) 17 | - LTBL2 (https://github.com/222464/LTBL2) 18 | 19 | ## Building and Running 20 | Building requires GCC 4.9 or later, or any compiler with C++14 support. The `data` folder and `config.ini` (or .ini specified on ``argv[1]``) should be in the same directory as the built executable 21 | ``` 22 | cd SDL2D3/ 23 | git submodule init 24 | git submodule update 25 | mkdir build && cd build 26 | cmake .. 27 | make 28 | ``` 29 | 30 | This will build the executable SDL2D3 in the top-level directory. 31 | 32 | ## Controls 33 | Control | Action 34 | ----------| --------- 35 | Arrow Keys / WASD | Pan screen 36 | Mouse wheel | Zoom screen 37 | Mouse wheel + CTRL | Change light size 38 | Left click | Place box 39 | Right click | Place circle 40 | Middle click| Remove body at cursor 41 | -------------------------------------------------------------------------------- /config.ini: -------------------------------------------------------------------------------- 1 | ; Screen width, height, window icon 2 | WIDTH=1200 3 | HEIGHT=900 4 | ICON_TEXTURE=data/icon.png 5 | 6 | ; LTBL; The shader name for both .frag and .vert shaders, and textures 7 | LIGHT_OVER_SHADER=data/lightOverShapeShader 8 | LIGHT_UNSHADOW_SHADER=data/unshadowShader 9 | LIGHT_PRENUMBRA_TEXTURE=data/penumbraTexture.png 10 | LIGHT_POINT_TEXTURE=data/pointLightTexture.png 11 | 12 | ; Box2D Textures 13 | BOX_TEXTURES=data/wood_crate_03.bmp:data/wood_crate_12.jpg:data/wood_crate_02.jpg:data/wood_crate_10.jpg 14 | BALL_TEXTURES=data/bouncy_ball.png:data/bouncy_ball2.png:data/bouncy_ball3.png 15 | BACKGROUND_TEXTURE=data/noise.png 16 | OBJECT_FONT=data/sansation.ttf 17 | 18 | -------------------------------------------------------------------------------- /data/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamesrwaugh/SDL2D3/31e6d6ed6a74c7dba513303c7c3205b0be9a7a43/data/background.png -------------------------------------------------------------------------------- /data/bouncy_ball.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamesrwaugh/SDL2D3/31e6d6ed6a74c7dba513303c7c3205b0be9a7a43/data/bouncy_ball.png -------------------------------------------------------------------------------- /data/bouncy_ball2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamesrwaugh/SDL2D3/31e6d6ed6a74c7dba513303c7c3205b0be9a7a43/data/bouncy_ball2.png -------------------------------------------------------------------------------- /data/bouncy_ball3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamesrwaugh/SDL2D3/31e6d6ed6a74c7dba513303c7c3205b0be9a7a43/data/bouncy_ball3.png -------------------------------------------------------------------------------- /data/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamesrwaugh/SDL2D3/31e6d6ed6a74c7dba513303c7c3205b0be9a7a43/data/icon.png -------------------------------------------------------------------------------- /data/lightOverShapeShader.frag: -------------------------------------------------------------------------------- 1 | uniform sampler2D emissionTexture; 2 | 3 | uniform vec2 targetSizeInv; 4 | 5 | void main() { 6 | vec2 targetCoords = gl_FragCoord.xy * targetSizeInv; 7 | vec4 emissionColor = texture2D(emissionTexture, targetCoords); 8 | 9 | gl_FragColor = vec4(emissionColor.rgb, 1.0); 10 | } -------------------------------------------------------------------------------- /data/lightOverShapeShader.vert: -------------------------------------------------------------------------------- 1 | void main() { 2 | gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; 3 | 4 | gl_TexCoord[0] = gl_MultiTexCoord0; 5 | } -------------------------------------------------------------------------------- /data/noise.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamesrwaugh/SDL2D3/31e6d6ed6a74c7dba513303c7c3205b0be9a7a43/data/noise.png -------------------------------------------------------------------------------- /data/penumbraTexture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamesrwaugh/SDL2D3/31e6d6ed6a74c7dba513303c7c3205b0be9a7a43/data/penumbraTexture.png -------------------------------------------------------------------------------- /data/pointLightTexture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamesrwaugh/SDL2D3/31e6d6ed6a74c7dba513303c7c3205b0be9a7a43/data/pointLightTexture.png -------------------------------------------------------------------------------- /data/sansation.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamesrwaugh/SDL2D3/31e6d6ed6a74c7dba513303c7c3205b0be9a7a43/data/sansation.ttf -------------------------------------------------------------------------------- /data/unshadowShader.frag: -------------------------------------------------------------------------------- 1 | uniform sampler2D penumbraTexture; 2 | 3 | uniform float lightBrightness; 4 | uniform float darkBrightness; 5 | 6 | void main() { 7 | float penumbra = texture2D(penumbraTexture, gl_TexCoord[0].xy).x; 8 | 9 | float shadow = (lightBrightness - darkBrightness) * penumbra + darkBrightness; 10 | 11 | gl_FragColor = vec4(vec3(1.0 - shadow), 1.0); 12 | } -------------------------------------------------------------------------------- /data/unshadowShader.vert: -------------------------------------------------------------------------------- 1 | void main() { 2 | gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; 3 | 4 | gl_TexCoord[0] = gl_MultiTexCoord0; 5 | 6 | gl_FrontColor = gl_Color; 7 | } -------------------------------------------------------------------------------- /data/wood_01_b.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamesrwaugh/SDL2D3/31e6d6ed6a74c7dba513303c7c3205b0be9a7a43/data/wood_01_b.jpg -------------------------------------------------------------------------------- /data/wood_crate_02.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamesrwaugh/SDL2D3/31e6d6ed6a74c7dba513303c7c3205b0be9a7a43/data/wood_crate_02.jpg -------------------------------------------------------------------------------- /data/wood_crate_03.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamesrwaugh/SDL2D3/31e6d6ed6a74c7dba513303c7c3205b0be9a7a43/data/wood_crate_03.bmp -------------------------------------------------------------------------------- /data/wood_crate_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamesrwaugh/SDL2D3/31e6d6ed6a74c7dba513303c7c3205b0be9a7a43/data/wood_crate_10.jpg -------------------------------------------------------------------------------- /data/wood_crate_12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamesrwaugh/SDL2D3/31e6d6ed6a74c7dba513303c7c3205b0be9a7a43/data/wood_crate_12.jpg -------------------------------------------------------------------------------- /sdl2d3_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamesrwaugh/SDL2D3/31e6d6ed6a74c7dba513303c7c3205b0be9a7a43/sdl2d3_0.jpg -------------------------------------------------------------------------------- /sdl2d3_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamesrwaugh/SDL2D3/31e6d6ed6a74c7dba513303c7c3205b0be9a7a43/sdl2d3_1.jpg -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set (CMAKE_CXX_STANDARD 14) 2 | 3 | #For FindSFGUI.cmake and FindSFML.cmake 4 | set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/src//cmake) 5 | 6 | #Smaller External libraries as submodules (Box2D, LTBL, EntityX) 7 | add_subdirectory(extlibs) 8 | 9 | #SFML / SFGUI 10 | find_package(SFML 2 COMPONENTS system window graphics REQUIRED) 11 | find_package(SFGUI REQUIRED ) 12 | include_directories(${SFML_INCLUDE_DIR} ${SFGUI_INCLUDE_DIR}) 13 | 14 | #SDL2D3 Executable 15 | file(GLOB_RECURSE SDL2D3_SOURCES utility/*.cpp sdl2d3/*.cpp) 16 | add_executable(${PROJECT_NAME} main.cpp ${SDL2D3_SOURCES}) 17 | 18 | #Include directores for extlibs 19 | target_include_directories(${PROJECT_NAME} PUBLIC 20 | ${CMAKE_CURRENT_SOURCE_DIR} #Allows #include "utiity/..." and etc includes 21 | ${CMAKE_CURRENT_SOURCE_DIR}/extlibs 22 | ${CMAKE_CURRENT_SOURCE_DIR}/extlibs/LTBL2/LTBL2/source 23 | ${CMAKE_CURRENT_SOURCE_DIR}/extlibs/Box2D/Box2D 24 | ${CMAKE_CURRENT_SOURCE_DIR}/extlibs/entityx 25 | ) 26 | set_target_properties(${PROJECT_NAME} PROPERTIES 27 | RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR} 28 | ) 29 | target_link_libraries(${PROJECT_NAME} 30 | ${SFML_LIBRARY} 31 | ${SFGUI_LIBRARY} 32 | Box2D 33 | GL 34 | entityx 35 | LTBL2 36 | ) 37 | 38 | -------------------------------------------------------------------------------- /src/cmake/FindSFGUI.cmake: -------------------------------------------------------------------------------- 1 | # This script locates the SFGUI library 2 | # ------------------------------------ 3 | # 4 | # Usage 5 | # ----- 6 | # 7 | # You can enforce a specific version, one of either MAJOR.MINOR.REVISION, 8 | # MAJOR.MINOR or only MAJOR. If nothing is specified, the version won't 9 | # be checked i.e. any version will be accepted. SFGUI does not consist of 10 | # multiple components, so specifying COMPONENTS is not required. 11 | # 12 | # Example: 13 | # find_package( SFGUI ) // no specific version 14 | # find_package( SFGUI 0.2 ) // any 0.2 version 15 | # find_package( SFGUI 0.2.3 ) // version 0.2.3 or greater 16 | # 17 | # By default, the dynamic version of SFGUI will be found. To find the static 18 | # version instead, you must set the SFGUI_STATIC_LIBRARIES variable to TRUE 19 | # before calling find_package( SFGUI ). In that case, SFGUI_STATIC will also be 20 | # defined by this script. 21 | # 22 | # Example: 23 | # set( SFGUI_STATIC_LIBRARIES TRUE ) 24 | # find_package( SFGUI ) 25 | # 26 | # Since you have to link all of SFGUI's dependencies when you link SFGUI 27 | # statically, the variable SFGUI_DEPENDENCIES is also defined. See below 28 | # for a detailed description. 29 | # 30 | # On Mac OS X if SFGUI_STATIC_LIBRARIES is not set to TRUE then by default CMake 31 | # will search for frameworks unless CMAKE_FIND_FRAMEWORK is set to "NEVER". 32 | # Please refer to CMake documentation for more details. 33 | # Moreover, keep in mind that SFGUI frameworks are only available as release 34 | # libraries unlike dylibs which are available for both release and debug modes. 35 | # 36 | # If SFGUI is not installed in a standard path, you can use the SFGUI_ROOT 37 | # CMake (or environment) variable to tell CMake where to look for SFGUI. 38 | # 39 | # Output 40 | # ------ 41 | # 42 | # This script defines the following variables: 43 | # - SFGUI_LIBRARY_DEBUG: the path to the debug library 44 | # - SFGUI_LIBRARY_RELEASE: the path to the release library 45 | # - SFGUI_LIBRARY: the path to the library to link to 46 | # - SFGUI_FOUND: TRUE if the SFGUI library is found 47 | # - SFGUI_INCLUDE_DIR: the path where SFGUI headers are located (the directory containing the SFGUI/Config.hpp file) 48 | # - SFGUI_DEPENDENCIES: the list of libraries SFGUI depends on, in case of static linking 49 | # 50 | # Example (dynamic linking): 51 | # find_package( SFGUI REQUIRED ) 52 | # include_directories( ${SFGUI_INCLUDE_DIR} ) 53 | # add_executable( myapp ... ) 54 | # target_link_libraries( myapp ${SFGUI_LIBRARY} ... ) 55 | # 56 | # Example (static linking): 57 | # set( SFGUI_STATIC_LIBRARIES TRUE ) 58 | # find_package( SFGUI REQUIRED ) 59 | # include_directories( ${SFGUI_INCLUDE_DIR} ) 60 | # add_executable( myapp ... ) 61 | # target_link_libraries( myapp ${SFGUI_LIBRARY} ${SFGUI_DEPENDENCIES} ... ) 62 | 63 | if( SFGUI_STATIC_LIBRARIES ) 64 | add_definitions( -DSFGUI_STATIC ) 65 | endif() 66 | 67 | set( 68 | SFGUI_SEARCH_PATHS 69 | "${SFGUI_ROOT}" 70 | "$ENV{SFGUI_ROOT}" 71 | ~/Library/Frameworks 72 | /Library/Frameworks 73 | /usr/local 74 | /usr 75 | /sw 76 | /opt/local 77 | /opt/csw 78 | /opt 79 | ) 80 | 81 | find_path( 82 | SFGUI_INCLUDE_DIR 83 | SFGUI/Config.hpp 84 | PATH_SUFFIXES 85 | include 86 | PATHS 87 | ${SFGUI_SEARCH_PATHS} 88 | ) 89 | 90 | set( SFGUI_VERSION_OK true ) 91 | if( SFGUI_FIND_VERSION AND SFGUI_INCLUDE_DIR ) 92 | file( READ "${SFGUI_INCLUDE_DIR}/SFGUI/Config.hpp" SFGUI_CONFIG_HPP ) 93 | 94 | string( REGEX MATCH ".*#define SFGUI_MAJOR_VERSION ([0-9]+).*#define SFGUI_MINOR_VERSION ([0-9]+).*#define SFGUI_REVISION_VERSION ([0-9]+).*" SFGUI_CONFIG_HPP "${SFGUI_CONFIG_HPP}" ) 95 | string( REGEX REPLACE ".*#define SFGUI_MAJOR_VERSION ([0-9]+).*" "\\1" SFGUI_VERSION_MAJOR "${SFGUI_CONFIG_HPP}" ) 96 | string( REGEX REPLACE ".*#define SFGUI_MINOR_VERSION ([0-9]+).*" "\\1" SFGUI_VERSION_MINOR "${SFGUI_CONFIG_HPP}" ) 97 | string( REGEX REPLACE ".*#define SFGUI_REVISION_VERSION ([0-9]+).*" "\\1" SFGUI_VERSION_PATCH "${SFGUI_CONFIG_HPP}" ) 98 | 99 | math( EXPR SFGUI_REQUESTED_VERSION "${SFGUI_FIND_VERSION_MAJOR} * 10000 + ${SFGUI_FIND_VERSION_MINOR} * 100 + ${SFGUI_FIND_VERSION_PATCH}" ) 100 | 101 | if( SFGUI_VERSION_MAJOR OR SFGUI_VERSION_MINOR OR SFGUI_VERSION_PATCH ) 102 | math( EXPR SFGUI_VERSION "${SFGUI_VERSION_MAJOR} * 10000 + ${SFGUI_VERSION_MINOR} * 100 + ${SFGUI_VERSION_PATCH}" ) 103 | 104 | if( SFGUI_VERSION LESS SFGUI_REQUESTED_VERSION ) 105 | set( SFGUI_VERSION_OK false ) 106 | endif() 107 | else() 108 | # SFGUI version is < 0.3.0 109 | if( SFGUI_REQUESTED_VERSION GREATER 300 ) 110 | set( SFGUI_VERSION_OK false ) 111 | set( SFGUI_VERSION_MAJOR 0 ) 112 | set( SFGUI_VERSION_MINOR x ) 113 | set( SFGUI_VERSION_PATCH y ) 114 | endif() 115 | endif() 116 | endif() 117 | 118 | find_library( 119 | SFGUI_LIBRARY_DYNAMIC_RELEASE 120 | NAMES 121 | sfgui 122 | PATH_SUFFIXES 123 | lib 124 | lib64 125 | PATHS 126 | ${SFGUI_SEARCH_PATHS} 127 | ) 128 | 129 | find_library( 130 | SFGUI_LIBRARY_DYNAMIC_DEBUG 131 | NAMES 132 | sfgui-d 133 | PATH_SUFFIXES 134 | lib 135 | lib64 136 | PATHS 137 | ${SFGUI_SEARCH_PATHS} 138 | ) 139 | 140 | find_library( 141 | SFGUI_LIBRARY_STATIC_RELEASE 142 | NAMES 143 | sfgui-s 144 | PATH_SUFFIXES 145 | lib 146 | lib64 147 | PATHS 148 | ${SFGUI_SEARCH_PATHS} 149 | ) 150 | 151 | find_library( 152 | SFGUI_LIBRARY_STATIC_DEBUG 153 | NAMES 154 | sfgui-s-d 155 | PATH_SUFFIXES 156 | lib 157 | lib64 158 | PATHS 159 | ${SFGUI_SEARCH_PATHS} 160 | ) 161 | 162 | if( SFGUI_STATIC_LIBRARIES ) 163 | if( SFGUI_LIBRARY_STATIC_RELEASE ) 164 | set( SFGUI_LIBRARY_RELEASE "${SFGUI_LIBRARY_STATIC_RELEASE}" ) 165 | endif() 166 | if( SFGUI_LIBRARY_STATIC_DEBUG ) 167 | set( SFGUI_LIBRARY_DEBUG "${SFGUI_LIBRARY_STATIC_DEBUG}" ) 168 | endif() 169 | else() 170 | if( SFGUI_LIBRARY_DYNAMIC_RELEASE ) 171 | set( SFGUI_LIBRARY_RELEASE "${SFGUI_LIBRARY_DYNAMIC_RELEASE}" ) 172 | endif() 173 | if( SFGUI_LIBRARY_DYNAMIC_DEBUG ) 174 | set( SFGUI_LIBRARY_DEBUG "${SFGUI_LIBRARY_DYNAMIC_DEBUG}" ) 175 | endif() 176 | endif() 177 | 178 | mark_as_advanced( 179 | SFGUI_LIBRARY_STATIC_RELEASE 180 | SFGUI_LIBRARY_STATIC_DEBUG 181 | SFGUI_LIBRARY_DYNAMIC_RELEASE 182 | SFGUI_LIBRARY_DYNAMIC_DEBUG 183 | ) 184 | 185 | if( SFGUI_LIBRARY_RELEASE OR SFGUI_LIBRARY_DEBUG ) 186 | if( SFGUI_LIBRARY_RELEASE AND SFGUI_LIBRARY_DEBUG ) 187 | set( SFGUI_LIBRARY debug "${SFGUI_LIBRARY_DEBUG}" optimized "${SFGUI_LIBRARY_RELEASE}" ) 188 | elseif( SFGUI_LIBRARY_DEBUG AND NOT SFGUI_LIBRARY_RELEASE ) 189 | set( SFGUI_LIBRARY_RELEASE "${SFGUI_LIBRARY_DEBUG}" ) 190 | set( SFGUI_LIBRARY "${SFGUI_LIBRARY_DEBUG}" ) 191 | elseif( SFGUI_LIBRARY_RELEASE AND NOT SFGUI_LIBRARY_DEBUG ) 192 | set( SFGUI_LIBRARY_DEBUG "${SFGUI_LIBRARY_RELEASE}" ) 193 | set( SFGUI_LIBRARY "${SFGUI_LIBRARY_RELEASE}" ) 194 | endif() 195 | 196 | set( SFGUI_FOUND true ) 197 | else() 198 | set( SFGUI_LIBRARY "" ) 199 | set( SFGUI_FOUND false ) 200 | endif() 201 | 202 | mark_as_advanced( 203 | SFGUI_LIBRARY 204 | SFGUI_LIBRARY_RELEASE 205 | SFGUI_LIBRARY_DEBUG 206 | ) 207 | 208 | if( SFGUI_STATIC_LIBRARIES ) 209 | set( SFGUI_DEPENDENCIES ) 210 | set( SFGUI_MISSING_DEPENDENCIES ) 211 | 212 | if( "${CMAKE_SYSTEM_NAME}" MATCHES "Linux" ) 213 | find_library( X11_LIBRARY NAMES X11 PATHS ${SFGUI_SEARCH_PATHS} PATH_SUFFIXES lib ) 214 | 215 | if( ${X11_LIBRARY} STREQUAL "X11_LIBRARY-NOTFOUND" ) 216 | unset( X11_LIBRARY ) 217 | set( SFGUI_MISSING_DEPENDENCIES "${SFGUI_MISSING_DEPENDENCIES} X11" ) 218 | endif() 219 | endif() 220 | 221 | if( "${CMAKE_SYSTEM_NAME}" MATCHES "Windows" ) 222 | set( SFGUI_DEPENDENCIES ${SFGUI_DEPENDENCIES} "opengl32" ) 223 | elseif( ( "${CMAKE_SYSTEM_NAME}" MATCHES "Linux" ) OR ( "${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD" ) ) 224 | set( SFGUI_DEPENDENCIES ${SFGUI_DEPENDENCIES} "GL" ${X11_LIBRARY} ) 225 | elseif( "${CMAKE_SYSTEM_NAME}" MATCHES "Darwin" ) 226 | set( SFGUI_DEPENDENCIES ${SFGUI_DEPENDENCIES} "-framework OpenGL -framework Foundation" ) 227 | endif() 228 | endif() 229 | 230 | if( NOT SFGUI_INCLUDE_DIR OR NOT SFGUI_LIBRARY ) 231 | set( SFGUI_FOUND false ) 232 | endif() 233 | 234 | if( NOT SFGUI_FOUND ) 235 | set( FIND_SFGUI_ERROR "SFGUI not found." ) 236 | elseif( NOT SFGUI_VERSION_OK ) 237 | set( FIND_SFGUI_ERROR "SFGUI found but version too low, requested: ${SFGUI_FIND_VERSION}, found: ${SFGUI_VERSION_MAJOR}.${SFGUI_VERSION_MINOR}.${SFGUI_VERSION_PATCH}" ) 238 | set( SFGUI_FOUND false ) 239 | elseif( SFGUI_STATIC_LIBRARIES AND SFGUI_MISSING_DEPENDENCIES ) 240 | set( FIND_SFGUI_ERROR "SFGUI found but some of its dependencies are missing: ${SFGUI_MISSING_DEPENDENCIES}" ) 241 | set( SFGUI_FOUND false ) 242 | endif() 243 | 244 | if( NOT SFGUI_FOUND ) 245 | if( SFGUI_FIND_REQUIRED ) 246 | message( FATAL_ERROR "${FIND_SFGUI_ERROR}" ) 247 | elseif( NOT SFGUI_FIND_QUIETLY ) 248 | message( "${FIND_SFGUI_ERROR}" ) 249 | endif() 250 | else() 251 | if( SFGUI_FIND_VERSION ) 252 | message( STATUS "Found SFGUI version ${SFGUI_VERSION_MAJOR}.${SFGUI_VERSION_MINOR}.${SFGUI_VERSION_PATCH} in ${SFGUI_INCLUDE_DIR}" ) 253 | else() 254 | message( STATUS "Found SFGUI in ${SFGUI_INCLUDE_DIR}" ) 255 | endif() 256 | endif() 257 | -------------------------------------------------------------------------------- /src/cmake/FindSFML.cmake: -------------------------------------------------------------------------------- 1 | # This script locates the SFML library 2 | # ------------------------------------ 3 | # 4 | # Usage 5 | # ----- 6 | # 7 | # When you try to locate the SFML libraries, you must specify which modules you want to use (system, window, graphics, network, audio, main). 8 | # If none is given, the SFML_LIBRARIES variable will be empty and you'll end up linking to nothing. 9 | # example: 10 | # find_package(SFML COMPONENTS graphics window system) # find the graphics, window and system modules 11 | # 12 | # You can enforce a specific version, either MAJOR.MINOR or only MAJOR. 13 | # If nothing is specified, the version won't be checked (i.e. any version will be accepted). 14 | # example: 15 | # find_package(SFML COMPONENTS ...) # no specific version required 16 | # find_package(SFML 2 COMPONENTS ...) # any 2.x version 17 | # find_package(SFML 2.4 COMPONENTS ...) # version 2.4 or greater 18 | # 19 | # By default, the dynamic libraries of SFML will be found. To find the static ones instead, 20 | # you must set the SFML_STATIC_LIBRARIES variable to TRUE before calling find_package(SFML ...). 21 | # Since you have to link yourself all the SFML dependencies when you link it statically, the following 22 | # additional variables are defined: SFML_XXX_DEPENDENCIES and SFML_DEPENDENCIES (see their detailed 23 | # description below). 24 | # In case of static linking, the SFML_STATIC macro will also be defined by this script. 25 | # example: 26 | # set(SFML_STATIC_LIBRARIES TRUE) 27 | # find_package(SFML 2 COMPONENTS network system) 28 | # 29 | # On Mac OS X if SFML_STATIC_LIBRARIES is not set to TRUE then by default CMake will search for frameworks unless 30 | # CMAKE_FIND_FRAMEWORK is set to "NEVER" for example. Please refer to CMake documentation for more details. 31 | # Moreover, keep in mind that SFML frameworks are only available as release libraries unlike dylibs which 32 | # are available for both release and debug modes. 33 | # 34 | # If SFML is not installed in a standard path, you can use the SFML_ROOT CMake (or environment) variable 35 | # to tell CMake where SFML is. 36 | # 37 | # Output 38 | # ------ 39 | # 40 | # This script defines the following variables: 41 | # - For each specified module XXX (system, window, graphics, network, audio, main): 42 | # - SFML_XXX_LIBRARY_DEBUG: the name of the debug library of the xxx module (set to SFML_XXX_LIBRARY_RELEASE is no debug version is found) 43 | # - SFML_XXX_LIBRARY_RELEASE: the name of the release library of the xxx module (set to SFML_XXX_LIBRARY_DEBUG is no release version is found) 44 | # - SFML_XXX_LIBRARY: the name of the library to link to for the xxx module (includes both debug and optimized names if necessary) 45 | # - SFML_XXX_FOUND: true if either the debug or release library of the xxx module is found 46 | # - SFML_XXX_DEPENDENCIES: the list of libraries the module depends on, in case of static linking 47 | # - SFML_LIBRARIES: the list of all libraries corresponding to the required modules 48 | # - SFML_FOUND: true if all the required modules are found 49 | # - SFML_INCLUDE_DIR: the path where SFML headers are located (the directory containing the SFML/Config.hpp file) 50 | # - SFML_DEPENDENCIES: the list of libraries SFML depends on, in case of static linking 51 | # 52 | # example: 53 | # find_package(SFML 2 COMPONENTS system window graphics audio REQUIRED) 54 | # include_directories(${SFML_INCLUDE_DIR}) 55 | # add_executable(myapp ...) 56 | # target_link_libraries(myapp ${SFML_LIBRARIES}) 57 | 58 | # define the SFML_STATIC macro if static build was chosen 59 | if(SFML_STATIC_LIBRARIES) 60 | add_definitions(-DSFML_STATIC) 61 | endif() 62 | 63 | # define the list of search paths for headers and libraries 64 | set(FIND_SFML_PATHS 65 | ${SFML_ROOT} 66 | $ENV{SFML_ROOT} 67 | ~/Library/Frameworks 68 | /Library/Frameworks 69 | /usr/local 70 | /usr 71 | /sw 72 | /opt/local 73 | /opt/csw 74 | /opt) 75 | 76 | # find the SFML include directory 77 | find_path(SFML_INCLUDE_DIR SFML/Config.hpp 78 | PATH_SUFFIXES include 79 | PATHS ${FIND_SFML_PATHS}) 80 | 81 | # check the version number 82 | set(SFML_VERSION_OK TRUE) 83 | if(SFML_FIND_VERSION AND SFML_INCLUDE_DIR) 84 | # extract the major and minor version numbers from SFML/Config.hpp 85 | # we have to handle framework a little bit differently: 86 | if("${SFML_INCLUDE_DIR}" MATCHES "SFML.framework") 87 | set(SFML_CONFIG_HPP_INPUT "${SFML_INCLUDE_DIR}/Headers/Config.hpp") 88 | else() 89 | set(SFML_CONFIG_HPP_INPUT "${SFML_INCLUDE_DIR}/SFML/Config.hpp") 90 | endif() 91 | FILE(READ "${SFML_CONFIG_HPP_INPUT}" SFML_CONFIG_HPP_CONTENTS) 92 | STRING(REGEX REPLACE ".*#define SFML_VERSION_MAJOR ([0-9]+).*" "\\1" SFML_VERSION_MAJOR "${SFML_CONFIG_HPP_CONTENTS}") 93 | STRING(REGEX REPLACE ".*#define SFML_VERSION_MINOR ([0-9]+).*" "\\1" SFML_VERSION_MINOR "${SFML_CONFIG_HPP_CONTENTS}") 94 | STRING(REGEX REPLACE ".*#define SFML_VERSION_PATCH ([0-9]+).*" "\\1" SFML_VERSION_PATCH "${SFML_CONFIG_HPP_CONTENTS}") 95 | if (NOT "${SFML_VERSION_PATCH}" MATCHES "^[0-9]+$") 96 | set(SFML_VERSION_PATCH 0) 97 | endif() 98 | math(EXPR SFML_REQUESTED_VERSION "${SFML_FIND_VERSION_MAJOR} * 10000 + ${SFML_FIND_VERSION_MINOR} * 100 + ${SFML_FIND_VERSION_PATCH}") 99 | 100 | # if we could extract them, compare with the requested version number 101 | if (SFML_VERSION_MAJOR) 102 | # transform version numbers to an integer 103 | math(EXPR SFML_VERSION "${SFML_VERSION_MAJOR} * 10000 + ${SFML_VERSION_MINOR} * 100 + ${SFML_VERSION_PATCH}") 104 | 105 | # compare them 106 | if(SFML_VERSION LESS SFML_REQUESTED_VERSION) 107 | set(SFML_VERSION_OK FALSE) 108 | endif() 109 | else() 110 | # SFML version is < 2.0 111 | if (SFML_REQUESTED_VERSION GREATER 10900) 112 | set(SFML_VERSION_OK FALSE) 113 | set(SFML_VERSION_MAJOR 1) 114 | set(SFML_VERSION_MINOR x) 115 | set(SFML_VERSION_PATCH x) 116 | endif() 117 | endif() 118 | endif() 119 | 120 | # find the requested modules 121 | set(SFML_FOUND TRUE) # will be set to false if one of the required modules is not found 122 | foreach(FIND_SFML_COMPONENT ${SFML_FIND_COMPONENTS}) 123 | string(TOLOWER ${FIND_SFML_COMPONENT} FIND_SFML_COMPONENT_LOWER) 124 | string(TOUPPER ${FIND_SFML_COMPONENT} FIND_SFML_COMPONENT_UPPER) 125 | set(FIND_SFML_COMPONENT_NAME sfml-${FIND_SFML_COMPONENT_LOWER}) 126 | 127 | # no suffix for sfml-main, it is always a static library 128 | if(FIND_SFML_COMPONENT_LOWER STREQUAL "main") 129 | # release library 130 | find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE 131 | NAMES ${FIND_SFML_COMPONENT_NAME} 132 | PATH_SUFFIXES lib64 lib 133 | PATHS ${FIND_SFML_PATHS}) 134 | 135 | # debug library 136 | find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG 137 | NAMES ${FIND_SFML_COMPONENT_NAME}-d 138 | PATH_SUFFIXES lib64 lib 139 | PATHS ${FIND_SFML_PATHS}) 140 | else() 141 | # static release library 142 | find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_RELEASE 143 | NAMES ${FIND_SFML_COMPONENT_NAME}-s 144 | PATH_SUFFIXES lib64 lib 145 | PATHS ${FIND_SFML_PATHS}) 146 | 147 | # static debug library 148 | find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_DEBUG 149 | NAMES ${FIND_SFML_COMPONENT_NAME}-s-d 150 | PATH_SUFFIXES lib64 lib 151 | PATHS ${FIND_SFML_PATHS}) 152 | 153 | # dynamic release library 154 | find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_RELEASE 155 | NAMES ${FIND_SFML_COMPONENT_NAME} 156 | PATH_SUFFIXES lib64 lib 157 | PATHS ${FIND_SFML_PATHS}) 158 | 159 | # dynamic debug library 160 | find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_DEBUG 161 | NAMES ${FIND_SFML_COMPONENT_NAME}-d 162 | PATH_SUFFIXES lib64 lib 163 | PATHS ${FIND_SFML_PATHS}) 164 | 165 | # choose the entries that fit the requested link type 166 | if(SFML_STATIC_LIBRARIES) 167 | if(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_RELEASE) 168 | set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_RELEASE}) 169 | endif() 170 | if(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_DEBUG) 171 | set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_DEBUG}) 172 | endif() 173 | else() 174 | if(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_RELEASE) 175 | set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_RELEASE}) 176 | endif() 177 | if(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_DEBUG) 178 | set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_DEBUG}) 179 | endif() 180 | endif() 181 | endif() 182 | 183 | if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG OR SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE) 184 | # library found 185 | set(SFML_${FIND_SFML_COMPONENT_UPPER}_FOUND TRUE) 186 | 187 | # if both are found, set SFML_XXX_LIBRARY to contain both 188 | if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG AND SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE) 189 | set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY debug ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG} 190 | optimized ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE}) 191 | endif() 192 | 193 | # if only one debug/release variant is found, set the other to be equal to the found one 194 | if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG AND NOT SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE) 195 | # debug and not release 196 | set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG}) 197 | set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG}) 198 | endif() 199 | if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE AND NOT SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG) 200 | # release and not debug 201 | set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE}) 202 | set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE}) 203 | endif() 204 | else() 205 | # library not found 206 | set(SFML_FOUND FALSE) 207 | set(SFML_${FIND_SFML_COMPONENT_UPPER}_FOUND FALSE) 208 | set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY "") 209 | set(FIND_SFML_MISSING "${FIND_SFML_MISSING} SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY") 210 | endif() 211 | 212 | # mark as advanced 213 | MARK_AS_ADVANCED(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY 214 | SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE 215 | SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG 216 | SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_RELEASE 217 | SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_DEBUG 218 | SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_RELEASE 219 | SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_DEBUG) 220 | 221 | # add to the global list of libraries 222 | set(SFML_LIBRARIES ${SFML_LIBRARIES} "${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY}") 223 | endforeach() 224 | 225 | # in case of static linking, we must also define the list of all the dependencies of SFML libraries 226 | if(SFML_STATIC_LIBRARIES) 227 | 228 | # detect the OS 229 | if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") 230 | set(FIND_SFML_OS_WINDOWS 1) 231 | elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") 232 | set(FIND_SFML_OS_LINUX 1) 233 | elseif(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") 234 | set(FIND_SFML_OS_FREEBSD 1) 235 | elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") 236 | set(FIND_SFML_OS_MACOSX 1) 237 | endif() 238 | 239 | # start with an empty list 240 | set(SFML_DEPENDENCIES) 241 | set(FIND_SFML_DEPENDENCIES_NOTFOUND) 242 | 243 | # macro that searches for a 3rd-party library 244 | macro(find_sfml_dependency output friendlyname) 245 | # No lookup in environment variables (PATH on Windows), as they may contain wrong library versions 246 | find_library(${output} NAMES ${ARGN} PATHS ${FIND_SFML_PATHS} PATH_SUFFIXES lib NO_SYSTEM_ENVIRONMENT_PATH) 247 | if(${${output}} STREQUAL "${output}-NOTFOUND") 248 | unset(output) 249 | set(FIND_SFML_DEPENDENCIES_NOTFOUND "${FIND_SFML_DEPENDENCIES_NOTFOUND} ${friendlyname}") 250 | endif() 251 | endmacro() 252 | 253 | # sfml-system 254 | list(FIND SFML_FIND_COMPONENTS "system" FIND_SFML_SYSTEM_COMPONENT) 255 | if(NOT ${FIND_SFML_SYSTEM_COMPONENT} EQUAL -1) 256 | 257 | # update the list -- these are only system libraries, no need to find them 258 | if(FIND_SFML_OS_LINUX OR FIND_SFML_OS_FREEBSD OR FIND_SFML_OS_MACOSX) 259 | set(SFML_SYSTEM_DEPENDENCIES "pthread") 260 | endif() 261 | if(FIND_SFML_OS_LINUX) 262 | set(SFML_SYSTEM_DEPENDENCIES ${SFML_SYSTEM_DEPENDENCIES} "rt") 263 | endif() 264 | if(FIND_SFML_OS_WINDOWS) 265 | set(SFML_SYSTEM_DEPENDENCIES "winmm") 266 | endif() 267 | set(SFML_DEPENDENCIES ${SFML_SYSTEM_DEPENDENCIES} ${SFML_DEPENDENCIES}) 268 | endif() 269 | 270 | # sfml-network 271 | list(FIND SFML_FIND_COMPONENTS "network" FIND_SFML_NETWORK_COMPONENT) 272 | if(NOT ${FIND_SFML_NETWORK_COMPONENT} EQUAL -1) 273 | 274 | # update the list -- these are only system libraries, no need to find them 275 | if(FIND_SFML_OS_WINDOWS) 276 | set(SFML_NETWORK_DEPENDENCIES "ws2_32") 277 | endif() 278 | set(SFML_DEPENDENCIES ${SFML_NETWORK_DEPENDENCIES} ${SFML_DEPENDENCIES}) 279 | endif() 280 | 281 | # sfml-window 282 | list(FIND SFML_FIND_COMPONENTS "window" FIND_SFML_WINDOW_COMPONENT) 283 | if(NOT ${FIND_SFML_WINDOW_COMPONENT} EQUAL -1) 284 | 285 | # find libraries 286 | if(FIND_SFML_OS_LINUX OR FIND_SFML_OS_FREEBSD) 287 | find_sfml_dependency(X11_LIBRARY "X11" X11) 288 | find_sfml_dependency(LIBXCB_LIBRARIES "XCB" xcb libxcb) 289 | find_sfml_dependency(X11_XCB_LIBRARY "X11-xcb" X11-xcb libX11-xcb) 290 | find_sfml_dependency(XCB_RANDR_LIBRARY "xcb-randr" xcb-randr libxcb-randr) 291 | find_sfml_dependency(XCB_IMAGE_LIBRARY "xcb-image" xcb-image libxcb-image) 292 | endif() 293 | 294 | if(FIND_SFML_OS_LINUX) 295 | find_sfml_dependency(UDEV_LIBRARIES "UDev" udev libudev) 296 | endif() 297 | 298 | # update the list 299 | if(FIND_SFML_OS_WINDOWS) 300 | set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "opengl32" "winmm" "gdi32") 301 | elseif(FIND_SFML_OS_LINUX) 302 | set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "GL" ${X11_LIBRARY} ${LIBXCB_LIBRARIES} ${X11_XCB_LIBRARY} ${XCB_RANDR_LIBRARY} ${XCB_IMAGE_LIBRARY} ${UDEV_LIBRARIES}) 303 | elseif(FIND_SFML_OS_FREEBSD) 304 | set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "GL" ${X11_LIBRARY} ${LIBXCB_LIBRARIES} ${X11_XCB_LIBRARY} ${XCB_RANDR_LIBRARY} ${XCB_IMAGE_LIBRARY} "usbhid") 305 | elseif(FIND_SFML_OS_MACOSX) 306 | set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "-framework OpenGL -framework Foundation -framework AppKit -framework IOKit -framework Carbon") 307 | endif() 308 | set(SFML_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} ${SFML_DEPENDENCIES}) 309 | endif() 310 | 311 | # sfml-graphics 312 | list(FIND SFML_FIND_COMPONENTS "graphics" FIND_SFML_GRAPHICS_COMPONENT) 313 | if(NOT ${FIND_SFML_GRAPHICS_COMPONENT} EQUAL -1) 314 | 315 | # find libraries 316 | find_sfml_dependency(FREETYPE_LIBRARY "FreeType" freetype) 317 | find_sfml_dependency(JPEG_LIBRARY "libjpeg" jpeg) 318 | 319 | # update the list 320 | set(SFML_GRAPHICS_DEPENDENCIES ${FREETYPE_LIBRARY} ${JPEG_LIBRARY}) 321 | set(SFML_DEPENDENCIES ${SFML_GRAPHICS_DEPENDENCIES} ${SFML_DEPENDENCIES}) 322 | endif() 323 | 324 | # sfml-audio 325 | list(FIND SFML_FIND_COMPONENTS "audio" FIND_SFML_AUDIO_COMPONENT) 326 | if(NOT ${FIND_SFML_AUDIO_COMPONENT} EQUAL -1) 327 | 328 | # find libraries 329 | find_sfml_dependency(OPENAL_LIBRARY "OpenAL" openal openal32) 330 | find_sfml_dependency(OGG_LIBRARY "Ogg" ogg) 331 | find_sfml_dependency(VORBIS_LIBRARY "Vorbis" vorbis) 332 | find_sfml_dependency(VORBISFILE_LIBRARY "VorbisFile" vorbisfile) 333 | find_sfml_dependency(VORBISENC_LIBRARY "VorbisEnc" vorbisenc) 334 | find_sfml_dependency(FLAC_LIBRARY "FLAC" FLAC) 335 | 336 | # update the list 337 | set(SFML_AUDIO_DEPENDENCIES ${OPENAL_LIBRARY} ${FLAC_LIBRARY} ${VORBISENC_LIBRARY} ${VORBISFILE_LIBRARY} ${VORBIS_LIBRARY} ${OGG_LIBRARY}) 338 | set(SFML_DEPENDENCIES ${SFML_DEPENDENCIES} ${SFML_AUDIO_DEPENDENCIES}) 339 | endif() 340 | 341 | endif() 342 | 343 | # handle errors 344 | if(NOT SFML_VERSION_OK) 345 | # SFML version not ok 346 | set(FIND_SFML_ERROR "SFML found but version too low (requested: ${SFML_FIND_VERSION}, found: ${SFML_VERSION_MAJOR}.${SFML_VERSION_MINOR}.${SFML_VERSION_PATCH})") 347 | set(SFML_FOUND FALSE) 348 | elseif(SFML_STATIC_LIBRARIES AND FIND_SFML_DEPENDENCIES_NOTFOUND) 349 | set(FIND_SFML_ERROR "SFML found but some of its dependencies are missing (${FIND_SFML_DEPENDENCIES_NOTFOUND})") 350 | set(SFML_FOUND FALSE) 351 | elseif(NOT SFML_FOUND) 352 | # include directory or library not found 353 | set(FIND_SFML_ERROR "Could NOT find SFML (missing: ${FIND_SFML_MISSING})") 354 | endif() 355 | if (NOT SFML_FOUND) 356 | if(SFML_FIND_REQUIRED) 357 | # fatal error 358 | message(FATAL_ERROR ${FIND_SFML_ERROR}) 359 | elseif(NOT SFML_FIND_QUIETLY) 360 | # error but continue 361 | message("${FIND_SFML_ERROR}") 362 | endif() 363 | endif() 364 | 365 | # handle success 366 | if(SFML_FOUND AND NOT SFML_FIND_QUIETLY) 367 | message(STATUS "Found SFML ${SFML_VERSION_MAJOR}.${SFML_VERSION_MINOR}.${SFML_VERSION_PATCH} in ${SFML_INCLUDE_DIR}") 368 | endif() 369 | -------------------------------------------------------------------------------- /src/extlibs/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(LTBL2/LTBL2) 2 | 3 | set(ENTITYX_BUILD_TESTING false CACHE BOOL "Enable building of tests.") 4 | set(ENTITYX_RUN_BENCHMARKS false CACHE BOOL "Run benchmarks (in conjunction with -DENTITYX_BUILD_TESTING=1).") 5 | set(ENTITYX_MAX_COMPONENTS 64 CACHE STRING "Set the maximum number of components.") 6 | set(ENTITYX_DT_TYPE double CACHE STRING "The type used for delta time in EntityX update methods.") 7 | set(ENTITYX_BUILD_SHARED false CACHE BOOL "Build shared libraries?") 8 | add_subdirectory(entityx) 9 | 10 | set(BOX2D_INSTALL_DOC OFF) 11 | set(BOX2D_BUILD_EXAMPLES OFF) 12 | set(BOX2D_INSTALL OFF CACHE BOOL "Install Box2D libs, includes, and CMake scripts") 13 | set(BOX2D_INSTALL_DOC OFF CACHE BOOL "Install Box2D documentation") 14 | set(BOX2D_BUILD_SHARED OFF CACHE BOOL "Build Box2D shared libraries") 15 | set(BOX2D_BUILD_EXAMPLES OFF CACHE BOOL "Build Box2D examples") 16 | add_subdirectory(Box2D/Box2D) 17 | 18 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "utility/keyvalues.h" 4 | 5 | //Entity X systems 6 | #include "sdl2d3/systems/Box2DSystem.h" 7 | #include "sdl2d3/systems/SFGUISystem.h" 8 | #include "sdl2d3/systems/LTBLSystem.h" 9 | #include "sdl2d3/systems/TextureSystem.h" 10 | 11 | class SDL2D3 : public entityx::EntityX 12 | { 13 | public: 14 | SDL2D3(int argc, char** argv); 15 | void update(entityx::TimeDelta dt); 16 | void run(); 17 | 18 | private: 19 | KeyValue keys; //Interface to keys file 20 | sf::RenderWindow window; //Render window created here 21 | }; 22 | 23 | SDL2D3::SDL2D3(int argc, char** argv) 24 | { 25 | //Load a key=value config file 26 | std::string path = (argc > 1) ? argv[1] : "config.ini"; 27 | keys.LoadFromFile(path); 28 | 29 | //Initialize our SFML window 30 | int width = keys.GetInt("WIDTH"); 31 | int height = keys.GetInt("HEIGHT"); 32 | if(width == 0 || height == 0) { 33 | std::cerr << "Invalid Window width and height" << std::endl; 34 | std::exit(1); 35 | } 36 | auto style = sf::Style::Titlebar | sf::Style::Close; 37 | sf::ContextSettings settings; 38 | settings.antialiasingLevel = 4; 39 | window.create(sf::VideoMode(width, height), "SDL2D3", style, settings); 40 | window.setFramerateLimit(60); 41 | 42 | //Initialize systems 43 | systems.add(window); 44 | systems.add(window, entities, events); 45 | systems.add(window, entities, keys); 46 | systems.add(window,entities, keys); 47 | systems.configure(); 48 | } 49 | 50 | void SDL2D3::update(entityx::TimeDelta dt) 51 | { 52 | systems.update(dt); 53 | systems.update(dt); 54 | systems.update(dt); 55 | systems.update(dt); 56 | } 57 | 58 | void SDL2D3::run() 59 | { 60 | sf::Clock clock; 61 | 62 | /* window.pollEvent et al is handled in the SFGUISystem update() 63 | * the reason is to more cleanly filter events and pass to other systems */ 64 | while (window.isOpen()) 65 | { 66 | window.clear({100,100,100}); 67 | update(clock.restart().asSeconds()); 68 | window.display(); 69 | } 70 | } 71 | 72 | 73 | /***************************************************************/ 74 | 75 | int main(int argc, char** argv) 76 | { 77 | SDL2D3 D3(argc, argv); 78 | D3.run(); 79 | return EXIT_SUCCESS; 80 | } 81 | -------------------------------------------------------------------------------- /src/sdl2d3/components.h: -------------------------------------------------------------------------------- 1 | #ifndef SDL2D3_COMPONENTS_H 2 | #define SDL2D3_COMPONENTS_H 3 | #include 4 | #include 5 | 6 | /* EntityX components. These are properties given to an entity 7 | * corrisponding to each library the entity is used in. */ 8 | 9 | //Component given from GUI as where to spawn the entity 10 | struct SpawnComponent 11 | { 12 | enum TYPE { CIRCLE=0, BOX=1 } type; //Type of shape 13 | int x, y; //Initial spawn position 14 | 15 | SpawnComponent(float x, float y, TYPE t) : type(t), x(x), y(y) { } 16 | }; 17 | 18 | //Handle to a body in the Box2D physics engine 19 | struct Box2DComponent 20 | { 21 | Box2DComponent(b2Body* body) : body(body) { } 22 | b2Body* body; 23 | }; 24 | 25 | //Handle to a light occulder in the LTBL system 26 | struct LTBLComponent 27 | { 28 | LTBLComponent(std::shared_ptr light) : light(light) { } 29 | std::shared_ptr light; 30 | }; 31 | 32 | //Handle to an image texture to draw with SFML over the entity 33 | struct TextureComponent 34 | { 35 | TextureComponent(sf::Sprite sprite) : sprite(sprite) { } 36 | sf::Sprite sprite; 37 | sf::Text positionText; 38 | }; 39 | 40 | #endif // SDL2D3_COMPONENTS_H 41 | -------------------------------------------------------------------------------- /src/sdl2d3/events.h: -------------------------------------------------------------------------------- 1 | #ifndef SDL2D3_EVENTS_H 2 | #define SDL2D3_EVENTS_H 3 | #include 4 | #include 5 | 6 | struct PhysicsEvent 7 | { 8 | enum TYPE { 9 | WindowCollision, //! 2 | #include "utility/utility.h" 3 | #include "sdl2d3/components.h" 4 | #include "Box2DSystem.h" 5 | 6 | Box2DSystem::Box2DSystem(sf::RenderWindow& rw) 7 | : windowBody(nullptr) 8 | , window(rw) 9 | , debugEnabled(true) 10 | , windowCollisionEnabled(false) 11 | { 12 | //Create world, initially 0 gravity 13 | world = std::make_unique(b2Vec2(0,0)); 14 | 15 | //Add static boxes to world to create walls around screen 16 | addWallsOnScreen(); 17 | 18 | //Setup Debug draw and link to world 19 | drawer.setWindow(window); 20 | drawer.SetFlags(b2Draw::e_shapeBit); 21 | world->SetDebugDraw(&drawer); 22 | } 23 | 24 | void Box2DSystem::update(ex::EntityManager&, ex::EventManager&, ex::TimeDelta dt) 25 | { 26 | //If we have unspawned entites, create bodies in the world for them each 27 | for(ex::Entity e : unspawned) 28 | addToWorld(e); 29 | unspawned.clear(); 30 | 31 | //Step the world 32 | const int32 velocityIterations = 8; 33 | const int32 positionIterations = 5; 34 | world->Step(dt, velocityIterations, positionIterations); 35 | if(debugEnabled) { 36 | world->DrawDebugData(); 37 | } 38 | } 39 | 40 | void Box2DSystem::configure(ex::EventManager& events) 41 | { 42 | events.subscribe>(*this); 43 | events.subscribe(*this); 44 | events.subscribe(*this); 45 | events.subscribe(*this); 46 | } 47 | 48 | void Box2DSystem::receive(const PhysicsEvent& e) 49 | { 50 | switch(e.type) 51 | { 52 | case PhysicsEvent::GravityChange: 53 | world->SetGravity(e.grav); 54 | break; 55 | case PhysicsEvent::WindowCollision: 56 | windowCollisionEnabled = e.value; 57 | toggleWindowCollision(); 58 | break; 59 | default: 60 | break; 61 | } 62 | } 63 | 64 | void Box2DSystem::receive(const GraphicsEvent& e) 65 | { 66 | switch(e.type) 67 | { 68 | case GraphicsEvent::ImageRender: 69 | debugEnabled = !e.value; 70 | break; 71 | case GraphicsEvent::ShowAAABs: 72 | drawer.SetFlags(drawer.GetFlags() ^ b2Draw::e_aabbBit); 73 | break; 74 | case GraphicsEvent::GuiWindowChange: 75 | //TODO? Window collison like SDL2D2 76 | //std::cout << e.alloc.top << " " << e.alloc.left << " " 77 | // << e.alloc.width << " " << e.alloc.height << std::endl; 78 | if(windowCollisionEnabled && windowBody != nullptr) { 79 | 80 | } 81 | default: 82 | break; 83 | } 84 | } 85 | 86 | void Box2DSystem::receive(const entityx::ComponentAddedEvent& e) 87 | { 88 | //Event listener to add a Box2D component when an entity is spawned 89 | unspawned.push_back(e.entity); 90 | } 91 | 92 | void Box2DSystem::receive(const ex::EntityDestroyedEvent& e) 93 | { 94 | /* We only care if a Box2DComponent ent has been removed. 95 | * If one has, we remove it from the b2World. */ 96 | if(e.entity.has_component()) 97 | world->DestroyBody(e.entity.component()->body); 98 | } 99 | 100 | void Box2DSystem::addToWorld(ex::Entity e) 101 | { 102 | //Get the spawn info and add an actual b2Body to the world 103 | auto spawn = e.component(); 104 | b2Body* body = createSpawnComponentBody(spawn->x, spawn->y, spawn->type, b2_dynamicBody); 105 | 106 | //Store it in the EntityX system 107 | e.assign(body); 108 | } 109 | 110 | void Box2DSystem::toggleWindowCollision() 111 | { 112 | if(windowCollisionEnabled) { 113 | world->DestroyBody(windowBody); 114 | windowBody = createBody(0, 0, 100, 100, SpawnComponent::BOX, b2_dynamicBody); 115 | windowBody->SetFixedRotation(true); 116 | } else { 117 | world->DestroyBody(windowBody); 118 | windowBody = nullptr; 119 | } 120 | } 121 | 122 | void Box2DSystem::addWallsOnScreen() 123 | { 124 | float width = meters(window.getSize().x); 125 | float height = meters(window.getSize().y); 126 | float halfwidth = width / 2; 127 | float halfheight = height / 2; 128 | const float wallsz = 15_px; 129 | createStaticBox(halfwidth, wallsz, halfwidth, wallsz); //Top wall 130 | createStaticBox(wallsz, halfheight, wallsz, halfheight); //Left wall 131 | createStaticBox(width-wallsz, halfheight, wallsz, halfheight);//Right wall 132 | createStaticBox(halfwidth, height-wallsz, halfwidth, wallsz); //Bottom wall 133 | } 134 | 135 | b2Body* Box2DSystem::createStaticBox(float x, float y, float halfwidth, float halfheight) 136 | { 137 | return createBody(x, y, halfwidth, halfheight, SpawnComponent::BOX, b2_staticBody); 138 | } 139 | 140 | b2Body* Box2DSystem::createDynamicBox(float x, float y, float halfwidth, float halfheight) 141 | { 142 | return createBody(x, y, halfwidth, halfheight, SpawnComponent::BOX, b2_dynamicBody); 143 | } 144 | 145 | b2Body* Box2DSystem::createSpawnComponentBody(float x, float y, SpawnComponent::TYPE type, b2BodyType btype) 146 | { 147 | float width = (type == SpawnComponent::BOX) ? conf::box_halfwidth : conf::circle_radius; 148 | return createBody(x, y, width, width, type, btype); 149 | } 150 | 151 | b2Body* Box2DSystem::createBody(float x, float y, float wx, float wy, SpawnComponent::TYPE type, b2BodyType btype) 152 | { 153 | b2Body* body; 154 | b2BodyDef bodyDef; 155 | b2FixtureDef fix; 156 | b2PolygonShape poly; //Two shapes for fixtures. Must remain in scope until CreateFixture 157 | b2CircleShape circle; 158 | bodyDef.type = btype; 159 | bodyDef.position.Set(x,y); 160 | fix.density = (btype == b2_dynamicBody) ? 1.0 : 0.0; 161 | fix.restitution = 0.3; 162 | body = world->CreateBody(&bodyDef); 163 | 164 | if(type == SpawnComponent::BOX) { 165 | poly.SetAsBox(wx, wy); 166 | fix.shape = &poly; 167 | } 168 | else if(type == SpawnComponent::CIRCLE) { 169 | circle.m_radius = wx; 170 | fix.restitution = 1; 171 | fix.shape = &circle; 172 | } 173 | else { 174 | throw std::runtime_error("This Spawn type is not implemented"); 175 | } 176 | 177 | body->CreateFixture(&fix); 178 | body->SetSleepingAllowed(false); 179 | 180 | return body; 181 | } 182 | 183 | 184 | -------------------------------------------------------------------------------- /src/sdl2d3/systems/Box2DSystem.h: -------------------------------------------------------------------------------- 1 | #ifndef SDL2D3_BOX2D_SYSTEM_H 2 | #define SDL2D3_BOX2D_SYSTEM_H 3 | #include 4 | #include 5 | #include 6 | #include "sdl2d3/events.h" 7 | #include "sdl2d3/components.h" 8 | #include "utility/SFMLDebugDraw.h" 9 | #include "utility/keyvalues.h" 10 | namespace ex = entityx; 11 | 12 | /* The Box2D System is to manage the Box2D world and receive events from the GUI 13 | * about changing gravity and whatever else. This is the entire Box2D part of the code 14 | */ 15 | 16 | class Box2DSystem : public entityx::System, public entityx::Receiver 17 | { 18 | public: 19 | //Initizlize with a RenderWindow so we can create walls around it 20 | Box2DSystem(sf::RenderWindow& rw); 21 | 22 | public: 23 | /** EntityX Interfaces **/ 24 | //Steps the Box2D world and draws shapes 25 | void update(ex::EntityManager&, ex::EventManager&, ex::TimeDelta dt) override; 26 | 27 | //EntityX event listeners 28 | void configure(ex::EventManager& events) override; 29 | void receive(const entityx::ComponentAddedEvent& e); 30 | void receive(const entityx::EntityDestroyedEvent& e); 31 | void receive(const PhysicsEvent& e); 32 | void receive(const GraphicsEvent& e); 33 | 34 | private: 35 | //Event listeners and handlers 36 | void addToWorld(ex::Entity e); 37 | void addWallsOnScreen(); 38 | void toggleWindowCollision(); 39 | 40 | //Utility functions to create b2 bodies 41 | b2Body* createStaticBox(float x, float y, float halfwidth, float halfheight); 42 | b2Body* createDynamicBox(float x, float y, float halfwidth, float halfheight); 43 | b2Body* createDynamicCircle(float x, float y, int radius); 44 | b2Body* createSpawnComponentBody(float x, float y, SpawnComponent::TYPE type, b2BodyType btype); 45 | b2Body* createBody(float x, float y, float wx, float wy, SpawnComponent::TYPE type, b2BodyType btype); 46 | 47 | //World information and state data 48 | std::unique_ptr world; //The World. 49 | b2Body* windowBody; //Body for the SFGUI window 50 | std::list unspawned; //Entities added by EntityX not yet given a b2Body 51 | SFMLDebugDraw drawer; //DebugDraw instance 52 | sf::RenderWindow& window; //Reference to the render window 53 | bool debugEnabled; 54 | bool windowCollisionEnabled; 55 | }; 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /src/sdl2d3/systems/LTBLSystem.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "utility/utility.h" 3 | #include "sdl2d3/components.h" 4 | #include "LTBLSystem.h" 5 | #include "Box2DSystem.h" 6 | 7 | LTBLSystem::LTBLSystem(sf::RenderWindow& rw, entityx::EntityManager& entities, KeyValue& keys) 8 | : lighingEnabled(true) 9 | , lightingMouseEnabled(true) 10 | , window(rw) 11 | , entities(entities) 12 | , keys(keys) 13 | { 14 | loadSetupLightSystem(); 15 | } 16 | 17 | void LTBLSystem::loadSetupLightSystem() 18 | { 19 | //Loads textures and shaders 20 | loadTextures(); 21 | 22 | //Initialize the light system 23 | ls = std::make_unique(); 24 | ls->create({0,0,9999,9999}, window.getSize(), penumbraTexture, unshadowShader, lightOverShapeShader); 25 | ls->_directionEmissionRange = 200; 26 | ls->_directionEmissionRadiusMultiplier = 0.3; 27 | ls->_ambientColor = {100,100,100}; 28 | 29 | //Create and setup the mouse light 30 | ls->removeLight(mouselight); 31 | sf::Vector2u texsize { pointLightTexture.getSize() }; 32 | mouselight = std::make_shared(); 33 | mouselight->_emissionSprite.setOrigin((float)texsize.x * 0.5, (float)texsize.y * 0.5); 34 | mouselight->_emissionSprite.setTexture(pointLightTexture); 35 | ls->addLight(mouselight); 36 | } 37 | 38 | void LTBLSystem::loadTextures() 39 | { 40 | //Load shaders and create objects 41 | std::string ushadowPath = keys.GetString("LIGHT_UNSHADOW_SHADER"); 42 | std::string overShaderPath = keys.GetString("LIGHT_OVER_SHADER"); 43 | unshadowShader.loadFromFile(ushadowPath + ".vert", ushadowPath + ".frag"); 44 | lightOverShapeShader.loadFromFile(overShaderPath + ".vert", overShaderPath + ".frag"); 45 | 46 | //Load and create the penumbra and point light textures 47 | std::string prenumbraPath = keys.GetString("LIGHT_PRENUMBRA_TEXTURE"); 48 | std::string pointLightPath = keys.GetString("LIGHT_POINT_TEXTURE"); 49 | penumbraTexture.loadFromFile(prenumbraPath); 50 | pointLightTexture.loadFromFile(pointLightPath); 51 | penumbraTexture.setSmooth(true); 52 | pointLightTexture.setSmooth(true); 53 | } 54 | 55 | void LTBLSystem::update(ex::EntityManager&, ex::EventManager&, ex::TimeDelta) 56 | { 57 | //If we have entities to place in the system, do it 58 | for(ex::Entity e : unspawned) 59 | addToWorld(e); 60 | unspawned.clear(); 61 | 62 | if(lighingEnabled) { 63 | //Take all Box2D components, and update the LTBL components 64 | ex::ComponentHandle box; 65 | ex::ComponentHandle light; 66 | for(ex::Entity e : entities.entities_with_components(box, light)) { 67 | (void)e; 68 | sf::ConvexShape& s = light->light->_shape; 69 | b2Vec2 position = box->body->GetPosition(); 70 | sf::Vector2f adjusted = {pixels(position.x), pixels(position.y)}; 71 | s.setPosition(window.mapPixelToCoords({(int)adjusted.x, (int)adjusted.y})); 72 | s.setRotation(box->body->GetAngle() * (180.0 / M_PI)); 73 | } 74 | //Update the mouse light's position 75 | if(lightingMouseEnabled) { 76 | sf::Vector2f mouse = window.mapPixelToCoords(sf::Mouse::getPosition(window)); 77 | mouselight->_emissionSprite.setPosition(window.mapPixelToCoords({(int)mouse.x,(int)mouse.y})); 78 | } 79 | //Render the lights 80 | ls->render(window.getView(), unshadowShader, lightOverShapeShader); 81 | sf::Sprite lighting(ls->getLightingTexture()); 82 | window.draw(lighting, sf::BlendMultiply); 83 | } 84 | } 85 | 86 | void LTBLSystem::configure(ex::EventManager& events) 87 | { 88 | events.subscribe>(*this); 89 | events.subscribe(*this); 90 | events.subscribe(*this); 91 | events.subscribe(*this); 92 | events.subscribe(*this); 93 | } 94 | 95 | void LTBLSystem::receive(const LightEvent& e) 96 | { 97 | switch(e.type) 98 | { 99 | case LightEvent::Color: 100 | mouselight->_emissionSprite.setColor(e.color); 101 | break; 102 | case LightEvent::Enabled: 103 | lighingEnabled = e.value; 104 | break; 105 | case LightEvent::MouseEnabled: 106 | if(e.value) { 107 | ls->addLight(mouselight); 108 | } else { 109 | ls->removeLight(mouselight); 110 | } 111 | break; 112 | case LightEvent::Reload: 113 | loadSetupLightSystem(); 114 | for(ex::Entity e : entities.entities_with_components()) 115 | addToWorld(e); 116 | break; 117 | default: 118 | break; 119 | } 120 | } 121 | 122 | void LTBLSystem::receive(const GraphicsEvent& e) 123 | { 124 | switch(e.type) 125 | { 126 | case GraphicsEvent::WindowZoomed: { 127 | float direction = std::copysign(0.1, -e.delta); 128 | scaleAllEntities(direction, false); 129 | break; 130 | } 131 | case GraphicsEvent::WindowZoomReset: { 132 | scaleAllEntities(1, true); 133 | break; 134 | } 135 | default: 136 | break; 137 | } 138 | } 139 | 140 | void LTBLSystem::receive(const ex::ComponentAddedEvent& e) 141 | { 142 | unspawned.push_back(e.entity); 143 | } 144 | 145 | void LTBLSystem::receive(const ex::EntityDestroyedEvent& e) 146 | { 147 | if(e.entity.has_component()) 148 | ls->removeShape(e.entity.component()->light); 149 | } 150 | 151 | void LTBLSystem::receive(const sf::Event &e) 152 | { 153 | switch(e.type) 154 | { 155 | case sf::Event::MouseWheelScrolled: { 156 | if(sf::Keyboard::isKeyPressed(sf::Keyboard::LControl)) { 157 | //Change size of light when scrolled and CTRL 158 | sf::Vector2f scale = mouselight->_emissionSprite.getScale(); 159 | float delta = e.mouseWheelScroll.delta; 160 | mouselight->_emissionSprite.setScale(scale + sf::Vector2f(delta,delta)); 161 | mouselight->_sourceRadius += delta; 162 | } 163 | break; 164 | } 165 | default: 166 | break; 167 | } 168 | } 169 | 170 | void LTBLSystem::addToWorld(ex::Entity e) 171 | { 172 | //Create an initial light shape... 173 | std::shared_ptr lightShape = std::make_shared(); 174 | 175 | //Use the SpawnComponent to create a light with the right body and x/y points 176 | auto spawn = e.component(); 177 | 178 | if(spawn->type == SpawnComponent::BOX) { 179 | float w = pixels(conf::box_halfwidth * 2); 180 | sf::ConvexShape& light = lightShape->_shape; 181 | light.setPointCount(4); 182 | light.setPoint(0, {0, 0}); 183 | light.setPoint(1, {0, w}); 184 | light.setPoint(2, {w, w}); 185 | light.setPoint(3, {w, 0}); 186 | light.setOrigin({w/2, w/2}); 187 | } 188 | else if(spawn->type == SpawnComponent::CIRCLE) { 189 | //Circle requested; create SFML circle shape and copy points out. 190 | float radius = pixels(conf::circle_radius); 191 | sf::CircleShape circle(radius, 15); 192 | int nPoints = circle.getPointCount(); 193 | lightShape->_shape.setPointCount(nPoints); 194 | for(int i = 0; i != nPoints; ++i) 195 | lightShape->_shape.setPoint(i, circle.getPoint(i)); 196 | lightShape->_shape.setOrigin(radius, radius); 197 | } 198 | else { 199 | throw std::runtime_error("Spawn type not recognized"); 200 | } 201 | 202 | lightShape->_shape.setPosition(spawn->x, spawn->y); 203 | 204 | //Accounts for window view. The light shape must be scaled to fit the Box2D size 205 | sf::View nowView = window.getView(); 206 | sf::View defView = window.getDefaultView(); 207 | float zoom = nowView.getSize().x / defView.getSize().x; 208 | lightShape->_shape.scale(zoom, zoom); 209 | 210 | //Add a LTBL component to the entity, and add to light system 211 | e.assign(lightShape); 212 | ls->addShape(lightShape); 213 | } 214 | 215 | void LTBLSystem::scaleAllEntities(float delta, bool absolute) 216 | { 217 | ex::ComponentHandle light; 218 | for(ex::Entity e : entities.entities_with_components(light)) { 219 | (void)e; 220 | if(absolute) { 221 | light->light->_shape.setScale(delta, delta); 222 | } else { 223 | light->light->_shape.scale(1.0 + delta, 1.0 + delta); 224 | } 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /src/sdl2d3/systems/LTBLSystem.h: -------------------------------------------------------------------------------- 1 | #ifndef SDL2D3_LTBL_SYSTEM_H 2 | #define SDL2D3_LTBL_SYSTEM_H 3 | 4 | #include 5 | #include 6 | #include "utility/keyvalues.h" 7 | #include "sdl2d3/events.h" 8 | #include "sdl2d3/components.h" 9 | namespace ex = entityx; 10 | 11 | /* The Let There Be Light system creates a light system and updates it 12 | * for all entities with light components. 13 | * Recieves events from GUI when creating objects 14 | */ 15 | 16 | class LTBLSystem : public ex::System, public ex::Receiver 17 | { 18 | public: 19 | //Creates light system; Renderwindow and keyValue to load shaders and textures 20 | LTBLSystem(sf::RenderWindow& rw, ex::EntityManager& entities, KeyValue& keys); 21 | 22 | public: 23 | /** EntityX Interfaces **/ 24 | //Updates and draws the light system 25 | void update(ex::EntityManager&, ex::EventManager&, ex::TimeDelta) override; 26 | 27 | /*Event subscription and receiving. We care when an object is added or removed because 28 | *we must remove them from the light system */ 29 | void configure(ex::EventManager& events) override; 30 | void receive(const ex::ComponentAddedEvent&); 31 | void receive(const ex::EntityDestroyedEvent&); 32 | void receive(const LightEvent& e); 33 | void receive(const GraphicsEvent& e); 34 | void receive(const sf::Event &e); 35 | 36 | private: 37 | //Setup the entire light system and load textures 38 | void loadSetupLightSystem(); 39 | void loadTextures(); 40 | 41 | //Add an entity to the light system (assuming a SpawnComponent is present) 42 | void addToWorld(ex::Entity e); 43 | 44 | //Scale all light shapes by adding some delta. Absolute for setScale, not scale 45 | void scaleAllEntities(float delta, bool absolute = false); 46 | 47 | private: 48 | //Light textures 49 | sf::Shader unshadowShader, lightOverShapeShader; 50 | sf::Texture penumbraTexture, pointLightTexture; 51 | 52 | //The mouse light and the light system 53 | std::shared_ptr mouselight; 54 | std::unique_ptr ls; 55 | std::list unspawned; 56 | bool lighingEnabled; 57 | bool lightingMouseEnabled; 58 | 59 | //I/O devices (keys for textures, window for drawing) 60 | sf::RenderWindow& window; 61 | ex::EntityManager& entities; 62 | KeyValue& keys; 63 | }; 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /src/sdl2d3/systems/SFGUISystem.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "utility/utility.h" 4 | #include "sdl2d3/events.h" 5 | #include "sdl2d3/components.h" 6 | #include "Box2DSystem.h" 7 | #include "SFGUISystem.h" 8 | 9 | SFGUISystem::SFGUISystem(sf::RenderWindow& rw, ex::EntityManager& entities, ex::EventManager& events) 10 | : window(rw) 11 | , entities(entities) 12 | , events(events) 13 | { 14 | createTheGUI(); 15 | } 16 | 17 | void SFGUISystem::update(ex::EntityManager&, ex::EventManager&, ex::TimeDelta dt) 18 | { 19 | //Obligatory to draw with SFGUI 20 | window.resetGLStates(); 21 | 22 | //The top-level event polling for the render window 23 | sf::Event event; 24 | while (window.pollEvent(event)) 25 | { 26 | switch (event.type) 27 | { 28 | case sf::Event::Closed: 29 | window.close(); 30 | break; 31 | case sf::Event::MouseButtonPressed: 32 | onMouseClick(event.mouseButton); 33 | break; 34 | case sf::Event::KeyPressed: 35 | onKeyPressed(event.key); 36 | break; 37 | case sf::Event::MouseWheelScrolled: 38 | onMouseWheelScrolled(event.mouseWheelScroll); 39 | break; 40 | default: 41 | break; 42 | } 43 | //Pass on the event to other listeners 44 | events.emit(event); 45 | } 46 | 47 | //Because sfg::Scale doesn't have good events 48 | checkSliderEvents(); 49 | 50 | //Handle view movement with keys 51 | updateWindowView(); 52 | 53 | //Updates and displays the GUI (also drawn last) 54 | gui_window->HandleEvent(event); 55 | gui_window->Update(dt); 56 | gui.Display(window); 57 | } 58 | 59 | void SFGUISystem::createTheGUI() 60 | { 61 | gui_window = sfg::Window::Create(); 62 | gui_window->SetTitle("Control Window"); 63 | gui_window->SetRequisition(sf::Vector2f(200,100)); 64 | gui_window->SetPosition(sf::Vector2f(200,200)); 65 | gui_window->GetSignal(sfg::Window::OnSizeAllocate) 66 | .Connect(std::bind(&SFGUISystem::onWindowPosSizeChage, this)); 67 | auto notebook = sfg::Notebook::Create(); 68 | 69 | //The Box2D setting widgets; a table 70 | auto Box2DWidget = sfg::Table::Create(); 71 | { 72 | //Widget layouts for table. {widget, {row,column,cspan,rspan}} 73 | static std::vector>> placement = { 74 | {sfg::Label::Create("Gravity X"), {0,0,1,1}}, 75 | {sfg::Label::Create("Gravity Y"), {1,0,1,1}}, 76 | {sfg::Scale::Create(-15,15,1), {0,1,1,1}}, 77 | {sfg::Scale::Create(-15,15,1), {1,1,1,1}}, 78 | {sfg::Button::Create("Zero Gravity"),{0,2,2,1}} 79 | }; 80 | //Paces each element in the table with their layouts 81 | for(const auto& entry : placement) { 82 | Box2DWidget->Attach(entry.first, entry.second); 83 | } 84 | //Save the slider widgets and register an event 85 | gravx = std::dynamic_pointer_cast(placement[2].first); 86 | gravy = std::dynamic_pointer_cast(placement[3].first); 87 | placement[4].first->GetSignal(sfg::Button::OnMouseLeftRelease) 88 | .Connect([&](){gravx->SetValue(0);gravy->SetValue(0);}); 89 | } 90 | 91 | //Let There Be Light settings widgets 92 | auto LTBLWidget = sfg::Box::Create(sfg::Box::Orientation::VERTICAL); 93 | { 94 | //Creates three horizontal sliders to set RGB of mouse light 95 | sfg::Scale::Ptr sliders[3]; 96 | std::string names[] = {"R", "G", "B"}; 97 | auto colorFrame = sfg::Frame::Create("Light Color"); 98 | auto sliderBox = sfg::Box::Create(); 99 | for(int i = 0; i != 3; ++i) { 100 | auto labelbox = sfg::Box::Create(sfg::Box::Orientation::VERTICAL); 101 | sliders[i] = sfg::Scale::Create(0, 255, 1); 102 | sliders[i]->SetRequisition( sf::Vector2f( 80.f, 20.f ) ); 103 | labelbox->Pack(sfg::Label::Create(names[i])); 104 | labelbox->Pack(sliders[i]); 105 | sliderBox->Pack(labelbox); 106 | } 107 | colorr = sliders[0]; 108 | colorg = sliders[1]; 109 | colorb = sliders[2]; 110 | colorFrame->Add(sliderBox); 111 | 112 | //Misc buttons to control light, packed horizontally 113 | auto miscBox = sfg::Box::Create(); 114 | auto enableButton = sfg::CheckButton::Create("Enable"); 115 | auto mouseButton = sfg::CheckButton::Create("Mouse light"); 116 | enableButton->SetActive(true); 117 | mouseButton->SetActive(true); 118 | miscBox->Pack(enableButton); 119 | miscBox->Pack(mouseButton); 120 | 121 | //Reload light button; reloads textures and such 122 | auto reloadButton = sfg::Button::Create("Reload Light"); 123 | reloadButton->GetSignal(sfg::Button::OnMouseLeftRelease) 124 | .Connect(std::bind(&SFGUISystem::lightReloadEvent, this)); 125 | 126 | //Put everyhing in the notebook widget 127 | LTBLWidget->SetSpacing(8); 128 | LTBLWidget->Pack(colorFrame); 129 | LTBLWidget->Pack(miscBox); 130 | LTBLWidget->Pack(reloadButton); 131 | } 132 | 133 | //Frame to control graphics settings 134 | auto graphicsFrame = sfg::Frame::Create("Graphics"); 135 | { 136 | //Layout table. This time it is Event Type -> {Widget,Layout} 137 | graphics = { 138 | {GraphicsEvent::ImageRender, {sfg::CheckButton::Create("Image Render"), {0, 0, 1, 1}}}, 139 | {GraphicsEvent::ShowPositions, {sfg::CheckButton::Create("Show Positions"), {0, 1, 1, 1}}}, 140 | {GraphicsEvent::ShowAAABs, {sfg::CheckButton::Create("Show AABBs"), {1, 0, 1, 1}}}, 141 | {GraphicsEvent::RandomTextures, {sfg::CheckButton::Create("Random Textures"), {1, 1, 1, 1}}} 142 | }; 143 | //Put all button in table, and set up event when clicked 144 | auto table = sfg::Table::Create(); 145 | for(const auto& entry : graphics) { 146 | const auto& placement = entry.second; 147 | table->Attach(placement.first, placement.second); 148 | placement.first-> 149 | GetSignal(sfg::CheckButton::OnToggle).Connect(std::bind(&SFGUISystem::graphicsEvent, this, entry)); 150 | } 151 | //Turn on checkboxes that are initially on 152 | graphics[GraphicsEvent::RandomTextures].first->SetActive(true); 153 | graphicsFrame->Add(table); 154 | } 155 | 156 | //Add the two trees to the notebook 157 | notebook->AppendPage(Box2DWidget, sfg::Label::Create("Box2D")); 158 | notebook->AppendPage(LTBLWidget, sfg::Label::Create("LTBL2")); 159 | 160 | //"Clear bodies" and "Reset View buttons 161 | auto clearButton = sfg::Button::Create("Clear Bodies"); 162 | auto resetButton = sfg::Button::Create("Reset View"); 163 | clearButton->GetSignal(sfg::Button::OnMouseLeftRelease).Connect(std::bind(&SFGUISystem::destroyAllEntities, this)); 164 | resetButton->GetSignal(sfg::Button::OnMouseLeftRelease).Connect(std::bind(&SFGUISystem::resetWindowView, this)); 165 | auto miscBox = sfg::Box::Create(); 166 | miscBox->Pack(clearButton); 167 | miscBox->Pack(resetButton); 168 | 169 | //Pack the notbook above the clear button and graphics boxes, and add to window 170 | auto final_box = sfg::Box::Create(sfg::Box::Orientation::VERTICAL); 171 | final_box->SetSpacing(8); 172 | final_box->Pack(notebook); 173 | final_box->Pack(miscBox); 174 | final_box->Pack(graphicsFrame); 175 | gui_window->Add(final_box); 176 | } 177 | 178 | void SFGUISystem::onMouseWheelScrolled(sf::Event::MouseWheelScrollEvent scroll) 179 | { 180 | //On mousewheel scrolling, we zoom the view in and out if CTRL isn't pressed 181 | if(!sf::Keyboard::isKeyPressed(sf::Keyboard::LControl)) { 182 | sf::View view = window.getView(); 183 | float direction = std::copysign(0.1, scroll.delta); 184 | view.zoom(1.0 - direction); 185 | window.setView(view); 186 | 187 | //Inform rest of code 188 | GraphicsEvent e(GraphicsEvent::WindowZoomed); 189 | e.delta = direction; 190 | std::cout << direction; 191 | events.emit(e); 192 | } 193 | } 194 | 195 | void SFGUISystem::onMouseClick(sf::Event::MouseButtonEvent click) 196 | { 197 | //Do nothing if we have clicked inside the GUI window (uses global coordinates) 198 | if(gui_window->GetAllocation().contains(click.x, click.y)) 199 | return; 200 | 201 | //Converts global mouse position to a world position first 202 | sf::Vector2f adjusted = window.mapPixelToCoords({click.x, click.y}); 203 | click.x = meters(adjusted.x); 204 | click.y = meters(adjusted.y); 205 | 206 | if(click.button == sf::Mouse::Button::Middle) { 207 | /* On a middle click, we want to remove the closest entity to the click position. 208 | * This is queried using the Box2D body information to distance to the click point */ 209 | b2Vec2 request(click.x, click.y); 210 | auto candidates = entities.entities_with_components(); 211 | ex::Entity e = *std::min_element(candidates.begin(), candidates.end(), 212 | [request](ex::Entity a, ex::Entity b) { 213 | b2Vec2 pos_a = a.component()->body->GetPosition(), 214 | pos_b = b.component()->body->GetPosition(); 215 | return b2Distance(pos_a, request) < b2Distance(pos_b, request); 216 | }); 217 | if(e.valid()) { 218 | b2Vec2 pos = e.component()->body->GetPosition(); 219 | if(b2Distance(request, pos) < conf::circle_radius*2) 220 | entities.destroy(e.id()); 221 | } 222 | } else { 223 | /* On a left or right click, we want to spawn a 224 | * new physics entity, either a box or a circle. */ 225 | SpawnComponent::TYPE type; 226 | if(click.button == sf::Mouse::Button::Left) { 227 | type = SpawnComponent::BOX; 228 | } else if(sf::Mouse::Button::Right) { 229 | type = SpawnComponent::CIRCLE; 230 | } else { 231 | //Do nothing 232 | } 233 | ex::Entity e = entities.create(); 234 | e.assign(click.x, click.y, type); 235 | } 236 | } 237 | 238 | void SFGUISystem::onKeyPressed(sf::Event::KeyEvent) 239 | { 240 | 241 | } 242 | 243 | void SFGUISystem::updateWindowView() 244 | { 245 | static std::map keyMoveMap = { 246 | {sf::Keyboard::Left, {-15, 0}}, 247 | {sf::Keyboard::Right,{ 15, 0}}, 248 | {sf::Keyboard::Up, { 0, -15}}, 249 | {sf::Keyboard::Down, { 0, 15}}, 250 | {sf::Keyboard::A, {-15, 0}}, 251 | {sf::Keyboard::D, { 15, 0}}, 252 | {sf::Keyboard::W, { 0, -15}}, 253 | {sf::Keyboard::S, { 0, 15}} 254 | }; 255 | 256 | for(const auto& entry : keyMoveMap) { 257 | if(sf::Keyboard::isKeyPressed(entry.first)) { 258 | sf::View view = window.getView(); 259 | view.move(entry.second); 260 | window.setView(view); 261 | } 262 | } 263 | } 264 | 265 | void SFGUISystem::resetWindowView() 266 | { 267 | //Inform the rest of the code first 268 | events.emit(GraphicsEvent::WindowZoomReset); 269 | 270 | //Now reset the view 271 | window.setView(window.getDefaultView()); 272 | } 273 | 274 | void SFGUISystem::checkSliderEvents() 275 | { 276 | /* Check for gravity updates from sliders. The "Zero Gravity" button 277 | * sets these sliders to 0, which causes this to occur as well */ 278 | sf::Vector2f newGrav { gravx->GetValue(), gravy->GetValue() }; 279 | if(newGrav != storedGrav) { 280 | storedGrav = newGrav; 281 | PhysicsEvent e(PhysicsEvent::GravityChange); 282 | e.grav = b2Vec2(storedGrav.x, storedGrav.y); 283 | events.emit(e); 284 | } 285 | 286 | //Checks for changes in the RGB light-color sliders 287 | sf::Color newColor {(sf::Uint8)colorr->GetValue(), (sf::Uint8)colorg->GetValue(), (sf::Uint8)colorb->GetValue()}; 288 | if(newColor != storedColor) { 289 | storedColor = newColor; 290 | LightEvent e(LightEvent::Color); 291 | e.color = storedColor; 292 | events.emit(e); 293 | } 294 | } 295 | 296 | void SFGUISystem::onWindowPosSizeChage() 297 | { 298 | GraphicsEvent e(GraphicsEvent::GuiWindowChange); 299 | e.alloc = gui_window->GetAllocation(); 300 | events.emit(e); 301 | } 302 | 303 | void SFGUISystem::lightReloadEvent() 304 | { 305 | LightEvent e(LightEvent::Reload); 306 | events.emit(e); 307 | } 308 | 309 | void SFGUISystem::destroyAllEntities() 310 | { 311 | for(ex::Entity e : entities.entities_with_components()) 312 | entities.destroy(e.id()); 313 | } 314 | 315 | void SFGUISystem::graphicsEvent(const GraphicsEntry& entry) 316 | { 317 | events.emit(entry.first, entry.second.first->IsActive()); 318 | } 319 | -------------------------------------------------------------------------------- /src/sdl2d3/systems/SFGUISystem.h: -------------------------------------------------------------------------------- 1 | #ifndef SDL2D3_SFGUI_SYSTEM_H 2 | #define SDL2D3_SFGUI_SYSTEM_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "sdl2d3/events.h" 9 | namespace ex = entityx; 10 | 11 | /* The SFGUI system creates the GUI window, and emits all events to EntityX 12 | * as the user interacts with the entire game window. SFML events are polled 13 | * here, and the passed along to the rest of the system */ 14 | 15 | class SFGUISystem : public ex::System 16 | { 17 | public: 18 | SFGUISystem(sf::RenderWindow& rw, ex::EntityManager& entities, ex::EventManager& events); 19 | 20 | public: 21 | /** EntityX Interfaces **/ 22 | //Draw the GUI and etc, and emit events if needed 23 | void update(ex::EntityManager&, ex::EventManager&, ex::TimeDelta dt) override; 24 | 25 | private: 26 | //General GUI components 27 | void createTheGUI(); 28 | sf::RenderWindow& window; //Window to draw to 29 | sfg::SFGUI gui; //Obligatory 30 | sfg::Window::Ptr gui_window; //The single GUI window 31 | 32 | /* Slider section and data, because the sfg::Scale doesn't have slider 33 | * dragged/dropped events, we poll the sliders each update() with this data */ 34 | void checkSliderEvents(); 35 | sfg::Scale::Ptr gravx, gravy, colorr, colorg, colorb; 36 | sf::Vector2f storedGrav; 37 | sf::Color storedColor; 38 | 39 | /* For the "Graphics" checkboxes, this is a map of the event type to the button 40 | * handle in SFGUI, and the placement in the table the buttons are packed in */ 41 | std::map>> graphics; 42 | typedef decltype(graphics)::value_type GraphicsEntry; 43 | 44 | private: 45 | //GUI callbacks and event handlers 46 | void onMouseClick(sf::Event::MouseButtonEvent); 47 | void onKeyPressed(sf::Event::KeyEvent); 48 | void onMouseWheelScrolled(sf::Event::MouseWheelScrollEvent); 49 | void onWindowPosSizeChage(); 50 | void updateWindowView(); 51 | void resetWindowView(); 52 | void lightReloadEvent(); 53 | void graphicsEvent(const GraphicsEntry& entry); 54 | void destroyAllEntities(); 55 | 56 | private: 57 | ex::EntityManager& entities; //EntityX convience items 58 | ex::EventManager& events; 59 | }; 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /src/sdl2d3/systems/TextureSystem.cpp: -------------------------------------------------------------------------------- 1 | #include "utility/utility.h" 2 | #include "Box2DSystem.h" 3 | #include "TextureSystem.h" 4 | 5 | TextureSystem::TextureSystem(sf::RenderWindow& rw, entityx::EntityManager& entities, KeyValue& keys) 6 | : window(rw) 7 | , imageRenderEnabled(false) 8 | , randomTexturesEnabled(true) 9 | , positionTextEnabled(false) 10 | , entities(entities) 11 | { 12 | /* This doesn't change. It maps the type shape to the vector of textures aviliable 13 | * under random texturing, or we use the first for no random textures */ 14 | texturemap = { 15 | { SpawnComponent::BOX, {&boxTextures, conf::box_halfwidth*2}}, 16 | { SpawnComponent::CIRCLE, {&ballTextures, conf::circle_radius*2}} 17 | }; 18 | 19 | /* Textures for physics objects 20 | * `loadTextures` reads a key from an .ini consisting of colon-delimited 21 | * textures, and loads them into a vector */ 22 | loadTextures(boxTextures, keys.GetString("BOX_TEXTURES")); 23 | loadTextures(ballTextures, keys.GetString("BALL_TEXTURES")); 24 | 25 | //Load background texture and make it repeating 26 | bgTexture.loadFromFile(keys.GetString("BACKGROUND_TEXTURE")); 27 | bgTexture.setRepeated(true); 28 | bgSprite.setTexture(bgTexture); 29 | auto windsz = rw.getSize(); 30 | bgSprite.setTextureRect(sf::IntRect(0, 0, windsz.x, windsz.y)); 31 | 32 | //Font for displaying positions and other things 33 | boxFont.loadFromFile(keys.GetString("OBJECT_FONT")); 34 | } 35 | 36 | //General-porpose string split function 37 | static std::vector strSplit(const std::string& target, const std::string& delim) 38 | { 39 | std::vector result; 40 | size_t startPos = 0, it = 0; 41 | do { 42 | it = target.find(delim, startPos); 43 | result.push_back(target.substr(startPos, it - startPos)); 44 | startPos = it + delim.length(); 45 | } 46 | while(it != std::string::npos); 47 | return result; 48 | } 49 | 50 | void TextureSystem::loadTextures(std::vector& dest, const std::string& colonpaths) 51 | { 52 | std::vector paths = strSplit(colonpaths, ":"); 53 | for(const std::string& s : paths) { 54 | sf::Texture t; 55 | t.loadFromFile(s); 56 | dest.push_back(std::move(t)); 57 | } 58 | } 59 | 60 | void TextureSystem::update(ex::EntityManager&, ex::EventManager&, ex::TimeDelta) 61 | { 62 | //Untextured entities, deal with them 63 | for(ex::Entity e : unspawned) 64 | addToWorld(e); 65 | unspawned.clear(); 66 | 67 | //Draw background first if enabled 68 | if(imageRenderEnabled) 69 | window.draw(bgSprite); 70 | 71 | /* For each entity, the texture and position text info are updated from the 72 | * Box2D component, if enabled */ 73 | auto box = ex::ComponentHandle(); 74 | auto tex = ex::ComponentHandle(); 75 | for(ex::Entity e : entities.entities_with_components(box, tex)) 76 | { 77 | (void)e; 78 | b2Body* body = box->body; 79 | b2Vec2 position = body->GetPosition(); 80 | sf::Vector2f adjusted = {pixels(position.x), pixels(position.y)}; 81 | 82 | if(imageRenderEnabled) { 83 | sf::Sprite& sprite = tex->sprite; 84 | sprite.setPosition(adjusted); 85 | sprite.setRotation(body->GetAngle() * (180 / M_PI)); 86 | window.draw(sprite); 87 | } 88 | if(positionTextEnabled) { 89 | char buffer[32]; 90 | std::snprintf(buffer, 32, "[%.3d,%.3d]", (int)adjusted.x, (int)adjusted.y); 91 | sf::Text& text = tex->positionText; 92 | text.setString(buffer); 93 | text.setPosition(adjusted.x-28, adjusted.y-8); 94 | window.draw(text); 95 | } 96 | } 97 | } 98 | 99 | void TextureSystem::addToWorld(entityx::Entity e) 100 | { 101 | retexture(e); 102 | } 103 | 104 | void TextureSystem::retexture(entityx::Entity e) 105 | { 106 | //Add a texture component if it is not there. Lazy initialization 107 | if(!e.has_component()) { 108 | e.assign(sf::Sprite()); 109 | } 110 | 111 | /* Use the texturemap on the type the ent was spawned with to choose a random texure. 112 | * Then, the new texture needs to be scaled to the Box2D component */ 113 | auto textureComponent = e.component(); 114 | auto spawnShape = e.component()->type; 115 | auto& textureBank = texturemap.at(spawnShape).first; 116 | sf::Sprite& s = textureComponent->sprite; 117 | s.setTexture(textureBank->at(rand() % (randomTexturesEnabled ? textureBank->size() : 1)), true); 118 | scaleTexture(e); 119 | 120 | //Set font info 121 | sf::Text& text = textureComponent->positionText; 122 | text.setFont(boxFont); 123 | text.setCharacterSize(12); 124 | } 125 | 126 | void TextureSystem::scaleTexture(entityx::Entity e) 127 | { 128 | sf::Sprite& s = e.component()->sprite; 129 | auto type = e.component()->type; 130 | float scalar = pixels(texturemap[type].second); 131 | auto texsize = s.getTexture()->getSize(); 132 | s.setOrigin(texsize.x/2, texsize.y/2); 133 | s.setScale(1,1); 134 | s.scale(scalar / texsize.x, scalar / texsize.y); 135 | } 136 | 137 | void TextureSystem::configure(entityx::EventManager& events) 138 | { 139 | events.subscribe(*this); 140 | events.subscribe>(*this); 141 | } 142 | 143 | void TextureSystem::receive(const GraphicsEvent& e) 144 | { 145 | switch(e.type) { 146 | case GraphicsEvent::ImageRender: { 147 | imageRenderEnabled = e.value; 148 | break; 149 | } 150 | case GraphicsEvent::RandomTextures: { 151 | randomTexturesEnabled = e.value; 152 | for(ex::Entity e : entities.entities_with_components()) 153 | retexture(e); 154 | break; 155 | } 156 | case GraphicsEvent::ShowPositions: { 157 | positionTextEnabled = e.value; 158 | break; 159 | } 160 | default: { 161 | break; 162 | } 163 | } 164 | } 165 | 166 | void TextureSystem::receive(const ex::ComponentAddedEvent& e) 167 | { 168 | unspawned.push_back(e.entity); 169 | } 170 | -------------------------------------------------------------------------------- /src/sdl2d3/systems/TextureSystem.h: -------------------------------------------------------------------------------- 1 | #ifndef TEXTURESYSTEM_H 2 | #define TEXTURESYSTEM_H 3 | 4 | #include 5 | #include 6 | #include "utility/keyvalues.h" 7 | #include "sdl2d3/events.h" 8 | #include "sdl2d3/components.h" 9 | namespace ex = entityx; 10 | 11 | /* The texture system takes the world entities (with Box2DLTBLComponent) 12 | * and draws textures over them. Handles random textures and management there. 13 | * Also draws the background texture */ 14 | 15 | class TextureSystem : public ex::System, public ex::Receiver 16 | { 17 | public: 18 | TextureSystem(sf::RenderWindow& rw, ex::EntityManager& entities, KeyValue& keys); 19 | 20 | public: 21 | /** EntityX Interfaces **/ 22 | //Updating is drawing textures all over the Box2D objects 23 | void update(ex::EntityManager&, ex::EventManager&, ex::TimeDelta) override; 24 | 25 | //Receiving events; this is coming from the GUI enabling/disable graphic freatures 26 | void configure(ex::EventManager& events) override; 27 | void receive(const GraphicsEvent& e); 28 | void receive(const ex::ComponentAddedEvent& e); 29 | 30 | private: 31 | //Reference to window to draw below textures to 32 | sf::RenderWindow& window; 33 | 34 | //Textures; Multiple are supported for boxes/balls. 35 | //`loadTextures` loads a colon-delimited list of textures into a vector 36 | //`texturemap` is a map of "type" -> {aviliable textures for type, Box2D scale factor} 37 | std::map*,float>> texturemap; 38 | void loadTextures(std::vector&, const std::string&); 39 | std::vector boxTextures, ballTextures; 40 | sf::Texture bgTexture; 41 | sf::Sprite bgSprite; 42 | sf::Font boxFont; 43 | 44 | //Figure out textures for an entity, and handle untextures entities 45 | void addToWorld(ex::Entity e); 46 | void retexture(ex::Entity e); 47 | void scaleTexture(ex::Entity e); 48 | std::list unspawned; 49 | 50 | //State data. Passed from Graphics portion of GUI window 51 | bool imageRenderEnabled; 52 | bool randomTexturesEnabled; 53 | bool positionTextEnabled; 54 | 55 | private: 56 | //EntityX reference data, convience. 57 | ex::EntityManager& entities; 58 | }; 59 | 60 | #endif // TEXTURESYSTEM_H 61 | -------------------------------------------------------------------------------- /src/utility/SFMLDebugDraw.cpp: -------------------------------------------------------------------------------- 1 | // Debug draw for Box2D 2.2.1 - 2.3.0 for SFML 2.0 - SFMLDebugDraw.cpp 2 | // Copyright (C) 2013 Matija Lovrekovic 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | 17 | #include "SFMLDebugDraw.h" 18 | 19 | void SFMLDebugDraw::DrawPoint(const b2Vec2&, float32, const b2Color&) 20 | { 21 | //I don't think this is used in the scope of DebugDraw used by SDL2D3 22 | } 23 | 24 | void SFMLDebugDraw::DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) 25 | { 26 | sf::ConvexShape polygon(vertexCount); 27 | sf::Vector2f center; 28 | for(int i = 0; i < vertexCount; i++) 29 | { 30 | //polygon.setPoint(i, SFMLDraw::B2VecToSFVec(vertices[i])); 31 | sf::Vector2f transformedVec = SFMLDebugDraw::B2VecToSFVec(vertices[i]); 32 | polygon.setPoint(i, sf::Vector2f(std::floor(transformedVec.x), std::floor(transformedVec.y))); // flooring the coords to fix distorted lines on flat surfaces 33 | } // they still show up though.. but less frequently 34 | polygon.setOutlineThickness(-1.f); 35 | polygon.setFillColor(sf::Color::Transparent); 36 | polygon.setOutlineColor(SFMLDebugDraw::GLColorToSFML(color)); 37 | 38 | m_window->draw(polygon); 39 | } 40 | void SFMLDebugDraw::DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) 41 | { 42 | sf::ConvexShape polygon(vertexCount); 43 | for(int i = 0; i < vertexCount; i++) 44 | { 45 | //polygon.setPoint(i, SFMLDraw::B2VecToSFVec(vertices[i])); 46 | sf::Vector2f transformedVec = SFMLDebugDraw::B2VecToSFVec(vertices[i]); 47 | polygon.setPoint(i, sf::Vector2f(std::floor(transformedVec.x), std::floor(transformedVec.y))); // flooring the coords to fix distorted lines on flat surfaces 48 | } // they still show up though.. but less frequently 49 | polygon.setOutlineThickness(-1.f); 50 | polygon.setFillColor(SFMLDebugDraw::GLColorToSFML(color, 60)); 51 | polygon.setOutlineColor(SFMLDebugDraw::GLColorToSFML(color)); 52 | 53 | m_window->draw(polygon); 54 | } 55 | void SFMLDebugDraw::DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color) 56 | { 57 | sf::CircleShape circle(radius * sfdd::SCALE); 58 | circle.setOrigin(radius * sfdd::SCALE, radius * sfdd::SCALE); 59 | circle.setPosition(SFMLDebugDraw::B2VecToSFVec(center)); 60 | circle.setFillColor(sf::Color::Transparent); 61 | circle.setOutlineThickness(-1.f); 62 | circle.setOutlineColor(SFMLDebugDraw::GLColorToSFML(color)); 63 | 64 | m_window->draw(circle); 65 | } 66 | void SFMLDebugDraw::DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color) 67 | { 68 | sf::CircleShape circle(radius * sfdd::SCALE); 69 | circle.setOrigin(radius * sfdd::SCALE, radius * sfdd::SCALE); 70 | circle.setPosition(SFMLDebugDraw::B2VecToSFVec(center)); 71 | circle.setFillColor(SFMLDebugDraw::GLColorToSFML(color, 60)); 72 | circle.setOutlineThickness(1.f); 73 | circle.setOutlineColor(SFMLDebugDraw::GLColorToSFML(color)); 74 | 75 | b2Vec2 endPoint = center + radius * axis; 76 | sf::Vertex line[2] = 77 | { 78 | sf::Vertex(SFMLDebugDraw::B2VecToSFVec(center), SFMLDebugDraw::GLColorToSFML(color)), 79 | sf::Vertex(SFMLDebugDraw::B2VecToSFVec(endPoint), SFMLDebugDraw::GLColorToSFML(color)), 80 | }; 81 | 82 | m_window->draw(circle); 83 | m_window->draw(line, 2, sf::Lines); 84 | } 85 | void SFMLDebugDraw::DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color) 86 | { 87 | sf::Vertex line[] = 88 | { 89 | sf::Vertex(SFMLDebugDraw::B2VecToSFVec(p1), SFMLDebugDraw::GLColorToSFML(color)), 90 | sf::Vertex(SFMLDebugDraw::B2VecToSFVec(p2), SFMLDebugDraw::GLColorToSFML(color)) 91 | }; 92 | 93 | m_window->draw(line, 2, sf::Lines); 94 | } 95 | void SFMLDebugDraw::DrawTransform(const b2Transform& xf) 96 | { 97 | float lineLength = 0.4; 98 | 99 | /*b2Vec2 xAxis(b2Vec2(xf.p.x + (lineLength * xf.q.c), xf.p.y + (lineLength * xf.q.s)));*/ 100 | b2Vec2 xAxis = xf.p + lineLength * xf.q.GetXAxis(); 101 | sf::Vertex redLine[] = 102 | { 103 | sf::Vertex(SFMLDebugDraw::B2VecToSFVec(xf.p), sf::Color::Red), 104 | sf::Vertex(SFMLDebugDraw::B2VecToSFVec(xAxis), sf::Color::Red) 105 | }; 106 | 107 | // You might notice that the ordinate(Y axis) points downward unlike the one in Box2D testbed 108 | // That's because the ordinate in SFML coordinate system points downward while the OpenGL(testbed) points upward 109 | /*b2Vec2 yAxis(b2Vec2(xf.p.x + (lineLength * -xf.q.s), xf.p.y + (lineLength * xf.q.c)));*/ 110 | b2Vec2 yAxis = xf.p + lineLength * xf.q.GetYAxis(); 111 | sf::Vertex greenLine[] = 112 | { 113 | sf::Vertex(SFMLDebugDraw::B2VecToSFVec(xf.p), sf::Color::Green), 114 | sf::Vertex(SFMLDebugDraw::B2VecToSFVec(yAxis), sf::Color::Green) 115 | }; 116 | 117 | m_window->draw(redLine, 2, sf::Lines); 118 | m_window->draw(greenLine, 2, sf::Lines); 119 | } 120 | -------------------------------------------------------------------------------- /src/utility/SFMLDebugDraw.h: -------------------------------------------------------------------------------- 1 | // Debug draw for Box2D 2.2.1 - 2.3.0 for SFML 2.0 - SFMLDebugDraw.h 2 | // Copyright (C) 2013 Matija Lovrekovic 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | 17 | //[TehPwns] This is a modified version for SDL2D3. Notably, the use if conf::ppm, setWindow, 18 | //and the new DrawPoint function from Box2D 19 | 20 | #ifndef SFMLDEBUGDRAW_H 21 | #define SFMLDEBUGDRAW_H 22 | 23 | #include "utility/utility.h" 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | namespace sfdd 30 | { 31 | const float SCALE = conf::ppm; //Scale of pixels per meter 32 | } 33 | 34 | class SFMLDebugDraw : public b2Draw 35 | { 36 | private: 37 | sf::RenderWindow* m_window = nullptr; 38 | public: 39 | void setWindow(sf::RenderWindow& window) { 40 | m_window = &window; 41 | } 42 | 43 | /// Convert Box2D's OpenGL style color definition[0-1] to SFML's color definition[0-255], with optional alpha byte[Default - opaque] 44 | static sf::Color GLColorToSFML(const b2Color &color, sf::Uint8 alpha = 255) 45 | { 46 | return sf::Color(static_cast(color.r * 255), static_cast(color.g * 255), static_cast(color.b * 255), alpha); 47 | } 48 | 49 | /// Convert Box2D's vector to SFML vector [Default - scales the vector up by SCALE constants amount] 50 | static sf::Vector2f B2VecToSFVec(const b2Vec2 &vector, bool scaleToPixels = true) 51 | { 52 | return sf::Vector2f(vector.x * (scaleToPixels ? sfdd::SCALE : 1.f), vector.y * (scaleToPixels ? sfdd::SCALE : 1.f)); 53 | } 54 | 55 | public: 56 | // Draw a point (New). 57 | void DrawPoint(const b2Vec2& p, float32 size, const b2Color& color); 58 | 59 | /// Draw a closed polygon provided in CCW order. 60 | void DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color); 61 | 62 | /// Draw a solid closed polygon provided in CCW order. 63 | void DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color); 64 | 65 | /// Draw a circle. 66 | void DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color); 67 | 68 | /// Draw a solid circle. 69 | void DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color); 70 | 71 | /// Draw a line segment. 72 | void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color); 73 | 74 | /// Draw a transform. Choose your own length scale. 75 | void DrawTransform(const b2Transform& xf); 76 | }; 77 | #endif //SFMLDEBUGDRAW_H 78 | -------------------------------------------------------------------------------- /src/utility/keyvalues.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // KeyValues.cpp 3 | // KeyValues 4 | // 5 | // Created by David S. on 06.06.13. 6 | // Copyright (c) 2013 David S. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include "keyvalues.h" 12 | 13 | //--------------------------------------------------------- 14 | //--------------------------------------------------------- 15 | void KeyValue::LoadFromFile(const std::string &filename) 16 | { 17 | std::ifstream file; 18 | file.open(filename.c_str()); 19 | 20 | std::string line; 21 | std::size_t lineNo = 0; 22 | std::string key, value; 23 | 24 | if (file.is_open()) 25 | { 26 | while (std::getline(file, line)) 27 | { 28 | lineNo++; 29 | std::string temp = line; 30 | 31 | temp.erase(0, temp.find_first_not_of("\t ")); 32 | std::size_t pos = temp.find('='); 33 | 34 | RemoveComment(temp); 35 | if(OnlyWhiteSpace(temp)) 36 | continue; 37 | 38 | ExtractKey(key, pos, temp); 39 | ExtractValue(value, pos, temp); 40 | 41 | if (!KeyExist(key)) 42 | m_Keys[key] = value; 43 | else 44 | std::cerr << key << " already exists." << std::endl; 45 | } 46 | } 47 | else 48 | { 49 | std::cerr << "KeyValues: File " << filename << " couldn't be found!\n"; 50 | } 51 | } 52 | 53 | //--------------------------------------------------------- 54 | //--------------------------------------------------------- 55 | void KeyValue::SaveToFile(const std::string &filename) 56 | { 57 | std::ofstream file; 58 | file.open(filename.c_str()); 59 | 60 | if(file.is_open()) 61 | { 62 | for (std::map::iterator it = m_Keys.begin(); it != m_Keys.end(); ++it) 63 | { 64 | file << it->first << "=" << it->second << std::endl; 65 | } 66 | } 67 | else 68 | { 69 | std::cerr << "KeyValues: File " << filename << " couldn't be found!" << std::endl; 70 | } 71 | 72 | file.close(); 73 | } 74 | 75 | //--------------------------------------------------------- 76 | //--------------------------------------------------------- 77 | void KeyValue::SetString(const std::string &key, const std::string &value) 78 | { 79 | if (!KeyExist(key)) 80 | m_Keys[key] = value; 81 | else 82 | std::cerr << key << " already exists." << std::endl; 83 | } 84 | 85 | //--------------------------------------------------------- 86 | //--------------------------------------------------------- 87 | void KeyValue::SetInt(const std::string &key, int value) 88 | { 89 | if (!KeyExist(key)) 90 | m_Keys[key] = std::to_string(value); 91 | else 92 | std::cerr << key << " already exists." << std::endl; 93 | } 94 | 95 | //--------------------------------------------------------- 96 | //--------------------------------------------------------- 97 | void KeyValue::SetFloat(const std::string &key, float value) 98 | { 99 | if (!KeyExist(key)) 100 | m_Keys[key] = std::to_string(value); 101 | else 102 | std::cerr << key << " already exists." << std::endl; 103 | } 104 | 105 | //--------------------------------------------------------- 106 | //--------------------------------------------------------- 107 | std::string KeyValue::GetString(const std::string &key) const 108 | { 109 | auto it = m_Keys.find(key); 110 | if (it != m_Keys.end()) 111 | return it->second; 112 | else 113 | return ""; 114 | } 115 | 116 | //--------------------------------------------------------- 117 | //--------------------------------------------------------- 118 | int KeyValue::GetInt(const std::string &key) const 119 | { 120 | auto it = m_Keys.find(key); 121 | if (it != m_Keys.end()) 122 | return std::stoi(it->second); 123 | else 124 | return 0; 125 | } 126 | 127 | //--------------------------------------------------------- 128 | //--------------------------------------------------------- 129 | float KeyValue::GetFloat(const std::string &key) const 130 | { 131 | auto it = m_Keys.find(key); 132 | if (it != m_Keys.end()) 133 | return std::stof(it->second); 134 | else 135 | return 0.0f; 136 | } 137 | 138 | //--------------------------------------------------------- 139 | //--------------------------------------------------------- 140 | void KeyValue::ExtractKey(std::string &key, std::size_t pos, const std::string &line) 141 | { 142 | key = line.substr(0, pos); 143 | if (key.find('\t') != line.npos || key.find(' ') != line.npos) 144 | key.erase(key.find_first_of("\t ")); 145 | } 146 | 147 | //--------------------------------------------------------- 148 | //--------------------------------------------------------- 149 | void KeyValue::ExtractValue(std::string &value, std::size_t pos, const std::string &line) 150 | { 151 | value = line.substr(pos + 1); 152 | value.erase(0, value.find_first_not_of("\t ")); 153 | value.erase(value.find_last_not_of("\t ") + 1); 154 | } 155 | 156 | //--------------------------------------------------------- 157 | //--------------------------------------------------------- 158 | bool KeyValue::KeyExist(const std::string &key) const 159 | { 160 | return m_Keys.find(key) != m_Keys.end(); 161 | } 162 | 163 | //--------------------------------------------------------- 164 | //--------------------------------------------------------- 165 | void KeyValue::RemoveComment(std::string &line) const 166 | { 167 | if(line.find(';') != line.npos) 168 | line.erase(line.find(';')); 169 | } 170 | 171 | //--------------------------------------------------------- 172 | //--------------------------------------------------------- 173 | bool KeyValue::OnlyWhiteSpace(const std::string &line) const 174 | { 175 | return (line.find_first_not_of(' ') == line.npos); 176 | } 177 | -------------------------------------------------------------------------------- /src/utility/keyvalues.h: -------------------------------------------------------------------------------- 1 | // 2 | // KeyValues.h 3 | // KeyValues 4 | // 5 | // Created by David S. on 06.06.13. 6 | // Copyright (c) 2013 David S. All rights reserved. 7 | // 8 | 9 | #ifndef KEYVALUES_H 10 | #define KEYVALUES_H 11 | 12 | #include 13 | #include 14 | 15 | class KeyValue 16 | { 17 | public: 18 | void LoadFromFile(const std::string &filename); 19 | void SaveToFile(const std::string &filename); 20 | 21 | void SetString(const std::string &key, const std::string &value); 22 | void SetInt(const std::string &key, int value); 23 | void SetFloat(const std::string &key, float value); 24 | 25 | std::string GetString(const std::string &key) const; 26 | int GetInt(const std::string &key) const; 27 | float GetFloat(const std::string &key) const; 28 | 29 | private: 30 | void ExtractKey(std::string &key, std::size_t pos, const std::string &line); 31 | void ExtractValue(std::string &value, std::size_t pos, const std::string &line); 32 | bool KeyExist(const std::string &key) const; 33 | void RemoveComment(std::string &line) const; 34 | bool OnlyWhiteSpace(const std::string &line) const; 35 | std::map m_Keys; 36 | }; 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /src/utility/utility.cpp: -------------------------------------------------------------------------------- 1 | #include "utility.h" 2 | 3 | float meters(int pixels) 4 | { 5 | return pixels * conf::mpp; 6 | } 7 | 8 | float pixels(long double meters) 9 | { 10 | return meters * conf::ppm; 11 | } 12 | 13 | float operator"" _px(unsigned long long int _pixels) { 14 | return meters(_pixels); 15 | } 16 | -------------------------------------------------------------------------------- /src/utility/utility.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILITY_H 2 | #define UTILITY_H 3 | 4 | namespace conf { 5 | 6 | //Conversion factors for pixels to MKS 7 | static constexpr float ppm = 15.f; //Pixels-Per-Meter 8 | static constexpr float mpp = 1.f/ppm; //Meters-Per-Pixel 9 | 10 | //Dimentions of spawned entities 11 | static constexpr float box_halfwidth = 20.f * mpp; //Halfwidth of spwaned boxed in px 12 | static constexpr float circle_radius = 30.f * mpp; //Radius of spawned circles in px 13 | 14 | } 15 | 16 | //Convert a pixels value to meters 17 | float meters(int pixels); 18 | 19 | //Do the oppsite 20 | float pixels(long double meters); 21 | 22 | //Allows literals like 10px, which convert to the meter value 23 | float operator"" _px(unsigned long long int _pixels); 24 | 25 | #endif // UTILITY_H 26 | --------------------------------------------------------------------------------