LADXHD/Editor/MapEditorScreen.cs
2023-12-14 17:21:22 -05:00

368 lines
16 KiB
C#

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using ProjectZ.Base;
using ProjectZ.Base.UI;
using ProjectZ.InGame.SaveLoad;
using ProjectZ.InGame.Screens;
using ProjectZ.InGame.Things;
using System;
namespace ProjectZ.Editor
{
internal class MapEditorScreen : Screen
{
public enum EditorModes
{
TileMode,
ObjectMode,
DigMode,
MusicMode
}
public Vector2 MousePixelPosition => new Vector2(
(InputHandler.MousePosition().X - _camera.Location.X) / _camera.Scale,
(InputHandler.MousePosition().Y - _camera.Location.Y) / _camera.Scale);
public Point MouseMapPosition => new Point(
(InputHandler.MousePosition().X - _camera.Location.X) / (int)(Values.TileSize * _camera.Scale),
(InputHandler.MousePosition().Y - _camera.Location.Y) / (int)(Values.TileSize * _camera.Scale));
public bool ShowGrid;
private EditorModes _currentMode = EditorModes.ObjectMode;
private readonly EditorCamera _camera = new EditorCamera();
private readonly TileEditorScreen _tileEditorScreen;
private readonly ObjectEditorScreen _objectEditorScreen;
private readonly DigMapEditor _digMapEditor;
private readonly MusicTileEditor _musicTileEditor;
private UiNumberInput _niOffsetX;
private UiNumberInput _niOffsetY;
private Point _mousePosition;
private int _mapOffsetX = 0;
private int _mapOffsetY = 0;
private string _currentMapName;
private int _toolBarWidth = 200;
private bool _showTiles = true;
private bool _showObjects = true;
private bool _shiftDown;
public MapEditorScreen(string screenId) : base(screenId)
{
_tileEditorScreen = new TileEditorScreen(_camera);
_objectEditorScreen = new ObjectEditorScreen(_camera);
_digMapEditor = new DigMapEditor(_camera);
_musicTileEditor = new MusicTileEditor(_camera);
}
public override void Load(ContentManager content)
{
_tileEditorScreen.Load(content);
_objectEditorScreen.Load();
SetupUi();
}
public void SetupUi()
{
var buttonWidth = _toolBarWidth - 10;
var buttonWidthHalf = (buttonWidth - 4) / 2;
var buttonHeight = 30;
var lableHeight = 20;
var buttonQWidth = _toolBarWidth - 15 - buttonHeight;
var posY = Values.ToolBarHeight + 5;
var dist = 4;
var bigDist = 16;
var strScreenName = $"{Values.EditorUiTileEditor}:{Values.EditorUiObjectEditor}:{Values.EditorUiDigTileEditor}:{Values.EditorUiMusicTileEditor}";
// left background
Game1.EditorUi.AddElement(new UiRectangle(Rectangle.Empty, "left", strScreenName,
Values.ColorBackgroundLight, Color.White,
ui =>
{
ui.Rectangle = new Rectangle(0, Values.ToolBarHeight, _toolBarWidth,
Game1.WindowHeight - Values.ToolBarHeight);
}));
Game1.EditorUi.AddElement(new UiButton(new Rectangle(5, posY, buttonWidth, buttonHeight),
Resources.EditorFont,
"Load", "", strScreenName, null, ui => SaveLoadMap.LoadMap(Game1.GameManager.MapManager.CurrentMap)));
Game1.EditorUi.AddElement(new UiButton(new Rectangle(5, posY += buttonHeight + dist, buttonWidth, buttonHeight),
Resources.EditorFont,
"Save as...", "", strScreenName, null, ui => SaveLoadMap.SaveMapDialog(Game1.GameManager.MapManager.CurrentMap)));
Game1.EditorUi.AddElement(new UiButton(new Rectangle(5, posY += buttonHeight + dist, buttonWidth, buttonHeight),
Resources.EditorFont,
"Save...", "", strScreenName, null, ui => SaveLoadMap.SaveMap(Game1.GameManager.MapManager.CurrentMap)));
Game1.EditorUi.AddElement(new UiButton(new Rectangle(5, posY += buttonHeight + dist, buttonWidth, buttonHeight),
Resources.EditorFont,
"Update Maps", "", strScreenName, null, ui => SaveLoadMap.UpdateMaps()));
// map offset
Game1.EditorUi.AddElement(_niOffsetX = new UiNumberInput(
new Rectangle(5, posY += buttonHeight + dist, buttonWidthHalf, buttonHeight),
Resources.EditorFont, _mapOffsetX, -16, 16, 1, "", strScreenName, null, NumberInputChangeMapOffsetX));
Game1.EditorUi.AddElement(_niOffsetY = new UiNumberInput(
new Rectangle(5 + buttonWidthHalf + dist, posY, buttonWidthHalf, buttonHeight),
Resources.EditorFont, _mapOffsetX, -16, 16, 1, "", strScreenName, null, NumberInputChangeMapOffsetY));
Game1.EditorUi.AddElement(new UiNumberInput(
new Rectangle(5, posY += buttonHeight + dist, buttonWidthHalf, buttonHeight),
Resources.EditorFont, _mapOffsetX, -16, 16, 1, "", strScreenName, null, NumberInputChangeOffsetX));
Game1.EditorUi.AddElement(new UiNumberInput(
new Rectangle(5 + buttonWidthHalf + dist, posY, buttonWidthHalf, buttonHeight),
Resources.EditorFont, _mapOffsetX, -16, 16, 1, "", strScreenName, null, NumberInputChangeOffsetY));
Game1.EditorUi.AddElement(new UiButton(new Rectangle(5, posY += buttonHeight + dist, buttonWidth, buttonHeight),
Resources.EditorFont, "Offset Map", "", strScreenName, null, ButtonPressedOffsetMap));
// show grid button
Game1.EditorUi.AddElement(new UiCheckBox(
new Rectangle(5, posY += buttonHeight + bigDist, buttonWidth, buttonHeight), Resources.EditorFont,
"show grid", "cb", strScreenName, false, null,
ui => { ShowGrid = ((UiCheckBox)ui).CurrentState; }));
// tile/object mode switch
Game1.EditorUi.AddElement(new UiButton(new Rectangle(5, posY += buttonHeight + bigDist, buttonQWidth, buttonHeight),
Resources.EditorFont, "Tiles", "", strScreenName,
element => ((UiButton)element).Marked = _currentMode == EditorModes.TileMode,
element => _currentMode = EditorModes.TileMode));
Game1.EditorUi.AddElement(new UiButton(new Rectangle(5 + buttonQWidth + dist, posY, buttonHeight, buttonHeight),
Resources.EditorFont, "", "bt1", strScreenName, null, ButtonUpdateTilesVisibility)
{ ButtonIcon = Resources.EditorEyeOpen });
Game1.EditorUi.AddElement(new UiButton(new Rectangle(5, posY += buttonHeight + dist, buttonQWidth, buttonHeight),
Resources.EditorFont, "Objects", "", strScreenName,
element => ((UiButton)element).Marked = _currentMode == EditorModes.ObjectMode,
element => _currentMode = EditorModes.ObjectMode));
Game1.EditorUi.AddElement(new UiButton(new Rectangle(5 + buttonQWidth + dist, posY, buttonHeight, buttonHeight),
Resources.EditorFont, "", "bt1", strScreenName, null, ButtonUpdateObjectsVisibility)
{ ButtonIcon = Resources.EditorEyeOpen });
Game1.EditorUi.AddElement(new UiButton(new Rectangle(5, posY += buttonHeight + dist, buttonWidth, buttonHeight),
Resources.EditorFont, "Dig Map", "", strScreenName,
element => ((UiButton)element).Marked = _currentMode == EditorModes.DigMode,
element => _currentMode = EditorModes.DigMode));
Game1.EditorUi.AddElement(new UiButton(new Rectangle(5, posY += buttonHeight + dist, buttonWidth, buttonHeight),
Resources.EditorFont, "Music", "", strScreenName,
element => ((UiButton)element).Marked = _currentMode == EditorModes.MusicMode,
element => _currentMode = EditorModes.MusicMode));
posY += buttonHeight + bigDist;
// load the ui of the tile editor
_tileEditorScreen.SetupUi(posY);
// load the ui of the object editor
_objectEditorScreen.SetupUi(posY);
_digMapEditor.SetUpUi(posY);
// set up music ui
_musicTileEditor.SetUpUi(posY);
}
public override void Update(GameTime gameTime)
{
_shiftDown = InputHandler.KeyDown(Keys.LeftControl) & InputHandler.MousePosition().X < Game1.WindowWidth - _toolBarWidth;
// update the selection screen or the editor screen
if (_shiftDown)
UpdateSelectionScreen(gameTime);
else
UpdateEditorScreen(gameTime);
}
public void UpdateSelectionScreen(GameTime gameTime)
{
if (_currentMode == EditorModes.TileMode)
_tileEditorScreen.UpdateTileSelection(gameTime);
else if (_currentMode == EditorModes.ObjectMode)
_objectEditorScreen.UpdateObjectSelection(gameTime);
}
public void UpdateEditorScreen(GameTime gameTime)
{
_mousePosition = InputHandler.MousePosition();
// move the tileset
if (!InputHandler.MouseMiddleStart() && InputHandler.MouseMiddleDown())
_camera.Location += _mousePosition - InputHandler.LastMousePosition();
// center camera after map change
if (Game1.GameManager.MapManager.CurrentMap.MapName != _currentMapName)
{
_currentMapName = Game1.GameManager.MapManager.CurrentMap.MapName;
CenterCamera();
}
_musicTileEditor.Map = Game1.GameManager.MapManager.CurrentMap;
_tileEditorScreen.Map = Game1.GameManager.MapManager.CurrentMap;
_niOffsetX.Value = Game1.GameManager.MapManager.CurrentMap.MapOffsetX;
_niOffsetY.Value = Game1.GameManager.MapManager.CurrentMap.MapOffsetY;
// update the tile or the object editor screen
if (_currentMode == EditorModes.TileMode)
_tileEditorScreen.Update(gameTime);
else if (_currentMode == EditorModes.ObjectMode)
_objectEditorScreen.Update(gameTime);
else if (_currentMode == EditorModes.DigMode)
_digMapEditor.Update(gameTime);
else if (_currentMode == EditorModes.MusicMode)
_musicTileEditor.Update(gameTime);
// update tileset scale
if (InputHandler.MouseWheelUp())
_camera.Zoom(1, _mousePosition);
if (InputHandler.MouseWheelDown())
_camera.Zoom(-1, _mousePosition);
}
public override void Draw(SpriteBatch spriteBatch)
{
// show the tile or the object selection screen
if (_shiftDown)
DrawSelectionScreen(spriteBatch);
else
// draw the editor screen
DrawEditorScreen(spriteBatch);
}
private void DrawSelectionScreen(SpriteBatch spriteBatch)
{
if (_currentMode == EditorModes.TileMode)
_tileEditorScreen.DrawTileSelection(spriteBatch);
else if (_currentMode == EditorModes.ObjectMode)
_objectEditorScreen.DrawObjectSelection(spriteBatch);
}
private void DrawEditorScreen(SpriteBatch spriteBatch)
{
spriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointWrap, null, null, null, _camera.TransformMatrix);
// draw the background
spriteBatch.Draw(Resources.SprTiledBlock, new Rectangle(0, 0,
Game1.GameManager.MapManager.CurrentMap.MapWidth * Values.TileSize,
Game1.GameManager.MapManager.CurrentMap.MapHeight * Values.TileSize),
new Rectangle(0, 0,
Game1.GameManager.MapManager.CurrentMap.MapWidth * 2,
Game1.GameManager.MapManager.CurrentMap.MapHeight * 2),
Color.White);
// draw the tile layers
if (_showTiles)
_tileEditorScreen.Draw(spriteBatch, _currentMode == EditorModes.TileMode);
// draw the object layer
if (_showObjects)
_objectEditorScreen.Draw(spriteBatch);
if (_currentMode == EditorModes.DigMode)
_digMapEditor.Draw(spriteBatch);
else if (_currentMode == EditorModes.MusicMode)
_musicTileEditor.Draw(spriteBatch);
// draw the grid
var currentMap = Game1.GameManager.MapManager.CurrentMap;
if (ShowGrid)
{
var countX = MathF.Ceiling(currentMap.TileMap.ArrayTileMap.GetLength(0) / 10.0f);
var countY = MathF.Ceiling(currentMap.TileMap.ArrayTileMap.GetLength(1) / 8.0f);
for (var y = 0; y < countY; y++)
for (var x = 0; x < countX; x++)
if ((y + x) % 2 == 0)
{
var sizeX = Math.Min(10, currentMap.TileMap.ArrayTileMap.GetLength(0) - x * 10);
var sizeY = Math.Min(8, currentMap.TileMap.ArrayTileMap.GetLength(1) - y * 8);
spriteBatch.Draw(Resources.SprWhite, new Rectangle(
(x * 10 + currentMap.MapOffsetX) * Values.TileSize,
(y * 8 + currentMap.MapOffsetY) * Values.TileSize,
Values.TileSize * sizeX, Values.TileSize * sizeY), Color.White * 0.5f);
}
}
spriteBatch.End();
}
public override void DrawTop(SpriteBatch spriteBatch)
{
if (_shiftDown)
return;
if (_currentMode == EditorModes.TileMode)
_tileEditorScreen.DrawTop(spriteBatch);
else if (_currentMode == EditorModes.ObjectMode)
_objectEditorScreen.DrawTop(spriteBatch);
}
public void CenterCamera()
{
_camera.Location.X = (int)(Game1.WindowWidth - Values.TileSize * Game1.GameManager.MapManager.CurrentMap.MapWidth * _camera.Scale) / 2;
_camera.Location.Y = (int)(Game1.WindowHeight - Values.TileSize * Game1.GameManager.MapManager.CurrentMap.MapHeight * _camera.Scale) / 2;
}
public bool InsideField()
{
return InputHandler.MouseIntersect(new Rectangle(
_toolBarWidth, Values.ToolBarHeight,
Game1.WindowWidth - _toolBarWidth * 2,
Game1.WindowHeight - Values.ToolBarHeight));
}
private void ButtonUpdateTilesVisibility(UiElement ui)
{
_showTiles = !_showTiles;
((UiButton)ui).ButtonIcon = _showTiles ? Resources.EditorEyeOpen : Resources.EditorEyeClosed;
}
private void ButtonUpdateObjectsVisibility(UiElement ui)
{
_showObjects = !_showObjects;
((UiButton)ui).ButtonIcon = _showObjects ? Resources.EditorEyeOpen : Resources.EditorEyeClosed;
}
private void NumberInputChangeMapOffsetX(UiElement uiElement)
{
Game1.GameManager.MapManager.CurrentMap.MapOffsetX = (int)((UiNumberInput)uiElement).Value;
}
private void NumberInputChangeMapOffsetY(UiElement uiElement)
{
Game1.GameManager.MapManager.CurrentMap.MapOffsetY = (int)((UiNumberInput)uiElement).Value;
}
private void NumberInputChangeOffsetX(UiElement uiElement)
{
_mapOffsetX = (int)((UiNumberInput)uiElement).Value;
}
private void NumberInputChangeOffsetY(UiElement uiElement)
{
_mapOffsetY = (int)((UiNumberInput)uiElement).Value;
}
private void ButtonPressedOffsetMap(UiElement uiElement)
{
// offset the tilemap
_tileEditorScreen.OffsetTileMap(_mapOffsetX, _mapOffsetY);
// offset the objects
ObjectEditorScreen.OffsetObjects(
Game1.GameManager.MapManager.CurrentMap, _mapOffsetX * Values.TileSize, _mapOffsetY * Values.TileSize);
}
}
}