aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.cpp115
-rw-r--r--Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.h3
-rw-r--r--Minecraft.Client/Screen.cpp69
-rw-r--r--Minecraft.Client/Windows64/KeyboardMouseInput.cpp23
-rw-r--r--Minecraft.Client/Windows64/KeyboardMouseInput.h12
-rw-r--r--Minecraft.Client/Windows64/Windows64_Minecraft.cpp14
-rw-r--r--Minecraft.Client/stdafx.h1
-rw-r--r--Minecraft.Client/stubs.cpp41
-rw-r--r--Minecraft.Client/stubs.h12
-rw-r--r--README.md6
10 files changed, 284 insertions, 12 deletions
diff --git a/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.cpp b/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.cpp
index a1bd8270..942009d7 100644
--- a/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.cpp
+++ b/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.cpp
@@ -5,6 +5,9 @@
#include "..\..\..\Minecraft.World\net.minecraft.world.inventory.h"
#include "..\..\..\Minecraft.World\net.minecraft.world.item.h"
#include "..\..\MultiplayerLocalPlayer.h"
+#ifdef _WINDOWS64
+#include "..\..\Windows64\KeyboardMouseInput.h"
+#endif
UIScene_AbstractContainerMenu::UIScene_AbstractContainerMenu(int iPad, UILayer *parentLayer) : UIScene(iPad, parentLayer)
{
@@ -25,6 +28,9 @@ UIScene_AbstractContainerMenu::UIScene_AbstractContainerMenu(int iPad, UILayer *
ui.OverrideSFX(m_iPad,ACTION_MENU_DOWN,true);
m_bIgnoreInput=false;
+#ifdef _WINDOWS64
+ m_bMouseDragSlider=false;
+#endif
}
UIScene_AbstractContainerMenu::~UIScene_AbstractContainerMenu()
@@ -106,8 +112,8 @@ void UIScene_AbstractContainerMenu::PlatformInitialize(int iPad, int startIndex)
#ifdef __ORBIS__
// we need to map the touchpad rectangle to the UI rectangle. While it works great for the creative menu, it is much too sensitive for the smaller menus.
//X coordinate of the touch point (0 to 1919)
- //Y coordinate of the touch point (0 to 941: DUALSHOCK®4 wireless controllers and the CUH-ZCT1J/CAP-ZCT1J/CAP-ZCT1U controllers for the PlayStation®4 development tool,
- //0 to 753: JDX-1000x series controllers for the PlayStation®4 development tool,)
+ //Y coordinate of the touch point (0 to 941: DUALSHOCK�4 wireless controllers and the CUH-ZCT1J/CAP-ZCT1J/CAP-ZCT1U controllers for the PlayStation�4 development tool,
+ //0 to 753: JDX-1000x series controllers for the PlayStation�4 development tool,)
m_fTouchPadMulX=fPanelWidth/1919.0f;
m_fTouchPadMulY=fPanelHeight/941.0f;
m_fTouchPadDeadZoneX=15.0f*m_fTouchPadMulX;
@@ -173,13 +179,118 @@ void UIScene_AbstractContainerMenu::tick()
{
UIScene::tick();
+#ifdef _WINDOWS64
+ bool mouseActive = (m_iPad == 0 && !KMInput.IsCaptured());
+ float rawMouseMovieX = 0, rawMouseMovieY = 0;
+ // Map Windows mouse position to the virtual pointer in movie coordinates
+ if (mouseActive)
+ {
+ RECT clientRect;
+ GetClientRect(KMInput.GetHWnd(), &clientRect);
+ int clientWidth = clientRect.right;
+ int clientHeight = clientRect.bottom;
+ if (clientWidth > 0 && clientHeight > 0)
+ {
+ int mouseX = KMInput.GetMouseX();
+ int mouseY = KMInput.GetMouseY();
+
+ // Convert mouse position to movie coordinates using the movie/client ratio
+ float mx = (float)mouseX * ((float)m_movieWidth / (float)clientWidth);
+ float my = (float)mouseY * ((float)m_movieHeight / (float)clientHeight);
+
+ m_pointerPos.x = mx;
+ m_pointerPos.y = my;
+ rawMouseMovieX = mx;
+ rawMouseMovieY = my;
+ }
+ }
+#endif
+
onMouseTick();
+#ifdef _WINDOWS64
+ // Dispatch mouse clicks AFTER onMouseTick() has updated m_eCurrSection from the new pointer position
+ if (mouseActive)
+ {
+ if (KMInput.ConsumeMousePress(0))
+ {
+ if (m_eCurrSection == eSectionInventoryCreativeSlider)
+ {
+ // Scrollbar click: use raw mouse position (onMouseTick may have snapped m_pointerPos)
+ m_bMouseDragSlider = true;
+ m_pointerPos.x = rawMouseMovieX;
+ m_pointerPos.y = rawMouseMovieY;
+ handleOtherClicked(m_iPad, eSectionInventoryCreativeSlider, 0, false);
+ }
+ else
+ {
+ handleKeyDown(m_iPad, ACTION_MENU_A, false);
+ }
+ }
+ else if (m_bMouseDragSlider && KMInput.IsMouseDown(0))
+ {
+ // Continue scrollbar drag: update scroll position from current mouse Y
+ m_pointerPos.x = rawMouseMovieX;
+ m_pointerPos.y = rawMouseMovieY;
+ handleOtherClicked(m_iPad, eSectionInventoryCreativeSlider, 0, false);
+ }
+
+ if (!KMInput.IsMouseDown(0))
+ m_bMouseDragSlider = false;
+
+ if (KMInput.ConsumeMousePress(1))
+ {
+ handleKeyDown(m_iPad, ACTION_MENU_X, false);
+ }
+ if (KMInput.ConsumeMousePress(2))
+ {
+ handleKeyDown(m_iPad, ACTION_MENU_Y, false);
+ }
+
+ // Mouse scroll wheel for tab switching
+ int scrollDelta = KMInput.ConsumeScrollDelta();
+ if (scrollDelta > 0)
+ {
+ handleKeyDown(m_iPad, ACTION_MENU_LEFT_SCROLL, false);
+ }
+ else if (scrollDelta < 0)
+ {
+ handleKeyDown(m_iPad, ACTION_MENU_RIGHT_SCROLL, false);
+ }
+
+ // ESC to close — must be last since it may destroy this scene
+ if (KMInput.ConsumeKeyPress(VK_ESCAPE))
+ {
+ handleKeyDown(m_iPad, ACTION_MENU_B, false);
+ return;
+ }
+ }
+#endif
+
IggyEvent mouseEvent;
S32 width, height;
m_parentLayer->getRenderDimensions(width, height);
+
+#ifdef _WINDOWS64
+ S32 x, y;
+ if (mouseActive)
+ {
+ // Send raw mouse position directly as Iggy event to avoid coordinate round-trip errors
+ // Scale mouse client coords to the Iggy display space (which was set to getRenderDimensions())
+ RECT clientRect;
+ GetClientRect(KMInput.GetHWnd(), &clientRect);
+ x = (S32)((float)KMInput.GetMouseX() * ((float)width / (float)clientRect.right));
+ y = (S32)((float)KMInput.GetMouseY() * ((float)height / (float)clientRect.bottom));
+ }
+ else
+ {
+ x = (S32)(m_pointerPos.x * ((float)width / m_movieWidth));
+ y = (S32)(m_pointerPos.y * ((float)height / m_movieHeight));
+ }
+#else
S32 x = m_pointerPos.x*((float)width/m_movieWidth);
S32 y = m_pointerPos.y*((float)height/m_movieHeight);
+#endif
IggyMakeEventMouseMove( &mouseEvent, x, y);
// 4J Stu - This seems to be broken on Durango, so do it ourself
diff --git a/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.h b/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.h
index b98b3763..26688dc5 100644
--- a/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.h
+++ b/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.h
@@ -10,6 +10,9 @@ class UIScene_AbstractContainerMenu : public UIScene, public virtual IUIScene_Ab
private:
ESceneSection m_focusSection;
bool m_bIgnoreInput;
+#ifdef _WINDOWS64
+ bool m_bMouseDragSlider;
+#endif
protected:
UIControl m_controlMainPanel;
diff --git a/Minecraft.Client/Screen.cpp b/Minecraft.Client/Screen.cpp
index 0019b54d..6a402b04 100644
--- a/Minecraft.Client/Screen.cpp
+++ b/Minecraft.Client/Screen.cpp
@@ -5,6 +5,9 @@
#include "Tesselator.h"
#include "Textures.h"
#include "..\Minecraft.World\SoundTypes.h"
+#ifdef _WINDOWS64
+#include "Windows64\KeyboardMouseInput.h"
+#endif
@@ -103,20 +106,71 @@ void Screen::init()
void Screen::updateEvents()
{
+#ifdef _WINDOWS64
+ // Poll mouse button state and dispatch click/release events
+ for (int btn = 0; btn < 3; btn++)
+ {
+ if (KMInput.ConsumeMousePress(btn))
+ {
+ int xm = Mouse::getX() * width / minecraft->width;
+ int ym = height - Mouse::getY() * height / minecraft->height - 1;
+ mouseClicked(xm, ym, btn);
+ }
+ if (KMInput.ConsumeMouseRelease(btn))
+ {
+ int xm = Mouse::getX() * width / minecraft->width;
+ int ym = height - Mouse::getY() * height / minecraft->height - 1;
+ mouseReleased(xm, ym, btn);
+ }
+ }
+
+ // Poll keyboard events
+ for (int vk = 0; vk < 256; vk++)
+ {
+ if (KMInput.ConsumeKeyPress(vk))
+ {
+ // Map Windows virtual key to the Keyboard constants used by Screen::keyPressed
+ int mappedKey = -1;
+ wchar_t ch = 0;
+ if (vk == VK_ESCAPE) mappedKey = Keyboard::KEY_ESCAPE;
+ else if (vk == VK_RETURN) mappedKey = Keyboard::KEY_RETURN;
+ else if (vk == VK_BACK) mappedKey = Keyboard::KEY_BACK;
+ else if (vk == VK_UP) mappedKey = Keyboard::KEY_UP;
+ else if (vk == VK_DOWN) mappedKey = Keyboard::KEY_DOWN;
+ else if (vk == VK_LEFT) mappedKey = Keyboard::KEY_LEFT;
+ else if (vk == VK_RIGHT) mappedKey = Keyboard::KEY_RIGHT;
+ else if (vk == VK_LSHIFT || vk == VK_RSHIFT) mappedKey = Keyboard::KEY_LSHIFT;
+ else if (vk == VK_TAB) mappedKey = Keyboard::KEY_TAB;
+ else if (vk >= 'A' && vk <= 'Z')
+ {
+ ch = (wchar_t)(vk - 'A' + L'a');
+ if (KMInput.IsKeyDown(VK_SHIFT)) ch = (wchar_t)vk;
+ }
+ else if (vk >= '0' && vk <= '9') ch = (wchar_t)vk;
+ else if (vk == VK_SPACE) ch = L' ';
+
+ if (mappedKey != -1) keyPressed(ch, mappedKey);
+ else if (ch != 0) keyPressed(ch, -1);
+ }
+ }
+#else
/* 4J - TODO
- while (Mouse.next()) {
- mouseEvent();
- }
+ while (Mouse.next()) {
+ mouseEvent();
+ }
- while (Keyboard.next()) {
- keyboardEvent();
- }
+ while (Keyboard.next()) {
+ keyboardEvent();
+ }
*/
-
+#endif
}
void Screen::mouseEvent()
{
+#ifdef _WINDOWS64
+ // Mouse event dispatching is handled directly in updateEvents() for Windows
+#else
/* 4J - TODO
if (Mouse.getEventButtonState()) {
int xm = Mouse.getEventX() * width / minecraft.width;
@@ -128,6 +182,7 @@ void Screen::mouseEvent()
mouseReleased(xm, ym, Mouse.getEventButton());
}
*/
+#endif
}
void Screen::keyboardEvent()
diff --git a/Minecraft.Client/Windows64/KeyboardMouseInput.cpp b/Minecraft.Client/Windows64/KeyboardMouseInput.cpp
index 791eb272..fc763394 100644
--- a/Minecraft.Client/Windows64/KeyboardMouseInput.cpp
+++ b/Minecraft.Client/Windows64/KeyboardMouseInput.cpp
@@ -13,6 +13,8 @@ KeyboardMouseInput::KeyboardMouseInput()
, m_captured(false)
, m_hWnd(NULL)
, m_initialized(false)
+ , m_mouseX(0)
+ , m_mouseY(0)
{
memset(m_keyState, 0, sizeof(m_keyState));
memset(m_keyStatePrev, 0, sizeof(m_keyStatePrev));
@@ -20,6 +22,7 @@ KeyboardMouseInput::KeyboardMouseInput()
memset(m_mouseButtonsPrev, 0, sizeof(m_mouseButtonsPrev));
memset(m_keyPressedAccum, 0, sizeof(m_keyPressedAccum));
memset(m_mousePressedAccum, 0, sizeof(m_mousePressedAccum));
+ memset(m_mouseReleasedAccum, 0, sizeof(m_mouseReleasedAccum));
}
KeyboardMouseInput::~KeyboardMouseInput()
@@ -103,6 +106,7 @@ void KeyboardMouseInput::OnMouseButton(int button, bool down)
if (button >= 0 && button < 3)
{
if (down && !m_mouseButtons[button]) m_mousePressedAccum[button] = true;
+ if (!down && m_mouseButtons[button]) m_mouseReleasedAccum[button] = true;
m_mouseButtons[button] = down;
}
}
@@ -112,12 +116,23 @@ void KeyboardMouseInput::OnMouseWheel(int delta)
m_scrollDeltaAccum += delta;
}
+void KeyboardMouseInput::OnMouseMove(int x, int y)
+{
+ m_mouseX = x;
+ m_mouseY = y;
+}
+
+int KeyboardMouseInput::GetMouseX() const { return m_mouseX; }
+int KeyboardMouseInput::GetMouseY() const { return m_mouseY; }
+HWND KeyboardMouseInput::GetHWnd() const { return m_hWnd; }
+
void KeyboardMouseInput::ClearAllState()
{
memset(m_keyState, 0, sizeof(m_keyState));
memset(m_mouseButtons, 0, sizeof(m_mouseButtons));
memset(m_keyPressedAccum, 0, sizeof(m_keyPressedAccum));
memset(m_mousePressedAccum, 0, sizeof(m_mousePressedAccum));
+ memset(m_mouseReleasedAccum, 0, sizeof(m_mouseReleasedAccum));
m_mouseDeltaXAccum = 0.0f;
m_mouseDeltaYAccum = 0.0f;
m_scrollDeltaAccum = 0;
@@ -178,6 +193,14 @@ bool KeyboardMouseInput::ConsumeMousePress(int btn)
return pressed;
}
+bool KeyboardMouseInput::ConsumeMouseRelease(int btn)
+{
+ if (btn < 0 || btn >= 3) return false;
+ bool released = m_mouseReleasedAccum[btn];
+ m_mouseReleasedAccum[btn] = false;
+ return released;
+}
+
void KeyboardMouseInput::ConsumeMouseDelta(float &dx, float &dy)
{
dx = m_mouseDeltaXAccum;
diff --git a/Minecraft.Client/Windows64/KeyboardMouseInput.h b/Minecraft.Client/Windows64/KeyboardMouseInput.h
index 4d272f91..a09843f9 100644
--- a/Minecraft.Client/Windows64/KeyboardMouseInput.h
+++ b/Minecraft.Client/Windows64/KeyboardMouseInput.h
@@ -42,9 +42,16 @@ public:
// Use these from code that runs at game tick rate (20Hz).
bool ConsumeKeyPress(int vk);
bool ConsumeMousePress(int btn);
+ bool ConsumeMouseRelease(int btn);
void ConsumeMouseDelta(float &dx, float &dy);
int ConsumeScrollDelta();
+ // Absolute cursor position (client-area coordinates, for GUI when not captured)
+ void OnMouseMove(int x, int y);
+ int GetMouseX() const;
+ int GetMouseY() const;
+ HWND GetHWnd() const;
+
// Mouse capture for FPS look
void SetCapture(bool capture);
bool IsCaptured() const;
@@ -61,6 +68,7 @@ private:
// Sticky press accumulators (persist until consumed by game tick)
bool m_keyPressedAccum[256];
bool m_mousePressedAccum[3];
+ bool m_mouseReleasedAccum[3];
// Mouse delta accumulators (persist until consumed by game tick)
float m_mouseDeltaXAccum;
@@ -72,6 +80,10 @@ private:
bool m_captured;
HWND m_hWnd;
bool m_initialized;
+
+ // Absolute cursor position in client coordinates
+ int m_mouseX;
+ int m_mouseY;
};
extern KeyboardMouseInput KMInput;
diff --git a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp
index 6c6cec15..931e7f17 100644
--- a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp
+++ b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp
@@ -395,6 +395,9 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
case WM_MOUSEWHEEL:
KMInput.OnMouseWheel(GET_WHEEL_DELTA_WPARAM(wParam));
break;
+ case WM_MOUSEMOVE:
+ KMInput.OnMouseMove(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+ break;
case WM_ACTIVATE:
if (LOWORD(wParam) == WA_INACTIVE)
KMInput.SetCapture(false);
@@ -404,6 +407,15 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
KMInput.ClearAllState();
break;
+ case WM_SETCURSOR:
+ // Hide the OS cursor when an Iggy/Flash menu is displayed (it has its own Flash cursor)
+ if (LOWORD(lParam) == HTCLIENT && !KMInput.IsCaptured() && ui.GetMenuDisplayed(0))
+ {
+ SetCursor(NULL);
+ return TRUE;
+ }
+ return DefWindowProc(hWnd, message, wParam, lParam);
+
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
@@ -1184,7 +1196,7 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
// Update mouse capture: capture when in-game and no menu is open
{
static bool altToggleSuppressCapture = false;
- bool shouldCapture = app.GetGameStarted() && !ui.GetMenuDisplayed(0);
+ bool shouldCapture = app.GetGameStarted() && !ui.GetMenuDisplayed(0) && pMinecraft->screen == NULL;
// Left Alt key toggles capture on/off for debugging
if (KMInput.IsKeyPressed(VK_MENU))
{
diff --git a/Minecraft.Client/stdafx.h b/Minecraft.Client/stdafx.h
index 60cd4667..4ae4250e 100644
--- a/Minecraft.Client/stdafx.h
+++ b/Minecraft.Client/stdafx.h
@@ -66,6 +66,7 @@ typedef unsigned __int64 __uint64;
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files:
#include <windows.h>
+#include <windowsx.h>
#include <malloc.h>
#include <tchar.h>
// TODO: reference additional headers your program requires here
diff --git a/Minecraft.Client/stubs.cpp b/Minecraft.Client/stubs.cpp
index 0c7e680a..16215ba2 100644
--- a/Minecraft.Client/stubs.cpp
+++ b/Minecraft.Client/stubs.cpp
@@ -1,5 +1,46 @@
#include "stdafx.h"
+#ifdef _WINDOWS64
+#include "Windows64\KeyboardMouseInput.h"
+
+int Mouse::getX()
+{
+ return KMInput.GetMouseX();
+}
+
+int Mouse::getY()
+{
+ // Return Y in bottom-up coordinates (OpenGL convention, matching original Java LWJGL Mouse)
+ RECT rect;
+ GetClientRect(KMInput.GetHWnd(), &rect);
+ return (rect.bottom - 1) - KMInput.GetMouseY();
+}
+
+bool Mouse::isButtonDown(int button)
+{
+ return KMInput.IsMouseDown(button);
+}
+
+bool Keyboard::isKeyDown(int key)
+{
+ // Map Keyboard constants to Windows virtual key codes
+ if (key == Keyboard::KEY_LSHIFT) return KMInput.IsKeyDown(VK_LSHIFT);
+ if (key == Keyboard::KEY_RSHIFT) return KMInput.IsKeyDown(VK_RSHIFT);
+ if (key == Keyboard::KEY_ESCAPE) return KMInput.IsKeyDown(VK_ESCAPE);
+ if (key == Keyboard::KEY_RETURN) return KMInput.IsKeyDown(VK_RETURN);
+ if (key == Keyboard::KEY_BACK) return KMInput.IsKeyDown(VK_BACK);
+ if (key == Keyboard::KEY_SPACE) return KMInput.IsKeyDown(VK_SPACE);
+ if (key == Keyboard::KEY_TAB) return KMInput.IsKeyDown(VK_TAB);
+ if (key == Keyboard::KEY_UP) return KMInput.IsKeyDown(VK_UP);
+ if (key == Keyboard::KEY_DOWN) return KMInput.IsKeyDown(VK_DOWN);
+ if (key == Keyboard::KEY_LEFT) return KMInput.IsKeyDown(VK_LEFT);
+ if (key == Keyboard::KEY_RIGHT) return KMInput.IsKeyDown(VK_RIGHT);
+ if (key >= Keyboard::KEY_A && key <= Keyboard::KEY_Z)
+ return KMInput.IsKeyDown('A' + (key - Keyboard::KEY_A));
+ return false;
+}
+#endif
+
void glReadPixels(int,int, int, int, int, int, ByteBuffer *)
{
}
diff --git a/Minecraft.Client/stubs.h b/Minecraft.Client/stubs.h
index f9196e20..cc788867 100644
--- a/Minecraft.Client/stubs.h
+++ b/Minecraft.Client/stubs.h
@@ -186,7 +186,11 @@ class Keyboard
public:
static void create() {}
static void destroy() {}
+#ifdef _WINDOWS64
+ static bool isKeyDown(int key);
+#else
static bool isKeyDown(int) {return false;}
+#endif
static wstring getKeyName(int) { return L"KEYNAME"; }
static void enableRepeatEvents(bool) {}
static const int KEY_A = 0;
@@ -224,6 +228,8 @@ public:
static const int KEY_UP = 32;
static const int KEY_DOWN = 33;
static const int KEY_TAB = 34;
+ static const int KEY_LEFT = 35;
+ static const int KEY_RIGHT = 36;
};
class Mouse
@@ -231,9 +237,15 @@ class Mouse
public:
static void create() {}
static void destroy() {}
+#ifdef _WINDOWS64
+ static int getX();
+ static int getY();
+ static bool isButtonDown(int button);
+#else
static int getX() { return 0; }
static int getY() { return 0; }
static bool isButtonDown(int) { return false; }
+#endif
};
class Display
diff --git a/README.md b/README.md
index e9af7d0f..279f7051 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,7 @@
# MinecraftConsoles
+[![Discord](https://img.shields.io/badge/Discord-Join%20Server-5865F2?logo=discord&logoColor=white)](https://discord.gg/5CSzhc9t)
+
![img.png](img.png)
## Introduction
@@ -20,9 +22,9 @@ This project contains the source code of Minecraft Legacy Console Edition v1.3.0
2. Clone the repository
3. Open the project by double-clicking `MinecraftConsoles.sln`
4. Make sure `Minecraft.Client` is set as the Startup Project
-5. Set the build configuration to **Debug** or **Release** and the target platform to **Windows64**, then build and run
+5. Set the build configuration to **Debug** (Release is also OK but has some bugs) and the target platform to **Windows64**, then build and run
## Known Issues
- Builds for other platforms have not been tested and are most likely non-functional
-- Other unknown issues may exist \ No newline at end of file
+- There are some render bugs in the Release mode build