diff --git a/Assets/Asset.cs b/Assets/Asset.cs index 21c8342..a2c4117 100644 --- a/Assets/Asset.cs +++ b/Assets/Asset.cs @@ -13,12 +13,17 @@ abstract class Asset { public string Name { get; set; } = string.Empty; + public string Description { get; set; } = string.Empty; + public Image Preview { get; set; } public string SourceFile { get; } + public JsonDictWrapper Object { get; } + public Asset(JsonDictWrapper obj, string source) { + Object = obj; SourceFile = source; if (obj.TryPopValue("preview", out string path)) @@ -29,7 +34,8 @@ public Asset(JsonDictWrapper obj, string source) var bitmap = new Bitmap(stream); Preview = bitmap; } - catch { + catch + { Preview = Properties.Resources.InvalidPreview; } } @@ -37,6 +43,11 @@ public Asset(JsonDictWrapper obj, string source) { Preview = Properties.Resources.NoPreview; } + + if (obj.TryPopValue("description", out string desc)) + { + Description = desc; + } } } diff --git a/Assets/AssetCollection.cs b/Assets/AssetCollection.cs new file mode 100644 index 0000000..d067307 --- /dev/null +++ b/Assets/AssetCollection.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace LevelTemplateCreator.Assets; + +internal class AssetCollection : ICollection where T : Asset +{ + Dictionary assets = new Dictionary(); + + public int Count => assets.Count; + + public bool IsReadOnly => false; + + public void Add(T item) + { + assets[item.Name] = item; + } + + public void Clear() + { + assets.Clear(); + } + + public T this[string key] => assets[key]; + + + public bool ConatinsKey(string key) => assets.ContainsKey(key); + + public bool TryGetValue(string key, out T value) + { + return assets.TryGetValue(key, out value!); + } + + public bool Contains(T item) + { + return assets.ContainsKey(item.Name); + } + + public void CopyTo(T[] array, int arrayIndex) + { + assets.Values.CopyTo(array, arrayIndex); + } + + public IEnumerator GetEnumerator() + { + return assets.Values.GetEnumerator(); + } + + public bool Remove(T item) + { + return assets.Remove(item.Name); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return assets.Values.GetEnumerator(); + } +} diff --git a/Assets/AssetLibary.cs b/Assets/AssetLibary.cs index f0bfd27..6f22739 100644 --- a/Assets/AssetLibary.cs +++ b/Assets/AssetLibary.cs @@ -1,6 +1,7 @@ using LevelTemplateCreator.IO; using LevelTemplateCreator.IO.Resources; using LevelTemplateCreator.SceneTree; +using LevelTemplateCreator.SceneTree.Main; using System; using System.Collections.Generic; using System.Linq; @@ -12,24 +13,119 @@ namespace LevelTemplateCreator.Assets; internal class AssetLibary { - public List LevelPresets { get; } + public AssetCollection LevelPresets { get; } - public ResourceManager TextureFiles { get; } + public AssetCollection TerrainMaterials { get; } - public List TerrainMaterials { get; } + public AssetCollection ObjectMaterials { get; } - public List ObjectMaterials { get; } + public AssetCollection GroundCoverDefinitions { get; } - public List GroundCoverAssets { get; } + public AssetCollection GroundCoverInstances { get; } public Bitmap? Preview { get; set; } + public int TotalCount => LevelPresets.Count + TerrainMaterials.Count + ObjectMaterials.Count + GroundCoverDefinitions.Count + GroundCoverInstances.Count; + public AssetLibary() { LevelPresets = new(); - TextureFiles = new(); TerrainMaterials = new(); ObjectMaterials = new(); - GroundCoverAssets = new(); + GroundCoverDefinitions = new(); + GroundCoverInstances = new(); + } + + public void Add(IEnumerable assets) + { + foreach (var asset in assets) + { + Add(asset); + } + } + + public void Add(Asset asset) + { + switch (asset) + { + case LevelPreset preset: + LevelPresets.Add(preset); + break; + + case TerrainPbrMaterialAsset material: + TerrainMaterials.Add(material); + break; + + default: + throw new ArgumentException(); + } + } + + public void Clear() + { + LevelPresets.Clear(); + TerrainMaterials.Clear(); + ObjectMaterials.Clear(); + GroundCoverDefinitions.Clear(); + GroundCoverInstances.Clear(); + } + + public void SeperateGroundCoverInstances() + { + foreach (var item in GroundCoverDefinitions) + { + AddGroundCoverInstances(GroundCoverInstance.PopFromGroundcover(item.GroundCover), item.SourceFile); + } + + foreach (var item in TerrainMaterials) { + AddGroundCoverInstances(GroundCoverInstance.PopFromMaterial(item.Material), item.SourceFile); + } + } + + void AddGroundCoverInstances(GroundCoverInstance[] instances, string source) + { + foreach (var item in instances) + { + var asset = new GroundCoverInstanceAsset(item, source); + GroundCoverInstances.Add(asset); + } + } + + public void GetGroundCoverInstances(AssetCollection filter, AssetCollection target) + { + foreach (var item in GroundCoverInstances) + { + if (filter.ConatinsKey(item.Instance.Layer.Value)) + { + target.Add(item); + } + } + } + + public void CreateGroundCoverObjects(AssetCollection instances) + { + + } + + public void GetMaterials(AssetCollection filter, AssetCollection target) + { + foreach (var item in GroundCoverInstances) + { + if (filter.ConatinsKey(item.Instance.Layer.Value)) + { + //target.Add(item); + } + } + } + + public void PrintSumary() + { + Console.WriteLine($"Assets: {TotalCount}"); + Console.WriteLine($"- LevelPresets: {LevelPresets.Count}"); + Console.WriteLine($"- TerrainMaterials: {TerrainMaterials.Count}"); + Console.WriteLine($"- ObjectMaterials: {ObjectMaterials.Count}"); + Console.WriteLine($"- GroundCoverDefinitions: {GroundCoverDefinitions.Count}"); + Console.WriteLine($"- GroundCoverInstances: {GroundCoverInstances.Count}"); + Console.WriteLine(); } } diff --git a/Assets/AssetLibaryLoader.cs b/Assets/AssetLibaryLoader.cs index 1f0eb42..dffb7b4 100644 --- a/Assets/AssetLibaryLoader.cs +++ b/Assets/AssetLibaryLoader.cs @@ -110,7 +110,7 @@ void ParseObject(JsonDictWrapper item) case GroundCoverAsset.ClassName: { var groundcover = new GroundCoverAsset(item, currentFile); - Libary.GroundCoverAssets.Add(groundcover); + Libary.GroundCoverDefinitions.Add(groundcover); break; } default: @@ -130,4 +130,27 @@ void ParseArray(JsonDictWrapper array) ParseObject(si); } } + + public void PrintErrors() + { + if (Errors.Count == 0) + return; + + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine($"{Errors.Count} errors while loading assets."); + Console.ForegroundColor = ConsoleColor.Gray; + + Console.WriteLine(); + + for (int i = 0; i < Errors.Count; i++) + { + var error = Errors[i]; + + Console.WriteLine($"At {error.File}"); + Console.WriteLine(error.Exception.Message); + + Console.WriteLine(); + } + + } } diff --git a/Assets/GroundCoverAsset.cs b/Assets/GroundCoverAsset.cs index e8e7d8d..c266632 100644 --- a/Assets/GroundCoverAsset.cs +++ b/Assets/GroundCoverAsset.cs @@ -12,10 +12,15 @@ internal class GroundCoverAsset : Asset { public const string ClassName = "GroundCover"; - public GroundCoverDefinition Definition { get; } + public GroundCover GroundCover { get; } public GroundCoverAsset(JsonDictWrapper item, string file) : base(item, file) { - Definition = new GroundCoverDefinition(item.Dict); + GroundCover = new GroundCover(item.Dict); + } + + public void CreateNew(AssetCollection instances) + { + } } diff --git a/Assets/GroundCoverInstanceAsset.cs b/Assets/GroundCoverInstanceAsset.cs new file mode 100644 index 0000000..af316f3 --- /dev/null +++ b/Assets/GroundCoverInstanceAsset.cs @@ -0,0 +1,19 @@ +using LevelTemplateCreator.SceneTree; +using LevelTemplateCreator.SceneTree.Main; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace LevelTemplateCreator.Assets; + +internal class GroundCoverInstanceAsset : Asset +{ + public GroundCoverInstance Instance { get; } + + public GroundCoverInstanceAsset(JsonDictWrapper obj, string source) : base(obj, source) + { + Instance = new GroundCoverInstance(obj.Dict); + } +} diff --git a/Assets/IMaterialAsset.cs b/Assets/MaterialAsset.cs similarity index 100% rename from Assets/IMaterialAsset.cs rename to Assets/MaterialAsset.cs diff --git a/Assets/TerrainPbrMaterialAsset.cs b/Assets/TerrainPbrMaterialAsset.cs index 6a4d518..8bd4e2c 100644 --- a/Assets/TerrainPbrMaterialAsset.cs +++ b/Assets/TerrainPbrMaterialAsset.cs @@ -1,4 +1,5 @@ -using LevelTemplateCreator.SceneTree; +using LevelTemplateCreator.IO.Resources; +using LevelTemplateCreator.SceneTree; using LevelTemplateCreator.SceneTree.Art; using System; using System.Collections.Generic; @@ -31,17 +32,11 @@ internal class TerrainPbrMaterialAsset : MaterialAsset Name = Material.InternalName.Value; - /* - if (material.TryPopValue("groundcover", out Dictionary[] groundcover)) - { - - } - */ - - SetLayerIfEmpty(Material.AmbientOcclusion.Base, "#ffffff"); - SetLayerIfEmpty(Material.Normal.Base, "#7f7fff"); - SetLayerIfEmpty(Material.Height.Base, "#000000"); - SetLayerIfEmpty(Material.BaseColor.Base, "#515151"); + SetLayerIfEmpty(Material.AmbientOcclusion.Base, SolidColorNames.BaseAmbientOcclusion); + SetLayerIfEmpty(Material.Normal.Base, SolidColorNames.BaseNormal); + SetLayerIfEmpty(Material.Height.Base, SolidColorNames.BaseHeight); + SetLayerIfEmpty(Material.BaseColor.Base, SolidColorNames.BaseColor); + SetLayerIfEmpty(Material.Roughness.Base, SolidColorNames.BaseRoughness); } void SetLayerIfEmpty(TerrainMaterialTextureLayer layer, string value) diff --git a/EnvironmentInfo.cs b/EnvironmentInfo.cs index 9c7feba..4a542f6 100644 --- a/EnvironmentInfo.cs +++ b/EnvironmentInfo.cs @@ -164,4 +164,9 @@ static public void Save() using var stream = new FileStream(ConfigFilePath, FileMode.Create); JsonDictSerializer.Serialize(stream, dict, true); } + + public static void PrintSumary() + { + Console.WriteLine(); + } } diff --git a/GUI/AssetListBox.cs b/GUI/AssetListBox.cs deleted file mode 100644 index 7227d83..0000000 --- a/GUI/AssetListBox.cs +++ /dev/null @@ -1,69 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; -using System.Drawing; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Forms; -using LevelTemplateCreator.Assets; - -namespace LevelTemplateCreator; - -public partial class AssetListBox : ListBox -{ - public AssetListBox() - { - - } - - protected override void OnDrawItem(DrawItemEventArgs e) - { - var brush = new SolidBrush(e.ForeColor); - base.OnDrawItem(e); - var g = e.Graphics; - - if (e.Index >= Items.Count || e.Index < 0) - { - return; - } - - var item = (Asset)Items[e.Index]; - - var bounds = e.Bounds; - - var boundsPreview = new Rectangle(bounds.X, bounds.Y, bounds.Height, bounds.Height); - - var boundsText = new Rectangle(bounds.Height, bounds.Y, bounds.Width - bounds.Height, bounds.Height); - - Brush backcolor = e.Index % 2 == 0 ? Brushes.White : Brushes.Lavender; - - if (e.State.HasFlag(DrawItemState.Selected)) - { - backcolor = Brushes.LightBlue; - } - - g.FillRectangle(backcolor, bounds); - - if (item.Preview != null) - { - g.DrawImage(item.Preview, boundsPreview); - } - else - { - g.FillRectangle(Brushes.DarkGray, boundsPreview); - } - - - - - - g.DrawString(item.Name, e.Font, brush, boundsText); - - - - - - } -} diff --git a/GUI/AssetViewBox.cs b/GUI/AssetViewBox.cs new file mode 100644 index 0000000..ae1379e --- /dev/null +++ b/GUI/AssetViewBox.cs @@ -0,0 +1,184 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using LevelTemplateCreator.Assets; +using static System.Windows.Forms.VisualStyles.VisualStyleElement; + +namespace LevelTemplateCreator; + +internal class AssetViewBox : Control +{ + public List Items { get; } + + public int ItemHeight { get; set; } + + public int Position { get; set; } + + public int MaxPosition => Items.Count * ItemHeight; + + public int HoveredIndex { get; private set; } + + public VScrollBar ScrollBar { get; } + + public Action OnItemClick { get; set; } + + public AssetViewBox() + { + Items = new List(); + ItemHeight = 128; + + DoubleBuffered = true; + + ScrollBar = new VScrollBar(); + ScrollBar.Dock = DockStyle.Right; + ScrollBar.LargeChange = 200; + ScrollBar.ValueChanged += (object? sender, EventArgs e) => { + Position = ScrollBar.Value; + Invalidate(); + }; + + Controls.Add(ScrollBar); + } + + public void ItemsChanged() + { + ScrollBar.Maximum = MaxPosition + ScrollBar.LargeChange - 1; + Items.Sort((x, y) => x.Name.CompareTo(y.Name)); + + Invalidate(); + } + + protected override void OnPaint(PaintEventArgs e) + { + base.OnPaint(e); + + var g = e.Graphics; + + for (var i = 0; i < Items.Count; i++) + { + var asset = Items[i]; + DrawItem(g, asset, i); + } + } + + protected override void OnMouseWheel(MouseEventArgs e) + { + base.OnMouseWheel(e); + + Position -= e.Delta; + + if (Position > MaxPosition) { + Position = MaxPosition; + } + + if (Position < 0) + { + Position = 0; + } + + ScrollBar.Value = Position; + + Invalidate(); + } + + protected override void OnMouseClick(MouseEventArgs e) + { + base.OnMouseClick(e); + + if (HoveredIndex < 0) + return; + + if (HoveredIndex > Items.Count - 1) + return; + + if (OnItemClick == null) + return; + + OnItemClick(Items[HoveredIndex]); + } + + protected override void OnMouseMove(MouseEventArgs e) + { + base.OnMouseMove(e); + + HoveredIndex = (e.Location.Y + Position) / ItemHeight; + + Invalidate(); + } + + protected override void OnMouseLeave(EventArgs e) + { + base.OnMouseLeave(e); + + HoveredIndex = -1; + + Invalidate(); + } + + Rectangle GetBounds(int index) + { + return new Rectangle(0, ItemHeight * index - Position, ClientSize.Width, ItemHeight); + } + + + void DrawItem(Graphics g, Asset item, int index) + { + + var brush = new SolidBrush(Color.Black); + + var bounds = GetBounds(index); + + var boundsPreview = new Rectangle(bounds.X, bounds.Y, bounds.Height, bounds.Height); + + var boundsText = new Rectangle(bounds.Height, bounds.Y, bounds.Width - bounds.Height, bounds.Height); + + Brush backcolor = index % 2 == 0 ? Brushes.White : Brushes.Lavender; + + g.FillRectangle(backcolor, bounds); + + if (item.Preview != null) + { + g.DrawImage(item.Preview, boundsPreview); + } + else + { + g.FillRectangle(Brushes.DarkGray, boundsPreview); + } + + var sb = new StringBuilder(); + if (!string.IsNullOrEmpty(item.Name)) + { + sb.AppendLine(item.Name); + } + if (!string.IsNullOrEmpty(item.Description)) + { + sb.AppendLine(item.Description); + } + sb.AppendLine(item.Object.Class.Value); + sb.AppendLine(item.SourceFile); + + g.DrawString(sb.ToString(), Font, brush, boundsText); + + + + if (HoveredIndex == index) + { + int offset = 2; + var rect = new Rectangle(boundsPreview.X + offset, boundsPreview.Y + offset, boundsPreview.Width - offset * 2, boundsPreview.Height - offset * 2); + var pen = new Pen(Color.Green, offset*2); + g.DrawRectangle(pen, rect); + + var bru = new SolidBrush(Color.FromArgb(50, Color.Lime)); + g.FillRectangle(bru, boundsPreview); + } + + + } +} diff --git a/GUI/ContentManager.Designer.cs b/GUI/ContentManager.Designer.cs index 3615cbe..b929ff1 100644 --- a/GUI/ContentManager.Designer.cs +++ b/GUI/ContentManager.Designer.cs @@ -29,8 +29,8 @@ protected override void Dispose(bool disposing) private void InitializeComponent() { tableLayoutPanel1 = new TableLayoutPanel(); - AssetListBoxAvailable = new AssetListBox(); - AssetListBoxSelected = new AssetListBox(); + AssetListBoxAvailable = new AssetViewBox(); + AssetListBoxSelected = new AssetViewBox(); tableLayoutPanel1.SuspendLayout(); SuspendLayout(); // @@ -53,28 +53,18 @@ private void InitializeComponent() // AssetListBoxAvailable // AssetListBoxAvailable.Dock = DockStyle.Fill; - AssetListBoxAvailable.DrawMode = DrawMode.OwnerDrawFixed; - AssetListBoxAvailable.FormattingEnabled = true; - AssetListBoxAvailable.IntegralHeight = false; - AssetListBoxAvailable.ItemHeight = 128; AssetListBoxAvailable.Location = new Point(612, 0); AssetListBoxAvailable.Margin = new Padding(0); AssetListBoxAvailable.Name = "AssetListBoxAvailable"; - AssetListBoxAvailable.ScrollAlwaysVisible = true; AssetListBoxAvailable.Size = new Size(592, 701); AssetListBoxAvailable.TabIndex = 0; // // AssetListBoxSelected // AssetListBoxSelected.Dock = DockStyle.Fill; - AssetListBoxSelected.DrawMode = DrawMode.OwnerDrawFixed; - AssetListBoxSelected.FormattingEnabled = true; - AssetListBoxSelected.IntegralHeight = false; - AssetListBoxSelected.ItemHeight = 64; AssetListBoxSelected.Location = new Point(0, 0); AssetListBoxSelected.Margin = new Padding(0); AssetListBoxSelected.Name = "AssetListBoxSelected"; - AssetListBoxSelected.ScrollAlwaysVisible = true; AssetListBoxSelected.Size = new Size(592, 701); AssetListBoxSelected.TabIndex = 1; // @@ -92,7 +82,7 @@ private void InitializeComponent() #endregion private TableLayoutPanel tableLayoutPanel1; - public AssetListBox AssetListBoxAvailable; - public AssetListBox AssetListBoxSelected; + public AssetViewBox AssetListBoxAvailable; + public AssetViewBox AssetListBoxSelected; } } diff --git a/GUI/ContentManager.cs b/GUI/ContentManager.cs index 7359604..dc2501c 100644 --- a/GUI/ContentManager.cs +++ b/GUI/ContentManager.cs @@ -1,4 +1,5 @@ -using System; +using LevelTemplateCreator.Assets; +using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; @@ -15,5 +16,72 @@ internal partial class ContentManager : UserControl public ContentManager() { InitializeComponent(); + + AssetListBoxAvailable.OnItemClick = Select; + AssetListBoxSelected.OnItemClick = Deselcet; + } + + void Select(Asset a) + { + AssetListBoxAvailable.Items.Remove(a); + AssetListBoxSelected.Items.Add(a); + + ItemsChanged(); + } + + void Deselcet(Asset a) + { + AssetListBoxSelected.Items.Remove(a); + AssetListBoxAvailable.Items.Add(a); + + ItemsChanged(); + } + + public void SetItemHeight(int value) + { + AssetListBoxAvailable.ItemHeight = value; + AssetListBoxSelected.ItemHeight = value; + + ItemsChanged(); + } + + public void SetLibary(AssetLibary libary) + { + AssetListBoxAvailable.Items.Clear(); + AssetListBoxSelected.Items.Clear(); + + foreach (var item in libary.TerrainMaterials) + { + AssetListBoxAvailable.Items.Add(item); + } + + foreach (var item in libary.LevelPresets) + { + AssetListBoxAvailable.Items.Add(item); + } + + ItemsChanged(); + + TrySelcet(libary.TerrainMaterials, "10m_grid"); + TrySelcet(libary.LevelPresets, "Default"); + } + + void TrySelcet(AssetCollection values, string key) where T : Asset + { + if (values.TryGetValue(key, out var value)) + { + Select(value); + } + } + + public Asset[] GetSelectedAssets() + { + return AssetListBoxSelected.Items.ToArray(); + } + + void ItemsChanged() + { + AssetListBoxAvailable.ItemsChanged(); + AssetListBoxSelected.ItemsChanged(); } } diff --git a/GUI/LevelSettings.Designer.cs b/GUI/LevelSettings.Designer.cs index 94e2a89..fd4642e 100644 --- a/GUI/LevelSettings.Designer.cs +++ b/GUI/LevelSettings.Designer.cs @@ -28,233 +28,66 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - groupBox3 = new GroupBox(); - tableLayoutPanel2 = new TableLayoutPanel(); - comboBoxPreset = new ComboBox(); - label6 = new Label(); - textBoxNamespace = new TextBox(); - label7 = new Label(); - groupBox2 = new GroupBox(); TerainSettings = new TerrainSettings(); - groupBox1 = new GroupBox(); - tableLayoutPanel1 = new TableLayoutPanel(); - label4 = new Label(); - textBoxAuthors = new TextBox(); - label2 = new Label(); - textBoxTitle = new TextBox(); - groupBox3.SuspendLayout(); - tableLayoutPanel2.SuspendLayout(); - groupBox2.SuspendLayout(); - groupBox1.SuspendLayout(); - tableLayoutPanel1.SuspendLayout(); + TextBoxNamespace = new LabledTextbox(); + TextBoxTitle = new LabledTextbox(); + TextBoxAuthor = new LabledTextbox(); SuspendLayout(); // - // groupBox3 - // - groupBox3.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; - groupBox3.AutoSizeMode = AutoSizeMode.GrowAndShrink; - groupBox3.Controls.Add(tableLayoutPanel2); - groupBox3.Location = new Point(3, 3); - groupBox3.Name = "groupBox3"; - groupBox3.Size = new Size(297, 100); - groupBox3.TabIndex = 11; - groupBox3.TabStop = false; - groupBox3.Text = "System"; - // - // tableLayoutPanel2 - // - tableLayoutPanel2.AutoSize = true; - tableLayoutPanel2.AutoSizeMode = AutoSizeMode.GrowAndShrink; - tableLayoutPanel2.ColumnCount = 2; - tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle()); - tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle()); - tableLayoutPanel2.Controls.Add(comboBoxPreset, 1, 1); - tableLayoutPanel2.Controls.Add(label6, 0, 1); - tableLayoutPanel2.Controls.Add(textBoxNamespace, 1, 0); - tableLayoutPanel2.Controls.Add(label7, 0, 0); - tableLayoutPanel2.Dock = DockStyle.Fill; - tableLayoutPanel2.GrowStyle = TableLayoutPanelGrowStyle.FixedSize; - tableLayoutPanel2.Location = new Point(3, 19); - tableLayoutPanel2.Name = "tableLayoutPanel2"; - tableLayoutPanel2.RightToLeft = RightToLeft.No; - tableLayoutPanel2.RowCount = 3; - tableLayoutPanel2.RowStyles.Add(new RowStyle()); - tableLayoutPanel2.RowStyles.Add(new RowStyle()); - tableLayoutPanel2.RowStyles.Add(new RowStyle()); - tableLayoutPanel2.Size = new Size(291, 78); - tableLayoutPanel2.TabIndex = 7; - // - // comboBoxPreset - // - comboBoxPreset.Dock = DockStyle.Fill; - comboBoxPreset.DropDownWidth = 100; - comboBoxPreset.FormattingEnabled = true; - comboBoxPreset.Location = new Point(78, 32); - comboBoxPreset.Name = "comboBoxPreset"; - comboBoxPreset.Size = new Size(210, 23); - comboBoxPreset.TabIndex = 8; - // - // label6 - // - label6.Anchor = AnchorStyles.Left; - label6.AutoSize = true; - label6.Location = new Point(3, 36); - label6.Name = "label6"; - label6.Size = new Size(69, 15); - label6.TabIndex = 2; - label6.Text = "Level Preset"; - // - // textBoxNamespace - // - textBoxNamespace.Dock = DockStyle.Fill; - textBoxNamespace.Location = new Point(78, 3); - textBoxNamespace.Name = "textBoxNamespace"; - textBoxNamespace.Size = new Size(210, 23); - textBoxNamespace.TabIndex = 0; - textBoxNamespace.TextChanged += textBoxNamespace_TextChanged; - // - // label7 - // - label7.Anchor = AnchorStyles.Left; - label7.AutoSize = true; - label7.Location = new Point(3, 7); - label7.Name = "label7"; - label7.Size = new Size(69, 15); - label7.TabIndex = 0; - label7.Text = "Namepsace"; - // - // groupBox2 - // - groupBox2.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; - groupBox2.AutoSizeMode = AutoSizeMode.GrowAndShrink; - groupBox2.Controls.Add(TerainSettings); - groupBox2.Location = new Point(6, 212); - groupBox2.MinimumSize = new Size(100, 100); - groupBox2.Name = "groupBox2"; - groupBox2.Size = new Size(294, 145); - groupBox2.TabIndex = 10; - groupBox2.TabStop = false; - groupBox2.Text = "Terrain"; - // // TerainSettings // - TerainSettings.Dock = DockStyle.Fill; - TerainSettings.Location = new Point(3, 19); + TerainSettings.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; + TerainSettings.Location = new Point(3, 90); TerainSettings.MaximumSize = new Size(10000, 116); TerainSettings.MinimumSize = new Size(0, 116); TerainSettings.Name = "TerainSettings"; - TerainSettings.Size = new Size(288, 116); + TerainSettings.Size = new Size(514, 116); TerainSettings.TabIndex = 0; // - // groupBox1 - // - groupBox1.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; - groupBox1.AutoSizeMode = AutoSizeMode.GrowAndShrink; - groupBox1.Controls.Add(tableLayoutPanel1); - groupBox1.Location = new Point(6, 109); - groupBox1.MinimumSize = new Size(100, 100); - groupBox1.Name = "groupBox1"; - groupBox1.Size = new Size(294, 100); - groupBox1.TabIndex = 9; - groupBox1.TabStop = false; - groupBox1.Text = "Info"; - // - // tableLayoutPanel1 + // TextBoxNamespace // - tableLayoutPanel1.AutoSizeMode = AutoSizeMode.GrowAndShrink; - tableLayoutPanel1.ColumnCount = 2; - tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle()); - tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle()); - tableLayoutPanel1.Controls.Add(label4, 0, 1); - tableLayoutPanel1.Controls.Add(textBoxAuthors, 1, 1); - tableLayoutPanel1.Controls.Add(label2, 0, 0); - tableLayoutPanel1.Controls.Add(textBoxTitle, 1, 0); - tableLayoutPanel1.Dock = DockStyle.Fill; - tableLayoutPanel1.GrowStyle = TableLayoutPanelGrowStyle.FixedSize; - tableLayoutPanel1.Location = new Point(3, 19); - tableLayoutPanel1.Name = "tableLayoutPanel1"; - tableLayoutPanel1.RightToLeft = RightToLeft.No; - tableLayoutPanel1.RowCount = 3; - tableLayoutPanel1.RowStyles.Add(new RowStyle()); - tableLayoutPanel1.RowStyles.Add(new RowStyle()); - tableLayoutPanel1.RowStyles.Add(new RowStyle()); - tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F)); - tableLayoutPanel1.Size = new Size(288, 78); - tableLayoutPanel1.TabIndex = 5; + TextBoxNamespace.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; + TextBoxNamespace.LabelText = "Namespace"; + TextBoxNamespace.Location = new Point(3, 3); + TextBoxNamespace.Name = "TextBoxNamespace"; + TextBoxNamespace.Size = new Size(511, 23); + TextBoxNamespace.TabIndex = 1; // - // label4 + // TextBoxTitle // - label4.Anchor = AnchorStyles.Left; - label4.AutoSize = true; - label4.Location = new Point(3, 36); - label4.Name = "label4"; - label4.Size = new Size(49, 15); - label4.TabIndex = 8; - label4.Text = "Authors"; + TextBoxTitle.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; + TextBoxTitle.LabelText = "Title"; + TextBoxTitle.Location = new Point(3, 32); + TextBoxTitle.Name = "TextBoxTitle"; + TextBoxTitle.Size = new Size(511, 23); + TextBoxTitle.TabIndex = 2; // - // textBoxAuthors + // TextBoxAuthor // - textBoxAuthors.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; - textBoxAuthors.Location = new Point(58, 32); - textBoxAuthors.Name = "textBoxAuthors"; - textBoxAuthors.Size = new Size(227, 23); - textBoxAuthors.TabIndex = 4; - textBoxAuthors.TextChanged += textBoxAuthors_TextChanged; - // - // label2 - // - label2.Anchor = AnchorStyles.Left; - label2.AutoSize = true; - label2.Location = new Point(3, 7); - label2.Name = "label2"; - label2.Size = new Size(29, 15); - label2.TabIndex = 2; - label2.Text = "Title"; - // - // textBoxTitle - // - textBoxTitle.Dock = DockStyle.Fill; - textBoxTitle.Location = new Point(58, 3); - textBoxTitle.Name = "textBoxTitle"; - textBoxTitle.Size = new Size(227, 23); - textBoxTitle.TabIndex = 3; - textBoxTitle.TextChanged += textBoxTitle_TextChanged; + TextBoxAuthor.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; + TextBoxAuthor.LabelText = "Authors"; + TextBoxAuthor.Location = new Point(3, 61); + TextBoxAuthor.Name = "TextBoxAuthor"; + TextBoxAuthor.Size = new Size(511, 23); + TextBoxAuthor.TabIndex = 3; // // LevelSettings // AutoScaleDimensions = new SizeF(7F, 15F); AutoScaleMode = AutoScaleMode.Font; - Controls.Add(groupBox3); - Controls.Add(groupBox2); - Controls.Add(groupBox1); + Controls.Add(TextBoxAuthor); + Controls.Add(TextBoxTitle); + Controls.Add(TextBoxNamespace); + Controls.Add(TerainSettings); Name = "LevelSettings"; - Size = new Size(303, 378); - groupBox3.ResumeLayout(false); - groupBox3.PerformLayout(); - tableLayoutPanel2.ResumeLayout(false); - tableLayoutPanel2.PerformLayout(); - groupBox2.ResumeLayout(false); - groupBox1.ResumeLayout(false); - tableLayoutPanel1.ResumeLayout(false); - tableLayoutPanel1.PerformLayout(); + Size = new Size(517, 535); ResumeLayout(false); } #endregion - - private GroupBox groupBox3; - private TableLayoutPanel tableLayoutPanel2; - private ComboBox comboBoxPreset; - private Label label6; - private TextBox textBoxNamespace; - private Label label7; - private GroupBox groupBox2; - private GroupBox groupBox1; - private TableLayoutPanel tableLayoutPanel1; - private Label label4; - private TextBox textBoxAuthors; - private Label label2; - private TextBox textBoxTitle; public TerrainSettings TerainSettings; + private LabledTextbox TextBoxNamespace; + private LabledTextbox TextBoxTitle; + private LabledTextbox TextBoxAuthor; } } diff --git a/GUI/LevelSettings.cs b/GUI/LevelSettings.cs index a172327..991dec9 100644 --- a/GUI/LevelSettings.cs +++ b/GUI/LevelSettings.cs @@ -14,54 +14,50 @@ namespace LevelTemplateCreator.GUI; internal partial class LevelSettings : UserControl { - Level _level; + Level? _level; - public Level Level { get => _level; set => SetLevel(value); } - - public AssetLibary AssetLibary => Level.Libary; - - public LevelPreset SelectedLevelPreset => (LevelPreset)comboBoxPreset.SelectedItem; - - void SetLevel(Level level) + public void SetLevel(Level level) { _level = level; if (_level == null) return; - if (AssetLibary.LevelPresets.Count > 0) - { - foreach (var item in AssetLibary.LevelPresets) - { - comboBoxPreset.Items.Add(item); - } - comboBoxPreset.SelectedIndex = 0; - } - - TerainSettings.Terrain = Level.Terrain; + TerainSettings.Terrain = _level.Terrain; - textBoxNamespace.Text = Level.Namespace; - textBoxTitle.Text = Level.Info.Title; - textBoxAuthors.Text = Level.Info.Authors; + TextBoxNamespace.Text = _level.Namespace; + TextBoxTitle.Text = _level.Info.Title; + TextBoxAuthor.Text = _level.Info.Authors; } public LevelSettings() { InitializeComponent(); + + } private void textBoxNamespace_TextChanged(object sender, EventArgs e) { - Level.Namespace = textBoxNamespace.Text; + if (_level == null) + return; + + _level.Namespace = TextBoxNamespace.Text; } private void textBoxTitle_TextChanged(object sender, EventArgs e) { - Level.Info.Title = textBoxTitle.Text; + if (_level == null) + return; + + _level.Info.Title = TextBoxTitle.Text; } private void textBoxAuthors_TextChanged(object sender, EventArgs e) { - Level.Info.Authors = textBoxAuthors.Text; + if (_level == null) + return; + + _level.Info.Authors = TextBoxAuthor.Text; } } diff --git a/GUI/MainForm.Designer.cs b/GUI/MainForm.Designer.cs index 3b6e408..45f0c35 100644 --- a/GUI/MainForm.Designer.cs +++ b/GUI/MainForm.Designer.cs @@ -30,8 +30,6 @@ private void InitializeComponent() { menuStrip1 = new MenuStrip(); fileToolStripMenuItem = new ToolStripMenuItem(); - newToolStripMenuItem = new ToolStripMenuItem(); - toolStripSeparator1 = new ToolStripSeparator(); saveToolStripMenuItem = new ToolStripMenuItem(); saveAsToolStripMenuItem = new ToolStripMenuItem(); toolStripSeparator3 = new ToolStripSeparator(); @@ -40,9 +38,14 @@ private void InitializeComponent() systemToolStripMenuItem = new ToolStripMenuItem(); utilsToolStripMenuItem = new ToolStripMenuItem(); createTexturePackFromLevelToolStripMenuItem = new ToolStripMenuItem(); + displayToolStripMenuItem = new ToolStripMenuItem(); + itemSizeToolStripMenuItem = new ToolStripMenuItem(); + toolStripMenuItem2 = new ToolStripMenuItem(); + toolStripMenuItem3 = new ToolStripMenuItem(); + toolStripMenuItem4 = new ToolStripMenuItem(); splitContainer1 = new SplitContainer(); LevelSettings = new GUI.LevelSettings(); - contentManager1 = new GUI.ContentManager(); + ContentManager = new GUI.ContentManager(); menuStrip1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)splitContainer1).BeginInit(); splitContainer1.Panel1.SuspendLayout(); @@ -52,7 +55,7 @@ private void InitializeComponent() // // menuStrip1 // - menuStrip1.Items.AddRange(new ToolStripItem[] { fileToolStripMenuItem, settingsToolStripMenuItem, utilsToolStripMenuItem }); + menuStrip1.Items.AddRange(new ToolStripItem[] { fileToolStripMenuItem, settingsToolStripMenuItem, displayToolStripMenuItem, utilsToolStripMenuItem }); menuStrip1.Location = new Point(0, 0); menuStrip1.Name = "menuStrip1"; menuStrip1.Size = new Size(1335, 24); @@ -61,23 +64,11 @@ private void InitializeComponent() // // fileToolStripMenuItem // - fileToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { newToolStripMenuItem, toolStripSeparator1, saveToolStripMenuItem, saveAsToolStripMenuItem, toolStripSeparator3, exitToolStripMenuItem }); + fileToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { saveToolStripMenuItem, saveAsToolStripMenuItem, toolStripSeparator3, exitToolStripMenuItem }); fileToolStripMenuItem.Name = "fileToolStripMenuItem"; fileToolStripMenuItem.Size = new Size(37, 20); fileToolStripMenuItem.Text = "File"; // - // newToolStripMenuItem - // - newToolStripMenuItem.Name = "newToolStripMenuItem"; - newToolStripMenuItem.ShortcutKeys = Keys.Control | Keys.N; - newToolStripMenuItem.Size = new Size(186, 22); - newToolStripMenuItem.Text = "New"; - // - // toolStripSeparator1 - // - toolStripSeparator1.Name = "toolStripSeparator1"; - toolStripSeparator1.Size = new Size(183, 6); - // // saveToolStripMenuItem // saveToolStripMenuItem.Name = "saveToolStripMenuItem"; @@ -117,13 +108,14 @@ private void InitializeComponent() // systemToolStripMenuItem // systemToolStripMenuItem.Name = "systemToolStripMenuItem"; - systemToolStripMenuItem.Size = new Size(144, 22); + systemToolStripMenuItem.Size = new Size(180, 22); systemToolStripMenuItem.Text = "System Paths"; systemToolStripMenuItem.Click += systemToolStripMenuItem_Click; // // utilsToolStripMenuItem // utilsToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { createTexturePackFromLevelToolStripMenuItem }); + utilsToolStripMenuItem.Enabled = false; utilsToolStripMenuItem.Name = "utilsToolStripMenuItem"; utilsToolStripMenuItem.Size = new Size(42, 20); utilsToolStripMenuItem.Text = "Utils"; @@ -135,6 +127,41 @@ private void InitializeComponent() createTexturePackFromLevelToolStripMenuItem.Text = "Create Texture Pack From Level"; createTexturePackFromLevelToolStripMenuItem.Click += createTexturePackFromLevelToolStripMenuItem_Click; // + // displayToolStripMenuItem + // + displayToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { itemSizeToolStripMenuItem }); + displayToolStripMenuItem.Name = "displayToolStripMenuItem"; + displayToolStripMenuItem.Size = new Size(57, 20); + displayToolStripMenuItem.Text = "Display"; + // + // itemSizeToolStripMenuItem + // + itemSizeToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { toolStripMenuItem2, toolStripMenuItem3, toolStripMenuItem4 }); + itemSizeToolStripMenuItem.Name = "itemSizeToolStripMenuItem"; + itemSizeToolStripMenuItem.Size = new Size(121, 22); + itemSizeToolStripMenuItem.Text = "Item Size"; + // + // toolStripMenuItem2 + // + toolStripMenuItem2.Name = "toolStripMenuItem2"; + toolStripMenuItem2.Size = new Size(180, 22); + toolStripMenuItem2.Text = "Small Icons"; + toolStripMenuItem2.Click += toolStripMenuItem2_Click; + // + // toolStripMenuItem3 + // + toolStripMenuItem3.Name = "toolStripMenuItem3"; + toolStripMenuItem3.Size = new Size(180, 22); + toolStripMenuItem3.Text = "Medium Icons"; + toolStripMenuItem3.Click += toolStripMenuItem3_Click; + // + // toolStripMenuItem4 + // + toolStripMenuItem4.Name = "toolStripMenuItem4"; + toolStripMenuItem4.Size = new Size(180, 22); + toolStripMenuItem4.Text = "Large Icons"; + toolStripMenuItem4.Click += toolStripMenuItem4_Click; + // // splitContainer1 // splitContainer1.Dock = DockStyle.Fill; @@ -148,7 +175,7 @@ private void InitializeComponent() // // splitContainer1.Panel2 // - splitContainer1.Panel2.Controls.Add(contentManager1); + splitContainer1.Panel2.Controls.Add(ContentManager); splitContainer1.Size = new Size(1335, 558); splitContainer1.SplitterDistance = 346; splitContainer1.TabIndex = 10; @@ -156,19 +183,18 @@ private void InitializeComponent() // LevelSettings // LevelSettings.Dock = DockStyle.Fill; - LevelSettings.Level = null; LevelSettings.Location = new Point(0, 0); LevelSettings.Name = "LevelSettings"; LevelSettings.Size = new Size(346, 558); LevelSettings.TabIndex = 11; // - // contentManager1 + // ContentManager // - contentManager1.Dock = DockStyle.Fill; - contentManager1.Location = new Point(0, 0); - contentManager1.Name = "contentManager1"; - contentManager1.Size = new Size(985, 558); - contentManager1.TabIndex = 0; + ContentManager.Dock = DockStyle.Fill; + ContentManager.Location = new Point(0, 0); + ContentManager.Name = "ContentManager"; + ContentManager.Size = new Size(985, 558); + ContentManager.TabIndex = 0; // // MainForm // @@ -177,6 +203,7 @@ private void InitializeComponent() ClientSize = new Size(1335, 582); Controls.Add(splitContainer1); Controls.Add(menuStrip1); + DoubleBuffered = true; MainMenuStrip = menuStrip1; Name = "MainForm"; Text = "Template Creator"; @@ -194,8 +221,6 @@ private void InitializeComponent() #endregion private MenuStrip menuStrip1; private ToolStripMenuItem fileToolStripMenuItem; - private ToolStripMenuItem newToolStripMenuItem; - private ToolStripSeparator toolStripSeparator1; private ToolStripMenuItem saveToolStripMenuItem; private ToolStripMenuItem saveAsToolStripMenuItem; private ToolStripSeparator toolStripSeparator3; @@ -207,6 +232,11 @@ private void InitializeComponent() private Label label1; private SplitContainer splitContainer1; private GUI.LevelSettings LevelSettings; - private GUI.ContentManager contentManager1; + private GUI.ContentManager ContentManager; + private ToolStripMenuItem displayToolStripMenuItem; + private ToolStripMenuItem itemSizeToolStripMenuItem; + private ToolStripMenuItem toolStripMenuItem2; + private ToolStripMenuItem toolStripMenuItem3; + private ToolStripMenuItem toolStripMenuItem4; } } diff --git a/GUI/MainForm.cs b/GUI/MainForm.cs index 18dc380..e61beaa 100644 --- a/GUI/MainForm.cs +++ b/GUI/MainForm.cs @@ -1,4 +1,5 @@ using System.Diagnostics; +using System.Text; using LevelTemplateCreator.Assets; namespace LevelTemplateCreator @@ -13,7 +14,7 @@ public MainForm() InitializeComponent(); AssetLibary = new AssetLibary(); - Level = new Level(AssetLibary); + Level = new Level(); } private void groupBox2_Enter(object sender, EventArgs e) @@ -29,11 +30,7 @@ private void createTexturePackFromLevelToolStripMenuItem_Click(object sender, Ev private void saveToolStripMenuItem_Click(object sender, EventArgs e) { - if (!EnvironmentInfo.IsValid) { - new SettingsForm().ShowDialog(this); - } - - Export(EnvironmentInfo.UserData.LevelsPath); + Export(); } private void saveAsToolStripMenuItem_Click(object sender, EventArgs e) @@ -47,8 +44,41 @@ private void saveAsToolStripMenuItem_Click(object sender, EventArgs e) } } + bool AssertEnvironmentInfo() + { + if (EnvironmentInfo.IsValid) + return true; + + new SettingsForm().ShowDialog(this); + + if (EnvironmentInfo.IsValid) + return true; + + var sb = new StringBuilder(); + sb.AppendLine("Some of the paths are not correctly set, the program will not work correctly until this is fixed."); + sb.AppendLine(); + sb.AppendLine($"BeamNG-gamdata path valid: {EnvironmentInfo.GameData.IsValid}"); + sb.AppendLine($"BeamNG-userdata path valid: {EnvironmentInfo.UserData.IsValid}"); + sb.AppendLine($"Content path valid: {EnvironmentInfo.Packages.IsValid}"); + + MessageBox.Show(this, sb.ToString(), "Invalid Paths.", MessageBoxButtons.OK, MessageBoxIcon.Error); + + return false; + } + + void Export() + { + if (!AssertEnvironmentInfo()) + return; + + Export(EnvironmentInfo.UserData.LevelsPath); + } + void Export(string path) { + if (!AssertEnvironmentInfo()) + return; + var fullPath = Path.Combine(path, Level.Namespace); if (Directory.Exists(fullPath)) @@ -65,14 +95,11 @@ void Export(string path) Directory.CreateDirectory(fullPath); - Level.TerrainMaterials.Clear(); - foreach (var material in AssetLibary.TerrainMaterials) - { - Level.TerrainMaterials.Add(material); - } + Level.Content.Clear(); + Level.Content.Add(ContentManager.GetSelectedAssets()); + Level.Content.Preview = AssetLibary.Preview; + Level.Content.PrintSumary(); - Level.LevelPreset = LevelSettings.SelectedLevelPreset; - Level.Preview = AssetLibary.Preview; Level.Export(fullPath); if (MessageBox.Show(this, $"Level '{Level.Namespace}' at '{path}' successfully created, do you want to open it now?", "Template successfully created", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) @@ -94,45 +121,41 @@ private void MainForm_Load(object sender, EventArgs e) { EnvironmentInfo.Load(); + AssertEnvironmentInfo(); - if (!EnvironmentInfo.IsValid) + if (!EnvironmentInfo.Packages.IsValid) { - new SettingsForm().ShowDialog(this); + Close(); + return; } - var sw = Stopwatch.StartNew(); + EnvironmentInfo.PrintSumary(); var loader = new AssetLibaryLoader(AssetLibary); loader.LoadDirectory(EnvironmentInfo.Packages.Path); + loader.PrintErrors(); - if (loader.Errors.Count > 0) - { - var error = loader.Errors[0]; - var exception = error.Exception; - MessageBox.Show($"Error at '{error.File}'\n\n{exception.Message}\n\n{exception.StackTrace}", exception.GetType().FullName, MessageBoxButtons.OK, MessageBoxIcon.Error); - } - - /* - try - { - //AssetLibary.LoadDirectory(EnvironmentInfo.Packages.Path); - } - catch (Exception ex) - { - MessageBox.Show($"{ex.Message}\n\n{ex.StackTrace}", ex.GetType().FullName, MessageBoxButtons.OK, MessageBoxIcon.Error); - } - */ + AssetLibary.SeperateGroundCoverInstances(); + AssetLibary.PrintSumary(); - Console.WriteLine(sw.ElapsedMilliseconds); + LevelSettings.SetLevel(Level); - LevelSettings.Level = Level; + ContentManager.SetLibary(AssetLibary); + } - foreach (var item in AssetLibary.TerrainMaterials) - { - contentManager1.AssetListBoxAvailable.Items.Add(item); - } + private void toolStripMenuItem2_Click(object sender, EventArgs e) + { + ContentManager.SetItemHeight(64); + } + private void toolStripMenuItem3_Click(object sender, EventArgs e) + { + ContentManager.SetItemHeight(128); + } + private void toolStripMenuItem4_Click(object sender, EventArgs e) + { + ContentManager.SetItemHeight(256); } } } diff --git a/IO/JsonDictSerializer.cs b/IO/JsonDictSerializer.cs index 32c2aaa..84cf364 100644 --- a/IO/JsonDictSerializer.cs +++ b/IO/JsonDictSerializer.cs @@ -20,7 +20,7 @@ public static void Serialize(Stream stream, T value, bool intended = false) w JsonSerializer.Serialize(stream, value, options); } - public static Dictionary Deserialize(Stream stream) => Deserialize>(stream); + public static JsonDict Deserialize(Stream stream) => Deserialize(stream); public static T Deserialize(Stream stream) where T : IDictionary, new() { @@ -80,7 +80,7 @@ public static object GetArray(JsonElement json) if (first.ValueKind == JsonValueKind.Object) { - var objarray = new Dictionary[count]; + var objarray = new JsonDict[count]; for (int i = 0; i < count; i++) { @@ -102,9 +102,9 @@ public static object GetArray(JsonElement json) return array; } - public static Dictionary GetDict(JsonElement json) + public static JsonDict GetDict(JsonElement json) { - var result = new Dictionary(); + var result = new JsonDict(); GetDict(json, result); return result; } diff --git a/IO/LevelInfoSerializer.cs b/IO/LevelInfoSerializer.cs index 643204b..f6c0ab8 100644 --- a/IO/LevelInfoSerializer.cs +++ b/IO/LevelInfoSerializer.cs @@ -17,14 +17,14 @@ public static void Serialize(Level level, string path) public static void Serialize(Level level, Stream stream) { - var dict = new Dictionary() + var dict = new JsonDict() { ["defaultSpawnPointName"] = "spawn_default", ["size"] = new[] { level.Terrain.WorldSize, level.Terrain.WorldSize }, ["previews"] = new[] { "preview.png" }, - ["spawnPoints"] = new Dictionary[] + ["spawnPoints"] = new JsonDict[] { new() { diff --git a/IO/Resources/Resource.cs b/IO/Resources/Resource.cs index 485c543..94cdc20 100644 --- a/IO/Resources/Resource.cs +++ b/IO/Resources/Resource.cs @@ -1,5 +1,7 @@ -using System; +using LevelTemplateCreator.Properties; +using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -10,14 +12,25 @@ internal abstract class Resource { public string Name { get; } + public string DynamicName { get; protected set; } + public Resource(string name) { Name = name; + DynamicName = name; } public abstract Stream OpenStream(); - public virtual void Save(string path) + public void SaveToDirectory(string directory) + { + using var stream = OpenStream(); + var dstpath = Path.Combine(directory, DynamicName); + using var file = File.OpenWrite(dstpath); + stream.CopyTo(file); + } + + public void Save(string path) { using var src = OpenStream(); using var dst = new FileStream(path, FileMode.Create); diff --git a/IO/Resources/ResourceManager.cs b/IO/Resources/ResourceManager.cs index 4cd7f37..e351a19 100644 --- a/IO/Resources/ResourceManager.cs +++ b/IO/Resources/ResourceManager.cs @@ -14,6 +14,14 @@ internal class ResourceManager : IEnumerable { public Dictionary Files { get; } + + static readonly Dictionary _colors; + + static ResourceManager() + { + _colors = new(); + } + public ResourceManager() { Files = new Dictionary(); @@ -69,19 +77,16 @@ public static Resource Parse(string entry) if (entry.StartsWith('#')) { - var hex = entry.Substring(1); + var name = entry.Substring(1); + var key = $"#{name}.png"; int color; - try + + if (!int.TryParse(name, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out color)) { - color = int.Parse(hex, NumberStyles.HexNumber); + SolidColorNames.TryGet(entry, out color); } - catch { - throw new Exception($"Could not parse color '{entry}'"); - } - - var key = $"rgb#{hex}.png"; var resource = new SolidColorResource(key, color); return resource; @@ -120,8 +125,7 @@ public void Save(string path) { foreach (var resource in Files.Values) { - var dstpath = Path.Combine(path, resource.Name); - resource.Save(dstpath); + resource.SaveToDirectory(path); } } diff --git a/IO/Resources/SolidColorNames.cs b/IO/Resources/SolidColorNames.cs new file mode 100644 index 0000000..af963ac --- /dev/null +++ b/IO/Resources/SolidColorNames.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; +using System.Threading.Tasks; + +namespace LevelTemplateCreator.IO.Resources; + +internal static class SolidColorNames +{ + static readonly Dictionary _colors; + + public const string BaseNormal = "#base_nm"; + public const string BaseHeight= "#base_h"; + public const string BaseAmbientOcclusion = "#base_ao"; + public const string BaseColor = "#base_b"; + public const string BaseRoughness = "#base_r"; + + public const string AsphaltRoughness = "#asphalt_r"; + public const string AsphaltWetRoughness = "#asphalt_wet_r"; + + public const string GrassRoughness = "#grass_r"; + public const string DirtRoughness = "#dirt_r"; + public const string RockRoughness = "#rock_r"; + public const string MudRoughness = "#mud_r"; + + static SolidColorNames() + { + _colors = new Dictionary(); + _colors[BaseNormal] = 0x7f7fff; + _colors[BaseAmbientOcclusion] = 0xffffff; + _colors[BaseHeight] = 0x000000; + _colors[BaseRoughness] = 0xe7e7e7; + _colors[BaseColor] = 0x808080; + + _colors[AsphaltRoughness] = 0xd4d4d4; + _colors[AsphaltWetRoughness] = 0x464646; + _colors[GrassRoughness] = 0xe7e7e7; + _colors[DirtRoughness] = 0xe7e7e7; + _colors[RockRoughness] = 0xd4d4d4; + _colors[MudRoughness] = 0x464646; + } + + public static bool TryGet(string key, out int hex) + { + if (_colors.TryGetValue(key, out uint value)) + { + hex = Unsafe.As(ref value); + return true; + } + hex = 0; + return false; + } +} diff --git a/IO/Resources/ZipFileResource.cs b/IO/Resources/ZipFileResource.cs index 9ac9f76..2f6e6a5 100644 --- a/IO/Resources/ZipFileResource.cs +++ b/IO/Resources/ZipFileResource.cs @@ -21,25 +21,24 @@ public ZipFileResource(string name, string zipFilePath, string path) : base(name public override Stream OpenStream() { - var zipfile = ZipFile.OpenRead(ZipFilePath); - var entry = zipfile.GetEntry(EntryPath); + var archive = ZipFileManager.Open(ZipFilePath); + var entry = archive.GetEntry(EntryPath); if (entry == null) { - var match = Path.ChangeExtension(EntryPath, null).ToLower(); - - foreach (var e in zipfile.Entries) + var ext = Path.GetExtension(EntryPath).ToLower(); + if (ext == ".png") { - var zipmatch = Path.ChangeExtension(e.FullName, null).ToLower(); - if (zipmatch == match) - { - entry = e; - } + DynamicName = Path.ChangeExtension(Name, ".dds"); + var path = Path.ChangeExtension(EntryPath, ".dds"); + entry = archive.GetEntry(path); } } if (entry == null) + { throw new Exception($"Could not find '{EntryPath}' in '{ZipFilePath}'."); + } return entry.Open(); } diff --git a/IO/ZipFileManager.cs b/IO/ZipFileManager.cs new file mode 100644 index 0000000..618698f --- /dev/null +++ b/IO/ZipFileManager.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.IO.Compression; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace LevelTemplateCreator.IO; + +internal static class ZipFileManager +{ + public class ZipArchiveWrapper : IDisposable + { + readonly ZipArchive _archive; + + Dictionary? _lEntries; + + public ZipArchiveWrapper(ZipArchive archive) + { + _archive = archive; + } + + public bool TryGetEntry(string name, out ZipArchiveEntry entry) + { + var result = _archive.GetEntry(name)!; + if (result != null) + { + entry = result; + return true; + } + + if (_lEntries == null) + { + _lEntries = new Dictionary(); + + foreach (var zipentry in _archive.Entries) + { + _lEntries.Add(PathToLower(zipentry.FullName), zipentry); + } + } + + var lname = PathToLower(name); + if (_lEntries.TryGetValue(lname, out result)) + { + entry = result; + return true; + } + + entry = null!; + return false; + } + + public ZipArchiveEntry? GetEntry(string name) + { + TryGetEntry(name, out var entry); + return entry; + } + + public void Dispose() => _archive.Dispose(); + } + + static readonly Dictionary _archives; + + static ZipFileManager() + { + _archives = new(); + } + + static string PathToLower(string path) + { + return path.ToLower(); + } + + public static ZipArchiveWrapper Open(string path) + { + var fullpath = Path.GetFullPath(PathToLower(path)); + + if (_archives.TryGetValue(fullpath, out var wrapper)) + { + return wrapper; + } + + Console.WriteLine($"Open {fullpath}"); + + var archive = ZipFile.OpenRead(fullpath); + var newwrapper = new ZipArchiveWrapper(archive); + _archives[fullpath] = newwrapper; + return newwrapper; + } + + public static void Clear() + { + foreach (var pair in _archives) + { + Console.WriteLine($"Close {pair.Key}"); + pair.Value.Dispose(); + } + + _archives.Clear(); + } +} diff --git a/Level.cs b/Level.cs index 74323e5..ad4b321 100644 --- a/Level.cs +++ b/Level.cs @@ -16,21 +16,15 @@ namespace LevelTemplateCreator; internal class Level { - public AssetLibary Libary { get; } + public AssetLibary Content { get; } public string Namespace { get; set; } public LevelInfo Info { get; set; } - public List TerrainMaterials { get; set; } - public TerrainInfo Terrain { get; set; } - public LevelPreset? LevelPreset { get; set; } - - public Bitmap? Preview { get; set; } - - public Level(AssetLibary libary) + public Level() { Namespace = "new_pbr_template"; Info = new LevelInfo(); @@ -38,8 +32,7 @@ public Level(AssetLibary libary) { Resolution = 1024, }; - TerrainMaterials = new(); - Libary = libary; + Content = new AssetLibary(); } public TerrainBlock BuildTerrainBlock() @@ -54,11 +47,7 @@ public MaterialLibary BuildTerrainMaterialLibary() { var path = $"/levels/{Namespace}/art/terrains"; var lib = new MaterialLibary(path); - - foreach (var asset in TerrainMaterials) - { - lib.AddAsset(asset); - } + lib.AddAssets(Content.TerrainMaterials); lib.CreateTerrainMaterialTextureSet($"{Namespace}_TerrainMaterialTextureSet"); @@ -74,11 +63,14 @@ public SimGroup BuildMissionGroup() var terrain = BuildTerrainBlock(); levelObject.Terrain.Items.Add(terrain); - LevelPreset?.Apply(levelObject); + foreach (var preset in Content.LevelPresets) + { + preset.Apply(levelObject); + } - foreach (var cover in Libary.GroundCoverAssets) + foreach (var cover in Content.GroundCoverDefinitions) { - levelObject.Vegatation.Items.Add(cover.Definition); + levelObject.Vegatation.Items.Add(cover.GroundCover); } return root; @@ -92,11 +84,7 @@ public void Export(string path) var objpath = $"/levels/{Namespace}/art/objects"; var lib = new MaterialLibary(objpath); - - foreach (var asset in Libary.ObjectMaterials) - { - lib.AddAsset(asset); - } + lib.AddAssets(Content.ObjectMaterials); lib.SerializeItems(Path.Combine(path, "art/objects/" + MaterialLibary.FileName)); lib.Textures.Save(Path.Combine(path, "art/objects")); @@ -110,7 +98,7 @@ public void Export(string path) terrainMaterials.Textures.Save(texturespath); - Preview?.Save(Path.Combine(path, "preview.png")); + Content.Preview?.Save(Path.Combine(path, "preview.png")); BuildMissionGroup().SaveTree(Path.Combine(path, "main")); @@ -120,5 +108,7 @@ public void Export(string path) TerrainV9Serializer.Serialize(Terrain, names, Path.Combine(path, "terrain.ter")); LevelInfoSerializer.Serialize(this, Path.Combine(path, "info.json")); + + ZipFileManager.Clear(); } } diff --git a/SceneTree/Art/MaterialGroup.cs b/SceneTree/Art/MaterialGroup.cs deleted file mode 100644 index 2a7e1e5..0000000 --- a/SceneTree/Art/MaterialGroup.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace LevelTemplateCreator.SceneTree.Art; - -internal class MaterialGroup -{ - -} diff --git a/SceneTree/Art/MaterialLibary.cs b/SceneTree/Art/MaterialLibary.cs index 7b7e462..bb0dcce 100644 --- a/SceneTree/Art/MaterialLibary.cs +++ b/SceneTree/Art/MaterialLibary.cs @@ -39,6 +39,14 @@ public void AddAsset(MaterialAsset asset) Materials.Add(material); } + public void AddAssets(IEnumerable assets) + { + foreach (var asset in assets) + { + AddAsset(asset); + } + } + public string[] GetMaterialNames() { diff --git a/SceneTree/Art/MaterialNode.cs b/SceneTree/Art/MaterialNode.cs new file mode 100644 index 0000000..fdcd61b --- /dev/null +++ b/SceneTree/Art/MaterialNode.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace LevelTemplateCreator.SceneTree.Art; + +internal class MaterialNode +{ + public string Name { get; } + + public List Children { get; } + + public MaterialNode(string name) + { + Name = name; + + Children = new List(); + } + + public void SaveTree() + { + + } +} diff --git a/SceneTree/Art/TerrainPbrMaterial.cs b/SceneTree/Art/TerrainPbrMaterial.cs index 18c2d16..174bbca 100644 --- a/SceneTree/Art/TerrainPbrMaterial.cs +++ b/SceneTree/Art/TerrainPbrMaterial.cs @@ -30,8 +30,6 @@ public TerrainPbrMaterial(JsonDict dict) : base(dict) { GroundModel = new(this, "groundmodelName"); - Class.Value = ClassName; - BaseColor = new(this, "baseColor"); Normal = new(this, "normal"); Roughness = new(this, "roughness"); diff --git a/SceneTree/Main/GroundCover.cs b/SceneTree/Main/GroundCover.cs index 97fe5c6..45e9c2e 100644 --- a/SceneTree/Main/GroundCover.cs +++ b/SceneTree/Main/GroundCover.cs @@ -8,9 +8,17 @@ namespace LevelTemplateCreator.SceneTree.Main; internal class GroundCover : SimItem { - public const string ClassName = "GroundCover"; + public const string ClassName = "GroundCover_Definition"; + + public JsonDictProperty Material { get; } public GroundCover(JsonDict dict) : base(dict) { + Material = new(this, "material"); + } + + public void AddInstance(GroundCoverInstance instance) + { + } } diff --git a/SceneTree/Main/GroundCoverDefinition.cs b/SceneTree/Main/GroundCoverDefinition.cs deleted file mode 100644 index 6a321f2..0000000 --- a/SceneTree/Main/GroundCoverDefinition.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace LevelTemplateCreator.SceneTree.Main; - -internal class GroundCoverDefinition : SimItem -{ - public const string ClassName = "GroundCover_Definition"; - - public GroundCoverDefinition(JsonDict dict) : base(dict) - { - } -} diff --git a/SceneTree/Main/GroundCoverInstance.cs b/SceneTree/Main/GroundCoverInstance.cs index 4e9f4b5..a7aacfd 100644 --- a/SceneTree/Main/GroundCoverInstance.cs +++ b/SceneTree/Main/GroundCoverInstance.cs @@ -1,4 +1,5 @@ -using System; +using LevelTemplateCreator.SceneTree.Art; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,11 +7,47 @@ namespace LevelTemplateCreator.SceneTree.Main; -internal class GroundCoverInstance : SimItem +internal class GroundCoverInstance : JsonDictWrapper { public const string ClassName = "GroundCover_Instance"; + public JsonDictProperty Layer { get; } + + public JsonDictProperty Parent { get; } + public GroundCoverInstance(JsonDict dict) : base(dict) { + Layer = new(this, "layer"); + Parent = new(this, "parent"); + } + + public static GroundCoverInstance[] PopFromGroundcover(GroundCover obj) + { + return PopFromObject(obj, "Types", "parent"); + } + + public static GroundCoverInstance[] PopFromMaterial(TerrainPbrMaterial obj) + { + return PopFromObject(obj, "groundcover", "layer"); + } + + static GroundCoverInstance[] PopFromObject(JsonDictWrapper obj, string name, string parent) + { + var array = new JsonDictProperty(obj, name); + + if (!array.Exists) + return Array.Empty(); + + var result = new GroundCoverInstance[array.Value.Length]; + for (int i = 0; i < array.Value.Length; i++) + { + var instance = new GroundCoverInstance(array.Value[i]); + instance[parent] = obj.Name.Value; + result[i] = instance; + } + + array.Remove(); + + return result; } }