#ifndef __OPENGLPLAYGROUND_COMMON_HH__ #define __OPENGLPLAYGROUND_COMMON_HH__ #include #include #include #include #include #include #include #include using namespace gl; using namespace std::string_literals; class Exception { public: Exception() : msg_() { } Exception(std::string msg) : msg_(msg) { } virtual ~Exception() {} virtual std::string toString() const { return "Exception: "s + msg_; } protected: std::string msg_; }; class POSIXException : public Exception { public: POSIXException(int err): Exception(), err_(err) { } int getErr() const {return err_;} std::string toString() const override { return "POSIXException: "s + std::strerror(err_); } private: int err_; }; class GLException : public Exception { public: GLException(GLenum err) : Exception(), err_(err) { } GLenum getErr() const {return err_;} std::string errToString() const { std::string ret; if (err_ == GL_INVALID_ENUM) ret += "GL_INVALID_ENUM "; if (err_ == GL_INVALID_VALUE) ret += "GL_INVALID_VALUE "; if (err_ == GL_INVALID_OPERATION) ret += "GL_INVALID_OPERATION "; if (err_ == GL_INVALID_FRAMEBUFFER_OPERATION) ret += "GL_INVALID_FRAMEBUFFER_OPERATION "; if (err_ == GL_OUT_OF_MEMORY) ret += "GL_OUT_OF_MEMORY "; if (err_ == GL_STACK_UNDERFLOW) ret += "GL_STACK_UNDERFLOW "; if (err_ == GL_STACK_OVERFLOW) ret += "GL_STACK_OVERFLOW "; return ret; } std::string toString() const override { return "GLException: "s + errToString() + "(" + std::to_string(static_cast(err_)) + ")"; } private: GLenum err_; }; class SDLException : public Exception { public: SDLException() : Exception(SDL_GetError()) { } std::string toString() const override { return "SDLException: "s + msg_; } }; class TTFException : public Exception { public: TTFException() : Exception(TTF_GetError()) { } std::string toString() const override { return "TTFException: "s + msg_; } }; static void checkGlError() { GLenum err; if ((err = glGetError()) != GL_NO_ERROR) throw GLException(err); } static std::string fileToString(std::string const& name) { std::FILE *file = std::fopen(name.c_str(), "r"); if (!file) { throw POSIXException(errno); } std::string ret; char buf[512]; std::size_t p; while((p = std::fread(buf, 1, 511, file)) > 0) { buf[p] = '\0'; ret.append(buf); } if (!std::feof(file)) { std::fclose(file); throw POSIXException(errno); } std::fclose(file); return ret; } enum class VAFormats { Vertex, VertexTexcoord, VertexNormal, VertexNormalTexcoord }; // Some helpers to C++11-ify SDL struct SDLSurfaceDeleter { void operator()(SDL_Surface* ptr) const { SDL_FreeSurface(ptr); } }; using SDLSurfaceUPtr = std::unique_ptr; struct TTFFontDeleter { void operator()(TTF_Font* font) const { TTF_CloseFont(font); } }; using TTFFontUPtr = std::unique_ptr; class SDLSurfaceScopedLock { public: SDLSurfaceScopedLock(SDL_Surface *surf) : surf_(surf) { if (SDL_MUSTLOCK(surf_)) if (SDL_LockSurface(surf_) != 0) throw SDLException{}; } SDLSurfaceScopedLock(SDLSurfaceUPtr& surf) : surf_(surf.get()) { if (SDL_MUSTLOCK(surf_)) if (SDL_LockSurface(surf_) != 0) throw SDLException{}; } SDLSurfaceScopedLock(SDLSurfaceScopedLock const& copy) = delete; SDLSurfaceScopedLock& operator=(SDLSurfaceScopedLock const& copy) = delete; ~SDLSurfaceScopedLock() { if (surf_ && SDL_MUSTLOCK(surf_)) SDL_UnlockSurface(surf_); } void unlock() { if (surf_ && SDL_MUSTLOCK(surf_)) SDL_UnlockSurface(surf_); surf_ = nullptr; } private: SDL_Surface *surf_; }; static bool operator==(SDL_Color const& a, SDL_Color const& b) { return ((a.r == b.r) && (a.g == b.g) && (a.b == b.b) && (a.a == b.a)); } static bool operator!=(SDL_Color const& a, SDL_Color const& b) { return ((a.r != b.r) || (a.g != b.g) || (a.b != b.b) || (a.a != b.a)); } // Compatibility with C++11 where make_unique was not in std:: yet using std::make_unique; #endif