using System.Collections.ObjectModel; using System.Windows.Input; namespace codelanguage; public class MapEditorViewModel : ViewModelBase { private CraftMapFile? _map; private int _planeIndex; private int _maxX = 64; private int _maxY = 64; private int _maxZ = 1; private int _selectedTileX = -1; private int _selectedTileY = -1; private int _selectedTileZ = 1; private string _selectedTileType = "/turf"; private string _selectedTileIcon = ""; private bool _showGrid = true; private bool _showCoordinates = true; private double _zoom = 1.0; private int _tileSize = 32; private readonly ObservableCollection _availableTypes = new(); private readonly ObservableCollection _planeNames = new(); public CraftMapFile? Map { get => _map; set { _map = value; OnPropertyChanged(); OnPropertyChanged(nameof(Tiles)); } } public int PlaneIndex { get => _planeIndex; set { _planeIndex = value; OnPropertyChanged(); OnPropertyChanged(nameof(Tiles)); } } public int MaxX { get => _maxX; set => Set(ref _maxX, value); } public int MaxY { get => _maxY; set => Set(ref _maxY, value); } public int MaxZ { get => _maxZ; set => Set(ref _maxZ, value); } public int SelectedTileX { get => _selectedTileX; set => Set(ref _selectedTileX, value); } public int SelectedTileY { get => _selectedTileY; set => Set(ref _selectedTileY, value); } public int SelectedTileZ { get => _selectedTileZ; set => Set(ref _selectedTileZ, value); } public string SelectedTileType { get => _selectedTileType; set => Set(ref _selectedTileType, value); } public string SelectedTileIcon { get => _selectedTileIcon; set => Set(ref _selectedTileIcon, value); } public bool ShowGrid { get => _showGrid; set => Set(ref _showGrid, value); } public bool ShowCoordinates { get => _showCoordinates; set => Set(ref _showCoordinates, value); } public double Zoom { get => _zoom; set => Set(ref _zoom, value); } public int TileSize { get => _tileSize; set => Set(ref _tileSize, value); } public ObservableCollection AvailableTypes => _availableTypes; public ObservableCollection PlaneNames => _planeNames; public ObservableCollection Tiles { get; } = new(); public ICommand NewMapCommand { get; } public ICommand OpenMapCommand { get; } public ICommand SaveMapCommand { get; } public ICommand ResizeMapCommand { get; } public ICommand AddPlaneCommand { get; } public ICommand RemovePlaneCommand { get; } public ICommand FillPlaneCommand { get; } public ICommand ExportTk212Command { get; } // Host callbacks (wired by the IDE) for operations that need a file dialog // or user input the ViewModel itself cannot surface. public Func? RequestMapOpen { get; set; } public Func? RequestMapSave { get; set; } public Func<(int x, int y)?>? RequestMapResize { get; set; } public MapEditorViewModel() { NewMapCommand = new RelayCommand(_ => NewMap()); OpenMapCommand = new RelayCommand(_ => OpenMap()); SaveMapCommand = new RelayCommand(_ => SaveMap()); ResizeMapCommand = new RelayCommand(_ => ResizeMap()); AddPlaneCommand = new RelayCommand(_ => AddPlane()); RemovePlaneCommand = new RelayCommand(_ => RemovePlane()); FillPlaneCommand = new RelayCommand(_ => FillPlane()); ExportTk212Command = new RelayCommand(_ => ExportTk212()); } private void NewMap() { Map = new CraftMapFile("new.cpm") { MaxX = 64, MaxY = 64, MaxZ = 1 }; _maxX = 64; _maxY = 64; _maxZ = 1; PlaneIndex = 0; RefreshPlaneNames(); LoadMapTiles(); } private void OpenMap() { var path = RequestMapOpen?.Invoke(); if (!string.IsNullOrEmpty(path)) OpenMap(path!); } private void SaveMap() { if (_map == null) return; var path = RequestMapSave?.Invoke() ?? _map.Path; SaveMap(path); } private void ResizeMap() { var size = RequestMapResize?.Invoke(); if (size.HasValue) ResizeMap(size.Value.x, size.Value.y); } private void FillPlane() => FillPlane(PlaneIndex, _selectedTileType); public void OpenMap(string path) { var map = new CraftMapFile(path); if (!map.Load()) return; Map = map; _maxX = Math.Max(1, map.MaxX); _maxY = Math.Max(1, map.MaxY); _maxZ = Math.Max(1, map.MaxZ); PlaneIndex = 0; RefreshPlaneNames(); LoadMapTiles(); } public void SaveMap(string path) { if (_map == null) return; try { _map.Path = path; } catch { } _map.Save(); } public void ResizeMap(int newX, int newY) { if (_map == null) return; newX = Math.Max(1, newX); newY = Math.Max(1, newY); var newTiles = new Dictionary<(int, int, int), string>(); foreach (var kvp in _map.Tiles) { if (kvp.Key.x <= newX && kvp.Key.y <= newY) newTiles[kvp.Key] = kvp.Value; } _map.Tiles = newTiles; _map.MaxX = newX; _map.MaxY = newY; _maxX = newX; _maxY = newY; OnPropertyChanged(nameof(MaxX)); OnPropertyChanged(nameof(MaxY)); LoadMapTiles(); } public void AddPlane() { if (_map == null) return; _map.MaxZ++; _maxZ = _map.MaxZ; PlaneNames.Add($"Z{_map.MaxZ}"); PlaneIndex = _map.MaxZ - 1; OnPropertyChanged(nameof(MaxZ)); LoadMapTiles(); } public void RemovePlane() { if (_map == null || _map.MaxZ <= 1) return; int z = _map.MaxZ; var keys = _map.Tiles.Keys.Where(k => k.z == z).ToList(); foreach (var key in keys) _map.Tiles.Remove(key); _map.MaxZ--; _maxZ = _map.MaxZ; if (PlaneIndex >= _map.MaxZ) PlaneIndex = _map.MaxZ - 1; if (PlaneNames.Count > 0) PlaneNames.RemoveAt(PlaneNames.Count - 1); OnPropertyChanged(nameof(MaxZ)); LoadMapTiles(); } public void FillPlane(int plane, string tileType) { if (_map == null) return; int z = plane + 1; for (int y = 1; y <= _map.MaxY; y++) for (int x = 1; x <= _map.MaxX; x++) _map.Tiles[(x, y, z)] = tileType; LoadMapTiles(); } private void ExportTk212() { } private void RefreshPlaneNames() { PlaneNames.Clear(); for (int z = 1; z <= _maxZ; z++) PlaneNames.Add($"Z{z}"); } public void LoadMapTiles() { Tiles.Clear(); if (_map == null) return; for (int z = 1; z <= _map.MaxZ; z++) { for (int y = 1; y <= _map.MaxY; y++) { for (int x = 1; x <= _map.MaxX; x++) { var key = (x, y, z); string tileId = _map.Tiles.TryGetValue(key, out var id) ? id : "0"; Tiles.Add(new MapTileViewModel { X = x, Y = y, Z = z, TileId = tileId }); } } } } } public class MapTileViewModel : ViewModelBase { private int _x; private int _y; private int _z; private string _tileId = "0"; private string _type = "/turf"; private string _icon = ""; public int X { get => _x; set => Set(ref _x, value); } public int Y { get => _y; set => Set(ref _y, value); } public int Z { get => _z; set => Set(ref _z, value); } public string TileId { get => _tileId; set => Set(ref _tileId, value); } public string Type { get => _type; set => Set(ref _type, value); } public string Icon { get => _icon; set => Set(ref _icon, value); } }