- added Windows build using MinGW for box demo along with Windows instructions to main README

- replaced Model class in box demo with library's Model class
- switched GL context profile mask to compatibility in Windows builds
- only open audio device if audio is initialized
- increase default audio frequency and buffer size
- convert path objects to strings for compatibility with MinGW
- update MinGW builds to use regular filesystem library instead of experimental
This commit is contained in:
ohsqueezy 2023-10-18 00:07:32 -04:00
parent d575307b15
commit e168844fc5
17 changed files with 235 additions and 448 deletions

View File

@ -16,7 +16,7 @@ SPACEBOX
*SPACEBOX* is a C++ framework that makes creating cross-platform games and other interactive applications easier and faster by providing an added layer of abstraction between SDL + OpenGL and the project.
Users can start a project by extending only a single function, the Game class's update function. Using a standard Makefile that can be taken from the examples, the framework can export the same code to multiple platforms like, in order of current stability, Linux, Web, Android, OS X, Windows, and Raspberry Pi.
Users can start a project by extending only a single function, the Game class's update function. Using a standard Makefile that can be taken from the examples, the framework can export the same code to multiple platforms such as, in order of current stability, Linux, Web, Android, OS X, Windows, and Raspberry Pi.
It is in an early, untested state. It comes with a few simple examples that demonstrate how to use it.
@ -265,9 +265,41 @@ These steps were taken to build the fill_screen demo for Android. The Android SD
Note that `SDL_WINDOW_RESIZABLE` is [required for screen rotation](https://discourse.libsdl.org/t/screen-orientation-not-changing-when-rotating-android-device/26676) to work
### OS X, Windows
#### Cross compilation considerations
Builds for these platforms have only passed the proof of concept phase. An early version of SPACEBOX was compiled for each of them, but none of the demos have been compiled for them in their current form, so there is only some broken code available in the box demo Makefile.
* `std::filesystem::exists` will not work with files stored in the Android APK
### Windows
Windows builds are made with MinGW. The box demo contains a make target for building a Windows 32-bit executable from a Linux system. To build from Windows itself, the make target will have to be modified. The SDL MinGW releases and MinGW itself must be downloaded separately.
Download SDL's MinGW libraries from the SDL releases page. Download the libraries for SDL image, SDL mixer, and SDL ttf as well.
mkdir SDL2-mingw
cd SDL2-mingw
wget "https://github.com/libsdl-org/SDL/releases/download/release-2.24.2/SDL2-devel-2.24.2-mingw.zip"
unzip SDL2-devel-2.24.2-mingw.zip
wget "https://github.com/libsdl-org/SDL_image/releases/download/prerelease-2.5.2/SDL2_image-devel-2.5.2-mingw.tar.gz"
tar -xf SDL2_image-devel-2.5.2-mingw.tar.gz
wget "https://github.com/libsdl-org/SDL_ttf/releases/download/release-2.0.15/SDL2_ttf-devel-2.0.15-mingw.tar.gz"
tar -xf SDL2_ttf-devel-2.0.15-mingw.tar.gz
wget "https://github.com/libsdl-org/SDL_mixer/releases/download/prerelease-2.5.2/SDL2_mixer-devel-2.5.2-mingw.tar.gz"
tar -xf SDL2_mixer-devel-2.5.2-mingw.tar.gz
Install MinGW. The simplest way to install is through the package manager. On Debian the command is
apt install mingw-w64
See the Windows section of `demo/box/Makefile` for the necessary flags and build process.
#### Cross compilation considerations
* `std::filesystem::path::c_str` returns a `const wchar_t*` instead of `const char*`. To make a platform generic call, convert the path to a string, then use `std::filesystem::path::string::c_str` instead.
* In order to use `std::thread` with MinGW, you must use the POSIX version of the compiler, for example `x86_64-w64-mingw32-g++-posix` and add `-lpthread` to the linker flags.
### OS X
Builds for OS X have only passed the proof of concept phase. An early version of SPACEBOX was compiled for it, but none of the demos have been compiled in their current form, so there is only some broken code available in the box demo's `Makefile`.
Demos
-----

View File

@ -1,16 +1,16 @@
/*!<pre>
* /\ +------------------------------------------------------+
* ____/ \____ /| - Open source game framework licensed to freely use, |
* \ / / | copy, modify and sell without restriction |
* +--\ ^__^ /--+ | |
* | ~/ \~ | | - created for <https://foam.shampoo.ooo> |
* | ~~~~~~~~~~~~ | +------------------------------------------------------+
* | SPACE ~~~~~ | /
* | ~~~~~~~ BOX |/
* +--------------+ </pre>
*
* Display a rotating box with a space texture and gradient background using SDL, OpenGL, and Spacebox.
*/
/* +------------------------------------------------------+
____/ \____ /| - Open source game framework licensed to freely use, |
\ / / | copy, modify and sell without restriction |
+--\ ^__^ /--+ | |
| ~/ \~ | | - created for <https://foam.shampoo.ooo> |
| ~~~~~~~~~~~~ | +------------------------------------------------------+
| SPACE ~~~~~ | /
| ~~~~~~~ BOX |/
+--------------+
Display a rotating box with a space texture and gradient background using SDL, OpenGL, and [SPACE BOX].
*/
#include <iostream>
#include <stdio.h>
@ -34,8 +34,8 @@ struct BoxDemo : Game
private:
Model box;
Plane background;
sb::Model box;
sb::Plane background;
bool right_active = false, down_active = false, left_active = false, up_active = false, is_writing_audio = true;
SDL_Event event;
sb::Texture fake;
@ -43,6 +43,7 @@ private:
glm::mat4 projection, view, model = glm::mat4(1.0f), mvp;
sb::VAO vao;
sb::VBO vbo;
sb::Timer timer;
public:
@ -51,8 +52,9 @@ public:
Mix_Music *music = Mix_LoadMUS("resource/Field.mp3");
Mix_PlayMusic(music, -1);
load_gl_context();
delegate.subscribe(&BoxDemo::respond, this);
delegate.subscribe(&BoxDemo::respond, this, SDL_MOUSEBUTTONDOWN);
delegate().subscribe(&BoxDemo::respond, this);
delegate().subscribe(&BoxDemo::respond, this, SDL_MOUSEBUTTONDOWN);
timer.on();
}
void load_gl_context()
@ -82,7 +84,7 @@ public:
v4-v7-v6 (back)
v6-v5-v4
*/
box = Model({
box = sb::Model({
{"position", {
{1, 1, 1}, {-1, 1, 1}, {-1,-1, 1},
{-1,-1, 1}, {1,-1, 1}, {1, 1, 1},
@ -113,7 +115,7 @@ public:
}}
});
box.texture(sb::Texture());
box.texture().load("resource/tile.png");
box.texture(0).load("resource/tile.png");
/* Create a 1x1 white texture */
glm::vec2 fake_size = {1, 1};
@ -145,24 +147,24 @@ public:
world_program = glCreateProgram();
glAttachShader(world_program, triangle_vertex_shader);
glAttachShader(world_program, fragment_shader);
box.attributes("position")->bind(3, world_program, "in_Position");
box.attributes("uv")->bind(4, world_program, "vertexUV");
link_shader(world_program);
box.attributes("position")->bind("in_Position", world_program);
box.attributes("uv")->bind("vertexUV", world_program);
flat_program = glCreateProgram();
glAttachShader(flat_program, flat_vertex_shader);
glAttachShader(flat_program, fragment_shader);
background.attributes("position")->bind(0, flat_program, "in_Position");
background.attributes("uv")->bind(1, flat_program, "vertexUV");
background.attributes("color")->bind(2, flat_program, "in_Color");
link_shader(flat_program);
background.attributes("position")->bind("in_Position", flat_program);
background.attributes("uv")->bind("vertexUV", flat_program);
background.attributes("color")->bind("in_Color", flat_program);
mvp_uniform_id = glGetUniformLocation(world_program, "MVP");
/* Fill VBO with attribute data */
vbo.allocate(background.size() + box.size(), GL_STATIC_DRAW);
vbo.add(*Plane::position);
vbo.add(*Plane::uv);
vbo.add(*sb::Plane::position);
vbo.add(*sb::Plane::uv);
vbo.add(*background.attributes("color"));
vbo.add(*box.attributes("position"));
vbo.add(*box.attributes("uv"));
@ -182,29 +184,31 @@ public:
void respond(SDL_Event& event)
{
if (delegate.compare(event, "play-sound") || event.type == SDL_MOUSEBUTTONDOWN)
if (delegate().compare(event, "play-sound") || event.type == SDL_MOUSEBUTTONDOWN)
{
Mix_Chunk* music = Mix_LoadWAV("resource/Ag.ogg");
Mix_PlayChannel(-1, music, 0);
}
}
void update()
void update(float timestamp)
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
/* Keep timer up to date */
timer.update(timestamp);
/* Draw background */
glUseProgram(flat_program);
box.disable();
background.bind();
background.enable();
background.texture().bind();
glDrawArrays(GL_TRIANGLES, 0, background.attributes("position")->count());
/* Rotate projection matrix */
float rotation = .0005f * get_frame_length();
model = glm::rotate(model, rotation, glm::vec3(0.0f, 1.0f, 0.0f));
model = glm::rotate(model, timer.delta(0.25f), glm::vec3(0.0f, 1.0f, 0.0f));
mvp = projection * view * model;
glUseProgram(world_program);
@ -218,8 +222,8 @@ public:
/* Draw the box */
glEnable(GL_DEPTH_TEST);
background.disable();
box.bind();
box.enable();
box.texture().bind();
glDrawArrays(GL_TRIANGLES, 0, box.attributes("position")->count());
SDL_GL_SwapWindow(window());
}

View File

@ -8,24 +8,26 @@
# | ~~~~~~~ BOX |/
# +--------------+
#
# These are build targets for the box demo for Linux, Android, and web. Other platforms haven't been tested in a while
# and won't work without significant editing. Modify variables as necessary to match the system this is running on and
# run `make box`, `make build/android/ooo.shampoo.box/app_debug.apk`, or `make box_demo.js` in the current directory.
# These are build targets for the box demo for Linux, Android, Windows, and web. There is also outdated code for OS X
# at the end of the file that is broken. The Android build also has not been tested in a bit.
#
# Modify variables as necessary to match the system this is running on and run make for the appropriate target, for
# example `make Box-linux.x86_64` for a Linux executable and `make Box-windows_32bit.exe" for Windows.
#######################
# Location parameters #
#######################
# Location of source files for the demo
SRC_DIR := ./
SRC_DIR := .
# Locations of [SPACEBOX] source and dependencies required to be compiled from source. These locations are configured to match
# the structure of the [SPACEBOX] repository but can be modified as necessary.
SB_DIR := ../../
SB_SRC_DIR := $(SB_DIR)src/
SB_LIB_DIR := $(SB_DIR)lib/
SDLGFX2_DIR := $(SB_LIB_DIR)sdl2-gfx/
GLEW_DIR := $(SB_LIB_DIR)glew/
SB_DIR := ../..
SB_SRC_DIR := $(SB_DIR)/src
SB_LIB_DIR := $(SB_DIR)/lib
SDLGFX2_DIR := $(SB_LIB_DIR)/sdl2-gfx
GLEW_DIR := $(SB_LIB_DIR)/glew
# C and C++ compiler commands
CC := clang
@ -35,46 +37,48 @@ CXX := clang++
SDLCONFIG := ~/local/sdl/bin/sdl2-config
# Edit to point to the location of BPmono.ttf
CREATE_FONT_SYMLINK := ln -nsf $(SB_DIR)"BPmono.ttf" .
CREATE_FONT_SYMLINK := ln -nsf $(SB_DIR)/"BPmono.ttf" .
#############################
# Based on above parameters #
#############################
# Use SDL's utility program to get compilation and linker flags
SDL_CFLAGS = $(shell $(SDLCONFIG) --cflags)
SDL_LFLAGS := $(shell $(SDLCONFIG) --libs)
SB_H_FILES := $(wildcard $(addprefix $(SB_SRC_DIR),*.hpp))
SB_O_FILES := $(filter-out $(addprefix $(SB_SRC_DIR),filesystem.o),$(SB_H_FILES:.hpp=.o))
SRC_H_FILES := $(wildcard $(addprefix $(SRC_DIR),*.hpp))
SRC_O_FILES := BoxDemo.o $(SRC_H_FILES:.hpp=.o)
# Get all SPACEBOX header files, and get a list of object targets by replacing the .cpp suffix with .o
SB_H_FILES := $(wildcard $(addprefix $(SB_SRC_DIR)/,*.hpp))
SB_O_FILES := $(patsubst %.cpp, %.o, $(wildcard $(addprefix $(SB_SRC_DIR)/,*.cpp)))
SRC_O_FILES := $(SRC_DIR)/BoxDemo.o
#################################################################
# Targets for building [SPACEBOX], dependencies and demo source #
#################################################################
$(SDLGFX2_DIR)%.o: $(SDLGFX2_DIR)%.c $(SDLGFX2_DIR)%.h
$(GLEW_DIR)%.o: $(GLEW_DIR)%.c $(GLEW_DIR)%.h
$(SDLGFX2_DIR)/%.o: $(SDLGFX2_DIR)/%.c $(SDLGFX2_DIR)/%.h
$(GLEW_DIR)/%.o: $(GLEW_DIR)/%.c $(GLEW_DIR)/%.h
$(CC) $< $(CFLAGS) -c -o $@
$(SB_SRC_DIR)extension.o: $(addprefix $(SB_SRC_DIR),Box.hpp Segment.hpp Color.hpp filesystem.hpp Pixels.hpp Log.hpp)
$(SB_SRC_DIR)Node.o: $(addprefix $(SB_SRC_DIR),Game.hpp Configuration.hpp Delegate.hpp Display.hpp Input.hpp Box.hpp Audio.hpp Log.hpp)
$(SB_SRC_DIR)Game.o: $(addprefix $(SB_SRC_DIR),extension.hpp Node.hpp Recorder.hpp Input.hpp Configuration.hpp Delegate.hpp Audio.hpp Log.hpp)
$(SB_SRC_DIR)Animation.o: $(addprefix $(SB_SRC_DIR),Node.hpp Timer.hpp)
$(SB_SRC_DIR)Recorder.o: $(addprefix $(SB_SRC_DIR),Node.hpp Game.hpp Configuration.hpp Delegate.hpp Animation.hpp extension.hpp)
$(SB_SRC_DIR)Input.o: $(addprefix $(SB_SRC_DIR),Node.hpp Animation.hpp Configuration.hpp Delegate.hpp)
$(SB_SRC_DIR)Configuration.o: $(addprefix $(SB_SRC_DIR),Node.hpp Animation.hpp Log.hpp)
$(SB_SRC_DIR)Delegate.o: $(addprefix $(SB_SRC_DIR),Node.hpp Game.hpp Input.hpp)
$(SB_SRC_DIR)Display.o: $(addprefix $(SB_SRC_DIR),Node.hpp Game.hpp Box.hpp Configuration.hpp Delegate.hpp Log.hpp)
$(SB_SRC_DIR)Box.o: $(addprefix $(SB_SRC_DIR),extension.hpp Segment.hpp)
$(SB_SRC_DIR)Segment.o: $(addprefix $(SB_SRC_DIR),extension.hpp Box.hpp)
$(SB_SRC_DIR)Pixels.o: $(addprefix $(SB_SRC_DIR),Box.hpp extension.hpp Log.hpp utility.hpp)
$(SB_SRC_DIR)Audio.o: $(addprefix $(SB_SRC_DIR),Node.hpp Display.hpp Configuration.hpp Box.hpp filesystem.hpp extension.hpp)
$(SB_SRC_DIR)GLObject.o: $(addprefix $(SB_SRC_DIR),Log.hpp)
$(SB_SRC_DIR)Texture.o: $(addprefix $(SB_SRC_DIR),GLObject.hpp filesystem.hpp Log.hpp)
$(SB_SRC_DIR)VBO.o: $(addprefix $(SB_SRC_DIR),Log.hpp GLObject.hpp Attributes.hpp extension.hpp)
$(SB_SRC_DIR)Attributes.o: $(addprefix $(SB_SRC_DIR),Log.hpp extension.hpp)
$(SRC_DIR)Model.o: $(addprefix $(SB_SRC_DIR),extension.hpp Attributes.hpp Texture.hpp utility.hpp)
$(SRC_DIR)BoxDemo.o: $(SRC_H_FILES) $(SB_H_FILES)
$(SB_SRC_DIR)/extension.o: $(addprefix $(SB_SRC_DIR)/,Box.hpp Segment.hpp Color.hpp filesystem.hpp Pixels.hpp Log.hpp)
$(SB_SRC_DIR)/Node.o: $(addprefix $(SB_SRC_DIR)/,Game.hpp Configuration.hpp Delegate.hpp Display.hpp Input.hpp Box.hpp Audio.hpp Log.hpp)
$(SB_SRC_DIR)/Game.o: $(addprefix $(SB_SRC_DIR)/,extension.hpp Node.hpp Recorder.hpp Input.hpp Configuration.hpp Delegate.hpp Audio.hpp Log.hpp)
$(SB_SRC_DIR)/Animation.o: $(addprefix $(SB_SRC_DIR)/,Node.hpp Timer.hpp)
$(SB_SRC_DIR)/Recorder.o: $(addprefix $(SB_SRC_DIR)/,Node.hpp Game.hpp Configuration.hpp Delegate.hpp Animation.hpp extension.hpp)
$(SB_SRC_DIR)/Input.o: $(addprefix $(SB_SRC_DIR)/,Node.hpp Animation.hpp Configuration.hpp Delegate.hpp)
$(SB_SRC_DIR)/Configuration.o: $(addprefix $(SB_SRC_DIR)/,Node.hpp Animation.hpp Log.hpp)
$(SB_SRC_DIR)/Delegate.o: $(addprefix $(SB_SRC_DIR)/,Node.hpp Game.hpp Input.hpp)
$(SB_SRC_DIR)/Display.o: $(addprefix $(SB_SRC_DIR)/,Node.hpp Game.hpp Box.hpp Configuration.hpp Delegate.hpp Log.hpp)
$(SB_SRC_DIR)/Box.o: $(addprefix $(SB_SRC_DIR)/,extension.hpp Segment.hpp)
$(SB_SRC_DIR)/Segment.o: $(addprefix $(SB_SRC_DIR)/,extension.hpp Box.hpp)
$(SB_SRC_DIR)/Pixels.o: $(addprefix $(SB_SRC_DIR)/,Box.hpp extension.hpp Log.hpp)
$(SB_SRC_DIR)/Audio.o: $(addprefix $(SB_SRC_DIR)/,Node.hpp Display.hpp Configuration.hpp Box.hpp filesystem.hpp extension.hpp)
$(SB_SRC_DIR)/GLObject.o: $(addprefix $(SB_SRC_DIR)/,Log.hpp)
$(SB_SRC_DIR)/Texture.o: $(addprefix $(SB_SRC_DIR)/,GLObject.hpp filesystem.hpp Log.hpp)
$(SB_SRC_DIR)/VBO.o: $(addprefix $(SB_SRC_DIR)/,Log.hpp GLObject.hpp Attributes.hpp extension.hpp)
$(SB_SRC_DIR)/Attributes.o: $(addprefix $(SB_SRC_DIR)/,Log.hpp extension.hpp)
$(SRC_DIR)/BoxDemo.o: $(SB_H_FILES)
%.o: %.cpp %.hpp
$(CXX) $(CXXFLAGS) $< -c -o $@
@ -82,12 +86,12 @@ $(SRC_DIR)BoxDemo.o: $(SRC_H_FILES) $(SB_H_FILES)
# Linux #
#########
box: CFLAGS = -Wall -Wextra -g -O3 -c -I$(SB_LIB_DIR) -I$(SB_SRC_DIR) $(SDL_CFLAGS)
box: CXXFLAGS = $(CFLAGS) --std=c++17
box: LFLAGS = $(SDL_LFLAGS) -Wl,--enable-new-dtags -lpthread -lGL -lGLESv2 -lSDL2_image -lSDL2_ttf -lSDL2_mixer -lstdc++fs
box: $(GLEW_DIR)glew.o $(addprefix $(SDLGFX2_DIR),SDL2_rotozoom.o SDL2_gfxPrimitives.o) $(SB_O_FILES) $(SRC_O_FILES)
Box-linux.x86_64: CFLAGS = -Wall -Wextra -g -O3 -c -I$(SB_LIB_DIR) -I$(SB_SRC_DIR) $(SDL_CFLAGS)
Box-linux.x86_64: CXXFLAGS = $(CFLAGS) --std=c++17
Box-linux.x86_64: LFLAGS = $(SDL_LFLAGS) -Wl,--enable-new-dtags -lpthread -lGL -lGLESv2 -lSDL2_image -lSDL2_ttf -lSDL2_mixer -lstdc++fs
Box-linux.x86_64: $(GLEW_DIR)/glew.o $(addprefix $(SDLGFX2_DIR)/,SDL2_rotozoom.o SDL2_gfxPrimitives.o) $(SB_O_FILES) $(SRC_O_FILES)
$(CREATE_FONT_SYMLINK)
$(CXX) $^ $(LFLAGS) -D__LINUX__ -o box
$(CXX) $^ $(LFLAGS) -D__LINUX__ -o $@
#######
# Web #
@ -164,21 +168,61 @@ $(ANDROID_BUILD_DIR)/app-debug.apk: $(ANDROID_BUILD_DIR) $(ANDROID_BUILD_DIR)/$(
ln -nsf app/build/outputs/apk/debug/app-debug.apk $(ANDROID_BUILD_DIR)
ln -nsf app/build/outputs/apk/debug/app-release-unsigned.apk $(ANDROID_BUILD_DIR)
###########
# Windows #
###########
# Set the paths to the directories for the SDL MinGW libraries. See the main README.md for details.
SDL_MINGW_ROOT := $(HOME)/ext/software/SDL2-mingw
SDL_MINGW := $(SDL_MINGW_ROOT)/SDL2-2.24.2/i686-w64-mingw32
SDL_IMG_MINGW := $(SDL_MINGW_ROOT)/SDL2_image-2.5.2/i686-w64-mingw32
SDL_TTF_MINGW := $(SDL_MINGW_ROOT)/SDL2_ttf-2.0.15/i686-w64-mingw32
SDL_MIXER_MINGW := $(SDL_MINGW_ROOT)/SDL2_mixer-2.5.2/i686-w64-mingw32
# Set the compiler to the MinGW compilers. See the main README.md for details.
Box-windows_32bit.exe: CC = i686-w64-mingw32-gcc-posix
Box-windows_32bit.exe: CXX = i686-w64-mingw32-g++-posix
Box-windows_32bit.exe: CFLAGS = -Wall -Wextra -g -O3 -c -DGLEW_STATIC -I$(SB_LIB_DIR) -I$(SB_SRC_DIR) \
-I$(SDL_MINGW)/include/SDL2 -I$(SDL_IMG_MINGW)/include/SDL2 -I$(SDL_TTF_MINGW)/include/SDL2 -I$(SDL_MIXER_MINGW)/include/SDL2
Box-windows_32bit.exe: CXXFLAGS = $(CFLAGS) --std=c++17
Box-windows_32bit.exe: LFLAGS = -lpthread -lstdc++fs \
-L$(SDL_MINGW)/lib -L$(SDL_IMG_MINGW)/lib -L$(SDL_TTF_MINGW)/lib -L$(SDL_MIXER_MINGW)/lib -lmingw32 -lSDL2_image \
-lSDL2_ttf -lSDL2_mixer -lSDL2main -lSDL2 -lopengl32 -static-libstdc++ -static-libgcc
# Compile into the Windows build directory. Zip the executable, config files, shaders, resource folder, and DLLs together into a ZIP archive
# and move in into the build directory.
#
# The libwinpthread-1.dll path should be edited if necessary. The zip utility must be installed on the system. The /tmp directory must also exist.
Box-windows_32bit.exe: $(GLEW_DIR)/glew.o $(addprefix $(SDLGFX2_DIR)/,SDL2_rotozoom.o SDL2_gfxPrimitives.o) $(SB_O_FILES) $(SRC_O_FILES) config.json
$(CREATE_FONT_SYMLINK)
mkdir ${basename $@}
$(CXX) $(filter-out config.json, $^) $(LFLAGS) -o ${basename $@}/$@
cp $(SDL_MINGW)/bin/*.dll $(SDL_IMG_MINGW)/bin/*.dll $(SDL_TTF_MINGW)/bin/*.dll $(SDL_MIXER_MINGW)/bin/*.dll ${basename $@}
cp /usr/i686-w64-mingw32/lib/libwinpthread-1.dll ${basename $@}
cp -r resource/ shaders/ config.json ${basename $@}
zip -r ${@:exe=zip} ${basename $@}
mv ${basename $@} /tmp
rm -rf /tmp/${basename $@}
######################
# Clean object files #
######################
.PHONY = clean clean-all
clean:
-find $(SRC_DIR) -iname "*.o" -delete
rm -f BPmono.ttf
rm -f box
rm -f Box-linux.x86_64
rm -f Box-windows_32bit.zip
clean-all: clean
-find $(SB_SRC_DIR) -iname "*.o" -delete
-find $(SB_LIB_DIR) -iname "*.o" -delete
.PHONY = clean clean-all
#############
# compiledb #
#############
@ -200,29 +244,11 @@ SOFTWARE_ROOT := /home/frank/ext/software
SDLHOME := $(SOFTWARE_ROOT)/SDL2-2.0.14
SDL_IMG_HOME := $(SOFTWARE_ROOT)/SDL2_image-2.0.5
SDL_TTF_HOME := $(SOFTWARE_ROOT)/SDL2_ttf-2.0.15
GLEW_WIN32_HOME := $(SOFTWARE_ROOT)/glew-2.1.0-win32
PROJECTHOME := $(shell pwd)
SDLEMLIBSHOME := $(SDLHOME)/build/em/build/.libs
WINBUILDDIR := win
SDLMINGWHOME := $(SDLHOME)/i686-w64-mingw32
SDL_IMG_MINGW_HOME := $(SDL_IMG_HOME)/i686-w64-mingw32
SDL_TTF_MINGW_HOME := $(SDL_TTF_HOME)/i686-w64-mingw32
APPDIR := Main.app/Contents
SYSFWPATH := /Library/Frameworks
mingw :
if [ ! -d $(BUILDDIR)/$(WINBUILDDIR) ]; then mkdir -p $(BUILDDIR)/$(WINBUILDDIR); fi;
cd $(BUILDDIR)/$(WINBUILDDIR) && \
i686-w64-mingw32-g++ -std=c++17 $(PROJECTHOME)/main.cpp -I$(SDLMINGWHOME)/include/SDL2 \
-I$(SDL_IMG_MINGW_HOME)/include/SDL2 -I$(SDL_TTF_MINGW_HOME)/include/SDL2 $(INC) \
$(PROJECTHOME)/sdl2-gfx/SDL2_gfxPrimitives.c $(PROJECTHOME)/sdl2-gfx/SDL2_rotozoom.c $(PROJECTHOME)/glew/glew.c \
-L$(SDLMINGWHOME)/lib -L$(SDL_IMG_MINGW_HOME)/lib -L$(SDL_TTF_MINGW_HOME)/lib \
-lmingw32 -lSDL2_image \
-lSDL2_ttf -lstdc++fs \
-lSDL2main -lSDL2 -lopengl32 -Wall -O2 -o main.exe && \
cp $(SDLMINGWHOME)/bin/SDL2.dll $(SDL_IMG_MINGW_HOME)/bin/SDL2_image.dll \
$(SDL_TTF_MINGW_HOME)/bin/SDL2_ttf.dll .
osx :
g++ -I $(SYSFWPATH)/SDL2.framework/Headers $(INC) \
-I $(SYSFWPATH)/SDL2_image.framework/Headers -Wl,-rpath,$(SYSFWPATH) \
@ -241,5 +267,3 @@ osx-bundle :
g++ -I $(SYSFWPATH)/SDL2.framework/Headers -I $(SYSFWPATH)/SDL2_image.framework/Headers \
-Wl,-rpath,@executable_path/../Frameworks -Wl,-rpath,$(SYSFWPATH) \
-framework SDL2 -framework SDL2_image -framework OpenGL main.cpp -o $(APPDIR)/MacOS/main
cross : linux android emscripten mingw

View File

@ -1,196 +0,0 @@
/* _______________ ,----------------------------------------------------------------.
//`````````````\\ \ \
//~~~~~~~~~~~~~~~\\ \ by @ohsqueezy & @sleepin \
//=================\\ \ [ohsqueezy.itch.io] [sleepin.itch.io] \
// \\ \ \
// \\ \ code released under the zlib license [git.nugget.fun/pudding] \
// GUNKISS \\ \ \
//_________________________\\ `---------------------------------------------------------------*/
#include "Model.hpp"
/* Default constructor for Model */
Model::Model() {};
/* Construct a Model, adding Attributes each already wrapped in a shared pointer. The attributes should
* be passed as a map with each key being a name and each value being a shared pointer to attributes. */
Model::Model(const std::map<std::string, std::shared_ptr<sb::Attributes>>& attributes_pack)
{
for (auto attributes : attributes_pack)
{
this->attributes(attributes.second, attributes.first);
}
}
/* Construct a Model, adding Attributes, which will each be wrapped in a shared pointer and stored in the
* created object. The attributes should be passed as a map with each key being a name and each value being
* an attributes object. */
Model::Model(const std::map<std::string, sb::Attributes>& attributes_pack)
{
for (auto attributes : attributes_pack)
{
this->attributes(attributes.second, attributes.first);
}
}
/* Construct a new model object by passing a list of names which will be used to initialize
* empty attributes objects with the given names */
Model::Model(const std::initializer_list<std::string>& names)
{
for (const std::string& name : names)
{
this->attributes(sb::Attributes(), name);
}
}
/* Get the entire map of attributes, each wrapped in its shared pointer held by this object.
* Can be used to iterate through the attributes. */
std::map<std::string, std::shared_ptr<sb::Attributes>>& Model::attributes()
{
return model_attributes;
}
/* Get the attributes under name, wrapped in the shared pointer held by this object. This
* function uses the at method of std::map, so name must refer to attributes already
* stored in this model. Use this function to share ownership of the attributes or to gain
* access to the public interface of the attributes. */
std::shared_ptr<sb::Attributes>& Model::attributes(const std::string& name)
{
return attributes().at(name);
}
/* Get the attributes under name, wrapped in the shared pointer held by this object. This
* function uses operator[] or std::map, so this can be used to add new attributes to the
* object if they are wrapped in a shared pointer. */
std::shared_ptr<sb::Attributes>& Model::operator[](const std::string& name)
{
auto element = attributes().find(name);
/* add an empty Attributes at name if it doesn't exist yet */
if (element == attributes().end())
{
attributes(sb::Attributes{}, name);
}
return attributes()[name];
}
/* Assign name to attributes, copy and wrap in a shared pointer. The model can share
* ownership of the created attribute memory with callers that request it. */
void Model::attributes(const sb::Attributes& attributes, const std::string& name)
{
this->attributes(std::make_shared<sb::Attributes>(attributes), name);
}
/* Assign name to attributes and share ownership. */
void Model::attributes(const std::shared_ptr<sb::Attributes>& attributes, const std::string& name)
{
this->attributes()[name] = attributes;
}
/* Enable all attributes. */
void Model::enable()
{
for (const auto& attributes : this->attributes())
{
attributes.second->enable();
}
}
/* Disable all attributes. */
void Model::disable()
{
for (const auto& attributes : this->attributes())
{
attributes.second->disable();
}
}
/* Return a reference to the texture container. */
std::map<std::string, sb::Texture>& Model::textures()
{
return model_textures;
}
/* Get the texture at name. This can be used to read the texture memory, share ownership of it, or
* anything else a Texture object can be used for with direct calls to GL functions. */
sb::Texture& Model::texture(const std::string& name)
{
return textures().at(name);
}
/* Get the default texture. The default texture must have previously been set with the default key as
* the name, which can be done using Model::texture(sb::Texture). */
sb::Texture& Model::texture()
{
return texture(DEFAULT_TEXTURE_NAME);
}
/* Assign name to texture and share ownership. */
void Model::texture(const sb::Texture& texture, const std::string& name)
{
textures()[name] = texture;
}
/* If no name is specified, use the default texture. This can be used to conveniently setup a model
* with only one texture. */
void Model::texture(const sb::Texture& texture)
{
this->texture(texture, DEFAULT_TEXTURE_NAME);
}
/* Get the model's transformation matrix. */
const glm::mat4& Model::transformation() const
{
return model_transformation;
}
/* Set the model's transformation matrix. */
void Model::transformation(const glm::mat4& transformation)
{
model_transformation = transformation;
}
/* Return the size in bytes of the sum of the attributes. */
std::size_t Model::size()
{
std::size_t sum = 0;
for (const auto& attributes : this->attributes())
{
sum += attributes.second->size();
}
return sum;
}
/* Return the transformation matrix. */
Model::operator glm::mat4() const
{
return model_transformation;
}
PlaneDoubleBuffer::PlaneDoubleBuffer() : Plane()
{
texture(sb::Texture(), "front");
texture(sb::Texture(), "back");
}
void PlaneDoubleBuffer::generate(const glm::vec2& size)
{
for (sb::Texture* buffer : {&texture("front"), &texture("back")})
{
buffer->generate(size);
}
}
sb::Texture& PlaneDoubleBuffer::active()
{
return swapped ? texture("back") : texture("front");
}
sb::Texture& PlaneDoubleBuffer::inactive()
{
return swapped ? texture("front") : texture("back");
}
void PlaneDoubleBuffer::swap()
{
swapped = !swapped;
}

View File

@ -1,105 +0,0 @@
/* _______________ ,----------------------------------------------------------------.
//`````````````\\ \ \
//~~~~~~~~~~~~~~~\\ \ by @ohsqueezy & @sleepin \
//=================\\ \ [ohsqueezy.itch.io] [sleepin.itch.io] \
// \\ \ \
// \\ \ code released under the zlib license [git.nugget.fun/pudding] \
// GUNKISS \\ \ \
//_________________________\\ `---------------------------------------------------------------*/
#ifndef MODEL_H_
#define MODEL_H_
/* GL functions */
#if defined(__ANDROID__) || defined(ANDROID)
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
#else
#include "glew/glew.h"
#endif
#include <iostream>
#include <string>
#include <map>
#include <memory>
#include <iterator>
#include "glm/glm.hpp"
#include "Attributes.hpp"
#include "Texture.hpp"
class Model
{
private:
inline static const std::string DEFAULT_TEXTURE_NAME = "default";
std::map<std::string, sb::Texture> model_textures;
std::map<std::string, std::shared_ptr<sb::Attributes>> model_attributes;
glm::mat4 model_transformation {1.0f};
public:
Model();
Model(const std::map<std::string, std::shared_ptr<sb::Attributes>>&);
Model(const std::map<std::string, sb::Attributes>&);
Model(const std::initializer_list<std::string>&);
std::map<std::string, std::shared_ptr<sb::Attributes>>& attributes();
std::shared_ptr<sb::Attributes>& attributes(const std::string&);
void attributes(const sb::Attributes&, const std::string&);
void attributes(const std::shared_ptr<sb::Attributes>&, const std::string&);
std::shared_ptr<sb::Attributes>& operator[](const std::string&);
void enable();
void disable();
std::map<std::string, sb::Texture>& textures();
sb::Texture& texture(const std::string&);
sb::Texture& texture();
void texture(const sb::Texture&, const std::string&);
void texture(const sb::Texture&);
const glm::mat4& transformation() const;
void transformation(const glm::mat4&);
std::size_t size();
operator glm::mat4() const;
};
class Plane : public Model
{
public:
inline const static std::shared_ptr<sb::Attributes> position = std::make_shared<sb::Attributes>(sb::Attributes{
{-1.0f, 1.0f}, {1.0f, 1.0f}, {-1.0f, -1.0f},
{1.0f, 1.0f}, {1.0f, -1.0f}, {-1.0f, -1.0f}
});
inline const static std::shared_ptr<sb::Attributes> uv = std::make_shared<sb::Attributes>(sb::Attributes{
{0.0f, 1.0f}, {1.0f, 1.0f}, {0.0f, 0.0f},
{1.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 0.0f}
});
Plane() : Model(std::map<std::string, std::shared_ptr<sb::Attributes>>({{"position", position}, {"uv", uv}})) {}
};
/*!
* A version of `Plane` which contains two texture objects, one of which is active at a time. A reference
* to the active `sb::Texture` object is available from `PlaneDoubleBuffer.active`, and the inactive object is
* available from `PlaneDoubleBuffer.inactive`. The buffers can be swapped using `PlaneDoubleBuffer.swap`.
*/
class PlaneDoubleBuffer : public Plane
{
private:
bool swapped = false;
public:
PlaneDoubleBuffer();
void generate(const glm::vec2&);
sb::Texture& active();
sb::Texture& inactive();
void swap();
};
#endif

View File

@ -9,7 +9,7 @@ Chunk::Chunk(const fs::path& path)
void Chunk::load(const fs::path& path)
{
chunk = std::shared_ptr<Mix_Chunk>(Mix_LoadWAV(path.c_str()), Mix_FreeChunk);
chunk = std::shared_ptr<Mix_Chunk>(Mix_LoadWAV(path.string().c_str()), Mix_FreeChunk);
if (chunk.get() == nullptr)
{
std::ostringstream message;
@ -25,13 +25,28 @@ std::uint8_t Chunk::convert_volume(float volume)
float Chunk::volume() const
{
std::uint8_t sdl_volume = Mix_VolumeChunk(chunk.get(), -1);
return static_cast<float>(sdl_volume) / static_cast<float>(MIX_MAX_VOLUME);
if (Mix_QuerySpec(nullptr, nullptr, nullptr) != 0)
{
std::uint8_t sdl_volume = Mix_VolumeChunk(chunk.get(), -1);
return static_cast<float>(sdl_volume) / static_cast<float>(MIX_MAX_VOLUME);
}
else
{
Log::log("Cannot check volume. Audio device is not open.", Log::WARN);
return 0.0f;
}
}
void Chunk::volume(float level)
{
Mix_VolumeChunk(chunk.get(), convert_volume(level));
if (Mix_QuerySpec(nullptr, nullptr, nullptr) != 0)
{
Mix_VolumeChunk(chunk.get(), convert_volume(level));
}
else
{
Log::log("Cannot set volume. Audio device is not open.", Log::WARN);
}
}
void Chunk::channel_volume(float volume)
@ -173,7 +188,7 @@ Music::Music(const fs::path& path)
void Music::load(const fs::path& path)
{
music = std::shared_ptr<Mix_Music>(Mix_LoadMUS(path.c_str()), Mix_FreeMusic);
music = std::shared_ptr<Mix_Music>(Mix_LoadMUS(path.string().c_str()), Mix_FreeMusic);
if (music.get() == nullptr)
{
Log::sdl_error();

View File

@ -14,6 +14,7 @@
#include <map>
#include <functional>
#include <algorithm>
#include <cmath>
#include "SDL.h"
#include "SDL_mixer.h"
#include "filesystem.hpp"

View File

@ -49,7 +49,8 @@ void Configuration::set_defaults()
{"render driver", "opengl"},
{"fluid resize", false},
{"default font path", "BPmono.ttf"},
{"default font size", 16}
{"default font size", 16},
{"use play button", false}
};
config["audio"] = {
{"default-sfx-root", "resource/sfx"},
@ -189,7 +190,7 @@ void Configuration::enable_auto_refresh(const fs::path& file_to_refresh)
{
std::ostringstream message;
message << "File to auto-refresh does not exist: " << file_to_refresh;
sb::Log::log(file_to_refresh, sb::Log::WARN);
sb::Log::log(message, sb::Log::WARN);
}
#endif
files_to_refresh.push_back(file_to_refresh);

View File

@ -249,11 +249,11 @@ namespace glm
}
/* Extend std::filesystem so nlohmann::json can read and write std::filesystem::path */
#if defined(__MINGW32__)
namespace std::experimental::filesystem
#else
// #if defined(__MINGW32__)
// namespace std::experimental::filesystem
// #else
namespace std::filesystem
#endif
// #endif
{
template <typename T>
void to_json(nlohmann::json& j, const path& p)

View File

@ -98,7 +98,7 @@ Game::Game()
sb::Log::log(log_message);
/* allows use of our own main function (?) see SDL_SetMainReady.html */
SDL_SetMainReady();
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
sb::Log::sdl_error("SDL could not initialize");
flag_to_end();
@ -125,9 +125,14 @@ Game::Game()
SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, configuration()["gl"]["share-with-current-context"]);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, configuration()["gl"]["double-buffer"]);
#if !defined(__MINGW32__)
/* Set the profile to ES so that desktop and web builds are both using the same profile. This should be handled by a configuration
* option in the fututre. */
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
#else
/* Unless on Windows, which may need to be run in compatibility mode */
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
#endif
/* Create a window with dimensions set in the config, centered, and flagged to be usable in OpenGL context */
_window = SDL_CreateWindow(
@ -176,30 +181,37 @@ Game::Game()
}
/* Try to load the default font path. The font will be freed when the Game object is destroyed. */
_font = font(configuration()("display", "default font path"), configuration()("display", "default font size"));
_font = font(configuration()("display", "default font path").get<std::string>(), configuration()("display", "default font size"));
/* Initialize SDL mixer with OGG support (in addition to WAV) */
if (Mix_Init(MIX_INIT_OGG) == 0)
{
sb::Log::sdl_error("Could not initialize SDL mixer");
// flag_to_end();
}
else
{
SDL_Log("initialized SDL mixer %d.%d.%d", SDL_MIXER_MAJOR_VERSION, SDL_MIXER_MINOR_VERSION, SDL_MIXER_PATCHLEVEL);
/* Log the available audio devices found on the system */
const int audio_device_count = SDL_GetNumAudioDevices(SDL_TRUE);
for (int ii = 0; ii < audio_device_count; ii++)
{
std::ostringstream message;
message << "Found audio capture device " << ii << ": " << SDL_GetAudioDeviceName(ii, SDL_TRUE);
sb::Log::log(message);
}
/* Open the audio device chosen automatically by SDL mixer */
if (Mix_OpenAudio(48000, MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, 4096) < 0)
{
sb::Log::sdl_error("Could not set up audio");
}
else
{
SDL_Log("Using audio driver: %s", SDL_GetCurrentAudioDriver());
}
}
if (Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, 1024) < 0)
// if (Mix_OpenAudio(11025, AUDIO_U8, MIX_DEFAULT_CHANNELS, 2048) < 0)
{
sb::Log::sdl_error("Could not set up audio");
}
SDL_Log("Using audio driver: %s", SDL_GetCurrentAudioDriver());
const int audio_device_count = SDL_GetNumAudioDevices(SDL_TRUE);
for (int ii = 0; ii < audio_device_count; ii++)
{
std::ostringstream message;
message << "Found audio capture device " << ii << ": " << SDL_GetAudioDeviceName(ii, SDL_TRUE);
sb::Log::log(message);
}
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
sb::Log::log("big endian");
#else
@ -306,7 +318,7 @@ void Game::sdl_log_override(void* userdata, int category, SDL_LogPriority priori
/* Handle writing to log file */
if (game->configuration()["log"]["enabled"])
{
fs::path path = game->configuration()["log"]["output-directory"];
fs::path path = game->configuration()("log", "output-directory").get<std::string>();
if (!fs::exists(path))
{
fs::create_directories(path);
@ -319,7 +331,7 @@ void Game::sdl_log_override(void* userdata, int category, SDL_LogPriority priori
/* If debug is enabled, append message to debug log file */
if (game->configuration()["log"]["debug-to-file"])
{
fs::path debug_path = path / game->configuration()["log"]["debug-file-name"];
fs::path debug_path = path / game->configuration()("log", "debug-file-name").get<std::string>();
std::ofstream debug_stream(debug_path, std::ios_base::app);
debug_stream << stamped_message.str() << std::endl;
}
@ -327,7 +339,7 @@ void Game::sdl_log_override(void* userdata, int category, SDL_LogPriority priori
/* Only append messages to the info log that are higher than debug priority */
if (priority > SDL_LOG_PRIORITY_DEBUG)
{
fs::path info_path = path / game->configuration()["log"]["info-file-name"];
fs::path info_path = path / game->configuration()("log", "info-file-name").get<std::string>();
std::ofstream info_stream(info_path, std::ios_base::app);
info_stream << stamped_message.str() << std::endl;
}
@ -543,13 +555,13 @@ std::shared_ptr<TTF_Font> sb::Game::font() const
std::shared_ptr<TTF_Font> sb::Game::font(const fs::path& path, int size) const
{
std::shared_ptr<TTF_Font> font = std::shared_ptr<TTF_Font>(TTF_OpenFont(path.c_str(), size), TTF_CloseFont);
std::shared_ptr<TTF_Font> font = std::shared_ptr<TTF_Font>(TTF_OpenFont(path.string().c_str(), size), TTF_CloseFont);
if (font.get() == nullptr)
{
std::ostringstream message;
message << "Could not load " << path;
sb::Log::log(message, sb::Log::ERROR);
if (path != configuration()("display", "default font path").get<fs::path>())
if (path != configuration()("display", "default font path").get<std::string>())
{
return this->font();
}

View File

@ -24,7 +24,6 @@
#include "SDL_ttf.h"
#define GL_GLEXT_PROTOTYPES
#define GLEW_STATIC
#if defined(__EMSCRIPTEN__)
#include <emscripten.h>
#include <emscripten/html5.h>

View File

@ -160,7 +160,7 @@ namespace sb
/*!
* Set the function that will run when a pad object is clicked.
*
* This example always keeps the state true and prints "Hello, World!" whenever the pad is clicked,
* This example always keeps the state false and prints "Hello, World!" whenever the pad is clicked,
*
* start_button.on_state_change([&](bool state, int count){
* if (state) {

View File

@ -7,7 +7,7 @@
Recorder::Recorder(Node* parent) : Node(parent)
{
get_delegate().subscribe(&Recorder::respond, this);
Mix_SetPostMix(Recorder::process_audio, this);
// Mix_SetPostMix(Recorder::process_audio, this);
}
/* Returns length of a recorded video frame in seconds */
@ -58,13 +58,13 @@ void Recorder::capture_screen()
{
const nlohmann::json& config = configuration()();
SDL_Surface* surface = get_display().screen_surface();
fs::path directory = config["recording"]["screenshot-directory"];
fs::path directory = config["recording"]["screenshot-directory"].get<std::string>();
fs::create_directories(directory);
std::string prefix = config["recording"]["screenshot-prefix"].get<std::string>();
std::string extension = config["recording"]["screenshot-extension"].get<std::string>();
int zfill = config["recording"]["screenshot-zfill"];
fs::path path = sb::get_next_file_name(directory, zfill, prefix, extension);
IMG_SavePNG(surface, path.c_str());
IMG_SavePNG(surface, path.string().c_str());
SDL_FreeSurface(surface);
std::ostringstream message;
message << "saved screenshot to " << path;
@ -86,7 +86,7 @@ void Recorder::grab_stash()
current_stash = Stash();
writing_recording = true;
std::function<void()> f = std::bind(&Recorder::write_most_recent_frames, this);
std::thread writing(f);
std::thread writing {f};
writing.detach();
}
else
@ -225,7 +225,7 @@ int Recorder::get_memory_size()
void Recorder::make_directory()
{
fs::path root = configuration()["recording"]["video-directory"];
fs::path root = configuration()["recording"]["video-directory"].get<std::string>();
fs::create_directories(root);
fs::path directory = sb::get_next_file_name(root, 5, "video-");
fs::create_directories(directory);
@ -234,7 +234,7 @@ void Recorder::make_directory()
void Recorder::write_stash_frames(Stash* stash)
{
SDL_Log("Writing stash offset %i to %s...", stash->frame_offset, current_video_directory.c_str());
SDL_Log("Writing stash offset %i to %s...", stash->frame_offset, current_video_directory.string().c_str());
SDL_Surface* frame;
GifWriter gif_writer;
int gif_frame_length = configuration()["recording"]["gif-frame-length"];

View File

@ -16,10 +16,10 @@
#include <vector>
#include <sstream>
#include <string>
#include <thread>
#include <functional>
#include <cstdlib>
#include <fstream>
#include <thread>
#include "SDL.h"
#include "SDL_mixer.h"
#include "glm/ext.hpp"

View File

@ -89,7 +89,7 @@ void Texture::load(fs::path path)
{
/* Load file path as a surface object to access pixel data and flip into OpenGL orientation. Attach a destructor so it will free
* itself when it goes out of scope at the end of this function. */
std::unique_ptr<SDL_Surface, decltype(&SDL_FreeSurface)> surface(IMG_Load(path.c_str()), SDL_FreeSurface);
std::unique_ptr<SDL_Surface, decltype(&SDL_FreeSurface)> surface(IMG_Load(path.string().c_str()), SDL_FreeSurface);
if (surface.get() != nullptr)
{
std::unique_ptr<SDL_Surface, decltype(&SDL_FreeSurface)> flipped_surface(rotozoomSurfaceXY(surface.get(), 0, 1, -1, 0), SDL_FreeSurface);

View File

@ -645,7 +645,7 @@ fs::path sb::copy_file(fs::path from, fs::path to, bool overwrite_ok)
/* Open source */
SDL_RWops* source_rw;
fs::path destination;
if ((source_rw = SDL_RWFromFile(from.c_str(), "r")) != nullptr)
if ((source_rw = SDL_RWFromFile(from.string().c_str(), "r")) != nullptr)
{
std::ostringstream message;
message << "Copying " << (SDL_RWsize(source_rw) / 1000) << " KB from " << from << " to " << to;
@ -670,7 +670,7 @@ fs::path sb::copy_file(fs::path from, fs::path to, bool overwrite_ok)
{
/* Open destination, write entire contents in one call and ensure the entire size in bytes was written. */
SDL_RWops* to_rw;
if ((to_rw = SDL_RWFromFile(to.c_str(), "w")) != nullptr)
if ((to_rw = SDL_RWFromFile(to.string().c_str(), "w")) != nullptr)
{
if ((SDL_RWwrite(to_rw, content.data(), 1, content.size())) == content.size())
{

View File

@ -1,10 +1,10 @@
#pragma once
/* MinGW filesystem library is in another location */
#if defined(__MINGW32__)
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#else
// #if defined(__MINGW32__)
// #include <experimental/filesystem>
// namespace fs = std::experimental::filesystem;
// #else
#include <filesystem>
namespace fs = std::filesystem;
#endif
// #endif