diff --git a/.gitignore b/.gitignore index b266fac93..86c4ba55b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,23 +1,413 @@ -# Visual Studio -.vs/ -*.user +# Created by https://www.toptal.com/developers/gitignore/api/visualstudio +# Edit at https://www.toptal.com/developers/gitignore?templates=visualstudio + +### VisualStudio ### +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +# User-specific files +*.rsuser *.suo -*.sdf +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb *.opensdf +*.sdf +*.cachefile *.VC.db *.VC.VC.opendb -# Source control binding files -*.vspscc -*.vssscc +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap -# Build output -x64/ -x86/ -Debug/ -Release/ +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml + +### VisualStudio Patch ### +# Additional files built by Visual Studio + +# End of https://www.toptal.com/developers/gitignore/api/visualstudio + +enc_temp_folder/ # Game data / assets +Minecraft.Client/Schematics/ Minecraft.Client/Windows64/GameHDD/ # Intermediate build files (per-project) @@ -28,19 +418,3 @@ Minecraft.World/x64/ Minecraft.World/x64_Debug/ Minecraft.World/Debug/ Minecraft.World/Release/ - -# Compiled artifacts -*.exe -*.dll -*.lib -*.pdb -*.pch -*.ilk -*.exp -*.obj -*.idb -*.ipdb -*.iobj - -# Precompiled headers -*.gch diff --git a/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.cpp b/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.cpp index a1bd8270e..942009d7f 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 b98b37637..26688dc57 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 0019b54d4..6a402b04c 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/Iggy/gdraw/gdraw_d3d1x_shared.inl b/Minecraft.Client/Windows64/Iggy/gdraw/gdraw_d3d1x_shared.inl index 1ab1f13f7..e827cd823 100644 --- a/Minecraft.Client/Windows64/Iggy/gdraw/gdraw_d3d1x_shared.inl +++ b/Minecraft.Client/Windows64/Iggy/gdraw/gdraw_d3d1x_shared.inl @@ -502,7 +502,7 @@ static GDrawTexture * RADLINK gdraw_MakeTextureEnd(GDraw_MakeTexture_ProcessingI } // actually create texture - D3D1X_(TEXTURE2D_DESC) desc = { w, h, nmips, 1, (DXGI_FORMAT) p->i3, { 1, 0 }, + D3D1X_(TEXTURE2D_DESC) desc = { static_cast(w), static_cast(h), static_cast(nmips), 1, static_cast(p->i3), { 1, 0 }, (p->i2 & GDRAW_MAKETEXTURE_FLAGS_updatable) ? D3D1X_(USAGE_DEFAULT) : D3D1X_(USAGE_IMMUTABLE), D3D1X_(BIND_SHADER_RESOURCE), 0, 0 }; @@ -541,7 +541,7 @@ static rrbool RADLINK gdraw_UpdateTextureBegin(GDrawTexture *t, void *unique_id, static void RADLINK gdraw_UpdateTextureRect(GDrawTexture *t, void * /*unique_id*/, S32 x, S32 y, S32 stride, S32 w, S32 h, U8 *samples, gdraw_texture_format /*format*/) { GDrawHandle *s = (GDrawHandle *) t; - D3D1X_(BOX) box = { x, y, 0, x+w, y+h, 1 }; + D3D1X_(BOX) box = { static_cast(x), static_cast(y), 0U, static_cast(x + w), static_cast(y + h), 1U }; gdraw->d3d_context->UpdateSubresource(s->handle.tex.d3d, 0, &box, samples, stride, 0); } @@ -586,8 +586,8 @@ static void RADLINK gdraw_SetAntialiasTexture(S32 width, U8 *rgba) safe_release(gdraw->aa_tex_view); safe_release(gdraw->aa_tex); - D3D1X_(TEXTURE2D_DESC) desc = { width, 1, 1, 1, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D1X_(USAGE_IMMUTABLE), D3D1X_(BIND_SHADER_RESOURCE), 0, 0 }; - D3D1X_(SUBRESOURCE_DATA) data = { rgba, width*4, 0 }; + D3D1X_(TEXTURE2D_DESC) desc = { static_cast(width), 1U, 1U, 1U, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, D3D1X_(USAGE_IMMUTABLE), D3D1X_(BIND_SHADER_RESOURCE), 0U, 0U }; + D3D1X_(SUBRESOURCE_DATA) data = { rgba, static_cast(width) * 4U, 0U }; hr = gdraw->d3d_device->CreateTexture2D(&desc, &data, &gdraw->aa_tex); if (FAILED(hr)) { @@ -646,10 +646,10 @@ static GDrawVertexBuffer * RADLINK gdraw_MakeVertexBufferEnd(GDraw_MakeVertexBuf GDrawHandle *vb = (GDrawHandle *) p->p0; HRESULT hr; - D3D1X_(BUFFER_DESC) vbdesc = { p->vertex_data_length, D3D1X_(USAGE_IMMUTABLE), D3D1X_(BIND_VERTEX_BUFFER), 0, 0 }; + D3D1X_(BUFFER_DESC) vbdesc = { static_cast(p->vertex_data_length), D3D1X_(USAGE_IMMUTABLE), D3D1X_(BIND_VERTEX_BUFFER), 0U, 0U }; D3D1X_(SUBRESOURCE_DATA) vbdata = { p->vertex_data, 0, 0 }; - D3D1X_(BUFFER_DESC) ibdesc = { p->index_data_length, D3D1X_(USAGE_IMMUTABLE), D3D1X_(BIND_INDEX_BUFFER), 0, 0 }; + D3D1X_(BUFFER_DESC) ibdesc = { static_cast(p->index_data_length), D3D1X_(USAGE_IMMUTABLE), D3D1X_(BIND_INDEX_BUFFER), 0U, 0U }; D3D1X_(SUBRESOURCE_DATA) ibdata = { p->index_data, 0, 0 }; hr = gdraw->d3d_device->CreateBuffer(&vbdesc, &vbdata, &vb->handle.vbuf.verts); @@ -722,8 +722,8 @@ static GDrawHandle *get_color_rendertarget(GDrawStats *stats) return t; } - D3D1X_(TEXTURE2D_DESC) desc = { gdraw->frametex_width, gdraw->frametex_height, 1, 1, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, - D3D1X_(USAGE_DEFAULT), D3D1X_(BIND_SHADER_RESOURCE) | D3D1X_(BIND_RENDER_TARGET), 0, 0 }; + D3D1X_(TEXTURE2D_DESC) desc = { static_cast(gdraw->frametex_width), static_cast(gdraw->frametex_height), 1U, 1U, DXGI_FORMAT_R8G8B8A8_UNORM, { 1, 0 }, + D3D1X_(USAGE_DEFAULT), D3D1X_(BIND_SHADER_RESOURCE) | D3D1X_(BIND_RENDER_TARGET), 0U, 0U }; t->handle.tex.d3d = NULL; t->handle.tex.d3d_view = NULL; @@ -765,8 +765,8 @@ static ID3D1X(DepthStencilView) *get_rendertarget_depthbuffer(GDrawStats *stats) char *failed_call; assert(!gdraw->rt_depth_buffer); - D3D1X_(TEXTURE2D_DESC) desc = { gdraw->frametex_width, gdraw->frametex_height, 1, 1, DXGI_FORMAT_D24_UNORM_S8_UINT, { 1, 0 }, - D3D1X_(USAGE_DEFAULT), D3D1X_(BIND_DEPTH_STENCIL), 0, 0 }; + D3D1X_(TEXTURE2D_DESC) desc = { static_cast(gdraw->frametex_width), static_cast(gdraw->frametex_height), 1U, 1U, DXGI_FORMAT_D24_UNORM_S8_UINT, { 1, 0 }, + D3D1X_(USAGE_DEFAULT), D3D1X_(BIND_DEPTH_STENCIL), 0U, 0U }; HRESULT hr = gdraw->d3d_device->CreateTexture2D(&desc, NULL, &gdraw->rt_depth_buffer); failed_call = "CreateTexture2D"; @@ -2399,8 +2399,8 @@ GDrawTexture * RADLINK gdraw_D3D1X_(MakeTextureFromResource)(U8 *resource_file, mipmaps = texture->mipmaps; blk = 1; - D3D1X_(TEXTURE2D_DESC) desc = { width, height, mipmaps, 1, DXGI_FORMAT_UNKNOWN, { 1, 0 }, - D3D1X_(USAGE_IMMUTABLE), D3D1X_(BIND_SHADER_RESOURCE), 0, 0 }; + D3D1X_(TEXTURE2D_DESC) desc = { static_cast(width), static_cast(height), static_cast(mipmaps), 1U, DXGI_FORMAT_UNKNOWN, { 1, 0 }, + D3D1X_(USAGE_IMMUTABLE), D3D1X_(BIND_SHADER_RESOURCE), 0U, 0U }; switch (texture->format) { case IFT_FORMAT_rgba_8888 : size= 4; d3dfmt = DXGI_FORMAT_R8G8B8A8_UNORM; break; diff --git a/Minecraft.Client/Windows64/KeyboardMouseInput.cpp b/Minecraft.Client/Windows64/KeyboardMouseInput.cpp index 791eb2727..fc7633947 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 4d272f91f..a09843f90 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 0cbfd90fe..931e7f179 100644 --- a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp +++ b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp @@ -39,6 +39,10 @@ #include "Xbox/resource.h" +#ifdef _MSC_VER +#pragma comment(lib, "legacy_stdio_definitions.lib") +#endif + HINSTANCE hMyInst; LRESULT CALLBACK DlgProc(HWND hWndDlg, UINT Msg, WPARAM wParam, LPARAM lParam); char chGlobalText[256]; @@ -181,11 +185,11 @@ void DefineActions(void) InputManager.SetGameJoypadMaps(MAP_STYLE_1,MINECRAFT_ACTION_CRAFTING, _360_JOY_BUTTON_X); InputManager.SetGameJoypadMaps(MAP_STYLE_1,MINECRAFT_ACTION_RENDER_THIRD_PERSON, _360_JOY_BUTTON_RTHUMB); InputManager.SetGameJoypadMaps(MAP_STYLE_1,MINECRAFT_ACTION_GAME_INFO, _360_JOY_BUTTON_BACK); - + InputManager.SetGameJoypadMaps(MAP_STYLE_1,MINECRAFT_ACTION_DPAD_LEFT, _360_JOY_BUTTON_DPAD_LEFT); InputManager.SetGameJoypadMaps(MAP_STYLE_1,MINECRAFT_ACTION_DPAD_RIGHT, _360_JOY_BUTTON_DPAD_RIGHT); InputManager.SetGameJoypadMaps(MAP_STYLE_1,MINECRAFT_ACTION_DPAD_UP, _360_JOY_BUTTON_DPAD_UP); - InputManager.SetGameJoypadMaps(MAP_STYLE_1,MINECRAFT_ACTION_DPAD_DOWN, _360_JOY_BUTTON_DPAD_DOWN); + InputManager.SetGameJoypadMaps(MAP_STYLE_1,MINECRAFT_ACTION_DPAD_DOWN, _360_JOY_BUTTON_DPAD_DOWN); InputManager.SetGameJoypadMaps(MAP_STYLE_2,ACTION_MENU_A, _360_JOY_BUTTON_A); InputManager.SetGameJoypadMaps(MAP_STYLE_2,ACTION_MENU_B, _360_JOY_BUTTON_B); @@ -230,11 +234,11 @@ void DefineActions(void) InputManager.SetGameJoypadMaps(MAP_STYLE_2,ACTION_MENU_OTHER_STICK_DOWN, _360_JOY_BUTTON_RSTICK_DOWN); InputManager.SetGameJoypadMaps(MAP_STYLE_2,ACTION_MENU_OTHER_STICK_LEFT, _360_JOY_BUTTON_RSTICK_LEFT); InputManager.SetGameJoypadMaps(MAP_STYLE_2,ACTION_MENU_OTHER_STICK_RIGHT, _360_JOY_BUTTON_RSTICK_RIGHT); - + InputManager.SetGameJoypadMaps(MAP_STYLE_2,MINECRAFT_ACTION_DPAD_LEFT, _360_JOY_BUTTON_DPAD_LEFT); InputManager.SetGameJoypadMaps(MAP_STYLE_2,MINECRAFT_ACTION_DPAD_RIGHT, _360_JOY_BUTTON_DPAD_RIGHT); InputManager.SetGameJoypadMaps(MAP_STYLE_2,MINECRAFT_ACTION_DPAD_UP, _360_JOY_BUTTON_DPAD_UP); - InputManager.SetGameJoypadMaps(MAP_STYLE_2,MINECRAFT_ACTION_DPAD_DOWN, _360_JOY_BUTTON_DPAD_DOWN); + InputManager.SetGameJoypadMaps(MAP_STYLE_2,MINECRAFT_ACTION_DPAD_DOWN, _360_JOY_BUTTON_DPAD_DOWN); } #if 0 @@ -391,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); @@ -400,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); } @@ -590,6 +606,7 @@ app.DebugPrintf("width: %d, height: %d\n", width, height); // Create a depth stencil buffer D3D11_TEXTURE2D_DESC descDepth; + ZeroMemory(&descDepth, sizeof(descDepth)); descDepth.Width = width; descDepth.Height = height; @@ -605,6 +622,7 @@ app.DebugPrintf("width: %d, height: %d\n", width, height); hr = g_pd3dDevice->CreateTexture2D(&descDepth, NULL, &g_pDepthStencilBuffer); D3D11_DEPTH_STENCIL_VIEW_DESC descDSView; + ZeroMemory(&descDSView, sizeof(descDSView)); descDSView.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; descDSView.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; descDSView.Texture2D.MipSlice = 0; @@ -806,7 +824,7 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, app.loadMediaArchive(); RenderManager.Initialise(g_pd3dDevice, g_pSwapChain); - + app.loadStringTable(); ui.init(g_pd3dDevice,g_pImmediateContext,g_pRenderTargetView,g_pDepthStencilView,g_iScreenWidth,g_iScreenHeight); @@ -1178,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/Xbox/MinecraftWindows.rc b/Minecraft.Client/Xbox/MinecraftWindows.rc index 69ce53342..e4fd4960b 100644 Binary files a/Minecraft.Client/Xbox/MinecraftWindows.rc and b/Minecraft.Client/Xbox/MinecraftWindows.rc differ diff --git a/Minecraft.Client/Xbox/Resource.h b/Minecraft.Client/Xbox/Resource.h index 554357262..c5c2988f4 100644 Binary files a/Minecraft.Client/Xbox/Resource.h and b/Minecraft.Client/Xbox/Resource.h differ diff --git a/Minecraft.Client/stdafx.h b/Minecraft.Client/stdafx.h index 2f6dccc3b..05b17e819 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 +#include #include #include // TODO: reference additional headers your program requires here diff --git a/Minecraft.Client/stubs.cpp b/Minecraft.Client/stubs.cpp index 0c7e680a3..16215ba2f 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 f9196e206..cc7888672 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 e9af7d0fa..279f70518 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