diff --git a/olcPixelGameEngine.h b/olcPixelGameEngine.h index 48a9be5..a180715 100644 --- a/olcPixelGameEngine.h +++ b/olcPixelGameEngine.h @@ -1,9 +1,9 @@ -#pragma region license_and_help +#pragma region license_and_help /* olcPixelGameEngine.h +-------------------------------------------------------------+ - | OneLoneCoder Pixel Game Engine v2.16 | + | OneLoneCoder Pixel Game Engine v2.15 | | "What do you need? Pixels... Lots of Pixels..." - javidx9 | +-------------------------------------------------------------+ @@ -111,8 +111,7 @@ about Mac, so if you need support, I suggest checking out the instructions here: https://github.com/MumflrFumperdink/olcPGEMac - clang++ -arch x86_64 -std=c++17 -mmacosx-version-min=10.15 -Wall -framework OpenGL - -framework GLUT -framework Carbon -lpng YourSource.cpp -o YourProgName + clang++ -arch x86_64 -std=c++17 -mmacosx-version-min=10.15 -Wall -framework OpenGL -framework GLUT -lpng YourSource.cpp -o YourProgName @@ -120,7 +119,7 @@ ~~~~~~~~~~~~~~~~~~~~~~~~~ Emscripten compiler will turn your awesome C++ PixelGameEngine project into WASM! This means you can run your application in teh browser, great for distributing - and submission in to jams and things! It's a bit new at the moment. + and submission in to jams and things! It's a bit new at the moment. em++ -std=c++17 -O2 -s ALLOW_MEMORY_GROWTH=1 -s MAX_WEBGL_VERSION=2 -s MIN_WEBGL_VERSION=2 -s USE_LIBPNG=1 ./YourSource.cpp -o pge.html @@ -150,9 +149,9 @@ #define OLC_PGE_APPLICATION #include "olcPixelGameEngine.h" - That's all it should include. You can also include PGEX includes and - defines in here too. With this in place, you dont need to - #define OLC_PGE_APPLICATION anywhere, and can simply include this + That's all it should include. You can also include PGEX includes and + defines in here too. With this in place, you dont need to + #define OLC_PGE_APPLICATION anywhere, and can simply include this header file as an when you need to. @@ -169,8 +168,8 @@ Thanks ~~~~~~ I'd like to extend thanks to Ian McKay, Bispoo, Eremiell, slavka, gurkanctn, Phantim, - IProgramInCPP, JackOJC, KrossX, Huhlig, Dragoneye, Appa, JustinRichardsMusic, SliceNDice, - dandistine, Ralakus, Gorbit99, raoul, joshinils, benedani, Moros1138, Alexio, SaladinAkara + IProgramInCPP, JackOJC, KrossX, Huhlig, Dragoneye, Appa, JustinRichardsMusic, SliceNDice, + dandistine, Ralakus, Gorbit99, raoul, joshinils, benedani, Moros1138, Alexio, SaladinAkara & MagetzUb for advice, ideas and testing, and I'd like to extend my appreciation to the 230K YouTube followers, 80+ Patreons and 10K Discord server members who give me the motivation to keep going with all this :D @@ -180,10 +179,10 @@ Special thanks to those who bring gifts! GnarGnarHead.......Domina - Gorbit99...........Bastion, Ori & The Blind Forest, Terraria, Spelunky 2, Skully + Gorbit99...........Bastion, Ori & The Blind Forest, Terraria, Spelunky 2 Marti Morta........Gris Danicron...........Terraria - SaladinAkara.......Aseprite, Inside, Quern: Undying Thoughts, Outer Wilds + SaladinAkara.......Aseprite, Inside AlterEgo...........Final Fantasy XII - The Zodiac Age SlicEnDicE.........Noita, Inside @@ -194,7 +193,7 @@ Author ~~~~~~ - David Barr, aka javidx9, ©OneLoneCoder 2018, 2019, 2020, 2021 + David Barr, aka javidx9, �OneLoneCoder 2018, 2019, 2020, 2021 */ #pragma endregion @@ -255,12 +254,12 @@ +Wireframe Decal Mode - For debug overlays 2.11: Made PGEX hooks optional - (provide true to super constructor) 2.12: Fix for MinGW compiler non-compliance :( - why is its sdk structure different?? why??? - 2.13: +GetFontSprite() - allows access to font data + 2.13: +GetFontSprite() - allows access to font data 2.14: Fix WIN32 Definition reshuffle Fix DrawPartialDecal() - messed up dimension during renderer experiment, didnt remove junk code, thanks Alexio Fix? Strange error regarding GDI+ Image Loader not knowing about COM, SDK change? 2.15: Big Reformat - +WASM Platform (via Emscripten) - Big Thanks to OLC Community - See Platform for details + +WASM Platform (via Emscripten) - Big Thanks to OLC Community - See Platform for details +Sample Mode for Decals +Made olc_ConfigureSystem() accessible +Added OLC_----_CUSTOM_EX for externalised platforms, renderers and image loaders @@ -268,19 +267,9 @@ -Deprecating LoadFromPGESprFile() -Deprecating SaveToPGESprFile() Fix Pixel -= operator (thanks Au Lit) - 2.16: FIX Emscripten JS formatting in VS IDE (thanks Moros) - +"Headless" Mode - +DrawLineDecal() - +Mouse Button Constants - +Move Constructor for olc::Renderable - +Polar/Cartesian conversion for v2d_generic - +DrawRotatedStringDecal()/DrawRotatedStringPropDecal() (thanks Oso-Grande/Sopadeoso (PR #209)) - =Using olc::Renderable for layer surface - +Major Mac and GLUT Update (thanks Mumflr) - - - - !! Apple Platforms will not see these updates immediately - Sorry, I dont have a mac to test... !! + + + !! Apple Platforms will not see these updates immediately - Sorry, I dont have a mac to test... !! !! Volunteers willing to help appreciated, though PRs are manually integrated with credit !! */ #pragma endregion @@ -358,7 +347,7 @@ int main() #include #pragma endregion -#define PGE_VER 216 +#define PGE_VER 215 // O------------------------------------------------------------------------------O // | COMPILER CONFIGURATION ODDITIES | @@ -366,32 +355,32 @@ int main() #pragma region compiler_config #define USE_EXPERIMENTAL_FS #if defined(_WIN32) - #if _MSC_VER >= 1920 && _MSVC_LANG >= 201703L - #undef USE_EXPERIMENTAL_FS - #endif +#if _MSC_VER >= 1920 && _MSVC_LANG >= 201703L +#undef USE_EXPERIMENTAL_FS +#endif #endif #if defined(__linux__) || defined(__MINGW32__) || defined(__EMSCRIPTEN__) || defined(__FreeBSD__) || defined(__APPLE__) - #if __cplusplus >= 201703L - #undef USE_EXPERIMENTAL_FS - #endif +#if __cplusplus >= 201703L +#undef USE_EXPERIMENTAL_FS +#endif #endif #if defined(USE_EXPERIMENTAL_FS) || defined(FORCE_EXPERIMENTAL_FS) // C++14 - #define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING - #include - namespace _gfs = std::experimental::filesystem::v1; +#define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING +#include +namespace _gfs = std::experimental::filesystem::v1; #else // C++17 - #include - namespace _gfs = std::filesystem; +#include +namespace _gfs = std::filesystem; #endif #if defined(UNICODE) || defined(_UNICODE) - #define olcT(s) L##s +#define olcT(s) L##s #else - #define olcT(s) s +#define olcT(s) s #endif #define UNUSED(x) (void)(x) @@ -402,96 +391,92 @@ int main() // Platform #if !defined(OLC_PLATFORM_WINAPI) && !defined(OLC_PLATFORM_X11) && !defined(OLC_PLATFORM_GLUT) && !defined(OLC_PLATFORM_EMSCRIPTEN) - #if !defined(OLC_PLATFORM_CUSTOM_EX) - #if defined(_WIN32) - #define OLC_PLATFORM_WINAPI - #endif - #if defined(__linux__) || defined(__FreeBSD__) - #define OLC_PLATFORM_X11 - #endif - #if defined(__APPLE__) - #define GL_SILENCE_DEPRECATION - #define OLC_PLATFORM_GLUT - #endif - #if defined(__EMSCRIPTEN__) - #define OLC_PLATFORM_EMSCRIPTEN - #endif - #endif +#if !defined(OLC_PLATFORM_CUSTOM_EX) +#if defined(_WIN32) +#define OLC_PLATFORM_WINAPI +#endif +#if defined(__linux__) || defined(__FreeBSD__) +#define OLC_PLATFORM_X11 +#endif +#if defined(__APPLE__) +#define GL_SILENCE_DEPRECATION +#define OLC_PLATFORM_GLUT +#endif +#if defined(__EMSCRIPTEN__) +#define OLC_PLATFORM_EMSCRIPTEN +#endif +#endif #endif // Start Situation #if defined(OLC_PLATFORM_GLUT) || defined(OLC_PLATFORM_EMSCRIPTEN) - #define PGE_USE_CUSTOM_START +#define PGE_USE_CUSTOM_START #endif // Renderer #if !defined(OLC_GFX_OPENGL10) && !defined(OLC_GFX_OPENGL33) && !defined(OLC_GFX_DIRECTX10) - #if !defined(OLC_GFX_CUSTOM_EX) - #if defined(OLC_PLATFORM_EMSCRIPTEN) - #define OLC_GFX_OPENGL33 - #else - #define OLC_GFX_OPENGL10 - #endif - #endif +#if !defined(OLC_GFX_CUSTOM_EX) +#if defined(OLC_PLATFORM_EMSCRIPTEN) +#define OLC_GFX_OPENGL33 +#else +#define OLC_GFX_OPENGL10 +#endif +#endif #endif // Image loader #if !defined(OLC_IMAGE_STB) && !defined(OLC_IMAGE_GDI) && !defined(OLC_IMAGE_LIBPNG) - #if !defined(OLC_IMAGE_CUSTOM_EX) - #if defined(_WIN32) - #define OLC_IMAGE_GDI - #endif - #if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__EMSCRIPTEN__) - #define OLC_IMAGE_LIBPNG - #endif - #endif +#if !defined(OLC_IMAGE_CUSTOM_EX) +#if defined(_WIN32) +#define OLC_IMAGE_GDI +#endif +#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__EMSCRIPTEN__) +#define OLC_IMAGE_LIBPNG +#endif +#endif #endif // O------------------------------------------------------------------------------O // | PLATFORM-SPECIFIC DEPENDENCIES | // O------------------------------------------------------------------------------O -#if !defined(OLC_PGE_HEADLESS) #if defined(OLC_PLATFORM_WINAPI) - #define _WINSOCKAPI_ // Thanks Cornchipss - #if !defined(VC_EXTRALEAN) - #define VC_EXTRALEAN - #endif - #if !defined(NOMINMAX) - #define NOMINMAX - #endif - - // In Code::Blocks - #if !defined(_WIN32_WINNT) - #ifdef HAVE_MSMF - #define _WIN32_WINNT 0x0600 // Windows Vista - #else - #define _WIN32_WINNT 0x0500 // Windows 2000 - #endif - #endif - - #include - #undef _WINSOCKAPI_ +#define _WINSOCKAPI_ // Thanks Cornchipss +#if !defined(VC_EXTRALEAN) +#define VC_EXTRALEAN +#endif +#if !defined(NOMINMAX) +#define NOMINMAX +#endif + +// In Code::Blocks +#if !defined(_WIN32_WINNT) +#ifdef HAVE_MSMF +#define _WIN32_WINNT 0x0600 // Windows Vista +#else +#define _WIN32_WINNT 0x0500 // Windows 2000 +#endif +#endif + +#include +#undef _WINSOCKAPI_ #endif #if defined(OLC_PLATFORM_X11) - namespace X11 - { - #include - #include - } +namespace X11 +{ +#include +#include +} #endif #if defined(OLC_PLATFORM_GLUT) - #if defined(__linux__) - #include - #include - #endif - #if defined(__APPLE__) - #include - #include - #include - #endif +#if defined(__linux__) +#include +#include +#endif +#if defined(__APPLE__) +#include #endif #endif #pragma endregion @@ -576,13 +561,6 @@ namespace olc CAPS_LOCK, ENUM_END }; - namespace Mouse - { - static constexpr int32_t LEFT = 0; - static constexpr int32_t RIGHT = 1; - static constexpr int32_t MIDDLE = 2; - }; - // O------------------------------------------------------------------------------O // | olc::HWButton - Represents the state of a hardware button (mouse/key/joy) | // O------------------------------------------------------------------------------O @@ -617,8 +595,6 @@ namespace olc v2d_generic ceil() const { return v2d_generic(std::ceil(x), std::ceil(y)); } v2d_generic max(const v2d_generic& v) const { return v2d_generic(std::max(x, v.x), std::max(y, v.y)); } v2d_generic min(const v2d_generic& v) const { return v2d_generic(std::min(x, v.x), std::min(y, v.y)); } - v2d_generic cart() { return { std::cos(y) * x, std::sin(y) * x }; } - v2d_generic polar() { return { mag(), std::atan2(y, x) }; } T dot(const v2d_generic& rhs) const { return this->x * rhs.x + this->y * rhs.y; } T cross(const v2d_generic& rhs) const { return this->x * rhs.y - this->y * rhs.x; } v2d_generic operator + (const v2d_generic& rhs) const { return v2d_generic(this->x + rhs.x, this->y + rhs.y); } @@ -647,23 +623,39 @@ namespace olc // Note: joshinils has some good suggestions here, but they are complicated to implement at this moment, // however they will appear in a future version of PGE template inline v2d_generic operator * (const float& lhs, const v2d_generic& rhs) - { return v2d_generic((T)(lhs * (float)rhs.x), (T)(lhs * (float)rhs.y)); } + { + return v2d_generic((T)(lhs * (float)rhs.x), (T)(lhs * (float)rhs.y)); + } template inline v2d_generic operator * (const double& lhs, const v2d_generic& rhs) - { return v2d_generic((T)(lhs * (double)rhs.x), (T)(lhs * (double)rhs.y)); } + { + return v2d_generic((T)(lhs * (double)rhs.x), (T)(lhs * (double)rhs.y)); + } template inline v2d_generic operator * (const int& lhs, const v2d_generic& rhs) - { return v2d_generic((T)(lhs * (int)rhs.x), (T)(lhs * (int)rhs.y)); } + { + return v2d_generic((T)(lhs * (int)rhs.x), (T)(lhs * (int)rhs.y)); + } template inline v2d_generic operator / (const float& lhs, const v2d_generic& rhs) - { return v2d_generic((T)(lhs / (float)rhs.x), (T)(lhs / (float)rhs.y)); } + { + return v2d_generic((T)(lhs / (float)rhs.x), (T)(lhs / (float)rhs.y)); + } template inline v2d_generic operator / (const double& lhs, const v2d_generic& rhs) - { return v2d_generic((T)(lhs / (double)rhs.x), (T)(lhs / (double)rhs.y)); } + { + return v2d_generic((T)(lhs / (double)rhs.x), (T)(lhs / (double)rhs.y)); + } template inline v2d_generic operator / (const int& lhs, const v2d_generic& rhs) - { return v2d_generic((T)(lhs / (int)rhs.x), (T)(lhs / (int)rhs.y)); } + { + return v2d_generic((T)(lhs / (int)rhs.x), (T)(lhs / (int)rhs.y)); + } // To stop dandistine crying... template inline bool operator < (const v2d_generic& lhs, const v2d_generic& rhs) - { return lhs.y < rhs.y || (lhs.y == rhs.y && lhs.x < rhs.x); } + { + return lhs.y < rhs.y || (lhs.y == rhs.y && lhs.x < rhs.x); + } template inline bool operator > (const v2d_generic& lhs, const v2d_generic& rhs) - { return lhs.y > rhs.y || (lhs.y == rhs.y && lhs.x > rhs.x); } + { + return lhs.y > rhs.y || (lhs.y == rhs.y && lhs.x > rhs.x); + } typedef v2d_generic vi2d; typedef v2d_generic vu2d; @@ -673,7 +665,7 @@ namespace olc - + // O------------------------------------------------------------------------------O @@ -728,6 +720,8 @@ namespace olc public: olc::rcode LoadFromFile(const std::string& sImageFile, olc::ResourcePack* pack = nullptr); + olc::rcode LoadFromPGESprFile(const std::string& sImageFile, olc::ResourcePack* pack = nullptr); + olc::rcode SaveToPGESprFile(const std::string& sImageFile); public: int32_t width = 0; @@ -786,9 +780,7 @@ namespace olc class Renderable { public: - Renderable() = default; - Renderable(Renderable&& r) : pSprite(std::move(r.pSprite)), pDecal(std::move(r.pDecal)) {} - Renderable(const Renderable&) = delete; + Renderable() = default; olc::rcode Load(const std::string& sFile, ResourcePack* pack = nullptr, bool filter = false, bool clamp = true); void Create(uint32_t width, uint32_t height, bool filter = false, bool clamp = true); olc::Decal* Decal() const; @@ -821,7 +813,7 @@ namespace olc olc::vf2d vScale = { 1, 1 }; bool bShow = false; bool bUpdate = false; - olc::Renderable pDrawTarget; + olc::Sprite* pDrawTarget = nullptr; uint32_t nResID = 0; std::vector vecDecalInstance; olc::Pixel tint = olc::WHITE; @@ -976,7 +968,9 @@ namespace olc // Draws a circle located at (x,y) with radius void DrawCircle(int32_t x, int32_t y, int32_t radius, Pixel p = olc::WHITE, uint8_t mask = 0xFF); void DrawCircle(const olc::vi2d& pos, int32_t radius, Pixel p = olc::WHITE, uint8_t mask = 0xFF); - // Fills a circle located at (x,y) with radius + // Fills an arc from point 0 and point 1. The centre of the circle and the radius define the curvature + void FillArc(int32_t iterations, int32_t centreX, int32_t centreY, int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t radius, olc::Pixel p); + // Fills a circle located at (x,y) with radius void FillCircle(int32_t x, int32_t y, int32_t radius, Pixel p = olc::WHITE); void FillCircle(const olc::vi2d& pos, int32_t radius, Pixel p = olc::WHITE); // Draws a rectangle at (x,y) to (x+w,y+h) @@ -1036,10 +1030,7 @@ namespace olc void GradientFillRectDecal(const olc::vf2d& pos, const olc::vf2d& size, const olc::Pixel colTL, const olc::Pixel colBL, const olc::Pixel colBR, const olc::Pixel colTR); // Draws an arbitrary convex textured polygon using GPU void DrawPolygonDecal(olc::Decal* decal, const std::vector& pos, const std::vector& uv, const olc::Pixel tint = olc::WHITE); - // Draws a line in Decal Space - void DrawLineDecal(const olc::vf2d& pos1, const olc::vf2d& pos2, Pixel p = olc::WHITE); - void DrawRotatedStringDecal(const olc::vf2d& pos, const std::string& sText, const float fAngle, const olc::vf2d& center = { 0.0f, 0.0f }, const olc::Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f }); - void DrawRotatedStringPropDecal(const olc::vf2d& pos, const std::string& sText, const float fAngle, const olc::vf2d& center = { 0.0f, 0.0f }, const olc::Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f }); + // Clears entire draw target to Pixel void Clear(Pixel p); // Clears the rendering back buffer @@ -1051,7 +1042,7 @@ namespace olc std::string sAppName; private: // Inner mysterious workings - olc::Sprite* pDrawTarget = nullptr; + Sprite* pDrawTarget = nullptr; Pixel::Mode nPixelMode = Pixel::NORMAL; float fBlendFactor = 1.0f; olc::vi2d vScreenSize = { 256, 240 }; @@ -1076,6 +1067,7 @@ namespace olc int nFrameCount = 0; Sprite* fontSprite = nullptr; Decal* fontDecal = nullptr; + Sprite* pDefaultDrawTarget = nullptr; std::vector vLayers; uint8_t nTargetLayer = 0; uint32_t nLastFPS = 0; @@ -1180,19 +1172,29 @@ namespace olc // | olc::Pixel IMPLEMENTATION | // O------------------------------------------------------------------------------O Pixel::Pixel() - { r = 0; g = 0; b = 0; a = nDefaultAlpha; } + { + r = 0; g = 0; b = 0; a = nDefaultAlpha; + } Pixel::Pixel(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha) - { n = red | (green << 8) | (blue << 16) | (alpha << 24); } // Thanks jarekpelczar + { + n = red | (green << 8) | (blue << 16) | (alpha << 24); + } // Thanks jarekpelczar Pixel::Pixel(uint32_t p) - { n = p; } + { + n = p; + } bool Pixel::operator==(const Pixel& p) const - { return n == p.n; } + { + return n == p.n; + } bool Pixel::operator!=(const Pixel& p) const - { return n != p.n; } + { + return n != p.n; + } Pixel Pixel::operator * (const float i) const { @@ -1267,38 +1269,108 @@ namespace olc } Pixel PixelF(float red, float green, float blue, float alpha) - { return Pixel(uint8_t(red * 255.0f), uint8_t(green * 255.0f), uint8_t(blue * 255.0f), uint8_t(alpha * 255.0f)); } + { + return Pixel(uint8_t(red * 255.0f), uint8_t(green * 255.0f), uint8_t(blue * 255.0f), uint8_t(alpha * 255.0f)); + } Pixel PixelLerp(const olc::Pixel& p1, const olc::Pixel& p2, float t) - { return (p2 * t) + p1 * (1.0f - t); } + { + return (p2 * t) + p1 * (1.0f - t); + } // O------------------------------------------------------------------------------O // | olc::Sprite IMPLEMENTATION | // O------------------------------------------------------------------------------O Sprite::Sprite() - { width = 0; height = 0; } + { + width = 0; height = 0; + } Sprite::Sprite(const std::string& sImageFile, olc::ResourcePack* pack) - { LoadFromFile(sImageFile, pack); } + { + LoadFromFile(sImageFile, pack); + } Sprite::Sprite(int32_t w, int32_t h) - { + { width = w; height = h; pColData.resize(width * height); pColData.resize(width * height, nDefaultPixel); } Sprite::~Sprite() - { pColData.clear(); } + { + pColData.clear(); + } + + // To Be Deprecated + //olc::rcode Sprite::LoadFromPGESprFile(const std::string& sImageFile, olc::ResourcePack* pack) + //{ + // if (pColData) delete[] pColData; + // auto ReadData = [&](std::istream& is) + // { + // is.read((char*)&width, sizeof(int32_t)); + // is.read((char*)&height, sizeof(int32_t)); + // pColData = new Pixel[width * height]; + // is.read((char*)pColData, (size_t)width * (size_t)height * sizeof(uint32_t)); + // }; + + // // These are essentially Memory Surfaces represented by olc::Sprite + // // which load very fast, but are completely uncompressed + // if (pack == nullptr) + // { + // std::ifstream ifs; + // ifs.open(sImageFile, std::ifstream::binary); + // if (ifs.is_open()) + // { + // ReadData(ifs); + // return olc::OK; + // } + // else + // return olc::FAIL; + // } + // else + // { + // ResourceBuffer rb = pack->GetFileBuffer(sImageFile); + // std::istream is(&rb); + // ReadData(is); + // return olc::OK; + // } + // return olc::FAIL; + //} + + //olc::rcode Sprite::SaveToPGESprFile(const std::string& sImageFile) + //{ + // if (pColData == nullptr) return olc::FAIL; + + // std::ofstream ofs; + // ofs.open(sImageFile, std::ifstream::binary); + // if (ofs.is_open()) + // { + // ofs.write((char*)&width, sizeof(int32_t)); + // ofs.write((char*)&height, sizeof(int32_t)); + // ofs.write((char*)pColData, std::streamsize(width) * std::streamsize(height) * sizeof(uint32_t)); + // ofs.close(); + // return olc::OK; + // } + + // return olc::FAIL; + //} void Sprite::SetSampleMode(olc::Sprite::Mode mode) - { modeSample = mode; } + { + modeSample = mode; + } Pixel Sprite::GetPixel(const olc::vi2d& a) const - { return GetPixel(a.x, a.y); } + { + return GetPixel(a.x, a.y); + } bool Sprite::SetPixel(const olc::vi2d& a, Pixel p) - { return SetPixel(a.x, a.y, p); } + { + return SetPixel(a.x, a.y, p); + } Pixel Sprite::GetPixel(int32_t x, int32_t y) const { @@ -1356,7 +1428,9 @@ namespace olc } Pixel* Sprite::GetData() - { return pColData.data(); } + { + return pColData.data(); + } olc::rcode Sprite::LoadFromFile(const std::string& sImageFile, olc::ResourcePack* pack) @@ -1447,10 +1521,14 @@ namespace olc } olc::Decal* Renderable::Decal() const - { return pDecal.get(); } + { + return pDecal.get(); + } olc::Sprite* Renderable::Sprite() const - { return pSprite.get(); } + { + return pSprite.get(); + } // O------------------------------------------------------------------------------O // | olc::ResourcePack IMPLEMENTATION | @@ -1606,10 +1684,14 @@ namespace olc } ResourceBuffer ResourcePack::GetFileBuffer(const std::string& sFile) - { return ResourceBuffer(baseFile, mapFiles[sFile].nOffset, mapFiles[sFile].nSize); } + { + return ResourceBuffer(baseFile, mapFiles[sFile].nOffset, mapFiles[sFile].nSize); + } bool ResourcePack::Loaded() - { return baseFile.is_open(); } + { + return baseFile.is_open(); + } std::vector ResourcePack::scramble(const std::vector& data, const std::string& key) { @@ -1667,7 +1749,8 @@ namespace olc vInvScreenSize = { 1.0f / float(w), 1.0f / float(h) }; for (auto& layer : vLayers) { - layer.pDrawTarget.Create(vScreenSize.x, vScreenSize.y); + delete layer.pDrawTarget; // Erase existing layer sprites + layer.pDrawTarget = new Sprite(vScreenSize.x, vScreenSize.y); layer.bUpdate = true; } SetDrawTarget(nullptr); @@ -1711,7 +1794,7 @@ namespace olc else { nTargetLayer = 0; - pDrawTarget = vLayers[0].pDrawTarget.Sprite(); + pDrawTarget = vLayers[0].pDrawTarget; } } @@ -1719,46 +1802,66 @@ namespace olc { if (layer < vLayers.size()) { - pDrawTarget = vLayers[layer].pDrawTarget.Sprite(); + pDrawTarget = vLayers[layer].pDrawTarget; vLayers[layer].bUpdate = true; nTargetLayer = layer; } } void PixelGameEngine::EnableLayer(uint8_t layer, bool b) - { if (layer < vLayers.size()) vLayers[layer].bShow = b; } + { + if (layer < vLayers.size()) vLayers[layer].bShow = b; + } void PixelGameEngine::SetLayerOffset(uint8_t layer, const olc::vf2d& offset) - { SetLayerOffset(layer, offset.x, offset.y); } + { + SetLayerOffset(layer, offset.x, offset.y); + } void PixelGameEngine::SetLayerOffset(uint8_t layer, float x, float y) - { if (layer < vLayers.size()) vLayers[layer].vOffset = { x, y }; } + { + if (layer < vLayers.size()) vLayers[layer].vOffset = { x, y }; + } void PixelGameEngine::SetLayerScale(uint8_t layer, const olc::vf2d& scale) - { SetLayerScale(layer, scale.x, scale.y); } + { + SetLayerScale(layer, scale.x, scale.y); + } void PixelGameEngine::SetLayerScale(uint8_t layer, float x, float y) - { if (layer < vLayers.size()) vLayers[layer].vScale = { x, y }; } + { + if (layer < vLayers.size()) vLayers[layer].vScale = { x, y }; + } void PixelGameEngine::SetLayerTint(uint8_t layer, const olc::Pixel& tint) - { if (layer < vLayers.size()) vLayers[layer].tint = tint; } + { + if (layer < vLayers.size()) vLayers[layer].tint = tint; + } void PixelGameEngine::SetLayerCustomRenderFunction(uint8_t layer, std::function f) - { if (layer < vLayers.size()) vLayers[layer].funcHook = f; } + { + if (layer < vLayers.size()) vLayers[layer].funcHook = f; + } std::vector& PixelGameEngine::GetLayers() - { return vLayers; } + { + return vLayers; + } uint32_t PixelGameEngine::CreateLayer() { LayerDesc ld; - ld.pDrawTarget.Create(vScreenSize.x, vScreenSize.y); - vLayers.push_back(std::move(ld)); + ld.pDrawTarget = new olc::Sprite(vScreenSize.x, vScreenSize.y); + ld.nResID = renderer->CreateTexture(vScreenSize.x, vScreenSize.y); + renderer->UpdateTexture(ld.nResID, ld.pDrawTarget); + vLayers.push_back(ld); return uint32_t(vLayers.size()) - 1; } Sprite* PixelGameEngine::GetDrawTarget() const - { return pDrawTarget; } + { + return pDrawTarget; + } int32_t PixelGameEngine::GetDrawTargetWidth() const { @@ -1777,52 +1880,84 @@ namespace olc } uint32_t PixelGameEngine::GetFPS() const - { return nLastFPS; } + { + return nLastFPS; + } bool PixelGameEngine::IsFocused() const - { return bHasInputFocus; } + { + return bHasInputFocus; + } HWButton PixelGameEngine::GetKey(Key k) const - { return pKeyboardState[k]; } + { + return pKeyboardState[k]; + } HWButton PixelGameEngine::GetMouse(uint32_t b) const - { return pMouseState[b]; } + { + return pMouseState[b]; + } int32_t PixelGameEngine::GetMouseX() const - { return vMousePos.x; } + { + return vMousePos.x; + } int32_t PixelGameEngine::GetMouseY() const - { return vMousePos.y; } + { + return vMousePos.y; + } const olc::vi2d& PixelGameEngine::GetMousePos() const - { return vMousePos; } + { + return vMousePos; + } int32_t PixelGameEngine::GetMouseWheel() const - { return nMouseWheelDelta; } + { + return nMouseWheelDelta; + } int32_t PixelGameEngine::ScreenWidth() const - { return vScreenSize.x; } + { + return vScreenSize.x; + } int32_t PixelGameEngine::ScreenHeight() const - { return vScreenSize.y; } + { + return vScreenSize.y; + } float PixelGameEngine::GetElapsedTime() const - { return fLastElapsed; } + { + return fLastElapsed; + } const olc::vi2d& PixelGameEngine::GetWindowSize() const - { return vWindowSize; } + { + return vWindowSize; + } const olc::vi2d& PixelGameEngine::GetPixelSize() const - { return vPixelSize; } + { + return vPixelSize; + } const olc::vi2d& PixelGameEngine::GetScreenPixelSize() const - { return vScreenPixelSize; } + { + return vScreenPixelSize; + } const olc::vi2d& PixelGameEngine::GetWindowMouse() const - { return vMouseWindowPos; } + { + return vMouseWindowPos; + } bool PixelGameEngine::Draw(const olc::vi2d& pos, Pixel p) - { return Draw(pos.x, pos.y, p); } + { + return Draw(pos.x, pos.y, p); + } // This is it, the critical function that plots a pixel bool PixelGameEngine::Draw(int32_t x, int32_t y, Pixel p) @@ -1861,7 +1996,9 @@ namespace olc void PixelGameEngine::DrawLine(const olc::vi2d& pos1, const olc::vi2d& pos2, Pixel p, uint32_t pattern) - { DrawLine(pos1.x, pos1.y, pos2.x, pos2.y, p, pattern); } + { + DrawLine(pos1.x, pos1.y, pos2.x, pos2.y, p, pattern); + } void PixelGameEngine::DrawLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, Pixel p, uint32_t pattern) { @@ -1943,7 +2080,9 @@ namespace olc } void PixelGameEngine::DrawCircle(const olc::vi2d& pos, int32_t radius, Pixel p, uint8_t mask) - { DrawCircle(pos.x, pos.y, radius, p, mask); } + { + DrawCircle(pos.x, pos.y, radius, p, mask); + } void PixelGameEngine::DrawCircle(int32_t x, int32_t y, int32_t radius, Pixel p, uint8_t mask) { // Thanks to IanM-Matrix1 #PR121 @@ -1982,49 +2121,324 @@ namespace olc } void PixelGameEngine::FillCircle(const olc::vi2d& pos, int32_t radius, Pixel p) - { FillCircle(pos.x, pos.y, radius, p); } - + { + FillCircle(pos.x, pos.y, radius, p); + } + //Fills an arc from point 0 and point 1. The centre of the circle and the radius define the curvature + void PixelGameEngine::FillArc(int32_t iterations, int32_t centreX, int32_t centreY, int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t radius, olc::Pixel p) + { + if (!iterations) return; + //Get points + int32_t midX = (x0 + x1) >> 1; + int32_t midY = (y0 + y1) >> 1; + int32_t arcX = radius * cos(atan2(midY - centreY, midX - centreX)) + centreX; + int32_t arcY = radius * sin(atan2(midY - centreY, midX - centreX)) + centreY; + //Fill triangle + FillTriangle(x0, y0, x1, y1, arcX, arcY, p); + //Recur + FillArc(iterations - 1, centreX, centreY, x0, y0, arcX, arcY, radius, p); + FillArc(iterations - 1, centreX, centreY, x1, y1, arcX, arcY, radius, p); + return; + } void PixelGameEngine::FillCircle(int32_t x, int32_t y, int32_t radius, Pixel p) { // Thanks to IanM-Matrix1 #PR121 if (radius < 0 || x < -radius || y < -radius || x - GetDrawTargetWidth() > radius || y - GetDrawTargetHeight() > radius) return; - if (radius > 0) - { - int x0 = 0; - int y0 = radius; - int d = 3 - 2 * radius; - - auto drawline = [&](int sx, int ex, int y) + if (radius==0) + { + Draw(x, y, p); + return; + } + const int32_t width = ScreenWidth(); + const int32_t height = ScreenHeight(); + //When the circle becomes larger than the viewport, it is faster to draw the circle using arcs + if (radius > height || radius > width) + { + //This can be modified for higher precision + const int32_t ITERATIONS = 4; + + //Currently unprotected against overflow + //Check if all four points are within circle + const bool topLeft = (x)*(x)+(y)*(y) <= radius * radius; + const bool topRight = (x - width)*(x - width) + (y)*(y) <= radius * radius; + const bool bottomLeft = (x)*(x)+(y - height)*(y - height) <= radius * radius; + const bool bottomRight = (x - width)*(x - width) + (y - height)*(y - height) <= radius * radius; + + //Four Points inside circle + if ( + bottomRight && + topRight && + bottomLeft && + topLeft + ) + { + Clear(p); + return; + } + //Three Points inside circle + else if (topLeft + topRight + bottomRight + bottomLeft == 3) + { + if (!topLeft) + { + FillTriangle(width, 0, width, height, 0, height, p); + + int32_t yLeft = y - sqrt(radius*radius - x*x); + int32_t xTop = x - sqrt(radius*radius - y * y); + + FillTriangle(0, height, 0, yLeft, xTop, 0,p); + FillTriangle(0,height,xTop,0,width,0, p); + + //Fill arc + FillArc(ITERATIONS, x, y, 0, yLeft, xTop, 0, radius, p); + + return; + } + else if (!topRight) + { + FillTriangle(0,0, width, height, 0, height, p); + + int32_t yRight = y - sqrt(radius*radius - (width-x) * (width - x)); + int32_t xTop = x + sqrt(radius*radius - y*y); + + FillTriangle(0, 0, xTop, 0, width, yRight, p); + FillTriangle(0, 0, width, yRight, width, height, p); + + FillArc(ITERATIONS, x, y, width, yRight, xTop, 0, radius, p); + + return; + } + else if (!bottomLeft) + { + FillTriangle(0, 0, width, 0, width, height, p); + + int32_t yLeft = y + sqrt(radius*radius - x * x); + int32_t xBottom = x - sqrt(radius*radius - (height - y) * (height - y)); + + FillTriangle(0, yLeft, xBottom, height, width, height, p); + FillTriangle(0, 0, 0, yLeft, width, height, p); + + FillArc(ITERATIONS, x, y, 0, yLeft, xBottom, height, radius, p); + + return; + } + else //!bottomRight + { + FillTriangle(0, 0, width, 0, 0, height, p); + + int32_t yRight = y + sqrt(radius*radius - (width - x) * (width - x)); + int32_t xBottom = x + sqrt(radius*radius - (height - y) * (height - y)); + + FillTriangle(0, height, width, 0, width, yRight,p); + FillTriangle(0, height, xBottom, height, width, yRight, p); + + FillArc(ITERATIONS, x, y, width, yRight, xBottom, height, radius, p); + + return; + } + } + //Two points inside circle + else if (topLeft + topRight + bottomRight + bottomLeft == 2) + { + if (topLeft && topRight) + { + int32_t yRight = y + sqrt(radius*radius - (width - x)*(width - x)); + int32_t yLeft = y + sqrt(radius*radius - x * x); + if (x > width / 2) + { + FillRect(0, 0, width, yLeft, p); + FillTriangle(0, yLeft, width, yLeft, width, yRight, p); + } + else + { + FillRect(0, 0, width, yRight, p); + FillTriangle(0, yRight, 0, yLeft, width, yRight, p); + } + FillArc(ITERATIONS, x, y, 0, yLeft, width, yRight, radius, p); + return; + } + else if (topLeft && bottomLeft) + { + int32_t xTop = x + sqrt(radius*radius - (height - y)*(height - y)); + int32_t xBottom = x + sqrt(radius*radius - y * y); + if (y > height / 2) + { + FillRect(0, 0, xBottom, height, p); + FillTriangle(xBottom, 0, xBottom, height, xTop, height, p); + } + else + { + FillRect(0, 0, xTop, height, p); + FillTriangle(xTop, 0, xTop, height, xBottom, 0, p); + } + FillArc(ITERATIONS, x, y, xBottom, 0, xTop, height, radius, p); + return; + } + else if (bottomRight && topRight) + { + int32_t xTop = x - sqrt(radius*radius - (height - y)*(height - y)); + int32_t xBottom = x - sqrt(radius*radius - y * y); + if (y > height / 2) + { + FillTriangle(xBottom, 0, xTop, height, xBottom, height, p); + FillRect(xBottom, 0, width, height, p); + } + else + { + FillTriangle(xBottom, 0, xTop, 0, xTop, height, p); + FillRect(xTop, 0, width, height, p); + } + FillArc(ITERATIONS, x, y, xBottom, 0, xTop, height, radius, p); + return; + } + else //bottomRight && bottomLeft + { + int32_t yLeft = y - sqrt(radius*radius - x * x); + int32_t yRight = y - sqrt(radius*radius - (width - x)*(width - x)); + if (x > width / 2) + { + FillRect(0, yLeft, width, height, p); + FillTriangle(0, yLeft, width, yLeft, width, yRight, p); + } + else + { + FillRect(0, yRight, width, height, p); + FillTriangle(0, yRight, 0, yLeft, width, yRight, p); + } + FillArc(ITERATIONS, x, y, 0, yLeft, width, yRight, radius, p); + return; + } + } + //One Point inside circle + else if (topLeft) + { + int32_t yLeft = y + sqrt(radius*radius - x * x); + int32_t xTop = x + sqrt(radius*radius - y*y); + + FillTriangle(0, 0, xTop, 0, 0, yLeft, p); + + FillArc(ITERATIONS, x, y, xTop, 0, 0, yLeft, radius, p); + return; + } + else if (topRight) + { + int32_t yRight = y + sqrt(radius*radius - (width-x) * (width - x)); + int32_t xTop = x - sqrt(radius*radius - y * y); + + FillTriangle(xTop, 0, width, 0, width, yRight, p); + + FillArc(ITERATIONS, x, y, xTop, 0, width, yRight, radius, p); + return; + } + else if (bottomRight) + { + int32_t yRight = y - sqrt(radius*radius - (width - x) * (width - x)); + int32_t xBottom = x - sqrt(radius*radius - (height-y) * (height - y)); + + FillTriangle(xBottom, height, width, height, width, yRight, p); + + FillArc(ITERATIONS, x, y, xBottom, height, width, yRight, radius, p); + return; + } + else if (bottomLeft) + { + int32_t yLeft = y - sqrt(radius*radius - x*x); + int32_t xBottom = x + sqrt(radius*radius - (height - y) * (height - y)); + + FillTriangle(0, yLeft, 0, height, xBottom, height, p); + + FillArc(ITERATIONS, x, y, xBottom, height, 0, yLeft, radius, p); + return; + } + //No points inside circle + else + { + //Do extra checks on the y's + if (x <= 0) + { + int32_t yLeft1 = y - sqrt(radius*radius - x * x); + int32_t yLeft2 = y + sqrt(radius*radius - x * x); + + if (yLeft1 < 0 || yLeft2 < 0 || yLeft1 > height || yLeft2 > height) return; + + FillArc(ITERATIONS, x, y, 0, yLeft1, 0, yLeft2, radius, p); + return; + } + else if (x >= width) + { + int32_t yRight1 = y - sqrt(radius*radius - (width-x) * (width - x)); + int32_t yRight2 = y + sqrt(radius*radius - (width - x) * (width - x)); + + if (yRight1 < 0 || yRight2 < 0 || yRight1 > height || yRight2 > height) return; + + FillArc(ITERATIONS, x, y, width, yRight1, width, yRight2, radius, p); + return; + } + else if (y <= 0) + { + int32_t xTop1 = x - sqrt(radius*radius - y * y); + int32_t xTop2 = x + sqrt(radius*radius - y * y); + + if (xTop1 < 0 || xTop2 < 0 || xTop1 > width || xTop2 > width) return; + + FillArc(ITERATIONS, x, y, xTop1, 0, xTop2, 0, radius, p); + return; + } + else if (y >= height) //this check might be redundant + { + int32_t xBottom1 = x - sqrt(radius*radius - (height - y)*(height - y)); + int32_t xBottom2 = x + sqrt(radius*radius - (height - y)*(height - y)); + + if (xBottom1 < 0 || xBottom2 < 0 || xBottom1 > width || xBottom2 > width) return; + + FillArc(ITERATIONS, x, y, xBottom1, height, xBottom2, height, radius, p); + return; + } + + //overflow + return; + + } + + goto standardCircleFill; + } + else + { + standardCircleFill: + int x0 = 0; + int y0 = radius; + int d = 3 - 2 * radius; + + auto drawline = [&](int sx, int ex, int y) { for (int x = sx; x <= ex; x++) Draw(x, y, p); }; - while (y0 >= x0) - { - drawline(x - y0, x + y0, y - x0); - if (x0 > 0) drawline(x - y0, x + y0, y + x0); - - if (d < 0) - d += 4 * x0++ + 6; - else - { - if (x0 != y0) - { - drawline(x - x0, x + x0, y - y0); - drawline(x - x0, x + x0, y + y0); - } - d += 4 * (x0++ - y0--) + 10; - } - } - } - else - Draw(x, y, p); + while (y0 >= x0) + { + drawline(x - y0, x + y0, y - x0); + if (x0 > 0) drawline(x - y0, x + y0, y + x0); + + if (d < 0) + d += 4 * x0++ + 6; + else + { + if (x0 != y0) + { + drawline(x - x0, x + x0, y - y0); + drawline(x - x0, x + x0, y + y0); + } + d += 4 * (x0++ - y0--) + 10; + } + } + } } void PixelGameEngine::DrawRect(const olc::vi2d& pos, const olc::vi2d& size, Pixel p) - { DrawRect(pos.x, pos.y, size.x, size.y, p); } + { + DrawRect(pos.x, pos.y, size.x, size.y, p); + } void PixelGameEngine::DrawRect(int32_t x, int32_t y, int32_t w, int32_t h, Pixel p) { @@ -2042,13 +2456,19 @@ namespace olc } void PixelGameEngine::ClearBuffer(Pixel p, bool bDepth) - { renderer->ClearBuffer(p, bDepth); } + { + renderer->ClearBuffer(p, bDepth); + } olc::Sprite* PixelGameEngine::GetFontSprite() - { return fontSprite; } + { + return fontSprite; + } void PixelGameEngine::FillRect(const olc::vi2d& pos, const olc::vi2d& size, Pixel p) - { FillRect(pos.x, pos.y, size.x, size.y, p); } + { + FillRect(pos.x, pos.y, size.x, size.y, p); + } void PixelGameEngine::FillRect(int32_t x, int32_t y, int32_t w, int32_t h, Pixel p) { @@ -2071,7 +2491,9 @@ namespace olc } void PixelGameEngine::DrawTriangle(const olc::vi2d& pos1, const olc::vi2d& pos2, const olc::vi2d& pos3, Pixel p) - { DrawTriangle(pos1.x, pos1.y, pos2.x, pos2.y, pos3.x, pos3.y, p); } + { + DrawTriangle(pos1.x, pos1.y, pos2.x, pos2.y, pos3.x, pos3.y, p); + } void PixelGameEngine::DrawTriangle(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x3, int32_t y3, Pixel p) { @@ -2081,7 +2503,9 @@ namespace olc } void PixelGameEngine::FillTriangle(const olc::vi2d& pos1, const olc::vi2d& pos2, const olc::vi2d& pos3, Pixel p) - { FillTriangle(pos1.x, pos1.y, pos2.x, pos2.y, pos3.x, pos3.y, p); } + { + FillTriangle(pos1.x, pos1.y, pos2.x, pos2.y, pos3.x, pos3.y, p); + } // https://www.avrfreaks.net/sites/default/files/triangles.c void PixelGameEngine::FillTriangle(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x3, int32_t y3, Pixel p) @@ -2220,7 +2644,9 @@ namespace olc } void PixelGameEngine::DrawSprite(const olc::vi2d& pos, Sprite* sprite, uint32_t scale, uint8_t flip) - { DrawSprite(pos.x, pos.y, sprite, scale, flip); } + { + DrawSprite(pos.x, pos.y, sprite, scale, flip); + } void PixelGameEngine::DrawSprite(int32_t x, int32_t y, Sprite* sprite, uint32_t scale, uint8_t flip) { @@ -2257,7 +2683,9 @@ namespace olc } void PixelGameEngine::DrawPartialSprite(const olc::vi2d& pos, Sprite* sprite, const olc::vi2d& sourcepos, const olc::vi2d& size, uint32_t scale, uint8_t flip) - { DrawPartialSprite(pos.x, pos.y, sprite, sourcepos.x, sourcepos.y, size.x, size.y, scale, flip); } + { + DrawPartialSprite(pos.x, pos.y, sprite, sourcepos.x, sourcepos.y, size.x, size.y, scale, flip); + } void PixelGameEngine::DrawPartialSprite(int32_t x, int32_t y, Sprite* sprite, int32_t ox, int32_t oy, int32_t w, int32_t h, uint32_t scale, uint8_t flip) { @@ -2294,7 +2722,9 @@ namespace olc } void PixelGameEngine::SetDecalMode(const olc::DecalMode& mode) - { nDecalMode = mode; } + { + nDecalMode = mode; + } void PixelGameEngine::DrawPartialDecal(const olc::vf2d& pos, olc::Decal* decal, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::vf2d& scale, const olc::Pixel& tint) { @@ -2342,8 +2772,8 @@ namespace olc di.decal = decal; di.tint = { tint, tint, tint, tint }; di.pos = { { vScreenSpacePos.x, vScreenSpacePos.y }, { vScreenSpacePos.x, vScreenSpaceDim.y }, { vScreenSpaceDim.x, vScreenSpaceDim.y }, { vScreenSpaceDim.x, vScreenSpacePos.y } }; - olc::vf2d uvtl = (source_pos) * decal->vUVScale; - olc::vf2d uvbr = uvtl + ((source_size) * decal->vUVScale); + olc::vf2d uvtl = (source_pos)* decal->vUVScale; + olc::vf2d uvbr = uvtl + ((source_size)* decal->vUVScale); di.uv = { { uvtl.x, uvtl.y }, { uvtl.x, uvbr.y }, { uvbr.x, uvbr.y }, { uvbr.x, uvtl.y } }; di.w = { 1,1,1,1 }; di.mode = nDecalMode; @@ -2416,27 +2846,6 @@ namespace olc vLayers[nTargetLayer].vecDecalInstance.push_back(di); } - void PixelGameEngine::DrawLineDecal(const olc::vf2d& pos1, const olc::vf2d& pos2, Pixel p) - { - DecalInstance di; - di.decal = nullptr; - di.points = uint32_t(2); - di.pos.resize(di.points); - di.uv.resize(di.points); - di.w.resize(di.points); - di.tint.resize(di.points); - di.pos[0] = { (pos1.x * vInvScreenSize.x) * 2.0f - 1.0f, ((pos1.y * vInvScreenSize.y) * 2.0f - 1.0f) * -1.0f }; - di.uv[0] = { 0.0f, 0.0f }; - di.tint[0] = p; - di.w[0] = 1.0f; - di.pos[1] = { (pos2.x * vInvScreenSize.x) * 2.0f - 1.0f, ((pos2.y * vInvScreenSize.y) * 2.0f - 1.0f) * -1.0f }; - di.uv[1] = { 0.0f, 0.0f }; - di.tint[1] = p; - di.w[1] = 1.0f; - di.mode = olc::DecalMode::WIREFRAME; - vLayers[nTargetLayer].vecDecalInstance.push_back(di); - } - void PixelGameEngine::FillRectDecal(const olc::vf2d& pos, const olc::vf2d& size, const olc::Pixel col) { std::array points = { { {pos}, {pos.x, pos.y + size.y}, {pos + size}, {pos.x + size.x, pos.y} } }; @@ -2571,16 +2980,24 @@ namespace olc } void PixelGameEngine::DrawWarpedDecal(olc::Decal* decal, const std::array& pos, const olc::Pixel& tint) - { DrawWarpedDecal(decal, pos.data(), tint); } + { + DrawWarpedDecal(decal, pos.data(), tint); + } void PixelGameEngine::DrawWarpedDecal(olc::Decal* decal, const olc::vf2d(&pos)[4], const olc::Pixel& tint) - { DrawWarpedDecal(decal, &pos[0], tint); } + { + DrawWarpedDecal(decal, &pos[0], tint); + } void PixelGameEngine::DrawPartialWarpedDecal(olc::Decal* decal, const std::array& pos, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::Pixel& tint) - { DrawPartialWarpedDecal(decal, pos.data(), source_pos, source_size, tint); } + { + DrawPartialWarpedDecal(decal, pos.data(), source_pos, source_size, tint); + } void PixelGameEngine::DrawPartialWarpedDecal(olc::Decal* decal, const olc::vf2d(&pos)[4], const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::Pixel& tint) - { DrawPartialWarpedDecal(decal, &pos[0], source_pos, source_size, tint); } + { + DrawPartialWarpedDecal(decal, &pos[0], source_pos, source_size, tint); + } void PixelGameEngine::DrawStringDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col, const olc::vf2d& scale) { @@ -2619,44 +3036,6 @@ namespace olc } } } - // Thanks Oso-Grande/Sopadeoso For these awesom and stupidly clever Text Rotation routines... duh XD - void PixelGameEngine::DrawRotatedStringDecal(const olc::vf2d& pos, const std::string& sText, const float fAngle, const olc::vf2d& center, const Pixel col, const olc::vf2d& scale) - { - olc::vf2d spos = center; - for (auto c : sText) - { - if (c == '\n') - { - spos.x = center.x; spos.y -= 8.0f; - } - else - { - int32_t ox = (c - 32) % 16; - int32_t oy = (c - 32) / 16; - DrawPartialRotatedDecal(pos, fontDecal, fAngle, spos, { float(ox) * 8.0f, float(oy) * 8.0f }, { 8.0f, 8.0f }, scale, col); - spos.x -= 8.0f; - } - } - } - - void PixelGameEngine::DrawRotatedStringPropDecal(const olc::vf2d& pos, const std::string& sText, const float fAngle, const olc::vf2d& center, const Pixel col, const olc::vf2d& scale) - { - olc::vf2d spos = center; - for (auto c : sText) - { - if (c == '\n') - { - spos.x = center.x; spos.y -= 8.0f; - } - else - { - int32_t ox = (c - 32) % 16; - int32_t oy = (c - 32) / 16; - DrawPartialRotatedDecal(pos, fontDecal, fAngle, spos, { float(ox) * 8.0f + float(vFontSpacing[c - 32].x), float(oy) * 8.0f }, { float(vFontSpacing[c - 32].y), 8.0f }, scale, col); - spos.x -= float(vFontSpacing[c - 32].y); - } - } - } olc::vi2d PixelGameEngine::GetTextSize(const std::string& s) { @@ -2673,7 +3052,9 @@ namespace olc } void PixelGameEngine::DrawString(const olc::vi2d& pos, const std::string& sText, Pixel col, uint32_t scale) - { DrawString(pos.x, pos.y, sText, col, scale); } + { + DrawString(pos.x, pos.y, sText, col, scale); + } void PixelGameEngine::DrawString(int32_t x, int32_t y, const std::string& sText, Pixel col, uint32_t scale) { @@ -2736,7 +3117,9 @@ namespace olc } void PixelGameEngine::DrawStringProp(const olc::vi2d& pos, const std::string& sText, Pixel col, uint32_t scale) - { DrawStringProp(pos.x, pos.y, sText, col, scale); } + { + DrawStringProp(pos.x, pos.y, sText, col, scale); + } void PixelGameEngine::DrawStringProp(int32_t x, int32_t y, const std::string& sText, Pixel col, uint32_t scale) { @@ -2783,10 +3166,14 @@ namespace olc } void PixelGameEngine::SetPixelMode(Pixel::Mode m) - { nPixelMode = m; } + { + nPixelMode = m; + } Pixel::Mode PixelGameEngine::GetPixelMode() - { return nPixelMode; } + { + return nPixelMode; + } void PixelGameEngine::SetPixelMode(std::function pixelMode) { @@ -2806,14 +3193,20 @@ namespace olc // they are not overwritten bool PixelGameEngine::OnUserCreate() - { return false; } + { + return false; + } bool PixelGameEngine::OnUserUpdate(float fElapsedTime) - { UNUSED(fElapsedTime); return false; } + { + UNUSED(fElapsedTime); return false; + } bool PixelGameEngine::OnUserDestroy() - { return true; } - + { + return true; + } + void PixelGameEngine::olc_UpdateViewport() { int32_t ww = vScreenSize.x * vPixelSize.x; @@ -2847,7 +3240,9 @@ namespace olc } void PixelGameEngine::olc_UpdateMouseWheel(int32_t delta) - { nMouseWheelDeltaCache += delta; } + { + nMouseWheelDeltaCache += delta; + } void PixelGameEngine::olc_UpdateMouse(int32_t x, int32_t y) { @@ -2867,25 +3262,39 @@ namespace olc } void PixelGameEngine::olc_UpdateMouseState(int32_t button, bool state) - { pMouseNewState[button] = state; } + { + pMouseNewState[button] = state; + } void PixelGameEngine::olc_UpdateKeyState(int32_t key, bool state) - { pKeyNewState[key] = state; } + { + pKeyNewState[key] = state; + } void PixelGameEngine::olc_UpdateMouseFocus(bool state) - { bHasMouseFocus = state; } + { + bHasMouseFocus = state; + } void PixelGameEngine::olc_UpdateKeyFocus(bool state) - { bHasInputFocus = state; } + { + bHasInputFocus = state; + } void PixelGameEngine::olc_Reanimate() - { bAtomActive = true; } + { + bAtomActive = true; + } bool PixelGameEngine::olc_IsRunning() - { return bAtomActive; } + { + return bAtomActive; + } void PixelGameEngine::olc_Terminate() - { bAtomActive = false; } + { + bAtomActive = false; + } void PixelGameEngine::EngineThread() { @@ -3005,10 +3414,10 @@ namespace olc { if (layer->funcHook == nullptr) { - renderer->ApplyTexture(layer->pDrawTarget.Decal()->id); + renderer->ApplyTexture(layer->nResID); if (layer->bUpdate) { - layer->pDrawTarget.Decal()->Update(); + renderer->UpdateTexture(layer->nResID, layer->pDrawTarget); layer->bUpdate = false; } @@ -3098,13 +3507,13 @@ namespace olc void PixelGameEngine::pgex_Register(olc::PGEX* pgex) { if (std::find(vExtensions.begin(), vExtensions.end(), pgex) == vExtensions.end()) - vExtensions.push_back(pgex); + vExtensions.push_back(pgex); } - PGEX::PGEX(bool bHook) { if(bHook) pge->pgex_Register(this); } + PGEX::PGEX(bool bHook) { if (bHook) pge->pgex_Register(this); } void PGEX::OnBeforeUserCreate() {} - void PGEX::OnAfterUserCreate() {} + void PGEX::OnAfterUserCreate() {} void PGEX::OnBeforeUserUpdate(float& fElapsedTime) {} void PGEX::OnAfterUserUpdate(float fElapsedTime) {} @@ -3122,8 +3531,6 @@ namespace olc // | olcPixelGameEngine Renderers - the draw-y bits | // O------------------------------------------------------------------------------O -#if !defined(OLC_PGE_HEADLESS) - #pragma region renderer_ogl10 // O------------------------------------------------------------------------------O // | START RENDERER: OpenGL 1.0 (the original, the best...) | @@ -3131,37 +3538,37 @@ namespace olc #if defined(OLC_GFX_OPENGL10) #if defined(OLC_PLATFORM_WINAPI) - #include - #include - #if !defined(__MINGW32__) - #pragma comment(lib, "Dwmapi.lib") - #endif - typedef BOOL(WINAPI wglSwapInterval_t) (int interval); - static wglSwapInterval_t* wglSwapInterval = nullptr; - typedef HDC glDeviceContext_t; - typedef HGLRC glRenderContext_t; +#include +#include +#if !defined(__MINGW32__) +#pragma comment(lib, "Dwmapi.lib") +#endif +typedef BOOL(WINAPI wglSwapInterval_t) (int interval); +static wglSwapInterval_t* wglSwapInterval = nullptr; +typedef HDC glDeviceContext_t; +typedef HGLRC glRenderContext_t; #endif #if defined(__linux__) || defined(__FreeBSD__) - #include +#include #endif #if defined(OLC_PLATFORM_X11) - namespace X11 - { - #include - } - typedef int(glSwapInterval_t)(X11::Display* dpy, X11::GLXDrawable drawable, int interval); - static glSwapInterval_t* glSwapIntervalEXT; - typedef X11::GLXContext glDeviceContext_t; - typedef X11::GLXContext glRenderContext_t; +namespace X11 +{ +#include +} +typedef int(glSwapInterval_t)(X11::Display* dpy, X11::GLXDrawable drawable, int interval); +static glSwapInterval_t* glSwapIntervalEXT; +typedef X11::GLXContext glDeviceContext_t; +typedef X11::GLXContext glRenderContext_t; #endif #if defined(__APPLE__) - #define GL_SILENCE_DEPRECATION - #include - #include - #include +#define GL_SILENCE_DEPRECATION +#include +#include +#include #endif namespace olc @@ -3447,7 +3854,11 @@ namespace olc void UpdateViewport(const olc::vi2d& pos, const olc::vi2d& size) override { +#if defined(OLC_PLATFORM_GLUT) + if (!mFullScreen) glutReshapeWindow(size.x, size.y); +#else glViewport(pos.x, pos.y, size.x, size.y); +#endif } }; } @@ -3464,51 +3875,51 @@ namespace olc #if defined(OLC_GFX_OPENGL33) #if defined(OLC_PLATFORM_WINAPI) - #include - #include - #if !defined(__MINGW32__) - #pragma comment(lib, "Dwmapi.lib") - #endif - typedef void __stdcall locSwapInterval_t(GLsizei n); - typedef HDC glDeviceContext_t; - typedef HGLRC glRenderContext_t; - #define CALLSTYLE __stdcall - #define OGL_LOAD(t, n) (t*)wglGetProcAddress(#n) +#include +#include +#if !defined(__MINGW32__) +#pragma comment(lib, "Dwmapi.lib") +#endif +typedef void __stdcall locSwapInterval_t(GLsizei n); +typedef HDC glDeviceContext_t; +typedef HGLRC glRenderContext_t; +#define CALLSTYLE __stdcall +#define OGL_LOAD(t, n) (t*)wglGetProcAddress(#n) #endif #if defined(__linux__) || defined(__FreeBSD__) - #include +#include #endif #if defined(OLC_PLATFORM_X11) - namespace X11 - { - #include - } - typedef int(locSwapInterval_t)(X11::Display* dpy, X11::GLXDrawable drawable, int interval); - typedef X11::GLXContext glDeviceContext_t; - typedef X11::GLXContext glRenderContext_t; - #define CALLSTYLE - #define OGL_LOAD(t, n) (t*)glXGetProcAddress((unsigned char*)#n); +namespace X11 +{ +#include +} +typedef int(locSwapInterval_t)(X11::Display* dpy, X11::GLXDrawable drawable, int interval); +typedef X11::GLXContext glDeviceContext_t; +typedef X11::GLXContext glRenderContext_t; +#define CALLSTYLE +#define OGL_LOAD(t, n) (t*)glXGetProcAddress((unsigned char*)#n); #endif #if defined(__APPLE__) - #define GL_SILENCE_DEPRECATION - #include - #include - #include +#define GL_SILENCE_DEPRECATION +#include +#include +#include #endif #if defined(OLC_PLATFORM_EMSCRIPTEN) - #include - #include - #define GL_GLEXT_PROTOTYPES - #include - #include - #define CALLSTYLE - typedef EGLBoolean(locSwapInterval_t)(EGLDisplay display, EGLint interval); - #define GL_CLAMP GL_CLAMP_TO_EDGE - #define OGL_LOAD(t, n) n; +#include +#include +#define GL_GLEXT_PROTOTYPES +#include +#include +#define CALLSTYLE +typedef EGLBoolean(locSwapInterval_t)(EGLDisplay display, EGLint interval); +#define GL_CLAMP GL_CLAMP_TO_EDGE +#define OGL_LOAD(t, n) n; #endif namespace olc @@ -3552,10 +3963,10 @@ namespace olc #if defined(OLC_PLATFORM_GLUT) bool mFullScreen = false; #else - #if !defined(OLC_PLATFORM_EMSCRIPTEN) +#if !defined(OLC_PLATFORM_EMSCRIPTEN) glDeviceContext_t glDeviceContext = 0; glRenderContext_t glRenderContext = 0; - #endif +#endif #endif bool bSync = false; olc::DecalMode nDecalMode = olc::DecalMode(-1); // Thanks Gusgo & Bispoo @@ -3704,10 +4115,10 @@ namespace olc #endif } #else - #if !defined(OLC_PLATFORM_EMSCRIPTEN) +#if !defined(OLC_PLATFORM_EMSCRIPTEN) glEnable(GL_TEXTURE_2D); // Turn on texturing glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); - #endif +#endif #endif // Load External OpenGL Functions locCreateShader = OGL_LOAD(locCreateShader_t, glCreateShader); @@ -3968,7 +4379,11 @@ namespace olc void UpdateViewport(const olc::vi2d& pos, const olc::vi2d& size) override { +#if defined(OLC_PLATFORM_GLUT) + if (!mFullScreen) glutReshapeWindow(size.x, size.y); +#else glViewport(pos.x, pos.y, size.x, size.y); +#endif } }; } @@ -3993,17 +4408,17 @@ namespace olc #include #include #if defined(__MINGW32__) // Thanks Gusgo & Dandistine, but c'mon mingw!! wtf?! - #include +#include #else - #include +#include #endif #include #undef min #undef max #if !defined(__MINGW32__) - #pragma comment(lib, "gdiplus.lib") - #pragma comment(lib, "Shlwapi.lib") +#pragma comment(lib, "gdiplus.lib") +#pragma comment(lib, "Shlwapi.lib") #endif namespace olc @@ -4014,13 +4429,13 @@ namespace olc { public: GDIPlusStartup() - { + { Gdiplus::GdiplusStartupInput startupInput; GdiplusStartup(&token, &startupInput, NULL); } ULONG_PTR token; - + ~GDIPlusStartup() { // Well, MarcusTU thought this was important :D @@ -4301,9 +4716,9 @@ namespace olc #if defined(OLC_PLATFORM_WINAPI) #if defined(_WIN32) && !defined(__MINGW32__) - #pragma comment(lib, "user32.lib") // Visual Studio Only - #pragma comment(lib, "gdi32.lib") // For other Windows Compilers please add - #pragma comment(lib, "opengl32.lib") // these libs to your linker input +#pragma comment(lib, "user32.lib") // Visual Studio Only +#pragma comment(lib, "gdi32.lib") // For other Windows Compilers please add +#pragma comment(lib, "opengl32.lib") // these libs to your linker input #endif namespace olc @@ -4817,43 +5232,7 @@ namespace olc { exit(0); } -#if defined(__APPLE__) - static void scrollWheelUpdate(id selff, SEL _sel, id theEvent) { - static const SEL deltaYSel = sel_registerName("deltaY"); - - double deltaY = ((double (*)(id, SEL))objc_msgSend_fpret)(theEvent, deltaYSel); - - for (int i = 0; i < abs(deltaY); i++) { - if (deltaY > 0) { - ptrPGE->olc_UpdateMouseWheel(-1); - } - else if (deltaY < 0) { - ptrPGE->olc_UpdateMouseWheel(1); - } - } - } -#endif static void ThreadFunct() { -#if defined(__APPLE__) - static bool hasEnabledCocoa = false; - if (!hasEnabledCocoa) { - // Objective-C Wizardry - Class NSApplicationClass = objc_getClass("NSApplication"); - - // NSApp = [NSApplication sharedApplication] - SEL sharedApplicationSel = sel_registerName("sharedApplication"); - id NSApp = ((id(*)(Class, SEL))objc_msgSend)(NSApplicationClass, sharedApplicationSel); - // window = [NSApp mainWindow] - SEL mainWindowSel = sel_registerName("mainWindow"); - id window = ((id(*)(id, SEL))objc_msgSend)(NSApp, mainWindowSel); - - // [window setStyleMask: NSWindowStyleMaskClosable | ~NSWindowStyleMaskResizable] - SEL setStyleMaskSel = sel_registerName("setStyleMask:"); - ((void (*)(id, SEL, NSUInteger))objc_msgSend)(window, setStyleMaskSel, 7); - - hasEnabledCocoa = true; - } -#endif if (!*bActiveRef) { ExitMainLoop(); return; @@ -4867,30 +5246,19 @@ namespace olc { virtual olc::rcode CreateWindowPane(const olc::vi2d& vWindowPos, olc::vi2d& vWindowSize, bool bFullScreen) override { -#if defined(__APPLE__) - Class GLUTViewClass = objc_getClass("GLUTView"); - - SEL scrollWheelSel = sel_registerName("scrollWheel:"); - bool resultAddMethod = class_addMethod(GLUTViewClass, scrollWheelSel, (IMP)scrollWheelUpdate, "v@:@"); - assert(resultAddMethod); -#endif - renderer->PrepareDevice(); + if (bFullScreen) { vWindowSize.x = glutGet(GLUT_SCREEN_WIDTH); vWindowSize.y = glutGet(GLUT_SCREEN_HEIGHT); glutFullScreen(); } - else - { - if (vWindowSize.x > glutGet(GLUT_SCREEN_WIDTH) || vWindowSize.y > glutGet(GLUT_SCREEN_HEIGHT)) - { - perror("ERROR: The specified window dimensions do not fit on your screen\n"); - return olc::FAIL; - } - glutReshapeWindow(vWindowSize.x, vWindowSize.y - 1); + + if (vWindowSize.x > glutGet(GLUT_SCREEN_WIDTH) || vWindowSize.y > glutGet(GLUT_SCREEN_HEIGHT)) { + perror("ERROR: The specified window dimensions do not fit on your screen\n"); + return olc::FAIL; } // Create Keyboard Mapping @@ -4938,7 +5306,7 @@ namespace olc { if (mapKeys[key]) ptrPGE->olc_UpdateKeyState(mapKeys[key], true); - }); + }); glutKeyboardUpFunc([](unsigned char key, int x, int y) -> void { switch (glutGetModifiers()) { @@ -4960,18 +5328,18 @@ namespace olc { if (mapKeys[key]) ptrPGE->olc_UpdateKeyState(mapKeys[key], false); - }); + }); //Special keys glutSpecialFunc([](int key, int x, int y) -> void { if (mapKeys[key]) ptrPGE->olc_UpdateKeyState(mapKeys[key], true); - }); + }); glutSpecialUpFunc([](int key, int x, int y) -> void { if (mapKeys[key]) ptrPGE->olc_UpdateKeyState(mapKeys[key], false); - }); + }); glutMouseFunc([](int button, int state, int x, int y) -> void { switch (button) { @@ -4988,7 +5356,7 @@ namespace olc { else if (state == GLUT_DOWN) ptrPGE->olc_UpdateMouseState(1, true); break; } - }); + }); auto mouseMoveCall = [](int x, int y) -> void { ptrPGE->olc_UpdateMouse(x, y); @@ -5000,7 +5368,7 @@ namespace olc { glutEntryFunc([](int state) -> void { if (state == GLUT_ENTERED) ptrPGE->olc_UpdateKeyFocus(true); else if (state == GLUT_LEFT) ptrPGE->olc_UpdateKeyFocus(false); - }); + }); glutDisplayFunc(DrawFunct); glutIdleFunc(ThreadFunct); @@ -5036,12 +5404,19 @@ namespace olc { if (platform->CreateWindowPane({ 30,30 }, vWindowSize, bFullScreen) != olc::OK) return olc::FAIL; olc_UpdateWindowSize(vWindowSize.x, vWindowSize.y); + if (platform->ThreadStartUp() == olc::FAIL) return olc::FAIL; + olc_PrepareEngine(); + if (!OnUserCreate()) return olc::FAIL; + Platform_GLUT::bActiveRef = &bAtomActive; + glutWMCloseFunc(Platform_GLUT::ExitMainLoop); + bAtomActive = true; + platform->StartSystemEventLoop(); //This code will not even be run but why not @@ -5080,10 +5455,12 @@ namespace olc { #include #include -extern "C" +extern "C" { EMSCRIPTEN_KEEPALIVE inline int olc_OnPageUnload() - { olc::platform->ApplicationCleanUp(); return 0; } + { + olc::platform->ApplicationCleanUp(); return 0; + } } namespace olc @@ -5092,17 +5469,25 @@ namespace olc { public: - virtual olc::rcode ApplicationStartUp() override - { return olc::rcode::OK; } + virtual olc::rcode ApplicationStartUp() override + { + return olc::rcode::OK; + } - virtual olc::rcode ApplicationCleanUp() override - { ThreadCleanUp(); return olc::rcode::OK; } + virtual olc::rcode ApplicationCleanUp() override + { + ThreadCleanUp(); return olc::rcode::OK; + } virtual olc::rcode ThreadStartUp() override - { return olc::rcode::OK; } + { + return olc::rcode::OK; + } virtual olc::rcode ThreadCleanUp() override - { renderer->DestroyDevice(); return olc::OK; } + { + renderer->DestroyDevice(); return olc::OK; + } virtual olc::rcode CreateGraphics(bool bFullScreen, bool bEnableVSYNC, const olc::vi2d& vViewPos, const olc::vi2d& vViewSize) override { @@ -5177,9 +5562,9 @@ namespace olc // Canvas Focus Callbacks emscripten_set_blur_callback("#canvas", 0, 1, focus_callback); emscripten_set_focus_callback("#canvas", 0, 1, focus_callback); - + #pragma warning disable format - EM_ASM( window.onunload = Module._olc_OnPageUnload; ); + EM_ASM(window.onunload = Module._olc_OnPageUnload; ); // IMPORTANT! - Sorry About This... // @@ -5192,19 +5577,19 @@ namespace olc // // Wake up people! Of course theres a spoon. There has to be to keep feeding // the giant web baby. - + // Fullscreen and Resize Observers EM_ASM({ - // cache for reuse - Module._olc_EmscriptenShellCss = "width: 100%; height: 70vh; margin-left: auto; margin-right: auto;"; + // cache for reuse + Module._olc_EmscriptenShellCss = "width: 100%; height: 70vh; margin-left: auto; margin-right: auto;"; // width / height = aspect ratio Module._olc_WindowAspectRatio = $0 / $1; - Module.canvas.parentNode.addEventListener("resize", function(e) { - - if (e.defaultPrevented) { e.stopPropagation(); return; } + Module.canvas.parentNode.addEventListener("resize", (e) = > { + + if (e.defaultPrevented) { e.stopPropagation(); return; } var viewWidth = e.detail.width; var viewHeight = e.detail.width / Module._olc_WindowAspectRatio; if (viewHeight > e.detail.height) @@ -5212,7 +5597,7 @@ namespace olc viewHeight = e.detail.height; viewWidth = e.detail.height * Module._olc_WindowAspectRatio; } - + if (Module.canvas.parentNode.className == 'emscripten_border') Module.canvas.parentNode.style.cssText = Module._olc_EmscriptenShellCss + " width: " + viewWidth.toString() + "px; height: " + viewHeight.toString() + "px;"; @@ -5220,7 +5605,7 @@ namespace olc Module.canvas.setAttribute("height", viewHeight); if (document.fullscreenElement != null) - { + { var top = (e.detail.height - viewHeight) / 2; var left = (e.detail.width - viewWidth) / 2; Module.canvas.style.position = "fixed"; @@ -5239,10 +5624,10 @@ namespace olc }); // helper function to prevent repeating the same code everywhere - Module._olc_ResizeCanvas = function() + Module._olc_ResizeCanvas = () = > { // yes, we still have to wait, sigh.. - setTimeout(function() + setTimeout(() = > { // if default template, stretch width as well if (Module.canvas.parentNode.className == 'emscripten_border') @@ -5252,7 +5637,7 @@ namespace olc Module.canvas.style.cssText = "width: 100%; height: 100%; outline: none;"; // setup custom resize event - var resizeEvent = new CustomEvent('resize', + var resizeEvent = new CustomEvent('resize', { detail: { width: Module.canvas.clientWidth, @@ -5281,10 +5666,10 @@ namespace olc Module._olc_ResizeCanvas(); // observe and react to resizing of the container element - var resizeObserver = new ResizeObserver(function(entries) {Module._olc_ResizeCanvas();}).observe(Module.canvas.parentNode); + var resizeObserver = new ResizeObserver((entries) = > {Module._olc_ResizeCanvas(); }).observe(Module.canvas.parentNode); // observe and react to changes that occur when entering/exiting fullscreen - var mutationObserver = new MutationObserver(function(mutationsList, observer) + var mutationObserver = new MutationObserver((mutationsList, observer) = > { // a change has occurred, let's check them out! for (var i = 0; i < mutationsList.length; i++) @@ -5297,7 +5682,7 @@ namespace olc Module._olc_ResizeCanvas(); } } - }).observe(Module.canvas.parentNode, + }).observe(Module.canvas.parentNode, { attributes: false, childList : true, @@ -5305,9 +5690,9 @@ namespace olc }); // add resize listener on window - window.addEventListener("resize", function(e) { Module._olc_ResizeCanvas(); }); + window.addEventListener("resize", (e) = > { Module._olc_ResizeCanvas(); }); - }, vWindowSize.x, vWindowSize.y); // Fullscreen and Resize Observers + }, vWindowSize.x, vWindowSize.y); // Fullscreen and Resize Observers #pragma warning restore format return olc::rcode::OK; } @@ -5319,7 +5704,7 @@ namespace olc } //TY Gorbit - static EM_BOOL focus_callback(int eventType, const EmscriptenFocusEvent* focusEvent, void* userData) + static EM_BOOL focus_callback(int eventType, const EmscriptenFocusEvent* focusEvent, void* userData) { if (eventType == EMSCRIPTEN_EVENT_BLUR) { @@ -5425,13 +5810,19 @@ namespace olc virtual olc::rcode SetWindowTitle(const std::string& s) override - { emscripten_set_window_title(s.c_str()); return olc::OK; } + { + emscripten_set_window_title(s.c_str()); return olc::OK; + } - virtual olc::rcode StartSystemEventLoop() override - { return olc::OK; } + virtual olc::rcode StartSystemEventLoop() override + { + return olc::OK; + } virtual olc::rcode HandleSystemEvent() override - { return olc::OK; } + { + return olc::OK; + } static void MainLoop() { @@ -5487,7 +5878,7 @@ namespace olc } } -extern "C" +extern "C" { EMSCRIPTEN_KEEPALIVE inline void olc_PGE_UpdateWindowSize(int width, int height) { @@ -5504,8 +5895,6 @@ extern "C" #pragma endregion -#endif // Headless - // O------------------------------------------------------------------------------O // | olcPixelGameEngine Auto-Configuration | // O------------------------------------------------------------------------------O @@ -5515,8 +5904,6 @@ namespace olc void PixelGameEngine::olc_ConfigureSystem() { -#if !defined(OLC_PGE_HEADLESS) - #if defined(OLC_IMAGE_GDI) olc::Sprite::loader = std::make_unique(); #endif @@ -5585,11 +5972,6 @@ namespace olc // Associate components with PGE instance platform->ptrPGE = this; renderer->ptrPGE = this; -#else - olc::Sprite::loader = nullptr; - platform = nullptr; - renderer = nullptr; -#endif } }