From 0882c488c9b5b488094096eeab9ffc0ee55b47a1 Mon Sep 17 00:00:00 2001 From: KillzXGaming Date: Tue, 15 Oct 2019 17:48:52 -0400 Subject: [PATCH] Some more bug fixes Fixed hit detection if the pane has custom scaling. Improve multi selection for panes (uses one selection box) Improve selecting (ctrl can be used properly to multi select, and mosue clicking already selected panes will allow dragging. Fix hash only sarcs to auto generate if name changed or new files added. Fixed texture folders for newly added textures for layouts --- .../FileFormats/Archives/SARC.cs | 65 +++- .../FileFormats/Layout/BxlytToGL.cs | 79 +---- .../FileFormats/Layout/Common.cs | 56 +++- .../FileFormats/Layout/TextureManager.cs | 9 +- .../Materials/PaneMatTextureMapsEditor.cs | 2 +- .../Window/WindowFrameEditorSettings.cs | 47 ++- .../GUI/BFLYT/LayoutEditor.Designer.cs | 43 ++- File_Format_Library/GUI/BFLYT/LayoutEditor.cs | 19 +- .../GUI/BFLYT/LayoutUndoManager.cs | 62 ++-- File_Format_Library/GUI/BFLYT/LayoutViewer.cs | 283 ++++++++++-------- Switch_Toolbox_Library/Config.cs | 4 + Switch_Toolbox_Library/Runtime.cs | 2 + 12 files changed, 400 insertions(+), 271 deletions(-) diff --git a/File_Format_Library/FileFormats/Archives/SARC.cs b/File_Format_Library/FileFormats/Archives/SARC.cs index 682fdeda..6b401b5b 100644 --- a/File_Format_Library/FileFormats/Archives/SARC.cs +++ b/File_Format_Library/FileFormats/Archives/SARC.cs @@ -250,22 +250,7 @@ namespace FirstPlugin file.SaveFileFormat(); if (sarcData.HashOnly) - { sarcData.Files.Add(file.HashName, file.FileData); - - /* - uint hash = 0; - bool IsHash = uint.TryParse(file.FileName, out hash); - if (IsHash && file.FileName.Length == 8) - { - sarcData.Files.Add(file.FileName, file.FileData); - } - else - { - string Hash = Crc32.Compute(file.FileName).ToString(); - sarcData.Files.Add(Hash, file.FileData); - }*/ - } else sarcData.Files.Add(file.FileName, file.FileData); } @@ -283,7 +268,54 @@ namespace FirstPlugin { public SARC sarc; //Sarc file the entry is located in - public string HashName; + public string OriginalFileName; + + private bool NameChanged + { + get { return OriginalFileName != FileName; } + } + + + + private string hashName; + public string HashName + { + get + { + if (hashName == null || NameChanged) + hashName = NameHash(FileName).ToString("X"); + + return hashName; + } + set + { + hashName = value; + } + } + + public bool IsHashMatch(string fileName) + { + uint hash = StringHashToUint(hashName); + return hash == NameHash(FileName); + } + + static uint NameHash(string name) + { + uint result = 0; + for (int i = 0; i < name.Length; i++) + { + result = name[i] + result * 0x00000065; + } + return result; + } + + static uint StringHashToUint(string name) + { + if (name.Contains(".")) + name = name.Split('.')[0]; + if (name.Length != 8) throw new Exception("Invalid hash length"); + return Convert.ToUInt32(name, 16); + } public SarcEntry() { @@ -310,6 +342,7 @@ namespace FirstPlugin public SarcEntry SetupFileEntry(string fullName, byte[] data, string HashName) { SarcEntry sarcEntry = new SarcEntry(); + sarcEntry.OriginalFileName = fullName; sarcEntry.FileName = fullName; sarcEntry.FileData = data; sarcEntry.HashName = HashName; diff --git a/File_Format_Library/FileFormats/Layout/BxlytToGL.cs b/File_Format_Library/FileFormats/Layout/BxlytToGL.cs index 6d646847..c2c85746 100644 --- a/File_Format_Library/FileFormats/Layout/BxlytToGL.cs +++ b/File_Format_Library/FileFormats/Layout/BxlytToGL.cs @@ -461,10 +461,10 @@ namespace LayoutBXLYT if (window.Content.TexCoords.Count > 0) { texCoords = new Vector2[] { - window.Content.TexCoords[0].BottomLeft.ToTKVector2(), - window.Content.TexCoords[0].BottomRight.ToTKVector2(), - window.Content.TexCoords[0].TopRight.ToTKVector2(), window.Content.TexCoords[0].TopLeft.ToTKVector2(), + window.Content.TexCoords[0].TopRight.ToTKVector2(), + window.Content.TexCoords[0].BottomRight.ToTKVector2(), + window.Content.TexCoords[0].BottomLeft.ToTKVector2(), }; } @@ -963,66 +963,11 @@ namespace LayoutBXLYT break; } - - //Lastly draw a selection box if selected - - if (isSelected) - { - if (!Runtime.LayoutEditor.IsGamePreview && !gameWindow) - DrawSelectionBox(pane, isSelected); - } - GL.Disable(EnableCap.Texture2D); GL.BindTexture(TextureTarget.Texture2D, 0); GL.UseProgram(0); } - public static void DrawSelectionBox(BasePane pane, bool isSelected) - { - var rect = pane.CreateRectangle(); - rect = rect.RotateZ(pane.Rotate.Z); - - GL.Disable(EnableCap.Blend); - GL.Disable(EnableCap.AlphaTest); - GL.Disable(EnableCap.Texture2D); - GL.UseProgram(0); - - GL.Begin(PrimitiveType.LineLoop); - GL.Color4(isSelected ? Color.Red : Color.Green); - GL.Vertex2(rect.LeftPoint, rect.BottomPoint); - GL.Vertex2(rect.RightPoint, rect.BottomPoint); - GL.Vertex2(rect.RightPoint, rect.TopPoint); - GL.Vertex2(rect.LeftPoint, rect.TopPoint); - GL.End(); - - if (isSelected) - { - var transformed = rect; - var leftTop = new Vector2(transformed.LeftPoint, transformed.TopPoint); - var left = new Vector2(transformed.LeftPoint, (transformed.BottomPoint + transformed.TopPoint) / 2); - var leftBottom = new Vector2(transformed.LeftPoint, transformed.BottomPoint); - var rightTop = new Vector2(transformed.RightPoint, transformed.TopPoint); - var right = new Vector2(transformed.RightPoint, (transformed.BottomPoint + transformed.TopPoint) / 2); - var rightBottom = new Vector2(transformed.RightPoint, transformed.BottomPoint); - var top = new Vector2((transformed.RightPoint + transformed.LeftPoint) / 2, transformed.TopPoint); - var bottom = new Vector2((transformed.RightPoint + transformed.LeftPoint) / 2, transformed.BottomPoint); - - DrawEdgeSquare(leftTop); - DrawEdgeSquare(left); - DrawEdgeSquare(leftBottom); - DrawEdgeSquare(rightTop); - DrawEdgeSquare(right); - DrawEdgeSquare(rightBottom); - DrawEdgeSquare(top); - DrawEdgeSquare(bottom); - } - - - GL.Enable(EnableCap.Blend); - GL.Enable(EnableCap.AlphaTest); - GL.Enable(EnableCap.Texture2D); - } - private static void GetTextureSize(BxlytMaterial pane, Dictionary Textures, out float width, out float height) { width = 0; @@ -1395,11 +1340,6 @@ namespace LayoutBXLYT GL.Vertex2(rect.LeftPoint, rect.TopPoint); GL.End(); } - - if (!gameWindow) - { - DrawSelectionBox(pane, selectionOutline); - } } else { @@ -1416,18 +1356,5 @@ namespace LayoutBXLYT // pane.renderablePane.Render(vertices, vertexColors, texCoords); } } - - private static void DrawEdgeSquare(Vector2 position) - { - float scale = 5; - - GL.Begin(PrimitiveType.LineLoop); - GL.Color4(Color.Red); - GL.Vertex2(position.X + -1 * scale, position.Y + -1 * scale); - GL.Vertex2(position.X + 1 * scale, position.Y + -1 * scale); - GL.Vertex2(position.X + 1 * scale, position.Y + 1 * scale); - GL.Vertex2(position.X + -1 * scale, position.Y + 1 * scale); - GL.End(); - } } } diff --git a/File_Format_Library/FileFormats/Layout/Common.cs b/File_Format_Library/FileFormats/Layout/Common.cs index f6c00284..ce4ac0da 100644 --- a/File_Format_Library/FileFormats/Layout/Common.cs +++ b/File_Format_Library/FileFormats/Layout/Common.cs @@ -163,6 +163,24 @@ namespace LayoutBXLYT } } + public void KeepChildrenTransform(float newTransX, float newTransY) + { + Vector2F distance = new Vector2F(newTransX - Translate.X, newTransY - Translate.Y); + KeepChildrenTransform(distance); + } + + private void KeepChildrenTransform(Vector2F distance) + { + if (HasChildern) + { + foreach (var child in Childern) + { + child.Translate -= new Vector3F(distance.X, distance.Y, 0); + child.KeepChildrenTransform(distance); + } + } + } + public CustomRectangle TransformParent(CustomRectangle rect) { return rect.GetTransformedRectangle(Parent, Translate,Rotate, Scale); @@ -198,13 +216,28 @@ namespace LayoutBXLYT parentTransform.W); } - public void TransformRectangle(LayoutViewer.PickAction pickAction, float pickMouseX, float pickMouseY) + public void TransformRectangle(LayoutViewer.PickAction pickAction, CustomRectangle selectionBox, float pickMouseX, float pickMouseY) { + CustomRectangle currentRectangle = this.CreateRectangle(); + currentRectangle = currentRectangle.GetTransformedRectangle(Parent, Translate, Rotate, Scale); + + //The selection box can have mutlile panes selected in one box + //Scaling the edges will have different distances + float distanceLeft = selectionBox.LeftPoint - currentRectangle.LeftPoint; + float distanceRight = selectionBox.RightPoint - currentRectangle.RightPoint; + float distanceTop = selectionBox.TopPoint - currentRectangle.TopPoint; + float distanceBottom = selectionBox.BottomPoint - currentRectangle.BottomPoint; + + Console.WriteLine("distanceLeft " + distanceLeft); + Console.WriteLine("distanceRight " + distanceRight); + Console.WriteLine("distanceTop " + distanceTop); + Console.WriteLine("distanceBottom " + distanceBottom); + + float posX = Translate.X; float posY = Translate.Y; float posZ = Translate.Z; - Console.WriteLine("pickMouseX " + pickMouseX); float pickWidth = pickMouseX; float pickHeight = pickMouseY; @@ -1826,6 +1859,11 @@ namespace LayoutBXLYT double cosTheta = Math.Cos(angleInRadians); double sinTheta = Math.Sin(angleInRadians); var centerPoint = new OpenTK.Vector2(0,0); + + return new OpenTK.Vector2( + (int)(p1 * cosTheta - p2 * sinTheta), + (int)(p1 * sinTheta + p2 * cosTheta)); + return new OpenTK.Vector2( (int) (cosTheta * (p1 - centerPoint.X) - @@ -1835,14 +1873,14 @@ namespace LayoutBXLYT cosTheta * (p2 - centerPoint.Y) + centerPoint.Y)); } - public CustomRectangle GetTransformedRectangle(BasePane parent, Vector3F Transform, Vector3F Rotate, Vector2F Scale) + public CustomRectangle GetTransformedRectangle(BasePane parent, Vector3F Transform, Vector3F Rotate, Vector2F scale) { var rect = this.RotateZ(Rotate.Z); rect = new CustomRectangle( - (int)(rect.LeftPoint + Transform.X * Scale.X), - (int)(rect.RightPoint + Transform.X * Scale.X), - (int)(rect.TopPoint + Transform.Y * Scale.Y), - (int)(rect.BottomPoint + Transform.Y * Scale.Y)); + (int)(((rect.LeftPoint * scale.X) + Transform.X)), + (int)(((rect.RightPoint * scale.X) + Transform.X)), + (int)(((rect.TopPoint * scale.Y) + Transform.Y)), + (int)(((rect.BottomPoint * scale.Y) + Transform.Y))); if (parent != null) return parent.TransformParent(rect); @@ -1850,12 +1888,12 @@ namespace LayoutBXLYT return rect; } - public float Width + public int Width { get { return LeftPoint - RightPoint; } } - public float Height + public int Height { get { return TopPoint - BottomPoint; } } diff --git a/File_Format_Library/FileFormats/Layout/TextureManager.cs b/File_Format_Library/FileFormats/Layout/TextureManager.cs index 88afb3b2..a8433792 100644 --- a/File_Format_Library/FileFormats/Layout/TextureManager.cs +++ b/File_Format_Library/FileFormats/Layout/TextureManager.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; +using System.Linq; using System.Threading.Tasks; using Toolbox.Library; using FirstPlugin; @@ -102,6 +102,11 @@ namespace LayoutBXLYT var archive = ArchiveParent; if (archive == null) return null; + var matches = archive.Files.Where(p => p.FileName.Contains("bflim")).ToList(); + string textureFolder = "timg"; + if (matches.Count > 0) + textureFolder = System.IO.Path.GetDirectoryName(matches[0].FileName); + var bflim = BFLIM.CreateNewFromImage(); if (bflim == null) @@ -114,7 +119,7 @@ namespace LayoutBXLYT archive.AddFile(new ArchiveFileInfo() { FileData = mem.ToArray(), - FileName = bflim.Text, + FileName = System.IO.Path.Combine(textureFolder, bflim.Text).Replace('\\','/'), }); } break; diff --git a/File_Format_Library/GUI/BFLYT/Editor/Materials/PaneMatTextureMapsEditor.cs b/File_Format_Library/GUI/BFLYT/Editor/Materials/PaneMatTextureMapsEditor.cs index 8a006295..5becd4a3 100644 --- a/File_Format_Library/GUI/BFLYT/Editor/Materials/PaneMatTextureMapsEditor.cs +++ b/File_Format_Library/GUI/BFLYT/Editor/Materials/PaneMatTextureMapsEditor.cs @@ -166,7 +166,7 @@ namespace LayoutBXLYT expandCB.SelectedItem = texMap.MaxFilterMode; shrinkCB.SelectedItem = texMap.MinFilterMode; - if (ActiveMaterial.TextureTransforms.Length > SelectedIndex) + if (ActiveMaterial.TextureTransforms?.Length > SelectedIndex) { var transform = ActiveMaterial.TextureTransforms[SelectedIndex]; scaleXUD.Value = transform.Scale.X; diff --git a/File_Format_Library/GUI/BFLYT/Editor/Window/WindowFrameEditorSettings.cs b/File_Format_Library/GUI/BFLYT/Editor/Window/WindowFrameEditorSettings.cs index b009480d..50fd5fa3 100644 --- a/File_Format_Library/GUI/BFLYT/Editor/Window/WindowFrameEditorSettings.cs +++ b/File_Format_Library/GUI/BFLYT/Editor/Window/WindowFrameEditorSettings.cs @@ -125,7 +125,7 @@ namespace LayoutBXLYT if (isHorizintal) { - switch (pane.WindowFrames.Count) + switch (pane.FrameCount) { case 1: frameNumCB.SelectedIndex = 0; @@ -137,7 +137,7 @@ namespace LayoutBXLYT } else { - switch (pane.WindowFrames.Count) + switch (pane.FrameCount) { case 1: frameNumCB.SelectedIndex = 0; @@ -194,20 +194,37 @@ namespace LayoutBXLYT { if (!loaded) return; - switch (frameNumCB.SelectedIndex) + if (ActivePane.WindowKind != WindowKind.Around) { - case 0: - ActivePane.FrameCount = 1; - windowFrameSelector1.FrameCount = 1; - break; - case 1: - ActivePane.FrameCount = 4; - windowFrameSelector1.FrameCount = 4; - break; - case 2: - ActivePane.FrameCount = 8; - windowFrameSelector1.FrameCount = 8; - break; + switch (frameNumCB.SelectedIndex) + { + case 0: + ActivePane.FrameCount = 1; + windowFrameSelector1.FrameCount = 1; + break; + case 1: + ActivePane.FrameCount = 2; + windowFrameSelector1.FrameCount = 2; + break; + } + } + else + { + switch (frameNumCB.SelectedIndex) + { + case 0: + ActivePane.FrameCount = 1; + windowFrameSelector1.FrameCount = 1; + break; + case 1: + ActivePane.FrameCount = 4; + windowFrameSelector1.FrameCount = 4; + break; + case 2: + ActivePane.FrameCount = 8; + windowFrameSelector1.FrameCount = 8; + break; + } } ActivePane.ReloadFrames(); diff --git a/File_Format_Library/GUI/BFLYT/LayoutEditor.Designer.cs b/File_Format_Library/GUI/BFLYT/LayoutEditor.Designer.cs index a9d521d3..9adbfc95 100644 --- a/File_Format_Library/GUI/BFLYT/LayoutEditor.Designer.cs +++ b/File_Format_Library/GUI/BFLYT/LayoutEditor.Designer.cs @@ -52,6 +52,7 @@ this.displayGridToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.textureListToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.textConverterToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.viewPartsAsNullPanesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.orthographicViewToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.displayNullPanesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.displayyBoundryPanesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); @@ -62,7 +63,8 @@ this.resetToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.windowToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.showGameWindowToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.viewPartsAsNullPanesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.panesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.transformChildrenToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); ((System.ComponentModel.ISupportInitialize)(this.backColorDisplay)).BeginInit(); this.stToolStrip1.SuspendLayout(); this.stMenuStrip1.SuspendLayout(); @@ -124,6 +126,7 @@ // // stToolStrip1 // + this.stToolStrip1.HighlightSelectedTab = false; this.stToolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.toolStripButton1, this.toolstripOrthoBtn}); @@ -155,6 +158,7 @@ // // stMenuStrip1 // + this.stMenuStrip1.HighlightSelectedTab = false; this.stMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.fileToolStripMenuItem, this.editToolStripMenuItem, @@ -218,7 +222,8 @@ // this.editToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.undoToolStripMenuItem, - this.redoToolStripMenuItem}); + this.redoToolStripMenuItem, + this.panesToolStripMenuItem}); this.editToolStripMenuItem.Name = "editToolStripMenuItem"; this.editToolStripMenuItem.Size = new System.Drawing.Size(39, 20); this.editToolStripMenuItem.Text = "Edit"; @@ -226,14 +231,14 @@ // undoToolStripMenuItem // this.undoToolStripMenuItem.Name = "undoToolStripMenuItem"; - this.undoToolStripMenuItem.Size = new System.Drawing.Size(103, 22); + this.undoToolStripMenuItem.Size = new System.Drawing.Size(180, 22); this.undoToolStripMenuItem.Text = "Undo"; this.undoToolStripMenuItem.Click += new System.EventHandler(this.undoToolStripMenuItem_Click); // // redoToolStripMenuItem // this.redoToolStripMenuItem.Name = "redoToolStripMenuItem"; - this.redoToolStripMenuItem.Size = new System.Drawing.Size(103, 22); + this.redoToolStripMenuItem.Size = new System.Drawing.Size(180, 22); this.redoToolStripMenuItem.Text = "Redo"; this.redoToolStripMenuItem.Click += new System.EventHandler(this.redoToolStripMenuItem_Click); // @@ -285,6 +290,14 @@ this.textConverterToolStripMenuItem.Text = "Text Converter"; this.textConverterToolStripMenuItem.Click += new System.EventHandler(this.textConverterToolStripMenuItem_Click); // + // viewPartsAsNullPanesToolStripMenuItem + // + this.viewPartsAsNullPanesToolStripMenuItem.CheckOnClick = true; + this.viewPartsAsNullPanesToolStripMenuItem.Name = "viewPartsAsNullPanesToolStripMenuItem"; + this.viewPartsAsNullPanesToolStripMenuItem.Size = new System.Drawing.Size(203, 22); + this.viewPartsAsNullPanesToolStripMenuItem.Text = "View Parts As Null Panes"; + this.viewPartsAsNullPanesToolStripMenuItem.Click += new System.EventHandler(this.viewPartsAsNullPanesToolStripMenuItem_Click); + // // orthographicViewToolStripMenuItem // this.orthographicViewToolStripMenuItem.Checked = true; @@ -375,13 +388,21 @@ this.showGameWindowToolStripMenuItem.Text = "Show Game Window"; this.showGameWindowToolStripMenuItem.Click += new System.EventHandler(this.showGameWindowToolStripMenuItem_Click); // - // viewPartsAsNullPanesToolStripMenuItem + // panesToolStripMenuItem // - this.viewPartsAsNullPanesToolStripMenuItem.CheckOnClick = true; - this.viewPartsAsNullPanesToolStripMenuItem.Name = "viewPartsAsNullPanesToolStripMenuItem"; - this.viewPartsAsNullPanesToolStripMenuItem.Size = new System.Drawing.Size(203, 22); - this.viewPartsAsNullPanesToolStripMenuItem.Text = "View Parts As Null Panes"; - this.viewPartsAsNullPanesToolStripMenuItem.Click += new System.EventHandler(this.viewPartsAsNullPanesToolStripMenuItem_Click); + this.panesToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.transformChildrenToolStripMenuItem}); + this.panesToolStripMenuItem.Name = "panesToolStripMenuItem"; + this.panesToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.panesToolStripMenuItem.Text = "Panes"; + // + // transformChildrenToolStripMenuItem + // + this.transformChildrenToolStripMenuItem.CheckOnClick = true; + this.transformChildrenToolStripMenuItem.Name = "transformChildrenToolStripMenuItem"; + this.transformChildrenToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.transformChildrenToolStripMenuItem.Text = "Transform Children"; + this.transformChildrenToolStripMenuItem.Click += new System.EventHandler(this.transformChildrenToolStripMenuItem_Click); // // LayoutEditor // @@ -449,5 +470,7 @@ private System.Windows.Forms.ToolStripMenuItem undoToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem redoToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem viewPartsAsNullPanesToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem panesToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem transformChildrenToolStripMenuItem; } } diff --git a/File_Format_Library/GUI/BFLYT/LayoutEditor.cs b/File_Format_Library/GUI/BFLYT/LayoutEditor.cs index 89f4186d..ad8c2057 100644 --- a/File_Format_Library/GUI/BFLYT/LayoutEditor.cs +++ b/File_Format_Library/GUI/BFLYT/LayoutEditor.cs @@ -77,6 +77,7 @@ namespace LayoutBXLYT renderInGamePreviewToolStripMenuItem.Checked = Runtime.LayoutEditor.IsGamePreview; displayGridToolStripMenuItem.Checked = Runtime.LayoutEditor.DisplayGrid; displayTextPanesToolStripMenuItem.Checked = Runtime.LayoutEditor.DisplayTextPane; + transformChildrenToolStripMenuItem.Checked = Runtime.LayoutEditor.TransformChidlren; ObjectSelected += OnObjectSelected; ObjectChanged += OnObjectChanged; @@ -244,6 +245,7 @@ namespace LayoutBXLYT ActiveViewport.UpdateViewport(); } + private bool isSelectedInViewer = false; private bool isChecked = false; private void OnObjectSelected(object sender, EventArgs e) { @@ -269,11 +271,12 @@ namespace LayoutBXLYT } if (LayoutPaneEditor != null && (string)sender == "Select") { - ActiveViewport?.SelectedPanes.Clear(); - if (e is TreeViewEventArgs) { var node = ((TreeViewEventArgs)e).Node; + if (!isSelectedInViewer) + ActiveViewport?.SelectedPanes.Clear(); + if (node.Tag is BasePane) LoadPaneEditorOnSelect(node.Tag as BasePane); else if (node.Tag is BxlytMaterial) @@ -321,7 +324,11 @@ namespace LayoutBXLYT LayoutPaneEditor.Text = $"Properties [{pane.Name}] | (Null Pane)"; LayoutPaneEditor.LoadPane(pane, this); - ActiveViewport?.SelectedPanes.Add(pane); + + if (ActiveViewport == null) return; + + if (!ActiveViewport.SelectedPanes.Contains(pane)) + ActiveViewport.SelectedPanes.Add(pane); } public void RefreshEditors() @@ -334,7 +341,9 @@ namespace LayoutBXLYT var nodeWrapper = pane.NodeWrapper; if (nodeWrapper == null) return; + isSelectedInViewer = true; LayoutHierarchy?.SelectNode(nodeWrapper); + isSelectedInViewer = false; } private void UpdateAnimationNode(ListViewItem node) @@ -1080,5 +1089,9 @@ namespace LayoutBXLYT } #endregion + + private void transformChildrenToolStripMenuItem_Click(object sender, EventArgs e) { + Runtime.LayoutEditor.TransformChidlren = transformChildrenToolStripMenuItem.Checked; + } } } diff --git a/File_Format_Library/GUI/BFLYT/LayoutUndoManager.cs b/File_Format_Library/GUI/BFLYT/LayoutUndoManager.cs index 072c0e02..33c74a22 100644 --- a/File_Format_Library/GUI/BFLYT/LayoutUndoManager.cs +++ b/File_Format_Library/GUI/BFLYT/LayoutUndoManager.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Syroot.Maths; +using Toolbox.Library; namespace LayoutBXLYT { @@ -178,35 +179,56 @@ namespace LayoutBXLYT public class UndoActionTransform : IRevertAction { - public Vector3F Translate; - public Vector3F Rotate; - public Vector2F Scale; + bool TransformChidlren = false; - public float Width; - public float Height; + public List Panes = new List(); - public BasePane targetPane; - - - public UndoActionTransform(BasePane pane) + public UndoActionTransform(List panes) { - targetPane = pane; - Translate = pane.Translate; - Scale = pane.Scale; - Rotate = pane.Rotate; - Width = pane.Width; - Height = pane.Height; + foreach (var pane in panes) + { + TransformChidlren = Runtime.LayoutEditor.TransformChidlren; + Panes.Add(new PaneInfo() + { + targetPane = pane, + Translate = pane.Translate, + Scale = pane.Scale, + Rotate = pane.Rotate, + Width = pane.Width, + Height = pane.Height, + }); + } + } public IRevertAction Revert() { - targetPane.Translate = Translate; - targetPane.Scale = Scale; - targetPane.Rotate = Rotate; - targetPane.Width = Width; - targetPane.Height = Height; + foreach (var pane in Panes) + { + if (!TransformChidlren) + pane.targetPane.KeepChildrenTransform(pane.Translate.X, pane.Translate.Y); + + pane.targetPane.Translate = pane.Translate; + pane.targetPane.Scale = pane.Scale; + pane.targetPane.Rotate = pane.Rotate; + pane.targetPane.Width = pane.Width; + pane.targetPane.Height = pane.Height; + } + return this; } + + public class PaneInfo + { + public Vector3F Translate; + public Vector3F Rotate; + public Vector2F Scale; + + public float Width; + public float Height; + + public BasePane targetPane; + } } } } diff --git a/File_Format_Library/GUI/BFLYT/LayoutViewer.cs b/File_Format_Library/GUI/BFLYT/LayoutViewer.cs index 858bff4f..78d2794e 100644 --- a/File_Format_Library/GUI/BFLYT/LayoutViewer.cs +++ b/File_Format_Library/GUI/BFLYT/LayoutViewer.cs @@ -238,7 +238,7 @@ namespace LayoutBXLYT { foreach (var pane in file.PaneLookup.Values) { - if (!pane.Visible || !pane.DisplayInEditor) + if (!pane.Visible || !pane.DisplayInEditor && !pane.IsRoot) continue; //Hitbox debug @@ -306,9 +306,7 @@ namespace LayoutBXLYT //Create a bounding box for all selected panes //This box will allow resizing of all selected panes if (SelectedPanes.Count > 0) - { - - } + DrawSelectionBox(SelectedPanes, true); if (UseOrtho) GL.PopMatrix(); @@ -318,9 +316,91 @@ namespace LayoutBXLYT glControl1.SwapBuffers(); } - private void DrawRectangle() + private static CustomRectangle GetSelectedPanesBounding(List panes) { + CustomRectangle rect = new CustomRectangle(0, 0, 0, 0); + List points = new List(); + foreach (var pane in panes) + { + var paneRect = pane.CreateRectangle(); + rect = paneRect.GetTransformedRectangle(pane.Parent, pane.Translate, pane.Rotate, pane.Scale); + points.AddRange(new Vector2[4] + { + new Vector2(rect.LeftPoint, rect.TopPoint), + new Vector2(rect.RightPoint, rect.TopPoint), + new Vector2(rect.RightPoint, rect.BottomPoint), + new Vector2(rect.LeftPoint, rect.BottomPoint) + }); + + var minX = (int)points.Min(p => p.X); + var maxX = (int)points.Max(p => p.X); + var minY = (int)points.Min(p => p.Y); + var maxY = (int)points.Max(p => p.Y); + + rect = new CustomRectangle(minX, maxX, maxY, minY); + } + points.Clear(); + + return rect; + } + + public static void DrawSelectionBox(List panes, bool isSelected) + { + //Create a rectangle with the largest points selected + CustomRectangle rect = GetSelectedPanesBounding(panes); + + GL.Disable(EnableCap.Blend); + GL.Disable(EnableCap.AlphaTest); + GL.Disable(EnableCap.Texture2D); + GL.UseProgram(0); + + GL.Begin(PrimitiveType.LineLoop); + GL.Color4(isSelected ? Color.Red : Color.Green); + GL.Vertex2(rect.LeftPoint, rect.BottomPoint); + GL.Vertex2(rect.RightPoint, rect.BottomPoint); + GL.Vertex2(rect.RightPoint, rect.TopPoint); + GL.Vertex2(rect.LeftPoint, rect.TopPoint); + GL.End(); + + if (isSelected) + { + var transformed = rect; + var leftTop = new Vector2(transformed.LeftPoint, transformed.TopPoint); + var left = new Vector2(transformed.LeftPoint, (transformed.BottomPoint + transformed.TopPoint) / 2); + var leftBottom = new Vector2(transformed.LeftPoint, transformed.BottomPoint); + var rightTop = new Vector2(transformed.RightPoint, transformed.TopPoint); + var right = new Vector2(transformed.RightPoint, (transformed.BottomPoint + transformed.TopPoint) / 2); + var rightBottom = new Vector2(transformed.RightPoint, transformed.BottomPoint); + var top = new Vector2((transformed.RightPoint + transformed.LeftPoint) / 2, transformed.TopPoint); + var bottom = new Vector2((transformed.RightPoint + transformed.LeftPoint) / 2, transformed.BottomPoint); + + DrawEdgeSquare(leftTop); + DrawEdgeSquare(left); + DrawEdgeSquare(leftBottom); + DrawEdgeSquare(rightTop); + DrawEdgeSquare(right); + DrawEdgeSquare(rightBottom); + DrawEdgeSquare(top); + DrawEdgeSquare(bottom); + } + + GL.Enable(EnableCap.Blend); + GL.Enable(EnableCap.AlphaTest); + GL.Enable(EnableCap.Texture2D); + } + + private static void DrawEdgeSquare(Vector2 position) + { + float scale = 5; + + GL.Begin(PrimitiveType.LineLoop); + GL.Color4(Color.Red); + GL.Vertex2(position.X + -1 * scale, position.Y + -1 * scale); + GL.Vertex2(position.X + 1 * scale, position.Y + -1 * scale); + GL.Vertex2(position.X + 1 * scale, position.Y + 1 * scale); + GL.Vertex2(position.X + -1 * scale, position.Y + 1 * scale); + GL.End(); } private void RenderPanes(BxlytShader shader, BasePane pane, bool isRoot, byte parentAlpha, bool parentAlphaInfluence, BasePane partPane = null, int stage = 0) @@ -516,7 +596,7 @@ namespace LayoutBXLYT if (partPane != null) RenderPanes(shader,partPane, true, effectiveAlpha, parentInfluenceAlpha); else - DrawDefaultPane(shader, pane); + DrawDefaultPane(shader, pane, isSelected); if (pane.Properties != null) { @@ -688,27 +768,29 @@ namespace LayoutBXLYT mouseDown = true; RenderEditor(); - var coords = convertScreenToWorldCoords(e.Location.X, e.Location.Y); + var coords = OpenGLHelper.convertScreenToWorldCoords(e.Location.X, e.Location.Y); + + GL.PopMatrix(); bool hasEdgeHit = false; - foreach (var pane in SelectedPanes) + + var rect = GetSelectedPanesBounding(SelectedPanes); + var edgePick = SearchEdgePicking(rect, coords.X, coords.Y); + if (edgePick != PickAction.None) { - var edgePick = SearchEdgePicking(pane, coords.X, coords.Y); - if (edgePick != PickAction.None) - { - pickAction = edgePick; - isPicked = true; - hasEdgeHit = true; - - UndoManger.AddToUndo(new LayoutUndoManager.UndoActionTransform(pane)); - - pickOriginMouse = e.Location; - - RenderScene(); - return; - } + pickAction = edgePick; + isPicked = true; + hasEdgeHit = true; } + if (hasEdgeHit) + { + UndoManger.AddToUndo(new LayoutUndoManager.UndoActionTransform(SelectedPanes)); + pickOriginMouse = e.Location; + return; + } + + BasePane hitPane = null; SearchHit(LayoutFile.RootPane, coords.X, coords.Y, ref hitPane); if (hitPane != null) @@ -716,38 +798,36 @@ namespace LayoutBXLYT pickAction = PickAction.Translate; if (!SelectedPanes.Contains(hitPane)) + { + if (Control.ModifierKeys != Keys.Control) + SelectedPanes.Clear(); + SelectedPanes.Add(hitPane); - - foreach (var pane in SelectedPanes) - { - var edgePick = SearchEdgePicking(pane, coords.X, coords.Y); - if (edgePick != PickAction.None) - pickAction = edgePick; - - Console.WriteLine(pane.Name + " " + pickAction); } - foreach (var pane in SelectedPanes) - { - UndoManger.AddToUndo(new LayoutUndoManager.UndoActionTransform(pane)); - } + + var paneRect = GetSelectedPanesBounding(SelectedPanes); + var paneEdgePick = SearchEdgePicking(paneRect, coords.X, coords.Y); + if (paneEdgePick != PickAction.None) + pickAction = paneEdgePick; + + UndoManger.AddToUndo(new LayoutUndoManager.UndoActionTransform(SelectedPanes)); ParentEditor.UpdateUndo(); ParentEditor.UpdateHiearchyNodeSelection(hitPane); isPicked = true; - } //Check edge hit and control key (multi selecting panes) - else if (!hasEdgeHit && Control.ModifierKeys != Keys.Control) + } //Check control key (multi selecting panes) + else if (Control.ModifierKeys != Keys.Control) SelectedPanes.Clear(); - pickOriginMouse = e.Location; - RenderScene(); + pickOriginMouse = e.Location; } else if (e.Button == MouseButtons.Right) { RenderEditor(); - var coords = convertScreenToWorldCoords(e.Location.X, e.Location.Y); + var coords = OpenGLHelper.convertScreenToWorldCoords(e.Location.X, e.Location.Y); pickOriginMouse = coords; GL.PopMatrix(); @@ -963,9 +1043,8 @@ namespace LayoutBXLYT return SelectedPanes; } - private PickAction SearchEdgePicking(BasePane pane, int X, int Y) + private PickAction SearchEdgePicking(CustomRectangle transformed, int X, int Y) { - var transformed = pane.CreateRectangle().GetTransformedRectangle(pane.Parent, pane.Translate, pane.Rotate, pane.Scale); var leftTop = new Point(transformed.LeftPoint, transformed.TopPoint); var left = new Point(transformed.LeftPoint, (transformed.BottomPoint + transformed.TopPoint) / 2); var leftBottom = new Point(transformed.LeftPoint, transformed.BottomPoint); @@ -1053,47 +1132,47 @@ namespace LayoutBXLYT if (SelectedPanes.Count > 0 && !showSelectionBox) { RenderEditor(); - var posWorld = convertScreenToWorldCoords(e.Location.X, e.Location.Y); + var posWorld = OpenGLHelper.convertScreenToWorldCoords(e.Location.X, e.Location.Y); GL.PopMatrix(); //Setup edge picking with move event bool hasPick = false; - foreach (var pane in SelectedPanes) + + var paneRect = GetSelectedPanesBounding(SelectedPanes); + var pickState = SearchEdgePicking(paneRect, posWorld.X, posWorld.Y); + + if (pickState != PickAction.None) { - var pickState = SearchEdgePicking(pane, posWorld.X, posWorld.Y); - if (pickState != PickAction.None) - { - if (pickState == PickAction.DragTop) - Cursor.Current = Cursors.SizeNS; - if (pickState == PickAction.DragBottom) - Cursor.Current = Cursors.SizeNS; - if (pickState == PickAction.DragLeft) - Cursor.Current = Cursors.SizeWE; - if (pickState == PickAction.DragRight) - Cursor.Current = Cursors.SizeWE; - if (pickState == PickAction.DragBottomLeft) - Cursor.Current = Cursors.SizeNESW; - if (pickState == PickAction.DragBottomRight) - Cursor.Current = Cursors.SizeNWSE; - if (pickState == PickAction.DragTopLeft) - Cursor.Current = Cursors.SizeNWSE; - if (pickState == PickAction.DragTopRight) - Cursor.Current = Cursors.SizeNESW; + if (pickState == PickAction.DragTop) + Cursor.Current = Cursors.SizeNS; + if (pickState == PickAction.DragBottom) + Cursor.Current = Cursors.SizeNS; + if (pickState == PickAction.DragLeft) + Cursor.Current = Cursors.SizeWE; + if (pickState == PickAction.DragRight) + Cursor.Current = Cursors.SizeWE; + if (pickState == PickAction.DragBottomLeft) + Cursor.Current = Cursors.SizeNESW; + if (pickState == PickAction.DragBottomRight) + Cursor.Current = Cursors.SizeNWSE; + if (pickState == PickAction.DragTopLeft) + Cursor.Current = Cursors.SizeNWSE; + if (pickState == PickAction.DragTopRight) + Cursor.Current = Cursors.SizeNESW; - hasPick = true; - } - else if (isPicked && pickAction != PickAction.None) - { - if (pickAction == PickAction.Translate) - Cursor.Current = Cursors.SizeAll; - if (pickAction == PickAction.Rotate) - Cursor.Current = Cursors.SizeAll; - if (pickAction == PickAction.Scale) - Cursor.Current = Cursors.SizeAll; + hasPick = true; + } + else if (isPicked && pickAction != PickAction.None) + { + if (pickAction == PickAction.Translate) + Cursor.Current = Cursors.SizeAll; + if (pickAction == PickAction.Rotate) + Cursor.Current = Cursors.SizeAll; + if (pickAction == PickAction.Scale) + Cursor.Current = Cursors.SizeAll; - hasPick = true; - } + hasPick = true; } if (!hasPick) @@ -1104,8 +1183,8 @@ namespace LayoutBXLYT { RenderEditor(); var temp = e.Location; - var curPos = convertScreenToWorldCoords(temp.X, temp.Y); - var prevPos = convertScreenToWorldCoords(pickOriginMouse.X, pickOriginMouse.Y); + var curPos = OpenGLHelper.convertScreenToWorldCoords(temp.X, temp.Y); + var prevPos = OpenGLHelper.convertScreenToWorldCoords(pickOriginMouse.X, pickOriginMouse.Y); var pickMouse = new Point((int)(prevPos.X - curPos.X), (int)(prevPos.Y - curPos.Y)); if (pickAction == PickAction.Translate) @@ -1128,6 +1207,9 @@ namespace LayoutBXLYT posY = pane.Translate.Y - pickMouse.Y; } + if (!Runtime.LayoutEditor.TransformChidlren) + pane.KeepChildrenTransform(posX, posY); + if (snapToGrid) { int gridCubeWidth = 16, gridCubeHeight = 16; @@ -1146,9 +1228,11 @@ namespace LayoutBXLYT } else if (!showSelectionBox) { + var selectionBox = GetSelectedPanesBounding(SelectedPanes); + //Setup edge picking with move event foreach (var pane in SelectedPanes) - pane.TransformRectangle(pickAction, pickMouse.X, pickMouse.Y); + pane.TransformRectangle(pickAction, selectionBox, pickMouse.X, pickMouse.Y); } pickOriginMouse = temp; @@ -1160,8 +1244,8 @@ namespace LayoutBXLYT { RenderEditor(); var temp = e.Location; - var curPos = convertScreenToWorldCoords(temp.X, temp.Y); - var prevPos = convertScreenToWorldCoords(pickOriginMouse.X, pickOriginMouse.Y); + var curPos = OpenGLHelper.convertScreenToWorldCoords(temp.X, temp.Y); + var prevPos = OpenGLHelper.convertScreenToWorldCoords(pickOriginMouse.X, pickOriginMouse.Y); DrawSelectionBox(prevPos, curPos); } @@ -1209,45 +1293,6 @@ namespace LayoutBXLYT RenderScene(true); } - public static Point convertScreenToWorldCoords(int x, int y) - { - int[] viewport = new int[4]; - Matrix4 modelViewMatrix, projectionMatrix; - GL.GetFloat(GetPName.ModelviewMatrix, out modelViewMatrix); - GL.GetFloat(GetPName.ProjectionMatrix, out projectionMatrix); - GL.GetInteger(GetPName.Viewport, viewport); - Vector2 mouse; - mouse.X = x; - mouse.Y = y; - Vector4 vector = UnProject(ref projectionMatrix, modelViewMatrix, new Size(viewport[2], viewport[3]), mouse); - Point coords = new Point((int)vector.X, (int)vector.Y); - return coords; - } - public static Vector4 UnProject(ref Matrix4 projection, Matrix4 view, Size viewport, Vector2 mouse) - { - Vector4 vec; - - vec.X = (2.0f * mouse.X / (float)viewport.Width - 1); - vec.Y = -(2.0f * mouse.Y / (float)viewport.Height - 1); - vec.Z = 0; - vec.W = 1.0f; - - Matrix4 viewInv = Matrix4.Invert(view); - Matrix4 projInv = Matrix4.Invert(projection); - - Vector4.Transform(ref vec, ref projInv, out vec); - Vector4.Transform(ref vec, ref viewInv, out vec); - - if (vec.W > float.Epsilon || vec.W < float.Epsilon) - { - vec.X /= vec.W; - vec.Y /= vec.W; - vec.Z /= vec.W; - } - - return vec; - } - protected override void OnMouseWheel(MouseEventArgs e) { base.OnMouseWheel(e); @@ -1321,7 +1366,7 @@ namespace LayoutBXLYT var point = this.PointToClient(new Point(e.X, e.Y)); RenderEditor(); - var coords = convertScreenToWorldCoords(point.X, point.Y); + var coords = OpenGLHelper.convertScreenToWorldCoords(point.X, point.Y); GL.PopMatrix(); var pane = ParentEditor.AddNewPicturePane(); diff --git a/Switch_Toolbox_Library/Config.cs b/Switch_Toolbox_Library/Config.cs index 7196c882..423a93a8 100644 --- a/Switch_Toolbox_Library/Config.cs +++ b/Switch_Toolbox_Library/Config.cs @@ -288,6 +288,9 @@ namespace Toolbox.Library case "PartsAsNullPanes": bool.TryParse(node.InnerText, out Runtime.LayoutEditor.PartsAsNullPanes); break; + case "TransformPaneChidlren": + bool.TryParse(node.InnerText, out Runtime.LayoutEditor.TransformChidlren); + break; } } @@ -415,6 +418,7 @@ namespace Toolbox.Library layoutSettingsNode.AppendChild(createNode(doc, "DisplayWindowPane", Runtime.LayoutEditor.DisplayWindowPane.ToString())); layoutSettingsNode.AppendChild(createNode(doc, "DisplayTextPane", Runtime.LayoutEditor.DisplayTextPane.ToString())); layoutSettingsNode.AppendChild(createNode(doc, "PartsAsNullPanes", Runtime.LayoutEditor.PartsAsNullPanes.ToString())); + layoutSettingsNode.AppendChild(createNode(doc, "TransformPaneChidlren", Runtime.LayoutEditor.TransformChidlren.ToString())); } private static void AppendDeveloperSettings(XmlDocument doc, XmlNode parentNode) diff --git a/Switch_Toolbox_Library/Runtime.cs b/Switch_Toolbox_Library/Runtime.cs index 1ee1598a..301c5558 100644 --- a/Switch_Toolbox_Library/Runtime.cs +++ b/Switch_Toolbox_Library/Runtime.cs @@ -64,6 +64,8 @@ namespace Toolbox.Library public class LayoutEditor { + public static bool TransformChidlren = false; + public static bool PartsAsNullPanes = false; public static bool IsGamePreview = false; public static bool DisplayNullPane = true;