Files
LuaCsForBarotraumaEP/Barotrauma/BarotraumaClient/ClientSource/Screens/ParticleEditorScreen.cs
Joonas Rikkonen c27e2ea5ab v0.14.6.0
2021-06-17 17:58:09 +03:00

386 lines
15 KiB
C#

using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Barotrauma.Particles;
using System;
using System.Collections.Generic;
using System.Xml.Linq;
using System.Text;
using Barotrauma.Extensions;
using FarseerPhysics;
#if DEBUG
using System.IO;
using System.Xml;
#else
using Barotrauma.IO;
#endif
namespace Barotrauma
{
class ParticleEditorScreen : EditorScreen
{
private GUIComponent rightPanel, leftPanel;
private GUIListBox prefabList;
private GUITextBox filterBox;
private GUITextBlock filterLabel;
private ParticlePrefab selectedPrefab;
private readonly ParticleEmitterProperties emitterProperties = new ParticleEmitterProperties(null)
{
ScaleMax = 1f,
ScaleMin = 1f,
AngleMax = 360f,
AngleMin = 0,
ParticlesPerSecond = 1f
};
private ParticleEmitterPrefab emitterPrefab;
private ParticleEmitter emitter;
private readonly Camera cam;
public override Camera Cam => cam;
private const string sizeRefFilePath = "Content/size_reference.png";
private readonly Texture2D sizeReference;
private Vector2 sizeRefPosition = Vector2.Zero;
private readonly Vector2 sizeRefOrigin;
private bool sizeRefEnabled;
public ParticleEditorScreen()
{
cam = new Camera();
GameMain.Instance.ResolutionChanged += CreateUI;
CreateUI();
if (File.Exists(sizeRefFilePath))
{
sizeReference = TextureLoader.FromFile(sizeRefFilePath, compress: false);
sizeRefOrigin = new Vector2(sizeReference.Width / 2f, sizeReference.Height / 2f);
}
}
private void CreateUI()
{
Frame.ClearChildren();
leftPanel = new GUIFrame(new RectTransform(new Vector2(0.125f, 1.0f), Frame.RectTransform) { MinSize = new Point(150, 0) },
style: "GUIFrameLeft");
var paddedLeftPanel = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.95f), leftPanel.RectTransform, Anchor.CenterLeft) { RelativeOffset = new Vector2(0.02f, 0.0f) })
{
RelativeSpacing = 0.01f,
Stretch = true
};
rightPanel = new GUIFrame(new RectTransform(new Vector2(0.25f, 1.0f), Frame.RectTransform, Anchor.TopRight) { MinSize = new Point(350, 0) },
style: "GUIFrameRight");
var paddedRightPanel = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), rightPanel.RectTransform, Anchor.Center) { RelativeOffset = new Vector2(0.02f, 0.0f) })
{
RelativeSpacing = 0.01f,
Stretch = true
};
var saveAllButton = new GUIButton(new RectTransform(new Vector2(1.0f, 0.03f), paddedRightPanel.RectTransform),
TextManager.Get("editor.saveall"))
{
OnClicked = (btn, obj) =>
{
SerializeAll();
return true;
}
};
new GUIButton(new RectTransform(new Vector2(1.0f, 0.03f), paddedRightPanel.RectTransform),
TextManager.Get("ParticleEditor.CopyPrefabToClipboard"))
{
OnClicked = (btn, obj) =>
{
SerializeToClipboard(selectedPrefab);
return true;
}
};
new GUIButton(new RectTransform(new Vector2(1.0f, 0.03f), paddedRightPanel.RectTransform),
TextManager.Get("ParticleEditor.CopyEmitterToClipboard"))
{
OnClicked = (btn, obj) =>
{
SerializeEmitterToClipboard();
return true;
}
};
var emitterListBox = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.25f), paddedRightPanel.RectTransform));
new SerializableEntityEditor(emitterListBox.Content.RectTransform, emitterProperties, false, true, elementHeight: 20, titleFont: GUI.SubHeadingFont);
var listBox = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.6f), paddedRightPanel.RectTransform));
var filterArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.03f), paddedLeftPanel.RectTransform) { MinSize = new Point(0, 20) }, isHorizontal: true)
{
Stretch = true,
UserData = "filterarea"
};
filterLabel = new GUITextBlock(new RectTransform(Vector2.One, filterArea.RectTransform), TextManager.Get("serverlog.filter"), font: GUI.Font) { IgnoreLayoutGroups = true };
filterBox = new GUITextBox(new RectTransform(new Vector2(0.8f, 1.0f), filterArea.RectTransform), font: GUI.Font);
filterBox.OnTextChanged += (textBox, text) => { FilterEmitters(text); return true; };
new GUIButton(new RectTransform(new Vector2(0.05f, 1.0f), filterArea.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "GUICancelButton")
{
OnClicked = (btn, userdata) => { FilterEmitters(""); filterBox.Text = ""; filterBox.Flash(Color.White); return true; }
};
prefabList = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.8f), paddedLeftPanel.RectTransform));
prefabList.OnSelected += (GUIComponent component, object obj) =>
{
cam.Position = Vector2.Zero;
selectedPrefab = obj as ParticlePrefab;
emitterPrefab = new ParticleEmitterPrefab(selectedPrefab, emitterProperties);
emitter = new ParticleEmitter(emitterPrefab);
listBox.ClearChildren();
new SerializableEntityEditor(listBox.Content.RectTransform, selectedPrefab, false, true, elementHeight: 20, titleFont: GUI.SubHeadingFont);
//listBox.Content.RectTransform.NonScaledSize = particlePrefabEditor.RectTransform.NonScaledSize;
//listBox.UpdateScrollBarSize();
return true;
};
if (GameMain.ParticleManager != null) { RefreshPrefabList(); }
}
public override void Select()
{
base.Select();
GameMain.ParticleManager.Camera = cam;
RefreshPrefabList();
}
public override void Deselect()
{
base.Deselect();
GameMain.ParticleManager.Camera = GameMain.GameScreen.Cam;
filterBox.Text = "";
}
private void RefreshPrefabList()
{
prefabList.ClearChildren();
var particlePrefabs = GameMain.ParticleManager.GetPrefabList();
foreach (ParticlePrefab particlePrefab in particlePrefabs)
{
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), prefabList.Content.RectTransform) { MinSize = new Point(0, 20) },
particlePrefab.DisplayName)
{
Padding = Vector4.Zero,
UserData = particlePrefab
};
}
}
private void FilterEmitters(string text)
{
if (string.IsNullOrWhiteSpace(text))
{
filterLabel.Visible = true;
prefabList.Content.Children.ForEach(c => c.Visible = true);
return;
}
text = text.ToLower();
filterLabel.Visible = false;
foreach (GUIComponent child in prefabList.Content.Children)
{
if (!(child is GUITextBlock textBlock)) { continue; }
textBlock.Visible = textBlock.Text.ToLower().Contains(text);
}
}
private void SerializeAll()
{
Barotrauma.IO.Validation.SkipValidationInDebugBuilds = true;
foreach (ContentFile configFile in GameMain.Instance.GetFilesOfType(ContentType.Particles))
{
XDocument doc = XMLExtensions.TryLoadXml(configFile.Path);
if (doc == null) { continue; }
var prefabList = GameMain.ParticleManager.GetPrefabList();
foreach (ParticlePrefab prefab in prefabList)
{
foreach (XElement element in doc.Root.Elements())
{
if (!element.Name.ToString().Equals(prefab.Name, StringComparison.OrdinalIgnoreCase)) { continue; }
SerializableProperty.SerializeProperties(prefab, element, true);
}
}
System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings
{
Indent = true,
OmitXmlDeclaration = true,
NewLineOnAttributes = true
};
using (var writer = XmlWriter.Create(configFile.Path, settings))
{
doc.WriteTo(writer);
writer.Flush();
}
}
Barotrauma.IO.Validation.SkipValidationInDebugBuilds = false;
}
private void SerializeEmitterToClipboard()
{
XElement element = new XElement(nameof(ParticleEmitter));
if (selectedPrefab is { } prefab)
{
element.Add(new XAttribute("particle", prefab.Identifier));
}
SerializableProperty.SerializeProperties(emitterProperties, element, saveIfDefault: false, ignoreEditable: true);
StringBuilder sb = new StringBuilder();
System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings
{
OmitXmlDeclaration = true
};
using (var writer = System.Xml.XmlWriter.Create(sb, settings))
{
element.WriteTo(writer);
writer.Flush();
}
Clipboard.SetText(sb.ToString());
}
private void SerializeToClipboard(ParticlePrefab prefab)
{
if (prefab == null) { return; }
System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings
{
Indent = true,
OmitXmlDeclaration = true,
NewLineOnAttributes = true
};
XElement originalElement = null;
foreach (ContentFile configFile in GameMain.Instance.GetFilesOfType(ContentType.Particles))
{
XDocument doc = XMLExtensions.TryLoadXml(configFile.Path);
if (doc == null) { continue; }
var prefabList = GameMain.ParticleManager.GetPrefabList();
foreach (ParticlePrefab otherPrefab in prefabList)
{
foreach (XElement subElement in doc.Root.Elements())
{
if (!subElement.Name.ToString().Equals(prefab.Name, StringComparison.OrdinalIgnoreCase)) { continue; }
SerializableProperty.SerializeProperties(prefab, subElement, true);
originalElement = subElement;
break;
}
}
}
if (originalElement == null)
{
originalElement = new XElement(prefab.Name);
SerializableProperty.SerializeProperties(prefab, originalElement, true);
}
StringBuilder sb = new StringBuilder();
using (var writer = System.Xml.XmlWriter.Create(sb, settings))
{
originalElement.WriteTo(writer);
writer.Flush();
}
Clipboard.SetText(sb.ToString());
}
public override void Update(double deltaTime)
{
cam.MoveCamera((float)deltaTime, allowMove: true, allowZoom: GUI.MouseOn == null);
if (GUI.MouseOn is null && PlayerInput.PrimaryMouseButtonHeld())
{
sizeRefPosition = cam.ScreenToWorld(PlayerInput.MousePosition);
}
if (PlayerInput.SecondaryMouseButtonClicked())
{
CreateContextMenu();
}
if (selectedPrefab != null && emitter != null)
{
emitter.Emit((float) deltaTime, Vector2.Zero);
}
GameMain.ParticleManager.Update((float)deltaTime);
}
private void CreateContextMenu()
{
GUIContextMenu.CreateContextMenu
(
new ContextMenuOption("subeditor.editbackgroundcolor", true, CreateBackgroundColorPicker),
new ContextMenuOption("editor.togglereferencecharacter", true, delegate { sizeRefEnabled = !sizeRefEnabled; })
);
}
public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
{
cam.UpdateTransform();
GameMain.ParticleManager.UpdateTransforms();
//-------------------------------------------------------
spriteBatch.Begin(SpriteSortMode.Deferred,
BlendState.NonPremultiplied,
null, null, null, null,
cam.Transform);
graphics.Clear(BackgroundColor);
GameMain.ParticleManager.Draw(spriteBatch, false, false, ParticleBlendState.AlphaBlend);
GameMain.ParticleManager.Draw(spriteBatch, true, false, ParticleBlendState.AlphaBlend);
spriteBatch.End();
spriteBatch.Begin(SpriteSortMode.Deferred,
BlendState.Additive,
null, null, null, null,
cam.Transform);
GameMain.ParticleManager.Draw(spriteBatch, false, false, ParticleBlendState.Additive);
GameMain.ParticleManager.Draw(spriteBatch, true, false, ParticleBlendState.Additive);
spriteBatch.End();
if (sizeRefEnabled && !(sizeReference is null))
{
spriteBatch.Begin(SpriteSortMode.Deferred,
BlendState.NonPremultiplied,
null, null, null, null,
cam.Transform);
Vector2 pos = sizeRefPosition;
pos.Y = -pos.Y;
spriteBatch.Draw(sizeReference, pos, null, Color.White, 0f, sizeRefOrigin, new Vector2(0.4f), SpriteEffects.None, 0f);
spriteBatch.End();
}
//-------------------------------------------------------
spriteBatch.Begin(SpriteSortMode.Deferred, null, GUI.SamplerState, null, GameMain.ScissorTestEnable);
GUI.Draw(Cam, spriteBatch);
spriteBatch.End();
}
}
}