Open source Star Ruler 2 source code!

This commit is contained in:
Lucas de Vries
2018-07-17 14:15:37 +02:00
commit cc307720ff
4342 changed files with 2365070 additions and 0 deletions
+569
View File
@@ -0,0 +1,569 @@
#include "os/glfw_driver.h"
#include "compat/misc.h"
#include "compat/gl.h"
#include "main/game_platform.h"
#include "main/references.h"
#include "main/logging.h"
#include "threads.h"
#include "vec2.h"
#include <list>
#include <math.h>
#include <set>
#include <algorithm>
#ifndef WIN_MODE
#include <sys/time.h>
#include <random>
#else
//Undef duplicate macros from glfw
#undef APIENTRY
#undef WINGDIAPI
#include <Windows.h>
#include <WinCrypt.h>
#include "os/resource.h"
#endif
//We use std::max instead
#undef max
extern bool game_running;
namespace os {
void redirectWindowClose(GLFWwindow*);
void redirectWindowResize(GLFWwindow*,int, int);
void redirectSpecialKey(GLFWwindow*,int key, int scan, int action, int mods);
void redirectCharKey(GLFWwindow*,unsigned);
void redirectMouseButton(GLFWwindow*,int button, int action, int mods);
void redirectMouseMove(GLFWwindow*,double x, double y);
void redirectMouseWheel(GLFWwindow*,double x, double y);
void trackMouseOver(GLFWwindow*,int over);
void glfwError(int, const char*);
class GLFWDriver;
GLFWDriver* driver = 0;
class GLFWDriver : public OSDriver {
union Callback {
std::function<bool(void)>* f_v;
std::function<bool(int)>* f_i;
std::function<bool(int,int)>* f_ii;
Callback(decltype(f_v) p_f_v) : f_v(p_f_v) {}
Callback(decltype(f_i) p_f_i) : f_i(p_f_i) {}
Callback(decltype(f_ii) p_f_ii) : f_ii(p_f_ii) {}
};
std::list<Callback> callbacks[OSC_COUNT];
GLFWwindow* window;
public:
#ifndef WIN_MODE
timeval start_time;
#else
ULARGE_INTEGER start_time;
LARGE_INTEGER start_time_hq, start_time_hq_freq;
#endif
bool mouseOver;
bool canLock, shouldLock;
double frameTime, gameTime, gameSpeed;
GLFWDriver() : window(0), mouseOver(true), canLock(false), shouldLock(false) {
glfwSetErrorCallback(glfwError);
glfwInit();
resetTimer();
}
~GLFWDriver() {
driver = 0;
glfwTerminate();
}
bool systemRandom(unsigned char* buffer, unsigned bytes) {
#ifdef WIN_MODE
HCRYPTPROV provider;
//Attempt to acquire the context if it exists, then make it if it does not
BOOL ctx = CryptAcquireContext(&provider, "SR2SysRand", NULL, PROV_RSA_AES, NULL);
if(!ctx)
ctx = CryptAcquireContext(&provider, "SR2SysRand", NULL, PROV_RSA_AES, CRYPT_NEWKEYSET);
if(ctx) {
BOOL success = CryptGenRandom(provider, bytes, buffer);
CryptReleaseContext(provider, NULL);
return success != 0;
}
return false;
#else
std::random_device rd;
for(unsigned i = 0; i < bytes; ++i)
buffer[i] = (unsigned char)rd();
return true;
#endif
}
void setVerticalSync(int waitFrames) {
glfwSwapInterval(waitFrames);
}
void swapBuffers(double minWait_s) {
glfwSwapBuffers(window);
glfwPollEvents();
if(devices.cloud)
devices.cloud->update();
double waitTill = frameTime + minWait_s;
double curTime = getAccurateTime();
while(curTime < waitTill) {
glfwPollEvents();
if(devices.cloud)
devices.cloud->update();
threads::sleep(0);
curTime = getAccurateTime();
}
if(gameSpeed > 0 && game_running) {
double delta = curTime - frameTime;
if(delta > 0.5)
delta = 0.5;
gameTime += delta * gameSpeed;
}
frameTime = curTime;
}
void handleEvents(unsigned minWait_ms) {
glfwPollEvents();
frameTime = getAccurateTime();
threads::sleep(minWait_ms);
}
void getDesktopSize(unsigned& width, unsigned& height) {
auto* primary = glfwGetPrimaryMonitor();
if(primary == nullptr) {
width = 1280;
height = 720;
return;
}
auto& desktop = *glfwGetVideoMode(primary);
width = desktop.width;
height = desktop.height;
}
void createWindow(WindowData& data) {
glfwWindowHint(GLFW_SAMPLES, data.aa_samples);
glfwWindowHint(GLFW_REFRESH_RATE, data.refreshRate);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
GLFWmonitor* monitor = nullptr;
if(data.mode == WM_Fullscreen) {
monitor = glfwGetPrimaryMonitor();
if(!data.targetMonitor.empty()) {
int count = 0;
GLFWmonitor** monitors = glfwGetMonitors(&count);
for(int i = 0; i < count; ++i) {
if(data.targetMonitor == glfwGetMonitorName(monitors[i])) {
monitor = monitors[i];
break;
}
}
}
if(monitor && !data.overrideMonitor) {
int count = 0;
const GLFWvidmode* modes = glfwGetVideoModes(monitor, &count);
bool match = false;
for(int i = 0; i < count; ++i) {
auto& mode = modes[i];
if(mode.width == data.width && mode.height == data.height && (data.refreshRate == 0 || data.refreshRate == mode.refreshRate)) {
match = true;
break;
}
}
if(!match) {
monitor = nullptr;
data.mode = WM_Window;
}
}
}
if(data.mode != WM_Fullscreen && (data.width == 0 || data.height == 0)) {
GLFWmonitor* primary = glfwGetPrimaryMonitor();
const GLFWvidmode* mode = glfwGetVideoMode(primary);
data.width = mode->width;
data.height = mode->height;
}
window = glfwCreateWindow(data.width, data.height, "Star Ruler 2", monitor, nullptr);
if(window == 0)
window = glfwCreateWindow(1024,768, "Star Ruler 2 - Error Creating Window", nullptr, nullptr);
if(window == 0) {
error("Could not create window.");
return;
}
glfwMakeContextCurrent(window);
glfwGetWindowSize(window, &win_width, &win_height);
glfwSwapInterval( data.verticalSync );
if(data.mode == WM_Fullscreen)
setCursorVisible(true);
glfwSetWindowCloseCallback(window, redirectWindowClose);
glfwSetWindowSizeCallback(window, redirectWindowResize);
glfwSetKeyCallback(window, redirectSpecialKey);
glfwSetCharCallback(window, redirectCharKey);
glfwSetMouseButtonCallback(window, redirectMouseButton);
glfwSetScrollCallback(window, redirectMouseWheel);
glfwSetCursorPosCallback(window, redirectMouseMove);
glfwSetCursorEnterCallback(window, trackMouseOver);
#ifdef WIN_MODE
HICON hSmallIcon = (HICON) LoadImage ( 0, "sr2.ico", IMAGE_ICON, 32, 32, LR_LOADFROMFILE | LR_DEFAULTCOLOR );
SendMessage ( GetActiveWindow(), WM_SETICON, ICON_SMALL, (long)hSmallIcon );
#endif
}
void getVideoModes(std::vector<OSDriver::VideoMode>& output) {
int count = 0;
const GLFWvidmode* modes;
auto* primary = glfwGetPrimaryMonitor();
if(primary)
modes = glfwGetVideoModes(primary, &count);
output.reserve(count);
output.resize(0);
std::set<uint64_t> sizes;
for(int i = 0; i < count; ++i) {
VideoMode m;
auto& mode = modes[i];
m.width = mode.width;
m.height = mode.height;
m.refresh = mode.refreshRate;
uint64_t size = (uint64_t)m.width << 16 | (uint64_t)m.height | ((uint64_t)mode.refreshRate << 32);
if(sizes.find(size) == sizes.end()) {
sizes.insert(size);
output.push_back(m);
}
}
}
void getMonitorNames(std::vector<std::string>& output) {
int count = 0;
GLFWmonitor** monitors = glfwGetMonitors(&count);
output.resize(count);
for(int i = 0; i < count; ++i)
output[i] = glfwGetMonitorName(monitors[i]);
}
bool isWindowFocused() override {
return glfwGetWindowAttrib(window, GLFW_FOCUSED) != 0;
}
bool isWindowMinimized() override {
return glfwGetWindowAttrib(window, GLFW_ICONIFIED) != 0;
}
void flashWindow() override {
glfwFlashWindow(window);
}
bool isMouseOver() {
return mouseOver;
}
void setClipboard(const std::string& text) {
glfwSetClipboardString(window, text.c_str());
}
std::string getClipboard() {
const char* str = glfwGetClipboardString(window);
if(str)
return std::string(str);
return std::string();
}
int getCharForKey(int key) {
return glfwGetCharForKey(key);
}
int getKeyForChar(unsigned char chr) {
return glfwGetKeyForChar(chr);
}
unsigned getDoubleClickTime() const {
#ifdef _MSC_VER
return GetDoubleClickTime();
#else
//TODO: Get user's setting on linux
return 200;
#endif
}
void getLastMousePos(int& x, int& y) {
x = mouse_x;
y = mouse_y;
}
void getMousePos(int& x, int& y) {
double dx, dy;
glfwGetCursorPos(window, &dx,&dy);
x = (int)floor(dx);
y = (int)floor(dy);
}
void setMousePos(int x, int y) {
glfwSetCursorPos(window, x,y);
}
void setCursorVisible(bool visible) {
glfwSetInputMode(window, GLFW_CURSOR, visible ? GLFW_CURSOR_NORMAL : GLFW_CURSOR_HIDDEN);
}
void setCursorLocked(bool locked) {
if(canLock == locked)
return;
canLock = locked;
if(shouldLock) {
if(locked)
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_CAPTURED);
else
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_FREE);
}
}
void setCursorShouldLock(bool locked) {
if(shouldLock == locked)
return;
shouldLock = locked;
if(canLock) {
if(locked)
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_CAPTURED);
else
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_FREE);
}
}
void sleep(int milliseconds) {
threads::sleep(milliseconds);
}
void resetTimer() {
#ifndef WIN_MODE
gettimeofday(&start_time, 0);
#else
FILETIME cur_time;
GetSystemTimeAsFileTime(&cur_time);
start_time.HighPart = cur_time.dwHighDateTime;
start_time.LowPart = cur_time.dwLowDateTime;
QueryPerformanceFrequency(&start_time_hq_freq);
QueryPerformanceCounter(&start_time_hq);
#endif
frameTime = 0.0;
resetGameTime(0);
}
int getTime() const {
#ifndef WIN_MODE
timeval cur_time;
gettimeofday(&cur_time, 0);
return (int)(
1000 * (cur_time.tv_sec - start_time.tv_sec)
+ (cur_time.tv_usec - start_time.tv_usec) / 1000);
#else
FILETIME cur_ftime;
GetSystemTimeAsFileTime(&cur_ftime);
ULARGE_INTEGER cur_time;
cur_time.HighPart = cur_ftime.dwHighDateTime;
cur_time.LowPart = cur_ftime.dwLowDateTime;
const double ticksPerSecond = 10000000.0;
auto timeInSeconds = (double)(cur_time.QuadPart - start_time.QuadPart) / ticksPerSecond;
return int(timeInSeconds * 1000.0);
#endif
}
double getAccurateTime() const {
#ifndef WIN_MODE
timeval cur_time;
gettimeofday(&cur_time, 0);
return (double)(cur_time.tv_sec - start_time.tv_sec)
+ (double)(cur_time.tv_usec - start_time.tv_usec)/1000000.0;
#else
LARGE_INTEGER cur_time, cur_freq;
QueryPerformanceCounter(&cur_time);
QueryPerformanceFrequency(&cur_freq);
return (double)cur_time.QuadPart / (double)cur_freq.QuadPart - (double)start_time_hq.QuadPart / (double)start_time_hq_freq.QuadPart;
#endif
}
void resetGameTime(double time) {
//Game time starts slightly ahead of render time
gameTime = time;
gameSpeed = 1;
}
double getGameTime() const {
return gameTime;
}
double getFrameTime() const {
return frameTime;
}
double getGameSpeed() const {
return gameSpeed;
}
void setGameSpeed(double speed) {
gameSpeed = speed;
}
unsigned getProcessorCount() {
return std::max(threads::getNumberOfProcessors(),1u);
}
void setWindowTitle(const char* str) {
glfwSetWindowTitle(window, str);
}
void setWindowSize(int width, int height){
glfwSetWindowSize(window, width, height);
}
void closeWindow() {
glfwDestroyWindow(window);
}
};
void redirectWindowClose(GLFWwindow*) {
driver->onWindowClose();
}
void redirectWindowResize(GLFWwindow*, int w, int h) {
driver->onResize(w,h);
driver->win_width = w;
driver->win_height = h;
glViewport(0, 0, w, h);
}
void redirectSpecialKey(GLFWwindow*, int key, int scan, int action, int mods) {
driver->shiftKey = (mods & GLFW_MOD_SHIFT) != 0;
driver->ctrlKey = (mods & GLFW_MOD_CONTROL) != 0;
driver->altKey = (mods & GLFW_MOD_ALT) != 0;
bool pressed;
int keyaction;
switch(action) {
case GLFW_PRESS:
pressed = true;
keyaction = KA_Pressed;
break;
case GLFW_RELEASE:
pressed = false;
keyaction = KA_Released;
break;
case GLFW_REPEAT:
pressed = true;
keyaction = KA_Repeated;
break;
default:
return;
}
switch(key) {
case GLFW_KEY_LEFT_SHIFT:
case GLFW_KEY_RIGHT_SHIFT:
driver->shiftKey = pressed;
break;
case GLFW_KEY_LEFT_CONTROL:
case GLFW_KEY_RIGHT_CONTROL:
driver->ctrlKey = pressed;
break;
case GLFW_KEY_LEFT_ALT:
case GLFW_KEY_RIGHT_ALT:
driver->altKey = pressed;
break;
}
driver->onKeyEvent(key, keyaction);
}
void redirectCharKey(GLFWwindow*, unsigned key) {
driver->onCharTyped(key);
}
void redirectMouseButton(GLFWwindow*, int button, int action, int mods) {
bool pressed = action == GLFW_PRESS;
driver->shiftKey = (mods & GLFW_MOD_SHIFT) != 0;
driver->ctrlKey = (mods & GLFW_MOD_CONTROL) != 0;
driver->altKey = (mods & GLFW_MOD_ALT) != 0;
switch(button) {
case GLFW_MOUSE_BUTTON_LEFT:
driver->leftButton = pressed;
break;
case GLFW_MOUSE_BUTTON_RIGHT:
driver->rightButton = pressed;
break;
case GLFW_MOUSE_BUTTON_MIDDLE:
driver->middleButton = pressed;
break;
}
driver->onMouseButton(button, pressed);
}
void redirectMouseMove(GLFWwindow*, double x, double y) {
driver->onMouseMoved((int)x, (int)y);
driver->mouse_x = (int)x;
driver->mouse_y = (int)y;
}
void redirectMouseWheel(GLFWwindow*, double x, double y) {
driver->onScroll(x, y);
}
void trackMouseOver(GLFWwindow*,int over) {
driver->mouseOver = over == GL_TRUE;
}
void glfwError(int code, const char* msg) {
error("GLFW Error %d: %s", code, msg);
}
OSDriver* getGLFWDriver() {
if(!driver)
driver = new GLFWDriver();
return driver;
}
};