Add entity manager content
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
using System.Reflection;
|
||||
|
||||
[assembly: AssemblyVersion("1.0.119.399")]
|
||||
[assembly: AssemblyFileVersion("1.0.119.399")]
|
||||
[assembly: AssemblyVersion("1.0.135.374")]
|
||||
[assembly: AssemblyFileVersion("1.0.135.374")]
|
@@ -1,4 +1,4 @@
|
||||
using System.Reflection;
|
||||
|
||||
[assembly: AssemblyVersion("1.0.119.399")]
|
||||
[assembly: AssemblyFileVersion("1.0.119.399")]
|
||||
[assembly: AssemblyVersion("1.0.135.374")]
|
||||
[assembly: AssemblyFileVersion("1.0.135.374")]
|
@@ -175,19 +175,28 @@
|
||||
<Compile Include="TorchServiceInstaller.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="ViewModels\CharacterViewModel.cs" />
|
||||
<Compile Include="ViewModels\Blocks\BlockViewModel.cs" />
|
||||
<Compile Include="ViewModels\Blocks\BlockViewModelGenerator.cs" />
|
||||
<Compile Include="ViewModels\Blocks\PropertyViewModel.cs" />
|
||||
<Compile Include="ViewModels\Entities\CharacterViewModel.cs" />
|
||||
<Compile Include="ViewModels\ConfigDedicatedViewModel.cs" />
|
||||
<Compile Include="ViewModels\EntityTreeViewModel.cs" />
|
||||
<Compile Include="ViewModels\EntityViewModel.cs" />
|
||||
<Compile Include="ViewModels\Entities\EntityViewModel.cs" />
|
||||
<Compile Include="ViewModels\FloatingObjectViewModel.cs" />
|
||||
<Compile Include="ViewModels\GridViewModel.cs" />
|
||||
<Compile Include="ViewModels\Entities\GridViewModel.cs" />
|
||||
<Compile Include="ViewModels\PluginManagerViewModel.cs" />
|
||||
<Compile Include="ViewModels\PluginViewModel.cs" />
|
||||
<Compile Include="ViewModels\SessionSettingsViewModel.cs" />
|
||||
<Compile Include="ViewModels\VoxelMapViewModel.cs" />
|
||||
<Compile Include="ViewModels\Entities\VoxelMapViewModel.cs" />
|
||||
<Compile Include="Views\AddWorkshopItemsDialog.xaml.cs">
|
||||
<DependentUpon>AddWorkshopItemsDialog.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\Blocks\BlockView.xaml.cs">
|
||||
<DependentUpon>BlockView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\Blocks\PropertyView.xaml.cs">
|
||||
<DependentUpon>PropertyView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\ChatControl.xaml.cs">
|
||||
<DependentUpon>ChatControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
@@ -251,6 +260,14 @@
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\Blocks\BlockView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\Blocks\PropertyView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\ChatControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
@@ -292,6 +309,7 @@
|
||||
<LastGenOutput>AssemblyInfo.cs</LastGenOutput>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>copy "$(SolutionDir)NLog.config" "$(TargetDir)"</PostBuildEvent>
|
||||
|
@@ -9,6 +9,7 @@ using System.Threading;
|
||||
using System.Xml.Serialization;
|
||||
using SteamSDK;
|
||||
using Torch.API;
|
||||
using Torch.Server.ViewModels.Blocks;
|
||||
using VRage.Dedicated;
|
||||
using VRage.FileSystem;
|
||||
using VRage.Game;
|
||||
|
55
Torch.Server/ViewModels/Blocks/BlockViewModel.cs
Normal file
55
Torch.Server/ViewModels/Blocks/BlockViewModel.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Sandbox.ModAPI;
|
||||
using Sandbox.ModAPI.Interfaces;
|
||||
using Torch.Server.ViewModels.Entities;
|
||||
|
||||
namespace Torch.Server.ViewModels.Blocks
|
||||
{
|
||||
public class BlockViewModel : EntityViewModel
|
||||
{
|
||||
public IMyTerminalBlock Block { get; }
|
||||
public MTObservableCollection<PropertyViewModel> Properties { get; } = new MTObservableCollection<PropertyViewModel>();
|
||||
|
||||
public string FullName => $"{Block.CubeGrid.CustomName} - {Block.CustomName}";
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get => Block?.CustomName ?? "null";
|
||||
set
|
||||
{
|
||||
TorchBase.Instance.InvokeBlocking(() => Block.CustomName = value);
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanStop => false;
|
||||
|
||||
public BlockViewModel(IMyTerminalBlock block) : base(block)
|
||||
{
|
||||
Block = block;
|
||||
var propList = new List<ITerminalProperty>();
|
||||
block.GetProperties(propList);
|
||||
foreach (var prop in propList)
|
||||
{
|
||||
Type propType = null;
|
||||
foreach (var iface in prop.GetType().GetInterfaces())
|
||||
{
|
||||
if (iface.IsGenericType && iface.GetGenericTypeDefinition() == typeof(ITerminalProperty<>))
|
||||
propType = iface.GenericTypeArguments[0];
|
||||
}
|
||||
|
||||
var modelType = typeof(PropertyViewModel<>).MakeGenericType(propType);
|
||||
Properties.Add((PropertyViewModel)Activator.CreateInstance(modelType, prop, this));
|
||||
}
|
||||
}
|
||||
|
||||
public BlockViewModel()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
132
Torch.Server/ViewModels/Blocks/BlockViewModelGenerator.cs
Normal file
132
Torch.Server/ViewModels/Blocks/BlockViewModelGenerator.cs
Normal file
@@ -0,0 +1,132 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Sandbox.Game.Entities.Cube;
|
||||
using Sandbox.ModAPI;
|
||||
using Sandbox.ModAPI.Interfaces;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using NLog;
|
||||
using Sandbox.ModAPI.Interfaces.Terminal;
|
||||
|
||||
namespace Torch.Server.ViewModels.Blocks
|
||||
{
|
||||
public static class BlockViewModelGenerator
|
||||
{
|
||||
private static Dictionary<Type, Type> _cache = new Dictionary<Type, Type>();
|
||||
private static AssemblyName _asmName;
|
||||
private static ModuleBuilder _mb;
|
||||
private static AssemblyBuilder _ab;
|
||||
private static Logger _log = LogManager.GetLogger("Generator");
|
||||
|
||||
static BlockViewModelGenerator()
|
||||
{
|
||||
_asmName = new AssemblyName("Torch.Server.ViewModels.Generated");
|
||||
_ab = AppDomain.CurrentDomain.DefineDynamicAssembly(_asmName, AssemblyBuilderAccess.RunAndSave);
|
||||
_mb = _ab.DefineDynamicModule(_asmName.Name);
|
||||
}
|
||||
|
||||
public static void GenerateModels()
|
||||
{
|
||||
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies().Where(a => !a.IsDynamic))
|
||||
{
|
||||
foreach (var type in assembly.ExportedTypes.Where(t => t.IsSubclassOf(typeof(MyTerminalBlock))))
|
||||
{
|
||||
GenerateModel(type);
|
||||
}
|
||||
}
|
||||
_ab.Save("Generated.dll", PortableExecutableKinds.ILOnly, ImageFileMachine.AMD64);
|
||||
}
|
||||
|
||||
public static Type GenerateModel(Type blockType, bool force = false)
|
||||
{
|
||||
if (_cache.ContainsKey(blockType) && !force)
|
||||
return _cache[blockType];
|
||||
|
||||
var propertyList = new List<ITerminalProperty>();
|
||||
MyTerminalControlFactoryHelper.Static.GetProperties(blockType, propertyList);
|
||||
|
||||
var getPropertyMethod = blockType.GetMethod("GetProperty", new[] {typeof(string)});
|
||||
var getValueMethod = typeof(ITerminalProperty<>).GetMethod("GetValue");
|
||||
var setValueMethod = typeof(ITerminalProperty<>).GetMethod("SetValue");
|
||||
var tb = _mb.DefineType($"{_asmName.Name}.{blockType.Name}ViewModel", TypeAttributes.Class | TypeAttributes.Public);
|
||||
var blockField = tb.DefineField("_block", blockType, FieldAttributes.Private);
|
||||
|
||||
var ctor = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new[] {blockType});
|
||||
var ctorIl = ctor.GetILGenerator();
|
||||
ctorIl.Emit(OpCodes.Ldarg_0);
|
||||
ctorIl.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));
|
||||
ctorIl.Emit(OpCodes.Ldarg_0);
|
||||
ctorIl.Emit(OpCodes.Ldarg_1);
|
||||
ctorIl.Emit(OpCodes.Stfld, blockField);
|
||||
ctorIl.Emit(OpCodes.Ret);
|
||||
|
||||
for (var i = 0; i < propertyList.Count; i++)
|
||||
{
|
||||
var prop = propertyList[i];
|
||||
var propType = prop.GetType();
|
||||
|
||||
Type propGenericArg = null;
|
||||
|
||||
foreach (var iface in propType.GetInterfaces())
|
||||
{
|
||||
if (iface.IsGenericType && iface.GetGenericTypeDefinition() == typeof(ITerminalProperty<>))
|
||||
propGenericArg = iface.GenericTypeArguments[0];
|
||||
}
|
||||
|
||||
if (propGenericArg == null)
|
||||
{
|
||||
_log.Error($"Property {prop.Id} does not implement {typeof(ITerminalProperty<>).Name}");
|
||||
return null;
|
||||
}
|
||||
|
||||
_log.Info($"GENERIC ARG: {propGenericArg.Name}");
|
||||
|
||||
var pb = tb.DefineProperty($"{prop.Id}", PropertyAttributes.HasDefault, propGenericArg, null);
|
||||
var getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
|
||||
|
||||
var getter = tb.DefineMethod($"get_{prop.Id}", getSetAttr, propGenericArg, Type.EmptyTypes);
|
||||
{
|
||||
var getterIl = getter.GetILGenerator();
|
||||
var propLoc = getterIl.DeclareLocal(propType);
|
||||
getterIl.Emit(OpCodes.Ldarg_0);
|
||||
getterIl.Emit(OpCodes.Ldfld, blockField);
|
||||
getterIl.Emit(OpCodes.Ldstr, prop.Id);
|
||||
getterIl.EmitCall(OpCodes.Callvirt, getPropertyMethod, null);
|
||||
getterIl.Emit(OpCodes.Stloc, propLoc);
|
||||
getterIl.Emit(OpCodes.Ldloc, propLoc);
|
||||
getterIl.Emit(OpCodes.Ldarg_0);
|
||||
getterIl.Emit(OpCodes.Ldfld, blockField);
|
||||
getterIl.EmitCall(OpCodes.Callvirt, getValueMethod, null);
|
||||
getterIl.Emit(OpCodes.Ret);
|
||||
pb.SetGetMethod(getter);
|
||||
}
|
||||
|
||||
var setter = tb.DefineMethod($"set_{prop.Id}", getSetAttr, null, Type.EmptyTypes);
|
||||
{
|
||||
var setterIl = setter.GetILGenerator();
|
||||
var propLoc = setterIl.DeclareLocal(propType);
|
||||
setterIl.Emit(OpCodes.Ldarg_0);
|
||||
setterIl.Emit(OpCodes.Stfld, blockField);
|
||||
setterIl.EmitCall(OpCodes.Callvirt, getPropertyMethod, null);
|
||||
setterIl.Emit(OpCodes.Stloc, propLoc);
|
||||
setterIl.Emit(OpCodes.Ldarg_1);
|
||||
setterIl.Emit(OpCodes.Ldarg_0);
|
||||
setterIl.Emit(OpCodes.Ldfld, blockField);
|
||||
setterIl.EmitCall(OpCodes.Callvirt, setValueMethod, null);
|
||||
setterIl.Emit(OpCodes.Ret);
|
||||
pb.SetSetMethod(setter);
|
||||
}
|
||||
}
|
||||
|
||||
var vmType = tb.CreateType();
|
||||
_cache.Add(blockType, vmType);
|
||||
return vmType;
|
||||
}
|
||||
}
|
||||
}
|
49
Torch.Server/ViewModels/Blocks/PropertyViewModel.cs
Normal file
49
Torch.Server/ViewModels/Blocks/PropertyViewModel.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Sandbox.ModAPI;
|
||||
using Sandbox.ModAPI.Interfaces;
|
||||
|
||||
namespace Torch.Server.ViewModels.Blocks
|
||||
{
|
||||
public class PropertyViewModel<T> : PropertyViewModel
|
||||
{
|
||||
private readonly ITerminalProperty<T> _prop;
|
||||
public string Name { get; }
|
||||
public Type PropertyType => typeof(T);
|
||||
|
||||
public T Value
|
||||
{
|
||||
get
|
||||
{
|
||||
var val = default(T);
|
||||
TorchBase.Instance.InvokeBlocking(() => val = _prop.GetValue(Block.Block));
|
||||
return val;
|
||||
}
|
||||
set
|
||||
{
|
||||
TorchBase.Instance.InvokeBlocking(() => _prop.SetValue(Block.Block, value));
|
||||
OnPropertyChanged();
|
||||
Block.RefreshModel();
|
||||
}
|
||||
}
|
||||
|
||||
public PropertyViewModel(ITerminalProperty<T> property, BlockViewModel blockViewModel) : base(blockViewModel)
|
||||
{
|
||||
Name = property.Id;
|
||||
_prop = property;
|
||||
}
|
||||
}
|
||||
|
||||
public class PropertyViewModel : ViewModel
|
||||
{
|
||||
protected readonly BlockViewModel Block;
|
||||
|
||||
public PropertyViewModel(BlockViewModel blockViewModel)
|
||||
{
|
||||
Block = blockViewModel;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,18 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Sandbox.Game.Entities.Character;
|
||||
using VRage.Game.ModAPI;
|
||||
|
||||
namespace Torch.Server.ViewModels
|
||||
{
|
||||
public class CharacterViewModel : EntityViewModel
|
||||
{
|
||||
public CharacterViewModel(MyCharacter character) : base(character)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
12
Torch.Server/ViewModels/Entities/CharacterViewModel.cs
Normal file
12
Torch.Server/ViewModels/Entities/CharacterViewModel.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using Sandbox.Game.Entities.Character;
|
||||
|
||||
namespace Torch.Server.ViewModels.Entities
|
||||
{
|
||||
public class CharacterViewModel : EntityViewModel
|
||||
{
|
||||
public CharacterViewModel(MyCharacter character) : base(character)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,13 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VRage.Game.ModAPI;
|
||||
using VRage.Game.ModAPI;
|
||||
using VRage.ModAPI;
|
||||
using VRageMath;
|
||||
|
||||
namespace Torch.Server.ViewModels
|
||||
namespace Torch.Server.ViewModels.Entities
|
||||
{
|
||||
public class EntityViewModel : ViewModel
|
||||
{
|
||||
@@ -45,5 +40,10 @@ namespace Torch.Server.ViewModels
|
||||
{
|
||||
Entity = entity;
|
||||
}
|
||||
|
||||
public EntityViewModel()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
49
Torch.Server/ViewModels/Entities/GridViewModel.cs
Normal file
49
Torch.Server/ViewModels/Entities/GridViewModel.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System.Linq;
|
||||
using Sandbox.Game.Entities;
|
||||
using Sandbox.ModAPI;
|
||||
using Torch.Server.ViewModels.Blocks;
|
||||
|
||||
namespace Torch.Server.ViewModels.Entities
|
||||
{
|
||||
public class GridViewModel : EntityViewModel
|
||||
{
|
||||
private MyCubeGrid Grid => (MyCubeGrid)Entity;
|
||||
public MTObservableCollection<BlockViewModel> Blocks { get; } = new MTObservableCollection<BlockViewModel>();
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Name => $"{base.Name} ({Grid.BlocksCount} blocks)";
|
||||
|
||||
public GridViewModel(MyCubeGrid grid) : base(grid)
|
||||
{
|
||||
TorchBase.Instance.InvokeBlocking(() =>
|
||||
{
|
||||
foreach (var block in grid.GetFatBlocks().Where(b => b is IMyTerminalBlock))
|
||||
{
|
||||
Blocks.Add(new BlockViewModel((IMyTerminalBlock)block));
|
||||
}
|
||||
});
|
||||
Blocks.Sort(b => b.Block.GetType().AssemblyQualifiedName);
|
||||
|
||||
grid.OnBlockAdded += Grid_OnBlockAdded;
|
||||
grid.OnBlockRemoved += Grid_OnBlockRemoved;
|
||||
}
|
||||
|
||||
private void Grid_OnBlockRemoved(Sandbox.Game.Entities.Cube.MySlimBlock obj)
|
||||
{
|
||||
if (obj.FatBlock != null)
|
||||
Blocks.RemoveWhere(b => b.Block.EntityId == obj.FatBlock?.EntityId);
|
||||
|
||||
Blocks.Sort(b => b.Block.GetType().AssemblyQualifiedName);
|
||||
OnPropertyChanged(nameof(Name));
|
||||
}
|
||||
|
||||
private void Grid_OnBlockAdded(Sandbox.Game.Entities.Cube.MySlimBlock obj)
|
||||
{
|
||||
if (obj.FatBlock != null)
|
||||
Blocks.Add(new BlockViewModel((IMyTerminalBlock)obj.FatBlock));
|
||||
|
||||
Blocks.Sort(b => b.Block.GetType().AssemblyQualifiedName);
|
||||
OnPropertyChanged(nameof(Name));
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,13 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Medieval.ObjectBuilders.Definitions;
|
||||
using Sandbox.Game.Entities;
|
||||
using VRage.ModAPI;
|
||||
using Sandbox.Game.Entities;
|
||||
|
||||
namespace Torch.Server.ViewModels
|
||||
namespace Torch.Server.ViewModels.Entities
|
||||
{
|
||||
public class VoxelMapViewModel : EntityViewModel
|
||||
{
|
@@ -5,6 +5,7 @@ using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Sandbox.Game.Entities;
|
||||
using Sandbox.Game.Entities.Character;
|
||||
using Torch.Server.ViewModels.Entities;
|
||||
using VRage.Game.ModAPI;
|
||||
using VRage.ModAPI;
|
||||
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Sandbox.Game.Entities;
|
||||
using Torch.Server.ViewModels.Entities;
|
||||
|
||||
namespace Torch.Server.ViewModels
|
||||
{
|
||||
|
@@ -1,23 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Sandbox.Game.Entities;
|
||||
using VRage.Game.ModAPI;
|
||||
|
||||
namespace Torch.Server.ViewModels
|
||||
{
|
||||
public class GridViewModel : EntityViewModel
|
||||
{
|
||||
private MyCubeGrid Grid => (MyCubeGrid)Entity;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Name => $"{base.Name} ({Grid.BlocksCount} blocks)";
|
||||
|
||||
public GridViewModel(MyCubeGrid grid) : base(grid)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
32
Torch.Server/Views/Blocks/BlockView.xaml
Normal file
32
Torch.Server/Views/Blocks/BlockView.xaml
Normal file
@@ -0,0 +1,32 @@
|
||||
<UserControl x:Class="Torch.Server.Views.Blocks.BlockView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Torch.Server.Views.Blocks"
|
||||
xmlns:blocks="clr-namespace:Torch.Server.ViewModels.Blocks"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.DataContext>
|
||||
<blocks:BlockViewModel />
|
||||
</UserControl.DataContext>
|
||||
<DockPanel x:Name="Stack" Margin="3">
|
||||
<Label Content="{Binding FullName}" FontSize="16" DockPanel.Dock="Top" />
|
||||
<ListView ItemsSource="{Binding Properties}" Margin="3" IsEnabled="True" DockPanel.Dock="Bottom">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<local:PropertyView />
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
<ListView.ItemContainerStyle>
|
||||
<Style TargetType="ListViewItem">
|
||||
<Setter Property="HorizontalContentAlignment"
|
||||
Value="Stretch" />
|
||||
<Setter Property="VerticalContentAlignment"
|
||||
Value="Center" />
|
||||
<Setter Property="Focusable"
|
||||
Value="false" />
|
||||
</Style>
|
||||
</ListView.ItemContainerStyle>
|
||||
</ListView>
|
||||
</DockPanel>
|
||||
</UserControl>
|
73
Torch.Server/Views/Blocks/BlockView.xaml.cs
Normal file
73
Torch.Server/Views/Blocks/BlockView.xaml.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
using Sandbox.ModAPI;
|
||||
using Sandbox.ModAPI.Interfaces;
|
||||
using Torch.Server.ViewModels.Blocks;
|
||||
using VRage.Game.ModAPI;
|
||||
|
||||
namespace Torch.Server.Views.Blocks
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for BlockView.xaml
|
||||
/// </summary>
|
||||
public partial class BlockView : UserControl
|
||||
{
|
||||
public BlockView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
/*
|
||||
public void SetTarget(BlockViewModel model)
|
||||
{
|
||||
DataContext = model;
|
||||
Stack.Children.Clear();
|
||||
|
||||
var propList = new List<ITerminalProperty>();
|
||||
model.Block.GetProperties(propList);
|
||||
foreach (var prop in propList)
|
||||
{
|
||||
Type propType = null;
|
||||
foreach (var iface in prop.GetType().GetInterfaces())
|
||||
{
|
||||
if (iface.IsGenericType && iface.GetGenericTypeDefinition() == typeof(ITerminalProperty<>))
|
||||
propType = iface.GenericTypeArguments[0];
|
||||
}
|
||||
|
||||
var modelType = typeof(PropertyViewModel<>).MakeGenericType(propType);
|
||||
var vm = Activator.CreateInstance(modelType, prop, model.Block);
|
||||
|
||||
var label = new Label { Content = $"{prop.Id}: "};
|
||||
var textBox = new TextBox { Margin = new Thickness(3) };
|
||||
var binding = new Binding("Value") {Source = vm};
|
||||
textBox.SetBinding(TextBox.TextProperty, binding);
|
||||
var stack = new DockPanel {Children = {label, textBox}, LastChildFill = true};
|
||||
Stack.Children.Add(stack);
|
||||
}
|
||||
|
||||
/*
|
||||
var properties = model.PropertyWrapper.GetType().GetProperties();
|
||||
foreach (var property in properties)
|
||||
{
|
||||
var control = new TextBox {Margin = new Thickness(3), Text = property.GetValue(model.PropertyWrapper).ToString()};
|
||||
var bindingPath = $"{nameof(model.PropertyWrapper)}.{property.Name}";
|
||||
var binding = new Binding {Path = new PropertyPath(bindingPath), Source = model};
|
||||
BindingOperations.SetBinding(control, TextBox.TextProperty, binding);
|
||||
Stack.Children.Add(control);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
21
Torch.Server/Views/Blocks/PropertyView.xaml
Normal file
21
Torch.Server/Views/Blocks/PropertyView.xaml
Normal file
@@ -0,0 +1,21 @@
|
||||
<UserControl x:Class="Torch.Server.Views.Blocks.PropertyView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Torch.Server.Views.Blocks"
|
||||
xmlns:blocks="clr-namespace:Torch.Server.ViewModels.Blocks"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Resources>
|
||||
<local:StringIdConverter x:Key="StringIdConverter"/>
|
||||
</UserControl.Resources>
|
||||
<DockPanel x:Name="Dock">
|
||||
<Label x:Name="Label" Width="150" VerticalAlignment="Center" DockPanel.Dock="Left">
|
||||
<Label.Content>
|
||||
<TextBlock Text="{Binding Name, StringFormat={}{0}: }" />
|
||||
</Label.Content>
|
||||
</Label>
|
||||
<Frame x:Name="Frame" DockPanel.Dock="Right" NavigationUIVisibility="Hidden"/>
|
||||
</DockPanel>
|
||||
</UserControl>
|
||||
|
104
Torch.Server/Views/Blocks/PropertyView.xaml.cs
Normal file
104
Torch.Server/Views/Blocks/PropertyView.xaml.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
using Torch.Server.ViewModels.Blocks;
|
||||
using VRage.Utils;
|
||||
|
||||
namespace Torch.Server.Views.Blocks
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for PropertyView.xaml
|
||||
/// </summary>
|
||||
public partial class PropertyView : UserControl
|
||||
{
|
||||
public PropertyView()
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContextChanged += OnDataContextChanged;
|
||||
}
|
||||
|
||||
private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs args)
|
||||
{
|
||||
switch (args.NewValue)
|
||||
{
|
||||
case PropertyViewModel<bool> vmBool:
|
||||
InitBool();
|
||||
break;
|
||||
case PropertyViewModel<StringBuilder> vmSb:
|
||||
InitStringBuilder();
|
||||
break;
|
||||
default:
|
||||
InitDefault();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void InitStringBuilder()
|
||||
{
|
||||
var textBox = new TextBox { VerticalAlignment = VerticalAlignment.Center, HorizontalAlignment = HorizontalAlignment.Stretch };
|
||||
var binding = new Binding("Value") { Source = DataContext, Converter = new StringBuilderConverter()};
|
||||
textBox.SetBinding(TextBox.TextProperty, binding);
|
||||
Frame.Content = textBox;
|
||||
|
||||
}
|
||||
|
||||
private void InitBool()
|
||||
{
|
||||
var checkBox = new CheckBox {VerticalAlignment = VerticalAlignment.Center, HorizontalAlignment = HorizontalAlignment.Left};
|
||||
var binding = new Binding("Value") { Source = DataContext };
|
||||
checkBox.SetBinding(CheckBox.IsCheckedProperty, binding);
|
||||
Frame.Content = checkBox;
|
||||
}
|
||||
|
||||
private void InitDefault()
|
||||
{
|
||||
var textBox = new TextBox { VerticalAlignment = VerticalAlignment.Center, HorizontalAlignment = HorizontalAlignment.Stretch};
|
||||
var binding = new Binding("Value") { Source = DataContext };
|
||||
textBox.SetBinding(TextBox.TextProperty, binding);
|
||||
Frame.Content = textBox;
|
||||
}
|
||||
}
|
||||
|
||||
public class StringBuilderConverter : IValueConverter
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return ((StringBuilder)value).ToString();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return new StringBuilder((string)value);
|
||||
}
|
||||
}
|
||||
|
||||
public class StringIdConverter : IValueConverter
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return MyStringId.GetOrCompute((string)value);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
}
|
@@ -5,6 +5,9 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Torch.Server.Views"
|
||||
xmlns:viewModels="clr-namespace:Torch.Server.ViewModels"
|
||||
xmlns:blocks="clr-namespace:Torch.Server.Views.Blocks"
|
||||
xmlns:entities="clr-namespace:Torch.Server.ViewModels.Entities"
|
||||
xmlns:blocks1="clr-namespace:Torch.Server.ViewModels.Blocks"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.DataContext>
|
||||
<viewModels:EntityTreeViewModel />
|
||||
@@ -17,15 +20,18 @@
|
||||
<Button Content="Stop" Click="Stop_OnClick" IsEnabled="{Binding CurrentEntity.CanStop}" Margin="3" />
|
||||
</StackPanel>
|
||||
<TreeView Width="300" Margin="3" DockPanel.Dock="Top" SelectedItemChanged="TreeView_OnSelectedItemChanged">
|
||||
<TreeView.Resources>
|
||||
<HierarchicalDataTemplate DataType="{x:Type entities:GridViewModel}" ItemsSource="{Binding Blocks}">
|
||||
<TextBlock Text="{Binding Name}" />
|
||||
</HierarchicalDataTemplate>
|
||||
<DataTemplate DataType="{x:Type blocks1:BlockViewModel}">
|
||||
<TextBlock Text="{Binding Path=Name}" />
|
||||
</DataTemplate>
|
||||
</TreeView.Resources>
|
||||
<TreeViewItem ItemsSource="{Binding Grids}" IsExpanded="true">
|
||||
<TreeViewItem.Header>
|
||||
<TextBlock Text="{Binding Grids.Count, StringFormat=Grids ({0})}" />
|
||||
</TreeViewItem.Header>
|
||||
<TreeViewItem.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Name}" />
|
||||
</DataTemplate>
|
||||
</TreeViewItem.ItemTemplate>
|
||||
</TreeViewItem>
|
||||
<TreeViewItem ItemsSource="{Binding Characters}" IsExpanded="true">
|
||||
<TreeViewItem.Header>
|
||||
@@ -59,6 +65,6 @@
|
||||
</TreeViewItem>
|
||||
</TreeView>
|
||||
</DockPanel>
|
||||
<Frame Margin="3" />
|
||||
<Frame x:Name="EditorFrame" Margin="3" NavigationUIVisibility="Hidden" />
|
||||
</DockPanel>
|
||||
</UserControl>
|
@@ -13,6 +13,9 @@ using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
using Torch.Server.ViewModels;
|
||||
using Torch.Server.ViewModels.Blocks;
|
||||
using Torch.Server.ViewModels.Entities;
|
||||
using Torch.Server.Views.Blocks;
|
||||
using VRage.Game.ModAPI;
|
||||
|
||||
namespace Torch.Server.Views
|
||||
@@ -33,7 +36,11 @@ namespace Torch.Server.Views
|
||||
private void TreeView_OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
|
||||
{
|
||||
if (e.NewValue is EntityViewModel vm)
|
||||
{
|
||||
Entities.CurrentEntity = vm;
|
||||
if (e.NewValue is BlockViewModel bvm)
|
||||
EditorFrame.Content = new BlockView { DataContext = bvm };
|
||||
}
|
||||
else
|
||||
Entities.CurrentEntity = null;
|
||||
}
|
||||
|
@@ -33,12 +33,25 @@ namespace Torch
|
||||
}
|
||||
}
|
||||
|
||||
public void Sort<TKey>(Func<T, TKey> selector, IComparer<TKey> comparer = null)
|
||||
{
|
||||
List<T> sortedItems;
|
||||
if (comparer != null)
|
||||
sortedItems = Items.OrderBy(selector, comparer).ToList();
|
||||
else
|
||||
sortedItems = Items.OrderBy(selector).ToList();
|
||||
|
||||
Items.Clear();
|
||||
foreach (var item in sortedItems)
|
||||
Add(item);
|
||||
}
|
||||
|
||||
public void RemoveWhere(Func<T, bool> condition)
|
||||
{
|
||||
for (var i = Items.Count - 1; i > 0; i--)
|
||||
{
|
||||
if (condition(Items[i]))
|
||||
Items.RemoveAt(i);
|
||||
RemoveAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user