Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix incorrect mouse -> world position conversion in console #391

Merged
merged 2 commits into from
Oct 31, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions Celeste.Mod.mm/Patches/Level.cs
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,40 @@ public override void End() {
((patch_EntityList) (object) Entities).ClearEntities();
}
}

public Vector2 ScreenToWorld(Vector2 position) {
Vector2 size = new Vector2(320f, 180f);
Vector2 scaledSize = size / ZoomTarget;
Vector2 offset = ZoomTarget != 1f ? (ZoomFocusPoint - scaledSize / 2f) / (size - scaledSize) * size : Vector2.Zero;
float scale = Zoom * ((320f - ScreenPadding * 2f) / 320f);
Vector2 paddingOffset = new Vector2(ScreenPadding, ScreenPadding * 9f / 16f);

if (SaveData.Instance?.Assists.MirrorMode ?? false) {
position.X = 1920f - position.X;
}
position /= 1920f / 320f;
position -= paddingOffset;
position = (position - offset) / scale + offset;
position = Camera.ScreenToCamera(position);
return position;
}

public Vector2 WorldToScreen(Vector2 position) {
Vector2 size = new Vector2(320f, 180f);
Vector2 scaledSize = size / ZoomTarget;
Vector2 offset = ZoomTarget != 1f ? (ZoomFocusPoint - scaledSize / 2f) / (size - scaledSize) * size : Vector2.Zero;
float scale = Zoom * ((320f - ScreenPadding * 2f) / 320f);
Vector2 paddingOffset = new Vector2(ScreenPadding, ScreenPadding * 9f / 16f);

position = Camera.CameraToScreen(position);
position = (position - offset) * scale + offset;
position += paddingOffset;
position *= 1920f / 320f;
if (SaveData.Instance?.Assists.MirrorMode ?? false) {
position.X = 1920f - position.X;
}
return position;
}
}

public static class LevelExt {
Expand Down
22 changes: 10 additions & 12 deletions Celeste.Mod.mm/Patches/Monocle/Commands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,15 @@ internal void Render() {
int viewHeight = Engine.ViewHeight;

// Vector2 mousePosition = MInput.Mouse.Position;
// For whatever reason, MInput.Mouse.Position keeps returning 0, 0
// When the console is opening, MInput.Mouse.UpdateNull is called so MInput.Mouse.Position keeps returning 0, 0
// Let's just use the XNA / FNA MouseState instead.
MouseState mouseState = Mouse.GetState();
int mouseScrollDelta = mouseState.ScrollWheelValue - mouseScroll;
mouseScroll = mouseState.ScrollWheelValue;
Vector2 mousePosition = new Vector2(mouseState.X, mouseState.Y);
Vector2? mouseSnapPosition = null;

int viewScale = 1;
int maxCursorScale = 1;

string mouseText = "";

Expand All @@ -102,28 +102,26 @@ internal void Render() {

if (level != null) {
Camera cam = level.Camera;
viewScale = (int) Math.Round(Engine.Instance.GraphicsDevice.PresentationParameters.BackBufferWidth / (float) cam.Viewport.Width);
Vector2 mouseWorldPosition = mousePosition;
// Convert screen to world position.
mouseWorldPosition = Calc.Floor(mouseWorldPosition / viewScale);
mouseWorldPosition = cam.ScreenToCamera(mouseWorldPosition);
float viewScale = (float) Engine.ViewWidth / Engine.Width;
// Convert screen to world position. The method assumes screen is in full size (1920x1080) so we need to scale the position.
Vector2 mouseWorldPosition = Calc.Floor(((patch_Level) level).ScreenToWorld(mousePosition / viewScale));
// CelesteTAS already displays world coordinates. If it is installed, leave that up to it.
if (!celesteTASInstalled.Value) {
mouseText += $"\n world: {(int) Math.Round(mouseWorldPosition.X)}, {(int) Math.Round(mouseWorldPosition.Y)}";
}
mouseWorldPosition -= level.LevelOffset;
mouseText += $"\n level: {(int) Math.Round(mouseWorldPosition.X)}, {(int) Math.Round(mouseWorldPosition.Y)}";
// Convert world to world-snap position.
mouseSnapPosition = mouseWorldPosition;
mouseSnapPosition = Calc.Floor(mouseSnapPosition.Value / 8f);
mouseSnapPosition = Calc.Floor(mouseWorldPosition / 8f);
mouseText += $"\n level, /8: {(int) Math.Round(mouseSnapPosition.Value.X)}, {(int) Math.Round(mouseSnapPosition.Value.Y)}";
mouseSnapPosition = 8f * mouseSnapPosition;
mouseText += $"\n level, snap: {(int) Math.Round(mouseSnapPosition.Value.X)}, {(int) Math.Round(mouseSnapPosition.Value.Y)}";
// Convert world-snap to screen-snap position.
mouseSnapPosition += new Vector2(4f, 4f); // Center the cursor on the tile.
mouseSnapPosition += level.LevelOffset;
mouseSnapPosition = cam.CameraToScreen(mouseSnapPosition.Value);
mouseSnapPosition *= viewScale;
mouseSnapPosition = Calc.Floor(((patch_Level) level).WorldToScreen(mouseSnapPosition.Value) * viewScale);
// Cursor shouldn't be larger than an unzoomed tile (level.Zoom and cam.Zoom are both 1)
maxCursorScale = Engine.ViewWidth / cam.Viewport.Width;
}

Draw.SpriteBatch.Begin();
Expand All @@ -133,7 +131,7 @@ internal void Render() {
cursorScale--;
else if (mouseScrollDelta > 0)
cursorScale++;
cursorScale = Calc.Clamp(cursorScale, 1, viewScale);
cursorScale = Calc.Clamp(cursorScale, 1, maxCursorScale);
if (mouseSnapPosition != null)
DrawCursor(mouseSnapPosition.Value, cursorScale, Color.Red);
DrawCursor(mousePosition, cursorScale, Color.Yellow);
Expand Down