diff --git a/C++ProjectTemplate b/C++ProjectTemplate index 90e0074..c678470 100755 Binary files a/C++ProjectTemplate and b/C++ProjectTemplate differ diff --git a/main.cpp b/main.cpp index de543e5..dbb67ae 100644 --- a/main.cpp +++ b/main.cpp @@ -60,28 +60,6 @@ struct Data{ int main() { - std::vector testList; - std::cout<<"Test"< #pragma endregion -#define PGE_VER 220 +#define PGE_VER 223 // O------------------------------------------------------------------------------O // | COMPILER CONFIGURATION ODDITIES | @@ -433,8 +445,16 @@ int main() // | PLATFORM SELECTION CODE, Thanks slavka! | // O------------------------------------------------------------------------------O +#if defined(OLC_PGE_HEADLESS) + #define OLC_PLATFORM_HEADLESS + #define OLC_GFX_HEADLESS + #if !defined(OLC_IMAGE_STB) && !defined(OLC_IMAGE_GDI) && !defined(OLC_IMAGE_LIBPNG) + #define OLC_IMAGE_HEADLESS + #endif +#endif + // Platform -#if !defined(OLC_PLATFORM_WINAPI) && !defined(OLC_PLATFORM_X11) && !defined(OLC_PLATFORM_GLUT) && !defined(OLC_PLATFORM_EMSCRIPTEN) +#if !defined(OLC_PLATFORM_WINAPI) && !defined(OLC_PLATFORM_X11) && !defined(OLC_PLATFORM_GLUT) && !defined(OLC_PLATFORM_EMSCRIPTEN) && !defined(OLC_PLATFORM_HEADLESS) #if !defined(OLC_PLATFORM_CUSTOM_EX) #if defined(_WIN32) #define OLC_PLATFORM_WINAPI @@ -457,8 +477,10 @@ int main() #define PGE_USE_CUSTOM_START #endif + + // Renderer -#if !defined(OLC_GFX_OPENGL10) && !defined(OLC_GFX_OPENGL33) && !defined(OLC_GFX_DIRECTX10) +#if !defined(OLC_GFX_OPENGL10) && !defined(OLC_GFX_OPENGL33) && !defined(OLC_GFX_DIRECTX10) && !defined(OLC_GFX_HEADLESS) #if !defined(OLC_GFX_CUSTOM_EX) #if defined(OLC_PLATFORM_EMSCRIPTEN) #define OLC_GFX_OPENGL33 @@ -469,7 +491,7 @@ int main() #endif // Image loader -#if !defined(OLC_IMAGE_STB) && !defined(OLC_IMAGE_GDI) && !defined(OLC_IMAGE_LIBPNG) +#if !defined(OLC_IMAGE_STB) && !defined(OLC_IMAGE_GDI) && !defined(OLC_IMAGE_LIBPNG) && !defined(OLC_IMAGE_HEADLESS) #if !defined(OLC_IMAGE_CUSTOM_EX) #if defined(_WIN32) #define OLC_IMAGE_GDI @@ -527,6 +549,15 @@ int main() #endif #endif #endif + +#if defined(OLC_PGE_HEADLESS) +#if defined max +#undef max +#endif +#if defined min +#undef min +#endif +#endif #pragma endregion // O------------------------------------------------------------------------------O @@ -543,6 +574,7 @@ namespace olc constexpr uint8_t nDefaultAlpha = 0xFF; constexpr uint32_t nDefaultPixel = (nDefaultAlpha << 24); constexpr uint8_t nTabSizeInSpaces = 4; + constexpr size_t OLC_MAX_VERTS = 128; enum rcode { FAIL = 0, OK = 1, NO_FILE = -1 }; // O------------------------------------------------------------------------------O @@ -572,6 +604,8 @@ namespace olc Pixel operator - (const Pixel& p) const; Pixel& operator +=(const Pixel& p); Pixel& operator -=(const Pixel& p); + Pixel operator * (const Pixel& p) const; + Pixel& operator *=(const Pixel& p); Pixel inv() const; }; @@ -653,6 +687,8 @@ namespace olc 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) }; } + v2d_generic clamp(const v2d_generic& v1, const v2d_generic& v2) const { return this->max(v1).min(v2); } + v2d_generic lerp(const v2d_generic& v1, const double t) { return this->operator*(T(1.0 - t)) + (v1 * T(t)); } 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); } @@ -776,7 +812,9 @@ namespace olc Pixel GetPixel(const olc::vi2d& a) const; bool SetPixel(const olc::vi2d& a, Pixel p); Pixel Sample(float x, float y) const; + Pixel Sample(const olc::vf2d& uv) const; Pixel SampleBL(float u, float v) const; + Pixel SampleBL(const olc::vf2d& uv) const; Pixel* GetData(); olc::Sprite* Duplicate(); olc::Sprite* Duplicate(const olc::vi2d& vPos, const olc::vi2d& vSize); @@ -946,6 +984,7 @@ namespace olc // Called when a console command is executed virtual bool OnConsoleCommand(const std::string& sCommand); + public: // Hardware Interfaces // Returns true if window is currently in focus bool IsFocused() const; @@ -994,6 +1033,9 @@ namespace olc const olc::vi2d& GetScreenPixelSize() const; // Gets "screen" size const olc::vi2d& GetScreenSize() const; + // Gets any files dropped this frame + const std::vector& GetDroppedFiles() const; + const olc::vi2d& GetDroppedFilesPoint() const; public: // CONFIGURATION ROUTINES // Layer targeting functions @@ -1047,6 +1089,9 @@ namespace olc // Flat fills a triangle between points (x1,y1), (x2,y2) and (x3,y3) void FillTriangle(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x3, int32_t y3, Pixel p = olc::WHITE); void FillTriangle(const olc::vi2d& pos1, const olc::vi2d& pos2, const olc::vi2d& pos3, Pixel p = olc::WHITE); + // Fill a textured and coloured triangle + void FillTexturedTriangle(const std::vector& vPoints, std::vector vTex, std::vector vColour, olc::Sprite* sprTex); + void FillTexturedPolygon(const std::vector& vPoints, const std::vector& vTex, const std::vector& vColour, olc::Sprite* sprTex, olc::DecalStructure structure = olc::DecalStructure::LIST); // Draws an entire sprite at location (x,y) void DrawSprite(int32_t x, int32_t y, Sprite* sprite, uint32_t scale = 1, uint8_t flip = olc::Sprite::NONE); void DrawSprite(const olc::vi2d& pos, Sprite* sprite, uint32_t scale = 1, uint8_t flip = olc::Sprite::NONE); @@ -1096,7 +1141,7 @@ namespace olc void DrawPolygonDecal(olc::Decal* decal, const std::vector& pos, const std::vector& uv, const olc::Pixel tint = olc::WHITE); void DrawPolygonDecal(olc::Decal* decal, const std::vector& pos, const std::vector& depth, const std::vector& uv, const olc::Pixel tint = olc::WHITE); void DrawPolygonDecal(olc::Decal* decal, const std::vector& pos, const std::vector& uv, const std::vector& tint); - + void DrawPolygonDecal(olc::Decal* decal, const std::vector& pos, const std::vector& uv, const std::vector& colours, const olc::Pixel tint); // 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 }); @@ -1199,6 +1244,10 @@ namespace olc std::function funcPixelMode; std::chrono::time_point m_tp1, m_tp2; std::vector vFontSpacing; + std::vector vDroppedFiles; + std::vector vDroppedFilesCache; + olc::vi2d vDroppedFilesPoint; + olc::vi2d vDroppedFilesPointCache; // Command Console Specific bool bConsoleShow = false; @@ -1253,6 +1302,7 @@ namespace olc void olc_UpdateMouseFocus(bool state); void olc_UpdateKeyFocus(bool state); void olc_Terminate(); + void olc_DropFiles(int32_t x, int32_t y, const std::vector& vFiles); void olc_Reanimate(); bool olc_IsRunning(); @@ -1296,6 +1346,101 @@ namespace olc #pragma endregion + +#pragma region opengl33_iface +// In order to facilitate more advanced graphics features, some PGEX +// will rely on shaders. Instead of having each PGEX responsible for +// managing this, for convenience, this interface exists. + +#if defined(OLC_GFX_OPENGL33) + + #if defined(OLC_PLATFORM_WINAPI) + #include + #define CALLSTYLE __stdcall + #endif + + #if defined(__linux__) || defined(__FreeBSD__) + #include + #endif + + #if defined(OLC_PLATFORM_X11) + namespace X11 { + #include + } + #define CALLSTYLE + #endif + + #if defined(__APPLE__) + #define GL_SILENCE_DEPRECATION + #include + #include + #include + #endif + + #if defined(OLC_PLATFORM_EMSCRIPTEN) + #include + #include + #define GL_GLEXT_PROTOTYPES + #include + #include + #define CALLSTYLE + #define GL_CLAMP GL_CLAMP_TO_EDGE + #endif + +namespace olc +{ + typedef char GLchar; + typedef ptrdiff_t GLsizeiptr; + + typedef GLuint CALLSTYLE locCreateShader_t(GLenum type); + typedef GLuint CALLSTYLE locCreateProgram_t(void); + typedef void CALLSTYLE locDeleteShader_t(GLuint shader); + typedef void CALLSTYLE locCompileShader_t(GLuint shader); + typedef void CALLSTYLE locLinkProgram_t(GLuint program); + typedef void CALLSTYLE locDeleteProgram_t(GLuint program); + typedef void CALLSTYLE locAttachShader_t(GLuint program, GLuint shader); + typedef void CALLSTYLE locBindBuffer_t(GLenum target, GLuint buffer); + typedef void CALLSTYLE locBufferData_t(GLenum target, GLsizeiptr size, const void* data, GLenum usage); + typedef void CALLSTYLE locGenBuffers_t(GLsizei n, GLuint* buffers); + typedef void CALLSTYLE locVertexAttribPointer_t(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer); + typedef void CALLSTYLE locEnableVertexAttribArray_t(GLuint index); + typedef void CALLSTYLE locUseProgram_t(GLuint program); + typedef void CALLSTYLE locBindVertexArray_t(GLuint array); + typedef void CALLSTYLE locGenVertexArrays_t(GLsizei n, GLuint* arrays); + typedef void CALLSTYLE locGetShaderInfoLog_t(GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog); + typedef GLint CALLSTYLE locGetUniformLocation_t(GLuint program, const GLchar* name); + typedef void CALLSTYLE locUniform1f_t(GLint location, GLfloat v0); + typedef void CALLSTYLE locUniform1i_t(GLint location, GLint v0); + typedef void CALLSTYLE locUniform2fv_t(GLint location, GLsizei count, const GLfloat* value); + typedef void CALLSTYLE locActiveTexture_t(GLenum texture); + typedef void CALLSTYLE locGenFrameBuffers_t(GLsizei n, GLuint* ids); + typedef void CALLSTYLE locBindFrameBuffer_t(GLenum target, GLuint fb); + typedef GLenum CALLSTYLE locCheckFrameBufferStatus_t(GLenum target); + typedef void CALLSTYLE locDeleteFrameBuffers_t(GLsizei n, const GLuint* fbs); + typedef void CALLSTYLE locFrameBufferTexture2D_t(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); + typedef void CALLSTYLE locDrawBuffers_t(GLsizei n, const GLenum* bufs); + typedef void CALLSTYLE locBlendFuncSeparate_t(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); + +#if defined(OLC_PLATFORM_WINAPI) + typedef void __stdcall locSwapInterval_t(GLsizei n); +#endif + +#if defined(OLC_PLATFORM_X11) + typedef int(locSwapInterval_t)(X11::Display* dpy, X11::GLXDrawable drawable, int interval); +#endif + +#if defined(OLC_PLATFORM_EMSCRIPTEN) + typedef void CALLSTYLE locShaderSource_t(GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length); + typedef EGLBoolean(locSwapInterval_t)(EGLDisplay display, EGLint interval); +#else + typedef void CALLSTYLE locShaderSource_t(GLuint shader, GLsizei count, const GLchar** string, const GLint* length); +#endif + +} // olc namespace +#endif // OpenGL33 Definitions +#pragma endregion + + #endif // OLC_PGE_DEF @@ -1394,6 +1539,24 @@ namespace olc return *this; } + Pixel Pixel::operator * (const Pixel& p) const + { + uint8_t nR = uint8_t(std::min(255.0f, std::max(0.0f, float(r) * float(p.r) / 255.0f))); + uint8_t nG = uint8_t(std::min(255.0f, std::max(0.0f, float(g) * float(p.g) / 255.0f))); + uint8_t nB = uint8_t(std::min(255.0f, std::max(0.0f, float(b) * float(p.b) / 255.0f))); + uint8_t nA = uint8_t(std::min(255.0f, std::max(0.0f, float(a) * float(p.a) / 255.0f))); + return Pixel(nR, nG, nB, nA); + } + + Pixel& Pixel::operator *=(const Pixel& p) + { + this->r = uint8_t(std::min(255.0f, std::max(0.0f, float(r) * float(p.r) / 255.0f))); + this->g = uint8_t(std::min(255.0f, std::max(0.0f, float(g) * float(p.g) / 255.0f))); + this->b = uint8_t(std::min(255.0f, std::max(0.0f, float(b) * float(p.b) / 255.0f))); + this->a = uint8_t(std::min(255.0f, std::max(0.0f, float(a) * float(p.a) / 255.0f))); + return *this; + } + Pixel Pixel::inv() const { uint8_t nR = uint8_t(std::min(255, std::max(0, 255 - int(r)))); @@ -1472,6 +1635,11 @@ namespace olc return GetPixel(sx, sy); } + Pixel Sprite::Sample(const olc::vf2d& uv) const + { + return Sample(uv.x, uv.y); + } + Pixel Sprite::SampleBL(float u, float v) const { u = u * width - 0.5f; @@ -1494,6 +1662,11 @@ namespace olc (uint8_t)((p1.b * u_opposite + p2.b * u_ratio) * v_opposite + (p3.b * u_opposite + p4.b * u_ratio) * v_ratio)); } + Pixel Sprite::SampleBL(const olc::vf2d& uv) const + { + return SampleBL(uv.x, uv.y); + } + Pixel* Sprite::GetData() { return pColData.data(); } @@ -2411,6 +2584,168 @@ namespace olc } } + void PixelGameEngine::FillTexturedTriangle(const std::vector& vPoints, std::vector vTex, std::vector vColour, olc::Sprite* sprTex) + { + olc::vi2d p1 = vPoints[0]; + olc::vi2d p2 = vPoints[1]; + olc::vi2d p3 = vPoints[2]; + + if (p2.y < p1.y){std::swap(p1.y, p2.y); std::swap(p1.x, p2.x); std::swap(vTex[0].x, vTex[1].x); std::swap(vTex[0].y, vTex[1].y); std::swap(vColour[0], vColour[1]);} + if (p3.y < p1.y){std::swap(p1.y, p3.y); std::swap(p1.x, p3.x); std::swap(vTex[0].x, vTex[2].x); std::swap(vTex[0].y, vTex[2].y); std::swap(vColour[0], vColour[2]);} + if (p3.y < p2.y){std::swap(p2.y, p3.y); std::swap(p2.x, p3.x); std::swap(vTex[1].x, vTex[2].x); std::swap(vTex[1].y, vTex[2].y); std::swap(vColour[1], vColour[2]);} + + olc::vi2d dPos1 = p2 - p1; + olc::vf2d dTex1 = vTex[1] - vTex[0]; + int dcr1 = vColour[1].r - vColour[0].r; + int dcg1 = vColour[1].g - vColour[0].g; + int dcb1 = vColour[1].b - vColour[0].b; + int dca1 = vColour[1].a - vColour[0].a; + + olc::vi2d dPos2 = p3 - p1; + olc::vf2d dTex2 = vTex[2] - vTex[0]; + int dcr2 = vColour[2].r - vColour[0].r; + int dcg2 = vColour[2].g - vColour[0].g; + int dcb2 = vColour[2].b - vColour[0].b; + int dca2 = vColour[2].a - vColour[0].a; + + float dax_step = 0, dbx_step = 0, dcr1_step = 0, dcr2_step = 0, dcg1_step = 0, dcg2_step = 0, dcb1_step = 0, dcb2_step = 0, dca1_step = 0, dca2_step = 0; + olc::vf2d vTex1Step, vTex2Step; + + if (dPos1.y) + { + dax_step = dPos1.x / (float)abs(dPos1.y); + vTex1Step = dTex1 / (float)abs(dPos1.y); + dcr1_step = dcr1 / (float)abs(dPos1.y); + dcg1_step = dcg1 / (float)abs(dPos1.y); + dcb1_step = dcb1 / (float)abs(dPos1.y); + dca1_step = dca1 / (float)abs(dPos1.y); + } + + if (dPos2.y) + { + dbx_step = dPos2.x / (float)abs(dPos2.y); + vTex2Step = dTex2 / (float)abs(dPos2.y); + dcr2_step = dcr2 / (float)abs(dPos2.y); + dcg2_step = dcg2 / (float)abs(dPos2.y); + dcb2_step = dcb2 / (float)abs(dPos2.y); + dca2_step = dca2 / (float)abs(dPos2.y); + } + + olc::vi2d vStart; + olc::vi2d vEnd; + int vStartIdx; + + for (int pass = 0; pass < 2; pass++) + { + if (pass == 0) + { + vStart = p1; vEnd = p2; vStartIdx = 0; + } + else + { + dPos1 = p3 - p2; + dTex1 = vTex[2] - vTex[1]; + dcr1 = vColour[2].r - vColour[1].r; + dcg1 = vColour[2].g - vColour[1].g; + dcb1 = vColour[2].b - vColour[1].b; + dca1 = vColour[2].a - vColour[1].a; + dcr1_step = 0; dcg1_step = 0; dcb1_step = 0; dca1_step = 0; + + if (dPos2.y) dbx_step = dPos2.x / (float)abs(dPos2.y); + if (dPos1.y) + { + dax_step = dPos1.x / (float)abs(dPos1.y); + vTex1Step = dTex1 / (float)abs(dPos1.y); + dcr1_step = dcr1 / (float)abs(dPos1.y); + dcg1_step = dcg1 / (float)abs(dPos1.y); + dcb1_step = dcb1 / (float)abs(dPos1.y); + dca1_step = dca1 / (float)abs(dPos1.y); + } + + vStart = p2; vEnd = p3; vStartIdx = 1; + } + + if (dPos1.y) + { + for (int i = vStart.y; i <= vEnd.y; i++) + { + int ax = int(vStart.x + (float)(i - vStart.y) * dax_step); + int bx = int(p1.x + (float)(i - p1.y) * dbx_step); + + olc::vf2d tex_s(vTex[vStartIdx].x + (float)(i - vStart.y) * vTex1Step.x, vTex[vStartIdx].y + (float)(i - vStart.y) * vTex1Step.y); + olc::vf2d tex_e(vTex[0].x + (float)(i - p1.y) * vTex2Step.x, vTex[0].y + (float)(i - p1.y) * vTex2Step.y); + + olc::Pixel col_s(vColour[vStartIdx].r + uint8_t((float)(i - vStart.y) * dcr1_step), vColour[vStartIdx].g + uint8_t((float)(i - vStart.y) * dcg1_step), + vColour[vStartIdx].b + uint8_t((float)(i - vStart.y) * dcb1_step), vColour[vStartIdx].a + uint8_t((float)(i - vStart.y) * dca1_step)); + + olc::Pixel col_e(vColour[0].r + uint8_t((float)(i - p1.y) * dcr2_step), vColour[0].g + uint8_t((float)(i - p1.y) * dcg2_step), + vColour[0].b + uint8_t((float)(i - p1.y) * dcb2_step), vColour[0].a + uint8_t((float)(i - p1.y) * dca2_step)); + + if (ax > bx) { std::swap(ax, bx); std::swap(tex_s, tex_e); std::swap(col_s, col_e); } + + float tstep = 1.0f / ((float)(bx - ax)); + float t = 0.0f; + + for (int j = ax; j < bx; j++) + { + olc::Pixel pixel = PixelLerp(col_s, col_e, t); + if (sprTex != nullptr) pixel *= sprTex->Sample(tex_s.lerp(tex_e, t)); + Draw(j, i, pixel); + t += tstep; + } + } + } + } + } + + void PixelGameEngine::FillTexturedPolygon(const std::vector& vPoints, const std::vector& vTex, const std::vector& vColour, olc::Sprite* sprTex, olc::DecalStructure structure) + { + if (structure == olc::DecalStructure::LINE) + { + return; // Meaningless, so do nothing + } + + if (vPoints.size() < 3 || vTex.size() < 3 || vColour.size() < 3) + return; + + if (structure == olc::DecalStructure::LIST) + { + for (int tri = 0; tri < vPoints.size() / 3; tri++) + { + std::vector vP = { vPoints[tri * 3 + 0], vPoints[tri * 3 + 1], vPoints[tri * 3 + 2] }; + std::vector vT = { vTex[tri * 3 + 0], vTex[tri * 3 + 1], vTex[tri * 3 + 2] }; + std::vector vC = { vColour[tri * 3 + 0], vColour[tri * 3 + 1], vColour[tri * 3 + 2] }; + FillTexturedTriangle(vP, vT, vC, sprTex); + } + return; + } + + if (structure == olc::DecalStructure::STRIP) + { + for (int tri = 2; tri < vPoints.size(); tri++) + { + std::vector vP = { vPoints[tri - 2], vPoints[tri-1], vPoints[tri] }; + std::vector vT = { vTex[tri - 2], vTex[tri - 1], vTex[tri] }; + std::vector vC = { vColour[tri - 2], vColour[tri - 1], vColour[tri] }; + FillTexturedTriangle(vP, vT, vC, sprTex); + } + return; + } + + if (structure == olc::DecalStructure::FAN) + { + for (int tri = 2; tri < vPoints.size(); tri++) + { + std::vector vP = { vPoints[0], vPoints[tri - 1], vPoints[tri] }; + std::vector vT = { vTex[0], vTex[tri - 1], vTex[tri] }; + std::vector vC = { vColour[0], vColour[tri - 1], vColour[tri] }; + FillTexturedTriangle(vP, vT, vC, sprTex); + } + return; + } + } + + void PixelGameEngine::DrawSprite(const olc::vi2d& pos, Sprite* sprite, uint32_t scale, uint8_t flip) { DrawSprite(pos.x, pos.y, sprite, scale, flip); } @@ -2642,6 +2977,15 @@ namespace olc vLayers[nTargetLayer].vecDecalInstance.push_back(di); } + void PixelGameEngine::DrawPolygonDecal(olc::Decal* decal, const std::vector& pos, const std::vector& uv, const std::vector& colours, const olc::Pixel tint) + { + std::vector newColours(colours.size(), olc::WHITE); + std::transform(colours.begin(), colours.end(), newColours.begin(), + [&tint](const olc::Pixel pin) { return pin * tint; }); + DrawPolygonDecal(decal, pos, uv, newColours); + } + + void PixelGameEngine::DrawPolygonDecal(olc::Decal* decal, const std::vector& pos, const std::vector& depth, const std::vector& uv, const olc::Pixel tint) { DecalInstance di; @@ -3217,6 +3561,12 @@ namespace olc } + const std::vector& PixelGameEngine::GetDroppedFiles() const + { return vDroppedFiles; } + + const olc::vi2d& PixelGameEngine::GetDroppedFilesPoint() const + { return vDroppedFilesPoint; } + void PixelGameEngine::TextEntryEnable(const bool bEnable, const std::string& sText) { @@ -3338,7 +3688,6 @@ namespace olc void PixelGameEngine::OnTextEntryComplete(const std::string& sText) { UNUSED(sText); } bool PixelGameEngine::OnConsoleCommand(const std::string& sCommand) { UNUSED(sCommand); return false; } - // Externalised API void PixelGameEngine::olc_UpdateViewport() { @@ -3404,6 +3753,19 @@ namespace olc void PixelGameEngine::olc_UpdateKeyFocus(bool state) { bHasInputFocus = state; } + void PixelGameEngine::olc_DropFiles(int32_t x, int32_t y, const std::vector& vFiles) + { + x -= vViewPos.x; + y -= vViewPos.y; + vDroppedFilesPointCache.x = (int32_t)(((float)x / (float)(vWindowSize.x - (vViewPos.x * 2)) * (float)vScreenSize.x)); + vDroppedFilesPointCache.y = (int32_t)(((float)y / (float)(vWindowSize.y - (vViewPos.y * 2)) * (float)vScreenSize.y)); + if (vDroppedFilesPointCache.x >= (int32_t)vScreenSize.x) vDroppedFilesPointCache.x = vScreenSize.x - 1; + if (vDroppedFilesPointCache.y >= (int32_t)vScreenSize.y) vDroppedFilesPointCache.y = vScreenSize.y - 1; + if (vDroppedFilesPointCache.x < 0) vDroppedFilesPointCache.x = 0; + if (vDroppedFilesPointCache.y < 0) vDroppedFilesPointCache.y = 0; + vDroppedFilesCache = vFiles; + } + void PixelGameEngine::olc_Reanimate() { bAtomActive = true; } @@ -3520,17 +3882,22 @@ namespace olc nMouseWheelDelta = nMouseWheelDeltaCache; nMouseWheelDeltaCache = 0; + vDroppedFiles = vDroppedFilesCache; + vDroppedFilesPoint = vDroppedFilesPointCache; + vDroppedFilesCache.clear(); + if (bTextEntryEnable) { UpdateTextEntry(); } // Handle Frame Update - bool bExtensionBlockFrame = false; + bool bExtensionBlockFrame = false; for (auto& ext : vExtensions) bExtensionBlockFrame |= ext->OnBeforeUserUpdate(fElapsedTime); if (!bExtensionBlockFrame) { if (!OnUserUpdate(fElapsedTime)) bAtomActive = false; + } for (auto& ext : vExtensions) ext->OnAfterUserUpdate(fElapsedTime); @@ -3540,6 +3907,8 @@ namespace olc UpdateConsole(); } + + // Display Frame renderer->UpdateViewport(vViewPos, vViewSize); renderer->ClearBuffer(olc::BLACK, true); @@ -3698,10 +4067,118 @@ namespace olc }; #pragma endregion + +#pragma region platform_headless +namespace olc +{ +#if defined(OLC_GFX_HEADLESS) + class Renderer_Headless : public olc::Renderer + { + public: + virtual void PrepareDevice() {}; + virtual olc::rcode CreateDevice(std::vector params, bool bFullScreen, bool bVSYNC) { return olc::rcode::OK; } + virtual olc::rcode DestroyDevice() { return olc::rcode::OK; } + virtual void DisplayFrame() {} + virtual void PrepareDrawing() {} + virtual void SetDecalMode(const olc::DecalMode& mode) {} + virtual void DrawLayerQuad(const olc::vf2d& offset, const olc::vf2d& scale, const olc::Pixel tint) {} + virtual void DrawDecal(const olc::DecalInstance& decal) {} + virtual uint32_t CreateTexture(const uint32_t width, const uint32_t height, const bool filtered = false, const bool clamp = true) {return 1;}; + virtual void UpdateTexture(uint32_t id, olc::Sprite* spr) {} + virtual void ReadTexture(uint32_t id, olc::Sprite* spr) {} + virtual uint32_t DeleteTexture(const uint32_t id) {return 1;} + virtual void ApplyTexture(uint32_t id) {} + virtual void UpdateViewport(const olc::vi2d& pos, const olc::vi2d& size) {} + virtual void ClearBuffer(olc::Pixel p, bool bDepth) {} + }; +#endif +#if defined(OLC_PLATFORM_HEADLESS) + class Platform_Headless : public olc::Platform + { + public: + virtual olc::rcode ApplicationStartUp() { return olc::rcode::OK; } + virtual olc::rcode ApplicationCleanUp() { return olc::rcode::OK; } + virtual olc::rcode ThreadStartUp() { return olc::rcode::OK; } + virtual olc::rcode ThreadCleanUp() { return olc::rcode::OK; } + virtual olc::rcode CreateGraphics(bool bFullScreen, bool bEnableVSYNC, const olc::vi2d& vViewPos, const olc::vi2d& vViewSize) { return olc::rcode::OK; } + virtual olc::rcode CreateWindowPane(const olc::vi2d& vWindowPos, olc::vi2d& vWindowSize, bool bFullScreen) { return olc::rcode::OK; } + virtual olc::rcode SetWindowTitle(const std::string& s) { return olc::rcode::OK; } + virtual olc::rcode StartSystemEventLoop() { return olc::rcode::OK; } + virtual olc::rcode HandleSystemEvent() { return olc::rcode::OK; } + }; +#endif +} +#pragma endregion + // O------------------------------------------------------------------------------O // | olcPixelGameEngine Renderers - the draw-y bits | // O------------------------------------------------------------------------------O +#pragma region image_stb +// O------------------------------------------------------------------------------O +// | START IMAGE LOADER: stb_image.h, all systems, very fast | +// O------------------------------------------------------------------------------O +// Thanks to Sean Barrett - https://github.com/nothings/stb/blob/master/stb_image.h +// MIT License - Copyright(c) 2017 Sean Barrett + +// Note you need to download the above file into your project folder, and +// #define OLC_IMAGE_STB +// #define OLC_PGE_APPLICATION +// #include "olcPixelGameEngine.h" + +#if defined(OLC_IMAGE_STB) +#define STB_IMAGE_IMPLEMENTATION +#include "stb_image.h" +namespace olc +{ + class ImageLoader_STB : public olc::ImageLoader + { + public: + ImageLoader_STB() : ImageLoader() + {} + + olc::rcode LoadImageResource(olc::Sprite* spr, const std::string& sImageFile, olc::ResourcePack* pack) override + { + UNUSED(pack); + // clear out existing sprite + spr->pColData.clear(); + // Open file + stbi_uc* bytes = nullptr; + int w = 0, h = 0, cmp = 0; + if (pack != nullptr) + { + ResourceBuffer rb = pack->GetFileBuffer(sImageFile); + bytes = stbi_load_from_memory((unsigned char*)rb.vMemory.data(), rb.vMemory.size(), &w, &h, &cmp, 4); + } + else + { + // Check file exists + if (!_gfs::exists(sImageFile)) return olc::rcode::NO_FILE; + bytes = stbi_load(sImageFile.c_str(), &w, &h, &cmp, 4); + } + + if (!bytes) return olc::rcode::FAIL; + spr->width = w; spr->height = h; + spr->pColData.resize(spr->width * spr->height); + std::memcpy(spr->pColData.data(), bytes, spr->width * spr->height * 4); + delete[] bytes; + return olc::rcode::OK; + } + + olc::rcode SaveImageResource(olc::Sprite* spr, const std::string& sImageFile) override + { + return olc::rcode::OK; + } + }; +} +#endif +// O------------------------------------------------------------------------------O +// | START IMAGE LOADER: stb_image.h | +// O------------------------------------------------------------------------------O +#pragma endregion + + + #if !defined(OLC_PGE_HEADLESS) #pragma region renderer_ogl10 @@ -4103,39 +4580,39 @@ namespace olc #if defined(OLC_PLATFORM_WINAPI) #include - #include + //#include #if !defined(__MINGW32__) #pragma comment(lib, "Dwmapi.lib") #endif - typedef void __stdcall locSwapInterval_t(GLsizei n); + //typedef void __stdcall locSwapInterval_t(GLsizei n); typedef HDC glDeviceContext_t; typedef HGLRC glRenderContext_t; - #define CALLSTYLE __stdcall + //#define CALLSTYLE __stdcall #define OGL_LOAD(t, n) (t*)wglGetProcAddress(#n) #endif - -#if defined(__linux__) || defined(__FreeBSD__) - #include -#endif +// +//#if defined(__linux__) || defined(__FreeBSD__) +// #include +//#endif #if defined(OLC_PLATFORM_X11) - namespace X11 + /*namespace X11 { #include } - typedef int(locSwapInterval_t)(X11::Display* dpy, X11::GLXDrawable drawable, int interval); + 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 CALLSTYLE #define OGL_LOAD(t, n) (t*)glXGetProcAddress((unsigned char*)#n); #endif -#if defined(__APPLE__) - #define GL_SILENCE_DEPRECATION - #include - #include - #include -#endif +//#if defined(__APPLE__) +// #define GL_SILENCE_DEPRECATION +// #include +// #include +// #include +//#endif #if defined(OLC_PLATFORM_EMSCRIPTEN) #include @@ -4151,31 +4628,43 @@ namespace olc namespace olc { - typedef char GLchar; - typedef ptrdiff_t GLsizeiptr; - typedef GLuint CALLSTYLE locCreateShader_t(GLenum type); - typedef GLuint CALLSTYLE locCreateProgram_t(void); - typedef void CALLSTYLE locDeleteShader_t(GLuint shader); -#if defined(OLC_PLATFORM_EMSCRIPTEN) - typedef void CALLSTYLE locShaderSource_t(GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length); -#else - typedef void CALLSTYLE locShaderSource_t(GLuint shader, GLsizei count, const GLchar** string, const GLint* length); -#endif - typedef void CALLSTYLE locCompileShader_t(GLuint shader); - typedef void CALLSTYLE locLinkProgram_t(GLuint program); - typedef void CALLSTYLE locDeleteProgram_t(GLuint program); - typedef void CALLSTYLE locAttachShader_t(GLuint program, GLuint shader); - typedef void CALLSTYLE locBindBuffer_t(GLenum target, GLuint buffer); - typedef void CALLSTYLE locBufferData_t(GLenum target, GLsizeiptr size, const void* data, GLenum usage); - typedef void CALLSTYLE locGenBuffers_t(GLsizei n, GLuint* buffers); - typedef void CALLSTYLE locVertexAttribPointer_t(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer); - typedef void CALLSTYLE locEnableVertexAttribArray_t(GLuint index); - typedef void CALLSTYLE locUseProgram_t(GLuint program); - typedef void CALLSTYLE locBindVertexArray_t(GLuint array); - typedef void CALLSTYLE locGenVertexArrays_t(GLsizei n, GLuint* arrays); - typedef void CALLSTYLE locGetShaderInfoLog_t(GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog); +// typedef char GLchar; +// typedef ptrdiff_t GLsizeiptr; +// typedef GLuint CALLSTYLE locCreateShader_t(GLenum type); +// typedef GLuint CALLSTYLE locCreateProgram_t(void); +// typedef void CALLSTYLE locDeleteShader_t(GLuint shader); +//#if defined(OLC_PLATFORM_EMSCRIPTEN) +// typedef void CALLSTYLE locShaderSource_t(GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length); +//#else +// typedef void CALLSTYLE locShaderSource_t(GLuint shader, GLsizei count, const GLchar** string, const GLint* length); +//#endif +// typedef void CALLSTYLE locCompileShader_t(GLuint shader); +// typedef void CALLSTYLE locLinkProgram_t(GLuint program); +// typedef void CALLSTYLE locDeleteProgram_t(GLuint program); +// typedef void CALLSTYLE locAttachShader_t(GLuint program, GLuint shader); +// typedef void CALLSTYLE locBindBuffer_t(GLenum target, GLuint buffer); +// typedef void CALLSTYLE locBufferData_t(GLenum target, GLsizeiptr size, const void* data, GLenum usage); +// typedef void CALLSTYLE locGenBuffers_t(GLsizei n, GLuint* buffers); +// typedef void CALLSTYLE locVertexAttribPointer_t(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer); +// typedef void CALLSTYLE locEnableVertexAttribArray_t(GLuint index); +// typedef void CALLSTYLE locUseProgram_t(GLuint program); +// typedef void CALLSTYLE locBindVertexArray_t(GLuint array); +// typedef void CALLSTYLE locGenVertexArrays_t(GLsizei n, GLuint* arrays); +// typedef void CALLSTYLE locGetShaderInfoLog_t(GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog); +// typedef GLint CALLSTYLE locGetUniformLocation_t(GLuint program, const GLchar* name); +// typedef void CALLSTYLE locUniform1f_t(GLint location, GLfloat v0); +// typedef void CALLSTYLE locUniform1i_t(GLint location, GLint v0); +// typedef void CALLSTYLE locUniform2fv_t(GLint location, GLsizei count, const GLfloat* value); +// typedef void CALLSTYLE locActiveTexture_t(GLenum texture); +// typedef void CALLSTYLE locGenFrameBuffers_t(GLsizei n, GLuint* ids); +// typedef void CALLSTYLE locBindFrameBuffer_t(GLenum target, GLuint fb); +// typedef GLenum CALLSTYLE locCheckFrameBufferStatus_t(GLenum target); +// typedef void CALLSTYLE locDeleteFrameBuffers_t(GLsizei n, const GLuint* fbs); +// typedef void CALLSTYLE locFrameBufferTexture2D_t(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +// typedef void CALLSTYLE locDrawBuffers_t(GLsizei n, const GLenum* bufs); +// typedef void CALLSTYLE locBlendFuncSeparate_t(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); - constexpr size_t OLC_MAX_VERTS = 128; + class Renderer_OGL33 : public olc::Renderer { @@ -4280,7 +4769,7 @@ namespace olc wglMakeCurrent(glDeviceContext, glRenderContext); // Set Vertical Sync - locSwapInterval = OGL_LOAD(locSwapInterval_t, "wglSwapIntervalEXT"); + locSwapInterval = OGL_LOAD(locSwapInterval_t, wglSwapIntervalEXT); if (locSwapInterval && !bVSYNC) locSwapInterval(0); bSync = bVSYNC; #endif @@ -4300,7 +4789,7 @@ namespace olc XGetWindowAttributes(olc_Display, *olc_Window, &gwa); glViewport(0, 0, gwa.width, gwa.height); - locSwapInterval = OGL_LOAD(locSwapInterval_t, "glXSwapIntervalEXT"); + locSwapInterval = OGL_LOAD(locSwapInterval_t, glXSwapIntervalEXT); if (locSwapInterval == nullptr && !bVSYNC) { @@ -4537,7 +5026,14 @@ namespace olc if (nDecalMode == DecalMode::WIREFRAME) glDrawArrays(GL_LINE_LOOP, 0, decal.points); else - glDrawArrays(GL_TRIANGLE_FAN, 0, decal.points); + { + if (decal.structure == olc::DecalStructure::FAN) + glDrawArrays(GL_TRIANGLE_FAN, 0, decal.points); + else if (decal.structure == olc::DecalStructure::STRIP) + glDrawArrays(GL_TRIANGLE_STRIP, 0, decal.points); + else if (decal.structure == olc::DecalStructure::LIST) + glDrawArrays(GL_TRIANGLES, 0, decal.points); + } } uint32_t CreateTexture(const uint32_t width, const uint32_t height, const bool filtered, const bool clamp) override @@ -4865,68 +5361,6 @@ namespace olc // O------------------------------------------------------------------------------O #pragma endregion -#pragma region image_stb -// O------------------------------------------------------------------------------O -// | START IMAGE LOADER: stb_image.h, all systems, very fast | -// O------------------------------------------------------------------------------O -// Thanks to Sean Barrett - https://github.com/nothings/stb/blob/master/stb_image.h -// MIT License - Copyright(c) 2017 Sean Barrett - -// Note you need to download the above file into your project folder, and -// #define OLC_IMAGE_STB -// #define OLC_PGE_APPLICATION -// #include "olcPixelGameEngine.h" - -#if defined(OLC_IMAGE_STB) -#define STB_IMAGE_IMPLEMENTATION -#include "stb_image.h" -namespace olc -{ - class ImageLoader_STB : public olc::ImageLoader - { - public: - ImageLoader_STB() : ImageLoader() - {} - - olc::rcode LoadImageResource(olc::Sprite* spr, const std::string& sImageFile, olc::ResourcePack* pack) override - { - UNUSED(pack); - // clear out existing sprite - spr->pColData.clear(); - // Open file - stbi_uc* bytes = nullptr; - int w = 0, h = 0, cmp = 0; - if (pack != nullptr) - { - ResourceBuffer rb = pack->GetFileBuffer(sImageFile); - bytes = stbi_load_from_memory((unsigned char*)rb.vMemory.data(), rb.vMemory.size(), &w, &h, &cmp, 4); - } - else - { - // Check file exists - if (!_gfs::exists(sImageFile)) return olc::rcode::NO_FILE; - bytes = stbi_load(sImageFile.c_str(), &w, &h, &cmp, 4); - } - - if (!bytes) return olc::rcode::FAIL; - spr->width = w; spr->height = h; - spr->pColData.resize(spr->width * spr->height); - std::memcpy(spr->pColData.data(), bytes, spr->width * spr->height * 4); - delete[] bytes; - return olc::rcode::OK; - } - - olc::rcode SaveImageResource(olc::Sprite* spr, const std::string& sImageFile) override - { - return olc::rcode::OK; - } - }; -} -#endif -// O------------------------------------------------------------------------------O -// | START IMAGE LOADER: stb_image.h | -// O------------------------------------------------------------------------------O -#pragma endregion // O------------------------------------------------------------------------------O // | olcPixelGameEngine Platforms | @@ -4968,6 +5402,8 @@ namespace olc return w; } + + public: virtual olc::rcode ApplicationStartUp() override { return olc::rcode::OK; } virtual olc::rcode ApplicationCleanUp() override { return olc::rcode::OK; } @@ -5034,6 +5470,8 @@ namespace olc olc_hWnd = CreateWindowEx(dwExStyle, olcT("OLC_PIXEL_GAME_ENGINE"), olcT(""), dwStyle, vTopLeft.x, vTopLeft.y, width, height, NULL, NULL, GetModuleHandle(nullptr), this); + DragAcceptFiles(olc_hWnd, true); + // Create Keyboard Mapping mapKeys[0x00] = Key::NONE; mapKeys[0x41] = Key::A; mapKeys[0x42] = Key::B; mapKeys[0x43] = Key::C; mapKeys[0x44] = Key::D; mapKeys[0x45] = Key::E; @@ -5131,6 +5569,44 @@ namespace olc case WM_RBUTTONUP: ptrPGE->olc_UpdateMouseState(1, false); return 0; case WM_MBUTTONDOWN:ptrPGE->olc_UpdateMouseState(2, true); return 0; case WM_MBUTTONUP: ptrPGE->olc_UpdateMouseState(2, false); return 0; + case WM_DROPFILES: + { + // This is all eww... + HDROP drop = (HDROP)wParam; + + uint32_t nFiles = DragQueryFile(drop, 0xFFFFFFFF, nullptr, 0); + std::vector vFiles; + for (uint32_t i = 0; i < nFiles; i++) + { + TCHAR dfbuffer[256]{}; + uint32_t len = DragQueryFile(drop, i, nullptr, 0); + DragQueryFile(drop, i, dfbuffer, 256); +#ifdef UNICODE + #ifdef __MINGW32__ + char* buffer = new char[len + 1]; + wcstombs(buffer, dfbuffer, len); + buffer[len] = '\0'; + #else + int count = WideCharToMultiByte(CP_UTF8, 0, dfbuffer, -1, NULL, 0, NULL, NULL); + char* buffer = new char[count]; + WideCharToMultiByte(CP_UTF8, 0, dfbuffer, -1, buffer, count, NULL, NULL); + #endif + vFiles.push_back(std::string(buffer)); + delete[] buffer; +#else + vFiles.push_back(std::string(dfbuffer)); +#endif + } + + // Even more eww... + POINT p; DragQueryPoint(drop, &p); + ptrPGE->olc_DropFiles(p.x, p.y, vFiles); + DragFinish(drop); + return 0; + } + break; + + case WM_CLOSE: ptrPGE->olc_Terminate(); return 0; case WM_DESTROY: PostQuitMessage(0); DestroyWindow(hWnd); return 0; } @@ -5700,6 +6176,9 @@ namespace olc { #pragma endregion + + + #pragma region platform_emscripten // O------------------------------------------------------------------------------O // | START PLATFORM: Emscripten - Totally Game Changing... | @@ -5836,118 +6315,100 @@ namespace olc // 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;"; + // olc_ApsectRatio + // + // Used by olc_ResizeHandler to calculate the viewport from the + // dimensions of the canvas container's element. + Module.olc_AspectRatio = $0 / $1; + + // HACK ALERT! + // + // Here we assume any html shell that uses 3 or more instance of the class "emscripten" + // is using one of the default or minimal emscripten page layouts + Module.olc_AssumeDefaultShells = (document.querySelectorAll('.emscripten').length >= 3) ? true : false; + + // olc_ResizeHandler + // + // Used by olc_Init, and is called when a resize observer and fullscreenchange event is triggered. + var olc_ResizeHandler = function() + { + // are we in fullscreen mode? + let isFullscreen = (document.fullscreenElement != null); - // width / height = aspect ratio - Module._olc_WindowAspectRatio = $0 / $1; - Module.canvas.parentNode.addEventListener("resize", function(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) + // get the width of the containing element + let width = (isFullscreen) ? window.innerWidth : Module.canvas.parentNode.clientWidth; + let height = (isFullscreen) ? window.innerHeight : Module.canvas.parentNode.clientHeight; + + // calculate the expected viewport size + let viewWidth = width; + let viewHeight = width / Module.olc_AspectRatio; + + // if we're taller than the containing element, recalculate based on height + if(viewHeight > height) { - 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;"; - - Module.canvas.setAttribute("width", viewWidth); - 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"; - Module.canvas.style.top = top.toString() + "px"; - Module.canvas.style.left = left.toString() + "px"; - Module.canvas.style.width = ""; - Module.canvas.style.height = ""; + viewWidth = height * Module.olc_AspectRatio; + viewHeight = height; } + + // ensure resulting viewport is in integer space + viewWidth = parseInt(viewWidth); + viewHeight = parseInt(viewHeight); - // trigger PGE update - Module._olc_PGE_UpdateWindowSize(viewWidth, viewHeight); - // this is really only needed when enter/exiting fullscreen - Module.canvas.focus(); - // prevent this event from ever affecting the document beyond this element - e.stopPropagation(); - }); - - // helper function to prevent repeating the same code everywhere - Module._olc_ResizeCanvas = function() - { - // yes, we still have to wait, sigh.. setTimeout(function() { - // if default template, stretch width as well - if (Module.canvas.parentNode.className == 'emscripten_border') - Module.canvas.parentNode.style.cssText = Module._olc_EmscriptenShellCss; - - // override it's styling so we can get it's stretched size - Module.canvas.style.cssText = "width: 100%; height: 100%; outline: none;"; - - // setup custom resize event - var resizeEvent = new CustomEvent('resize', - { - detail: { - width: Module.canvas.clientWidth, - height : Module.canvas.clientHeight - }, - bubbles : true, - cancelable : true - }); - - // trigger custom resize event on canvas element - Module.canvas.dispatchEvent(resizeEvent); - }, 50); + // if default shells, apply default styles + if(Module.olc_AssumeDefaultShells) + Module.canvas.parentNode.setAttribute('style', 'width: 100%; height: 70vh; margin-left: auto; margin-right: auto;'); + + // apply viewport dimensions to teh canvas + Module.canvas.setAttribute('width', viewWidth); + Module.canvas.setAttribute('height', viewHeight); + Module.canvas.setAttribute('style', `width: ${viewWidth}px; height: ${viewHeight}px;`); + + // update the PGE window size + Module._olc_PGE_UpdateWindowSize(viewWidth, viewHeight); + + // force focus on our PGE canvas + Module.canvas.focus(); + }, 200); }; - - // Disable Refresh Gesture on mobile - document.body.style.cssText += " overscroll-behavior-y: contain;"; - - if (Module.canvas.parentNode.className == 'emscripten_border') + + // olc_Init + // + // set up resize observer and fullscreenchange event handler + var olc_Init = function() { - // force body to have no margin in emscripten's minimal shell - document.body.style.margin = "0"; - Module.canvas.parentNode.style.cssText = Module._olc_EmscriptenShellCss; - } - - Module._olc_ResizeCanvas(); + if(Module.olc_AspectRatio === undefined) + { + setTimeout(function() { Module.olc_Init(); }, 50); + return; + } + + let resizeObserver = new ResizeObserver(function(entries) + { + Module.olc_ResizeHandler(); + }).observe(Module.canvas.parentNode); - // observe and react to resizing of the container element - var resizeObserver = new ResizeObserver(function(entries) {Module._olc_ResizeCanvas();}).observe(Module.canvas.parentNode); + let mutationObserver = new MutationObserver(function(mutationsList, observer) + { + setTimeout(function() { Module.olc_ResizeHandler(); }, 200); + }).observe(Module.canvas.parentNode, { attributes: false, childList: true, subtree: false }); - // observe and react to changes that occur when entering/exiting fullscreen - var mutationObserver = new MutationObserver(function(mutationsList, observer) - { - // a change has occurred, let's check them out! - for (var i = 0; i < mutationsList.length; i++) + window.addEventListener('fullscreenchange', function(e) { - // cycle through all of the newly added elements - for (var j = 0; j < mutationsList[i].addedNodes.length; j++) - { - // if this element is a our canvas, trigger resize - if (mutationsList[i].addedNodes[j].id == 'canvas') - Module._olc_ResizeCanvas(); - } - } - }).observe(Module.canvas.parentNode, - { - attributes: false, - childList : true, - subtree : false - }); + setTimeout(function() { Module.olc_ResizeHandler();}, 200); + }); + }; + + // set up hooks + Module.olc_ResizeHandler = (Module.olc_ResizeHandler != undefined) ? Module.olc_ResizeHandler : olc_ResizeHandler; + Module.olc_Init = (Module.olc_Init != undefined) ? Module.olc_Init : olc_Init; - // add resize listener on window - window.addEventListener("resize", function(e) { Module._olc_ResizeCanvas(); }); + // run everything! + Module.olc_Init(); }, vWindowSize.x, vWindowSize.y); // Fullscreen and Resize Observers #pragma warning restore format @@ -6157,7 +6618,9 @@ namespace olc void PixelGameEngine::olc_ConfigureSystem() { -#if !defined(OLC_PGE_HEADLESS) +//#if !defined(OLC_PGE_HEADLESS) + + olc::Sprite::loader = nullptr; #if defined(OLC_IMAGE_GDI) olc::Sprite::loader = std::make_unique(); @@ -6176,7 +6639,9 @@ namespace olc #endif - +#if defined(OLC_PLATFORM_HEADLESS) + platform = std::make_unique(); +#endif #if defined(OLC_PLATFORM_WINAPI) platform = std::make_unique(); @@ -6198,7 +6663,9 @@ namespace olc platform = std::make_unique(); #endif - +#if defined(OLC_GFX_HEADLESS) + renderer = std::make_unique(); +#endif #if defined(OLC_GFX_OPENGL10) renderer = std::make_unique(); @@ -6227,11 +6694,11 @@ namespace olc // Associate components with PGE instance platform->ptrPGE = this; renderer->ptrPGE = this; -#else - olc::Sprite::loader = nullptr; - platform = nullptr; - renderer = nullptr; -#endif +//#else +// olc::Sprite::loader = nullptr; +// platform = nullptr; +// renderer = nullptr; +//#endif } } @@ -6242,4 +6709,3 @@ namespace olc // O------------------------------------------------------------------------------O // | END OF OLC_PGE_APPLICATION | // O------------------------------------------------------------------------------O - diff --git a/pixelGameEngine.o b/pixelGameEngine.o index 038d93c..4f5be2d 100644 Binary files a/pixelGameEngine.o and b/pixelGameEngine.o differ diff --git a/sig b/sig index 5cc1e85..b29b259 100755 --- a/sig +++ b/sig @@ -3,7 +3,7 @@ export AUTO_UPDATE=true source utils/define.sh define PROJECT_NAME "C++ProjectTemplate" -define CUSTOM_PARAMS "-std=c++17 -lX11 -lpthread -lpng -lstdc++fs -I/usr/include/lua5.3" +define CUSTOM_PARAMS "-std=c++17 -lX11 -lGL -lpthread -lpng -lstdc++fs -I/usr/include/lua5.3" define LANGUAGE "C++" source utils/main.sh