Observable collection base code for those without a true backing collection.
Observable sorted dictionary Grid view now displays blocks grouped by subtype. Null propagation in entity view models because WPF.
This commit is contained in:
@@ -1,69 +1,118 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Sandbox.Definitions;
|
||||
using Sandbox.Game.Entities;
|
||||
using Sandbox.Game.Entities.Cube;
|
||||
using Sandbox.ModAPI;
|
||||
using Torch.API.Managers;
|
||||
using Torch.Collections;
|
||||
using Torch.Server.ViewModels.Blocks;
|
||||
using VRage.Game;
|
||||
|
||||
namespace Torch.Server.ViewModels.Entities
|
||||
{
|
||||
public class GridViewModel : EntityViewModel, ILazyLoad
|
||||
{
|
||||
private MyCubeGrid Grid => (MyCubeGrid)Entity;
|
||||
public MtObservableList<BlockViewModel> Blocks { get; } = new MtObservableList<BlockViewModel>();
|
||||
private static readonly MyCubeBlockDefinition _fillerDefinition = new MyCubeBlockDefinition()
|
||||
{
|
||||
Id = new MyDefinitionId(typeof(MyObjectBuilder_DefinitionBase), "")
|
||||
};
|
||||
|
||||
private class CubeBlockDefinitionComparer : IComparer<MyCubeBlockDefinition>
|
||||
{
|
||||
public static readonly CubeBlockDefinitionComparer Default = new CubeBlockDefinitionComparer();
|
||||
|
||||
public int Compare(MyCubeBlockDefinition x, MyCubeBlockDefinition y)
|
||||
{
|
||||
if (x == null && y == null)
|
||||
return 0;
|
||||
if (x == null)
|
||||
return -1;
|
||||
if (y == null)
|
||||
return 1;
|
||||
if (ReferenceEquals(x, y))
|
||||
return 0;
|
||||
MyDefinitionId xi = x.Id;
|
||||
MyDefinitionId yi = y.Id;
|
||||
if (xi == yi)
|
||||
return 0;
|
||||
if (xi.TypeId != yi.TypeId)
|
||||
return string.CompareOrdinal(((Type) xi.TypeId).Name, ((Type) yi.TypeId).Name);
|
||||
return xi.SubtypeId == yi.SubtypeId ? 0 : string.CompareOrdinal(xi.SubtypeName, yi.SubtypeName);
|
||||
}
|
||||
}
|
||||
|
||||
private MyCubeGrid Grid => (MyCubeGrid) Entity;
|
||||
|
||||
public MtObservableSortedDictionary<MyCubeBlockDefinition, MtObservableSortedDictionary<long, BlockViewModel>>
|
||||
Blocks { get; } =
|
||||
new MtObservableSortedDictionary<MyCubeBlockDefinition, MtObservableSortedDictionary<long, BlockViewModel>>(
|
||||
CubeBlockDefinitionComparer.Default);
|
||||
|
||||
/// <inheritdoc />
|
||||
public string DescriptiveName { get; }
|
||||
|
||||
public GridViewModel() { }
|
||||
public GridViewModel()
|
||||
{
|
||||
}
|
||||
|
||||
public GridViewModel(MyCubeGrid grid, EntityTreeViewModel tree) : base(grid, tree)
|
||||
{
|
||||
DescriptiveName = $"{grid.DisplayName} ({grid.BlocksCount} blocks)";
|
||||
Blocks.Add(new BlockViewModel(null, Tree));
|
||||
Blocks.Add(_fillerDefinition, new MtObservableSortedDictionary<long, BlockViewModel>());
|
||||
}
|
||||
|
||||
private void Grid_OnBlockRemoved(Sandbox.Game.Entities.Cube.MySlimBlock obj)
|
||||
{
|
||||
if (obj.FatBlock != null)
|
||||
Blocks.RemoveWhere(b => b.Block.EntityId == obj.FatBlock?.EntityId);
|
||||
RemoveBlock(obj.FatBlock);
|
||||
|
||||
OnPropertyChanged(nameof(Name));
|
||||
}
|
||||
|
||||
private void RemoveBlock(MyCubeBlock block)
|
||||
{
|
||||
if (!Blocks.TryGetValue(block.BlockDefinition, out var group))
|
||||
return;
|
||||
if (group.Remove(block.EntityId) && group.Count == 0 && Blocks.Count > 1)
|
||||
Blocks.Remove(block.BlockDefinition);
|
||||
}
|
||||
|
||||
private void AddBlock(MyTerminalBlock block)
|
||||
{
|
||||
if (!Blocks.TryGetValue(block.BlockDefinition, out var group))
|
||||
group = Blocks[block.BlockDefinition] = new MtObservableSortedDictionary<long, BlockViewModel>();
|
||||
group.Add(block.EntityId, new BlockViewModel(block, Tree));
|
||||
}
|
||||
|
||||
private void Grid_OnBlockAdded(Sandbox.Game.Entities.Cube.MySlimBlock obj)
|
||||
{
|
||||
var block = obj.FatBlock as IMyTerminalBlock;
|
||||
var block = obj.FatBlock as MyTerminalBlock;
|
||||
if (block != null)
|
||||
Blocks.Add(new BlockViewModel(block, Tree));
|
||||
AddBlock(block);
|
||||
|
||||
OnPropertyChanged(nameof(Name));
|
||||
}
|
||||
|
||||
private bool _load;
|
||||
|
||||
public void Load()
|
||||
{
|
||||
if (_load)
|
||||
return;
|
||||
|
||||
_load = true;
|
||||
Blocks.Clear();
|
||||
TorchBase.Instance.Invoke(() =>
|
||||
{
|
||||
foreach (var block in Grid.GetFatBlocks().Where(b => b is IMyTerminalBlock))
|
||||
{
|
||||
Blocks.Add(new BlockViewModel((IMyTerminalBlock)block, Tree));
|
||||
}
|
||||
Blocks.Clear();
|
||||
foreach (var block in Grid.GetFatBlocks().OfType<MyTerminalBlock>())
|
||||
AddBlock(block);
|
||||
|
||||
Grid.OnBlockAdded += Grid_OnBlockAdded;
|
||||
Grid.OnBlockRemoved += Grid_OnBlockRemoved;
|
||||
|
||||
Tree.ControlDispatcher.BeginInvoke(() =>
|
||||
{
|
||||
Blocks.Sort(b => b.Block.CustomName);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user