diff --git a/.gitignore b/.gitignore index 10657cc1b..5a56e2911 100644 --- a/.gitignore +++ b/.gitignore @@ -50,7 +50,7 @@ artifacts/ *_i.h *.ilk *.meta -*.obj +#*.obj *.pch *.pdb *.pgc @@ -261,4 +261,4 @@ __pycache__/ *.pyc # dbc -.DS_Store \ No newline at end of file +.DS_Store diff --git a/Avalonia.props b/Avalonia.props index e80105b46..87fb61713 100644 --- a/Avalonia.props +++ b/Avalonia.props @@ -4,7 +4,7 @@ - + diff --git a/AvaloniaEdit b/AvaloniaEdit index 90540be74..e81fb0baa 160000 --- a/AvaloniaEdit +++ b/AvaloniaEdit @@ -1 +1 @@ -Subproject commit 90540be743bbae6b680314f817f2ce3cc49ba566 +Subproject commit e81fb0baa453c756fc85e8c6f60c531518cd42fb diff --git a/AvaloniaStyles/Styles/BigSur/Button.xaml b/AvaloniaStyles/Styles/BigSur/Button.xaml index de4ad883e..6e2817e2a 100644 --- a/AvaloniaStyles/Styles/BigSur/Button.xaml +++ b/AvaloniaStyles/Styles/BigSur/Button.xaml @@ -10,7 +10,7 @@ + diff --git a/WDE.WorldMap/WoWMapViewer.axaml.cs b/WDE.WorldMap/WoWMapViewer.axaml.cs new file mode 100644 index 000000000..ad680fb1a --- /dev/null +++ b/WDE.WorldMap/WoWMapViewer.axaml.cs @@ -0,0 +1,140 @@ +using System; +using Avalonia; +using Avalonia.Controls; +using Avalonia.Controls.Primitives; +using Avalonia.Threading; +using WDE.WorldMap.Models; +using WDE.WorldMap.PanAndZoom; + +namespace WDE.WorldMap +{ + public class WoWMapViewer : ContentControl + { + private double zoom; + public static readonly DirectProperty ZoomProperty = AvaloniaProperty.RegisterDirect("Zoom", o => o.Zoom, (o, v) => o.Zoom = v); + + private string? map; + public static readonly DirectProperty MapProperty = AvaloniaProperty.RegisterDirect("Map", o => o.Map, (o, v) => o.Map = v); + + private string? mapsPath; + public static readonly DirectProperty MapsPathProperty = AvaloniaProperty.RegisterDirect("MapsPath", o => o.MapsPath, (o, v) => o.MapsPath = v); + + private IMapContext? mapViewModel; + public static readonly DirectProperty MapViewModelProperty = AvaloniaProperty.RegisterDirect("Context", o => o.MapViewModel, (o, v) => o.MapViewModel = v); + + private bool renderBackground = true; + public static readonly DirectProperty RenderBackgroundProperty = AvaloniaProperty.RegisterDirect("RenderBackground", o => o.RenderBackground, (o, v) => o.RenderBackground = v); + + private Point topLeftVirtual; + public static readonly DirectProperty TopLeftVirtualProperty = AvaloniaProperty.RegisterDirect("TopLeftVirtual", o => o.TopLeftVirtual, (o, v) => o.TopLeftVirtual = v); + + private Point bottomRightVirtual; + public static readonly DirectProperty BottomRightVirtualProperty = AvaloniaProperty.RegisterDirect("BottomRightVirtual", o => o.BottomRightVirtual, (o, v) => o.BottomRightVirtual = v); + + private ExtendedZoomBorder? zoomBorder; + + public double Zoom + { + get => zoom; + set => SetAndRaise(ZoomProperty, ref zoom, value); + } + + public string? Map + { + get => map; + set => SetAndRaise(MapProperty, ref map, value); + } + + public string? MapsPath + { + get => mapsPath; + set => SetAndRaise(MapsPathProperty, ref mapsPath, value); + } + + private void OnCenter(double x, double y) + { + var editorCoords = CoordsUtils.WorldToEditor(x, y); + if (zoomBorder != null) + zoomBorder.SetCenter(editorCoords.editorX, editorCoords.editorY); + } + + private void BoundsToView(double left, double right, double top, double bottom) + { + var leftTopEditor = CoordsUtils.WorldToEditor(left - 10, top - 10); + var rightBottomEditor = CoordsUtils.WorldToEditor(right + 10, bottom + 10); + if (zoomBorder != null) + zoomBorder.MoveToBounds(leftTopEditor.editorX, rightBottomEditor.editorX, leftTopEditor.editorY, rightBottomEditor.editorY); + } + + public IMapContext? MapViewModel + { + get => mapViewModel; + set + { + if (mapViewModel != null) + Unbind(mapViewModel); + SetAndRaise(MapViewModelProperty, ref mapViewModel, value); + if (value != null && Parent != null) + Bind(value); + } + } + + public bool RenderBackground + { + get => renderBackground; + set => SetAndRaise(RenderBackgroundProperty, ref renderBackground, value); + } + + public Point TopLeftVirtual + { + get => topLeftVirtual; + set => SetAndRaise(TopLeftVirtualProperty, ref topLeftVirtual, value); + } + + public Point BottomRightVirtual + { + get => bottomRightVirtual; + set => SetAndRaise(BottomRightVirtualProperty, ref bottomRightVirtual, value); + } + + private void Bind(IMapContext ctx) + { + ctx.RequestCenter += OnCenter; + ctx.RequestBoundsToView += BoundsToView; + InvalidateVisual(); + } + + private void Unbind(IMapContext ctx) + { + ctx.RequestCenter -= OnCenter; + ctx.RequestBoundsToView -= BoundsToView; + } + + protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) + { + if (mapViewModel != null) + { + Unbind(mapViewModel); + Bind(mapViewModel); + } + } + + protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e) + { + if (mapViewModel != null) + Unbind(mapViewModel); + } + + protected override void OnApplyTemplate(TemplateAppliedEventArgs e) + { + base.OnApplyTemplate(e); + zoomBorder = e.NameScope.Find("ZoomBorder"); + + DispatcherTimer.RunOnce(() => + { + if (mapViewModel != null) + mapViewModel.Initialized(); + }, TimeSpan.FromMilliseconds(500)); + } + } +} \ No newline at end of file diff --git a/WDE.WorldMap/WorldMapModule.cs b/WDE.WorldMap/WorldMapModule.cs new file mode 100644 index 000000000..6821493e6 --- /dev/null +++ b/WDE.WorldMap/WorldMapModule.cs @@ -0,0 +1,11 @@ +using System; +using WDE.Module; +using WDE.Module.Attributes; + +namespace WDE.WorldMap +{ + [AutoRegister] + public class WorldMapModule : ModuleBase + { + } +} \ No newline at end of file diff --git a/WoWDatabaseEditor.Common/WDE.Common/DBC/IDatabaseClientFileOpener.cs b/WoWDatabaseEditor.Common/WDE.Common/DBC/IDatabaseClientFileOpener.cs new file mode 100644 index 000000000..abd19abed --- /dev/null +++ b/WoWDatabaseEditor.Common/WDE.Common/DBC/IDatabaseClientFileOpener.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; +using WDE.Module.Attributes; + +namespace WDE.Common.DBC +{ + [UniqueProvider] + public interface IDatabaseClientFileOpener + { + IEnumerable Open(byte[] data); + IEnumerable Open(string path); + } +} \ No newline at end of file diff --git a/WoWDatabaseEditor.Common/WDE.DbcStore/FastReader/IDbcIterator.cs b/WoWDatabaseEditor.Common/WDE.Common/DBC/IDbcIterator.cs similarity index 86% rename from WoWDatabaseEditor.Common/WDE.DbcStore/FastReader/IDbcIterator.cs rename to WoWDatabaseEditor.Common/WDE.Common/DBC/IDbcIterator.cs index 02b4a95f3..1c72f97bd 100644 --- a/WoWDatabaseEditor.Common/WDE.DbcStore/FastReader/IDbcIterator.cs +++ b/WoWDatabaseEditor.Common/WDE.Common/DBC/IDbcIterator.cs @@ -1,4 +1,4 @@ -namespace WDE.DbcStore.FastReader +namespace WDE.Common.DBC { public interface IDbcIterator { diff --git a/WoWDatabaseEditor.Common/WDE.Common/MPQ/IMpqService.cs b/WoWDatabaseEditor.Common/WDE.Common/MPQ/IMpqService.cs index 2b199b429..a506b48a6 100644 --- a/WoWDatabaseEditor.Common/WDE.Common/MPQ/IMpqService.cs +++ b/WoWDatabaseEditor.Common/WDE.Common/MPQ/IMpqService.cs @@ -5,6 +5,7 @@ namespace WDE.Common.MPQ [UniqueProvider] public interface IMpqService { + bool IsConfigured(); IMpqArchive Open(); } } \ No newline at end of file diff --git a/WoWDatabaseEditor.Common/WDE.Common/Services/ISolutionTasksService.cs b/WoWDatabaseEditor.Common/WDE.Common/Services/ISolutionTasksService.cs index b68ea1444..aabdfefe4 100644 --- a/WoWDatabaseEditor.Common/WDE.Common/Services/ISolutionTasksService.cs +++ b/WoWDatabaseEditor.Common/WDE.Common/Services/ISolutionTasksService.cs @@ -1,13 +1,14 @@ -using WDE.Module.Attributes; +using System.Threading.Tasks; +using WDE.Module.Attributes; namespace WDE.Common.Services { [UniqueProvider] public interface ISolutionTasksService { - void SaveSolutionToDatabaseTask(ISolutionItem item); - void ReloadSolutionRemotelyTask(ISolutionItem item); - void SaveAndReloadSolutionTask(ISolutionItem item); + Task SaveSolutionToDatabaseTask(ISolutionItem item); + Task ReloadSolutionRemotelyTask(ISolutionItem item); + Task SaveAndReloadSolutionTask(ISolutionItem item); bool CanSaveToDatabase { get; } bool CanReloadRemotely { get; } diff --git a/WoWDatabaseEditor.Common/WDE.Common/Tasks/GlobalApplication.cs b/WoWDatabaseEditor.Common/WDE.Common/Tasks/GlobalApplication.cs index 490a2df22..d26f7b31a 100644 --- a/WoWDatabaseEditor.Common/WDE.Common/Tasks/GlobalApplication.cs +++ b/WoWDatabaseEditor.Common/WDE.Common/Tasks/GlobalApplication.cs @@ -30,6 +30,7 @@ public static IMainThread MainThread public static bool HighDpi { get; set; } public static bool IsRunning { get; set; } = true; + public static bool Supports3D { get; set; } = true; public static void InitializeApplication(IMainThread thread, AppBackend backend) { diff --git a/WoWDatabaseEditor.Common/WDE.Common/Utils/ListExtensions.cs b/WoWDatabaseEditor.Common/WDE.Common/Utils/ListExtensions.cs index f09ffe784..805d011de 100644 --- a/WoWDatabaseEditor.Common/WDE.Common/Utils/ListExtensions.cs +++ b/WoWDatabaseEditor.Common/WDE.Common/Utils/ListExtensions.cs @@ -38,6 +38,19 @@ public static void OverrideWith(this IList that, IList with) return default; } + public static int IndexIf(this IList list, Func pred) + { + for (int i = 0; i < list.Count; i++) + { + if (pred(list[i])) + { + return i; + } + } + + return -1; + } + public static T? RemoveIf(this IList list, Func pred) { for (int i = list.Count - 1; i >= 0; i--) diff --git a/WoWDatabaseEditor.Common/WDE.Common/Windows/ITool.cs b/WoWDatabaseEditor.Common/WDE.Common/Windows/ITool.cs index 070d53703..fc162b6ca 100644 --- a/WoWDatabaseEditor.Common/WDE.Common/Windows/ITool.cs +++ b/WoWDatabaseEditor.Common/WDE.Common/Windows/ITool.cs @@ -21,6 +21,6 @@ public interface IFocusableTool : ITool public enum ToolPreferedPosition { - Left, Right, Bottom + Left, Right, Bottom, DocumentCenter } } \ No newline at end of file diff --git a/WoWDatabaseEditor.Common/WDE.DbcStore/FastReader/DatabaseClientFileOpener.cs b/WoWDatabaseEditor.Common/WDE.DbcStore/FastReader/DatabaseClientFileOpener.cs index 41346c773..c47eb337b 100644 --- a/WoWDatabaseEditor.Common/WDE.DbcStore/FastReader/DatabaseClientFileOpener.cs +++ b/WoWDatabaseEditor.Common/WDE.DbcStore/FastReader/DatabaseClientFileOpener.cs @@ -1,11 +1,26 @@ using System; using System.Collections.Generic; using System.IO; +using WDE.Common.DBC; +using WDE.Module.Attributes; namespace WDE.DbcStore.FastReader { - public class DatabaseClientFileOpener + [AutoRegister] + public class DatabaseClientFileOpener : IDatabaseClientFileOpener { + public IEnumerable Open(byte[] data) + { + uint magic = BitConverter.ToUInt32(data); + if (magic == FastDbcReader.WDBC) + return new FastDbcReader(data); + + if (magic == FastDb2Reader.WDB2) + return new FastDb2Reader(data); + + throw new Exception("Only dbc and db2 supported"); + } + public IEnumerable Open(string path) { byte[] buffer = new byte[4]; diff --git a/WoWDatabaseEditor.Common/WDE.DbcStore/FastReader/FastDBCReader.cs b/WoWDatabaseEditor.Common/WDE.DbcStore/FastReader/FastDBCReader.cs index 6af94d0d1..f041a3b6b 100644 --- a/WoWDatabaseEditor.Common/WDE.DbcStore/FastReader/FastDBCReader.cs +++ b/WoWDatabaseEditor.Common/WDE.DbcStore/FastReader/FastDBCReader.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Text; +using WDE.Common.DBC; namespace WDE.DbcStore.FastReader { diff --git a/WoWDatabaseEditor.Common/WDE.DbcStore/FastReader/FastDb2Reader.cs b/WoWDatabaseEditor.Common/WDE.DbcStore/FastReader/FastDb2Reader.cs index 755deb1ca..47e27621f 100644 --- a/WoWDatabaseEditor.Common/WDE.DbcStore/FastReader/FastDb2Reader.cs +++ b/WoWDatabaseEditor.Common/WDE.DbcStore/FastReader/FastDb2Reader.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Text; +using WDE.Common.DBC; namespace WDE.DbcStore.FastReader { diff --git a/WoWDatabaseEditor.Common/WDE.DbcStore/FastReader/SlowWdcReaderWrapper.cs b/WoWDatabaseEditor.Common/WDE.DbcStore/FastReader/SlowWdcReaderWrapper.cs index a773fc40d..fc517fe62 100644 --- a/WoWDatabaseEditor.Common/WDE.DbcStore/FastReader/SlowWdcReaderWrapper.cs +++ b/WoWDatabaseEditor.Common/WDE.DbcStore/FastReader/SlowWdcReaderWrapper.cs @@ -4,6 +4,7 @@ using System.Data; using WDBXEditor.Reader; using WDBXEditor.Storage; +using WDE.Common.DBC; namespace WDE.DbcStore.FastReader { diff --git a/WoWDatabaseEditor.sln b/WoWDatabaseEditor.sln index c41e8dab5..62ad0369b 100644 --- a/WoWDatabaseEditor.sln +++ b/WoWDatabaseEditor.sln @@ -233,6 +233,22 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WDE.SqlInterpreter.Test", " EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WDE.MPQ", "WDE.MPQ\WDE.MPQ.csproj", "{F63A6DDA-874A-41FF-A707-3B95862036A5}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenGLBindings", "Rendering\OpenGLBindings\OpenGLBindings.csproj", "{22B7CA06-975B-452A-96FB-78ED9988B94A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TheAvaloniaOpenGL", "Rendering\TheAvaloniaOpenGL\TheAvaloniaOpenGL.csproj", "{CCD7E775-0ED3-498D-A958-CEB993F42BDE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TheEngine", "Rendering\TheEngine\TheEngine.csproj", "{05F74B30-019C-475B-BC54-79D470EB9EAA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TheMaths", "Rendering\TheMaths\TheMaths.csproj", "{6FF3D2AA-4FC5-4D50-A529-FCAC89CAC392}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WDE.MapRenderer", "WDE.MapRenderer\WDE.MapRenderer.csproj", "{28C4ACA6-EFD8-4A21-BD32-B2404EB59D68}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WDE.MpqReader", "WDE.MpqReader\WDE.MpqReader.csproj", "{B72EDF49-BF73-407A-A381-8FB7BD91A61D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TheEngine.Test", "Rendering\TheEngine.Test\TheEngine.Test.csproj", "{B6C2EDA7-665A-4CF1-97CF-356BB5141339}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WDE.WorldMap", "WoWDatabaseEditor\WDE.WorldMap\WDE.WorldMap.csproj", "{7A409931-190E-44E5-B5AC-159FA1743F07}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -540,6 +556,40 @@ Global {F63A6DDA-874A-41FF-A707-3B95862036A5}.Debug|Any CPU.Build.0 = Debug|Any CPU {F63A6DDA-874A-41FF-A707-3B95862036A5}.Release|Any CPU.ActiveCfg = Release|Any CPU {F63A6DDA-874A-41FF-A707-3B95862036A5}.Release|Any CPU.Build.0 = Release|Any CPU + + + {7A409931-190E-44E5-B5AC-159FA1743F07}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7A409931-190E-44E5-B5AC-159FA1743F07}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7A409931-190E-44E5-B5AC-159FA1743F07}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7A409931-190E-44E5-B5AC-159FA1743F07}.Release|Any CPU.Build.0 = Release|Any CPU + {22B7CA06-975B-452A-96FB-78ED9988B94A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {22B7CA06-975B-452A-96FB-78ED9988B94A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {22B7CA06-975B-452A-96FB-78ED9988B94A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {22B7CA06-975B-452A-96FB-78ED9988B94A}.Release|Any CPU.Build.0 = Release|Any CPU + {CCD7E775-0ED3-498D-A958-CEB993F42BDE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CCD7E775-0ED3-498D-A958-CEB993F42BDE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CCD7E775-0ED3-498D-A958-CEB993F42BDE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CCD7E775-0ED3-498D-A958-CEB993F42BDE}.Release|Any CPU.Build.0 = Release|Any CPU + {05F74B30-019C-475B-BC54-79D470EB9EAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {05F74B30-019C-475B-BC54-79D470EB9EAA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {05F74B30-019C-475B-BC54-79D470EB9EAA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {05F74B30-019C-475B-BC54-79D470EB9EAA}.Release|Any CPU.Build.0 = Release|Any CPU + {6FF3D2AA-4FC5-4D50-A529-FCAC89CAC392}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6FF3D2AA-4FC5-4D50-A529-FCAC89CAC392}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6FF3D2AA-4FC5-4D50-A529-FCAC89CAC392}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6FF3D2AA-4FC5-4D50-A529-FCAC89CAC392}.Release|Any CPU.Build.0 = Release|Any CPU + {28C4ACA6-EFD8-4A21-BD32-B2404EB59D68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {28C4ACA6-EFD8-4A21-BD32-B2404EB59D68}.Debug|Any CPU.Build.0 = Debug|Any CPU + {28C4ACA6-EFD8-4A21-BD32-B2404EB59D68}.Release|Any CPU.ActiveCfg = Release|Any CPU + {28C4ACA6-EFD8-4A21-BD32-B2404EB59D68}.Release|Any CPU.Build.0 = Release|Any CPU + {B72EDF49-BF73-407A-A381-8FB7BD91A61D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B72EDF49-BF73-407A-A381-8FB7BD91A61D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B72EDF49-BF73-407A-A381-8FB7BD91A61D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B72EDF49-BF73-407A-A381-8FB7BD91A61D}.Release|Any CPU.Build.0 = Release|Any CPU + {B6C2EDA7-665A-4CF1-97CF-356BB5141339}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B6C2EDA7-665A-4CF1-97CF-356BB5141339}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B6C2EDA7-665A-4CF1-97CF-356BB5141339}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B6C2EDA7-665A-4CF1-97CF-356BB5141339}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -616,5 +666,13 @@ Global {5AE7D201-A541-49F3-A980-3935D3FCA48D} = {4C553308-1140-42F2-B99C-90402248A983} {0370DA8A-3EC6-445E-97AF-0F517D853E1E} = {4C553308-1140-42F2-B99C-90402248A983} {F63A6DDA-874A-41FF-A707-3B95862036A5} = {4C553308-1140-42F2-B99C-90402248A983} + + {22B7CA06-975B-452A-96FB-78ED9988B94A} = {C9F8B770-A4E7-479A-A8A0-0DE5A1838AFD} + {CCD7E775-0ED3-498D-A958-CEB993F42BDE} = {C9F8B770-A4E7-479A-A8A0-0DE5A1838AFD} + {05F74B30-019C-475B-BC54-79D470EB9EAA} = {C9F8B770-A4E7-479A-A8A0-0DE5A1838AFD} + {6FF3D2AA-4FC5-4D50-A529-FCAC89CAC392} = {C9F8B770-A4E7-479A-A8A0-0DE5A1838AFD} + {28C4ACA6-EFD8-4A21-BD32-B2404EB59D68} = {C9F8B770-A4E7-479A-A8A0-0DE5A1838AFD} + {B72EDF49-BF73-407A-A381-8FB7BD91A61D} = {C9F8B770-A4E7-479A-A8A0-0DE5A1838AFD} + {B6C2EDA7-665A-4CF1-97CF-356BB5141339} = {C9F8B770-A4E7-479A-A8A0-0DE5A1838AFD} EndGlobalSection EndGlobal diff --git a/WoWDatabaseEditor/Icons/icon_3d.png b/WoWDatabaseEditor/Icons/icon_3d.png new file mode 100644 index 000000000..6ce4988f2 Binary files /dev/null and b/WoWDatabaseEditor/Icons/icon_3d.png differ diff --git a/WoWDatabaseEditor/Icons/icon_3d@2x.png b/WoWDatabaseEditor/Icons/icon_3d@2x.png new file mode 100644 index 000000000..7e9e76ecd Binary files /dev/null and b/WoWDatabaseEditor/Icons/icon_3d@2x.png differ diff --git a/WoWDatabaseEditor/Icons/icon_3d_dark.png b/WoWDatabaseEditor/Icons/icon_3d_dark.png new file mode 100644 index 000000000..94608c77d Binary files /dev/null and b/WoWDatabaseEditor/Icons/icon_3d_dark.png differ diff --git a/WoWDatabaseEditor/Icons/icon_3d_dark@2x.png b/WoWDatabaseEditor/Icons/icon_3d_dark@2x.png new file mode 100644 index 000000000..5d89625f6 Binary files /dev/null and b/WoWDatabaseEditor/Icons/icon_3d_dark@2x.png differ diff --git a/WoWDatabaseEditor/Icons/icon_day_night.png b/WoWDatabaseEditor/Icons/icon_day_night.png new file mode 100644 index 000000000..1452fbb6f Binary files /dev/null and b/WoWDatabaseEditor/Icons/icon_day_night.png differ diff --git a/WoWDatabaseEditor/Icons/icon_day_night@2x.png b/WoWDatabaseEditor/Icons/icon_day_night@2x.png new file mode 100644 index 000000000..4c1971a88 Binary files /dev/null and b/WoWDatabaseEditor/Icons/icon_day_night@2x.png differ diff --git a/WoWDatabaseEditor/Icons/icon_grid.png b/WoWDatabaseEditor/Icons/icon_grid.png new file mode 100644 index 000000000..89791e91f Binary files /dev/null and b/WoWDatabaseEditor/Icons/icon_grid.png differ diff --git a/WoWDatabaseEditor/Icons/icon_grid@2x.png b/WoWDatabaseEditor/Icons/icon_grid@2x.png new file mode 100644 index 000000000..7f0ee3a5a Binary files /dev/null and b/WoWDatabaseEditor/Icons/icon_grid@2x.png differ diff --git a/WoWDatabaseEditor/Icons/icon_grid_dark.png b/WoWDatabaseEditor/Icons/icon_grid_dark.png new file mode 100644 index 000000000..044102ee2 Binary files /dev/null and b/WoWDatabaseEditor/Icons/icon_grid_dark.png differ diff --git a/WoWDatabaseEditor/Icons/icon_grid_dark@2x.png b/WoWDatabaseEditor/Icons/icon_grid_dark@2x.png new file mode 100644 index 000000000..3e080f098 Binary files /dev/null and b/WoWDatabaseEditor/Icons/icon_grid_dark@2x.png differ diff --git a/WoWDatabaseEditor/Icons/icon_pause.png b/WoWDatabaseEditor/Icons/icon_pause.png new file mode 100644 index 000000000..6a97aff28 Binary files /dev/null and b/WoWDatabaseEditor/Icons/icon_pause.png differ diff --git a/WoWDatabaseEditor/Icons/icon_pause@2x.png b/WoWDatabaseEditor/Icons/icon_pause@2x.png new file mode 100644 index 000000000..d52dce6af Binary files /dev/null and b/WoWDatabaseEditor/Icons/icon_pause@2x.png differ diff --git a/WoWDatabaseEditor/Icons/icon_play_path.png b/WoWDatabaseEditor/Icons/icon_play_path.png new file mode 100644 index 000000000..99086348b Binary files /dev/null and b/WoWDatabaseEditor/Icons/icon_play_path.png differ diff --git a/WoWDatabaseEditor/Icons/icon_play_path@2x.png b/WoWDatabaseEditor/Icons/icon_play_path@2x.png new file mode 100644 index 000000000..d8a06ca7e Binary files /dev/null and b/WoWDatabaseEditor/Icons/icon_play_path@2x.png differ diff --git a/WoWDatabaseEditor/Services/SolutionService/SolutionTasksService.cs b/WoWDatabaseEditor/Services/SolutionService/SolutionTasksService.cs index 043bb070e..cfb7cc94a 100644 --- a/WoWDatabaseEditor/Services/SolutionService/SolutionTasksService.cs +++ b/WoWDatabaseEditor/Services/SolutionService/SolutionTasksService.cs @@ -1,4 +1,5 @@ using System; +using System.Threading.Tasks; using WDE.Common; using WDE.Common.Database; using WDE.Common.Managers; @@ -41,13 +42,13 @@ public SolutionTasksService(ITaskRunner taskRunner, this.statusBar = statusBar; } - public void SaveSolutionToDatabaseTask(ISolutionItem item) + public Task SaveSolutionToDatabaseTask(ISolutionItem item) { if (!CanSaveToDatabase) - return; + return Task.CompletedTask; var itemName = solutionItemNameRegistry.GetName(item); - taskRunner.ScheduleTask($"Export {itemName} to database", + return taskRunner.ScheduleTask($"Export {itemName} to database", async progress => { progress.Report(0, 2, "Generate query"); @@ -66,11 +67,11 @@ public void SaveSolutionToDatabaseTask(ISolutionItem item) }); } - public void ReloadSolutionRemotelyTask(ISolutionItem item) + public Task ReloadSolutionRemotelyTask(ISolutionItem item) { var itemName = solutionItemNameRegistry.GetName(item); - taskRunner.ScheduleTask($"Reload {itemName} on server", + return taskRunner.ScheduleTask($"Reload {itemName} on server", async progress => { var commands = remoteCommandGenerator.GenerateCommand(item); @@ -99,10 +100,10 @@ public void ReloadSolutionRemotelyTask(ISolutionItem item) }); } - public void SaveAndReloadSolutionTask(ISolutionItem item) + public Task SaveAndReloadSolutionTask(ISolutionItem item) { var itemName = solutionItemNameRegistry.GetName(item); - taskRunner.ScheduleTask($"Save and reload {itemName} on server", + return taskRunner.ScheduleTask($"Save and reload {itemName} on server", async progress => { progress.Report(0, 1, "Generate query"); diff --git a/WoWDatabaseEditor/ViewModels/MainWindowViewModel.cs b/WoWDatabaseEditor/ViewModels/MainWindowViewModel.cs index a9dd91223..a10bee288 100644 --- a/WoWDatabaseEditor/ViewModels/MainWindowViewModel.cs +++ b/WoWDatabaseEditor/ViewModels/MainWindowViewModel.cs @@ -29,7 +29,7 @@ public class MainWindowViewModel : ObservableBase, ILayoutViewModelResolver, ICl private readonly Func quickStartCreator; private readonly Func textDocumentCreator; - private string title = "WoW Database Editor 2021.2"; + private string title = "WoW Database Editor 2021.3"; private readonly Dictionary toolById = new(); public MainWindowViewModel(IDocumentManager documentManager, diff --git a/WoWDatabaseEditorCore.Avalonia/App.xaml.cs b/WoWDatabaseEditorCore.Avalonia/App.xaml.cs index 7a1f22892..3006f9818 100644 --- a/WoWDatabaseEditorCore.Avalonia/App.xaml.cs +++ b/WoWDatabaseEditorCore.Avalonia/App.xaml.cs @@ -100,6 +100,7 @@ protected override IContainerExtension CreateContainerExtension() var container = new UnityContainerExtension(unity); var mainScope = new ScopedContainer(container, unity); container.RegisterInstance(mainScope); + ViewBind.ContainerProvider = container; return container; } diff --git a/WoWDatabaseEditorCore.Avalonia/Docking/AvaloniaDockAdapter.cs b/WoWDatabaseEditorCore.Avalonia/Docking/AvaloniaDockAdapter.cs index 210bfd436..a1e2fda7b 100644 --- a/WoWDatabaseEditorCore.Avalonia/Docking/AvaloniaDockAdapter.cs +++ b/WoWDatabaseEditorCore.Avalonia/Docking/AvaloniaDockAdapter.cs @@ -2,6 +2,7 @@ using Dock.Model.Controls; using Dock.Model.Core; using WDE.Common.Managers; +using WDE.Common.Windows; using WDE.MVVM; using WDE.MVVM.Observable; using WoWDatabaseEditorCore.Avalonia.Docking.Serialization; @@ -110,7 +111,14 @@ public AvaloniaDockAdapter(IDocumentManager documentManager, ILayoutViewModelRes { var dockable = new AvaloniaToolDockWrapper(documentManager, tool); tools[tool] = dockable; - factory.AddTool(currentLayout!, dockable); + if (tool.PreferedPosition == ToolPreferedPosition.DocumentCenter) + factory.AddToolAsDocument(currentLayout!, dockable); + else + factory.AddTool(currentLayout!, dockable); + factory.SetActiveDockable(dockable); + } else if (isVisible && tools.ContainsKey(tool)) + { + factory.SetActiveDockable(tools[tool]); } else if (!isVisible) { diff --git a/WoWDatabaseEditorCore.Avalonia/Docking/AvaloniaToolDockWrapper.cs b/WoWDatabaseEditorCore.Avalonia/Docking/AvaloniaToolDockWrapper.cs index aadbf859f..0e40de588 100644 --- a/WoWDatabaseEditorCore.Avalonia/Docking/AvaloniaToolDockWrapper.cs +++ b/WoWDatabaseEditorCore.Avalonia/Docking/AvaloniaToolDockWrapper.cs @@ -1,4 +1,5 @@ -using Dock.Model.ReactiveUI.Controls; +using System; +using Dock.Model.ReactiveUI.Controls; using WDE.Common.Managers; using WDE.Common.Windows; using ITool = WDE.Common.Windows.ITool; diff --git a/WoWDatabaseEditorCore.Avalonia/Docking/DockFactory.cs b/WoWDatabaseEditorCore.Avalonia/Docking/DockFactory.cs index 145c77b31..faa0f33ff 100644 --- a/WoWDatabaseEditorCore.Avalonia/Docking/DockFactory.cs +++ b/WoWDatabaseEditorCore.Avalonia/Docking/DockFactory.cs @@ -14,6 +14,18 @@ public class DockFactory : Factory public override IDocumentDock CreateDocumentDock() => new FocusAwareDocumentDock() {CanFloat = false}; public override IToolDock CreateToolDock() => new FocusAwareToolDock() {CanFloat = false}; + public void AddToolAsDocument(IDock layout, AvaloniaToolDockWrapper tool) + { + var documentsDock = FindDockable(layout, dockable => dockable is IDocumentDock) as IDocumentDock; + if (documentsDock == null) + { + documentsDock = CreateDocumentDock(); + documentsDock.Proportion = 1; + AddDockable(layout, documentsDock); + } + AddDockable(documentsDock, tool); + } + public void AddDocument(IDock layout, AvaloniaDocumentDockWrapper document) { var documentsDock = FindDockable(layout, dockable => dockable is IDocumentDock) as IDocumentDock; diff --git a/WoWDatabaseEditorCore.Avalonia/Docking/PersistentDockDataTemplate.cs b/WoWDatabaseEditorCore.Avalonia/Docking/PersistentDockDataTemplate.cs index c70c02c1c..bbd8dda68 100644 --- a/WoWDatabaseEditorCore.Avalonia/Docking/PersistentDockDataTemplate.cs +++ b/WoWDatabaseEditorCore.Avalonia/Docking/PersistentDockDataTemplate.cs @@ -1,12 +1,15 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Reactive.Linq; using Avalonia.Collections; using Avalonia.Controls; using Avalonia.Controls.Templates; using Avalonia.VisualTree; using WDE.Common.Avalonia.Utils; +using WDE.Common.Disposables; using WDE.Common.Managers; using WDE.Common.Windows; +using WDE.MVVM; using WDE.MVVM.Observable; namespace WoWDatabaseEditorCore.Avalonia.Docking @@ -54,7 +57,7 @@ public IControl Build(object data, IControl? existing) children.Remove(view); return view; } - + if (ViewBind.TryResolve(toolDockWrapper.ViewModel, out var documentView) && documentView is IControl control) { tools[toolDockWrapper.ViewModel] = control; @@ -82,6 +85,15 @@ private void Bind() { documents.Remove(item.Item); }); + foreach (var tool in DocumentManager.AllTools) + { + tool.ToObservable(i => i.Visibility) + .SubscribeAction(toolVisibility => + { + if (!toolVisibility) + tools.Remove(tool); + }); + } } } } diff --git a/WoWDatabaseEditorCore.Avalonia/Program.cs b/WoWDatabaseEditorCore.Avalonia/Program.cs index 7381ee4f5..d64fed2f2 100644 --- a/WoWDatabaseEditorCore.Avalonia/Program.cs +++ b/WoWDatabaseEditorCore.Avalonia/Program.cs @@ -1,9 +1,14 @@ using System; +using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using AsyncAwaitBestPractices; using Avalonia; +using Avalonia.Controls; +using Avalonia.OpenGL; +using Avalonia.OpenTK; using Avalonia.ReactiveUI; using WDE.Common.Tasks; using WoWDatabaseEditorCore.Managers; @@ -41,6 +46,25 @@ private static void FixCurrentDirectory() Directory.SetCurrentDirectory(exePath.Directory.FullName); } + private static T SafeUseOpenTK(T builder, IList probeVersions) where T : AppBuilderBase, new() + { + return builder.AfterPlatformServicesSetup(_ => + { + var method = typeof(AvaloniaOpenTKIntegration).GetMethod("Initialize", + BindingFlags.NonPublic | BindingFlags.Static); + + try + { + method!.Invoke(null, new object?[]{probeVersions}); + } + catch (Exception e) + { + GlobalApplication.Supports3D = false; + Console.WriteLine(e); + } + }); + } + // Avalonia configuration, don't remove; also used by visual designer. public static AppBuilder BuildAvaloniaApp() { @@ -51,11 +75,26 @@ public static AppBuilder BuildAvaloniaApp() //.With(new Win32PlatformOptions(){AllowEglInitialization = false}) .UseReactiveUI() .LogToTrace(); +#if USE_OPENTK + Console.WriteLine("Initializing OpenGL"); + configuration = SafeUseOpenTK(configuration, new List { new GlVersion(GlProfileType.OpenGL, 4, 1, true) }); +// configuration = configuration.UseOpenTK(new List { new GlVersion(GlProfileType.OpenGL, 4, 1, true) }); +#endif if (GlobalApplication.Arguments.IsArgumentSet("wgl")) { configuration = configuration. - With(new Win32PlatformOptions() { UseWgl = true }); + With(new Win32PlatformOptions() { UseWgl = true, + AllowEglInitialization = false, + WglProfiles = new List() + { + new GlVersion(GlProfileType.OpenGL, 4, 6), + new GlVersion(GlProfileType.OpenGL, 4, 5), + new GlVersion(GlProfileType.OpenGL, 4, 4), + new GlVersion(GlProfileType.OpenGL, 4, 3), + new GlVersion(GlProfileType.OpenGL, 4, 2), + new GlVersion(GlProfileType.OpenGL, 4, 1), + }}); } return configuration; diff --git a/WoWDatabaseEditorCore.Avalonia/Services/AppearanceService/Views/ThemeConfigView.axaml b/WoWDatabaseEditorCore.Avalonia/Services/AppearanceService/Views/ThemeConfigView.axaml index 64adb0960..56fbabadc 100644 --- a/WoWDatabaseEditorCore.Avalonia/Services/AppearanceService/Views/ThemeConfigView.axaml +++ b/WoWDatabaseEditorCore.Avalonia/Services/AppearanceService/Views/ThemeConfigView.axaml @@ -3,6 +3,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:prism="http://prismlibrary.com/" xmlns:controls="clr-namespace:WDE.Common.Avalonia.Controls;assembly=WDE.Common.Avalonia" + xmlns:converters="clr-namespace:WDE.Common.Avalonia.Converters;assembly=WDE.Common.Avalonia" prism:ViewModelLocator.AutoWireViewModel="False"> @@ -20,6 +21,6 @@ - Info: Custom scaling is available only on Windows + Info: Custom scaling is available only on Windows \ No newline at end of file diff --git a/WoWDatabaseEditorCore.Avalonia/Services/NewItemService/NewItemDialogView.axaml.cs b/WoWDatabaseEditorCore.Avalonia/Services/NewItemService/NewItemDialogView.axaml.cs index 358f5456b..4a7761027 100644 --- a/WoWDatabaseEditorCore.Avalonia/Services/NewItemService/NewItemDialogView.axaml.cs +++ b/WoWDatabaseEditorCore.Avalonia/Services/NewItemService/NewItemDialogView.axaml.cs @@ -27,7 +27,7 @@ private void UIElement_OnKeyDown(object sender, KeyEventArgs e) vm.Accept.Execute(null); } - private void InputElement_OnDoubleTapped(object? sender, RoutedEventArgs e) + private void InputElement_OnDoubleTapped(object? sender, TappedEventArgs e) { if (DataContext is NewItemDialogViewModel vm) vm.Accept.Execute(null); diff --git a/WoWDatabaseEditorCore.Avalonia/Views/AboutView.axaml b/WoWDatabaseEditorCore.Avalonia/Views/AboutView.axaml index b75232abc..b0fd84689 100644 --- a/WoWDatabaseEditorCore.Avalonia/Views/AboutView.axaml +++ b/WoWDatabaseEditorCore.Avalonia/Views/AboutView.axaml @@ -12,7 +12,7 @@ - WoW Database Editor 2021.2 + WoW Database Editor 2021.3 diff --git a/WoWDatabaseEditorCore.Avalonia/Views/QuickStartView.axaml b/WoWDatabaseEditorCore.Avalonia/Views/QuickStartView.axaml index 1a25a10b3..5b15d2bb8 100644 --- a/WoWDatabaseEditorCore.Avalonia/Views/QuickStartView.axaml +++ b/WoWDatabaseEditorCore.Avalonia/Views/QuickStartView.axaml @@ -76,7 +76,7 @@ - WoW Database Editor 2021.2 + WoW Database Editor 2021.3 diff --git a/WoWDatabaseEditorCore.Avalonia/WoWDatabaseEditorCore.Avalonia.csproj b/WoWDatabaseEditorCore.Avalonia/WoWDatabaseEditorCore.Avalonia.csproj index fda9c35e0..af478647e 100644 --- a/WoWDatabaseEditorCore.Avalonia/WoWDatabaseEditorCore.Avalonia.csproj +++ b/WoWDatabaseEditorCore.Avalonia/WoWDatabaseEditorCore.Avalonia.csproj @@ -7,6 +7,8 @@ Icon.ico enable nullable + $(DefineConstants);USE_OPENTK + $(DefineConstants);USE_OPENTK ..\bin\$(Configuration)\ @@ -24,6 +26,7 @@ + diff --git a/WoWPacketParser b/WoWPacketParser index 3c33d8e20..1bd6638a1 160000 --- a/WoWPacketParser +++ b/WoWPacketParser @@ -1 +1 @@ -Subproject commit 3c33d8e20da119fdb82d0348fb11522591fe6fde +Subproject commit 1bd6638a11e76908b7a17c4781fe426fd59d8286