From c081bea43bf03a3ac987a1d9f1c594c8a3899dad Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sat, 14 Mar 2026 13:49:12 +0000 Subject: [PATCH 1/6] Progress report --- DarkUI/DarkUI.WPF/Styles/NumericUpDown.xaml | 1 + TombEditor/Command.cs | 15 + TombEditor/TombEditor.csproj | 76 +- TombEditor/ToolWindows/Lighting.Designer.cs | 534 +----- TombEditor/ToolWindows/Lighting.cs | 251 +-- TombEditor/ToolWindows/Palette.Designer.cs | 114 +- TombEditor/ToolWindows/Palette.cs | 95 +- .../ToolWindows/RoomOptions.Designer.cs | 511 +----- TombEditor/ToolWindows/RoomOptions.cs | 394 +--- .../ToolWindows/SectorOptions.Designer.cs | 437 +---- TombEditor/ToolWindows/SectorOptions.cs | 119 +- TombEditor/WPF/Controls/Panel2DGrid.cs | 555 ++++++ TombEditor/WPF/Controls/PanelPaletteGrid.cs | 375 ++++ .../WPF/Converters/HtmlToUIColorConverter.cs | 23 + .../Converters/VectorToUIColorConverter.cs | 50 + TombEditor/WPF/DynamicKeyBinding.cs | 79 + TombEditor/WPF/KeyBindingsExtension.cs | 44 + TombEditor/WPF/KeyBindingsWrapper.cs | 24 + .../ToolWindows/ImportedGeometryBrowser.xaml | 61 + .../ImportedGeometryBrowser.xaml.cs | 25 + TombEditor/WPF/ToolWindows/ItemBrowser.xaml | 68 + .../WPF/ToolWindows/ItemBrowser.xaml.cs | 25 + TombEditor/WPF/ToolWindows/Lighting.xaml | 285 +++ TombEditor/WPF/ToolWindows/Lighting.xaml.cs | 20 + TombEditor/WPF/ToolWindows/ObjectList.xaml | 34 + TombEditor/WPF/ToolWindows/ObjectList.xaml.cs | 25 + TombEditor/WPF/ToolWindows/Palette.xaml | 54 + TombEditor/WPF/ToolWindows/Palette.xaml.cs | 89 + TombEditor/WPF/ToolWindows/RoomOptions.xaml | 299 +++ .../WPF/ToolWindows/RoomOptions.xaml.cs | 21 + TombEditor/WPF/ToolWindows/SectorOptions.xaml | 341 ++++ .../WPF/ToolWindows/SectorOptions.xaml.cs | 34 + TombEditor/WPF/ToolWindows/TexturePanel.xaml | 96 + .../WPF/ToolWindows/TexturePanel.xaml.cs | 18 + TombEditor/WPF/ToolWindows/TriggerList.xaml | 39 + .../WPF/ToolWindows/TriggerList.xaml.cs | 25 + .../WPF/ViewModels/LightingViewModel.cs | 280 +++ .../WPF/ViewModels/MainViewViewModel.cs | 16 + .../WPF/ViewModels/MainWindowViewModel.cs | 794 ++++++++ TombEditor/WPF/ViewModels/OptionsViewModel.cs | 1627 +++++++++++++++++ TombEditor/WPF/ViewModels/PaletteViewModel.cs | 67 + .../WPF/ViewModels/RoomOptionsViewModel.cs | 519 ++++++ .../WPF/ViewModels/SectorOptionsViewModel.cs | 139 ++ TombEditor/WPF/ViewModels/ViewModelBase.cs | 11 + .../WPF/Views/AnimatedTexturesWindow.xaml | 548 ++++++ .../WPF/Views/AnimatedTexturesWindow.xaml.cs | 27 + TombEditor/WPF/Views/BumpMapsWindow.xaml | 66 + TombEditor/WPF/Views/BumpMapsWindow.xaml.cs | 27 + TombEditor/WPF/Views/CameraWindow.xaml | 62 + TombEditor/WPF/Views/CameraWindow.xaml.cs | 27 + TombEditor/WPF/Views/ChooseRoomWindow.xaml | 43 + TombEditor/WPF/Views/ChooseRoomWindow.xaml.cs | 25 + TombEditor/WPF/Views/FindTexturesWindow.xaml | 66 + .../WPF/Views/FindTexturesWindow.xaml.cs | 27 + TombEditor/WPF/Views/FlybyCameraWindow.xaml | 193 ++ .../WPF/Views/FlybyCameraWindow.xaml.cs | 27 + .../WPF/Views/FootStepSoundsWindow.xaml | 73 + .../WPF/Views/FootStepSoundsWindow.xaml.cs | 27 + TombEditor/WPF/Views/ImportPrjWindow.xaml | 89 + TombEditor/WPF/Views/ImportPrjWindow.xaml.cs | 27 + .../WPF/Views/ImportedGeometryWindow.xaml | 98 + .../WPF/Views/ImportedGeometryWindow.xaml.cs | 27 + .../WPF/Views/KeyboardLayoutWindow.xaml | 94 + .../WPF/Views/KeyboardLayoutWindow.xaml.cs | 27 + TombEditor/WPF/Views/MainWindow.xaml | 1537 ++++++++++++++++ TombEditor/WPF/Views/MainWindow.xaml.cs | 15 + TombEditor/WPF/Views/OptionsWindow.xaml | 1375 ++++++++++++++ TombEditor/WPF/Views/OptionsWindow.xaml.cs | 44 + TombEditor/WPF/Views/TriggerWindow.xaml | 216 +++ TombEditor/WPF/Views/TriggerWindow.xaml.cs | 27 + TombEditor/WPF/Views/ViewUserControl.cs | 13 + TombEditor/WPF/Views/ViewWindow.cs | 23 + TombEditor/WPF/WPFUtils.cs | 70 + .../Resources/Localization/EN/TombEditor.json | 488 +++++ 74 files changed, 11688 insertions(+), 2429 deletions(-) create mode 100644 TombEditor/WPF/Controls/Panel2DGrid.cs create mode 100644 TombEditor/WPF/Controls/PanelPaletteGrid.cs create mode 100644 TombEditor/WPF/Converters/HtmlToUIColorConverter.cs create mode 100644 TombEditor/WPF/Converters/VectorToUIColorConverter.cs create mode 100644 TombEditor/WPF/DynamicKeyBinding.cs create mode 100644 TombEditor/WPF/KeyBindingsExtension.cs create mode 100644 TombEditor/WPF/KeyBindingsWrapper.cs create mode 100644 TombEditor/WPF/ToolWindows/ImportedGeometryBrowser.xaml create mode 100644 TombEditor/WPF/ToolWindows/ImportedGeometryBrowser.xaml.cs create mode 100644 TombEditor/WPF/ToolWindows/ItemBrowser.xaml create mode 100644 TombEditor/WPF/ToolWindows/ItemBrowser.xaml.cs create mode 100644 TombEditor/WPF/ToolWindows/Lighting.xaml create mode 100644 TombEditor/WPF/ToolWindows/Lighting.xaml.cs create mode 100644 TombEditor/WPF/ToolWindows/ObjectList.xaml create mode 100644 TombEditor/WPF/ToolWindows/ObjectList.xaml.cs create mode 100644 TombEditor/WPF/ToolWindows/Palette.xaml create mode 100644 TombEditor/WPF/ToolWindows/Palette.xaml.cs create mode 100644 TombEditor/WPF/ToolWindows/RoomOptions.xaml create mode 100644 TombEditor/WPF/ToolWindows/RoomOptions.xaml.cs create mode 100644 TombEditor/WPF/ToolWindows/SectorOptions.xaml create mode 100644 TombEditor/WPF/ToolWindows/SectorOptions.xaml.cs create mode 100644 TombEditor/WPF/ToolWindows/TexturePanel.xaml create mode 100644 TombEditor/WPF/ToolWindows/TexturePanel.xaml.cs create mode 100644 TombEditor/WPF/ToolWindows/TriggerList.xaml create mode 100644 TombEditor/WPF/ToolWindows/TriggerList.xaml.cs create mode 100644 TombEditor/WPF/ViewModels/LightingViewModel.cs create mode 100644 TombEditor/WPF/ViewModels/MainViewViewModel.cs create mode 100644 TombEditor/WPF/ViewModels/MainWindowViewModel.cs create mode 100644 TombEditor/WPF/ViewModels/OptionsViewModel.cs create mode 100644 TombEditor/WPF/ViewModels/PaletteViewModel.cs create mode 100644 TombEditor/WPF/ViewModels/RoomOptionsViewModel.cs create mode 100644 TombEditor/WPF/ViewModels/SectorOptionsViewModel.cs create mode 100644 TombEditor/WPF/ViewModels/ViewModelBase.cs create mode 100644 TombEditor/WPF/Views/AnimatedTexturesWindow.xaml create mode 100644 TombEditor/WPF/Views/AnimatedTexturesWindow.xaml.cs create mode 100644 TombEditor/WPF/Views/BumpMapsWindow.xaml create mode 100644 TombEditor/WPF/Views/BumpMapsWindow.xaml.cs create mode 100644 TombEditor/WPF/Views/CameraWindow.xaml create mode 100644 TombEditor/WPF/Views/CameraWindow.xaml.cs create mode 100644 TombEditor/WPF/Views/ChooseRoomWindow.xaml create mode 100644 TombEditor/WPF/Views/ChooseRoomWindow.xaml.cs create mode 100644 TombEditor/WPF/Views/FindTexturesWindow.xaml create mode 100644 TombEditor/WPF/Views/FindTexturesWindow.xaml.cs create mode 100644 TombEditor/WPF/Views/FlybyCameraWindow.xaml create mode 100644 TombEditor/WPF/Views/FlybyCameraWindow.xaml.cs create mode 100644 TombEditor/WPF/Views/FootStepSoundsWindow.xaml create mode 100644 TombEditor/WPF/Views/FootStepSoundsWindow.xaml.cs create mode 100644 TombEditor/WPF/Views/ImportPrjWindow.xaml create mode 100644 TombEditor/WPF/Views/ImportPrjWindow.xaml.cs create mode 100644 TombEditor/WPF/Views/ImportedGeometryWindow.xaml create mode 100644 TombEditor/WPF/Views/ImportedGeometryWindow.xaml.cs create mode 100644 TombEditor/WPF/Views/KeyboardLayoutWindow.xaml create mode 100644 TombEditor/WPF/Views/KeyboardLayoutWindow.xaml.cs create mode 100644 TombEditor/WPF/Views/MainWindow.xaml create mode 100644 TombEditor/WPF/Views/MainWindow.xaml.cs create mode 100644 TombEditor/WPF/Views/OptionsWindow.xaml create mode 100644 TombEditor/WPF/Views/OptionsWindow.xaml.cs create mode 100644 TombEditor/WPF/Views/TriggerWindow.xaml create mode 100644 TombEditor/WPF/Views/TriggerWindow.xaml.cs create mode 100644 TombEditor/WPF/Views/ViewUserControl.cs create mode 100644 TombEditor/WPF/Views/ViewWindow.cs create mode 100644 TombEditor/WPF/WPFUtils.cs diff --git a/DarkUI/DarkUI.WPF/Styles/NumericUpDown.xaml b/DarkUI/DarkUI.WPF/Styles/NumericUpDown.xaml index be3000ccd3..9c33e70d1a 100644 --- a/DarkUI/DarkUI.WPF/Styles/NumericUpDown.xaml +++ b/DarkUI/DarkUI.WPF/Styles/NumericUpDown.xaml @@ -16,6 +16,7 @@ + diff --git a/TombEditor/Command.cs b/TombEditor/Command.cs index 06ca63f345..33499a0699 100644 --- a/TombEditor/Command.cs +++ b/TombEditor/Command.cs @@ -53,6 +53,14 @@ public class CommandArgs public Editor Editor; public IWin32Window Window; public Keys KeyData = Keys.None; + + public CommandArgs() { } + + public CommandArgs(IWin32Window window, Editor editor) + { + Window = window; + Editor = editor; + } } public static class CommandHandler @@ -69,6 +77,13 @@ public static CommandObj GetCommand(string name) return command; } + public static System.Windows.Input.ICommand GetCommand(string name, CommandArgs args) + { + var command = GetCommand(name); + return new CommunityToolkit.Mvvm.Input.RelayCommand( + () => command.Execute?.Invoke(args)); + } + public static void ExecuteHotkey(CommandArgs args) { var hotkeyForCommands = args.Editor.Configuration.UI_Hotkeys.Where(set => set.Value.Contains(args.KeyData)); diff --git a/TombEditor/TombEditor.csproj b/TombEditor/TombEditor.csproj index d78607f265..3bfeb72e3c 100644 --- a/TombEditor/TombEditor.csproj +++ b/TombEditor/TombEditor.csproj @@ -8,6 +8,8 @@ true Debug;Release x64;x86 + TE.ico + TombEditor.Program ..\Build ($(Platform))\ @@ -23,12 +25,6 @@ x86 - - TE.ico - - - TombEditor.Program - MSBuild:Compile @@ -77,21 +73,17 @@ GlobalPaths.cs - - - - + + + + + Component UserControl - - - - - UserControl @@ -101,7 +93,12 @@ Component - + + Component + + + Component + Form @@ -115,27 +112,6 @@ True Settings.settings - - - - - - - - - - - - - - - Component - - - Component - - - @@ -147,22 +123,28 @@ - - + + + + + + + + + + + + + + + - - - - - + - - - ResXFileCodeGenerator diff --git a/TombEditor/ToolWindows/Lighting.Designer.cs b/TombEditor/ToolWindows/Lighting.Designer.cs index a77c7aaad2..f6f2b247f0 100644 --- a/TombEditor/ToolWindows/Lighting.Designer.cs +++ b/TombEditor/ToolWindows/Lighting.Designer.cs @@ -2,533 +2,39 @@ { partial class Lighting { - /// - /// Required designer variable. - /// private System.ComponentModel.IContainer components = null; #region Component Designer generated code - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// private void InitializeComponent() { - this.components = new System.ComponentModel.Container(); - this.cbLightIsDynamicallyUsed = new DarkUI.Controls.DarkCheckBox(); - this.cbLightIsStaticallyUsed = new DarkUI.Controls.DarkCheckBox(); - this.cbLightIsObstructedByRoomGeometry = new DarkUI.Controls.DarkCheckBox(); - this.cbLightEnabled = new DarkUI.Controls.DarkCheckBox(); - this.panelLightColor = new DarkUI.Controls.DarkPanel(); - this.darkLabel12 = new DarkUI.Controls.DarkLabel(); - this.darkLabel13 = new DarkUI.Controls.DarkLabel(); - this.darkLabel11 = new DarkUI.Controls.DarkLabel(); - this.darkLabel9 = new DarkUI.Controls.DarkLabel(); - this.darkLabel10 = new DarkUI.Controls.DarkLabel(); - this.darkLabel8 = new DarkUI.Controls.DarkLabel(); - this.darkLabel7 = new DarkUI.Controls.DarkLabel(); - this.butAddLight = new DarkUI.Controls.DarkButton(); - this.numIntensity = new DarkUI.Controls.DarkNumericUpDown(); - this.numInnerRange = new DarkUI.Controls.DarkNumericUpDown(); - this.numOuterRange = new DarkUI.Controls.DarkNumericUpDown(); - this.numInnerAngle = new DarkUI.Controls.DarkNumericUpDown(); - this.numOuterAngle = new DarkUI.Controls.DarkNumericUpDown(); - this.numDirectionX = new DarkUI.Controls.DarkNumericUpDown(); - this.numDirectionY = new DarkUI.Controls.DarkNumericUpDown(); - this.toolTip = new System.Windows.Forms.ToolTip(this.components); - this.cbLightIsUsedForImportedGeometry = new DarkUI.Controls.DarkCheckBox(); - this.cmbLightQuality = new DarkUI.Controls.DarkComboBox(); - this.cmbLightTypes = new DarkUI.Controls.DarkComboBox(); - this.cbLightCastsShadow = new DarkUI.Controls.DarkCheckBox(); - this.darkLabel6 = new DarkUI.Controls.DarkLabel(); - ((System.ComponentModel.ISupportInitialize)(this.numIntensity)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.numInnerRange)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.numOuterRange)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.numInnerAngle)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.numOuterAngle)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.numDirectionX)).BeginInit(); - ((System.ComponentModel.ISupportInitialize)(this.numDirectionY)).BeginInit(); - this.SuspendLayout(); + _elementHost = new System.Windows.Forms.Integration.ElementHost(); + _lightingView = new WPF.ToolWindows.Lighting(); + SuspendLayout(); // - // cbLightIsDynamicallyUsed + // _elementHost // - this.cbLightIsDynamicallyUsed.Enabled = false; - this.cbLightIsDynamicallyUsed.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.cbLightIsDynamicallyUsed.Location = new System.Drawing.Point(79, 100); - this.cbLightIsDynamicallyUsed.Name = "cbLightIsDynamicallyUsed"; - this.cbLightIsDynamicallyUsed.Size = new System.Drawing.Size(70, 22); - this.cbLightIsDynamicallyUsed.TabIndex = 18; - this.cbLightIsDynamicallyUsed.Text = "Dynamic"; - this.toolTip.SetToolTip(this.cbLightIsDynamicallyUsed, "Use light for moveables ingame"); - this.cbLightIsDynamicallyUsed.CheckedChanged += new System.EventHandler(this.cbLightIsDynamicallyUsed_CheckedChanged); - // - // cbLightIsStaticallyUsed - // - this.cbLightIsStaticallyUsed.Enabled = false; - this.cbLightIsStaticallyUsed.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.cbLightIsStaticallyUsed.Location = new System.Drawing.Point(79, 81); - this.cbLightIsStaticallyUsed.Name = "cbLightIsStaticallyUsed"; - this.cbLightIsStaticallyUsed.Size = new System.Drawing.Size(70, 22); - this.cbLightIsStaticallyUsed.TabIndex = 17; - this.cbLightIsStaticallyUsed.Text = "Static"; - this.toolTip.SetToolTip(this.cbLightIsStaticallyUsed, "Use light for room geometry lighting"); - this.cbLightIsStaticallyUsed.CheckedChanged += new System.EventHandler(this.cbLightIsStaticallyUsed_CheckedChanged); - // - // cbLightIsObstructedByRoomGeometry - // - this.cbLightIsObstructedByRoomGeometry.Enabled = false; - this.cbLightIsObstructedByRoomGeometry.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.cbLightIsObstructedByRoomGeometry.Location = new System.Drawing.Point(3, 100); - this.cbLightIsObstructedByRoomGeometry.Name = "cbLightIsObstructedByRoomGeometry"; - this.cbLightIsObstructedByRoomGeometry.Size = new System.Drawing.Size(70, 22); - this.cbLightIsObstructedByRoomGeometry.TabIndex = 16; - this.cbLightIsObstructedByRoomGeometry.Text = "Obstruct"; - this.toolTip.SetToolTip(this.cbLightIsObstructedByRoomGeometry, "Determines whether the effect of this light is obstructed by room geometry"); - this.cbLightIsObstructedByRoomGeometry.CheckedChanged += new System.EventHandler(this.cbLightIsObstructedByRoomGeometry_CheckedChanged); - // - // cbLightEnabled - // - this.cbLightEnabled.Enabled = false; - this.cbLightEnabled.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.cbLightEnabled.Location = new System.Drawing.Point(3, 81); - this.cbLightEnabled.Name = "cbLightEnabled"; - this.cbLightEnabled.Size = new System.Drawing.Size(65, 22); - this.cbLightEnabled.TabIndex = 15; - this.cbLightEnabled.Text = "Enabled"; - this.toolTip.SetToolTip(this.cbLightEnabled, "Light is enabled"); - this.cbLightEnabled.CheckedChanged += new System.EventHandler(this.cbLightEnabled_CheckedChanged); - // - // panelLightColor - // - this.panelLightColor.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.panelLightColor.Enabled = false; - this.panelLightColor.Location = new System.Drawing.Point(206, 28); - this.panelLightColor.Name = "panelLightColor"; - this.panelLightColor.Size = new System.Drawing.Size(60, 22); - this.panelLightColor.TabIndex = 7; - this.toolTip.SetToolTip(this.panelLightColor, "Light color"); - this.panelLightColor.Click += new System.EventHandler(this.panelLightColor_Click); - // - // darkLabel12 - // - this.darkLabel12.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.darkLabel12.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); - this.darkLabel12.Location = new System.Drawing.Point(268, 84); - this.darkLabel12.Name = "darkLabel12"; - this.darkLabel12.Size = new System.Drawing.Size(38, 22); - this.darkLabel12.TabIndex = 80; - this.darkLabel12.Text = "Dir Y"; - this.darkLabel12.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - // - // darkLabel13 - // - this.darkLabel13.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.darkLabel13.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); - this.darkLabel13.Location = new System.Drawing.Point(268, 113); - this.darkLabel13.Name = "darkLabel13"; - this.darkLabel13.Size = new System.Drawing.Size(38, 22); - this.darkLabel13.TabIndex = 79; - this.darkLabel13.Text = "Dir X"; - this.darkLabel13.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - // - // darkLabel11 - // - this.darkLabel11.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.darkLabel11.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); - this.darkLabel11.Location = new System.Drawing.Point(155, 55); - this.darkLabel11.Name = "darkLabel11"; - this.darkLabel11.Size = new System.Drawing.Size(51, 22); - this.darkLabel11.TabIndex = 78; - this.darkLabel11.Text = "Intensity"; - this.darkLabel11.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - // - // darkLabel9 - // - this.darkLabel9.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.darkLabel9.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); - this.darkLabel9.Location = new System.Drawing.Point(268, 55); - this.darkLabel9.Name = "darkLabel9"; - this.darkLabel9.Size = new System.Drawing.Size(38, 22); - this.darkLabel9.TabIndex = 77; - this.darkLabel9.Text = "Out α"; - this.darkLabel9.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - // - // darkLabel10 - // - this.darkLabel10.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.darkLabel10.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); - this.darkLabel10.Location = new System.Drawing.Point(268, 26); - this.darkLabel10.Name = "darkLabel10"; - this.darkLabel10.Size = new System.Drawing.Size(38, 22); - this.darkLabel10.TabIndex = 73; - this.darkLabel10.Text = "In α"; - this.darkLabel10.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - // - // darkLabel8 - // - this.darkLabel8.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.darkLabel8.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); - this.darkLabel8.Location = new System.Drawing.Point(155, 113); - this.darkLabel8.Name = "darkLabel8"; - this.darkLabel8.Size = new System.Drawing.Size(51, 22); - this.darkLabel8.TabIndex = 71; - this.darkLabel8.Text = "Out d"; - this.darkLabel8.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - // - // darkLabel7 - // - this.darkLabel7.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.darkLabel7.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); - this.darkLabel7.Location = new System.Drawing.Point(155, 84); - this.darkLabel7.Name = "darkLabel7"; - this.darkLabel7.Size = new System.Drawing.Size(51, 22); - this.darkLabel7.TabIndex = 70; - this.darkLabel7.Text = "In d"; - this.darkLabel7.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - // - // butAddLight - // - this.butAddLight.Checked = false; - this.butAddLight.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.butAddLight.Image = global::TombEditor.Properties.Resources.general_plus_math_16; - this.butAddLight.Location = new System.Drawing.Point(123, 28); - this.butAddLight.Name = "butAddLight"; - this.butAddLight.Size = new System.Drawing.Size(23, 23); - this.butAddLight.TabIndex = 0; - this.butAddLight.Tag = ""; - this.toolTip.SetToolTip(this.butAddLight, "Place light"); - this.butAddLight.Click += new System.EventHandler(this.butAddLight_Click); - // - // numIntensity - // - this.numIntensity.DecimalPlaces = 2; - this.numIntensity.Enabled = false; - this.numIntensity.Increment = new decimal(new int[] { - 3, - 0, - 0, - 131072}); - this.numIntensity.IncrementAlternate = new decimal(new int[] { - 12, - 0, - 0, - 131072}); - this.numIntensity.Location = new System.Drawing.Point(206, 57); - this.numIntensity.LoopValues = false; - this.numIntensity.Maximum = new decimal(new int[] { - 128, - 0, - 0, - 0}); - this.numIntensity.Minimum = new decimal(new int[] { - 128, - 0, - 0, - -2147483648}); - this.numIntensity.Name = "numIntensity"; - this.numIntensity.Size = new System.Drawing.Size(60, 22); - this.numIntensity.TabIndex = 8; - this.numIntensity.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; - this.toolTip.SetToolTip(this.numIntensity, "Light intensity"); - this.numIntensity.ValueChanged += new System.EventHandler(this.numIntensity_ValueChanged); - // - // numInnerRange - // - this.numInnerRange.DecimalPlaces = 2; - this.numInnerRange.Enabled = false; - this.numInnerRange.Increment = new decimal(new int[] { - 3, - 0, - 0, - 131072}); - this.numInnerRange.IncrementAlternate = new decimal(new int[] { - 1, - 0, - 0, - 0}); - this.numInnerRange.Location = new System.Drawing.Point(206, 86); - this.numInnerRange.LoopValues = false; - this.numInnerRange.Maximum = new decimal(new int[] { - 256, - 0, - 0, - 0}); - this.numInnerRange.Name = "numInnerRange"; - this.numInnerRange.Size = new System.Drawing.Size(60, 22); - this.numInnerRange.TabIndex = 9; - this.numInnerRange.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; - this.toolTip.SetToolTip(this.numInnerRange, "Inner radius or distance"); - this.numInnerRange.ValueChanged += new System.EventHandler(this.numInnerRange_ValueChanged); - // - // numOuterRange - // - this.numOuterRange.DecimalPlaces = 2; - this.numOuterRange.Enabled = false; - this.numOuterRange.Increment = new decimal(new int[] { - 3, - 0, - 0, - 131072}); - this.numOuterRange.IncrementAlternate = new decimal(new int[] { - 1, - 0, - 0, - 0}); - this.numOuterRange.Location = new System.Drawing.Point(206, 115); - this.numOuterRange.LoopValues = false; - this.numOuterRange.Maximum = new decimal(new int[] { - 256, - 0, - 0, - 0}); - this.numOuterRange.Name = "numOuterRange"; - this.numOuterRange.Size = new System.Drawing.Size(60, 22); - this.numOuterRange.TabIndex = 10; - this.numOuterRange.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; - this.toolTip.SetToolTip(this.numOuterRange, "Outer radius or distance"); - this.numOuterRange.ValueChanged += new System.EventHandler(this.numOuterRange_ValueChanged); - // - // numInnerAngle - // - this.numInnerAngle.DecimalPlaces = 2; - this.numInnerAngle.Enabled = false; - this.numInnerAngle.IncrementAlternate = new decimal(new int[] { - 10, - 0, - 0, - 0}); - this.numInnerAngle.Location = new System.Drawing.Point(306, 28); - this.numInnerAngle.LoopValues = false; - this.numInnerAngle.Maximum = new decimal(new int[] { - 180, - 0, - 0, - 0}); - this.numInnerAngle.Name = "numInnerAngle"; - this.numInnerAngle.Size = new System.Drawing.Size(60, 22); - this.numInnerAngle.TabIndex = 11; - this.numInnerAngle.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; - this.toolTip.SetToolTip(this.numInnerAngle, "Inner cone angle"); - this.numInnerAngle.ValueChanged += new System.EventHandler(this.numInnerAngle_ValueChanged); - // - // numOuterAngle - // - this.numOuterAngle.DecimalPlaces = 2; - this.numOuterAngle.Enabled = false; - this.numOuterAngle.IncrementAlternate = new decimal(new int[] { - 10, - 0, - 0, - 0}); - this.numOuterAngle.Location = new System.Drawing.Point(306, 57); - this.numOuterAngle.LoopValues = false; - this.numOuterAngle.Maximum = new decimal(new int[] { - 180, - 0, - 0, - 0}); - this.numOuterAngle.Name = "numOuterAngle"; - this.numOuterAngle.Size = new System.Drawing.Size(60, 22); - this.numOuterAngle.TabIndex = 12; - this.numOuterAngle.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; - this.toolTip.SetToolTip(this.numOuterAngle, "Outer cone angle"); - this.numOuterAngle.ValueChanged += new System.EventHandler(this.numOuterAngle_ValueChanged); - // - // numDirectionX - // - this.numDirectionX.DecimalPlaces = 2; - this.numDirectionX.Enabled = false; - this.numDirectionX.IncrementAlternate = new decimal(new int[] { - 10, - 0, - 0, - 0}); - this.numDirectionX.Location = new System.Drawing.Point(306, 115); - this.numDirectionX.LoopValues = false; - this.numDirectionX.Maximum = new decimal(new int[] { - 90, - 0, - 0, - 0}); - this.numDirectionX.Minimum = new decimal(new int[] { - 90, - 0, - 0, - -2147483648}); - this.numDirectionX.Name = "numDirectionX"; - this.numDirectionX.Size = new System.Drawing.Size(60, 22); - this.numDirectionX.TabIndex = 14; - this.numDirectionX.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; - this.toolTip.SetToolTip(this.numDirectionX, "Angle around the X axis (vertical rotation)"); - this.numDirectionX.ValueChanged += new System.EventHandler(this.numDirectionX_ValueChanged); - // - // numDirectionY - // - this.numDirectionY.DecimalPlaces = 2; - this.numDirectionY.Enabled = false; - this.numDirectionY.IncrementAlternate = new decimal(new int[] { - 10, - 0, - 0, - 0}); - this.numDirectionY.Location = new System.Drawing.Point(306, 86); - this.numDirectionY.LoopValues = false; - this.numDirectionY.Maximum = new decimal(new int[] { - 720, - 0, - 0, - 0}); - this.numDirectionY.Minimum = new decimal(new int[] { - 360, - 0, - 0, - -2147483648}); - this.numDirectionY.Name = "numDirectionY"; - this.numDirectionY.Size = new System.Drawing.Size(60, 22); - this.numDirectionY.TabIndex = 13; - this.numDirectionY.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; - this.toolTip.SetToolTip(this.numDirectionY, "Angle around the Y axis (horizontal rotation)"); - this.numDirectionY.ValueChanged += new System.EventHandler(this.numDirectionY_ValueChanged); - // - // toolTip - // - this.toolTip.AutoPopDelay = 5000; - this.toolTip.InitialDelay = 500; - this.toolTip.ReshowDelay = 100; - // - // cbLightIsUsedForImportedGeometry - // - this.cbLightIsUsedForImportedGeometry.Enabled = false; - this.cbLightIsUsedForImportedGeometry.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.cbLightIsUsedForImportedGeometry.Location = new System.Drawing.Point(79, 119); - this.cbLightIsUsedForImportedGeometry.Name = "cbLightIsUsedForImportedGeometry"; - this.cbLightIsUsedForImportedGeometry.Size = new System.Drawing.Size(70, 22); - this.cbLightIsUsedForImportedGeometry.TabIndex = 19; - this.cbLightIsUsedForImportedGeometry.Text = "Imported"; - this.toolTip.SetToolTip(this.cbLightIsUsedForImportedGeometry, "Use light for imported geometry"); - this.cbLightIsUsedForImportedGeometry.CheckedChanged += new System.EventHandler(this.cbLightIsUsedForImportedGeometry_CheckedChanged); - // - // cmbLightQuality - // - this.cmbLightQuality.Enabled = false; - this.cmbLightQuality.Items.AddRange(new object[] { - "Default quality", - "Low quality", - "Medium quality", - "High quality"}); - this.cmbLightQuality.Location = new System.Drawing.Point(3, 57); - this.cmbLightQuality.Name = "cmbLightQuality"; - this.cmbLightQuality.Size = new System.Drawing.Size(143, 23); - this.cmbLightQuality.TabIndex = 6; - this.toolTip.SetToolTip(this.cmbLightQuality, "Raytracing sample count.\r\nHigher value gives more smooth shadows on obstructed ar" + - "eas."); - this.cmbLightQuality.SelectionChangeCommitted += new System.EventHandler(this.cmbLightQualityChanged); - // - // cmbLightTypes - // - this.cmbLightTypes.Location = new System.Drawing.Point(3, 28); - this.cmbLightTypes.Name = "cmbLightTypes"; - this.cmbLightTypes.Size = new System.Drawing.Size(114, 23); - this.cmbLightTypes.TabIndex = 81; - this.toolTip.SetToolTip(this.cmbLightTypes, "Light type to place"); - this.cmbLightTypes.SelectedIndexChanged += new System.EventHandler(this.cmbLightTypes_SelectedIndexChanged); - // - // cbLightCastsShadow - // - this.cbLightCastsShadow.Enabled = false; - this.cbLightCastsShadow.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.cbLightCastsShadow.Location = new System.Drawing.Point(3, 119); - this.cbLightCastsShadow.Name = "cbLightCastsShadow"; - this.cbLightCastsShadow.Size = new System.Drawing.Size(70, 22); - this.cbLightCastsShadow.TabIndex = 87; - this.cbLightCastsShadow.Text = "Shadow"; - this.toolTip.SetToolTip(this.cbLightCastsShadow, "Determines whether this light can cast shadows"); - this.cbLightCastsShadow.CheckedChanged += new System.EventHandler(this.cbLightCastsShadow_CheckedChanged); - // - // darkLabel6 - // - this.darkLabel6.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.darkLabel6.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(220)))), ((int)(((byte)(220)))), ((int)(((byte)(220))))); - this.darkLabel6.Location = new System.Drawing.Point(155, 26); - this.darkLabel6.Name = "darkLabel6"; - this.darkLabel6.Size = new System.Drawing.Size(51, 22); - this.darkLabel6.TabIndex = 68; - this.darkLabel6.Text = "Color"; - this.darkLabel6.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + _elementHost.Dock = System.Windows.Forms.DockStyle.Fill; + _elementHost.Name = "_elementHost"; + _elementHost.Child = _lightingView; // // Lighting // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.Controls.Add(this.cbLightCastsShadow); - this.Controls.Add(this.cmbLightTypes); - this.Controls.Add(this.cmbLightQuality); - this.Controls.Add(this.cbLightIsUsedForImportedGeometry); - this.Controls.Add(this.numDirectionY); - this.Controls.Add(this.numDirectionX); - this.Controls.Add(this.numOuterAngle); - this.Controls.Add(this.numInnerAngle); - this.Controls.Add(this.numOuterRange); - this.Controls.Add(this.numInnerRange); - this.Controls.Add(this.numIntensity); - this.Controls.Add(this.cbLightIsDynamicallyUsed); - this.Controls.Add(this.cbLightIsStaticallyUsed); - this.Controls.Add(this.cbLightIsObstructedByRoomGeometry); - this.Controls.Add(this.cbLightEnabled); - this.Controls.Add(this.panelLightColor); - this.Controls.Add(this.darkLabel12); - this.Controls.Add(this.darkLabel13); - this.Controls.Add(this.darkLabel11); - this.Controls.Add(this.darkLabel9); - this.Controls.Add(this.darkLabel10); - this.Controls.Add(this.darkLabel8); - this.Controls.Add(this.darkLabel7); - this.Controls.Add(this.darkLabel6); - this.Controls.Add(this.butAddLight); - this.DefaultDockArea = DarkUI.Docking.DarkDockArea.Bottom; - this.DockText = "Lighting"; - this.MinimumSize = new System.Drawing.Size(371, 141); - this.Name = "Lighting"; - this.SerializationKey = "Lighting"; - this.Size = new System.Drawing.Size(371, 141); - ((System.ComponentModel.ISupportInitialize)(this.numIntensity)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.numInnerRange)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.numOuterRange)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.numInnerAngle)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.numOuterAngle)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.numDirectionX)).EndInit(); - ((System.ComponentModel.ISupportInitialize)(this.numDirectionY)).EndInit(); - this.ResumeLayout(false); - + AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + Controls.Add(_elementHost); + DefaultDockArea = DarkUI.Docking.DarkDockArea.Bottom; + DockText = "Lighting"; + MinimumSize = new System.Drawing.Size(371, 141); + Name = "Lighting"; + SerializationKey = "Lighting"; + Size = new System.Drawing.Size(371, 141); + ResumeLayout(false); } #endregion - private DarkUI.Controls.DarkCheckBox cbLightIsDynamicallyUsed; - private DarkUI.Controls.DarkCheckBox cbLightIsStaticallyUsed; - private DarkUI.Controls.DarkCheckBox cbLightIsObstructedByRoomGeometry; - private DarkUI.Controls.DarkCheckBox cbLightEnabled; - private DarkUI.Controls.DarkPanel panelLightColor; - private DarkUI.Controls.DarkLabel darkLabel12; - private DarkUI.Controls.DarkLabel darkLabel13; - private DarkUI.Controls.DarkLabel darkLabel11; - private DarkUI.Controls.DarkLabel darkLabel9; - private DarkUI.Controls.DarkLabel darkLabel10; - private DarkUI.Controls.DarkLabel darkLabel8; - private DarkUI.Controls.DarkLabel darkLabel7; - private DarkUI.Controls.DarkButton butAddLight; - private DarkUI.Controls.DarkNumericUpDown numIntensity; - private DarkUI.Controls.DarkNumericUpDown numInnerRange; - private DarkUI.Controls.DarkNumericUpDown numOuterRange; - private DarkUI.Controls.DarkNumericUpDown numInnerAngle; - private DarkUI.Controls.DarkNumericUpDown numOuterAngle; - private DarkUI.Controls.DarkNumericUpDown numDirectionX; - private DarkUI.Controls.DarkNumericUpDown numDirectionY; - private System.Windows.Forms.ToolTip toolTip; - private DarkUI.Controls.DarkCheckBox cbLightIsUsedForImportedGeometry; - private DarkUI.Controls.DarkComboBox cmbLightQuality; - private DarkUI.Controls.DarkComboBox cmbLightTypes; - private DarkUI.Controls.DarkCheckBox cbLightCastsShadow; - private DarkUI.Controls.DarkLabel darkLabel6; + + private System.Windows.Forms.Integration.ElementHost _elementHost; + private WPF.ToolWindows.Lighting _lightingView; } } diff --git a/TombEditor/ToolWindows/Lighting.cs b/TombEditor/ToolWindows/Lighting.cs index e0157da546..937f7ab3ac 100644 --- a/TombEditor/ToolWindows/Lighting.cs +++ b/TombEditor/ToolWindows/Lighting.cs @@ -1,270 +1,21 @@ using DarkUI.Docking; -using System; -using System.Numerics; -using System.Windows.Forms; -using TombLib.LevelData; -using TombLib.Utils; namespace TombEditor.ToolWindows { public partial class Lighting : DarkToolWindow { - private readonly Editor _editor; - public Lighting() { InitializeComponent(); - CommandHandler.AssignCommandsToControls(Editor.Instance, this, toolTip); - - foreach (LightType l in Enum.GetValues(typeof(LightType))) - cmbLightTypes.Items.Add(l.ToString().SplitCamelcase()); - - cmbLightQuality.SelectedIndex = cmbLightTypes.SelectedIndex = 0; // Reset index to default - - _editor = Editor.Instance; - _editor.EditorEventRaised += EditorEventRaised; } protected override void Dispose(bool disposing) { if (disposing) - _editor.EditorEventRaised -= EditorEventRaised; + _lightingView?.Cleanup(); if (disposing && components != null) components.Dispose(); base.Dispose(disposing); } - - private void EditorEventRaised(IEditorEvent obj) - { - - // Update light UI - if (obj is Editor.InitEvent || - obj is Editor.GameVersionChangedEvent || - obj is Editor.LevelChangedEvent || - obj is Editor.ObjectChangedEvent || - obj is Editor.SelectedObjectChangedEvent) - { - var isTEN = _editor.Level.Settings.GameVersion == TRVersion.Game.TombEngine; - var light = _editor.SelectedObject as LightInstance; - - // Get light type - bool HasInRange = false; - bool HasOutRange = false; - bool HasInOutAngle = false; - bool HasDirection = false; - bool CanCastShadows = false; - bool CanCastDynamicShadows = false; - bool CanIlluminateGeometry = false; - - cmbLightQuality.Enabled = false; - - if (light != null) - switch (light.Type) - { - case LightType.Point: - HasInRange = true; - HasOutRange = true; - CanIlluminateGeometry = true; - CanCastShadows = true; - CanCastDynamicShadows = isTEN; - break; - - case LightType.Shadow: - HasInRange = true; - HasOutRange = true; - CanCastShadows = true; - CanIlluminateGeometry = true; - break; - - case LightType.Effect: - HasInRange = true; - HasOutRange = true; - break; - - case LightType.FogBulb: - HasOutRange = true; - break; - - case LightType.Spot: - HasInRange = true; - HasOutRange = true; - HasInOutAngle = true; - HasDirection = true; - CanIlluminateGeometry = true; - CanCastShadows = true; - CanCastDynamicShadows = isTEN; - break; - - case LightType.Sun: - HasDirection = true; - CanCastShadows = true; - CanIlluminateGeometry = true; - break; - } - - // Update enable state - // We set it before the values to make sure that irrelevant values are - // not recognized as being changed to 0 in the "ValueChanged" functions. - panelLightColor.Enabled = light != null; - cbLightEnabled.Enabled = light != null; - cbLightIsObstructedByRoomGeometry.Enabled = CanCastShadows; - cbLightCastsShadow.Enabled = CanCastDynamicShadows; - cbLightIsDynamicallyUsed.Enabled = CanIlluminateGeometry; - cbLightIsStaticallyUsed.Enabled = CanIlluminateGeometry; - cbLightIsUsedForImportedGeometry.Enabled = CanIlluminateGeometry; - numIntensity.Enabled = light != null; - numInnerRange.Enabled = HasInRange; - numOuterRange.Enabled = HasOutRange; - numInnerAngle.Enabled = HasInOutAngle; - numOuterAngle.Enabled = HasInOutAngle; - numDirectionY.Enabled = HasDirection; - numDirectionX.Enabled = HasDirection; - - // Update value state - panelLightColor.BackColor = light != null ? new Vector4(light.Color * 0.5f, 1.0f).ToWinFormsColor() : BackColor; - numIntensity.Value = (decimal)(light?.Intensity ?? 0); - numInnerRange.Value = HasInRange ? (decimal)light.InnerRange : 0; - numOuterRange.Value = HasOutRange ? (decimal)light.OuterRange : 0; - numInnerAngle.Value = HasInOutAngle ? (decimal)light.InnerAngle : 0; - numOuterAngle.Value = HasInOutAngle ? (decimal)light.OuterAngle : 0; - numDirectionY.Value = HasDirection ? (decimal)light.RotationY : 0; - numDirectionX.Value = HasDirection ? (decimal)light.RotationX : 0; - - cbLightEnabled.Checked = light?.Enabled ?? false; - cbLightIsObstructedByRoomGeometry.Checked = light?.IsObstructedByRoomGeometry ?? false; - cbLightIsDynamicallyUsed.Checked = light?.IsDynamicallyUsed ?? false; - cbLightIsStaticallyUsed.Checked = light?.IsStaticallyUsed ?? false; - cbLightIsUsedForImportedGeometry.Checked = light?.IsUsedForImportedGeometry ?? false; - cbLightCastsShadow.Checked = light?.CastDynamicShadows ?? false; - cmbLightQuality.Enabled = light != null; - cmbLightQuality.SelectedIndex = (int)(light?.Quality ?? 0); - cmbLightTypes.SelectedIndex = (int)(light?.Type ?? (LightType)cmbLightTypes.SelectedIndex); - } - - // Update tooltip texts - if (obj is Editor.ConfigurationChangedEvent) - { - if (((Editor.ConfigurationChangedEvent)obj).UpdateKeyboardShortcuts) - CommandHandler.AssignCommandsToControls(_editor, this, toolTip, true); - } - } - - private void cbLightEnabled_CheckedChanged(object sender, EventArgs e) - { - EditorActions.UpdateLight((light, value) => light.Enabled == value, (light, value) => light.Enabled = value, - light => cbLightEnabled.Checked); - } - - private void cbLightIsObstructedByRoomGeometry_CheckedChanged(object sender, EventArgs e) - { - EditorActions.UpdateLight((light, value) => light.IsObstructedByRoomGeometry == value, (light, value) => light.IsObstructedByRoomGeometry = value, - light => cbLightIsObstructedByRoomGeometry.Checked); - } - - private void cbLightIsStaticallyUsed_CheckedChanged(object sender, EventArgs e) - { - EditorActions.UpdateLight((light, value) => light.IsStaticallyUsed == value, (light, value) => light.IsStaticallyUsed = value, - light => cbLightIsStaticallyUsed.Checked); - } - - private void cbLightIsDynamicallyUsed_CheckedChanged(object sender, EventArgs e) - { - EditorActions.UpdateLight((light, value) => light.IsDynamicallyUsed == value, (light, value) => light.IsDynamicallyUsed = value, - light => cbLightIsDynamicallyUsed.Checked); - } - - private void cbLightIsUsedForImportedGeometry_CheckedChanged(object sender, EventArgs e) - { - EditorActions.UpdateLight((light, value) => light.IsUsedForImportedGeometry == value, (light, value) => light.IsUsedForImportedGeometry = value, - light => cbLightIsUsedForImportedGeometry.Checked); - } - - private void cbLightCastsShadow_CheckedChanged(object sender, EventArgs e) - { - EditorActions.UpdateLight((light, value) => light.CastDynamicShadows == value, (light, value) => light.CastDynamicShadows = value, - light => cbLightCastsShadow.Checked); - } - - private static bool Compare(float firstValue, float secondValue, NumericUpDown control) - { - // Check that this setting even matters for the light... - if (!control.Enabled) - return true; - - // Check if the value differs enough to warrant changing it - // We don't want to polute the editor with useless event's because NumericUpDown - // decided to round. - for (int i = 0; i < control.DecimalPlaces; ++i) - { - firstValue *= 10.0f; - secondValue *= 10.0f; - } - - double firstValueDbl = Math.Round(firstValue); - double secondValueDbl = Math.Round(secondValue); - return firstValueDbl == secondValueDbl; - } - - private void numIntensity_ValueChanged(object sender, EventArgs e) - { - EditorActions.UpdateLight((light, value) => Compare(light.Intensity, value, numIntensity), - (light, value) => light.Intensity = value, light => (float)numIntensity.Value); - } - - private void numInnerRange_ValueChanged(object sender, EventArgs e) - { - EditorActions.UpdateLight((light, value) => Compare(light.InnerRange, value, numInnerRange), - (light, value) => light.InnerRange = value, light => (float)numInnerRange.Value); - } - - private void numOuterRange_ValueChanged(object sender, EventArgs e) - { - EditorActions.UpdateLight((light, value) => Compare(light.OuterRange, value, numOuterRange), - (light, value) => light.OuterRange = value, light => (float)numOuterRange.Value); - } - - private void numInnerAngle_ValueChanged(object sender, EventArgs e) - { - EditorActions.UpdateLight((light, value) => Compare(light.InnerAngle, value, numInnerAngle), - (light, value) => light.InnerAngle = value, light => (float)numInnerAngle.Value); - } - - private void numOuterAngle_ValueChanged(object sender, EventArgs e) - { - EditorActions.UpdateLight((light, value) => Compare(light.OuterAngle, value, numOuterAngle), - (light, value) => light.OuterAngle = value, light => (float)numOuterAngle.Value); - } - - private void numDirectionY_ValueChanged(object sender, EventArgs e) - { - EditorActions.UpdateLight((light, value) => Compare(light.RotationY, value, numDirectionY), - (light, value) => light.RotationY = value, light => (float)numDirectionY.Value); - } - - private void numDirectionX_ValueChanged(object sender, EventArgs e) - { - EditorActions.UpdateLight((light, value) => Compare(light.RotationX, value, numDirectionX), - (light, value) => light.RotationX = value, light => (float)numDirectionX.Value); - } - - private void panelLightColor_Click(object sender, EventArgs e) - { - EditorActions.EditLightColor(this); - } - - private void cmbLightQualityChanged(object sender, EventArgs e) - { - EditorActions.UpdateLightQuality((LightQuality)cmbLightQuality.SelectedIndex); - } - - private void butAddLight_Click(object sender, EventArgs e) - { - EditorActions.PlaceLight((LightType)cmbLightTypes.SelectedIndex); - } - - private void cmbLightTypes_SelectedIndexChanged(object sender, EventArgs e) - { - EditorActions.UpdateLightType((LightType)cmbLightTypes.SelectedIndex); - } } } diff --git a/TombEditor/ToolWindows/Palette.Designer.cs b/TombEditor/ToolWindows/Palette.Designer.cs index d4c9975bd7..8c79570cf2 100644 --- a/TombEditor/ToolWindows/Palette.Designer.cs +++ b/TombEditor/ToolWindows/Palette.Designer.cs @@ -2,115 +2,39 @@ { partial class Palette { - /// - /// Required designer variable. - /// private System.ComponentModel.IContainer components = null; #region Component Designer generated code - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// private void InitializeComponent() { - this.components = new System.ComponentModel.Container(); - this.paletteToolBar = new System.Windows.Forms.FlowLayoutPanel(); - this.butResetToDefaults = new DarkUI.Controls.DarkButton(); - this.butSampleFromTextures = new DarkUI.Controls.DarkButton(); - this.butEditColor = new DarkUI.Controls.DarkButton(); - this.toolTip = new System.Windows.Forms.ToolTip(this.components); - this.lightPalette = new TombEditor.Controls.PanelPalette(); - this.paletteToolBar.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.lightPalette)).BeginInit(); - this.SuspendLayout(); + _elementHost = new System.Windows.Forms.Integration.ElementHost(); + _paletteView = new WPF.ToolWindows.Palette(); + SuspendLayout(); // - // paletteToolBar + // _elementHost // - this.paletteToolBar.AutoSize = true; - this.paletteToolBar.Controls.Add(this.butResetToDefaults); - this.paletteToolBar.Controls.Add(this.butSampleFromTextures); - this.paletteToolBar.Controls.Add(this.butEditColor); - this.paletteToolBar.Dock = System.Windows.Forms.DockStyle.Left; - this.paletteToolBar.Location = new System.Drawing.Point(0, 25); - this.paletteToolBar.Name = "paletteToolBar"; - this.paletteToolBar.Size = new System.Drawing.Size(29, 116); - this.paletteToolBar.TabIndex = 84; - // - // butResetToDefaults - // - this.butResetToDefaults.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.butResetToDefaults.Checked = false; - this.butResetToDefaults.Image = global::TombEditor.Properties.Resources.actions_refresh_16; - this.butResetToDefaults.Location = new System.Drawing.Point(3, 3); - this.butResetToDefaults.Name = "butResetToDefaults"; - this.butResetToDefaults.Size = new System.Drawing.Size(23, 23); - this.butResetToDefaults.TabIndex = 5; - this.butResetToDefaults.Tag = "ResetPalette"; - // - // butSampleFromTextures - // - this.butSampleFromTextures.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.butSampleFromTextures.Checked = false; - this.butSampleFromTextures.Image = global::TombEditor.Properties.Resources.actions_TextureMode_16; - this.butSampleFromTextures.Location = new System.Drawing.Point(3, 32); - this.butSampleFromTextures.Name = "butSampleFromTextures"; - this.butSampleFromTextures.Size = new System.Drawing.Size(23, 23); - this.butSampleFromTextures.TabIndex = 6; - this.butSampleFromTextures.Tag = "SamplePaletteFromTextures"; - // - // butEditColor - // - this.butEditColor.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.butEditColor.Checked = false; - this.butEditColor.Enabled = false; - this.butEditColor.Image = global::TombEditor.Properties.Resources.general_edit_16; - this.butEditColor.Location = new System.Drawing.Point(3, 61); - this.butEditColor.Name = "butEditColor"; - this.butEditColor.Size = new System.Drawing.Size(23, 23); - this.butEditColor.TabIndex = 7; - this.butEditColor.Tag = "EditObjectColor"; - this.toolTip.SetToolTip(this.butEditColor, "Edit color for selected object"); - // - // lightPalette - // - this.lightPalette.Dock = System.Windows.Forms.DockStyle.Fill; - this.lightPalette.Editable = true; - this.lightPalette.Location = new System.Drawing.Point(29, 25); - this.lightPalette.Margin = new System.Windows.Forms.Padding(2); - this.lightPalette.Name = "lightPalette"; - this.lightPalette.Padding = new System.Windows.Forms.Padding(3); - this.lightPalette.Size = new System.Drawing.Size(616, 116); - this.lightPalette.TabIndex = 82; - this.lightPalette.TabStop = false; + _elementHost.Dock = System.Windows.Forms.DockStyle.Fill; + _elementHost.Name = "_elementHost"; + _elementHost.Child = _paletteView; // // Palette // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.Controls.Add(this.lightPalette); - this.Controls.Add(this.paletteToolBar); - this.DefaultDockArea = DarkUI.Docking.DarkDockArea.Bottom; - this.DockText = "Palette"; - this.MinimumSize = new System.Drawing.Size(100, 100); - this.Name = "Palette"; - this.SerializationKey = "Palette"; - this.Size = new System.Drawing.Size(645, 141); - this.paletteToolBar.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)(this.lightPalette)).EndInit(); - this.ResumeLayout(false); - this.PerformLayout(); - + AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + Controls.Add(_elementHost); + DefaultDockArea = DarkUI.Docking.DarkDockArea.Bottom; + DockText = "Palette"; + MinimumSize = new System.Drawing.Size(100, 100); + Name = "Palette"; + SerializationKey = "Palette"; + Size = new System.Drawing.Size(645, 141); + ResumeLayout(false); } #endregion - private Controls.PanelPalette lightPalette; - private DarkUI.Controls.DarkButton butSampleFromTextures; - private DarkUI.Controls.DarkButton butResetToDefaults; - private System.Windows.Forms.FlowLayoutPanel paletteToolBar; - private System.Windows.Forms.ToolTip toolTip; - private DarkUI.Controls.DarkButton butEditColor; + private System.Windows.Forms.Integration.ElementHost _elementHost; + private WPF.ToolWindows.Palette _paletteView; } } diff --git a/TombEditor/ToolWindows/Palette.cs b/TombEditor/ToolWindows/Palette.cs index 358e337130..237ad45f38 100644 --- a/TombEditor/ToolWindows/Palette.cs +++ b/TombEditor/ToolWindows/Palette.cs @@ -1,112 +1,21 @@ -using System; -using System.Collections.Generic; -using DarkUI.Docking; -using TombLib.LevelData; -using TombLib.Utils; +using DarkUI.Docking; namespace TombEditor.ToolWindows { public partial class Palette : DarkToolWindow { - private readonly Editor _editor; - private List _lastTexturePalette; - public Palette() { InitializeComponent(); - - CommandHandler.AssignCommandsToControls(Editor.Instance, this, toolTip); - _editor = Editor.Instance; - _editor.EditorEventRaised += EditorEventRaised; - - // Reset palette to default and prepare controls - lightPalette.LoadPalette(LevelSettings.LoadPalette()); - UpdateControls(false); } protected override void Dispose(bool disposing) { if (disposing) - _editor.EditorEventRaised -= EditorEventRaised; + _paletteView?.Cleanup(); if (disposing && components != null) components.Dispose(); base.Dispose(disposing); } - - private void EditorEventRaised(IEditorEvent obj) - { - if (obj is Editor.LevelChangedEvent) - { - _lastTexturePalette = null; - lightPalette.LoadPalette(((Editor.LevelChangedEvent)obj).Current.Settings.Palette); - } - - if (obj is Editor.SelectedObjectChangedEvent) - { - butEditColor.Enabled = ((Editor.SelectedObjectChangedEvent)obj).Current.CanBeColored(); - lightPalette.PickColor(); - } - - if (obj is Editor.ObjectChangedEvent) - { - var o = obj as Editor.ObjectChangedEvent; - if (o.ChangeType == ObjectChangeType.Change && o.Object == _editor.SelectedObject && o.Object is IColorable) - lightPalette.PickColor(); - } - - if (obj is Editor.ResetPaletteEvent) - { - if (!butSampleFromTextures.Checked) - { - lightPalette.LoadPalette(LevelSettings.LoadPalette()); - _editor.Level.Settings.Palette = lightPalette.Palette; - } - } - - if (obj is Editor.SelectedLevelTextureChangedSetEvent) - { - var o = (Editor.SelectedLevelTextureChangedSetEvent)obj; - _lastTexturePalette = new List(o.Texture.Image.Palette); - UpdateControls(); - } - - if (obj is Editor.ConfigurationChangedEvent) - { - var o = (Editor.ConfigurationChangedEvent)obj; - if (((Editor.ConfigurationChangedEvent)obj).UpdateKeyboardShortcuts) - CommandHandler.AssignCommandsToControls(_editor, this, toolTip, true); - UpdateControls(); - } - } - - private void UpdateControls(bool reloadPalette = true) - { - bool useTexture = _editor.Configuration.Palette_TextureSamplingMode; - - butSampleFromTextures.Checked = useTexture; - butResetToDefaults.Enabled = !useTexture; - lightPalette.Editable = !useTexture; - - if (reloadPalette) - { - if (useTexture && _lastTexturePalette != null && _lastTexturePalette.Count > 0) - lightPalette.LoadPalette(_lastTexturePalette); - else - lightPalette.LoadPalette(_editor.Level.Settings.Palette); - - // Also update last colour on editor so next created light will receive updated colour. - _editor.LastUsedPaletteColourChange(lightPalette.SelectedColor); - } - } - - protected override void OnSizeChanged(EventArgs e) - { - base.OnSizeChanged(e); - - if (ClientSize.Width >= ClientSize.Height * 2) - paletteToolBar.Dock = System.Windows.Forms.DockStyle.Left; - else - paletteToolBar.Dock = System.Windows.Forms.DockStyle.Top; - } } } diff --git a/TombEditor/ToolWindows/RoomOptions.Designer.cs b/TombEditor/ToolWindows/RoomOptions.Designer.cs index 56603217de..1cd6197c85 100644 --- a/TombEditor/ToolWindows/RoomOptions.Designer.cs +++ b/TombEditor/ToolWindows/RoomOptions.Designer.cs @@ -2,531 +2,38 @@ { partial class RoomOptions { - /// - /// Required designer variable. - /// private System.ComponentModel.IContainer components = null; #region Component Designer generated code - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// private void InitializeComponent() { - components = new System.ComponentModel.Container(); - cbNoPathfinding = new DarkUI.Controls.DarkCheckBox(); - cbHorizon = new DarkUI.Controls.DarkCheckBox(); - darkLabel19 = new DarkUI.Controls.DarkLabel(); - darkLabel18 = new DarkUI.Controls.DarkLabel(); - darkLabel16 = new DarkUI.Controls.DarkLabel(); - cbFlagOutside = new DarkUI.Controls.DarkCheckBox(); - cbFlagCold = new DarkUI.Controls.DarkCheckBox(); - cbFlagDamage = new DarkUI.Controls.DarkCheckBox(); - darkLabel15 = new DarkUI.Controls.DarkLabel(); - panelRoomAmbientLight = new DarkUI.Controls.DarkPanel(); - darkLabel3 = new DarkUI.Controls.DarkLabel(); - cbNoLensflare = new DarkUI.Controls.DarkCheckBox(); - toolTip = new System.Windows.Forms.ToolTip(components); - numLightEffectStrength = new DarkUI.Controls.DarkNumericUpDown(); - comboPortalShade = new DarkUI.Controls.DarkComboBox(); - comboLightEffect = new DarkUI.Controls.DarkComboBox(); - tbRoomTags = new TombLib.Controls.DarkAutocompleteTextBox(); - darkLabel2 = new DarkUI.Controls.DarkLabel(); - darkLabel1 = new DarkUI.Controls.DarkLabel(); - butSelectPreviousRoom = new DarkUI.Controls.DarkButton(); - butNewRoom = new DarkUI.Controls.DarkButton(); - butDeleteRoom = new DarkUI.Controls.DarkButton(); - butDublicateRoom = new DarkUI.Controls.DarkButton(); - butLocked = new DarkUI.Controls.DarkButton(); - comboFlipMap = new DarkUI.Controls.DarkComboBox(); - butRoomUp = new DarkUI.Controls.DarkButton(); - comboReverberation = new DarkUI.Controls.DarkComboBox(); - comboRoomType = new DarkUI.Controls.DarkComboBox(); - comboRoom = new TombLib.Controls.DarkSearchableComboBox(); - butRoomDown = new DarkUI.Controls.DarkButton(); - butEditRoomName = new DarkUI.Controls.DarkButton(); - butCropRoom = new DarkUI.Controls.DarkButton(); - butSplitRoom = new DarkUI.Controls.DarkButton(); - butHidden = new DarkUI.Controls.DarkButton(); - cbFlagNoCaustics = new DarkUI.Controls.DarkCheckBox(); - ((System.ComponentModel.ISupportInitialize)numLightEffectStrength).BeginInit(); + _elementHost = new System.Windows.Forms.Integration.ElementHost(); + _roomOptionsView = new WPF.ToolWindows.RoomOptions(); SuspendLayout(); // - // cbNoPathfinding + // _elementHost // - cbNoPathfinding.AutoCheck = false; - cbNoPathfinding.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - cbNoPathfinding.Location = new System.Drawing.Point(129, 130); - cbNoPathfinding.Name = "cbNoPathfinding"; - cbNoPathfinding.Size = new System.Drawing.Size(96, 17); - cbNoPathfinding.TabIndex = 8; - cbNoPathfinding.Tag = "SetRoomNoPathfinding"; - cbNoPathfinding.Text = "No pathfinding"; - // - // cbHorizon - // - cbHorizon.AutoCheck = false; - cbHorizon.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - cbHorizon.Location = new System.Drawing.Point(3, 130); - cbHorizon.Name = "cbHorizon"; - cbHorizon.Size = new System.Drawing.Size(58, 17); - cbHorizon.TabIndex = 6; - cbHorizon.Tag = "SetRoomSkybox"; - cbHorizon.Text = "Skybox"; - // - // darkLabel19 - // - darkLabel19.AutoSize = true; - darkLabel19.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - darkLabel19.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - darkLabel19.Location = new System.Drawing.Point(87, 84); - darkLabel19.Name = "darkLabel19"; - darkLabel19.Size = new System.Drawing.Size(48, 13); - darkLabel19.TabIndex = 103; - darkLabel19.Text = "Flipmap"; - // - // darkLabel18 - // - darkLabel18.AutoSize = true; - darkLabel18.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - darkLabel18.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - darkLabel18.Location = new System.Drawing.Point(148, 84); - darkLabel18.Name = "darkLabel18"; - darkLabel18.Size = new System.Drawing.Size(42, 13); - darkLabel18.TabIndex = 100; - darkLabel18.Text = "Reverb"; - // - // darkLabel16 - // - darkLabel16.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left; - darkLabel16.AutoSize = true; - darkLabel16.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - darkLabel16.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - darkLabel16.Location = new System.Drawing.Point(140, 194); - darkLabel16.Name = "darkLabel16"; - darkLabel16.Size = new System.Drawing.Size(36, 13); - darkLabel16.TabIndex = 96; - darkLabel16.Text = "Effect"; - // - // cbFlagOutside - // - cbFlagOutside.AutoCheck = false; - cbFlagOutside.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - cbFlagOutside.Location = new System.Drawing.Point(3, 150); - cbFlagOutside.Name = "cbFlagOutside"; - cbFlagOutside.Size = new System.Drawing.Size(50, 17); - cbFlagOutside.TabIndex = 9; - cbFlagOutside.Tag = "SetRoomOutside"; - cbFlagOutside.Text = "Wind"; - // - // cbFlagCold - // - cbFlagCold.AutoCheck = false; - cbFlagCold.AutoSize = true; - cbFlagCold.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - cbFlagCold.Location = new System.Drawing.Point(64, 150); - cbFlagCold.Name = "cbFlagCold"; - cbFlagCold.Size = new System.Drawing.Size(50, 17); - cbFlagCold.TabIndex = 10; - cbFlagCold.Tag = "SetRoomCold"; - cbFlagCold.Text = "Cold"; - // - // cbFlagDamage - // - cbFlagDamage.AutoCheck = false; - cbFlagDamage.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - cbFlagDamage.Location = new System.Drawing.Point(64, 130); - cbFlagDamage.Name = "cbFlagDamage"; - cbFlagDamage.Size = new System.Drawing.Size(64, 17); - cbFlagDamage.TabIndex = 7; - cbFlagDamage.Tag = "SetRoomDamage"; - cbFlagDamage.Text = "Damage"; - // - // darkLabel15 - // - darkLabel15.AutoSize = true; - darkLabel15.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - darkLabel15.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - darkLabel15.Location = new System.Drawing.Point(0, 84); - darkLabel15.Name = "darkLabel15"; - darkLabel15.Size = new System.Drawing.Size(62, 13); - darkLabel15.TabIndex = 91; - darkLabel15.Text = "Room type"; - // - // panelRoomAmbientLight - // - panelRoomAmbientLight.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left; - panelRoomAmbientLight.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - panelRoomAmbientLight.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - panelRoomAmbientLight.Location = new System.Drawing.Point(3, 210); - panelRoomAmbientLight.Name = "panelRoomAmbientLight"; - panelRoomAmbientLight.Size = new System.Drawing.Size(59, 23); - panelRoomAmbientLight.TabIndex = 12; - panelRoomAmbientLight.Tag = "EditAmbientLight"; - // - // darkLabel3 - // - darkLabel3.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left; - darkLabel3.AutoSize = true; - darkLabel3.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - darkLabel3.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - darkLabel3.Location = new System.Drawing.Point(0, 194); - darkLabel3.Name = "darkLabel3"; - darkLabel3.Size = new System.Drawing.Size(50, 13); - darkLabel3.TabIndex = 88; - darkLabel3.Text = "Ambient"; - // - // cbNoLensflare - // - cbNoLensflare.AutoCheck = false; - cbNoLensflare.AutoSize = true; - cbNoLensflare.Location = new System.Drawing.Point(129, 150); - cbNoLensflare.Name = "cbNoLensflare"; - cbNoLensflare.Size = new System.Drawing.Size(88, 17); - cbNoLensflare.TabIndex = 11; - cbNoLensflare.Tag = "SetRoomNoLensflare"; - cbNoLensflare.Text = "No lensflare"; - // - // toolTip - // - toolTip.AutoPopDelay = 5000; - toolTip.InitialDelay = 500; - toolTip.ReshowDelay = 100; - // - // numLightEffectStrength - // - numLightEffectStrength.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right; - numLightEffectStrength.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - numLightEffectStrength.IncrementAlternate = new decimal(new int[] { 10, 0, 0, 65536 }); - numLightEffectStrength.Location = new System.Drawing.Point(246, 210); - numLightEffectStrength.LoopValues = false; - numLightEffectStrength.Maximum = new decimal(new int[] { 4, 0, 0, 0 }); - numLightEffectStrength.Name = "numLightEffectStrength"; - numLightEffectStrength.Size = new System.Drawing.Size(36, 23); - numLightEffectStrength.TabIndex = 15; - numLightEffectStrength.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; - toolTip.SetToolTip(numLightEffectStrength, "Light / transform effect strength"); - numLightEffectStrength.Value = new decimal(new int[] { 1, 0, 0, 0 }); - numLightEffectStrength.ValueChanged += numLightEffectStrength_ValueChanged; - // - // comboPortalShade - // - comboPortalShade.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left; - comboPortalShade.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - comboPortalShade.Items.AddRange(new object[] { "Default", "Smooth", "Sharp" }); - comboPortalShade.Location = new System.Drawing.Point(68, 210); - comboPortalShade.Name = "comboPortalShade"; - comboPortalShade.Size = new System.Drawing.Size(69, 23); - comboPortalShade.TabIndex = 13; - toolTip.SetToolTip(comboPortalShade, "Smoothing on room edges"); - comboPortalShade.SelectedIndexChanged += comboPortalShade_SelectedIndexChanged; - // - // comboLightEffect - // - comboLightEffect.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right; - comboLightEffect.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - comboLightEffect.Items.AddRange(new object[] { "None", "Default", "Reflection", "Glow", "Move", "Glow & Move", "Mist" }); - comboLightEffect.Location = new System.Drawing.Point(143, 210); - comboLightEffect.Name = "comboLightEffect"; - comboLightEffect.Size = new System.Drawing.Size(97, 23); - comboLightEffect.TabIndex = 14; - toolTip.SetToolTip(comboLightEffect, "Light / transform effect on room vertices"); - comboLightEffect.SelectedIndexChanged += comboLightEffect_SelectedIndexChanged; - // - // tbRoomTags - // - tbRoomTags.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right; - tbRoomTags.CharacterCasing = System.Windows.Forms.CharacterCasing.Lower; - tbRoomTags.Location = new System.Drawing.Point(39, 57); - tbRoomTags.Name = "tbRoomTags"; - tbRoomTags.Size = new System.Drawing.Size(183, 22); - tbRoomTags.TabIndex = 2; - tbRoomTags.Tag = "SetRoomTags"; - toolTip.SetToolTip(tbRoomTags, "Set room tags, separated by spaces"); - tbRoomTags.TextChanged += TbTags_TextChanged; - // - // darkLabel2 - // - darkLabel2.AutoSize = true; - darkLabel2.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - darkLabel2.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - darkLabel2.Location = new System.Drawing.Point(1, 59); - darkLabel2.Name = "darkLabel2"; - darkLabel2.Size = new System.Drawing.Size(33, 13); - darkLabel2.TabIndex = 110; - darkLabel2.Text = "Tags:"; - // - // darkLabel1 - // - darkLabel1.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left; - darkLabel1.AutoSize = true; - darkLabel1.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - darkLabel1.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - darkLabel1.Location = new System.Drawing.Point(65, 194); - darkLabel1.Name = "darkLabel1"; - darkLabel1.Size = new System.Drawing.Size(71, 13); - darkLabel1.TabIndex = 112; - darkLabel1.Text = "Portal shade"; - // - // butSelectPreviousRoom - // - butSelectPreviousRoom.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right; - butSelectPreviousRoom.BackColor = System.Drawing.Color.FromArgb(128, 64, 64); - butSelectPreviousRoom.Checked = false; - butSelectPreviousRoom.Image = Properties.Resources.actions_back_16; - butSelectPreviousRoom.Location = new System.Drawing.Point(228, 144); - butSelectPreviousRoom.Name = "butSelectPreviousRoom"; - butSelectPreviousRoom.Size = new System.Drawing.Size(24, 22); - butSelectPreviousRoom.TabIndex = 24; - butSelectPreviousRoom.Tag = "SelectPreviousRoom"; - // - // butNewRoom - // - butNewRoom.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right; - butNewRoom.Checked = false; - butNewRoom.Image = Properties.Resources.general_plus_math_16; - butNewRoom.Location = new System.Drawing.Point(258, 28); - butNewRoom.Name = "butNewRoom"; - butNewRoom.Size = new System.Drawing.Size(24, 23); - butNewRoom.TabIndex = 17; - butNewRoom.Tag = "AddNewRoom"; - // - // butDeleteRoom - // - butDeleteRoom.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right; - butDeleteRoom.Checked = false; - butDeleteRoom.Image = Properties.Resources.general_trash_16; - butDeleteRoom.Location = new System.Drawing.Point(258, 57); - butDeleteRoom.Name = "butDeleteRoom"; - butDeleteRoom.Size = new System.Drawing.Size(24, 23); - butDeleteRoom.TabIndex = 19; - butDeleteRoom.Tag = "DeleteRooms"; - // - // butDublicateRoom - // - butDublicateRoom.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right; - butDublicateRoom.Checked = false; - butDublicateRoom.Image = Properties.Resources.general_copy_16; - butDublicateRoom.Location = new System.Drawing.Point(228, 57); - butDublicateRoom.Name = "butDublicateRoom"; - butDublicateRoom.Size = new System.Drawing.Size(24, 23); - butDublicateRoom.TabIndex = 18; - butDublicateRoom.Tag = "DuplicateRoom"; - // - // butLocked - // - butLocked.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right; - butLocked.Checked = false; - butLocked.Image = Properties.Resources.general_Lock_16; - butLocked.Location = new System.Drawing.Point(258, 144); - butLocked.Name = "butLocked"; - butLocked.Size = new System.Drawing.Size(24, 22); - butLocked.TabIndex = 25; - butLocked.Tag = "LockRoom"; - // - // comboFlipMap - // - comboFlipMap.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - comboFlipMap.Items.AddRange(new object[] { "None", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15" }); - comboFlipMap.Location = new System.Drawing.Point(90, 100); - comboFlipMap.Name = "comboFlipMap"; - comboFlipMap.Size = new System.Drawing.Size(55, 23); - comboFlipMap.TabIndex = 4; - comboFlipMap.SelectedIndexChanged += comboFlipMap_SelectedIndexChanged; - // - // butRoomUp - // - butRoomUp.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right; - butRoomUp.Checked = false; - butRoomUp.Image = Properties.Resources.general_ArrowUp_16; - butRoomUp.Location = new System.Drawing.Point(258, 86); - butRoomUp.Name = "butRoomUp"; - butRoomUp.Size = new System.Drawing.Size(24, 23); - butRoomUp.TabIndex = 21; - butRoomUp.Tag = "MoveRoomUp"; - // - // comboReverberation - // - comboReverberation.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right; - comboReverberation.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - comboReverberation.Items.AddRange(new object[] { "None", "Small", "Medium", "Large", "Pipe" }); - comboReverberation.Location = new System.Drawing.Point(151, 100); - comboReverberation.Name = "comboReverberation"; - comboReverberation.Size = new System.Drawing.Size(71, 23); - comboReverberation.TabIndex = 5; - comboReverberation.SelectedIndexChanged += comboReverberation_SelectedIndexChanged; - // - // comboRoomType - // - comboRoomType.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - comboRoomType.Location = new System.Drawing.Point(3, 100); - comboRoomType.Name = "comboRoomType"; - comboRoomType.Size = new System.Drawing.Size(81, 23); - comboRoomType.TabIndex = 3; - comboRoomType.SelectedIndexChanged += comboRoomType_SelectedIndexChanged; - // - // comboRoom - // - comboRoom.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right; - comboRoom.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - comboRoom.Location = new System.Drawing.Point(3, 28); - comboRoom.Name = "comboRoom"; - comboRoom.Size = new System.Drawing.Size(219, 23); - comboRoom.TabIndex = 0; - comboRoom.SelectedIndexChanged += comboRoom_SelectedIndexChanged; - // - // butRoomDown - // - butRoomDown.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right; - butRoomDown.Checked = false; - butRoomDown.Image = Properties.Resources.general_ArrowDown_16; - butRoomDown.Location = new System.Drawing.Point(258, 115); - butRoomDown.Name = "butRoomDown"; - butRoomDown.Size = new System.Drawing.Size(24, 23); - butRoomDown.TabIndex = 23; - butRoomDown.Tag = "MoveRoomDown"; - // - // butEditRoomName - // - butEditRoomName.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right; - butEditRoomName.Checked = false; - butEditRoomName.Image = Properties.Resources.general_edit_16; - butEditRoomName.Location = new System.Drawing.Point(228, 28); - butEditRoomName.Name = "butEditRoomName"; - butEditRoomName.Size = new System.Drawing.Size(24, 23); - butEditRoomName.TabIndex = 16; - butEditRoomName.Tag = "EditRoomName"; - // - // butCropRoom - // - butCropRoom.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right; - butCropRoom.Checked = false; - butCropRoom.Image = Properties.Resources.general_crop_16; - butCropRoom.Location = new System.Drawing.Point(228, 86); - butCropRoom.Name = "butCropRoom"; - butCropRoom.Size = new System.Drawing.Size(24, 23); - butCropRoom.TabIndex = 20; - butCropRoom.Tag = "CropRoom"; - // - // butSplitRoom - // - butSplitRoom.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right; - butSplitRoom.Checked = false; - butSplitRoom.Image = Properties.Resources.actions_Split_16; - butSplitRoom.Location = new System.Drawing.Point(228, 115); - butSplitRoom.Name = "butSplitRoom"; - butSplitRoom.Size = new System.Drawing.Size(24, 23); - butSplitRoom.TabIndex = 22; - butSplitRoom.Tag = "SplitRoom"; - // - // butHidden - // - butHidden.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right; - butHidden.Checked = false; - butHidden.Image = Properties.Resources.toolbox_Invisible_16; - butHidden.Location = new System.Drawing.Point(228, 172); - butHidden.Name = "butHidden"; - butHidden.Size = new System.Drawing.Size(54, 22); - butHidden.TabIndex = 26; - butHidden.Tag = "HideRoom"; - // - // cbFlagNoCaustics - // - cbFlagNoCaustics.AutoCheck = false; - cbFlagNoCaustics.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - cbFlagNoCaustics.Location = new System.Drawing.Point(129, 165); - cbFlagNoCaustics.Name = "cbFlagNoCaustics"; - cbFlagNoCaustics.Size = new System.Drawing.Size(81, 26); - cbFlagNoCaustics.TabIndex = 113; - cbFlagNoCaustics.Tag = "SetRoomNoCaustics"; - cbFlagNoCaustics.Text = "No caustics"; + _elementHost.Dock = System.Windows.Forms.DockStyle.Fill; + _elementHost.Name = "_elementHost"; + _elementHost.Child = _roomOptionsView; // // RoomOptions // AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - Controls.Add(cbFlagCold); - Controls.Add(cbFlagNoCaustics); - Controls.Add(butHidden); - Controls.Add(butSelectPreviousRoom); - Controls.Add(comboPortalShade); - Controls.Add(darkLabel1); - Controls.Add(butNewRoom); - Controls.Add(darkLabel2); - Controls.Add(tbRoomTags); - Controls.Add(numLightEffectStrength); - Controls.Add(butDeleteRoom); - Controls.Add(butDublicateRoom); - Controls.Add(butLocked); - Controls.Add(cbNoLensflare); - Controls.Add(cbNoPathfinding); - Controls.Add(cbHorizon); - Controls.Add(comboFlipMap); - Controls.Add(darkLabel19); - Controls.Add(butRoomUp); - Controls.Add(comboReverberation); - Controls.Add(darkLabel18); - Controls.Add(comboLightEffect); - Controls.Add(darkLabel16); - Controls.Add(cbFlagOutside); - Controls.Add(cbFlagDamage); - Controls.Add(comboRoomType); - Controls.Add(darkLabel15); - Controls.Add(comboRoom); - Controls.Add(panelRoomAmbientLight); - Controls.Add(darkLabel3); - Controls.Add(butRoomDown); - Controls.Add(butEditRoomName); - Controls.Add(butCropRoom); - Controls.Add(butSplitRoom); + Controls.Add(_elementHost); DockText = "Room Options"; MinimumSize = new System.Drawing.Size(284, 236); Name = "RoomOptions"; SerializationKey = "RoomOptions"; Size = new System.Drawing.Size(284, 236); - ((System.ComponentModel.ISupportInitialize)numLightEffectStrength).EndInit(); ResumeLayout(false); - PerformLayout(); } #endregion - private DarkUI.Controls.DarkCheckBox cbNoPathfinding; - private DarkUI.Controls.DarkCheckBox cbHorizon; - private DarkUI.Controls.DarkComboBox comboFlipMap; - private DarkUI.Controls.DarkLabel darkLabel19; - private DarkUI.Controls.DarkButton butRoomUp; - private DarkUI.Controls.DarkComboBox comboReverberation; - private DarkUI.Controls.DarkLabel darkLabel18; - private DarkUI.Controls.DarkComboBox comboLightEffect; - private DarkUI.Controls.DarkLabel darkLabel16; - private DarkUI.Controls.DarkCheckBox cbFlagOutside; - private DarkUI.Controls.DarkCheckBox cbFlagCold; - private DarkUI.Controls.DarkCheckBox cbFlagDamage; - private DarkUI.Controls.DarkComboBox comboRoomType; - private DarkUI.Controls.DarkLabel darkLabel15; - private TombLib.Controls.DarkSearchableComboBox comboRoom; - private DarkUI.Controls.DarkPanel panelRoomAmbientLight; - private DarkUI.Controls.DarkLabel darkLabel3; - private DarkUI.Controls.DarkButton butRoomDown; - private DarkUI.Controls.DarkButton butEditRoomName; - private DarkUI.Controls.DarkButton butCropRoom; - private DarkUI.Controls.DarkButton butSplitRoom; - private DarkUI.Controls.DarkCheckBox cbNoLensflare; - private System.Windows.Forms.ToolTip toolTip; - private DarkUI.Controls.DarkButton butLocked; - private DarkUI.Controls.DarkButton butDublicateRoom; - private DarkUI.Controls.DarkButton butDeleteRoom; - private DarkUI.Controls.DarkNumericUpDown numLightEffectStrength; - private TombLib.Controls.DarkAutocompleteTextBox tbRoomTags; - private DarkUI.Controls.DarkLabel darkLabel2; - private DarkUI.Controls.DarkButton butNewRoom; - private DarkUI.Controls.DarkLabel darkLabel1; - private DarkUI.Controls.DarkComboBox comboPortalShade; - private DarkUI.Controls.DarkButton butSelectPreviousRoom; - private DarkUI.Controls.DarkButton butHidden; - private DarkUI.Controls.DarkCheckBox cbFlagNoCaustics; + private System.Windows.Forms.Integration.ElementHost _elementHost; + private WPF.ToolWindows.RoomOptions _roomOptionsView; } } diff --git a/TombEditor/ToolWindows/RoomOptions.cs b/TombEditor/ToolWindows/RoomOptions.cs index 546b840888..4fb3bbead3 100644 --- a/TombEditor/ToolWindows/RoomOptions.cs +++ b/TombEditor/ToolWindows/RoomOptions.cs @@ -1,413 +1,21 @@ using DarkUI.Docking; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Numerics; -using TombLib.Forms; -using TombLib.LevelData; -using TombLib.Utils; namespace TombEditor.ToolWindows { public partial class RoomOptions : DarkToolWindow { - private readonly Editor _editor; - public RoomOptions() { InitializeComponent(); - CommandHandler.AssignCommandsToControls(Editor.Instance, this, toolTip); - - _editor = Editor.Instance; - _editor.EditorEventRaised += EditorEventRaised; - - // A hack to edit textbox size - tbRoomTags.AutoSize = false; - tbRoomTags.Height = 23; } protected override void Dispose(bool disposing) { if (disposing) - _editor.EditorEventRaised -= EditorEventRaised; + _roomOptionsView?.Cleanup(); if (disposing && components != null) components.Dispose(); base.Dispose(disposing); } - - private int GetFlipMapSelectedIndex(Room room) - { - return room.Alternated ? ((comboFlipMap.Items.Count - 1 <= room.AlternateGroup) ? -1 : room.AlternateGroup + 1) : 0; - } - - private void EditorEventRaised(IEditorEvent obj) - { - // Disable version-specific controls - if (obj is Editor.InitEvent || - obj is Editor.GameVersionChangedEvent || - obj is Editor.LevelChangedEvent) - { - bool isTR4orNG = _editor.Level.Settings.GameVersion.Native() == TRVersion.Game.TR4; - bool isNGorTEN = _editor.Level.Settings.GameVersion is TRVersion.Game.TRNG or TRVersion.Game.TombEngine; - bool supportsLensflare = _editor.Level.Settings.GameVersion.SupportsLensflare(); - bool supportsReverb = _editor.Level.Settings.GameVersion.SupportsReverberation(); - bool isTR1 = _editor.Level.Settings.GameVersion.Native() == TRVersion.Game.TR1; - bool isTEN = _editor.Level.Settings.GameVersion is TRVersion.Game.TombEngine; - - cbHorizon.Enabled = !isTR1 || _editor.Level.IsTRX; - cbFlagOutside.Enabled = !isTR1 || _editor.Level.IsTRX; - cbFlagCold.Enabled = isNGorTEN; - cbFlagDamage.Enabled = isNGorTEN; - cbFlagNoCaustics.Enabled = isTEN; - cbNoLensflare.Enabled = supportsLensflare; - comboReverberation.Enabled = supportsReverb; - comboReverberation.SelectedIndexChanged -= comboReverberation_SelectedIndexChanged; // Prevent SelectedIndexChanged event from DataSource assignment in next line - comboReverberation.DataSource = isTR4orNG && _editor.Level.Settings.GameEnableExtraReverbPresets ? StringEnums.ExtraReverberationTypes : StringEnums.ReverberationTypes; - comboReverberation.SelectedIndexChanged += comboReverberation_SelectedIndexChanged; - comboReverberation.SelectedIndex = _editor.SelectedRoom.Properties.Reverberation < comboReverberation.Items.Count ? _editor.SelectedRoom.Properties.Reverberation : -1; - comboReverberation.DropDownWidth = isTR4orNG && _editor.Level.Settings.GameEnableExtraReverbPresets ? 121 : 71; - comboLightEffect.Enabled = !isTR1; - numLightEffectStrength.Enabled = !isTR1; - - RepopulateRoomTypes(); - RepopulateFlipmapList(); - - comboFlipMap.SelectedIndex = GetFlipMapSelectedIndex(_editor.SelectedRoom); - } - - // Update the room list - if (obj is Editor.InitEvent || obj is Editor.RoomListChangedEvent) - { - // Adjust the amount of entries in the combo list - while (comboRoom.Items.Count > _editor.Level.Rooms.GetLength(0)) - comboRoom.Items.RemoveAt(comboRoom.Items.Count - 1); - while (comboRoom.Items.Count < _editor.Level.Rooms.GetLength(0)) - comboRoom.Items.Add(""); - - // Update the room list - for (int i = 0; i < _editor.Level.Rooms.GetLength(0); i++) - if (_editor.Level.Rooms[i] != null) - comboRoom.Items[i] = i + ": " + _editor.Level.Rooms[i].Name; - else - comboRoom.Items[i] = i + ": --- Empty room ---"; - } - - // Update taglist - if (obj is Editor.LevelChangedEvent || obj is Editor.SelectedRoomChangedEvent) - { - tbRoomTags.AutocompleteWords.Clear(); - foreach (var room in (_editor.Level.Rooms)) - if (room != null && room.ExistsInLevel) - tbRoomTags.AutocompleteWords.AddRange(room.Properties.Tags.Except(tbRoomTags.AutocompleteWords)); - } - - // Update the room property controls - if (obj is Editor.InitEvent || obj is Editor.SelectedRoomChangedEvent || obj is Editor.LevelChangedEvent || - _editor.IsSelectedRoomEvent(obj as Editor.RoomPropertiesChangedEvent)) - { - Room room = _editor.SelectedRoom; - if (obj is Editor.InitEvent || obj is Editor.SelectedRoomChangedEvent) - comboRoom.SelectedIndex = _editor.Level.Rooms.ReferenceIndexOf(room); - - // Update the state of other controls - ReadRoomType(); - panelRoomAmbientLight.BackColor = (room.Properties.AmbientLight * new Vector3(0.5f, 0.5f, 0.5f)).ToWinFormsColor(); - comboReverberation.SelectedIndex = room.Properties.Reverberation < comboReverberation.Items.Count ? room.Properties.Reverberation : -1; - comboPortalShade.SelectedIndex = (int)room.Properties.LightInterpolationMode; - comboLightEffect.SelectedIndex = (int)room.Properties.LightEffect; - numLightEffectStrength.Value = room.Properties.LightEffectStrength; - cbFlagCold.Checked = room.Properties.FlagCold; - cbFlagDamage.Checked = room.Properties.FlagDamage; - cbFlagOutside.Checked = room.Properties.FlagOutside; - cbFlagNoCaustics.Checked = room.Properties.FlagNoCaustics; - cbHorizon.Checked = room.Properties.FlagHorizon; - cbNoLensflare.Checked = room.Properties.FlagNoLensflare; - cbNoPathfinding.Checked = room.Properties.FlagExcludeFromPathFinding; - butHidden.Checked = room.Properties.Hidden; - - if (!tbRoomTags.ReadOnly) // Only update tags field if we're not in the process of editing - { - if (room.Properties.Tags.Count > 0) - tbRoomTags.Text = string.Join(" ", room.Properties.Tags); - else - tbRoomTags.Text = ""; - } - - if (room.AlternateBaseRoom != null) - { - butLocked.Enabled = false; - butLocked.Checked = room.AlternateBaseRoom.Properties.Locked; - } - else - { - butLocked.Enabled = true; - butLocked.Checked = room.Properties.Locked; - } - - comboFlipMap.SelectedIndex = GetFlipMapSelectedIndex(room); - } - - // Activate default control - if (obj is Editor.DefaultControlActivationEvent) - { - if (DockPanel != null && ((Editor.DefaultControlActivationEvent)obj).ContainerName == GetType().Name) - { - MakeActive(); - comboRoom.Search(); - } - } - - // Update tooltip texts - if (obj is Editor.ConfigurationChangedEvent) - { - if (((Editor.ConfigurationChangedEvent)obj).UpdateKeyboardShortcuts) - CommandHandler.AssignCommandsToControls(_editor, this, toolTip, true); - } - } - - private void RepopulateFlipmapList() - { - var index = comboFlipMap.SelectedIndex; - - comboFlipMap.Items.Clear(); - comboFlipMap.Items.Add("None"); - - int flipmapCount = (_editor.Level.Settings.GameVersion == TRVersion.Game.TombEngine) ? byte.MaxValue : 15; - - for (int i = 0; i < flipmapCount; i++) - comboFlipMap.Items.Add(i.ToString()); - - comboFlipMap.SelectedIndex = (comboFlipMap.Items.Count - 1 <= index) ? -1 : index; - } - - private void RepopulateRoomTypes() - { - // Repopulate room type - comboRoomType.Items.Clear(); - comboRoomType.Items.Add("Normal"); - comboRoomType.Items.Add("Water"); - - if (_editor.Level.Settings.GameVersion == TRVersion.Game.TR3 || - _editor.Level.IsTRX || - _editor.Level.IsNG || - _editor.Level.IsTombEngine) - comboRoomType.Items.Add("Quicksand"); - - if (_editor.Level.IsNG) - StringEnums.NGRoomTypes.ForEach(i => comboRoomType.Items.Add(i)); - - ReadRoomType(); - - // Repopulate room effect type - bool isTR2 = _editor.Level.Settings.GameVersion.Native() == TRVersion.Game.TR2; - var list = new List() - { - "None", - "Default", - "Reflection", - "Glow", - isTR2 ? "Flicker" : "Move", // Show as flicker for TR2 - isTR2 ? "Sunset" : "Glow & Move", // Show as sunset for TR2 - "Mist" - }; - - var backupIndex = comboLightEffect.SelectedIndex; - comboLightEffect.Items.Clear(); - list.ForEach(i => comboLightEffect.Items.Add(i)); - comboLightEffect.SelectedIndex = backupIndex; - } - - private void WriteRoomType() - { - RoomType newType; - byte newStrength = 0; - - switch (comboRoomType.SelectedIndex) - { - case -1: - // Wrong type, do nothing - return; - case 0: - newType = RoomType.Normal; - break; - case 1: - newType = RoomType.Water; - break; - case 2: - newType = RoomType.Quicksand; - break; - default: - if (comboRoomType.SelectedIndex <= 6) - { - newType = RoomType.Rain; - newStrength = (byte)(comboRoomType.SelectedIndex - 3); - } - else - { - newType = RoomType.Snow; - newStrength = (byte)(comboRoomType.SelectedIndex - 7); - } - break; - } - - if (_editor.SelectedRoom.Properties.Type != newType || _editor.SelectedRoom.Properties.TypeStrength != newStrength) - { - _editor.SelectedRoom.Properties.Type = newType; - _editor.SelectedRoom.Properties.TypeStrength = newStrength; - _editor.RoomPropertiesChange(_editor.SelectedRoom); - } - } - - private void ReadRoomType() - { - var room = _editor.SelectedRoom; - - // Cleverly switch room types dependent on game version. - // We disable rain/snow types for TombEngine because it is expected to set these options with triggers and/or script. - - int roomType = -1; - if (room.Properties.Type == RoomType.Quicksand && - (_editor.Level.Settings.GameVersion != TRVersion.Game.TR3 && - _editor.Level.Settings.GameVersion != TRVersion.Game.TRNG && - _editor.Level.Settings.GameVersion != TRVersion.Game.TombEngine && - !_editor.Level.IsTRX)) - roomType = -1; - else if ((room.Properties.Type == RoomType.Rain || room.Properties.Type == RoomType.Snow) && - _editor.Level.Settings.GameVersion != TRVersion.Game.TRNG) - roomType = -1; - else - { - switch (room.Properties.Type) - { - case RoomType.Normal: - roomType = 0; - break; - case RoomType.Water: - roomType = 1; - break; - case RoomType.Quicksand: - roomType = 2; - break; - case RoomType.Rain: - roomType = 3 + room.Properties.TypeStrength; - break; - case RoomType.Snow: - roomType = 7 + room.Properties.TypeStrength; - break; - } - } - - comboRoomType.SelectedIndex = roomType; - - // If selected type is -1 it means this room type is unsupported in current version. Throw a message about it. - if (roomType == -1) - _editor.SendMessage("Current room type is not supported in this engine version.\nChange it manually or switch engine version.", PopupType.Warning); - - } - - private void comboRoom_SelectedIndexChanged(object sender, EventArgs e) - { - Room selectedRoom = _editor.Level.Rooms[comboRoom.SelectedIndex]; - if (selectedRoom == null) - EditorActions.MakeNewRoom(comboRoom.SelectedIndex); - else - _editor.SelectRoom(selectedRoom); - } - - private void comboFlipMap_SelectedIndexChanged(object sender, EventArgs e) - { - if (_editor.SelectedRoom == null || comboFlipMap.SelectedIndex == -1) - return; - - var room = _editor.SelectedRoom; - short alternateGroupIndex = (short)(comboFlipMap.SelectedIndex - 1); - - if (room.Alternated) - { - if (alternateGroupIndex == -1) - { // Delete flipped room - EditorActions.AlternateRoomDisableWithWarning(room, this); - } - else - { // Change flipped map number, not much to do here - if (room.AlternateGroup != alternateGroupIndex && - room.AlternateOpposite.AlternateGroup != alternateGroupIndex) - { - - room.AlternateGroup = alternateGroupIndex; - room.AlternateOpposite.AlternateGroup = alternateGroupIndex; - _editor.RoomPropertiesChange(room); - _editor.RoomPropertiesChange(room.AlternateOpposite); - } - } - } - else - { - if (alternateGroupIndex != -1) - {// Create a new flipped room - EditorActions.AlternateRoomEnable(room, alternateGroupIndex); - } - } - - // Update combo box even if nothing changed internally - // to correct invalid user input - EditorEventRaised(new Editor.RoomPropertiesChangedEvent { Room = room }); - } - - private void comboReverberation_SelectedIndexChanged(object sender, EventArgs e) - { - if (_editor.SelectedRoom.Properties.Reverberation == comboReverberation.SelectedIndex) - return; - - // Show extra tooltips in case reverb modes are extended - if (_editor.Level.Settings.GameEnableExtraReverbPresets && comboReverberation.SelectedIndex > 0) - toolTip.SetToolTip(comboReverberation, comboReverberation.Text); - else - toolTip.SetToolTip(comboReverberation, string.Empty); - - _editor.SelectedRoom.Properties.Reverberation = (byte)comboReverberation.SelectedIndex; - _editor.RoomPropertiesChange(_editor.SelectedRoom); - } - - private void numLightEffectStrength_ValueChanged(object sender, EventArgs e) - { - _editor.SelectedRoom.Properties.LightEffectStrength = (byte)numLightEffectStrength.Value; - _editor.RoomPropertiesChange(_editor.SelectedRoom); - } - - private void comboRoomType_SelectedIndexChanged(object sender, EventArgs e) => WriteRoomType(); - - private void comboLightEffect_SelectedIndexChanged(object sender, EventArgs e) - { - if (_editor.SelectedRoom.Properties.LightEffect == (RoomLightEffect)comboLightEffect.SelectedIndex) - return; - - _editor.SelectedRoom.Properties.LightEffect = (RoomLightEffect)comboLightEffect.SelectedIndex; - _editor.RoomPropertiesChange(_editor.SelectedRoom); - } - - private void comboPortalShade_SelectedIndexChanged(object sender, EventArgs e) - { - - if (_editor.SelectedRoom.Properties.LightInterpolationMode == (RoomLightInterpolationMode)comboPortalShade.SelectedIndex) - return; - - _editor.SelectedRoom.Properties.LightInterpolationMode = (RoomLightInterpolationMode)comboPortalShade.SelectedIndex; - _editor.RoomPropertiesChange(_editor.SelectedRoom); - } - - private void TbTags_TextChanged(object sender, EventArgs e) - { - if (_editor.SelectedRoom == null) - return; - - tbRoomTags.ReadOnly = true; // Prevent textbox from internally recalling this event - - _editor.SelectedRoom.Properties.Tags = tbRoomTags.Text.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList(); - _editor.RoomPropertiesChange(_editor.SelectedRoom); - - tbRoomTags.ReadOnly = false; // Re-enable editing - } - } } diff --git a/TombEditor/ToolWindows/SectorOptions.Designer.cs b/TombEditor/ToolWindows/SectorOptions.Designer.cs index de328e59c1..ddcdf8f6ab 100644 --- a/TombEditor/ToolWindows/SectorOptions.Designer.cs +++ b/TombEditor/ToolWindows/SectorOptions.Designer.cs @@ -2,436 +2,39 @@ { partial class SectorOptions { - /// - /// Required designer variable. - /// private System.ComponentModel.IContainer components = null; #region Component Designer generated code - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// private void InitializeComponent() { - this.components = new System.ComponentModel.Container(); - this.panel2DGrid = new TombEditor.Controls.Panel2DGrid(); - this.panelRight = new System.Windows.Forms.Panel(); - this.butAddGhostBlock = new DarkUI.Controls.DarkButton(); - this.butCeiling = new DarkUI.Controls.DarkButton(); - this.butClimbPositiveZ = new DarkUI.Controls.DarkButton(); - this.butClimbPositiveX = new DarkUI.Controls.DarkButton(); - this.butClimbNegativeZ = new DarkUI.Controls.DarkButton(); - this.butClimbNegativeX = new DarkUI.Controls.DarkButton(); - this.butNotWalkableBox = new DarkUI.Controls.DarkButton(); - this.butPortal = new DarkUI.Controls.DarkButton(); - this.butFlagTriggerTriggerer = new DarkUI.Controls.DarkButton(); - this.butDeath = new DarkUI.Controls.DarkButton(); - this.butForceSolidFloor = new DarkUI.Controls.DarkButton(); - this.butMonkey = new DarkUI.Controls.DarkButton(); - this.butFlagBeetle = new DarkUI.Controls.DarkButton(); - this.butBox = new DarkUI.Controls.DarkButton(); - this.butFloor = new DarkUI.Controls.DarkButton(); - this.butWall = new DarkUI.Controls.DarkButton(); - this.panel2DGrid_sub = new System.Windows.Forms.Panel(); - this.panelBottom = new System.Windows.Forms.Panel(); - this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); - this.butDiagonalWall = new DarkUI.Controls.DarkButton(); - this.butDiagonalFloor = new DarkUI.Controls.DarkButton(); - this.butDiagonalCeiling = new DarkUI.Controls.DarkButton(); - this.toolTip = new System.Windows.Forms.ToolTip(this.components); - this.panelRight.SuspendLayout(); - this.panel2DGrid_sub.SuspendLayout(); - this.panelBottom.SuspendLayout(); - this.tableLayoutPanel1.SuspendLayout(); - this.SuspendLayout(); + _elementHost = new System.Windows.Forms.Integration.ElementHost(); + _sectorOptionsView = new WPF.ToolWindows.SectorOptions(); + SuspendLayout(); // - // panel2DGrid + // _elementHost // - this.panel2DGrid.Dock = System.Windows.Forms.DockStyle.Fill; - this.panel2DGrid.Location = new System.Drawing.Point(2, 0); - this.panel2DGrid.Name = "panel2DGrid"; - this.panel2DGrid.Padding = new System.Windows.Forms.Padding(2); - this.panel2DGrid.Room = null; - this.panel2DGrid.Size = new System.Drawing.Size(224, 223); - this.panel2DGrid.TabIndex = 103; - // - // panelRight - // - this.panelRight.Controls.Add(this.butAddGhostBlock); - this.panelRight.Controls.Add(this.butCeiling); - this.panelRight.Controls.Add(this.butClimbPositiveZ); - this.panelRight.Controls.Add(this.butClimbPositiveX); - this.panelRight.Controls.Add(this.butClimbNegativeZ); - this.panelRight.Controls.Add(this.butClimbNegativeX); - this.panelRight.Controls.Add(this.butNotWalkableBox); - this.panelRight.Controls.Add(this.butPortal); - this.panelRight.Controls.Add(this.butFlagTriggerTriggerer); - this.panelRight.Controls.Add(this.butDeath); - this.panelRight.Controls.Add(this.butForceSolidFloor); - this.panelRight.Controls.Add(this.butMonkey); - this.panelRight.Controls.Add(this.butFlagBeetle); - this.panelRight.Controls.Add(this.butBox); - this.panelRight.Controls.Add(this.butFloor); - this.panelRight.Controls.Add(this.butWall); - this.panelRight.Dock = System.Windows.Forms.DockStyle.Right; - this.panelRight.Location = new System.Drawing.Point(226, 0); - this.panelRight.Name = "panelRight"; - this.panelRight.Padding = new System.Windows.Forms.Padding(2); - this.panelRight.Size = new System.Drawing.Size(58, 223); - this.panelRight.TabIndex = 109; - // - // butAddGhostBlock - // - this.butAddGhostBlock.Anchor = System.Windows.Forms.AnchorStyles.Right; - this.butAddGhostBlock.Checked = false; - this.butAddGhostBlock.Image = global::TombEditor.Properties.Resources.objects_geometry_override_16; - this.butAddGhostBlock.Location = new System.Drawing.Point(3, 197); - this.butAddGhostBlock.Name = "butAddGhostBlock"; - this.butAddGhostBlock.Size = new System.Drawing.Size(24, 24); - this.butAddGhostBlock.TabIndex = 14; - this.butAddGhostBlock.Tag = "AddGhostBlocksToSelection"; - // - // butCeiling - // - this.butCeiling.Anchor = System.Windows.Forms.AnchorStyles.Right; - this.butCeiling.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(170)))), ((int)(((byte)(170))))); - this.butCeiling.BackColorUseGeneric = false; - this.butCeiling.Checked = false; - this.butCeiling.ForeColor = System.Drawing.Color.White; - this.butCeiling.Image = global::TombEditor.Properties.Resources.sectortype_Roof_16; - this.butCeiling.Location = new System.Drawing.Point(32, 1); - this.butCeiling.Name = "butCeiling"; - this.butCeiling.Size = new System.Drawing.Size(24, 24); - this.butCeiling.TabIndex = 1; - this.butCeiling.Tag = "SetCeiling"; - this.butCeiling.MouseEnter += new System.EventHandler(this.but_MouseEnter); - // - // butClimbPositiveZ - // - this.butClimbPositiveZ.Anchor = System.Windows.Forms.AnchorStyles.Right; - this.butClimbPositiveZ.Checked = false; - this.butClimbPositiveZ.Image = global::TombEditor.Properties.Resources.sectortype_ClimbNorth_16; - this.butClimbPositiveZ.Location = new System.Drawing.Point(3, 141); - this.butClimbPositiveZ.Name = "butClimbPositiveZ"; - this.butClimbPositiveZ.Size = new System.Drawing.Size(24, 24); - this.butClimbPositiveZ.TabIndex = 10; - this.butClimbPositiveZ.Tag = "SetClimbPositiveZ"; - this.butClimbPositiveZ.MouseEnter += new System.EventHandler(this.but_MouseEnter); - // - // butClimbPositiveX - // - this.butClimbPositiveX.Anchor = System.Windows.Forms.AnchorStyles.Right; - this.butClimbPositiveX.Checked = false; - this.butClimbPositiveX.Image = global::TombEditor.Properties.Resources.sectortype_ClimbEast_16; - this.butClimbPositiveX.Location = new System.Drawing.Point(32, 169); - this.butClimbPositiveX.Name = "butClimbPositiveX"; - this.butClimbPositiveX.Size = new System.Drawing.Size(24, 24); - this.butClimbPositiveX.TabIndex = 13; - this.butClimbPositiveX.Tag = "SetClimbPositiveX"; - this.butClimbPositiveX.MouseEnter += new System.EventHandler(this.but_MouseEnter); - // - // butClimbNegativeZ - // - this.butClimbNegativeZ.Anchor = System.Windows.Forms.AnchorStyles.Right; - this.butClimbNegativeZ.Checked = false; - this.butClimbNegativeZ.Image = global::TombEditor.Properties.Resources.sectortype_ClimbSouth_1_16; - this.butClimbNegativeZ.Location = new System.Drawing.Point(32, 141); - this.butClimbNegativeZ.Name = "butClimbNegativeZ"; - this.butClimbNegativeZ.Size = new System.Drawing.Size(24, 24); - this.butClimbNegativeZ.TabIndex = 11; - this.butClimbNegativeZ.Tag = "SetClimbNegativeZ"; - this.butClimbNegativeZ.MouseEnter += new System.EventHandler(this.but_MouseEnter); - // - // butClimbNegativeX - // - this.butClimbNegativeX.Anchor = System.Windows.Forms.AnchorStyles.Right; - this.butClimbNegativeX.Checked = false; - this.butClimbNegativeX.Image = global::TombEditor.Properties.Resources.sectortype_ClimbWest_16; - this.butClimbNegativeX.Location = new System.Drawing.Point(3, 169); - this.butClimbNegativeX.Name = "butClimbNegativeX"; - this.butClimbNegativeX.Size = new System.Drawing.Size(24, 24); - this.butClimbNegativeX.TabIndex = 12; - this.butClimbNegativeX.Tag = "SetClimbNegativeX"; - this.butClimbNegativeX.MouseEnter += new System.EventHandler(this.but_MouseEnter); - // - // butNotWalkableBox - // - this.butNotWalkableBox.Anchor = System.Windows.Forms.AnchorStyles.Right; - this.butNotWalkableBox.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(150))))); - this.butNotWalkableBox.BackColorUseGeneric = false; - this.butNotWalkableBox.Checked = false; - this.butNotWalkableBox.ForeColor = System.Drawing.Color.White; - this.butNotWalkableBox.Image = global::TombEditor.Properties.Resources.sectortype_NotWalkable_16; - this.butNotWalkableBox.Location = new System.Drawing.Point(32, 29); - this.butNotWalkableBox.Name = "butNotWalkableBox"; - this.butNotWalkableBox.Size = new System.Drawing.Size(24, 24); - this.butNotWalkableBox.TabIndex = 3; - this.butNotWalkableBox.Tag = "SetNotWalkable"; - this.butNotWalkableBox.MouseEnter += new System.EventHandler(this.but_MouseEnter); - // - // butPortal - // - this.butPortal.Anchor = System.Windows.Forms.AnchorStyles.Right; - this.butPortal.BackColor = System.Drawing.Color.Black; - this.butPortal.BackColorUseGeneric = false; - this.butPortal.Checked = false; - this.butPortal.ForeColor = System.Drawing.Color.White; - this.butPortal.Image = global::TombEditor.Properties.Resources.sectortype_Portal__16; - this.butPortal.Location = new System.Drawing.Point(3, 85); - this.butPortal.Name = "butPortal"; - this.butPortal.Size = new System.Drawing.Size(24, 24); - this.butPortal.TabIndex = 6; - this.butPortal.Tag = "AddPortal"; - this.butPortal.MouseEnter += new System.EventHandler(this.but_MouseEnter); - // - // butFlagTriggerTriggerer - // - this.butFlagTriggerTriggerer.Anchor = System.Windows.Forms.AnchorStyles.Right; - this.butFlagTriggerTriggerer.Checked = false; - this.butFlagTriggerTriggerer.Image = global::TombEditor.Properties.Resources.sectortype_TriggerTriggerer_16; - this.butFlagTriggerTriggerer.Location = new System.Drawing.Point(3, 113); - this.butFlagTriggerTriggerer.Name = "butFlagTriggerTriggerer"; - this.butFlagTriggerTriggerer.Size = new System.Drawing.Size(24, 24); - this.butFlagTriggerTriggerer.TabIndex = 9; - this.butFlagTriggerTriggerer.Tag = "SetTriggerTriggerer"; - this.butFlagTriggerTriggerer.MouseEnter += new System.EventHandler(this.but_MouseEnter); - // - // butDeath - // - this.butDeath.Anchor = System.Windows.Forms.AnchorStyles.Right; - this.butDeath.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(200)))), ((int)(((byte)(0))))); - this.butDeath.BackColorUseGeneric = false; - this.butDeath.Checked = false; - this.butDeath.ForeColor = System.Drawing.Color.White; - this.butDeath.Image = global::TombEditor.Properties.Resources.sectortype_Death_16; - this.butDeath.Location = new System.Drawing.Point(32, 57); - this.butDeath.Name = "butDeath"; - this.butDeath.Size = new System.Drawing.Size(24, 24); - this.butDeath.TabIndex = 5; - this.butDeath.Tag = "SetDeath"; - this.butDeath.MouseEnter += new System.EventHandler(this.but_MouseEnter); - // - // butForceSolidFloor - // - this.butForceSolidFloor.Anchor = System.Windows.Forms.AnchorStyles.Right; - this.butForceSolidFloor.Checked = false; - this.butForceSolidFloor.Image = global::TombEditor.Properties.Resources.sectortype_ForceSolidFloor_16_copy; - this.butForceSolidFloor.Location = new System.Drawing.Point(32, 197); - this.butForceSolidFloor.Name = "butForceSolidFloor"; - this.butForceSolidFloor.Size = new System.Drawing.Size(24, 24); - this.butForceSolidFloor.TabIndex = 15; - this.butForceSolidFloor.Tag = "ToggleForceFloorSolid"; - this.butForceSolidFloor.MouseEnter += new System.EventHandler(this.but_MouseEnter); - // - // butMonkey - // - this.butMonkey.Anchor = System.Windows.Forms.AnchorStyles.Right; - this.butMonkey.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.butMonkey.BackColorUseGeneric = false; - this.butMonkey.Checked = false; - this.butMonkey.ForeColor = System.Drawing.Color.White; - this.butMonkey.Image = global::TombEditor.Properties.Resources.sectortype_Monkey_16; - this.butMonkey.Location = new System.Drawing.Point(3, 57); - this.butMonkey.Name = "butMonkey"; - this.butMonkey.Size = new System.Drawing.Size(24, 24); - this.butMonkey.TabIndex = 4; - this.butMonkey.Tag = "SetMonkeyswing"; - this.butMonkey.MouseEnter += new System.EventHandler(this.but_MouseEnter); - // - // butFlagBeetle - // - this.butFlagBeetle.Anchor = System.Windows.Forms.AnchorStyles.Right; - this.butFlagBeetle.Checked = false; - this.butFlagBeetle.Image = global::TombEditor.Properties.Resources.sectortype_Beetle_16; - this.butFlagBeetle.Location = new System.Drawing.Point(32, 113); - this.butFlagBeetle.Name = "butFlagBeetle"; - this.butFlagBeetle.Size = new System.Drawing.Size(24, 24); - this.butFlagBeetle.TabIndex = 8; - this.butFlagBeetle.Tag = "SetBeetleCheckpoint"; - this.butFlagBeetle.MouseEnter += new System.EventHandler(this.but_MouseEnter); - // - // butBox - // - this.butBox.Anchor = System.Windows.Forms.AnchorStyles.Right; - this.butBox.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(100)))), ((int)(((byte)(100))))); - this.butBox.BackColorUseGeneric = false; - this.butBox.Checked = false; - this.butBox.ForeColor = System.Drawing.Color.White; - this.butBox.Image = global::TombEditor.Properties.Resources.sectortype_Box_16; - this.butBox.Location = new System.Drawing.Point(3, 29); - this.butBox.Name = "butBox"; - this.butBox.Size = new System.Drawing.Size(24, 24); - this.butBox.TabIndex = 2; - this.butBox.Tag = "SetBox"; - this.butBox.MouseEnter += new System.EventHandler(this.but_MouseEnter); - // - // butFloor - // - this.butFloor.Anchor = System.Windows.Forms.AnchorStyles.Right; - this.butFloor.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(170)))), ((int)(((byte)(170))))); - this.butFloor.BackColorUseGeneric = false; - this.butFloor.Checked = false; - this.butFloor.ForeColor = System.Drawing.Color.White; - this.butFloor.Image = global::TombEditor.Properties.Resources.sectortype_Floor_1_16; - this.butFloor.Location = new System.Drawing.Point(3, 1); - this.butFloor.Name = "butFloor"; - this.butFloor.Size = new System.Drawing.Size(24, 24); - this.butFloor.TabIndex = 0; - this.butFloor.Tag = "SetFloor"; - this.butFloor.MouseEnter += new System.EventHandler(this.but_MouseEnter); - // - // butWall - // - this.butWall.Anchor = System.Windows.Forms.AnchorStyles.Right; - this.butWall.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(120)))), ((int)(((byte)(0))))); - this.butWall.BackColorUseGeneric = false; - this.butWall.Checked = false; - this.butWall.ForeColor = System.Drawing.Color.White; - this.butWall.Image = global::TombEditor.Properties.Resources.sectortype_Wall_1_16; - this.butWall.Location = new System.Drawing.Point(32, 85); - this.butWall.Name = "butWall"; - this.butWall.Size = new System.Drawing.Size(24, 24); - this.butWall.TabIndex = 7; - this.butWall.Tag = "SetWall"; - this.butWall.MouseEnter += new System.EventHandler(this.but_MouseEnter); - // - // panel2DGrid_sub - // - this.panel2DGrid_sub.Controls.Add(this.panel2DGrid); - this.panel2DGrid_sub.Controls.Add(this.panelRight); - this.panel2DGrid_sub.Dock = System.Windows.Forms.DockStyle.Fill; - this.panel2DGrid_sub.Location = new System.Drawing.Point(0, 25); - this.panel2DGrid_sub.Name = "panel2DGrid_sub"; - this.panel2DGrid_sub.Padding = new System.Windows.Forms.Padding(2, 0, 0, 4); - this.panel2DGrid_sub.Size = new System.Drawing.Size(284, 227); - this.panel2DGrid_sub.TabIndex = 111; - // - // panelBottom - // - this.panelBottom.Controls.Add(this.tableLayoutPanel1); - this.panelBottom.Dock = System.Windows.Forms.DockStyle.Bottom; - this.panelBottom.Location = new System.Drawing.Point(0, 252); - this.panelBottom.Margin = new System.Windows.Forms.Padding(0); - this.panelBottom.Name = "panelBottom"; - this.panelBottom.Size = new System.Drawing.Size(284, 26); - this.panelBottom.TabIndex = 110; - // - // tableLayoutPanel1 - // - this.tableLayoutPanel1.ColumnCount = 3; - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F)); - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F)); - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F)); - this.tableLayoutPanel1.Controls.Add(this.butDiagonalWall, 2, 0); - this.tableLayoutPanel1.Controls.Add(this.butDiagonalFloor, 0, 0); - this.tableLayoutPanel1.Controls.Add(this.butDiagonalCeiling, 1, 0); - this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; - this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); - this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(0); - this.tableLayoutPanel1.Name = "tableLayoutPanel1"; - this.tableLayoutPanel1.RowCount = 1; - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel1.Size = new System.Drawing.Size(284, 26); - this.tableLayoutPanel1.TabIndex = 0; - // - // butDiagonalWall - // - this.butDiagonalWall.Checked = false; - this.butDiagonalWall.Dock = System.Windows.Forms.DockStyle.Fill; - this.butDiagonalWall.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.butDiagonalWall.Image = global::TombEditor.Properties.Resources.sectortype_DiagonalWall2_16; - this.butDiagonalWall.Location = new System.Drawing.Point(190, 0); - this.butDiagonalWall.Margin = new System.Windows.Forms.Padding(2, 0, 2, 2); - this.butDiagonalWall.Name = "butDiagonalWall"; - this.butDiagonalWall.Size = new System.Drawing.Size(92, 24); - this.butDiagonalWall.TabIndex = 18; - this.butDiagonalWall.Tag = "SetDiagonalWall"; - this.butDiagonalWall.Text = "Diag wall"; - this.butDiagonalWall.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; - // - // butDiagonalFloor - // - this.butDiagonalFloor.Checked = false; - this.butDiagonalFloor.Dock = System.Windows.Forms.DockStyle.Fill; - this.butDiagonalFloor.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.butDiagonalFloor.Image = global::TombEditor.Properties.Resources.sectortype_StepFloor_1_16; - this.butDiagonalFloor.Location = new System.Drawing.Point(2, 0); - this.butDiagonalFloor.Margin = new System.Windows.Forms.Padding(2, 0, 2, 2); - this.butDiagonalFloor.Name = "butDiagonalFloor"; - this.butDiagonalFloor.Size = new System.Drawing.Size(90, 24); - this.butDiagonalFloor.TabIndex = 16; - this.butDiagonalFloor.Tag = "SetDiagonalFloorStep"; - this.butDiagonalFloor.Text = "Floor step"; - this.butDiagonalFloor.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; - // - // butDiagonalCeiling - // - this.butDiagonalCeiling.Checked = false; - this.butDiagonalCeiling.Dock = System.Windows.Forms.DockStyle.Fill; - this.butDiagonalCeiling.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.butDiagonalCeiling.Image = global::TombEditor.Properties.Resources.sectortype_StepCeiling_16; - this.butDiagonalCeiling.Location = new System.Drawing.Point(96, 0); - this.butDiagonalCeiling.Margin = new System.Windows.Forms.Padding(2, 0, 2, 2); - this.butDiagonalCeiling.Name = "butDiagonalCeiling"; - this.butDiagonalCeiling.Size = new System.Drawing.Size(90, 24); - this.butDiagonalCeiling.TabIndex = 17; - this.butDiagonalCeiling.Tag = "SetDiagonalCeilingStep"; - this.butDiagonalCeiling.Text = "Ceiling step"; - this.butDiagonalCeiling.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; - // - // toolTip - // - this.toolTip.AutoPopDelay = 5000; - this.toolTip.InitialDelay = 500; - this.toolTip.ReshowDelay = 100; + _elementHost.Dock = System.Windows.Forms.DockStyle.Fill; + _elementHost.Name = "_elementHost"; + _elementHost.Child = _sectorOptionsView; // // SectorOptions // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.Controls.Add(this.panel2DGrid_sub); - this.Controls.Add(this.panelBottom); - this.DockText = "Sector Options"; - this.MinimumSize = new System.Drawing.Size(284, 278); - this.Name = "SectorOptions"; - this.SerializationKey = "SectorOptions"; - this.Size = new System.Drawing.Size(284, 278); - this.panelRight.ResumeLayout(false); - this.panel2DGrid_sub.ResumeLayout(false); - this.panelBottom.ResumeLayout(false); - this.tableLayoutPanel1.ResumeLayout(false); - this.ResumeLayout(false); - + AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + Controls.Add(_elementHost); + DockText = "Sector Options"; + MinimumSize = new System.Drawing.Size(284, 278); + Name = "SectorOptions"; + SerializationKey = "SectorOptions"; + Size = new System.Drawing.Size(284, 278); + ResumeLayout(false); } #endregion - private Controls.Panel2DGrid panel2DGrid; - private System.Windows.Forms.Panel panelRight; - private DarkUI.Controls.DarkButton butCeiling; - private DarkUI.Controls.DarkButton butClimbPositiveZ; - private DarkUI.Controls.DarkButton butClimbPositiveX; - private DarkUI.Controls.DarkButton butClimbNegativeZ; - private DarkUI.Controls.DarkButton butClimbNegativeX; - private DarkUI.Controls.DarkButton butNotWalkableBox; - private DarkUI.Controls.DarkButton butPortal; - private DarkUI.Controls.DarkButton butFlagTriggerTriggerer; - private DarkUI.Controls.DarkButton butDeath; - private DarkUI.Controls.DarkButton butForceSolidFloor; - private DarkUI.Controls.DarkButton butMonkey; - private DarkUI.Controls.DarkButton butFlagBeetle; - private DarkUI.Controls.DarkButton butBox; - private DarkUI.Controls.DarkButton butFloor; - private DarkUI.Controls.DarkButton butWall; - private System.Windows.Forms.Panel panel2DGrid_sub; - private DarkUI.Controls.DarkButton butDiagonalWall; - private DarkUI.Controls.DarkButton butDiagonalCeiling; - private DarkUI.Controls.DarkButton butDiagonalFloor; - private System.Windows.Forms.Panel panelBottom; - private System.Windows.Forms.ToolTip toolTip; - private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; - private DarkUI.Controls.DarkButton butAddGhostBlock; + + private System.Windows.Forms.Integration.ElementHost _elementHost; + private WPF.ToolWindows.SectorOptions _sectorOptionsView; } } diff --git a/TombEditor/ToolWindows/SectorOptions.cs b/TombEditor/ToolWindows/SectorOptions.cs index 0682cc1d7f..92121fb640 100644 --- a/TombEditor/ToolWindows/SectorOptions.cs +++ b/TombEditor/ToolWindows/SectorOptions.cs @@ -1,138 +1,21 @@ using DarkUI.Docking; -using NLog; -using System; -using System.Windows.Forms; -using TombLib.LevelData; -using TombLib.Rendering; -using TombLib.Utils; namespace TombEditor.ToolWindows { public partial class SectorOptions : DarkToolWindow { - private readonly Editor _editor; - private static readonly Logger logger = LogManager.GetCurrentClassLogger(); - - private const float iconSwitchBrightnessThreshold = 0.8f; - public SectorOptions() { InitializeComponent(); - CommandHandler.AssignCommandsToControls(Editor.Instance, this, toolTip); - - _editor = Editor.Instance; - _editor.EditorEventRaised += EditorEventRaised; - - panel2DGrid.Room = _editor.SelectedRoom; } protected override void Dispose(bool disposing) { if (disposing) - _editor.EditorEventRaised -= EditorEventRaised; + _sectorOptionsView?.Cleanup(); if (disposing && components != null) components.Dispose(); base.Dispose(disposing); } - - private void EditorEventRaised(IEditorEvent obj) - { - if (obj is Editor.SelectedRoomChangedEvent) - panel2DGrid.Room = ((Editor.SelectedRoomChangedEvent)obj).Current; - - // Update tooltip texts - if (obj is Editor.ConfigurationChangedEvent) - { - if (((Editor.ConfigurationChangedEvent)obj).UpdateKeyboardShortcuts) - CommandHandler.AssignCommandsToControls(_editor, this, toolTip, true); - } - - // Update color scheme on buttons - if (obj is Editor.ConfigurationChangedEvent || obj is Editor.InitEvent) - { - butFloor.BackColor = _editor.Configuration.UI_ColorScheme.ColorFloor.ToWinFormsColor(); - butFloor.Image = (butFloor.BackColor.GetBrightness() > iconSwitchBrightnessThreshold) ? Properties.Resources.sectortype_Floor_neg_16 : Properties.Resources.sectortype_Floor_1_16; - butCeiling.BackColor = _editor.Configuration.UI_ColorScheme.ColorFloor.ToWinFormsColor(); - butCeiling.Image = (butCeiling.BackColor.GetBrightness() > iconSwitchBrightnessThreshold) ? Properties.Resources.sectortype_Roof_neg_16 : Properties.Resources.sectortype_Roof_16; - butBox.BackColor = _editor.Configuration.UI_ColorScheme.ColorBox.ToWinFormsColor(); - butBox.Image = (butBox.BackColor.GetBrightness() > iconSwitchBrightnessThreshold) ? Properties.Resources.sectortype_Box_neg_16 : Properties.Resources.sectortype_Box_16; - butNotWalkableBox.BackColor = _editor.Configuration.UI_ColorScheme.ColorNotWalkable.ToWinFormsColor(); - butNotWalkableBox.Image = (butNotWalkableBox.BackColor.GetBrightness() > iconSwitchBrightnessThreshold) ? Properties.Resources.sectortype_NotWalkable_neg_16 : Properties.Resources.sectortype_NotWalkable_16; - butMonkey.BackColor = _editor.Configuration.UI_ColorScheme.ColorMonkey.ToWinFormsColor(); - butMonkey.Image = (butMonkey.BackColor.GetBrightness() > iconSwitchBrightnessThreshold) ? Properties.Resources.sectortype_Monkey_neg_16 : Properties.Resources.sectortype_Monkey_16; - butDeath.BackColor = _editor.Configuration.UI_ColorScheme.ColorDeath.ToWinFormsColor(); - butDeath.Image = (butDeath.BackColor.GetBrightness() > iconSwitchBrightnessThreshold) ? Properties.Resources.sectortype_Death_neg_16 : Properties.Resources.sectortype_Death_16; - butPortal.BackColor = _editor.Configuration.UI_ColorScheme.ColorPortal.ToWinFormsColor(); - butPortal.Image = (butPortal.BackColor.GetBrightness() > iconSwitchBrightnessThreshold) ? Properties.Resources.sectortype_Portal_neg__16 : Properties.Resources.sectortype_Portal__16; - butWall.BackColor = _editor.Configuration.UI_ColorScheme.ColorWall.ToWinFormsColor(); - butWall.Image = (butWall.BackColor.GetBrightness() > iconSwitchBrightnessThreshold) ? Properties.Resources.sectortype_Wall_neg_16 : Properties.Resources.sectortype_Wall_1_16; - } - - // Disable version-specific controls - if (obj is Editor.InitEvent || - obj is Editor.GameVersionChangedEvent || - obj is Editor.LevelChangedEvent) - { - bool climbingSupported = _editor.Level.Settings.GameVersion.SupportsClimbing(); - bool isTR345 = _editor.Level.Settings.GameVersion.Native() >= TRVersion.Game.TR3; - - butClimbNegativeX.Enabled = climbingSupported; - butClimbNegativeZ.Enabled = climbingSupported; - butClimbPositiveX.Enabled = climbingSupported; - butClimbPositiveZ.Enabled = climbingSupported; - butMonkey.Enabled = _editor.Level.Settings.GameVersion.SupportsMonkeySwing(); - butFlagBeetle.Enabled = isTR345; - butFlagTriggerTriggerer.Enabled = isTR345; - - if (_editor.Level.Settings.GameVersion.Native() >= TRVersion.Game.TR4) - { - butFlagTriggerTriggerer.Image = Properties.Resources.sectortype_TriggerTriggerer_16; - butFlagBeetle.Image = Properties.Resources.sectortype_Beetle_16; - } - else - { - - butFlagTriggerTriggerer.Image = Properties.Resources.sectortype_MinecartLeft_16; - butFlagBeetle.Image = Properties.Resources.sectortype_MinecartRight_16; - } - } - } - - private void but_MouseEnter(object sender, EventArgs e) - { - SetSectorColoringInfoPriority(sender as Control); - } - - private void SetSectorColoringInfoPriority(Control button) - { - if (!_editor.Configuration.UI_AutoSwitchSectorColoringInfo) - return; - - if (button == butBox) - _editor.SectorColoringManager.SetPriority(SectorColoringType.Box); - else if (button == butDeath) - _editor.SectorColoringManager.SetPriority(SectorColoringType.Death); - else if (button == butMonkey) - _editor.SectorColoringManager.SetPriority(SectorColoringType.Monkey); - else if (button == butFlagBeetle) - _editor.SectorColoringManager.SetPriority(SectorColoringType.Beetle); - else if (button == butFlagTriggerTriggerer) - _editor.SectorColoringManager.SetPriority(SectorColoringType.TriggerTriggerer); - else if (button == butNotWalkableBox) - _editor.SectorColoringManager.SetPriority(SectorColoringType.NotWalkableFloor); - else if (button == butPortal) - _editor.SectorColoringManager.SetPriority(SectorColoringType.Portal); - else if (button == butForceSolidFloor) - _editor.SectorColoringManager.SetPriority(SectorColoringType.ForceFloorSolid); - else if (button == butClimbNegativeX || - button == butClimbNegativeZ || - button == butClimbPositiveX || - button == butClimbPositiveZ) - _editor.SectorColoringManager.SetPriority(SectorColoringType.Climb); - else if (button == butWall) - _editor.SectorColoringManager.SetPriority(SectorColoringType.Wall); - else - _editor.SectorColoringManager.SetPriority(SectorColoringType.Trigger); - } } } diff --git a/TombEditor/WPF/Controls/Panel2DGrid.cs b/TombEditor/WPF/Controls/Panel2DGrid.cs new file mode 100644 index 0000000000..fca238c9d0 --- /dev/null +++ b/TombEditor/WPF/Controls/Panel2DGrid.cs @@ -0,0 +1,555 @@ +using NLog; +using System; +using System.ComponentModel; +using System.Linq; +using System.Numerics; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; +using TombLib; +using TombLib.LevelData; +using TombLib.Rendering; +using TombLib.Utils; + +namespace TombEditor.WPF.Controls +{ + /// + /// Native WPF replacement for the WinForms Panel2DGrid control. + /// Uses OnRender with DrawingContext for hardware-accelerated rendering. + /// + public class Panel2DGrid : FrameworkElement + { + private static readonly Logger logger = LogManager.GetCurrentClassLogger(); + + private static readonly double OutlineSectorColoringInfoWidth = 3.0; + + private readonly Editor _editor; + private Room _room; + private bool _doSectorSelection; + + // Frozen pens for rendering performance. + private static readonly Pen GridPen = CreateFrozenPen(Color.FromArgb(140, 0, 0, 0), 1.0); + private static readonly Pen BorderPen = CreateFrozenPen(Colors.Black, 1.0); + private static readonly Pen SelectedPortalPen = CreateFrozenPen(Colors.YellowGreen, 2.0); + private static readonly Pen SelectedTriggerPen = CreateFrozenPen(Colors.White, 2.0); + + public Room Room + { + get => _room; + set + { + if (_room == value) + return; + _room = value; + InvalidateVisual(); + } + } + + public Panel2DGrid() + { + ClipToBounds = true; + Focusable = true; + + if (DesignerProperties.GetIsInDesignMode(this)) + return; + + _editor = Editor.Instance; + _editor.EditorEventRaised += EditorEventRaised; + } + + public void Dispose() + { + _editor.EditorEventRaised -= EditorEventRaised; + } + + private void EditorEventRaised(IEditorEvent obj) + { + if (obj is SectorColoringManager.ChangeSectorColoringInfoEvent || + obj is Editor.GameVersionChangedEvent || + obj is Editor.SelectedSectorsChangedEvent || + obj is Editor.RoomSectorPropertiesChangedEvent || + obj is Editor.ObjectChangedEvent || + obj is Editor.RoomGeometryChangedEvent || + obj is Editor.ConfigurationChangedEvent || + obj is Editor.SelectedObjectChangedEvent e && IsObjectChangeRelevant(e)) + { + InvalidateVisual(); + } + + if (obj is Editor.ActionChangedEvent actionChanged) + { + bool isCameraRelocate = actionChanged.Current is EditorActionRelocateCamera; + Cursor = isCameraRelocate ? Cursors.Cross : Cursors.Arrow; + } + } + + private static bool IsObjectChangeRelevant(Editor.SelectedObjectChangedEvent e) + { + return e.Previous is SectorBasedObjectInstance || e.Current is SectorBasedObjectInstance; + } + + // Grid coordinate calculations. + + private VectorInt2 RoomSize => Room.SectorSize; + + private VectorInt2 GetGridDimensions() + { + return VectorInt2.Max(RoomSize, new VectorInt2(Room.DefaultRoomDimensions, Room.DefaultRoomDimensions)); + } + + private double GetGridStep() + { + var gridDimensions = GetGridDimensions(); + double w = ActualWidth; + double h = ActualHeight; + + if (w * gridDimensions.Y < h * gridDimensions.X) + return w / gridDimensions.X; + else + return h / gridDimensions.Y; + } + + private Rect GetVisualAreaTotal() + { + double w = ActualWidth; + double h = ActualHeight; + var gridDimensions = GetGridDimensions(); + double gridStep = GetGridStep(); + double gridW = gridDimensions.X * gridStep; + double gridH = gridDimensions.Y * gridStep; + + return new Rect( + (w - gridW) * 0.5, + (h - gridH) * 0.5, + gridW, + gridH); + } + + private Rect GetVisualAreaRoom() + { + var totalArea = GetVisualAreaTotal(); + double gridStep = GetGridStep(); + var gridDimensions = GetGridDimensions(); + var roomSize = RoomSize; + + return new Rect( + totalArea.X + gridStep * ((gridDimensions.X - roomSize.X) / 2), + totalArea.Y + gridStep * ((gridDimensions.Y - roomSize.Y) / 2), + gridStep * roomSize.X, + gridStep * roomSize.Y); + } + + private Point ToVisualCoord(VectorInt2 sectorCoord) + { + var roomArea = GetVisualAreaRoom(); + double gridStep = GetGridStep(); + return new Point( + sectorCoord.X * gridStep + roomArea.X, + roomArea.Bottom - (sectorCoord.Y + 1) * gridStep); + } + + private Rect ToVisualCoord(RectangleInt2 sectorArea) + { + var p0 = ToVisualCoord(sectorArea.Start); + var p1 = ToVisualCoord(sectorArea.End); + double gridStep = GetGridStep(); + return new Rect( + Math.Min(p0.X, p1.X), Math.Min(p0.Y, p1.Y), + Math.Abs(p1.X - p0.X) + gridStep, Math.Abs(p1.Y - p0.Y) + gridStep); + } + + private VectorInt2 FromVisualCoord(Point point) + { + var roomArea = GetVisualAreaRoom(); + double gridStep = GetGridStep(); + var roomSize = RoomSize; + return new VectorInt2( + (int)Math.Max(0, Math.Min(roomSize.X - 1, (point.X - roomArea.X) / gridStep)), + (int)Math.Max(0, Math.Min(roomSize.Y - 1, (roomArea.Bottom - point.Y) / gridStep))); + } + + // Mouse interaction. + + protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) + { + base.OnMouseLeftButtonDown(e); + CaptureMouse(); + HandleMouseDown(e.GetPosition(this), isRightButton: false); + e.Handled = true; + } + + protected override void OnMouseRightButtonDown(MouseButtonEventArgs e) + { + base.OnMouseRightButtonDown(e); + HandleMouseDown(e.GetPosition(this), isRightButton: true); + e.Handled = true; + } + + protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) + { + base.OnMouseLeftButtonUp(e); + _doSectorSelection = false; + ReleaseMouseCapture(); + } + + protected override void OnMouseRightButtonUp(MouseButtonEventArgs e) + { + base.OnMouseRightButtonUp(e); + _doSectorSelection = false; + } + + protected override void OnMouseMove(MouseEventArgs e) + { + base.OnMouseMove(e); + + if (_editor?.SelectedRoom == null || _editor.Action is EditorActionRelocateCamera) + return; + + if (e.LeftButton == MouseButtonState.Pressed && _doSectorSelection) + _editor.SelectedSectors = new SectorSelection { Start = _editor.SelectedSectors.Start, End = FromVisualCoord(e.GetPosition(this)) }; + } + + private void HandleMouseDown(Point position, bool isRightButton) + { + if (_editor == null || Room == null) + return; + + // Move camera to selected sector. + if (_editor.Action is EditorActionRelocateCamera) + { + _editor.MoveCameraToSector(FromVisualCoord(position)); + return; + } + + var sectorPos = FromVisualCoord(position); + var selectedSectorObject = _editor.SelectedObject as SectorBasedObjectInstance; + bool isAltDown = Keyboard.Modifiers.HasFlag(ModifierKeys.Alt); + + if (!isRightButton && !isAltDown) + { + if (selectedSectorObject != null && + selectedSectorObject.Room == Room && + selectedSectorObject.Area.Contains(sectorPos)) + { + HandleSectorObjectClick(selectedSectorObject); + } + else + { + _editor.SelectedSectors = new SectorSelection { Start = sectorPos, End = sectorPos }; + + if (selectedSectorObject != null) + _editor.SelectedObject = null; + _doSectorSelection = true; + } + } + else + { + SelectNextObjectAtSector(sectorPos, selectedSectorObject, position); + } + } + + private void HandleSectorObjectClick(SectorBasedObjectInstance selectedSectorObject) + { + if (selectedSectorObject is PortalInstance portal) + { + var room = Room; + + if (room.AlternateBaseRoom != null && portal.AdjoiningRoom.Alternated) + { + _editor.SelectRoom(portal.AdjoiningRoom.AlternateRoom); + _editor.SelectedObject = portal.FindOppositePortal(room).FindAlternatePortal(portal.AdjoiningRoom.AlternateRoom); + } + else + { + _editor.SelectRoom(portal.AdjoiningRoom); + _editor.SelectedObject = portal.FindOppositePortal(room); + } + } + else if (selectedSectorObject is TriggerInstance) + { + EditorActions.EditObject(selectedSectorObject, null); + } + } + + private void SelectNextObjectAtSector(VectorInt2 sectorPos, SectorBasedObjectInstance selectedSectorObject, Point mousePosition) + { + var portalsInRoom = Room.Portals.Cast(); + var triggersInRoom = Room.Triggers.Cast(); + var relevantObjects = portalsInRoom.Concat(triggersInRoom) + .Where(obj => obj.Area.Contains(sectorPos)); + + var nextObject = relevantObjects + .FindFirstAfterWithWrapAround(obj => obj == selectedSectorObject, obj => true); + + if (nextObject != null) + { + _editor.SelectedObject = nextObject; + + // Show tooltip near the cursor. + var toolTip = new ToolTip + { + Content = nextObject.ToString(), + IsOpen = true, + StaysOpen = false + }; + ToolTip = toolTip; + } + } + + // Rendering. + + protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo) + { + base.OnRenderSizeChanged(sizeInfo); + InvalidateVisual(); + } + + protected override void OnRender(DrawingContext dc) + { + if (_editor == null || Room == null) + { + DrawDesignPlaceholder(dc); + return; + } + + try + { + var totalArea = GetVisualAreaTotal(); + var roomArea = GetVisualAreaRoom(); + var gridDimensions = GetGridDimensions(); + double gridStep = GetGridStep(); + var roomSize = RoomSize; + + // Draw background. + var bgBrush = CreateFrozenBrush(_editor.Configuration.UI_ColorScheme.Color2DBackground.ToWPFColor()); + dc.DrawRectangle(bgBrush, null, totalArea); + + // Draw sector tiles. + for (int x = 0; x < roomSize.X; x++) + { + for (int z = 0; z < roomSize.Y; z++) + { + var tileRect = new Rect( + roomArea.X + x * gridStep, + roomArea.Y + (roomSize.Y - 1 - z) * gridStep, + gridStep, + gridStep); + PaintSectorTile(dc, tileRect, x, z); + } + } + + // Draw grid lines. + DrawGridLines(dc, totalArea, gridDimensions, gridStep); + + // Draw selection. + DrawSelection(dc); + } + catch (Exception exc) + { + logger.Error(exc, "An exception occured while drawing the 2D grid."); + } + } + + private void DrawGridLines(DrawingContext dc, Rect totalArea, VectorInt2 gridDimensions, double gridStep) + { + for (int x = 0; x <= gridDimensions.X; ++x) + { + var pen = (x == 0 || x == gridDimensions.X) ? BorderPen : GridPen; + double xPos = totalArea.X + x * gridStep; + dc.DrawLine(pen, new Point(xPos, totalArea.Y), new Point(xPos, totalArea.Y + gridStep * gridDimensions.Y)); + } + + for (int y = 0; y <= gridDimensions.Y; ++y) + { + var pen = (y == 0 || y == gridDimensions.Y) ? BorderPen : GridPen; + double yPos = totalArea.Y + y * gridStep; + dc.DrawLine(pen, new Point(totalArea.X, yPos), new Point(totalArea.X + gridStep * gridDimensions.X, yPos)); + } + } + + private void DrawSelection(DrawingContext dc) + { + if (_editor.SelectedSectors.Valid) + { + var selectionPen = CreateFrozenPen(_editor.Configuration.UI_ColorScheme.ColorSelection.ToWPFColor(), 2.0); + dc.DrawRectangle(null, selectionPen, ToVisualCoord(_editor.SelectedSectors.Area)); + } + + var instance = _editor.SelectedObject as SectorBasedObjectInstance; + if (instance != null && instance.Room == Room) + { + var pen = instance is PortalInstance ? SelectedPortalPen : SelectedTriggerPen; + dc.DrawRectangle(null, pen, ToVisualCoord(instance.Area)); + } + } + + private void PaintSectorTile(DrawingContext dc, Rect sectorArea, int x, int z) + { + var coloringInfos = _editor.SectorColoringManager.ColoringInfo.GetColors( + _editor.Configuration.UI_ColorScheme, Room, x, z, + _editor.Configuration.UI_ProbeAttributesThroughPortals); + + if (coloringInfos == null) + return; + + for (int i = 0; i < coloringInfos.Count; i++) + { + var info = coloringInfos[i]; + var brush = CreateFrozenBrush(info.Color.ToWPFColor()); + + switch (info.Shape) + { + case SectorColoringShape.Rectangle: + dc.DrawRectangle(brush, null, sectorArea); + break; + + case SectorColoringShape.Frame: + DrawFrame(dc, sectorArea, info.Color); + break; + + case SectorColoringShape.Hatch: + DrawHatch(dc, sectorArea, info.Color); + break; + + case SectorColoringShape.EdgeZp: + case SectorColoringShape.EdgeZn: + case SectorColoringShape.EdgeXp: + case SectorColoringShape.EdgeXn: + DrawEdge(dc, sectorArea, info.Shape, brush); + break; + + case SectorColoringShape.TriangleXnZn: + case SectorColoringShape.TriangleXnZp: + case SectorColoringShape.TriangleXpZn: + case SectorColoringShape.TriangleXpZp: + DrawTriangle(dc, sectorArea, info.Shape, brush); + break; + } + } + } + + private void DrawFrame(DrawingContext dc, Rect sectorArea, Vector4 color) + { + var pen = CreateFrozenPen(color.ToWPFColor(), OutlineSectorColoringInfoWidth); + double half = OutlineSectorColoringInfoWidth / 2.0; + var frameRect = new Rect( + sectorArea.X + half, + sectorArea.Y + half, + sectorArea.Width - OutlineSectorColoringInfoWidth, + sectorArea.Height - OutlineSectorColoringInfoWidth); + dc.DrawRectangle(null, pen, frameRect); + } + + private void DrawHatch(DrawingContext dc, Rect sectorArea, Vector4 color) + { + // Simulate a hatch pattern using diagonal lines. + var pen = CreateFrozenPen(color.ToWPFColor(), 1.0); + double spacing = 6.0; + + dc.PushClip(new RectangleGeometry(sectorArea)); + + double totalRange = sectorArea.Width + sectorArea.Height; + for (double offset = 0; offset < totalRange; offset += spacing) + { + dc.DrawLine(pen, + new Point(sectorArea.X + offset, sectorArea.Bottom), + new Point(sectorArea.X + offset - sectorArea.Height, sectorArea.Top)); + } + + dc.Pop(); + } + + private static void DrawEdge(DrawingContext dc, Rect sectorArea, SectorColoringShape shape, Brush brush) + { + double w = OutlineSectorColoringInfoWidth; + Rect edgeRect; + + if (shape == SectorColoringShape.EdgeZp) + edgeRect = new Rect(sectorArea.X, sectorArea.Y, sectorArea.Width, w); + else if (shape == SectorColoringShape.EdgeZn) + edgeRect = new Rect(sectorArea.X, sectorArea.Bottom - w, sectorArea.Width, w); + else if (shape == SectorColoringShape.EdgeXp) + edgeRect = new Rect(sectorArea.Right - w, sectorArea.Y, w, sectorArea.Height); + else + edgeRect = new Rect(sectorArea.X, sectorArea.Y, w, sectorArea.Height); + + dc.DrawRectangle(brush, null, edgeRect); + } + + private static void DrawTriangle(DrawingContext dc, Rect sectorArea, SectorColoringShape shape, Brush brush) + { + var geometry = new StreamGeometry(); + using (var ctx = geometry.Open()) + { + Point p0, p1, p2; + + if (shape == SectorColoringShape.TriangleXnZn) + { + p0 = new Point(sectorArea.Left, sectorArea.Top); + p1 = new Point(sectorArea.Left, sectorArea.Bottom); + p2 = new Point(sectorArea.Right, sectorArea.Bottom); + } + else if (shape == SectorColoringShape.TriangleXnZp) + { + p0 = new Point(sectorArea.Left, sectorArea.Bottom); + p1 = new Point(sectorArea.Left, sectorArea.Top); + p2 = new Point(sectorArea.Right, sectorArea.Top); + } + else if (shape == SectorColoringShape.TriangleXpZn) + { + p0 = new Point(sectorArea.Left, sectorArea.Bottom); + p1 = new Point(sectorArea.Right, sectorArea.Top); + p2 = new Point(sectorArea.Right, sectorArea.Bottom); + } + else + { + p0 = new Point(sectorArea.Left, sectorArea.Top); + p1 = new Point(sectorArea.Right, sectorArea.Top); + p2 = new Point(sectorArea.Right, sectorArea.Bottom); + } + + ctx.BeginFigure(p0, true, true); + ctx.LineTo(p1, false, false); + ctx.LineTo(p2, false, false); + } + + geometry.Freeze(); + dc.DrawGeometry(brush, null, geometry); + } + + // Helper methods. + + private void DrawDesignPlaceholder(DrawingContext dc) + { + dc.DrawRectangle(CreateFrozenBrush(Color.FromRgb(50, 50, 50)), BorderPen, + new Rect(0, 0, ActualWidth, ActualHeight)); + + var text = new FormattedText("2D Grid", + System.Globalization.CultureInfo.InvariantCulture, + FlowDirection.LeftToRight, + new Typeface("Segoe UI"), 12.0, Brushes.Gray, + VisualTreeHelper.GetDpi(this).PixelsPerDip); + + dc.DrawText(text, new Point( + (ActualWidth - text.Width) / 2.0, + (ActualHeight - text.Height) / 2.0)); + } + + private static Pen CreateFrozenPen(Color color, double thickness) + { + var brush = new SolidColorBrush(color); + brush.Freeze(); + var pen = new Pen(brush, thickness); + pen.Freeze(); + return pen; + } + + private static SolidColorBrush CreateFrozenBrush(Color color) + { + var brush = new SolidColorBrush(color); + brush.Freeze(); + return brush; + } + } +} diff --git a/TombEditor/WPF/Controls/PanelPaletteGrid.cs b/TombEditor/WPF/Controls/PanelPaletteGrid.cs new file mode 100644 index 0000000000..465c15c0a0 --- /dev/null +++ b/TombEditor/WPF/Controls/PanelPaletteGrid.cs @@ -0,0 +1,375 @@ +using NLog; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Numerics; +using System.Windows; +using System.Windows.Input; +using System.Windows.Media; +using TombLib; +using TombLib.LevelData; +using TombLib.Utils; + +namespace TombEditor.WPF.Controls +{ + public class PanelPaletteGrid : FrameworkElement + { + private static readonly Logger logger = LogManager.GetCurrentClassLogger(); + + private const double CellWidth = 10.0; + private const double CellHeight = 10.0; + + private static readonly Pen GridPen = CreateFrozenPen(Color.FromArgb(140, 0, 0, 0), 1.0); + private static readonly Pen BorderPen = CreateFrozenPen(Colors.Black, 1.0); + private static readonly Pen SelectionPen = CreateFrozenPen(Colors.White, 1.0); + + private readonly Editor _editor; + private List _palette = new List(); + private int _selectedIndex = -1; + private Size _oldPaletteSize; + + public bool Editable { get; set; } = true; + + public Color SelectedColor => GetColorAtIndex(_selectedIndex); + + public ColorC SelectedColorC + { + get + { + if (_selectedIndex < 0 || _selectedIndex >= _palette.Count) + return new ColorC(128, 128, 128); + return _palette[_selectedIndex]; + } + } + + public List Palette => new List(_palette); + + private int ColumnCount => (int)(ActualWidth / CellWidth); + private int RowCount => (int)(ActualHeight / CellHeight); + + public PanelPaletteGrid() + { + ClipToBounds = true; + Focusable = true; + + if (DesignerProperties.GetIsInDesignMode(this)) + return; + + _editor = Editor.Instance; + } + + public void LoadPalette(List palette) + { + if (palette.Count < 1) + return; + + _palette.Clear(); + foreach (var c in palette) + _palette.Add(new ColorC(c.R, c.G, c.B)); + + PickColor(); + InvalidateVisual(); + } + + public void PickColor() + { + if (!_editor.Configuration.Palette_PickColorFromSelectedObject || _editor.SelectedObject == null) + return; + + if (_editor.SelectedObject is not IColorable instance) + return; + + var normalizedColor = instance.Color / 2.0f; + var color = new ColorC( + (byte)(normalizedColor.X * 255), + (byte)(normalizedColor.Y * 255), + (byte)(normalizedColor.Z * 255)); + + for (int i = 0; i < _palette.Count; i++) + { + if (_palette[i] == color) + { + _selectedIndex = i; + _editor.LastUsedPaletteColourChange(SelectedColorC); + InvalidateVisual(); + return; + } + } + } + + public void SetColorAtSelection(ColorC color) + { + if (_selectedIndex < 0) + return; + + if (_selectedIndex >= _palette.Count) + _palette.Add(color); + else + _palette[_selectedIndex] = color; + + InvalidateVisual(); + } + + // Mouse interaction. + + protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) + { + base.OnMouseLeftButtonDown(e); + Focus(); + + if (e.ClickCount == 2 && Editable) + { + PickColourFromDialog(); + return; + } + + CaptureMouse(); + + if (Keyboard.Modifiers.HasFlag(ModifierKeys.Alt)) + { + PickColourFromDialog(false); + return; + } + + if (_editor.SelectedObject is IColorable) + { + _editor.UndoManager.PushObjectPropertyChanged( + (PositionBasedObjectInstance)_editor.SelectedObject); + } + + _editor.ToggleHiddenSelection(true); + ChangeColorByMouse(e.GetPosition(this)); + } + + protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) + { + base.OnMouseLeftButtonUp(e); + _editor.ToggleHiddenSelection(false); + ReleaseMouseCapture(); + } + + protected override void OnMouseMove(MouseEventArgs e) + { + base.OnMouseMove(e); + + if (e.LeftButton == MouseButtonState.Pressed) + ChangeColorByMouse(e.GetPosition(this)); + } + + private void ChangeColorByMouse(Point position) + { + int columns = ColumnCount; + int rows = RowCount; + + if (columns <= 0 || rows <= 0) + return; + + int x = position.X < 0 ? 0 : (int)(position.X / CellWidth); + int y = position.Y < 0 ? 0 : (int)(position.Y / CellHeight); + + x = Math.Min(x, columns - 1); + y = Math.Min(y, rows - 1); + + _selectedIndex = y * columns + x; + + if (_editor.SelectedObject != null && _editor.SelectedObject.CanBeColored()) + { + _editor.ToggleHiddenSelection(true); + + if (_editor.SelectedObject is IColorable instance) + { + instance.Color = SelectedColor.ToFloat3Color() * 2.0f; + + if (_editor.SelectedObject is LightInstance) + _editor.SelectedObject.Room.RebuildLighting(_editor.Configuration.Rendering3D_HighQualityLightPreview); + + _editor.ObjectChange(_editor.SelectedObject, ObjectChangeType.Change); + } + } + + _editor.LastUsedPaletteColourChange(SelectedColorC); + InvalidateVisual(); + } + + private void PickColourFromDialog(bool onlyFromPalette = true) + { + using (var colorDialog = new TombLib.Controls.RealtimeColorDialog( + _editor.Configuration.ColorDialog_Position.X, + _editor.Configuration.ColorDialog_Position.Y, + null, + _editor.Configuration.UI_ColorScheme)) + { + var currentColor = SelectedColor; + colorDialog.Color = System.Drawing.Color.FromArgb(currentColor.A, currentColor.R, currentColor.G, currentColor.B); + + if (!onlyFromPalette) + { + var obj = _editor.SelectedObject; + if (obj is LightInstance light) + colorDialog.Color = (light.Color * 0.5f).ToWinFormsColor(); + else if (obj is StaticInstance stat) + colorDialog.Color = (stat.Color * 0.5f).ToWinFormsColor(); + else if (_editor.Level.IsTombEngine && obj is MoveableInstance moveable) + colorDialog.Color = moveable.Color.ToWinFormsColor(); + } + + if (colorDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) + { + var picked = colorDialog.Color; + SetColorAtSelection(new ColorC(picked.R, picked.G, picked.B)); + _editor.Level.Settings.Palette = Palette; + } + + _editor.Configuration.ColorDialog_Position = colorDialog.Position; + } + } + + // Rendering. + + protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo) + { + base.OnRenderSizeChanged(sizeInfo); + + // Recalculate selected color coordinate on resize. + if (_selectedIndex >= 0) + { + int oldColumns = _oldPaletteSize.Width > 0 ? (int)(_oldPaletteSize.Width / CellWidth) : ColumnCount; + int newColumns = ColumnCount; + + if (oldColumns > 0 && newColumns > 0 && oldColumns != newColumns) + { + int x = _selectedIndex % oldColumns; + int y = _selectedIndex / oldColumns; + int flatIndex = y * oldColumns + x; + _selectedIndex = flatIndex; + } + } + + _oldPaletteSize = sizeInfo.NewSize; + InvalidateVisual(); + } + + protected override void OnRender(DrawingContext dc) + { + if (_editor == null) + { + DrawDesignPlaceholder(dc); + return; + } + + try + { + int columns = ColumnCount; + int rows = RowCount; + + if (columns <= 0 || rows <= 0) + return; + + DrawCells(dc, columns, rows); + DrawGridLines(dc, columns, rows); + DrawOuterBorder(dc, columns, rows); + DrawSelectionRect(dc, columns, rows); + } + catch (Exception exc) + { + logger.Error(exc, "An exception occured while drawing the palette grid."); + } + } + + private void DrawCells(DrawingContext dc, int columns, int rows) + { + for (int y = 0; y < rows; y++) + { + for (int x = 0; x < columns; x++) + { + int index = y * columns + x; + var color = GetColorAtIndex(index); + var brush = CreateFrozenBrush(color); + dc.DrawRectangle(brush, null, new Rect(x * CellWidth, y * CellHeight, CellWidth, CellHeight)); + } + } + } + + private static void DrawGridLines(DrawingContext dc, int columns, int rows) + { + double totalWidth = columns * CellWidth; + double totalHeight = rows * CellHeight; + + for (int x = 1; x < columns; x++) + { + double xPos = x * CellWidth; + dc.DrawLine(GridPen, new Point(xPos, 0), new Point(xPos, totalHeight)); + } + + for (int y = 1; y < rows; y++) + { + double yPos = y * CellHeight; + dc.DrawLine(GridPen, new Point(0, yPos), new Point(totalWidth, yPos)); + } + } + + private static void DrawOuterBorder(DrawingContext dc, int columns, int rows) + { + double totalWidth = columns * CellWidth; + double totalHeight = rows * CellHeight; + dc.DrawRectangle(null, BorderPen, new Rect(0, 0, totalWidth, totalHeight)); + } + + private void DrawSelectionRect(DrawingContext dc, int columns, int rows) + { + if (_selectedIndex < 0 || columns <= 0) + return; + + int x = _selectedIndex % columns; + int y = _selectedIndex / columns; + + if (y >= rows) + return; + + dc.DrawRectangle(null, SelectionPen, new Rect(x * CellWidth, y * CellHeight, CellWidth, CellHeight)); + } + + private Color GetColorAtIndex(int index) + { + if (index < 0 || index >= _palette.Count) + return Colors.Transparent; + + var c = _palette[index]; + return Color.FromRgb(c.R, c.G, c.B); + } + + // Helper methods. + + private void DrawDesignPlaceholder(DrawingContext dc) + { + dc.DrawRectangle(CreateFrozenBrush(Color.FromRgb(50, 50, 50)), BorderPen, + new Rect(0, 0, ActualWidth, ActualHeight)); + + var text = new FormattedText("Palette", + System.Globalization.CultureInfo.InvariantCulture, + FlowDirection.LeftToRight, + new Typeface("Segoe UI"), 12.0, Brushes.Gray, + VisualTreeHelper.GetDpi(this).PixelsPerDip); + + dc.DrawText(text, new Point( + (ActualWidth - text.Width) / 2.0, + (ActualHeight - text.Height) / 2.0)); + } + + private static Pen CreateFrozenPen(Color color, double thickness) + { + var brush = new SolidColorBrush(color); + brush.Freeze(); + var pen = new Pen(brush, thickness); + pen.Freeze(); + return pen; + } + + private static SolidColorBrush CreateFrozenBrush(Color color) + { + var brush = new SolidColorBrush(color); + brush.Freeze(); + return brush; + } + } +} diff --git a/TombEditor/WPF/Converters/HtmlToUIColorConverter.cs b/TombEditor/WPF/Converters/HtmlToUIColorConverter.cs new file mode 100644 index 0000000000..734fff3ec4 --- /dev/null +++ b/TombEditor/WPF/Converters/HtmlToUIColorConverter.cs @@ -0,0 +1,23 @@ +using System; +using System.Drawing; +using System.Globalization; +using System.Windows.Data; + +namespace TombEditor.WPF.Converters +{ + public class HtmlToUIColorConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + var colString = (string)value; + var col = ColorTranslator.FromHtml(colString); + return System.Windows.Media.Color.FromArgb(col.A, col.R, col.G, col.B); + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + var col = (System.Windows.Media.Color)value; + return ColorTranslator.ToHtml(Color.FromArgb(col.A, col.R, col.G, col.B)); + } + } +} diff --git a/TombEditor/WPF/Converters/VectorToUIColorConverter.cs b/TombEditor/WPF/Converters/VectorToUIColorConverter.cs new file mode 100644 index 0000000000..756a9a76cf --- /dev/null +++ b/TombEditor/WPF/Converters/VectorToUIColorConverter.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Numerics; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Data; +using System.Windows.Media; +namespace TombEditor.WPF.Converters +{ + public class VectorToUIColorConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + var vec = (Vector4)value; + byte r = (byte)(Math.Clamp(vec.X, 0.0f, 1.0f) * 255.0f); + byte g = (byte)(Math.Clamp(vec.Y, 0.0f, 1.0f) * 255.0f); + byte b = (byte)(Math.Clamp(vec.Z, 0.0f, 1.0f) * 255.0f); + byte a = (byte)(Math.Clamp(vec.W, 0.0f, 1.0f) * 255.0f); + return Color.FromArgb(a, r, g, b); + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + var col = (Color)value; + return new Vector4(col.R / 255.0f, col.G / 255.0f, col.B / 255.0f, col.A / 255.0f); + } + } + + public class VectorToBrushConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + var vec = (Vector4)value; + byte r = (byte)(Math.Clamp(vec.X, 0.0f, 1.0f) * 255.0f); + byte g = (byte)(Math.Clamp(vec.Y, 0.0f, 1.0f) * 255.0f); + byte b = (byte)(Math.Clamp(vec.Z, 0.0f, 1.0f) * 255.0f); + byte a = (byte)(Math.Clamp(vec.W, 0.0f, 1.0f) * 255.0f); + + return new SolidColorBrush(Color.FromArgb(a, r, g, b)); + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + Color col = ((SolidColorBrush)value).Color; + return new Vector4(col.R / 255.0f, col.G / 255.0f, col.B / 255.0f, col.A / 255.0f); + } + } +} diff --git a/TombEditor/WPF/DynamicKeyBinding.cs b/TombEditor/WPF/DynamicKeyBinding.cs new file mode 100644 index 0000000000..b30a835cd3 --- /dev/null +++ b/TombEditor/WPF/DynamicKeyBinding.cs @@ -0,0 +1,79 @@ +#nullable enable + +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Input; +using WinForms = System.Windows.Forms; + +namespace TombEditor.WPF; + +public sealed class DynamicKeyBinding : InputBinding +{ + public static readonly DependencyProperty InputGestureTextProperty = DependencyProperty.Register(nameof(InputGestureText), typeof(string), typeof(DynamicKeyBinding)); + + public string? InputGestureText + { + get => (string)GetValue(InputGestureTextProperty); + set => SetValue(InputGestureTextProperty, value); + } + + protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) + { + if (e.Property == InputGestureTextProperty && e.NewValue is string text) + { + if (string.IsNullOrEmpty(text)) + { + Gesture = new KeyGestureEx(); + return; + } + + var hotkey = Hotkey.FromString(text); + + ModifierKeys modifiers = ModifierKeys.None; + Key key = Key.NoName; + + if ((hotkey.Keys & WinForms.Keys.Control) != WinForms.Keys.None) + modifiers |= ModifierKeys.Control; + + if ((hotkey.Keys & WinForms.Keys.Shift) != WinForms.Keys.None) + modifiers |= ModifierKeys.Shift; + + if ((hotkey.Keys & WinForms.Keys.Alt) != WinForms.Keys.None) + modifiers |= ModifierKeys.Alt; + + if (hotkey.MainKey != WinForms.Keys.None) + key = KeyInterop.KeyFromVirtualKey((int)hotkey.MainKey); + + Gesture = new KeyGestureEx(key, modifiers); + } + + base.OnPropertyChanged(e); + } +} + +public class KeyGestureEx : InputGesture +{ + public Key Key { get; set; } = Key.NoName; + public ModifierKeys Modifiers { get; set; } = ModifierKeys.None; + + public KeyGestureEx() + { } + + public KeyGestureEx(Key key, ModifierKeys modifiers) + { + Key = key; + Modifiers = modifiers; + } + + public override bool Matches(object targetElement, InputEventArgs inputEventArgs) + { + if (inputEventArgs is not KeyEventArgs keyEventArgs) + return false; + + if (inputEventArgs.OriginalSource is TextBoxBase or ListBoxItem) + return false; + + return keyEventArgs.Key == Key && keyEventArgs.KeyboardDevice.Modifiers == Modifiers; + } +} diff --git a/TombEditor/WPF/KeyBindingsExtension.cs b/TombEditor/WPF/KeyBindingsExtension.cs new file mode 100644 index 0000000000..b20cb9ec1f --- /dev/null +++ b/TombEditor/WPF/KeyBindingsExtension.cs @@ -0,0 +1,44 @@ +#nullable enable + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Windows.Data; +using System.Windows.Markup; + +namespace TombEditor.WPF; + +public class KeyBindingsExtension : MarkupExtension, IValueConverter +{ + public string Key { get; set; } + + public KeyBindingsExtension(string key) + => Key = key; + + public override object ProvideValue(IServiceProvider serviceProvider) + { + string keyToUse = Key; + HotkeySets uiKeys = Editor.Instance.Configuration.UI_Hotkeys; + + if (uiKeys.Any(keyPair => keyPair.Key == keyToUse && keyPair.Value.Count > 0)) + { + var binding = new Binding($"[{keyToUse}]") + { + Mode = BindingMode.OneWay, + Source = KeyBindingsWrapper.Instance, + Converter = this + }; + + return binding.ProvideValue(serviceProvider); + } + + return string.Empty; + } + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + => ((SortedSet)value).First().ToString(); + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + => throw new NotImplementedException(); +} diff --git a/TombEditor/WPF/KeyBindingsWrapper.cs b/TombEditor/WPF/KeyBindingsWrapper.cs new file mode 100644 index 0000000000..e5de212768 --- /dev/null +++ b/TombEditor/WPF/KeyBindingsWrapper.cs @@ -0,0 +1,24 @@ +#nullable enable + +using System.Collections.Generic; +using System.ComponentModel; + +namespace TombEditor.WPF; + +public class KeyBindingsWrapper : INotifyPropertyChanged +{ + public static KeyBindingsWrapper Instance { get; set; } = new KeyBindingsWrapper(); + + private const string IndexerName = "Item"; + private const string IndexerArrayName = "Item[]"; + + public SortedSet this[string key] => Editor.Instance.Configuration.UI_Hotkeys[key]; + + public event PropertyChangedEventHandler? PropertyChanged; + + public void Invalidate() + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(IndexerName)); + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(IndexerArrayName)); + } +} diff --git a/TombEditor/WPF/ToolWindows/ImportedGeometryBrowser.xaml b/TombEditor/WPF/ToolWindows/ImportedGeometryBrowser.xaml new file mode 100644 index 0000000000..b59511ebae --- /dev/null +++ b/TombEditor/WPF/ToolWindows/ImportedGeometryBrowser.xaml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TombEditor/WPF/ToolWindows/ImportedGeometryBrowser.xaml.cs b/TombEditor/WPF/ToolWindows/ImportedGeometryBrowser.xaml.cs new file mode 100644 index 0000000000..a1875b5e5f --- /dev/null +++ b/TombEditor/WPF/ToolWindows/ImportedGeometryBrowser.xaml.cs @@ -0,0 +1,25 @@ +using System.Linq; +using System.Windows.Forms; +using System.Windows.Forms.Integration; +using TombEditor.Controls; + +namespace TombEditor.WPF.ToolWindows; +/// +/// Interaction logic for ImportedGeometryBrowser.xaml +/// +public partial class ImportedGeometryBrowser : System.Windows.Controls.UserControl +{ + public TombEditor.ToolWindows.ImportedGeometryBrowser WinFormsLayer { get; } + + public ImportedGeometryBrowser() + { + InitializeComponent(); + //WinFormsLayer = new TombEditor.ToolWindows.ImportedGeometryBrowser(); + + //var panel = new Panel(); + //panel.Controls.AddRange(WinFormsLayer.Controls.Cast().ToArray()); + //panel.Dock = DockStyle.Fill; + + //ItemPreviewHost.Child = new PanelRenderingImportedGeometry(); + } +} diff --git a/TombEditor/WPF/ToolWindows/ItemBrowser.xaml b/TombEditor/WPF/ToolWindows/ItemBrowser.xaml new file mode 100644 index 0000000000..371b3c1845 --- /dev/null +++ b/TombEditor/WPF/ToolWindows/ItemBrowser.xaml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TombEditor/WPF/ToolWindows/ItemBrowser.xaml.cs b/TombEditor/WPF/ToolWindows/ItemBrowser.xaml.cs new file mode 100644 index 0000000000..41deeff35d --- /dev/null +++ b/TombEditor/WPF/ToolWindows/ItemBrowser.xaml.cs @@ -0,0 +1,25 @@ +using System.Linq; +using System.Windows.Forms; +using System.Windows.Forms.Integration; +using TombEditor.Controls; + +namespace TombEditor.WPF.ToolWindows; +/// +/// Interaction logic for ItemBrowser.xaml +/// +public partial class ItemBrowser : System.Windows.Controls.UserControl +{ + public TombEditor.ToolWindows.ItemBrowser WinFormsLayer { get; } + + public ItemBrowser() + { + InitializeComponent(); + //WinFormsLayer = new TombEditor.ToolWindows.ItemBrowser(); + + //var panel = new Panel(); + //panel.Controls.AddRange(WinFormsLayer.Controls.Cast().ToArray()); + //panel.Dock = DockStyle.Fill; + + //ItemPreviewHost.Child = new PanelRenderingItem(); + } +} diff --git a/TombEditor/WPF/ToolWindows/Lighting.xaml b/TombEditor/WPF/ToolWindows/Lighting.xaml new file mode 100644 index 0000000000..c6273480a6 --- /dev/null +++ b/TombEditor/WPF/ToolWindows/Lighting.xaml @@ -0,0 +1,285 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TombEditor/WPF/ToolWindows/Lighting.xaml.cs b/TombEditor/WPF/ToolWindows/Lighting.xaml.cs new file mode 100644 index 0000000000..881165fde3 --- /dev/null +++ b/TombEditor/WPF/ToolWindows/Lighting.xaml.cs @@ -0,0 +1,20 @@ +using TombEditor.WPF.ViewModels; + +namespace TombEditor.WPF.ToolWindows; + +public partial class Lighting : System.Windows.Controls.UserControl +{ + private readonly LightingViewModel _viewModel; + + public Lighting() + { + InitializeComponent(); + _viewModel = new LightingViewModel(Editor.Instance); + DataContext = _viewModel; + } + + public void Cleanup() + { + _viewModel.Cleanup(); + } +} diff --git a/TombEditor/WPF/ToolWindows/ObjectList.xaml b/TombEditor/WPF/ToolWindows/ObjectList.xaml new file mode 100644 index 0000000000..c538548058 --- /dev/null +++ b/TombEditor/WPF/ToolWindows/ObjectList.xaml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + diff --git a/TombEditor/WPF/ToolWindows/ObjectList.xaml.cs b/TombEditor/WPF/ToolWindows/ObjectList.xaml.cs new file mode 100644 index 0000000000..49cfb6d020 --- /dev/null +++ b/TombEditor/WPF/ToolWindows/ObjectList.xaml.cs @@ -0,0 +1,25 @@ +using DarkUI.Controls; +using System.Linq; +using System.Windows.Forms; +using System.Windows.Forms.Integration; + +namespace TombEditor.WPF.ToolWindows; +/// +/// Interaction logic for ObjectList.xaml +/// +public partial class ObjectList : System.Windows.Controls.UserControl +{ + public TombEditor.ToolWindows.ObjectList WinFormsLayer { get; } + + public ObjectList() + { + InitializeComponent(); + //WinFormsLayer = new TombEditor.ToolWindows.ObjectList(); + + //var panel = new Panel(); + //panel.Controls.AddRange(WinFormsLayer.Controls.Cast().ToArray()); + //panel.Dock = DockStyle.Fill; + + TreeViewHost.Child = new DarkListView(); + } +} diff --git a/TombEditor/WPF/ToolWindows/Palette.xaml b/TombEditor/WPF/ToolWindows/Palette.xaml new file mode 100644 index 0000000000..3506ed2a13 --- /dev/null +++ b/TombEditor/WPF/ToolWindows/Palette.xaml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TombEditor/WPF/ToolWindows/Palette.xaml.cs b/TombEditor/WPF/ToolWindows/Palette.xaml.cs new file mode 100644 index 0000000000..4b4cca9a6e --- /dev/null +++ b/TombEditor/WPF/ToolWindows/Palette.xaml.cs @@ -0,0 +1,89 @@ +using System.Collections.Generic; +using System.Windows.Controls; +using TombLib.LevelData; +using TombLib.Utils; +using TombEditor.WPF.ViewModels; + +namespace TombEditor.WPF.ToolWindows; + +public partial class Palette : UserControl +{ + private readonly Editor _editor; + private readonly PaletteViewModel _viewModel; + private List _lastTexturePalette; + + public Palette() + { + InitializeComponent(); + + _editor = Editor.Instance; + _viewModel = new PaletteViewModel(_editor); + DataContext = _viewModel; + + _editor.EditorEventRaised += EditorEventRaised; + + PaletteGrid.LoadPalette(LevelSettings.LoadPalette()); + UpdatePalette(false); + } + + public void Cleanup() + { + _editor.EditorEventRaised -= EditorEventRaised; + _viewModel.Cleanup(); + } + + private void EditorEventRaised(IEditorEvent obj) + { + if (obj is Editor.LevelChangedEvent levelChanged) + { + _lastTexturePalette = null; + PaletteGrid.LoadPalette(levelChanged.Current.Settings.Palette); + } + + if (obj is Editor.SelectedObjectChangedEvent) + PaletteGrid.PickColor(); + + if (obj is Editor.ObjectChangedEvent objectChanged) + { + if (objectChanged.ChangeType == ObjectChangeType.Change && + objectChanged.Object == _editor.SelectedObject && + objectChanged.Object is IColorable) + PaletteGrid.PickColor(); + } + + if (obj is Editor.ResetPaletteEvent) + { + if (!_editor.Configuration.Palette_TextureSamplingMode) + { + PaletteGrid.LoadPalette(LevelSettings.LoadPalette()); + _editor.Level.Settings.Palette = PaletteGrid.Palette; + } + } + + if (obj is Editor.SelectedLevelTextureChangedSetEvent textureChanged) + { + _lastTexturePalette = new List(textureChanged.Texture.Image.Palette); + UpdatePalette(); + } + + if (obj is Editor.ConfigurationChangedEvent) + UpdatePalette(); + } + + private void UpdatePalette(bool reloadPalette = true) + { + PaletteGrid.Editable = !_editor.Configuration.Palette_TextureSamplingMode; + + if (reloadPalette) + { + bool useTexture = _editor.Configuration.Palette_TextureSamplingMode; + + if (useTexture && _lastTexturePalette != null && _lastTexturePalette.Count > 0) + PaletteGrid.LoadPalette(_lastTexturePalette); + else + PaletteGrid.LoadPalette(_editor.Level.Settings.Palette); + + _editor.LastUsedPaletteColourChange(PaletteGrid.SelectedColorC); + } + } +} diff --git a/TombEditor/WPF/ToolWindows/RoomOptions.xaml b/TombEditor/WPF/ToolWindows/RoomOptions.xaml new file mode 100644 index 0000000000..072ca8dbc4 --- /dev/null +++ b/TombEditor/WPF/ToolWindows/RoomOptions.xaml @@ -0,0 +1,299 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TombEditor/WPF/ToolWindows/RoomOptions.xaml.cs b/TombEditor/WPF/ToolWindows/RoomOptions.xaml.cs new file mode 100644 index 0000000000..e1de7dc8f4 --- /dev/null +++ b/TombEditor/WPF/ToolWindows/RoomOptions.xaml.cs @@ -0,0 +1,21 @@ +using System.Windows.Controls; +using TombEditor.WPF.ViewModels; + +namespace TombEditor.WPF.ToolWindows; + +public partial class RoomOptions : UserControl +{ + private readonly RoomOptionsViewModel _viewModel; + + public RoomOptions() + { + InitializeComponent(); + _viewModel = new RoomOptionsViewModel(Editor.Instance); + DataContext = _viewModel; + } + + public void Cleanup() + { + _viewModel.Cleanup(); + } +} diff --git a/TombEditor/WPF/ToolWindows/SectorOptions.xaml b/TombEditor/WPF/ToolWindows/SectorOptions.xaml new file mode 100644 index 0000000000..f53c95b429 --- /dev/null +++ b/TombEditor/WPF/ToolWindows/SectorOptions.xaml @@ -0,0 +1,341 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TombEditor/WPF/ToolWindows/SectorOptions.xaml.cs b/TombEditor/WPF/ToolWindows/SectorOptions.xaml.cs new file mode 100644 index 0000000000..b03fd1664e --- /dev/null +++ b/TombEditor/WPF/ToolWindows/SectorOptions.xaml.cs @@ -0,0 +1,34 @@ +using System.Windows.Controls; +using TombEditor.WPF.ViewModels; + +namespace TombEditor.WPF.ToolWindows; + +public partial class SectorOptions : UserControl +{ + private readonly Editor _editor; + private readonly SectorOptionsViewModel _viewModel; + + public SectorOptions() + { + InitializeComponent(); + + _editor = Editor.Instance; + _viewModel = new SectorOptionsViewModel(_editor); + DataContext = _viewModel; + + _editor.EditorEventRaised += EditorEventRaised; + Panel2DGridControl.Room = _editor.SelectedRoom; + } + + public void Cleanup() + { + _editor.EditorEventRaised -= EditorEventRaised; + _viewModel.Cleanup(); + } + + private void EditorEventRaised(IEditorEvent obj) + { + if (obj is Editor.SelectedRoomChangedEvent selectedRoomChangedEvent) + Panel2DGridControl.Room = selectedRoomChangedEvent.Current; + } +} diff --git a/TombEditor/WPF/ToolWindows/TexturePanel.xaml b/TombEditor/WPF/ToolWindows/TexturePanel.xaml new file mode 100644 index 0000000000..8482c992f3 --- /dev/null +++ b/TombEditor/WPF/ToolWindows/TexturePanel.xaml @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TombEditor/WPF/ToolWindows/TriggerList.xaml.cs b/TombEditor/WPF/ToolWindows/TriggerList.xaml.cs new file mode 100644 index 0000000000..e06f0e6fb1 --- /dev/null +++ b/TombEditor/WPF/ToolWindows/TriggerList.xaml.cs @@ -0,0 +1,25 @@ +using DarkUI.Controls; +using System.Linq; +using System.Windows.Forms; +using System.Windows.Forms.Integration; + +namespace TombEditor.WPF.ToolWindows; +/// +/// Interaction logic for TriggerList.xaml +/// +public partial class TriggerList : System.Windows.Controls.UserControl +{ + public TombEditor.ToolWindows.TriggerList WinFormsLayer { get; } + + public TriggerList() + { + InitializeComponent(); + //WinFormsLayer = new TombEditor.ToolWindows.TriggerList(); + + //var panel = new Panel(); + //panel.Controls.AddRange(WinFormsLayer.Controls.Cast().ToArray()); + //panel.Dock = DockStyle.Fill; + + TreeViewHost.Child = new DarkListView(); + } +} diff --git a/TombEditor/WPF/ViewModels/LightingViewModel.cs b/TombEditor/WPF/ViewModels/LightingViewModel.cs new file mode 100644 index 0000000000..3398b85723 --- /dev/null +++ b/TombEditor/WPF/ViewModels/LightingViewModel.cs @@ -0,0 +1,280 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using System; +using System.Numerics; +using System.Windows.Input; +using System.Windows.Media; +using TombLib.LevelData; + +namespace TombEditor.WPF.ViewModels; + +public partial class LightingViewModel : ObservableObject +{ + private readonly Editor _editor; + + // Light type items matching LightType enum order: Point, Shadow, Spot, Effect, Sun, FogBulb. + public int SelectedLightType + { + get => (int)(_editor.SelectedObject is LightInstance light ? light.Type : (LightType)_lastSelectedLightType); + set + { + _lastSelectedLightType = value; + EditorActions.UpdateLightType((LightType)value); + } + } + + public int SelectedLightQuality + { + get => (int)(_editor.SelectedObject is LightInstance light ? light.Quality : 0); + set => EditorActions.UpdateLightQuality((LightQuality)value); + } + + public Color LightColor + { + get + { + if (_editor.SelectedObject is LightInstance light) + return new Vector4(light.Color * 0.5f, 1.0f).ToWPFColor(); + + return Colors.Transparent; + } + } + + public decimal Intensity + { + get => (decimal)(_editor.SelectedObject is LightInstance light ? light.Intensity : 0); + set => UpdateLightFloat( + (l, v) => CompareRounded(l.Intensity, v, 2), + (l, v) => l.Intensity = v, + (float)value); + } + + public decimal InnerRange + { + get => (decimal)(_editor.SelectedObject is LightInstance light && HasInRange(light) ? light.InnerRange : 0); + set => UpdateLightFloat( + (l, v) => CompareRounded(l.InnerRange, v, 2), + (l, v) => l.InnerRange = v, + (float)value); + } + + public decimal OuterRange + { + get => (decimal)(_editor.SelectedObject is LightInstance light && HasOutRange(light) ? light.OuterRange : 0); + set => UpdateLightFloat( + (l, v) => CompareRounded(l.OuterRange, v, 2), + (l, v) => l.OuterRange = v, + (float)value); + } + + public decimal InnerAngle + { + get => (decimal)(_editor.SelectedObject is LightInstance light && HasInOutAngle(light) ? light.InnerAngle : 0); + set => UpdateLightFloat( + (l, v) => CompareRounded(l.InnerAngle, v, 2), + (l, v) => l.InnerAngle = v, + (float)value); + } + + public decimal OuterAngle + { + get => (decimal)(_editor.SelectedObject is LightInstance light && HasInOutAngle(light) ? light.OuterAngle : 0); + set => UpdateLightFloat( + (l, v) => CompareRounded(l.OuterAngle, v, 2), + (l, v) => l.OuterAngle = v, + (float)value); + } + + public decimal DirectionY + { + get => (decimal)(_editor.SelectedObject is LightInstance light && HasDirection(light) ? light.RotationY : 0); + set => UpdateLightFloat( + (l, v) => CompareRounded(l.RotationY, v, 2), + (l, v) => l.RotationY = v, + (float)value); + } + + public decimal DirectionX + { + get => (decimal)(_editor.SelectedObject is LightInstance light && HasDirection(light) ? light.RotationX : 0); + set => UpdateLightFloat( + (l, v) => CompareRounded(l.RotationX, v, 2), + (l, v) => l.RotationX = v, + (float)value); + } + + public bool LightEnabled + { + get => _editor.SelectedObject is LightInstance light && light.Enabled; + set => UpdateLightBool( + (l, v) => l.Enabled == v, + (l, v) => l.Enabled = v, + value); + } + + public bool ObstructedByGeometry + { + get => _editor.SelectedObject is LightInstance light && light.IsObstructedByRoomGeometry; + set => UpdateLightBool( + (l, v) => l.IsObstructedByRoomGeometry == v, + (l, v) => l.IsObstructedByRoomGeometry = v, + value); + } + + public bool CastsShadow + { + get => _editor.SelectedObject is LightInstance light && light.CastDynamicShadows; + set => UpdateLightBool( + (l, v) => l.CastDynamicShadows == v, + (l, v) => l.CastDynamicShadows = v, + value); + } + + public bool StaticallyUsed + { + get => _editor.SelectedObject is LightInstance light && light.IsStaticallyUsed; + set => UpdateLightBool( + (l, v) => l.IsStaticallyUsed == v, + (l, v) => l.IsStaticallyUsed = v, + value); + } + + public bool DynamicallyUsed + { + get => _editor.SelectedObject is LightInstance light && light.IsDynamicallyUsed; + set => UpdateLightBool( + (l, v) => l.IsDynamicallyUsed == v, + (l, v) => l.IsDynamicallyUsed = v, + value); + } + + public bool UsedForImportedGeometry + { + get => _editor.SelectedObject is LightInstance light && light.IsUsedForImportedGeometry; + set => UpdateLightBool( + (l, v) => l.IsUsedForImportedGeometry == v, + (l, v) => l.IsUsedForImportedGeometry = v, + value); + } + + // Enabled state for controls. + [ObservableProperty] private bool _hasLight; + [ObservableProperty] private bool _canEditInRange; + [ObservableProperty] private bool _canEditOutRange; + [ObservableProperty] private bool _canEditInOutAngle; + [ObservableProperty] private bool _canEditDirection; + [ObservableProperty] private bool _canCastShadows; + [ObservableProperty] private bool _canCastDynamicShadows; + [ObservableProperty] private bool _canIlluminateGeometry; + [ObservableProperty] private bool _canEditQuality; + + public ICommand AddLightCommand { get; } + + private int _lastSelectedLightType; + + public LightingViewModel(Editor editor) + { + _editor = editor; + _editor.EditorEventRaised += EditorEventRaised; + + AddLightCommand = new RelayCommand(PlaceSelectedLightType); + + RefreshLightState(); + } + + public void Cleanup() + { + _editor.EditorEventRaised -= EditorEventRaised; + } + + [RelayCommand] + private void EditLightColor() + { + EditorActions.EditLightColor(WPFUtils.GetWin32WindowFromCaller(this)); + } + + private void EditorEventRaised(IEditorEvent obj) + { + if (obj is Editor.InitEvent or + Editor.GameVersionChangedEvent or + Editor.LevelChangedEvent or + Editor.ObjectChangedEvent or + Editor.SelectedObjectChangedEvent) + RefreshLightState(); + } + + private void RefreshLightState() + { + var isTEN = _editor.Level.Settings.GameVersion == TRVersion.Game.TombEngine; + var light = _editor.SelectedObject as LightInstance; + + HasLight = light != null; + CanEditInRange = light != null && HasInRange(light); + CanEditOutRange = light != null && HasOutRange(light); + CanEditInOutAngle = light != null && HasInOutAngle(light); + CanEditDirection = light != null && HasDirection(light); + CanCastShadows = light != null && CanObstruct(light); + CanCastDynamicShadows = light != null && CanDynamicShadow(light, isTEN); + CanIlluminateGeometry = light != null && CanIlluminate(light); + CanEditQuality = light != null; + + OnPropertyChanged(nameof(SelectedLightType)); + OnPropertyChanged(nameof(SelectedLightQuality)); + OnPropertyChanged(nameof(LightColor)); + OnPropertyChanged(nameof(Intensity)); + OnPropertyChanged(nameof(InnerRange)); + OnPropertyChanged(nameof(OuterRange)); + OnPropertyChanged(nameof(InnerAngle)); + OnPropertyChanged(nameof(OuterAngle)); + OnPropertyChanged(nameof(DirectionY)); + OnPropertyChanged(nameof(DirectionX)); + OnPropertyChanged(nameof(LightEnabled)); + OnPropertyChanged(nameof(ObstructedByGeometry)); + OnPropertyChanged(nameof(CastsShadow)); + OnPropertyChanged(nameof(StaticallyUsed)); + OnPropertyChanged(nameof(DynamicallyUsed)); + OnPropertyChanged(nameof(UsedForImportedGeometry)); + } + + private void PlaceSelectedLightType() + { + EditorActions.PlaceLight((LightType)_lastSelectedLightType); + } + + private void UpdateLightFloat(Func compare, Action setter, float value) + { + EditorActions.UpdateLight(compare, setter, light => (float?)value); + } + + private void UpdateLightBool(Func compare, Action setter, bool value) + { + EditorActions.UpdateLight(compare, setter, light => (bool?)value); + } + + private static bool CompareRounded(float first, float second, int decimalPlaces) + { + float multiplier = (float)Math.Pow(10, decimalPlaces); + return Math.Round(first * multiplier) == Math.Round(second * multiplier); + } + + private static bool HasInRange(LightInstance light) + => light.Type is LightType.Point or LightType.Shadow or LightType.Effect or LightType.Spot; + + private static bool HasOutRange(LightInstance light) + => light.Type is LightType.Point or LightType.Shadow or LightType.Effect or LightType.FogBulb or LightType.Spot; + + private static bool HasInOutAngle(LightInstance light) + => light.Type is LightType.Spot; + + private static bool HasDirection(LightInstance light) + => light.Type is LightType.Spot or LightType.Sun; + + private static bool CanObstruct(LightInstance light) + => light.Type is LightType.Point or LightType.Shadow or LightType.Spot or LightType.Sun; + + private static bool CanDynamicShadow(LightInstance light, bool isTEN) + => isTEN && light.Type is LightType.Point or LightType.Spot; + + private static bool CanIlluminate(LightInstance light) + => light.Type is LightType.Point or LightType.Shadow or LightType.Spot or LightType.Sun; +} diff --git a/TombEditor/WPF/ViewModels/MainViewViewModel.cs b/TombEditor/WPF/ViewModels/MainViewViewModel.cs new file mode 100644 index 0000000000..06054425c6 --- /dev/null +++ b/TombEditor/WPF/ViewModels/MainViewViewModel.cs @@ -0,0 +1,16 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using System.Windows.Input; + +namespace TombEditor.WPF.ViewModels; + +public partial class MainViewViewModel : ObservableObject +{ + private readonly Editor _editor; + + public ICommand ChangeModeCommand { get; } + + public MainViewViewModel(Editor editor) + { + _editor = editor; + } +} diff --git a/TombEditor/WPF/ViewModels/MainWindowViewModel.cs b/TombEditor/WPF/ViewModels/MainWindowViewModel.cs new file mode 100644 index 0000000000..64ed8eeabe --- /dev/null +++ b/TombEditor/WPF/ViewModels/MainWindowViewModel.cs @@ -0,0 +1,794 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using System; +using System.Windows.Forms; +using System.Windows.Input; +using TombLib.Forms; + +namespace TombEditor.WPF.ViewModels; + +public partial class MainWindowViewModel : ObservableObject +{ + [ObservableProperty] private bool _isSectorOptionsPanelVisible; + [ObservableProperty] private bool _isRoomOptionsPanelVisible; + [ObservableProperty] private bool _isItemBrowserVisible; + [ObservableProperty] private bool _isImportedGeometryBrowserVisible; + [ObservableProperty] private bool _isTriggerListVisible; + [ObservableProperty] private bool _isLightingPanelVisible; + [ObservableProperty] private bool _isPalettePanelVisible; + [ObservableProperty] private bool _isTexturePanelVisible; + [ObservableProperty] private bool _isObjectListVisible; + [ObservableProperty] private bool _isStatisticsPanelVisible; + [ObservableProperty] private bool _isToolPaletteVisible; + [ObservableProperty] private bool _isToolPaletteFloating; + + // File Menu + + public ICommand NewLevelCommand { get; } + public ICommand OpenLevelCommand { get; } + public ICommand SaveLevelCommand { get; } + public ICommand SaveLevelAsCommand { get; } + public ICommand ImportPrjCommand { get; } + public ICommand ConvertLevelToTombEngineCommand { get; } + public ICommand BuildAndPlayCommand { get; } + public ICommand BuildLevelCommand { get; } + public ICommand QuitEditorCommand { get; } + + // Edit Menu + + public ICommand UndoCommand { get; } + public ICommand RedoCommand { get; } + public ICommand CutCommand { get; } + public ICommand CopyCommand { get; } + public ICommand PasteCommand { get; } + public ICommand StampObjectCommand { get; } + public ICommand DeleteCommand { get; } + public ICommand SelectAllCommand { get; } + public ICommand BookmarkObjectCommand { get; } + public ICommand SelectBookmarkedObject { get; } + public ICommand EditObjectCommand { get; } + public ICommand EditVolumeEventSetsCommand { get; } + public ICommand EditGlobalEventSetsCommand { get; } + public ICommand SearchCommand { get; } + public ICommand SearchAndReplaceObjectsCommand { get; } + + // View Menu + + public ICommand ResetCameraCommand { get; } + public ICommand RelocateCameraCommand { get; } + public ICommand ToggleFlyModeCommand { get; } + public ICommand DrawWhiteTextureLightingOnlyCommand { get; } + public ICommand ShowRealTintForObjectsCommand { get; } + + // Rooms Menu + + public ICommand NewRoomUpCommand { get; } + public ICommand NewRoomDownCommand { get; } + public ICommand NewRoomLeftCommand { get; } + public ICommand NewRoomRightCommand { get; } + public ICommand NewRoomFrontCommand { get; } + public ICommand NewRoomBackCommand { get; } + public ICommand DuplicateRoomCommand { get; } + public ICommand CropRoomCommand { get; } + public ICommand SplitRoomCommand { get; } + public ICommand MergeRoomsHorizontallyCommand { get; } + public ICommand DeleteRoomsCommand { get; } + public ICommand MoveRoomUpCommand { get; } + public ICommand MoveRoomUp4ClicksCommand { get; } + public ICommand MoveRoomDownCommand { get; } + public ICommand MoveRoomDown4ClicksCommand { get; } + public ICommand MoveRoomLeftCommand { get; } + public ICommand MoveRoomRightCommand { get; } + public ICommand MoveRoomForwardCommand { get; } + public ICommand MoveRoomBackCommand { get; } + public ICommand RotateRoomsClockwiseCommand { get; } + public ICommand RotateRoomsCounterClockwiseCommand { get; } + public ICommand MirrorRoomsXCommand { get; } + public ICommand MirrorRoomsZCommand { get; } + public ICommand SelectWaterRoomsCommand { get; } + public ICommand SelectSkyRoomsCommand { get; } + public ICommand SelectOutsideRoomsCommand { get; } + public ICommand SelectQuicksandRoomsCommand { get; } + public ICommand SelectConnectedRoomsCommand { get; } + public ICommand SelectRoomsByTagsCommand { get; } + public ICommand ExportRoomsCommand { get; } + public ICommand ImportRoomsCommand { get; } + public ICommand ApplyRoomPropertiesCommand { get; } + + // Items Menu + + public ICommand AddWadCommand { get; } + public ICommand RemoveWadsCommand { get; } + public ICommand ReloadWadsCommand { get; } + public ICommand ReloadSoundsCommand { get; } + public ICommand AddCameraCommand { get; } + public ICommand AddFlybyCameraCommand { get; } + public ICommand AddSpriteCommand { get; } + public ICommand AddSinkCommand { get; } + public ICommand AddSoundSourceCommand { get; } + public ICommand AddImportedGeometryCommand { get; } + public ICommand AddGhostBlockCommand { get; } + public ICommand AddMemoCommand { get; } + public ICommand AddPortalCommand { get; } + public ICommand AddTriggerCommand { get; } + public ICommand AddBoxVolumeCommand { get; } + public ICommand AddSphereVolumeCommand { get; } + public ICommand DeleteAllLightsCommand { get; } + public ICommand DeleteAllObjectsCommand { get; } + public ICommand DeleteAllTriggersCommand { get; } + public ICommand DeleteMissingObjectsCommand { get; } + public ICommand LocateItemCommand { get; } + public ICommand MoveLaraCommand { get; } + public ICommand SelectAllObjectsInAreaCommand { get; } + public ICommand SelectFloorBelowObjectCommand { get; } + public ICommand SplitSectorObjectOnSelectionCommand { get; } + public ICommand SetStaticMeshesColorToRoomLightCommand { get; } + public ICommand SetStaticMeshesColorCommand { get; } + public ICommand MakeQuickItemGroupCommand { get; } + public ICommand GetObjectStatisticsCommand { get; } + public ICommand GenerateObjectNamesCommand { get; } + + // Textures Menu + + public ICommand AddTextureCommand { get; } + public ICommand RemoveTexturesCommand { get; } + public ICommand UnloadTexturesCommand { get; } + public ICommand ReloadTexturesCommand { get; } + public ICommand ConvertTexturesToPNGCommand { get; } + public ICommand RemapTextureCommand { get; } + public ICommand TextureFloorCommand { get; } + public ICommand TextureWallsCommand { get; } + public ICommand TextureCeilingCommand { get; } + public ICommand ClearAllTexturesInRoomCommand { get; } + public ICommand ClearAllTexturesInLevelCommand { get; } + public ICommand SearchTexturesCommand { get; } + public ICommand EditAnimationRangesCommand { get; } + + // Transform Menu + + public ICommand IncreaseStepHeightCommand { get; } + public ICommand DecreaseStepHeightCommand { get; } + public ICommand SmoothRandomFloorUpCommand { get; } + public ICommand SmoothRandomFloorDownCommand { get; } + public ICommand SmoothRandomCeilingUpCommand { get; } + public ICommand SmoothRandomCeilingDownCommand { get; } + public ICommand SharpRandomFloorUpCommand { get; } + public ICommand SharpRandomFloorDownCommand { get; } + public ICommand SharpRandomCeilingUpCommand { get; } + public ICommand SharpRandomCeilingDownCommand { get; } + public ICommand AverageFloorCommand { get; } + public ICommand AverageCeilingCommand { get; } + public ICommand FlattenFloorCommand { get; } + public ICommand FlattenCeilingCommand { get; } + public ICommand ResetGeometryCommand { get; } + public ICommand GridWallsIn3Command { get; } + public ICommand GridWallsIn5Command { get; } + public ICommand GridWallsIn3SquaresCommand { get; } + public ICommand GridWallsIn5SquaresCommand { get; } + + // Tools Menu + + public ICommand EditLevelSettingsCommand { get; } + public ICommand EditOptionsCommand { get; } + public ICommand EditKeyboardLayoutCommand { get; } + public ICommand StartWadToolCommand { get; } + public ICommand StartSoundToolCommand { get; } + + // Window Menu + + public ICommand ShowSectorOptionsCommand { get; } + public ICommand ShowRoomOptionsCommand { get; } + public ICommand ShowItemBrowserCommand { get; } + public ICommand ShowImportedGeometryBrowserCommand { get; } + public ICommand ShowTriggerListCommand { get; } + public ICommand ShowLightingCommand { get; } + public ICommand ShowPaletteCommand { get; } + public ICommand ShowTexturePanelCommand { get; } + public ICommand ShowObjectListCommand { get; } + public ICommand ShowStatisticsCommand { get; } + public ICommand ShowToolPaletteCommand { get; } + public ICommand ShowToolPaletteFloatingCommand { get; } + + // Tool Bar Commands + + public ICommand Switch2DModeCommand { get; } + public ICommand SwitchGeometryModeCommand { get; } + public ICommand SwitchFaceEditModeCommand { get; } + public ICommand SwitchLightingModeCommand { get; } + + // Non-menu Commands + + public ICommand CancelAnyActionCommand { get; } + + public ICommand RaiseQA1ClickCommand { get; } + public ICommand RaiseQA4ClickCommand { get; } + public ICommand LowerQA1ClickCommand { get; } + public ICommand LowerQA4ClickCommand { get; } + + public ICommand RaiseWS1ClickCommand { get; } + public ICommand RaiseWS4ClickCommand { get; } + public ICommand LowerWS1ClickCommand { get; } + public ICommand LowerWS4ClickCommand { get; } + + public ICommand RaiseED1ClickCommand { get; } + public ICommand RaiseED4ClickCommand { get; } + public ICommand LowerED1ClickCommand { get; } + public ICommand LowerED4ClickCommand { get; } + + public ICommand RaiseRF1ClickCommand { get; } + public ICommand RaiseRF4ClickCommand { get; } + public ICommand LowerRF1ClickCommand { get; } + public ICommand LowerRF4ClickCommand { get; } + + public ICommand RaiseQA1ClickSmoothCommand { get; } + public ICommand RaiseQA4ClickSmoothCommand { get; } + public ICommand LowerQA1ClickSmoothCommand { get; } + public ICommand LowerQA4ClickSmoothCommand { get; } + + public ICommand RaiseWS1ClickSmoothCommand { get; } + public ICommand RaiseWS4ClickSmoothCommand { get; } + public ICommand LowerWS1ClickSmoothCommand { get; } + public ICommand LowerWS4ClickSmoothCommand { get; } + + public ICommand RaiseED1ClickSmoothCommand { get; } + public ICommand RaiseED4ClickSmoothCommand { get; } + public ICommand LowerED1ClickSmoothCommand { get; } + public ICommand LowerED4ClickSmoothCommand { get; } + + public ICommand RaiseRF1ClickSmoothCommand { get; } + public ICommand RaiseRF4ClickSmoothCommand { get; } + public ICommand LowerRF1ClickSmoothCommand { get; } + public ICommand LowerRF4ClickSmoothCommand { get; } + + public ICommand RaiseYH1ClickCommand { get; } + public ICommand RaiseYH4ClickCommand { get; } + public ICommand LowerYH1ClickCommand { get; } + public ICommand LowerYH4ClickCommand { get; } + + public ICommand RaiseUJ1ClickCommand { get; } + public ICommand RaiseUJ4ClickCommand { get; } + public ICommand LowerUJ1ClickCommand { get; } + public ICommand LowerUJ4ClickCommand { get; } + + // Blend Mode Commands + + public ICommand SwitchBlendModeCommand { get; } + public ICommand SetBlendModeNormalCommand { get; } + public ICommand SetBlendModeAddCommand { get; } + public ICommand SetBlendModeSubtractCommand { get; } + public ICommand SetBlendModeExcludeCommand { get; } + public ICommand SetBlendModeScreenCommand { get; } + public ICommand SetBlendModeLightenCommand { get; } + + // Uncategorized Commands + + public ICommand AddTriggerWithBookmarkCommand { get; } + public ICommand RenameObjectCommand { get; } + public ICommand EditObjectColorCommand { get; } + + public ICommand SetTextureDoubleSidedCommand { get; } + public ICommand SetTextureInvisibleCommand { get; } + public ICommand ChangeTextureSelectionTileSizeCommand { get; } + + public ICommand RotateObjectLeftCommand { get; } + public ICommand RotateObjectRightCommand { get; } + public ICommand RotateObjectUpCommand { get; } + public ICommand RotateObjectDownCommand { get; } + public ICommand MoveObjectLeftCommand { get; } + public ICommand MoveObjectRightCommand { get; } + public ICommand MoveObjectForwardCommand { get; } + public ICommand MoveObjectBackCommand { get; } + public ICommand MoveObjectUpCommand { get; } + public ICommand MoveObjectDownCommand { get; } + + public ICommand SelectPreviousRoomCommand { get; } + public ICommand RotateObject5Command { get; } + public ICommand RotateObject45Command { get; } + public ICommand MoveObjectToCurrentRoomCommand { get; } + public ICommand RotateTextureCommand { get; } + public ICommand MirrorTextureCommand { get; } + public ICommand BuildAndPlayPreviewCommand { get; } + public ICommand SelectBookmarkedObjectCommand { get; } + public ICommand AddNewRoomCommand { get; } + public ICommand LockRoomCommand { get; } + public ICommand HideRoomCommand { get; } + public ICommand EditAmbientLightCommand { get; } + public ICommand AddBoxVolumeInSelectedAreaCommand { get; } + public ICommand AddItemCommand { get; } + public ICommand AssignAndClipboardScriptIdCommand { get; } + public ICommand FlipFloorSplitCommand { get; } + public ICommand FlipCeilingSplitCommand { get; } + public ICommand SwitchTool1Command { get; } + public ICommand SwitchTool2Command { get; } + public ICommand SwitchTool3Command { get; } + public ICommand SwitchTool4Command { get; } + public ICommand SwitchTool5Command { get; } + public ICommand SwitchTool6Command { get; } + public ICommand SwitchTool7Command { get; } + public ICommand SwitchTool8Command { get; } + public ICommand SwitchTool9Command { get; } + public ICommand SwitchTool10Command { get; } + public ICommand SwitchTool11Command { get; } + public ICommand SwitchTool12Command { get; } + public ICommand SwitchTool13Command { get; } + public ICommand SwitchTool14Command { get; } + public ICommand DrawPortalsCommand { get; } + public ICommand DrawHorizonCommand { get; } + public ICommand DrawRoomNamesCommand { get; } + public ICommand DrawIllegalSlopesCommand { get; } + public ICommand DrawMoveablesCommand { get; } + public ICommand DrawStaticsCommand { get; } + public ICommand DrawImportedGeometryCommand { get; } + public ICommand DrawGhostBlocksCommand { get; } + public ICommand DrawVolumesCommand { get; } + public ICommand DrawBoundingBoxesCommand { get; } + public ICommand DrawOtherObjectsCommand { get; } + public ICommand DrawLightRadiusCommand { get; } + public ICommand DrawSlideDirectionsCommand { get; } + public ICommand DrawExtraBlendingModesCommand { get; } + public ICommand HideTransparentFacesCommand { get; } + public ICommand BilinearFilterCommand { get; } + public ICommand DisableGeometryPickingCommand { get; } + public ICommand DisableHiddenRoomPickingCommand { get; } + public ICommand DrawAllRoomsCommand { get; } + public ICommand DrawCardinalDirectionsCommand { get; } + public ICommand SamplePaletteFromTexturesCommand { get; } + public ICommand ResetPaletteCommand { get; } + public ICommand ToggleFlipMapCommand { get; } + public ICommand ToggleNoOpacityCommand { get; } + public ICommand ToggleOpacityCommand { get; } + public ICommand ToggleOpacity2Command { get; } + public ICommand AddPointLightCommand { get; } + public ICommand AddShadowCommand { get; } + public ICommand AddSunLightCommand { get; } + public ICommand AddSpotLightCommand { get; } + public ICommand AddEffectLightCommand { get; } + public ICommand AddFogBulbCommand { get; } + public ICommand EditRoomNameCommand { get; } + public ICommand SetFloorCommand { get; } + public ICommand SetCeilingCommand { get; } + public ICommand SetWallCommand { get; } + public ICommand SetBoxCommand { get; } + public ICommand SetDeathCommand { get; } + public ICommand SetMonkeyswingCommand { get; } + public ICommand SetClimbPositiveZCommand { get; } + public ICommand SetClimbPositiveXCommand { get; } + public ICommand SetClimbNegativeZCommand { get; } + public ICommand SetClimbNegativeXCommand { get; } + public ICommand SetNotWalkableCommand { get; } + public ICommand SetDiagonalFloorStepCommand { get; } + public ICommand SetDiagonalCeilingStepCommand { get; } + public ICommand SetDiagonalWallCommand { get; } + public ICommand SetBeetleCheckpointCommand { get; } + public ICommand SetTriggerTriggererCommand { get; } + public ICommand ToggleForceFloorSolidCommand { get; } + public ICommand AddGhostBlocksToSelectionCommand { get; } + public ICommand SetRoomOutsideCommand { get; } + public ICommand SetRoomSkyboxCommand { get; } + public ICommand SetRoomNoLensflareCommand { get; } + public ICommand SetRoomNoPathfindingCommand { get; } + public ICommand SetRoomColdCommand { get; } + public ICommand SetRoomDamageCommand { get; } + public ICommand InPlaceSearchRoomsCommand { get; } + public ICommand InPlaceSearchItemsCommand { get; } + public ICommand InPlaceSearchTexturesCommand { get; } + public ICommand InPlaceSearchImportedGeometryCommand { get; } + public ICommand SearchMenusCommand { get; } + public ICommand MoveObjectLeftPreciseCommand { get; } + public ICommand MoveObjectRightPreciseCommand { get; } + public ICommand MoveObjectForwardPreciseCommand { get; } + public ICommand MoveObjectBackPreciseCommand { get; } + public ICommand MoveObjectUpPreciseCommand { get; } + public ICommand MoveObjectDownPreciseCommand { get; } + public ICommand HighlightSplit1Command { get; } + public ICommand HighlightSplit2Command { get; } + public ICommand HighlightSplit3Command { get; } + public ICommand HighlightSplit4Command { get; } + public ICommand HighlightSplit5Command { get; } + public ICommand HighlightSplit6Command { get; } + public ICommand HighlightSplit7Command { get; } + public ICommand HighlightSplit8Command { get; } + public ICommand HighlightSplit9Command { get; } + + private readonly Editor _editor; + + public MainWindowViewModel(Editor editor) + { + _editor = editor; + _editor.EditorEventRaised += EditorEventRaised; + + var commandArgs = new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor); + + // File Menu + + NewLevelCommand = CommandHandler.GetCommand("NewLevel", commandArgs); + OpenLevelCommand = CommandHandler.GetCommand("OpenLevel", commandArgs); + SaveLevelCommand = CommandHandler.GetCommand("SaveLevel", commandArgs); + SaveLevelAsCommand = CommandHandler.GetCommand("SaveLevelAs", commandArgs); + ImportPrjCommand = CommandHandler.GetCommand("ImportPrj", commandArgs); + ConvertLevelToTombEngineCommand = CommandHandler.GetCommand("ConvertLevelToTombEngine", commandArgs); + BuildAndPlayCommand = CommandHandler.GetCommand("BuildAndPlay", commandArgs); + BuildLevelCommand = CommandHandler.GetCommand("BuildLevel", commandArgs); + QuitEditorCommand = CommandHandler.GetCommand("QuitEditor", commandArgs); + + // Edit Menu + + UndoCommand = CommandHandler.GetCommand("Undo", commandArgs); + RedoCommand = CommandHandler.GetCommand("Redo", commandArgs); + CutCommand = CommandHandler.GetCommand("Cut", commandArgs); + CopyCommand = CommandHandler.GetCommand("Copy", commandArgs); + PasteCommand = CommandHandler.GetCommand("Paste", commandArgs); + StampObjectCommand = CommandHandler.GetCommand("StampObject", commandArgs); + DeleteCommand = CommandHandler.GetCommand("Delete", commandArgs); + SelectAllCommand = CommandHandler.GetCommand("SelectAll", commandArgs); + BookmarkObjectCommand = CommandHandler.GetCommand("BookmarkObject", commandArgs); + SelectBookmarkedObject = CommandHandler.GetCommand("SelectBookmarkedObject", commandArgs); + EditObjectCommand = CommandHandler.GetCommand("EditObject", commandArgs); + EditVolumeEventSetsCommand = CommandHandler.GetCommand("EditVolumeEventSets", commandArgs); + EditGlobalEventSetsCommand = CommandHandler.GetCommand("EditGlobalEventSets", commandArgs); + SearchCommand = CommandHandler.GetCommand("Search", commandArgs); + SearchAndReplaceObjectsCommand = CommandHandler.GetCommand("SearchAndReplaceObjects", commandArgs); + + // View Menu + + ResetCameraCommand = CommandHandler.GetCommand("ResetCamera", commandArgs); + RelocateCameraCommand = CommandHandler.GetCommand("RelocateCamera", commandArgs); + ToggleFlyModeCommand = CommandHandler.GetCommand("ToggleFlyMode", commandArgs); + DrawWhiteTextureLightingOnlyCommand = CommandHandler.GetCommand("DrawWhiteTextureLightingOnly", commandArgs); + ShowRealTintForObjectsCommand = CommandHandler.GetCommand("ShowRealTintForObjects", commandArgs); + + // Rooms Menu + + NewRoomUpCommand = CommandHandler.GetCommand("NewRoomUp", commandArgs); + NewRoomDownCommand = CommandHandler.GetCommand("NewRoomDown", commandArgs); + NewRoomLeftCommand = CommandHandler.GetCommand("NewRoomLeft", commandArgs); + NewRoomRightCommand = CommandHandler.GetCommand("NewRoomRight", commandArgs); + NewRoomFrontCommand = CommandHandler.GetCommand("NewRoomFront", commandArgs); + NewRoomBackCommand = CommandHandler.GetCommand("NewRoomBack", commandArgs); + DuplicateRoomCommand = CommandHandler.GetCommand("DuplicateRoom", commandArgs); + CropRoomCommand = CommandHandler.GetCommand("CropRoom", commandArgs); + SplitRoomCommand = CommandHandler.GetCommand("SplitRoom", commandArgs); + MergeRoomsHorizontallyCommand = CommandHandler.GetCommand("MergeRoomsHorizontally", commandArgs); + DeleteRoomsCommand = CommandHandler.GetCommand("DeleteRooms", commandArgs); + MoveRoomUpCommand = CommandHandler.GetCommand("MoveRoomUp", commandArgs); + MoveRoomUp4ClicksCommand = CommandHandler.GetCommand("MoveRoomUp4Clicks", commandArgs); + MoveRoomDownCommand = CommandHandler.GetCommand("MoveRoomDown", commandArgs); + MoveRoomDown4ClicksCommand = CommandHandler.GetCommand("MoveRoomDown4Clicks", commandArgs); + MoveRoomLeftCommand = CommandHandler.GetCommand("MoveRoomLeft", commandArgs); + MoveRoomRightCommand = CommandHandler.GetCommand("MoveRoomRight", commandArgs); + MoveRoomForwardCommand = CommandHandler.GetCommand("MoveRoomForward", commandArgs); + MoveRoomBackCommand = CommandHandler.GetCommand("MoveRoomBack", commandArgs); + RotateRoomsClockwiseCommand = CommandHandler.GetCommand("RotateRoomsClockwise", commandArgs); + RotateRoomsCounterClockwiseCommand = CommandHandler.GetCommand("RotateRoomsCounterClockwise", commandArgs); + MirrorRoomsXCommand = CommandHandler.GetCommand("MirrorRoomsX", commandArgs); + MirrorRoomsZCommand = CommandHandler.GetCommand("MirrorRoomsZ", commandArgs); + SelectWaterRoomsCommand = CommandHandler.GetCommand("SelectWaterRooms", commandArgs); + SelectSkyRoomsCommand = CommandHandler.GetCommand("SelectSkyRooms", commandArgs); + SelectOutsideRoomsCommand = CommandHandler.GetCommand("SelectOutsideRooms", commandArgs); + SelectQuicksandRoomsCommand = CommandHandler.GetCommand("SelectQuicksandRooms", commandArgs); + SelectConnectedRoomsCommand = CommandHandler.GetCommand("SelectConnectedRooms", commandArgs); + SelectRoomsByTagsCommand = CommandHandler.GetCommand("SelectRoomsByTags", commandArgs); + ExportRoomsCommand = CommandHandler.GetCommand("ExportRooms", commandArgs); + ImportRoomsCommand = CommandHandler.GetCommand("ImportRooms", commandArgs); + ApplyRoomPropertiesCommand = CommandHandler.GetCommand("ApplyRoomProperties", commandArgs); + + // Items Menu + + AddWadCommand = CommandHandler.GetCommand("AddWad", commandArgs); + RemoveWadsCommand = CommandHandler.GetCommand("RemoveWads", commandArgs); + ReloadWadsCommand = CommandHandler.GetCommand("ReloadWads", commandArgs); + ReloadSoundsCommand = CommandHandler.GetCommand("ReloadSounds", commandArgs); + AddCameraCommand = CommandHandler.GetCommand("AddCamera", commandArgs); + AddFlybyCameraCommand = CommandHandler.GetCommand("AddFlybyCamera", commandArgs); + AddSpriteCommand = CommandHandler.GetCommand("AddSprite", commandArgs); + AddSinkCommand = CommandHandler.GetCommand("AddSink", commandArgs); + AddSoundSourceCommand = CommandHandler.GetCommand("AddSoundSource", commandArgs); + AddImportedGeometryCommand = CommandHandler.GetCommand("AddImportedGeometry", commandArgs); + AddGhostBlockCommand = CommandHandler.GetCommand("AddGhostBlock", commandArgs); + AddMemoCommand = CommandHandler.GetCommand("AddMemo", commandArgs); + AddPortalCommand = CommandHandler.GetCommand("AddPortal", commandArgs); + AddTriggerCommand = CommandHandler.GetCommand("AddTrigger", commandArgs); + AddBoxVolumeCommand = CommandHandler.GetCommand("AddBoxVolume", commandArgs); + AddSphereVolumeCommand = CommandHandler.GetCommand("AddSphereVolume", commandArgs); + DeleteAllLightsCommand = CommandHandler.GetCommand("DeleteAllLights", commandArgs); + DeleteAllObjectsCommand = CommandHandler.GetCommand("DeleteAllObjects", commandArgs); + DeleteAllTriggersCommand = CommandHandler.GetCommand("DeleteAllTriggers", commandArgs); + DeleteMissingObjectsCommand = CommandHandler.GetCommand("DeleteMissingObjects", commandArgs); + LocateItemCommand = CommandHandler.GetCommand("LocateItem", commandArgs); + MoveLaraCommand = CommandHandler.GetCommand("MoveLara", commandArgs); + SelectAllObjectsInAreaCommand = CommandHandler.GetCommand("SelectAllObjectsInArea", commandArgs); + SelectFloorBelowObjectCommand = CommandHandler.GetCommand("SelectFloorBelowObject", commandArgs); + SplitSectorObjectOnSelectionCommand = CommandHandler.GetCommand("SplitSectorObjectOnSelection", commandArgs); + SetStaticMeshesColorToRoomLightCommand = CommandHandler.GetCommand("SetStaticMeshesColorToRoomLight", commandArgs); + SetStaticMeshesColorCommand = CommandHandler.GetCommand("SetStaticMeshesColor", commandArgs); + MakeQuickItemGroupCommand = CommandHandler.GetCommand("MakeQuickItemGroup", commandArgs); + GetObjectStatisticsCommand = CommandHandler.GetCommand("GetObjectStatistics", commandArgs); + GenerateObjectNamesCommand = CommandHandler.GetCommand("GenerateObjectNames", commandArgs); + + // Textures Menu + + AddTextureCommand = CommandHandler.GetCommand("AddTexture", commandArgs); + RemoveTexturesCommand = CommandHandler.GetCommand("RemoveTextures", commandArgs); + UnloadTexturesCommand = CommandHandler.GetCommand("UnloadTextures", commandArgs); + ReloadTexturesCommand = CommandHandler.GetCommand("ReloadTextures", commandArgs); + ConvertTexturesToPNGCommand = CommandHandler.GetCommand("ConvertTexturesToPNG", commandArgs); + RemapTextureCommand = CommandHandler.GetCommand("RemapTexture", commandArgs); + TextureFloorCommand = CommandHandler.GetCommand("TextureFloor", commandArgs); + TextureWallsCommand = CommandHandler.GetCommand("TextureWalls", commandArgs); + TextureCeilingCommand = CommandHandler.GetCommand("TextureCeiling", commandArgs); + ClearAllTexturesInRoomCommand = CommandHandler.GetCommand("ClearAllTexturesInRoom", commandArgs); + ClearAllTexturesInLevelCommand = CommandHandler.GetCommand("ClearAllTexturesInLevel", commandArgs); + SearchTexturesCommand = CommandHandler.GetCommand("SearchTextures", commandArgs); + EditAnimationRangesCommand = CommandHandler.GetCommand("EditAnimationRanges", commandArgs); + + // Transform Menu + + IncreaseStepHeightCommand = CommandHandler.GetCommand("IncreaseStepHeight", commandArgs); + DecreaseStepHeightCommand = CommandHandler.GetCommand("DecreaseStepHeight", commandArgs); + SmoothRandomFloorUpCommand = CommandHandler.GetCommand("SmoothRandomFloorUp", commandArgs); + SmoothRandomFloorDownCommand = CommandHandler.GetCommand("SmoothRandomFloorDown", commandArgs); + SmoothRandomCeilingUpCommand = CommandHandler.GetCommand("SmoothRandomCeilingUp", commandArgs); + SmoothRandomCeilingDownCommand = CommandHandler.GetCommand("SmoothRandomCeilingDown", commandArgs); + SharpRandomFloorUpCommand = CommandHandler.GetCommand("SharpRandomFloorUp", commandArgs); + SharpRandomFloorDownCommand = CommandHandler.GetCommand("SharpRandomFloorDown", commandArgs); + SharpRandomCeilingUpCommand = CommandHandler.GetCommand("SharpRandomCeilingUp", commandArgs); + SharpRandomCeilingDownCommand = CommandHandler.GetCommand("SharpRandomCeilingDown", commandArgs); + AverageFloorCommand = CommandHandler.GetCommand("AverageFloor", commandArgs); + AverageCeilingCommand = CommandHandler.GetCommand("AverageCeiling", commandArgs); + FlattenFloorCommand = CommandHandler.GetCommand("FlattenFloor", commandArgs); + FlattenCeilingCommand = CommandHandler.GetCommand("FlattenCeiling", commandArgs); + ResetGeometryCommand = CommandHandler.GetCommand("ResetGeometry", commandArgs); + GridWallsIn3Command = CommandHandler.GetCommand("GridWallsIn3", commandArgs); + GridWallsIn5Command = CommandHandler.GetCommand("GridWallsIn5", commandArgs); + GridWallsIn3SquaresCommand = CommandHandler.GetCommand("GridWallsIn3Squares", commandArgs); + GridWallsIn5SquaresCommand = CommandHandler.GetCommand("GridWallsIn5Squares", commandArgs); + + // Tools Menu + + EditLevelSettingsCommand = CommandHandler.GetCommand("EditLevelSettings", commandArgs); + EditOptionsCommand = CommandHandler.GetCommand("EditOptions", commandArgs); + EditKeyboardLayoutCommand = CommandHandler.GetCommand("EditKeyboardLayout", commandArgs); + StartWadToolCommand = CommandHandler.GetCommand("StartWadTool", commandArgs); + StartSoundToolCommand = CommandHandler.GetCommand("StartSoundTool", commandArgs); + + // Tool Bar Commands + + Switch2DModeCommand = CommandHandler.GetCommand("Switch2DMode", commandArgs); + SwitchGeometryModeCommand = CommandHandler.GetCommand("SwitchGeometryMode", commandArgs); + SwitchFaceEditModeCommand = CommandHandler.GetCommand("SwitchFaceEditMode", commandArgs); + SwitchLightingModeCommand = CommandHandler.GetCommand("SwitchLightingMode", commandArgs); + + // Non-menu Commands + + CancelAnyActionCommand = CommandHandler.GetCommand("CancelAnyAction", commandArgs); + + RaiseQA1ClickCommand = CommandHandler.GetCommand("RaiseQA1Click", commandArgs); + RaiseQA4ClickCommand = CommandHandler.GetCommand("RaiseQA4Click", commandArgs); + LowerQA1ClickCommand = CommandHandler.GetCommand("LowerQA1Click", commandArgs); + LowerQA4ClickCommand = CommandHandler.GetCommand("LowerQA4Click", commandArgs); + + RaiseWS1ClickCommand = CommandHandler.GetCommand("RaiseWS1Click", commandArgs); + RaiseWS4ClickCommand = CommandHandler.GetCommand("RaiseWS4Click", commandArgs); + LowerWS1ClickCommand = CommandHandler.GetCommand("LowerWS1Click", commandArgs); + LowerWS4ClickCommand = CommandHandler.GetCommand("LowerWS4Click", commandArgs); + + RaiseED1ClickCommand = CommandHandler.GetCommand("RaiseED1Click", commandArgs); + RaiseED4ClickCommand = CommandHandler.GetCommand("RaiseED4Click", commandArgs); + LowerED1ClickCommand = CommandHandler.GetCommand("LowerED1Click", commandArgs); + LowerED4ClickCommand = CommandHandler.GetCommand("LowerED4Click", commandArgs); + + RaiseRF1ClickCommand = CommandHandler.GetCommand("RaiseRF1Click", commandArgs); + RaiseRF4ClickCommand = CommandHandler.GetCommand("RaiseRF4Click", commandArgs); + LowerRF1ClickCommand = CommandHandler.GetCommand("LowerRF1Click", commandArgs); + LowerRF4ClickCommand = CommandHandler.GetCommand("LowerRF4Click", commandArgs); + + RaiseQA1ClickSmoothCommand = CommandHandler.GetCommand("RaiseQA1ClickSmooth", commandArgs); + RaiseQA4ClickSmoothCommand = CommandHandler.GetCommand("RaiseQA4ClickSmooth", commandArgs); + LowerQA1ClickSmoothCommand = CommandHandler.GetCommand("LowerQA1ClickSmooth", commandArgs); + LowerQA4ClickSmoothCommand = CommandHandler.GetCommand("LowerQA4ClickSmooth", commandArgs); + + RaiseWS1ClickSmoothCommand = CommandHandler.GetCommand("RaiseWS1ClickSmooth", commandArgs); + RaiseWS4ClickSmoothCommand = CommandHandler.GetCommand("RaiseWS4ClickSmooth", commandArgs); + LowerWS1ClickSmoothCommand = CommandHandler.GetCommand("LowerWS1ClickSmooth", commandArgs); + LowerWS4ClickSmoothCommand = CommandHandler.GetCommand("LowerWS4ClickSmooth", commandArgs); + + RaiseED1ClickSmoothCommand = CommandHandler.GetCommand("RaiseED1ClickSmooth", commandArgs); + RaiseED4ClickSmoothCommand = CommandHandler.GetCommand("RaiseED4ClickSmooth", commandArgs); + LowerED1ClickSmoothCommand = CommandHandler.GetCommand("LowerED1ClickSmooth", commandArgs); + LowerED4ClickSmoothCommand = CommandHandler.GetCommand("LowerED4ClickSmooth", commandArgs); + + RaiseRF1ClickSmoothCommand = CommandHandler.GetCommand("RaiseRF1ClickSmooth", commandArgs); + RaiseRF4ClickSmoothCommand = CommandHandler.GetCommand("RaiseRF4ClickSmooth", commandArgs); + LowerRF1ClickSmoothCommand = CommandHandler.GetCommand("LowerRF1ClickSmooth", commandArgs); + LowerRF4ClickSmoothCommand = CommandHandler.GetCommand("LowerRF4ClickSmooth", commandArgs); + + RaiseYH1ClickCommand = CommandHandler.GetCommand("RaiseYH1Click", commandArgs); + RaiseYH4ClickCommand = CommandHandler.GetCommand("RaiseYH4Click", commandArgs); + LowerYH1ClickCommand = CommandHandler.GetCommand("LowerYH1Click", commandArgs); + LowerYH4ClickCommand = CommandHandler.GetCommand("LowerYH4Click", commandArgs); + + RaiseUJ1ClickCommand = CommandHandler.GetCommand("RaiseUJ1Click", commandArgs); + RaiseUJ4ClickCommand = CommandHandler.GetCommand("RaiseUJ4Click", commandArgs); + LowerUJ1ClickCommand = CommandHandler.GetCommand("LowerUJ1Click", commandArgs); + LowerUJ4ClickCommand = CommandHandler.GetCommand("LowerUJ4Click", commandArgs); + + // Blend Mode Commands + + SwitchBlendModeCommand = CommandHandler.GetCommand("SwitchBlendMode", commandArgs); + SetBlendModeNormalCommand = CommandHandler.GetCommand("SetBlendModeNormal", commandArgs); + SetBlendModeAddCommand = CommandHandler.GetCommand("SetBlendModeAdd", commandArgs); + SetBlendModeSubtractCommand = CommandHandler.GetCommand("SetBlendModeSubtract", commandArgs); + SetBlendModeExcludeCommand = CommandHandler.GetCommand("SetBlendModeExclude", commandArgs); + SetBlendModeScreenCommand = CommandHandler.GetCommand("SetBlendModeScreen", commandArgs); + SetBlendModeLightenCommand = CommandHandler.GetCommand("SetBlendModeLighten", commandArgs); + + // Uncategorized Commands + + AddTriggerWithBookmarkCommand = CommandHandler.GetCommand("AddTriggerWithBookmark", commandArgs); + RenameObjectCommand = CommandHandler.GetCommand("RenameObject", commandArgs); + EditObjectColorCommand = CommandHandler.GetCommand("EditObjectColor", commandArgs); + + SetTextureDoubleSidedCommand = CommandHandler.GetCommand("SetTextureDoubleSided", commandArgs); + SetTextureInvisibleCommand = CommandHandler.GetCommand("SetTextureInvisible", commandArgs); + ChangeTextureSelectionTileSizeCommand = CommandHandler.GetCommand("ChangeTextureSelectionTileSize", commandArgs); + + RotateObjectLeftCommand = CommandHandler.GetCommand("RotateObjectLeft", commandArgs); + RotateObjectRightCommand = CommandHandler.GetCommand("RotateObjectRight", commandArgs); + RotateObjectUpCommand = CommandHandler.GetCommand("RotateObjectUp", commandArgs); + RotateObjectDownCommand = CommandHandler.GetCommand("RotateObjectDown", commandArgs); + MoveObjectLeftCommand = CommandHandler.GetCommand("MoveObjectLeft", commandArgs); + MoveObjectRightCommand = CommandHandler.GetCommand("MoveObjectRight", commandArgs); + MoveObjectForwardCommand = CommandHandler.GetCommand("MoveObjectForward", commandArgs); + MoveObjectBackCommand = CommandHandler.GetCommand("MoveObjectBack", commandArgs); + MoveObjectUpCommand = CommandHandler.GetCommand("MoveObjectUp", commandArgs); + MoveObjectDownCommand = CommandHandler.GetCommand("MoveObjectDown", commandArgs); + + SelectPreviousRoomCommand = CommandHandler.GetCommand("SelectPreviousRoom", commandArgs); + RotateObject5Command = CommandHandler.GetCommand("RotateObject5", commandArgs); + RotateObject45Command = CommandHandler.GetCommand("RotateObject45", commandArgs); + MoveObjectToCurrentRoomCommand = CommandHandler.GetCommand("MoveObjectToCurrentRoom", commandArgs); + RotateTextureCommand = CommandHandler.GetCommand("RotateTexture", commandArgs); + MirrorTextureCommand = CommandHandler.GetCommand("MirrorTexture", commandArgs); + BuildAndPlayPreviewCommand = CommandHandler.GetCommand("BuildAndPlayPreview", commandArgs); + SelectBookmarkedObjectCommand = CommandHandler.GetCommand("SelectBookmarkedObject", commandArgs); + AddNewRoomCommand = CommandHandler.GetCommand("AddNewRoom", commandArgs); + LockRoomCommand = CommandHandler.GetCommand("LockRoom", commandArgs); + HideRoomCommand = CommandHandler.GetCommand("HideRoom", commandArgs); + EditAmbientLightCommand = CommandHandler.GetCommand("EditAmbientLight", commandArgs); + AddBoxVolumeInSelectedAreaCommand = CommandHandler.GetCommand("AddBoxVolumeInSelectedArea", commandArgs); + AddItemCommand = CommandHandler.GetCommand("AddItem", commandArgs); + AssignAndClipboardScriptIdCommand = CommandHandler.GetCommand("AssignAndClipboardScriptId", commandArgs); + FlipFloorSplitCommand = CommandHandler.GetCommand("FlipFloorSplit", commandArgs); + FlipCeilingSplitCommand = CommandHandler.GetCommand("FlipCeilingSplit", commandArgs); + SwitchTool1Command = CommandHandler.GetCommand("SwitchTool1", commandArgs); + SwitchTool2Command = CommandHandler.GetCommand("SwitchTool2", commandArgs); + SwitchTool3Command = CommandHandler.GetCommand("SwitchTool3", commandArgs); + SwitchTool4Command = CommandHandler.GetCommand("SwitchTool4", commandArgs); + SwitchTool5Command = CommandHandler.GetCommand("SwitchTool5", commandArgs); + SwitchTool6Command = CommandHandler.GetCommand("SwitchTool6", commandArgs); + SwitchTool7Command = CommandHandler.GetCommand("SwitchTool7", commandArgs); + SwitchTool8Command = CommandHandler.GetCommand("SwitchTool8", commandArgs); + SwitchTool9Command = CommandHandler.GetCommand("SwitchTool9", commandArgs); + SwitchTool10Command = CommandHandler.GetCommand("SwitchTool10", commandArgs); + SwitchTool11Command = CommandHandler.GetCommand("SwitchTool11", commandArgs); + SwitchTool12Command = CommandHandler.GetCommand("SwitchTool12", commandArgs); + SwitchTool13Command = CommandHandler.GetCommand("SwitchTool13", commandArgs); + SwitchTool14Command = CommandHandler.GetCommand("SwitchTool14", commandArgs); + DrawPortalsCommand = CommandHandler.GetCommand("DrawPortals", commandArgs); + DrawHorizonCommand = CommandHandler.GetCommand("DrawHorizon", commandArgs); + DrawRoomNamesCommand = CommandHandler.GetCommand("DrawRoomNames", commandArgs); + DrawIllegalSlopesCommand = CommandHandler.GetCommand("DrawIllegalSlopes", commandArgs); + DrawMoveablesCommand = CommandHandler.GetCommand("DrawMoveables", commandArgs); + DrawStaticsCommand = CommandHandler.GetCommand("DrawStatics", commandArgs); + DrawImportedGeometryCommand = CommandHandler.GetCommand("DrawImportedGeometry", commandArgs); + DrawGhostBlocksCommand = CommandHandler.GetCommand("DrawGhostBlocks", commandArgs); + DrawVolumesCommand = CommandHandler.GetCommand("DrawVolumes", commandArgs); + DrawBoundingBoxesCommand = CommandHandler.GetCommand("DrawBoundingBoxes", commandArgs); + DrawOtherObjectsCommand = CommandHandler.GetCommand("DrawOtherObjects", commandArgs); + DrawLightRadiusCommand = CommandHandler.GetCommand("DrawLightRadius", commandArgs); + DrawSlideDirectionsCommand = CommandHandler.GetCommand("DrawSlideDirections", commandArgs); + DrawExtraBlendingModesCommand = CommandHandler.GetCommand("DrawExtraBlendingModes", commandArgs); + HideTransparentFacesCommand = CommandHandler.GetCommand("HideTransparentFaces", commandArgs); + BilinearFilterCommand = CommandHandler.GetCommand("BilinearFilter", commandArgs); + DisableGeometryPickingCommand = CommandHandler.GetCommand("DisableGeometryPicking", commandArgs); + DisableHiddenRoomPickingCommand = CommandHandler.GetCommand("DisableHiddenRoomPicking", commandArgs); + DrawAllRoomsCommand = CommandHandler.GetCommand("DrawAllRooms", commandArgs); + DrawCardinalDirectionsCommand = CommandHandler.GetCommand("DrawCardinalDirections", commandArgs); + SamplePaletteFromTexturesCommand = CommandHandler.GetCommand("SamplePaletteFromTextures", commandArgs); + ResetPaletteCommand = CommandHandler.GetCommand("ResetPalette", commandArgs); + ToggleFlipMapCommand = CommandHandler.GetCommand("ToggleFlipMap", commandArgs); + ToggleNoOpacityCommand = CommandHandler.GetCommand("ToggleNoOpacity", commandArgs); + ToggleOpacityCommand = CommandHandler.GetCommand("ToggleOpacity", commandArgs); + ToggleOpacity2Command = CommandHandler.GetCommand("ToggleOpacity2", commandArgs); + AddPointLightCommand = CommandHandler.GetCommand("AddPointLight", commandArgs); + AddShadowCommand = CommandHandler.GetCommand("AddShadow", commandArgs); + AddSunLightCommand = CommandHandler.GetCommand("AddSunLight", commandArgs); + AddSpotLightCommand = CommandHandler.GetCommand("AddSpotLight", commandArgs); + AddEffectLightCommand = CommandHandler.GetCommand("AddEffectLight", commandArgs); + AddFogBulbCommand = CommandHandler.GetCommand("AddFogBulb", commandArgs); + EditRoomNameCommand = CommandHandler.GetCommand("EditRoomName", commandArgs); + SetFloorCommand = CommandHandler.GetCommand("SetFloor", commandArgs); + SetCeilingCommand = CommandHandler.GetCommand("SetCeiling", commandArgs); + SetWallCommand = CommandHandler.GetCommand("SetWall", commandArgs); + SetBoxCommand = CommandHandler.GetCommand("SetBox", commandArgs); + SetDeathCommand = CommandHandler.GetCommand("SetDeath", commandArgs); + SetMonkeyswingCommand = CommandHandler.GetCommand("SetMonkeyswing", commandArgs); + SetClimbPositiveZCommand = CommandHandler.GetCommand("SetClimbPositiveZ", commandArgs); + SetClimbPositiveXCommand = CommandHandler.GetCommand("SetClimbPositiveX", commandArgs); + SetClimbNegativeZCommand = CommandHandler.GetCommand("SetClimbNegativeZ", commandArgs); + SetClimbNegativeXCommand = CommandHandler.GetCommand("SetClimbNegativeX", commandArgs); + SetNotWalkableCommand = CommandHandler.GetCommand("SetNotWalkable", commandArgs); + SetDiagonalFloorStepCommand = CommandHandler.GetCommand("SetDiagonalFloorStep", commandArgs); + SetDiagonalCeilingStepCommand = CommandHandler.GetCommand("SetDiagonalCeilingStep", commandArgs); + SetDiagonalWallCommand = CommandHandler.GetCommand("SetDiagonalWall", commandArgs); + SetBeetleCheckpointCommand = CommandHandler.GetCommand("SetBeetleCheckpoint", commandArgs); + SetTriggerTriggererCommand = CommandHandler.GetCommand("SetTriggerTriggerer", commandArgs); + ToggleForceFloorSolidCommand = CommandHandler.GetCommand("ToggleForceFloorSolid", commandArgs); + AddGhostBlocksToSelectionCommand = CommandHandler.GetCommand("AddGhostBlocksToSelection", commandArgs); + SetRoomOutsideCommand = CommandHandler.GetCommand("SetRoomOutside", commandArgs); + SetRoomSkyboxCommand = CommandHandler.GetCommand("SetRoomSkybox", commandArgs); + SetRoomNoLensflareCommand = CommandHandler.GetCommand("SetRoomNoLensflare", commandArgs); + SetRoomNoPathfindingCommand = CommandHandler.GetCommand("SetRoomNoPathfinding", commandArgs); + SetRoomColdCommand = CommandHandler.GetCommand("SetRoomCold", commandArgs); + SetRoomDamageCommand = CommandHandler.GetCommand("SetRoomDamage", commandArgs); + InPlaceSearchRoomsCommand = CommandHandler.GetCommand("InPlaceSearchRooms", commandArgs); + InPlaceSearchItemsCommand = CommandHandler.GetCommand("InPlaceSearchItems", commandArgs); + InPlaceSearchTexturesCommand = CommandHandler.GetCommand("InPlaceSearchTextures", commandArgs); + InPlaceSearchImportedGeometryCommand = CommandHandler.GetCommand("InPlaceSearchImportedGeometry", commandArgs); + SearchMenusCommand = CommandHandler.GetCommand("SearchMenus", commandArgs); + MoveObjectLeftPreciseCommand = CommandHandler.GetCommand("MoveObjectLeftPrecise", commandArgs); + MoveObjectRightPreciseCommand = CommandHandler.GetCommand("MoveObjectRightPrecise", commandArgs); + MoveObjectForwardPreciseCommand = CommandHandler.GetCommand("MoveObjectForwardPrecise", commandArgs); + MoveObjectBackPreciseCommand = CommandHandler.GetCommand("MoveObjectBackPrecise", commandArgs); + MoveObjectUpPreciseCommand = CommandHandler.GetCommand("MoveObjectUpPrecise", commandArgs); + MoveObjectDownPreciseCommand = CommandHandler.GetCommand("MoveObjectDownPrecise", commandArgs); + HighlightSplit1Command = CommandHandler.GetCommand("HighlightSplit1", commandArgs); + HighlightSplit2Command = CommandHandler.GetCommand("HighlightSplit2", commandArgs); + HighlightSplit3Command = CommandHandler.GetCommand("HighlightSplit3", commandArgs); + HighlightSplit4Command = CommandHandler.GetCommand("HighlightSplit4", commandArgs); + HighlightSplit5Command = CommandHandler.GetCommand("HighlightSplit5", commandArgs); + HighlightSplit6Command = CommandHandler.GetCommand("HighlightSplit6", commandArgs); + HighlightSplit7Command = CommandHandler.GetCommand("HighlightSplit7", commandArgs); + HighlightSplit8Command = CommandHandler.GetCommand("HighlightSplit8", commandArgs); + HighlightSplit9Command = CommandHandler.GetCommand("HighlightSplit9", commandArgs); + } + + private void EditorEventRaised(IEditorEvent obj) + { + if (obj is Editor.ConfigurationChangedEvent) + { + KeyBindingsWrapper.Instance.Invalidate(); + } + else if (obj is Editor.ModeChangedEvent modeChanged) + { + OnPropertyChanged(nameof(IsMap2DMode)); + OnPropertyChanged(nameof(IsGeometryMode)); + OnPropertyChanged(nameof(IsFaceEditMode)); + OnPropertyChanged(nameof(IsLightingMode)); + } + } + + [RelayCommand] + public void About() + { + using var form = new FormAbout(Properties.Resources.misc_AboutScreen_800) { StartPosition = FormStartPosition.CenterScreen }; + form.ShowDialog(WPFUtils.GetWin32WindowFromCaller(this)); + } + + [RelayCommand] + public void RestoreDefaultLayout() + { + Console.WriteLine("DEBUG"); + } + + [RelayCommand] + public void SetEditorMode(EditorMode mode) + { + _editor.Mode = mode; + } + + public bool IsMap2DMode => _editor.Mode == EditorMode.Map2D; + public bool IsGeometryMode => _editor.Mode == EditorMode.Geometry; + public bool IsFaceEditMode => _editor.Mode == EditorMode.FaceEdit; + public bool IsLightingMode => _editor.Mode == EditorMode.Lighting; +} diff --git a/TombEditor/WPF/ViewModels/OptionsViewModel.cs b/TombEditor/WPF/ViewModels/OptionsViewModel.cs new file mode 100644 index 0000000000..44df4c06ac --- /dev/null +++ b/TombEditor/WPF/ViewModels/OptionsViewModel.cs @@ -0,0 +1,1627 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Drawing; +using System.Linq; +using System.Numerics; +using TombLib.LevelData; +using TombLib.Rendering; + +namespace TombEditor.WPF.ViewModels +{ + public class OptionsViewModel : ViewModelBase + { + private readonly Configuration _config; + + #region Properties + + public IEnumerable GameVersions { get; set; } = Enum.GetValues().Cast(); + + public int Editor_UndoDepth + { + get => _config.Editor_UndoDepth; + set + { + _config.Editor_UndoDepth = value; + NotifyPropertyChanged(nameof(Editor_UndoDepth)); + } + } + + public bool Log_WriteToFile + { + get => _config.Log_WriteToFile; + set + { + _config.Log_WriteToFile = value; + NotifyPropertyChanged(nameof(Log_WriteToFile)); + } + } + + public int Log_ArchiveN + { + get => _config.Log_ArchiveN; + set + { + _config.Log_ArchiveN = value; + NotifyPropertyChanged(nameof(Log_ArchiveN)); + } + } + + public bool Editor_ReloadFilesAutomaticallyWhenChanged + { + get => _config.Editor_ReloadFilesAutomaticallyWhenChanged; + set + { + _config.Editor_ReloadFilesAutomaticallyWhenChanged = value; + NotifyPropertyChanged(nameof(Editor_ReloadFilesAutomaticallyWhenChanged)); + } + } + + public bool Editor_OpenLastProjectOnStartup + { + get => _config.Editor_OpenLastProjectOnStartup; + set + { + _config.Editor_OpenLastProjectOnStartup = value; + NotifyPropertyChanged(nameof(Editor_OpenLastProjectOnStartup)); + } + } + + public bool Editor_AllowMultipleInstances + { + get => _config.Editor_AllowMultipleInstances; + set + { + _config.Editor_AllowMultipleInstances = value; + NotifyPropertyChanged(nameof(Editor_AllowMultipleInstances)); + } + } + + // Defaults + + public TRVersion.Game Editor_DefaultProjectGameVersion { get; set; } = TRVersion.Game.TRNG; + + public int Editor_DefaultNewRoomSize + { + get => _config.Editor_DefaultNewRoomSize; + set + { + _config.Editor_DefaultNewRoomSize = value; + NotifyPropertyChanged(nameof(Editor_DefaultNewRoomSize)); + } + } + + public bool Editor_GridNewRoom + { + get => _config.Editor_GridNewRoom; + set + { + _config.Editor_GridNewRoom = value; + NotifyPropertyChanged(nameof(Editor_GridNewRoom)); + } + } + + public bool Editor_UseHalfPixelCorrectionOnPrjImport + { + get => _config.Editor_UseHalfPixelCorrectionOnPrjImport; + set + { + _config.Editor_UseHalfPixelCorrectionOnPrjImport = value; + NotifyPropertyChanged(nameof(Editor_UseHalfPixelCorrectionOnPrjImport)); + } + } + + public bool Editor_RespectFlybyPatchOnPrjImport + { + get => _config.Editor_RespectFlybyPatchOnPrjImport; + set + { + _config.Editor_RespectFlybyPatchOnPrjImport = value; + NotifyPropertyChanged(nameof(Editor_RespectFlybyPatchOnPrjImport)); + } + } + + // Item preview options + + public float RenderingItem_NavigationSpeedMouseWheelZoom + { + get => _config.RenderingItem_NavigationSpeedMouseWheelZoom; + set + { + _config.RenderingItem_NavigationSpeedMouseWheelZoom = value; + NotifyPropertyChanged(nameof(RenderingItem_NavigationSpeedMouseWheelZoom)); + } + } + + public float RenderingItem_NavigationSpeedMouseZoom + { + get => _config.RenderingItem_NavigationSpeedMouseZoom; + set + { + _config.RenderingItem_NavigationSpeedMouseZoom = value; + NotifyPropertyChanged(nameof(RenderingItem_NavigationSpeedMouseZoom)); + } + } + + public float RenderingItem_NavigationSpeedMouseTranslate + { + get => _config.RenderingItem_NavigationSpeedMouseTranslate; + set + { + _config.RenderingItem_NavigationSpeedMouseTranslate = value; + NotifyPropertyChanged(nameof(RenderingItem_NavigationSpeedMouseTranslate)); + } + } + + public float RenderingItem_NavigationSpeedMouseRotate + { + get => _config.RenderingItem_NavigationSpeedMouseRotate; + set + { + _config.RenderingItem_NavigationSpeedMouseRotate = value; + NotifyPropertyChanged(nameof(RenderingItem_NavigationSpeedMouseRotate)); + } + } + + public float RenderingItem_FieldOfView + { + get => _config.RenderingItem_FieldOfView; + set + { + _config.RenderingItem_FieldOfView = value; + NotifyPropertyChanged(nameof(RenderingItem_FieldOfView)); + } + } + + public bool RenderingItem_Antialias + { + get => _config.RenderingItem_Antialias; + set + { + _config.RenderingItem_Antialias = value; + NotifyPropertyChanged(nameof(RenderingItem_Antialias)); + } + } + + public bool RenderingItem_HideInternalObjects + { + get => _config.RenderingItem_HideInternalObjects; + set + { + _config.RenderingItem_HideInternalObjects = value; + NotifyPropertyChanged(nameof(RenderingItem_HideInternalObjects)); + } + } + + public bool RenderingItem_ShowMultipleWadsPrompt + { + get => _config.RenderingItem_ShowMultipleWadsPrompt; + set + { + _config.RenderingItem_ShowMultipleWadsPrompt = value; + NotifyPropertyChanged(nameof(RenderingItem_ShowMultipleWadsPrompt)); + } + } + + public bool RenderingItem_Animate + { + get => _config.RenderingItem_Animate; + set + { + _config.RenderingItem_Animate = value; + NotifyPropertyChanged(nameof(RenderingItem_Animate)); + } + } + + // Main 3D window options + + public int Rendering3D_DrawRoomsMaxDepth + { + get => _config.Rendering3D_DrawRoomsMaxDepth; + set + { + _config.Rendering3D_DrawRoomsMaxDepth = value; + NotifyPropertyChanged(nameof(Rendering3D_DrawRoomsMaxDepth)); + } + } + + public float Rendering3D_NavigationSpeedKeyRotate + { + get => _config.Rendering3D_NavigationSpeedKeyRotate; + set + { + _config.Rendering3D_NavigationSpeedKeyRotate = value; + NotifyPropertyChanged(nameof(Rendering3D_NavigationSpeedKeyRotate)); + } + } + + public float Rendering3D_NavigationSpeedKeyZoom + { + get => _config.Rendering3D_NavigationSpeedKeyZoom; + set + { + _config.Rendering3D_NavigationSpeedKeyZoom = value; + NotifyPropertyChanged(nameof(Rendering3D_NavigationSpeedKeyZoom)); + } + } + + public float Rendering3D_NavigationSpeedMouseWheelZoom + { + get => _config.Rendering3D_NavigationSpeedMouseWheelZoom; + set + { + _config.Rendering3D_NavigationSpeedMouseWheelZoom = value; + NotifyPropertyChanged(nameof(Rendering3D_NavigationSpeedMouseWheelZoom)); + } + } + + public float Rendering3D_NavigationSpeedMouseZoom + { + get => _config.Rendering3D_NavigationSpeedMouseZoom; + set + { + _config.Rendering3D_NavigationSpeedMouseZoom = value; + NotifyPropertyChanged(nameof(Rendering3D_NavigationSpeedMouseZoom)); + } + } + + public float Rendering3D_NavigationSpeedMouseTranslate + { + get => _config.Rendering3D_NavigationSpeedMouseTranslate; + set + { + _config.Rendering3D_NavigationSpeedMouseTranslate = value; + NotifyPropertyChanged(nameof(Rendering3D_NavigationSpeedMouseTranslate)); + } + } + + public float Rendering3D_NavigationSpeedMouseRotate + { + get => _config.Rendering3D_NavigationSpeedMouseRotate; + set + { + _config.Rendering3D_NavigationSpeedMouseRotate = value; + NotifyPropertyChanged(nameof(Rendering3D_NavigationSpeedMouseRotate)); + } + } + + public float Rendering3D_DragMouseSensitivity + { + get => _config.Rendering3D_DragMouseSensitivity; + set + { + _config.Rendering3D_DragMouseSensitivity = value; + NotifyPropertyChanged(nameof(Rendering3D_DragMouseSensitivity)); + } + } + + public bool Rendering3D_InvertMouseZoom + { + get => _config.Rendering3D_InvertMouseZoom; + set + { + _config.Rendering3D_InvertMouseZoom = value; + NotifyPropertyChanged(nameof(Rendering3D_InvertMouseZoom)); + } + } + + public float Rendering3D_LineWidth + { + get => _config.Rendering3D_LineWidth; + set + { + _config.Rendering3D_LineWidth = value; + NotifyPropertyChanged(nameof(Rendering3D_LineWidth)); + } + } + + public float Rendering3D_FieldOfView + { + get => _config.Rendering3D_FieldOfView; + set + { + _config.Rendering3D_FieldOfView = value; + NotifyPropertyChanged(nameof(Rendering3D_FieldOfView)); + } + } + + public bool Rendering3D_ToolboxVisible + { + get => _config.Rendering3D_ToolboxVisible; + set + { + _config.Rendering3D_ToolboxVisible = value; + NotifyPropertyChanged(nameof(Rendering3D_ToolboxVisible)); + } + } + + public Point Rendering3D_ToolboxPosition + { + get => _config.Rendering3D_ToolboxPosition; + set + { + _config.Rendering3D_ToolboxPosition = value; + NotifyPropertyChanged(nameof(Rendering3D_ToolboxPosition)); + } + } + + public bool Rendering3D_DisablePickingForImportedGeometry + { + get => _config.Rendering3D_DisablePickingForImportedGeometry; + set + { + _config.Rendering3D_DisablePickingForImportedGeometry = value; + NotifyPropertyChanged(nameof(Rendering3D_DisablePickingForImportedGeometry)); + } + } + + public bool Rendering3D_DisablePickingForHiddenRooms + { + get => _config.Rendering3D_DisablePickingForHiddenRooms; + set + { + _config.Rendering3D_DisablePickingForHiddenRooms = value; + NotifyPropertyChanged(nameof(Rendering3D_DisablePickingForHiddenRooms)); + } + } + + public bool Rendering3D_ShowPortals + { + get => _config.Rendering3D_ShowPortals; + set + { + _config.Rendering3D_ShowPortals = value; + NotifyPropertyChanged(nameof(Rendering3D_ShowPortals)); + } + } + + public bool Rendering3D_ShowHorizon + { + get => _config.Rendering3D_ShowHorizon; + set + { + _config.Rendering3D_ShowHorizon = value; + NotifyPropertyChanged(nameof(Rendering3D_ShowHorizon)); + } + } + + public bool Rendering3D_ShowAllRooms + { + get => _config.Rendering3D_ShowAllRooms; + set + { + _config.Rendering3D_ShowAllRooms = value; + NotifyPropertyChanged(nameof(Rendering3D_ShowAllRooms)); + } + } + + public bool Rendering3D_ShowIllegalSlopes + { + get => _config.Rendering3D_ShowIllegalSlopes; + set + { + _config.Rendering3D_ShowIllegalSlopes = value; + NotifyPropertyChanged(nameof(Rendering3D_ShowIllegalSlopes)); + } + } + + public bool Rendering3D_ShowMoveables + { + get => _config.Rendering3D_ShowMoveables; + set + { + _config.Rendering3D_ShowMoveables = value; + NotifyPropertyChanged(nameof(Rendering3D_ShowMoveables)); + } + } + + public bool Rendering3D_ShowStatics + { + get => _config.Rendering3D_ShowStatics; + set + { + _config.Rendering3D_ShowStatics = value; + NotifyPropertyChanged(nameof(Rendering3D_ShowStatics)); + } + } + + public bool Rendering3D_ShowImportedGeometry + { + get => _config.Rendering3D_ShowImportedGeometry; + set + { + _config.Rendering3D_ShowImportedGeometry = value; + NotifyPropertyChanged(nameof(Rendering3D_ShowImportedGeometry)); + } + } + + public bool Rendering3D_ShowGhostBlocks + { + get => _config.Rendering3D_ShowGhostBlocks; + set + { + _config.Rendering3D_ShowGhostBlocks = value; + NotifyPropertyChanged(nameof(Rendering3D_ShowGhostBlocks)); + } + } + + public bool Rendering3D_ShowVolumes + { + get => _config.Rendering3D_ShowVolumes; + set + { + _config.Rendering3D_ShowVolumes = value; + NotifyPropertyChanged(nameof(Rendering3D_ShowVolumes)); + } + } + + public bool Rendering3D_ShowBoundingBoxes + { + get => _config.Rendering3D_ShowBoundingBoxes; + set + { + _config.Rendering3D_ShowBoundingBoxes = value; + NotifyPropertyChanged(nameof(Rendering3D_ShowBoundingBoxes)); + } + } + + public bool Rendering3D_ShowOtherObjects + { + get => _config.Rendering3D_ShowOtherObjects; + set + { + _config.Rendering3D_ShowOtherObjects = value; + NotifyPropertyChanged(nameof(Rendering3D_ShowOtherObjects)); + } + } + + public bool Rendering3D_ShowSlideDirections + { + get => _config.Rendering3D_ShowSlideDirections; + set + { + _config.Rendering3D_ShowSlideDirections = value; + NotifyPropertyChanged(nameof(Rendering3D_ShowSlideDirections)); + } + } + + public bool Rendering3D_ShowFPS + { + get => _config.Rendering3D_ShowFPS; + set + { + _config.Rendering3D_ShowFPS = value; + NotifyPropertyChanged(nameof(Rendering3D_ShowFPS)); + } + } + + public bool Rendering3D_ShowRoomNames + { + get => _config.Rendering3D_ShowRoomNames; + set + { + _config.Rendering3D_ShowRoomNames = value; + NotifyPropertyChanged(nameof(Rendering3D_ShowRoomNames)); + } + } + + public bool Rendering3D_ShowCardinalDirections + { + get => _config.Rendering3D_ShowCardinalDirections; + set + { + _config.Rendering3D_ShowCardinalDirections = value; + NotifyPropertyChanged(nameof(Rendering3D_ShowCardinalDirections)); + } + } + + public bool Rendering3D_UseRoomEditorDirections + { + get => _config.Rendering3D_UseRoomEditorDirections; + set + { + _config.Rendering3D_UseRoomEditorDirections = value; + NotifyPropertyChanged(nameof(Rendering3D_UseRoomEditorDirections)); + } + } + + public bool Rendering3D_ShowExtraBlendingModes + { + get => _config.Rendering3D_ShowExtraBlendingModes; + set + { + _config.Rendering3D_ShowExtraBlendingModes = value; + NotifyPropertyChanged(nameof(Rendering3D_ShowExtraBlendingModes)); + } + } + + public bool Rendering3D_HideTransparentFaces + { + get => _config.Rendering3D_HideTransparentFaces; + set + { + _config.Rendering3D_HideTransparentFaces = value; + NotifyPropertyChanged(nameof(Rendering3D_HideTransparentFaces)); + } + } + + public bool Rendering3D_BilinearFilter + { + get => _config.Rendering3D_BilinearFilter; + set + { + _config.Rendering3D_BilinearFilter = value; + NotifyPropertyChanged(nameof(Rendering3D_BilinearFilter)); + } + } + + public bool Rendering3D_ShowLightingWhiteTextureOnly + { + get => _config.Rendering3D_ShowLightingWhiteTextureOnly; + set + { + _config.Rendering3D_ShowLightingWhiteTextureOnly = value; + NotifyPropertyChanged(nameof(Rendering3D_ShowLightingWhiteTextureOnly)); + } + } + + public string Rendering3D_FontName + { + get => _config.Rendering3D_FontName; + set + { + _config.Rendering3D_FontName = value; + NotifyPropertyChanged(nameof(Rendering3D_FontName)); + } + } + + public int Rendering3D_FontSize + { + get => _config.Rendering3D_FontSize; + set + { + _config.Rendering3D_FontSize = value; + NotifyPropertyChanged(nameof(Rendering3D_FontSize)); + } + } + + public bool Rendering3D_FontIsBold + { + get => _config.Rendering3D_FontIsBold; + set + { + _config.Rendering3D_FontIsBold = value; + NotifyPropertyChanged(nameof(Rendering3D_FontIsBold)); + } + } + + public bool Rendering3D_DrawFontOverlays + { + get => _config.Rendering3D_DrawFontOverlays; + set + { + _config.Rendering3D_DrawFontOverlays = value; + NotifyPropertyChanged(nameof(Rendering3D_DrawFontOverlays)); + } + } + + public bool Rendering3D_Antialias + { + get => _config.Rendering3D_Antialias; + set + { + _config.Rendering3D_Antialias = value; + NotifyPropertyChanged(nameof(Rendering3D_Antialias)); + } + } + + public bool Rendering3D_SafeMode + { + get => _config.Rendering3D_SafeMode; + set + { + _config.Rendering3D_SafeMode = value; + NotifyPropertyChanged(nameof(Rendering3D_SafeMode)); + } + } + + public bool Rendering3D_ResetCameraOnRoomSwitch + { + get => _config.Rendering3D_ResetCameraOnRoomSwitch; + set + { + _config.Rendering3D_ResetCameraOnRoomSwitch = value; + NotifyPropertyChanged(nameof(Rendering3D_ResetCameraOnRoomSwitch)); + } + } + + public bool Rendering3D_AnimateCameraOnDoubleClickRoomSwitch + { + get => _config.Rendering3D_AnimateCameraOnDoubleClickRoomSwitch; + set + { + _config.Rendering3D_AnimateCameraOnDoubleClickRoomSwitch = value; + NotifyPropertyChanged(nameof(Rendering3D_AnimateCameraOnDoubleClickRoomSwitch)); + } + } + + public bool Rendering3D_AnimateCameraOnRelocation + { + get => _config.Rendering3D_AnimateCameraOnRelocation; + set + { + _config.Rendering3D_AnimateCameraOnRelocation = value; + NotifyPropertyChanged(nameof(Rendering3D_AnimateCameraOnRelocation)); + } + } + + public bool Rendering3D_AnimateCameraOnReset + { + get => _config.Rendering3D_AnimateCameraOnReset; + set + { + _config.Rendering3D_AnimateCameraOnReset = value; + NotifyPropertyChanged(nameof(Rendering3D_AnimateCameraOnReset)); + } + } + + public bool Rendering3D_AnimateGhostBlockUnfolding + { + get => _config.Rendering3D_AnimateGhostBlockUnfolding; + set + { + _config.Rendering3D_AnimateGhostBlockUnfolding = value; + NotifyPropertyChanged(nameof(Rendering3D_AnimateGhostBlockUnfolding)); + } + } + + public bool Rendering3D_AllowTexturingInLightingMode + { + get => _config.Rendering3D_AllowTexturingInLightingMode; + set + { + _config.Rendering3D_AllowTexturingInLightingMode = value; + NotifyPropertyChanged(nameof(Rendering3D_AllowTexturingInLightingMode)); + } + } + + public bool Rendering3D_AlwaysShowCurrentRoomBounds + { + get => _config.Rendering3D_AlwaysShowCurrentRoomBounds; + set + { + _config.Rendering3D_AlwaysShowCurrentRoomBounds = value; + NotifyPropertyChanged(nameof(Rendering3D_AlwaysShowCurrentRoomBounds)); + } + } + + public bool Rendering3D_SelectObjectsInAnyRoom + { + get => _config.Rendering3D_SelectObjectsInAnyRoom; + set + { + _config.Rendering3D_SelectObjectsInAnyRoom = value; + NotifyPropertyChanged(nameof(Rendering3D_SelectObjectsInAnyRoom)); + } + } + + public bool Rendering3D_AutoswitchCurrentRoom + { + get => _config.Rendering3D_AutoswitchCurrentRoom; + set + { + _config.Rendering3D_AutoswitchCurrentRoom = value; + NotifyPropertyChanged(nameof(Rendering3D_AutoswitchCurrentRoom)); + } + } + + public bool Rendering3D_AutoBookmarkSelectedObject + { + get => _config.Rendering3D_AutoBookmarkSelectedObject; + set + { + _config.Rendering3D_AutoBookmarkSelectedObject = value; + NotifyPropertyChanged(nameof(Rendering3D_AutoBookmarkSelectedObject)); + } + } + + public bool Rendering3D_CursorWarping + { + get => _config.Rendering3D_CursorWarping; + set + { + _config.Rendering3D_CursorWarping = value; + NotifyPropertyChanged(nameof(Rendering3D_CursorWarping)); + } + } + + public int Rendering3D_FlyModeMoveSpeed + { + get => _config.Rendering3D_FlyModeMoveSpeed; + set + { + _config.Rendering3D_FlyModeMoveSpeed = value; + NotifyPropertyChanged(nameof(Rendering3D_FlyModeMoveSpeed)); + } + } + + public bool Rendering3D_ShowLightRadius + { + get => _config.Rendering3D_ShowLightRadius; + set + { + _config.Rendering3D_ShowLightRadius = value; + NotifyPropertyChanged(nameof(Rendering3D_ShowLightRadius)); + } + } + + public bool Rendering3D_HighQualityLightPreview + { + get => _config.Rendering3D_HighQualityLightPreview; + set + { + _config.Rendering3D_HighQualityLightPreview = value; + NotifyPropertyChanged(nameof(Rendering3D_HighQualityLightPreview)); + } + } + + public bool Rendering3D_ShowRealTintForObjects + { + get => _config.Rendering3D_ShowRealTintForObjects; + set + { + _config.Rendering3D_ShowRealTintForObjects = value; + NotifyPropertyChanged(nameof(Rendering3D_ShowRealTintForObjects)); + } + } + + public bool Rendering3D_UseSpritesForServiceObjects + { + get => _config.Rendering3D_UseSpritesForServiceObjects; + set + { + _config.Rendering3D_UseSpritesForServiceObjects = value; + NotifyPropertyChanged(nameof(Rendering3D_UseSpritesForServiceObjects)); + } + } + + // 2D Map options + + public float Map2D_NavigationMinZoom + { + get => _config.Map2D_NavigationMinZoom; + set + { + _config.Map2D_NavigationMinZoom = value; + NotifyPropertyChanged(nameof(Map2D_NavigationMinZoom)); + } + } + + public float Map2D_NavigationMaxZoom + { + get => _config.Map2D_NavigationMaxZoom; + set + { + _config.Map2D_NavigationMaxZoom = value; + NotifyPropertyChanged(nameof(Map2D_NavigationMaxZoom)); + } + } + + public float Map2D_NavigationSpeedMouseWheelZoom + { + get => _config.Map2D_NavigationSpeedMouseWheelZoom; + set + { + _config.Map2D_NavigationSpeedMouseWheelZoom = value; + NotifyPropertyChanged(nameof(Map2D_NavigationSpeedMouseWheelZoom)); + } + } + + public float Map2D_NavigationSpeedMouseZoom + { + get => _config.Map2D_NavigationSpeedMouseZoom; + set + { + _config.Map2D_NavigationSpeedMouseZoom = value; + NotifyPropertyChanged(nameof(Map2D_NavigationSpeedMouseZoom)); + } + } + + public float Map2D_NavigationSpeedKeyZoom + { + get => _config.Map2D_NavigationSpeedKeyZoom; + set + { + _config.Map2D_NavigationSpeedKeyZoom = value; + NotifyPropertyChanged(nameof(Map2D_NavigationSpeedKeyZoom)); + } + } + + public float Map2D_NavigationSpeedKeyMove + { + get => _config.Map2D_NavigationSpeedKeyMove; + set + { + _config.Map2D_NavigationSpeedKeyMove = value; + NotifyPropertyChanged(nameof(Map2D_NavigationSpeedKeyMove)); + } + } + + public int Map2D_ShowTimes + { + get => _config.Map2D_ShowTimes; + set + { + _config.Map2D_ShowTimes = value; + NotifyPropertyChanged(nameof(Map2D_ShowTimes)); + } + } + + // Texture map options + + public float TextureMap_NavigationMinZoom + { + get => _config.TextureMap_NavigationMinZoom; + set + { + _config.TextureMap_NavigationMinZoom = value; + NotifyPropertyChanged(nameof(TextureMap_NavigationMinZoom)); + } + } + + public float TextureMap_NavigationMaxZoom + { + get => _config.TextureMap_NavigationMaxZoom; + set + { + _config.TextureMap_NavigationMaxZoom = value; + NotifyPropertyChanged(nameof(TextureMap_NavigationMaxZoom)); + } + } + + public float TextureMap_NavigationSpeedMouseWheelZoom + { + get => _config.TextureMap_NavigationSpeedMouseWheelZoom; + set + { + _config.TextureMap_NavigationSpeedMouseWheelZoom = value; + NotifyPropertyChanged(nameof(TextureMap_NavigationSpeedMouseWheelZoom)); + } + } + + public float TextureMap_NavigationSpeedMouseZoom + { + get => _config.TextureMap_NavigationSpeedMouseZoom; + set + { + _config.TextureMap_NavigationSpeedMouseZoom = value; + NotifyPropertyChanged(nameof(TextureMap_NavigationSpeedMouseZoom)); + } + } + + public float TextureMap_NavigationSpeedKeyZoom + { + get => _config.TextureMap_NavigationSpeedKeyZoom; + set + { + _config.TextureMap_NavigationSpeedKeyZoom = value; + NotifyPropertyChanged(nameof(TextureMap_NavigationSpeedKeyZoom)); + } + } + + public float TextureMap_NavigationSpeedKeyMove + { + get => _config.TextureMap_NavigationSpeedKeyMove; + set + { + _config.TextureMap_NavigationSpeedKeyMove = value; + NotifyPropertyChanged(nameof(TextureMap_NavigationSpeedKeyMove)); + } + } + + public bool TextureMap_DrawSelectionDirectionIndicators + { + get => _config.TextureMap_DrawSelectionDirectionIndicators; + set + { + _config.TextureMap_DrawSelectionDirectionIndicators = value; + NotifyPropertyChanged(nameof(TextureMap_DrawSelectionDirectionIndicators)); + } + } + + public bool TextureMap_MouseWheelMovesTheTextureInsteadOfZooming + { + get => _config.TextureMap_MouseWheelMovesTheTextureInsteadOfZooming; + set + { + _config.TextureMap_MouseWheelMovesTheTextureInsteadOfZooming = value; + NotifyPropertyChanged(nameof(TextureMap_MouseWheelMovesTheTextureInsteadOfZooming)); + } + } + + public bool TextureMap_PickTextureWithoutAttributes + { + get => _config.TextureMap_PickTextureWithoutAttributes; + set + { + _config.TextureMap_PickTextureWithoutAttributes = value; + NotifyPropertyChanged(nameof(TextureMap_PickTextureWithoutAttributes)); + } + } + + public float TextureMap_TileSelectionSize + { + get => _config.TextureMap_TileSelectionSize; + set + { + _config.TextureMap_TileSelectionSize = value; + NotifyPropertyChanged(nameof(TextureMap_TileSelectionSize)); + } + } + + public bool TextureMap_ResetAttributesOnNewSelection + { + get => _config.TextureMap_ResetAttributesOnNewSelection; + set + { + _config.TextureMap_ResetAttributesOnNewSelection = value; + NotifyPropertyChanged(nameof(TextureMap_ResetAttributesOnNewSelection)); + } + } + + public bool TextureMap_WarnAboutIncorrectAttributes + { + get => _config.TextureMap_WarnAboutIncorrectAttributes; + set + { + _config.TextureMap_WarnAboutIncorrectAttributes = value; + NotifyPropertyChanged(nameof(TextureMap_WarnAboutIncorrectAttributes)); + } + } + + // Palette options + + public bool Palette_TextureSamplingMode + { + get => _config.Palette_TextureSamplingMode; + set + { + _config.Palette_TextureSamplingMode = value; + NotifyPropertyChanged(nameof(Palette_TextureSamplingMode)); + } + } + + public bool Palette_PickColorFromSelectedObject + { + get => _config.Palette_PickColorFromSelectedObject; + set + { + _config.Palette_PickColorFromSelectedObject = value; + NotifyPropertyChanged(nameof(Palette_PickColorFromSelectedObject)); + } + } + + // Node editor options + + public int NodeEditor_Size + { + get => _config.NodeEditor_Size; + set + { + _config.NodeEditor_Size = value; + NotifyPropertyChanged(nameof(NodeEditor_Size)); + } + } + + public int NodeEditor_DefaultNodeWidth + { + get => _config.NodeEditor_DefaultNodeWidth; + set + { + _config.NodeEditor_DefaultNodeWidth = value; + NotifyPropertyChanged(nameof(NodeEditor_DefaultNodeWidth)); + } + } + + public int NodeEditor_GridStep + { + get => _config.NodeEditor_GridStep; + set + { + _config.NodeEditor_GridStep = value; + NotifyPropertyChanged(nameof(NodeEditor_GridStep)); + } + } + + public bool NodeEditor_LinksAsRopes + { + get => _config.NodeEditor_LinksAsRopes; + set + { + _config.NodeEditor_LinksAsRopes = value; + NotifyPropertyChanged(nameof(NodeEditor_LinksAsRopes)); + } + } + + public bool NodeEditor_ShowGrips + { + get => _config.NodeEditor_ShowGrips; + set + { + _config.NodeEditor_ShowGrips = value; + NotifyPropertyChanged(nameof(NodeEditor_ShowGrips)); + } + } + + public int NodeEditor_DefaultEventMode + { + get => _config.NodeEditor_DefaultEventMode; + set + { + _config.NodeEditor_DefaultEventMode = value; + NotifyPropertyChanged(nameof(NodeEditor_DefaultEventMode)); + } + } + + public int NodeEditor_DefaultEventToEdit + { + get => _config.NodeEditor_DefaultEventToEdit; + set + { + _config.NodeEditor_DefaultEventToEdit = value; + NotifyPropertyChanged(nameof(NodeEditor_DefaultEventToEdit)); + } + } + + // Gizmo options + + public float Gizmo_Size + { + get => _config.Gizmo_Size; + set + { + _config.Gizmo_Size = value; + NotifyPropertyChanged(nameof(Gizmo_Size)); + } + } + + public float Gizmo_TranslationConeSize + { + get => _config.Gizmo_TranslationConeSize; + set + { + _config.Gizmo_TranslationConeSize = value; + NotifyPropertyChanged(nameof(Gizmo_TranslationConeSize)); + } + } + + public float Gizmo_CenterCubeSize + { + get => _config.Gizmo_CenterCubeSize; + set + { + _config.Gizmo_CenterCubeSize = value; + NotifyPropertyChanged(nameof(Gizmo_CenterCubeSize)); + } + } + + public float Gizmo_ScaleCubeSize + { + get => _config.Gizmo_ScaleCubeSize; + set + { + _config.Gizmo_ScaleCubeSize = value; + NotifyPropertyChanged(nameof(Gizmo_ScaleCubeSize)); + } + } + + public float Gizmo_LineThickness + { + get => _config.Gizmo_LineThickness; + set + { + _config.Gizmo_LineThickness = value; + NotifyPropertyChanged(nameof(Gizmo_LineThickness)); + } + } + + // Autosave options + + public bool AutoSave_Enable + { + get => _config.AutoSave_Enable; + set + { + _config.AutoSave_Enable = value; + NotifyPropertyChanged(nameof(AutoSave_Enable)); + } + } + + public int AutoSave_TimeInSeconds + { + get => _config.AutoSave_TimeInSeconds; + set + { + _config.AutoSave_TimeInSeconds = value; + NotifyPropertyChanged(nameof(AutoSave_TimeInSeconds)); + } + } + + public string AutoSave_DateTimeFormat + { + get => _config.AutoSave_DateTimeFormat; + set + { + _config.AutoSave_DateTimeFormat = value; + NotifyPropertyChanged(nameof(AutoSave_DateTimeFormat)); + } + } + + public bool AutoSave_CleanupEnable + { + get => _config.AutoSave_CleanupEnable; + set + { + _config.AutoSave_CleanupEnable = value; + NotifyPropertyChanged(nameof(AutoSave_CleanupEnable)); + } + } + + public int AutoSave_CleanupMaxAutoSaves + { + get => _config.AutoSave_CleanupMaxAutoSaves; + set + { + _config.AutoSave_CleanupMaxAutoSaves = value; + NotifyPropertyChanged(nameof(AutoSave_CleanupMaxAutoSaves)); + } + } + + public bool AutoSave_NamePutDateFirst + { + get => _config.AutoSave_NamePutDateFirst; + set + { + _config.AutoSave_NamePutDateFirst = value; + NotifyPropertyChanged(nameof(AutoSave_NamePutDateFirst)); + } + } + + public string AutoSave_NameSeparator + { + get => _config.AutoSave_NameSeparator; + set + { + _config.AutoSave_NameSeparator = value; + NotifyPropertyChanged(nameof(AutoSave_NameSeparator)); + } + } + + // User interface options + + public bool UI_ShowStats + { + get => _config.UI_ShowStats; + set + { + _config.UI_ShowStats = value; + NotifyPropertyChanged(nameof(UI_ShowStats)); + } + } + + public bool UI_AutoFillTriggerTypesForSwitchAndKey + { + get => _config.UI_AutoFillTriggerTypesForSwitchAndKey; + set + { + _config.UI_AutoFillTriggerTypesForSwitchAndKey = value; + NotifyPropertyChanged(nameof(UI_AutoFillTriggerTypesForSwitchAndKey)); + } + } + + public bool UI_AutoSwitchRoomToOutsideOnAppliedInvisibleTexture + { + get => _config.UI_AutoSwitchRoomToOutsideOnAppliedInvisibleTexture; + set + { + _config.UI_AutoSwitchRoomToOutsideOnAppliedInvisibleTexture = value; + NotifyPropertyChanged(nameof(UI_AutoSwitchRoomToOutsideOnAppliedInvisibleTexture)); + } + } + + public bool UI_DiscardSelectionOnModeSwitch + { + get => _config.UI_DiscardSelectionOnModeSwitch; + set + { + _config.UI_DiscardSelectionOnModeSwitch = value; + NotifyPropertyChanged(nameof(UI_DiscardSelectionOnModeSwitch)); + } + } + + public bool UI_ProbeAttributesThroughPortals + { + get => _config.UI_ProbeAttributesThroughPortals; + set + { + _config.UI_ProbeAttributesThroughPortals = value; + NotifyPropertyChanged(nameof(UI_ProbeAttributesThroughPortals)); + } + } + + public bool UI_SetAttributesAtOnce + { + get => _config.UI_SetAttributesAtOnce; + set + { + _config.UI_SetAttributesAtOnce = value; + NotifyPropertyChanged(nameof(UI_SetAttributesAtOnce)); + } + } + + public bool UI_OnlyShowSmallMessageWhenRoomIsLocked + { + get => _config.UI_OnlyShowSmallMessageWhenRoomIsLocked; + set + { + _config.UI_OnlyShowSmallMessageWhenRoomIsLocked = value; + NotifyPropertyChanged(nameof(UI_OnlyShowSmallMessageWhenRoomIsLocked)); + } + } + + public bool UI_WarnBeforeDeletingObjects + { + get => _config.UI_WarnBeforeDeletingObjects; + set + { + _config.UI_WarnBeforeDeletingObjects = value; + NotifyPropertyChanged(nameof(UI_WarnBeforeDeletingObjects)); + } + } + + public bool UI_GenerateRoomDescriptions + { + get => _config.UI_GenerateRoomDescriptions; + set + { + _config.UI_GenerateRoomDescriptions = value; + NotifyPropertyChanged(nameof(UI_GenerateRoomDescriptions)); + } + } + + public bool UI_AutoSwitchSectorColoringInfo + { + get => _config.UI_AutoSwitchSectorColoringInfo; + set + { + _config.UI_AutoSwitchSectorColoringInfo = value; + NotifyPropertyChanged(nameof(UI_AutoSwitchSectorColoringInfo)); + } + } + + public float UI_FormColor_Brightness { get; set; } = 100.0f; + public string UI_FormColor_ButtonHighlight { get; set; } = ColorTranslator.ToHtml(Color.FromArgb(104, 151, 187)); + + public ColorScheme UI_ColorScheme + { + get => _config.UI_ColorScheme; + set + { + if (value == null) + return; + + _config.UI_ColorScheme = value; + Color2DBackground = value.Color2DBackground; + ColorSelection = value.ColorSelection; + ColorIllegalSlope = value.ColorIllegalSlope; + ColorSlideDirection = value.ColorSlideDirection; + Color3DBackground = value.Color3DBackground; + ColorFlipRoom = value.ColorFlipRoom; + ColorPortal = value.ColorPortal; + ColorPortalFace = value.ColorPortalFace; + ColorFloor = value.ColorFloor; + ColorBorderWall = value.ColorBorderWall; + ColorWall = value.ColorWall; + ColorWallLower = value.ColorWallLower; + ColorWallUpper = value.ColorWallUpper; + ColorTrigger = value.ColorTrigger; + ColorMonkey = value.ColorMonkey; + ColorClimb = value.ColorClimb; + ColorBox = value.ColorBox; + ColorDeath = value.ColorDeath; + ColorNotWalkable = value.ColorNotWalkable; + ColorBeetle = value.ColorBeetle; + ColorTriggerTriggerer = value.ColorTriggerTriggerer; + ColorForceSolidFloor = value.ColorForceSolidFloor; + Color2DRoomsAbove = value.Color2DRoomsAbove; + Color2DRoomsBelow = value.Color2DRoomsBelow; + Color2DRoomsMoved = value.Color2DRoomsMoved; + } + } + + public HotkeySets UI_Hotkeys + { + get => _config.UI_Hotkeys; + set + { + _config.UI_Hotkeys = value; + NotifyPropertyChanged(nameof(UI_Hotkeys)); + } + } + + public IEnumerable> ColorSchemePresets + { + get => new Dictionary() + { + {"Default",ColorScheme.Default }, + {"Gray",ColorScheme.Gray }, + {"Dark",ColorScheme.Dark }, + {"Pastel",ColorScheme.Pastel }, + }.ToList(); + } + + public IEnumerable NodeEditorDefaultModes => new ReadOnlyCollection(new string[] { "Level script functions", "Node editor" }); + public IEnumerable NodeEditorDefaultEvents => new ReadOnlyCollection(new string[] { "On enter", "On inside", "On leave" }); + + #endregion Properties + + #region ColorProperties + + public Vector4 ColorSelection + { + get => _config.UI_ColorScheme.ColorSelection; + set + { + _config.UI_ColorScheme.ColorSelection = value; + NotifyPropertyChanged(nameof(ColorSelection)); + } + } + + public Vector4 ColorIllegalSlope + { + get => _config.UI_ColorScheme.ColorIllegalSlope; + set + { + _config.UI_ColorScheme.ColorIllegalSlope = value; + NotifyPropertyChanged(nameof(ColorIllegalSlope)); + } + } + + public Vector4 ColorSlideDirection + { + get => _config.UI_ColorScheme.ColorSlideDirection; + set + { + _config.UI_ColorScheme.ColorSlideDirection = value; + NotifyPropertyChanged(nameof(ColorSlideDirection)); + } + } + + public Vector4 Color3DBackground + { + get => _config.UI_ColorScheme.Color3DBackground; + set + { + _config.UI_ColorScheme.Color3DBackground = value; + NotifyPropertyChanged(nameof(Color3DBackground)); + } + } + + public Vector4 Color2DBackground + { + get => _config.UI_ColorScheme.Color2DBackground; + set + { + _config.UI_ColorScheme.Color2DBackground = value; + NotifyPropertyChanged(nameof(Color2DBackground)); + } + } + + public Vector4 ColorFlipRoom + { + get => _config.UI_ColorScheme.ColorFlipRoom; + set + { + _config.UI_ColorScheme.ColorFlipRoom = value; + NotifyPropertyChanged(nameof(ColorFlipRoom)); + } + } + + public Vector4 ColorPortal + { + get => _config.UI_ColorScheme.ColorPortal; + set + { + _config.UI_ColorScheme.ColorPortal = value; + NotifyPropertyChanged(nameof(ColorPortal)); + } + } + + public Vector4 ColorPortalFace + { + get => _config.UI_ColorScheme.ColorPortalFace; + set + { + _config.UI_ColorScheme.ColorPortalFace = value; + NotifyPropertyChanged(nameof(ColorPortalFace)); + } + } + + public Vector4 ColorFloor + { + get => _config.UI_ColorScheme.ColorFloor; + set + { + _config.UI_ColorScheme.ColorFloor = value; + NotifyPropertyChanged(nameof(ColorFloor)); + } + } + + public Vector4 ColorBorderWall + { + get => _config.UI_ColorScheme.ColorBorderWall; + set + { + _config.UI_ColorScheme.ColorBorderWall = value; + NotifyPropertyChanged(nameof(ColorBorderWall)); + } + } + + public Vector4 ColorWall + { + get => _config.UI_ColorScheme.ColorWall; + set + { + _config.UI_ColorScheme.ColorWall = value; + NotifyPropertyChanged(nameof(ColorWall)); + } + } + + public Vector4 ColorWallLower + { + get => _config.UI_ColorScheme.ColorWallLower; + set + { + _config.UI_ColorScheme.ColorWallLower = value; + NotifyPropertyChanged(nameof(ColorWallLower)); + } + } + + public Vector4 ColorWallUpper + { + get => _config.UI_ColorScheme.ColorWallUpper; + set + { + _config.UI_ColorScheme.ColorWallUpper = value; + NotifyPropertyChanged(nameof(ColorWallUpper)); + } + } + + public Vector4 ColorTrigger + { + get => _config.UI_ColorScheme.ColorTrigger; + set + { + _config.UI_ColorScheme.ColorTrigger = value; + NotifyPropertyChanged(nameof(ColorTrigger)); + } + } + + public Vector4 ColorMonkey + { + get => _config.UI_ColorScheme.ColorMonkey; + set + { + _config.UI_ColorScheme.ColorMonkey = value; + NotifyPropertyChanged(nameof(ColorMonkey)); + } + } + + public Vector4 ColorClimb + { + get => _config.UI_ColorScheme.ColorClimb; + set + { + _config.UI_ColorScheme.ColorClimb = value; + NotifyPropertyChanged(nameof(ColorClimb)); + } + } + + public Vector4 ColorBox + { + get => _config.UI_ColorScheme.ColorBox; + set + { + _config.UI_ColorScheme.ColorBox = value; + NotifyPropertyChanged(nameof(ColorBox)); + } + } + + public Vector4 ColorDeath + { + get => _config.UI_ColorScheme.ColorDeath; + set + { + _config.UI_ColorScheme.ColorDeath = value; + NotifyPropertyChanged(nameof(ColorDeath)); + } + } + + public Vector4 ColorNotWalkable + { + get => _config.UI_ColorScheme.ColorNotWalkable; + set + { + _config.UI_ColorScheme.ColorNotWalkable = value; + NotifyPropertyChanged(nameof(ColorNotWalkable)); + } + } + + public Vector4 ColorBeetle + { + get => _config.UI_ColorScheme.ColorBeetle; + set + { + _config.UI_ColorScheme.ColorBeetle = value; + NotifyPropertyChanged(nameof(ColorBeetle)); + } + } + + public Vector4 ColorTriggerTriggerer + { + get => _config.UI_ColorScheme.ColorTriggerTriggerer; + set + { + _config.UI_ColorScheme.ColorTriggerTriggerer = value; + NotifyPropertyChanged(nameof(ColorTriggerTriggerer)); + } + } + + public Vector4 ColorForceSolidFloor + { + get => _config.UI_ColorScheme.ColorForceSolidFloor; + set + { + _config.UI_ColorScheme.ColorForceSolidFloor = value; + NotifyPropertyChanged(nameof(ColorForceSolidFloor)); + } + } + + public Vector4 Color2DRoomsAbove + { + get => _config.UI_ColorScheme.Color2DRoomsAbove; + set + { + _config.UI_ColorScheme.Color2DRoomsAbove = value; + NotifyPropertyChanged(nameof(Color2DRoomsAbove)); + } + } + + public Vector4 Color2DRoomsBelow + { + get => _config.UI_ColorScheme.Color2DRoomsBelow; + set + { + _config.UI_ColorScheme.Color2DRoomsBelow = value; + NotifyPropertyChanged(nameof(Color2DRoomsBelow)); + } + } + + public Vector4 Color2DRoomsMoved + { + get => _config.UI_ColorScheme.Color2DRoomsMoved; + set + { + _config.UI_ColorScheme.Color2DRoomsMoved = value; + NotifyPropertyChanged(nameof(Color2DRoomsMoved)); + } + } + + #endregion ColorProperties + + public OptionsViewModel(Configuration config) + { + _config = config; + } + } +} diff --git a/TombEditor/WPF/ViewModels/PaletteViewModel.cs b/TombEditor/WPF/ViewModels/PaletteViewModel.cs new file mode 100644 index 0000000000..cde56463e2 --- /dev/null +++ b/TombEditor/WPF/ViewModels/PaletteViewModel.cs @@ -0,0 +1,67 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using System.Collections.Generic; +using System.Windows.Input; +using TombLib.LevelData; +using TombLib.Utils; + +namespace TombEditor.WPF.ViewModels; + +public partial class PaletteViewModel : ObservableObject +{ + private readonly Editor _editor; + + [ObservableProperty] private bool _isTextureSamplingMode; + [ObservableProperty] private bool _canResetPalette; + [ObservableProperty] private bool _canEditPalette; + [ObservableProperty] private bool _canEditColor; + + public ICommand ResetPaletteCommand { get; } + public ICommand SampleFromTexturesCommand { get; } + public ICommand EditObjectColorCommand { get; } + + private List _lastTexturePalette; + + public PaletteViewModel(Editor editor) + { + _editor = editor; + _editor.EditorEventRaised += EditorEventRaised; + + var args = new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor); + ResetPaletteCommand = CommandHandler.GetCommand("ResetPalette", args); + SampleFromTexturesCommand = CommandHandler.GetCommand("SamplePaletteFromTextures", args); + EditObjectColorCommand = CommandHandler.GetCommand("EditObjectColor", args); + + UpdateControlState(); + } + + public void Cleanup() + { + _editor.EditorEventRaised -= EditorEventRaised; + } + + private void EditorEventRaised(IEditorEvent obj) + { + if (obj is Editor.SelectedObjectChangedEvent selectedObjChanged) + CanEditColor = selectedObjChanged.Current.CanBeColored(); + + if (obj is Editor.SelectedLevelTextureChangedSetEvent textureChanged) + { + _lastTexturePalette = new List(textureChanged.Texture.Image.Palette); + UpdateControlState(); + } + + if (obj is Editor.ConfigurationChangedEvent) + UpdateControlState(); + } + + public List GetLastTexturePalette() => _lastTexturePalette; + + private void UpdateControlState() + { + bool useTexture = _editor.Configuration.Palette_TextureSamplingMode; + + IsTextureSamplingMode = useTexture; + CanResetPalette = !useTexture; + CanEditPalette = !useTexture; + } +} diff --git a/TombEditor/WPF/ViewModels/RoomOptionsViewModel.cs b/TombEditor/WPF/ViewModels/RoomOptionsViewModel.cs new file mode 100644 index 0000000000..f5d55455bd --- /dev/null +++ b/TombEditor/WPF/ViewModels/RoomOptionsViewModel.cs @@ -0,0 +1,519 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Windows.Input; +using System.Windows.Media; +using TombLib.Forms; +using TombLib.LevelData; +using TombLib.WPF; + +namespace TombEditor.WPF.ViewModels; + +public partial class RoomOptionsViewModel : ObservableObject +{ + public IEnumerable Rooms => _editor.Level.Rooms + .Select((room, index) => $"{index}: {room?.Name ?? Localizer.Instance["EmptyRoom"]}"); + + public IEnumerable RoomTypes + { + get + { + var result = new List + { + "Normal", + "Water" + }; + + if (_editor.Level.Settings.GameVersion == TRVersion.Game.TR3 || + _editor.Level.IsTRX || + _editor.Level.IsNG || + _editor.Level.IsTombEngine) + result.Add("Quicksand"); + + if (_editor.Level.IsNG) + StringEnums.NGRoomTypes.ForEach(result.Add); + + return result; + } + } + + public IEnumerable ReverbValues + => _editor.Level.Settings.GameVersion.Native() == TRVersion.Game.TR4 && _editor.Level.Settings.GameEnableExtraReverbPresets + ? StringEnums.ExtraReverberationTypes + : StringEnums.ReverberationTypes; + + public IEnumerable PortalShades => new List + { + "Default", + "Smooth", + "Sharp" + }; + + public IEnumerable Effects + { + get + { + bool isTR2 = _editor.Level.Settings.GameVersion is TRVersion.Game.TR2; + + return new List + { + "None", + "Default", + "Reflection", + "Glow", + isTR2 ? "Flicker" : "Move", + isTR2 ? "Sunset" : "Glow & Move", + "Mist" + }; + } + } + + public int SelectedRoom + { + get => Array.IndexOf(_editor.Level.Rooms, _editor.SelectedRoom); + set + { + if (value == -1) + return; + + Room selectedRoom = _editor.Level.Rooms[value]; + + if (selectedRoom is null) + EditorActions.MakeNewRoom(value); + else + _editor.SelectRoom(selectedRoom); + } + } + + public string Tags + { + get => string.Join(' ', _editor.SelectedRoom.Properties.Tags); + set + { + if (_editor.SelectedRoom is null) + return; + + _editor.SelectedRoom.Properties.Tags = value.Split(' ', StringSplitOptions.RemoveEmptyEntries).ToList(); + _editor.RoomPropertiesChange(_editor.SelectedRoom); + + OnPropertyChanged(nameof(TagsAutoCompleteData)); + } + } + + public bool Skybox + { + get => _editor.SelectedRoom.Properties.FlagHorizon; + set + { + _editor.SelectedRoom.Properties.FlagHorizon = value; + _editor.RoomPropertiesChange(_editor.SelectedRoom); + } + } + + public bool Wind + { + get => _editor.SelectedRoom.Properties.FlagOutside; + set + { + _editor.SelectedRoom.Properties.FlagOutside = value; + _editor.RoomPropertiesChange(_editor.SelectedRoom); + } + } + + public bool Damage + { + get => _editor.SelectedRoom.Properties.FlagDamage; + set + { + _editor.SelectedRoom.Properties.FlagDamage = value; + _editor.RoomPropertiesChange(_editor.SelectedRoom); + } + } + + public bool Cold + { + get => _editor.SelectedRoom.Properties.FlagCold; + set + { + _editor.SelectedRoom.Properties.FlagCold = value; + _editor.RoomPropertiesChange(_editor.SelectedRoom); + } + } + + public bool NoPathfinding + { + get => _editor.SelectedRoom.Properties.FlagExcludeFromPathFinding; + set + { + _editor.SelectedRoom.Properties.FlagExcludeFromPathFinding = value; + _editor.RoomPropertiesChange(_editor.SelectedRoom); + } + } + + public bool NoLensflare + { + get => _editor.SelectedRoom.Properties.FlagNoLensflare; + set + { + _editor.SelectedRoom.Properties.FlagNoLensflare = value; + _editor.RoomPropertiesChange(_editor.SelectedRoom); + } + } + + public bool NoCaustics + { + get => _editor.SelectedRoom.Properties.FlagNoCaustics; + set + { + _editor.SelectedRoom.Properties.FlagNoCaustics = value; + _editor.RoomPropertiesChange(_editor.SelectedRoom); + } + } + + public int SelectedRoomType + { + get + { + Room room = _editor.SelectedRoom; + + // Cleverly switch room types dependent on game version. + // We disable rain/snow types for TombEngine because it is expected to set these options with triggers and/or script. + + int roomType; + + if (room.Properties.Type is RoomType.Quicksand && + _editor.Level.Settings.GameVersion is not TRVersion.Game.TR3 and not TRVersion.Game.TRNG and not TRVersion.Game.TombEngine && + !_editor.Level.IsTRX) + roomType = -1; + else if (room.Properties.Type is RoomType.Rain or RoomType.Snow && _editor.Level.Settings.GameVersion is not TRVersion.Game.TRNG) + roomType = -1; + else + { + roomType = room.Properties.Type switch + { + RoomType.Normal => 0, + RoomType.Water => 1, + RoomType.Quicksand => 2, + RoomType.Rain => 3 + room.Properties.TypeStrength, + RoomType.Snow => 7 + room.Properties.TypeStrength, + _ => -1 + }; + } + + // If selected type is -1 it means this room type is unsupported in current version. Throw a message about it. + if (roomType == -1) + _editor.SendMessage("Current room type is not supported in this engine version.\nChange it manually or switch engine version.", PopupType.Warning); + + return roomType; + } + set + { + RoomType newType; + byte newStrength = 0; + + switch (value) + { + case -1: + // Wrong type, do nothing + return; + + case 0: + newType = RoomType.Normal; + break; + + case 1: + newType = RoomType.Water; + break; + + case 2: + newType = RoomType.Quicksand; + break; + + default: + if (value <= 6) + { + newType = RoomType.Rain; + newStrength = (byte)(value - 3); + } + else + { + newType = RoomType.Snow; + newStrength = (byte)(value - 7); + } + + break; + } + + if (_editor.SelectedRoom.Properties.Type != newType || _editor.SelectedRoom.Properties.TypeStrength != newStrength) + { + _editor.SelectedRoom.Properties.Type = newType; + _editor.SelectedRoom.Properties.TypeStrength = newStrength; + _editor.RoomPropertiesChange(_editor.SelectedRoom); + } + } + } + + public int SelectedFlipMap + { + get + { + Room room = _editor.SelectedRoom; + + if (!room.Alternated) + return 0; + + int index = room.AlternateGroup + 1; + return index < FlipMaps.Count ? index : -1; + } + set + { + if (_editor.SelectedRoom is null) + return; + + Room room = _editor.SelectedRoom; + short alternateGroupIndex = (short)(value - 1); + + if (room.Alternated) + { + if (alternateGroupIndex == -1) + { + // Delete flipped room + EditorActions.AlternateRoomDisableWithWarning(room, WPFUtils.GetWin32WindowFromCaller(this)); + } + else + { + // Change flipped map number, not much to do here + if (room.AlternateGroup != alternateGroupIndex && + room.AlternateOpposite.AlternateGroup != alternateGroupIndex) + { + room.AlternateGroup = alternateGroupIndex; + room.AlternateOpposite.AlternateGroup = alternateGroupIndex; + _editor.RoomPropertiesChange(room); + _editor.RoomPropertiesChange(room.AlternateOpposite); + } + } + } + else if (alternateGroupIndex != -1) + { + // Create a new flipped room + EditorActions.AlternateRoomEnable(room, alternateGroupIndex); + } + + // Update combo box even if nothing changed internally + // to correct invalid user input + EditorEventRaised(new Editor.RoomPropertiesChangedEvent { Room = room }); + } + } + + public int SelectedReverb + { + get => _editor.SelectedRoom.Properties.Reverberation; + set + { + if (_editor.SelectedRoom.Properties.Reverberation == value) + return; + + _editor.SelectedRoom.Properties.Reverberation = (byte)value; + _editor.RoomPropertiesChange(_editor.SelectedRoom); + } + } + + public int SelectedPortalShade + { + get => (int)_editor.SelectedRoom.Properties.LightInterpolationMode; + set + { + if (_editor.SelectedRoom.Properties.LightInterpolationMode == (RoomLightInterpolationMode)value) + return; + + _editor.SelectedRoom.Properties.LightInterpolationMode = (RoomLightInterpolationMode)value; + _editor.RoomPropertiesChange(_editor.SelectedRoom); + } + } + + public int SelectedEffect + { + get => (int)_editor.SelectedRoom.Properties.LightEffect; + set + { + if (_editor.SelectedRoom.Properties.LightEffect == (RoomLightEffect)value) + return; + + _editor.SelectedRoom.Properties.LightEffect = (RoomLightEffect)value; + _editor.RoomPropertiesChange(_editor.SelectedRoom); + } + } + + public byte EffectStrength + { + get => _editor.SelectedRoom.Properties.LightEffectStrength; + set + { + _editor.SelectedRoom.Properties.LightEffectStrength = value; + _editor.RoomPropertiesChange(_editor.SelectedRoom); + } + } + + public IReadOnlyList TagsAutoCompleteData => _editor.Level.Rooms + .Where(room => room?.ExistsInLevel == true) + .SelectMany(room => room.Properties.Tags) + .Distinct() + .ToList(); + + public bool Hidden => _editor.SelectedRoom.Properties.Hidden; + + public Color AmbientLightColor => _editor.SelectedRoom.Properties.AmbientLight.ToWPFColor(); + + [ObservableProperty] private bool supportsHorizon; + [ObservableProperty] private bool supportsFlagOutside; + [ObservableProperty] private bool supportsFlagCold; + [ObservableProperty] private bool supportsFlagDamage; + [ObservableProperty] private bool supportsNoLensflare; + [ObservableProperty] private bool supportsNoCaustics; + [ObservableProperty] private bool supportsReverb; + [ObservableProperty] private bool supportsLightEffect; + [ObservableProperty] private bool supportsLightEffectStrength; + [ObservableProperty] private bool canLockRoom = true; + + [ObservableProperty] private bool locked; + + public ICommand EditRoomNameCommand { get; } + public ICommand AddNewRoomCommand { get; } + public ICommand DuplicateRoomCommand { get; } + public ICommand DeleteRoomsCommand { get; } + public ICommand CropRoomCommand { get; } + public ICommand MoveRoomUpCommand { get; } + public ICommand SplitRoomCommand { get; } + public ICommand MoveRoomDownCommand { get; } + public ICommand SelectPreviousRoomCommand { get; } + public ICommand LockRoomCommand { get; } + public ICommand HideRoomCommand { get; } + public ICommand EditAmbientLightCommand { get; } + + private readonly Editor _editor; + + public ObservableCollection FlipMaps { get; } = new(); + + public RoomOptionsViewModel(Editor editor) + { + _editor = editor; + _editor.EditorEventRaised += EditorEventRaised; + RepopulateFlipMaps(); + + EditRoomNameCommand = CommandHandler.GetCommand("EditRoomName", new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor)); + AddNewRoomCommand = CommandHandler.GetCommand("AddNewRoom", new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor)); + DuplicateRoomCommand = CommandHandler.GetCommand("DuplicateRoom", new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor)); + DeleteRoomsCommand = CommandHandler.GetCommand("DeleteRooms", new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor)); + CropRoomCommand = CommandHandler.GetCommand("CropRoom", new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor)); + MoveRoomUpCommand = CommandHandler.GetCommand("MoveRoomUp", new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor)); + SplitRoomCommand = CommandHandler.GetCommand("SplitRoom", new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor)); + MoveRoomDownCommand = CommandHandler.GetCommand("MoveRoomDown", new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor)); + SelectPreviousRoomCommand = CommandHandler.GetCommand("SelectPreviousRoom", new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor)); + LockRoomCommand = CommandHandler.GetCommand("LockRoom", new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor)); + HideRoomCommand = CommandHandler.GetCommand("HideRoom", new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor)); + EditAmbientLightCommand = CommandHandler.GetCommand("EditAmbientLight", new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor)); + } + + public void Cleanup() + { + _editor.EditorEventRaised -= EditorEventRaised; + } + + private void RepopulateFlipMaps() + { + int index = FlipMaps.Count > 0 ? FlipMaps.IndexOf(FlipMaps.FirstOrDefault()) : -1; + + FlipMaps.Clear(); + FlipMaps.Add("None"); + + int flipmapCount = _editor.Level.Settings.GameVersion == TRVersion.Game.TombEngine ? byte.MaxValue : 15; + + for (int i = 0; i < flipmapCount; i++) + FlipMaps.Add(i.ToString()); + } + + private void EditorEventRaised(IEditorEvent obj) + { + // Disable version-specific controls. + if (obj is Editor.InitEvent or + Editor.GameVersionChangedEvent or + Editor.LevelChangedEvent) + { + var version = _editor.Level.Settings.GameVersion; + bool isNGorTEN = version is TRVersion.Game.TRNG or TRVersion.Game.TombEngine; + bool isTR1 = version.Native() == TRVersion.Game.TR1; + bool isTEN = version is TRVersion.Game.TombEngine; + + SupportsHorizon = !isTR1 || _editor.Level.IsTRX; + SupportsFlagOutside = !isTR1 || _editor.Level.IsTRX; + SupportsFlagCold = isNGorTEN; + SupportsFlagDamage = isNGorTEN; + SupportsNoLensflare = version.SupportsLensflare(); + SupportsNoCaustics = isTEN; + SupportsReverb = version.SupportsReverberation(); + + OnPropertyChanged(nameof(RoomTypes)); + OnPropertyChanged(nameof(ReverbValues)); + OnPropertyChanged(nameof(Effects)); + RepopulateFlipMaps(); + + SupportsLightEffect = !isTR1; + SupportsLightEffectStrength = !isTR1; + } + + // Update the room list. + if (obj is Editor.InitEvent or Editor.RoomListChangedEvent) + { + int cachedRoomIndex = SelectedRoom; + + OnPropertyChanged(nameof(Rooms)); + + SelectedRoom = cachedRoomIndex; + OnPropertyChanged(nameof(SelectedRoom)); + } + + // Update tag list. + if (obj is Editor.LevelChangedEvent or Editor.SelectedRoomChangedEvent) + OnPropertyChanged(nameof(TagsAutoCompleteData)); + + // Update all room property controls. + if (obj is Editor.InitEvent || obj is Editor.SelectedRoomChangedEvent || obj is Editor.LevelChangedEvent || + _editor.IsSelectedRoomEvent(obj as Editor.RoomPropertiesChangedEvent)) + { + if (obj is Editor.SelectedRoomChangedEvent) + OnPropertyChanged(nameof(SelectedRoom)); + + OnPropertyChanged(nameof(Tags)); + OnPropertyChanged(nameof(Skybox)); + OnPropertyChanged(nameof(Wind)); + OnPropertyChanged(nameof(Damage)); + OnPropertyChanged(nameof(Cold)); + OnPropertyChanged(nameof(NoPathfinding)); + OnPropertyChanged(nameof(NoLensflare)); + OnPropertyChanged(nameof(NoCaustics)); + OnPropertyChanged(nameof(SelectedRoomType)); + OnPropertyChanged(nameof(SelectedFlipMap)); + OnPropertyChanged(nameof(SelectedReverb)); + OnPropertyChanged(nameof(SelectedPortalShade)); + OnPropertyChanged(nameof(SelectedEffect)); + OnPropertyChanged(nameof(EffectStrength)); + OnPropertyChanged(nameof(Hidden)); + OnPropertyChanged(nameof(AmbientLightColor)); + + Room room = _editor.SelectedRoom; + + if (room.AlternateBaseRoom != null) + { + CanLockRoom = false; + Locked = room.AlternateBaseRoom.Properties.Locked; + } + else + { + CanLockRoom = true; + Locked = room.Properties.Locked; + } + } + } +} diff --git a/TombEditor/WPF/ViewModels/SectorOptionsViewModel.cs b/TombEditor/WPF/ViewModels/SectorOptionsViewModel.cs new file mode 100644 index 0000000000..71abe2be53 --- /dev/null +++ b/TombEditor/WPF/ViewModels/SectorOptionsViewModel.cs @@ -0,0 +1,139 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using System.Numerics; +using System.Windows.Input; +using TombLib.LevelData; +using TombLib.Rendering; + +namespace TombEditor.WPF.ViewModels; + +public partial class SectorOptionsViewModel : ObservableObject +{ + [ObservableProperty] private Vector4 floorColor; + [ObservableProperty] private Vector4 boxColor; + [ObservableProperty] private Vector4 notWalkableColor; + [ObservableProperty] private Vector4 monkeyswingColor; + [ObservableProperty] private Vector4 deathColor; + [ObservableProperty] private Vector4 portalColor; + [ObservableProperty] private Vector4 wallColor; + + [ObservableProperty] private bool supportsClimbing; + [ObservableProperty] private bool supportsMonkeySwing; + [ObservableProperty] private bool supportsBeetleCheckpoint; + [ObservableProperty] private bool supportsTriggerTriggerer; + + [ObservableProperty] private string triggerTriggererIcon = TriggerTriggererIconTR4; + [ObservableProperty] private string beetleIcon = BeetleIconTR4; + + private const string TriggerTriggererIconTR4 = "/TombEditor;component/Resources/icons_sectortype/sectortype_TriggerTriggerer-16.png"; + private const string TriggerTriggererIconTR3 = "/TombEditor;component/Resources/icons_sectortype/sectortype_MinecartLeft-16.png"; + private const string BeetleIconTR4 = "/TombEditor;component/Resources/icons_sectortype/sectortype_Beetle-16.png"; + private const string BeetleIconTR3 = "/TombEditor;component/Resources/icons_sectortype/sectortype_MinecartRight-16.png"; + + public ICommand SetFloorCommand { get; } + public ICommand SetCeilingCommand { get; } + public ICommand SetBoxCommand { get; } + public ICommand SetNotWalkableCommand { get; } + public ICommand SetMonkeyswingCommand { get; } + public ICommand SetDeathCommand { get; } + public ICommand AddPortalCommand { get; } + public ICommand SetWallCommand { get; } + public ICommand SetTriggerTriggererCommand { get; } + public ICommand SetBeetleCheckpointCommand { get; } + public ICommand SetClimbPositiveZCommand { get; } + public ICommand SetClimbPositiveXCommand { get; } + public ICommand SetClimbNegativeZCommand { get; } + public ICommand SetClimbNegativeXCommand { get; } + public ICommand AddGhostBlocksToSelectionCommand { get; } + public ICommand ToggleForceFloorSolidCommand { get; } + public ICommand FloorStepCommand { get; } + public ICommand CeilingStepCommand { get; } + public ICommand DiagonalWallCommand { get; } + + private readonly Editor _editor; + + public SectorOptionsViewModel(Editor editor) + { + _editor = editor; + _editor.EditorEventRaised += EditorEventRaised; + + SetFloorCommand = CommandHandler.GetCommand("SetFloor", new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor)); + SetCeilingCommand = CommandHandler.GetCommand("SetCeiling", new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor)); + SetBoxCommand = CommandHandler.GetCommand("SetBox", new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor)); + SetNotWalkableCommand = CommandHandler.GetCommand("SetNotWalkable", new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor)); + SetMonkeyswingCommand = CommandHandler.GetCommand("SetMonkeyswing", new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor)); + SetDeathCommand = CommandHandler.GetCommand("SetDeath", new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor)); + AddPortalCommand = CommandHandler.GetCommand("AddPortal", new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor)); + SetWallCommand = CommandHandler.GetCommand("SetWall", new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor)); + SetTriggerTriggererCommand = CommandHandler.GetCommand("SetTriggerTriggerer", new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor)); + SetBeetleCheckpointCommand = CommandHandler.GetCommand("SetBeetleCheckpoint", new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor)); + SetClimbPositiveZCommand = CommandHandler.GetCommand("SetClimbPositiveZ", new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor)); + SetClimbPositiveXCommand = CommandHandler.GetCommand("SetClimbPositiveX", new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor)); + SetClimbNegativeZCommand = CommandHandler.GetCommand("SetClimbNegativeZ", new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor)); + SetClimbNegativeXCommand = CommandHandler.GetCommand("SetClimbNegativeX", new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor)); + AddGhostBlocksToSelectionCommand = CommandHandler.GetCommand("AddGhostBlocksToSelection", new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor)); + ToggleForceFloorSolidCommand = CommandHandler.GetCommand("ToggleForceFloorSolid", new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor)); + FloorStepCommand = CommandHandler.GetCommand("SetDiagonalFloorStep", new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor)); + CeilingStepCommand = CommandHandler.GetCommand("SetDiagonalCeilingStep", new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor)); + DiagonalWallCommand = CommandHandler.GetCommand("SetDiagonalWall", new CommandArgs(WPFUtils.GetWin32WindowFromCaller(this), _editor)); + + SetButtonColors(); + UpdateVersionSpecificControls(); + } + + public void Cleanup() + { + _editor.EditorEventRaised -= EditorEventRaised; + } + + private void EditorEventRaised(IEditorEvent obj) + { + if (obj is Editor.ConfigurationChangedEvent or Editor.InitEvent) + SetButtonColors(); + + if (obj is Editor.InitEvent or Editor.GameVersionChangedEvent or Editor.LevelChangedEvent) + UpdateVersionSpecificControls(); + } + + private void SetButtonColors() + { + FloorColor = _editor.Configuration.UI_ColorScheme.ColorFloor; + BoxColor = _editor.Configuration.UI_ColorScheme.ColorBox; + NotWalkableColor = _editor.Configuration.UI_ColorScheme.ColorNotWalkable; + MonkeyswingColor = _editor.Configuration.UI_ColorScheme.ColorMonkey; + DeathColor = _editor.Configuration.UI_ColorScheme.ColorDeath; + PortalColor = _editor.Configuration.UI_ColorScheme.ColorPortal; + WallColor = _editor.Configuration.UI_ColorScheme.ColorWall; + } + + private void UpdateVersionSpecificControls() + { + var version = _editor.Level.Settings.GameVersion; + bool isTR345 = version.Native() >= TRVersion.Game.TR3; + + SupportsClimbing = version.SupportsClimbing(); + SupportsMonkeySwing = version.SupportsMonkeySwing(); + SupportsBeetleCheckpoint = isTR345; + SupportsTriggerTriggerer = isTR345; + + if (version.Native() >= TRVersion.Game.TR4) + { + TriggerTriggererIcon = TriggerTriggererIconTR4; + BeetleIcon = BeetleIconTR4; + } + else + { + TriggerTriggererIcon = TriggerTriggererIconTR3; + BeetleIcon = BeetleIconTR3; + } + } + + [RelayCommand] + private void SetSectorColoringInfoPriority(SectorColoringType type) + { + if (!_editor.Configuration.UI_AutoSwitchSectorColoringInfo) + return; + + _editor.SectorColoringManager.SetPriority(type); + } +} diff --git a/TombEditor/WPF/ViewModels/ViewModelBase.cs b/TombEditor/WPF/ViewModels/ViewModelBase.cs new file mode 100644 index 0000000000..2cf752a64b --- /dev/null +++ b/TombEditor/WPF/ViewModels/ViewModelBase.cs @@ -0,0 +1,11 @@ +using System.ComponentModel; + +namespace TombEditor.WPF.ViewModels; + +public class ViewModelBase : INotifyPropertyChanged +{ + public event PropertyChangedEventHandler? PropertyChanged; + + protected void NotifyPropertyChanged(string propertyName) + => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); +} diff --git a/TombEditor/WPF/Views/AnimatedTexturesWindow.xaml b/TombEditor/WPF/Views/AnimatedTexturesWindow.xaml new file mode 100644 index 0000000000..04a0a565e2 --- /dev/null +++ b/TombEditor/WPF/Views/AnimatedTexturesWindow.xaml @@ -0,0 +1,548 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +