v0.13.0.11
This commit is contained in:
@@ -0,0 +1,262 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.IO;
|
||||
using Barotrauma.Items.Components;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public class SpreadsheetExport
|
||||
{
|
||||
private const char separator = ',';
|
||||
private const string debugIdentifier = "_spreadsheet";
|
||||
|
||||
public static void Export()
|
||||
{
|
||||
XDocument doc = new XDocument();
|
||||
if (doc.Root == null)
|
||||
{
|
||||
doc.Add(new XElement("Content"));
|
||||
}
|
||||
|
||||
XElement root = doc.Root!;
|
||||
|
||||
foreach (ItemPrefab prefab in ItemPrefab.Prefabs)
|
||||
{
|
||||
XElement itemElement = new XElement("Item",
|
||||
new XAttribute("identifier", prefab.Identifier),
|
||||
new XAttribute("name", prefab.Name),
|
||||
new XAttribute("tags", FormatArray(prefab.Tags)),
|
||||
new XAttribute("value", prefab.DefaultPrice?.Price ?? 0)
|
||||
);
|
||||
|
||||
itemElement.Add(ParseRecipe(prefab));
|
||||
itemElement.Add(ParseDecon(prefab));
|
||||
itemElement.Add(ParseMedical(prefab));
|
||||
itemElement.Add(ParseWeapon(prefab));
|
||||
|
||||
root.Add(itemElement);
|
||||
}
|
||||
|
||||
System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings
|
||||
{
|
||||
Indent = false,
|
||||
NewLineOnAttributes = false
|
||||
};
|
||||
|
||||
using XmlWriter? writer = XmlWriter.Create("spreadsheetdata.xml", settings);
|
||||
doc.SaveSafe(writer);
|
||||
}
|
||||
|
||||
private static XElement ParseRecipe(ItemPrefab prefab)
|
||||
{
|
||||
FabricationRecipe? recipe = prefab.FabricationRecipes.FirstOrDefault();
|
||||
|
||||
List<ItemPrefab> ingredients = recipe?.RequiredItems.SelectMany(ri => ri.ItemPrefabs).Distinct().ToList() ?? new List<ItemPrefab>();
|
||||
Skill? skill = recipe?.RequiredSkills.FirstOrDefault();
|
||||
|
||||
return new XElement("Recipe",
|
||||
new XAttribute("amount", recipe?.Amount ?? 0),
|
||||
new XAttribute("time", recipe?.RequiredTime ?? 0),
|
||||
new XAttribute("skillname", skill?.Identifier ?? ""),
|
||||
new XAttribute("skillamount", (int?) skill?.Level ?? 0),
|
||||
new XAttribute("ingredients", FormatArray(ingredients.Select(ip => ip.Name))),
|
||||
new XAttribute("values", FormatArray(ingredients.Select(ip => ip.DefaultPrice?.Price ?? 0)))
|
||||
);
|
||||
}
|
||||
|
||||
private static XElement ParseDecon(ItemPrefab prefab)
|
||||
{
|
||||
List<ItemPrefab> deconOutput = prefab.DeconstructItems.Select(item => ItemPrefab.Find(null, item.ItemIdentifier)).Where(outputPrefab => outputPrefab != null).ToList();
|
||||
return new XElement("Deconstruct",
|
||||
new XAttribute("time", prefab.DeconstructTime),
|
||||
new XAttribute("outputs", FormatArray(deconOutput.Select(ip => ip.Name))),
|
||||
new XAttribute("values", FormatArray(deconOutput.Select(ip => ip.DefaultPrice?.Price ?? 0)))
|
||||
);
|
||||
}
|
||||
|
||||
private static XElement ParseMedical(ItemPrefab prefab)
|
||||
{
|
||||
XElement? itemMeleeWeapon = prefab.ConfigElement.GetChildElement(nameof(MeleeWeapon));
|
||||
// affliction, amount, duration
|
||||
List<Tuple<string, float, float>> onSuccessAfflictions = new List<Tuple<string, float, float>>();
|
||||
List<Tuple<string, float, float>> onFailureAfflictions = new List<Tuple<string, float, float>>();
|
||||
int medicalRequiredSkill = 0;
|
||||
if (itemMeleeWeapon != null)
|
||||
{
|
||||
List<StatusEffect> statusEffects = new List<StatusEffect>();
|
||||
foreach (XElement subElement in itemMeleeWeapon.Elements())
|
||||
{
|
||||
string name = subElement.Name.ToString();
|
||||
if (name.Equals(nameof(StatusEffect), StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
StatusEffect statusEffect = StatusEffect.Load(subElement, debugIdentifier);
|
||||
if (statusEffect == null || !statusEffect.HasTag("medical")) { continue; }
|
||||
|
||||
statusEffects.Add(statusEffect);
|
||||
}
|
||||
else if (IsRequiredSkill(subElement, out Skill? skill) && skill != null)
|
||||
{
|
||||
medicalRequiredSkill = (int) skill.Level;
|
||||
}
|
||||
}
|
||||
|
||||
List<StatusEffect> successEffects = statusEffects.Where(se => se.type == ActionType.OnUse).ToList();
|
||||
List<StatusEffect> failureEffects = statusEffects.Where(se => se.type == ActionType.OnFailure).ToList();
|
||||
|
||||
foreach (StatusEffect statusEffect in successEffects)
|
||||
{
|
||||
float duration = statusEffect.Duration;
|
||||
onSuccessAfflictions.AddRange(statusEffect.ReduceAffliction.Select(pair => Tuple.Create(GetAfflictionName(pair.First), -pair.Second, duration)));
|
||||
onSuccessAfflictions.AddRange(statusEffect.Afflictions.Select(affliction => Tuple.Create(affliction.Prefab.Name, affliction.NonClampedStrength, duration)));
|
||||
}
|
||||
|
||||
foreach (StatusEffect statusEffect in failureEffects)
|
||||
{
|
||||
float duration = statusEffect.Duration;
|
||||
onFailureAfflictions.AddRange(statusEffect.ReduceAffliction.Select(pair => Tuple.Create(GetAfflictionName(pair.First), -pair.Second, duration)));
|
||||
onFailureAfflictions.AddRange(statusEffect.Afflictions.Select(affliction => Tuple.Create(affliction.Prefab.Name, affliction.NonClampedStrength, duration)));
|
||||
}
|
||||
}
|
||||
|
||||
return new XElement("Medical",
|
||||
new XAttribute("skillamount", medicalRequiredSkill),
|
||||
new XAttribute("successafflictions", FormatArray(onSuccessAfflictions.Select(tpl => tpl.Item1))),
|
||||
new XAttribute("successamounts", FormatArray(onSuccessAfflictions.Select(tpl => FormatFloat(tpl.Item2)))),
|
||||
new XAttribute("successdurations", FormatArray(onSuccessAfflictions.Select(tpl => FormatFloat(tpl.Item3)))),
|
||||
new XAttribute("failureafflictions", FormatArray(onFailureAfflictions.Select(tpl => tpl.Item1))),
|
||||
new XAttribute("failureamounts", FormatArray(onFailureAfflictions.Select(tpl => FormatFloat(tpl.Item2)))),
|
||||
new XAttribute("failuredurations", FormatArray(onFailureAfflictions.Select(tpl => FormatFloat(tpl.Item3))))
|
||||
);
|
||||
}
|
||||
|
||||
private static XElement ParseWeapon(ItemPrefab prefab)
|
||||
{
|
||||
float stun = 0;
|
||||
bool isAoE = false;
|
||||
float? structDamage = null;
|
||||
int skillRequirement = 0;
|
||||
|
||||
// affliction, amount
|
||||
List<Tuple<string, float>> damages = new List<Tuple<string, float>>();
|
||||
|
||||
string[] validNames = { nameof(Projectile), nameof(MeleeWeapon), nameof(RepairTool), nameof(ItemComponent), nameof(RangedWeapon) };
|
||||
foreach (XElement icElement in prefab.ConfigElement.Elements())
|
||||
{
|
||||
string icName = icElement.Name.ToString();
|
||||
if (!validNames.Any(name => icName.Equals(name, StringComparison.OrdinalIgnoreCase))) { continue; }
|
||||
|
||||
foreach (XElement icChildElement in icElement.Elements())
|
||||
{
|
||||
string name = icChildElement.Name.ToString();
|
||||
if (IsRequiredSkill(icChildElement, out Skill? skill) && skill != null)
|
||||
{
|
||||
skillRequirement = (int) skill.Level;
|
||||
}
|
||||
else if (name.Equals(nameof(Attack), StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
ParseAttack(new Attack(icChildElement, debugIdentifier));
|
||||
}
|
||||
else if (name.Equals(nameof(Explosion), StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
ParseExplosion(new[] { new Explosion(icChildElement, debugIdentifier) });
|
||||
}
|
||||
else if (name.Equals(nameof(StatusEffect), StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
ParseStatusEffect(new[] { StatusEffect.Load(icChildElement, debugIdentifier) });
|
||||
}
|
||||
|
||||
void ParseStatusEffect(IEnumerable<StatusEffect> statusEffects)
|
||||
{
|
||||
foreach (StatusEffect effect in statusEffects)
|
||||
{
|
||||
if (effect.HasTargetType(StatusEffect.TargetType.Character)) { continue; }
|
||||
|
||||
ParseAfflictions(effect.Afflictions);
|
||||
ParseExplosion(effect.Explosions);
|
||||
}
|
||||
}
|
||||
|
||||
void ParseExplosion(IEnumerable<Explosion> explosions)
|
||||
{
|
||||
foreach (Explosion explosion in explosions)
|
||||
{
|
||||
isAoE = true;
|
||||
ParseAttack(explosion.Attack);
|
||||
ParseStatusEffect(explosion.Attack.StatusEffects);
|
||||
}
|
||||
}
|
||||
|
||||
void ParseAttack(Attack attack)
|
||||
{
|
||||
structDamage ??= attack.StructureDamage;
|
||||
ParseAfflictions(attack.Afflictions.Keys);
|
||||
ParseStatusEffect(attack.StatusEffects);
|
||||
}
|
||||
|
||||
void ParseAfflictions(IEnumerable<Affliction> afflictions)
|
||||
{
|
||||
foreach (Affliction affliction in afflictions)
|
||||
{
|
||||
// Exclude stuns
|
||||
if (affliction.Prefab == AfflictionPrefab.Stun)
|
||||
{
|
||||
stun += affliction.NonClampedStrength;
|
||||
continue;
|
||||
}
|
||||
|
||||
damages.Add(Tuple.Create(affliction.Prefab.Name, affliction.NonClampedStrength));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new XElement("Weapon",
|
||||
new XAttribute("damagenames", FormatArray(damages.Select(tpl => tpl.Item1))),
|
||||
new XAttribute("damageamounts", FormatArray(damages.Select(tpl => FormatFloat(tpl.Item2)))),
|
||||
new XAttribute("isaoe", isAoE),
|
||||
new XAttribute("structuredamage", structDamage ?? 0),
|
||||
new XAttribute("stun", FormatFloat(stun)),
|
||||
new XAttribute("skillrequirement", skillRequirement)
|
||||
);
|
||||
}
|
||||
|
||||
private static string GetAfflictionName(string identifier)
|
||||
{
|
||||
return AfflictionPrefab.Prefabs.Find(prefab => prefab.Identifier.Equals(identifier, StringComparison.OrdinalIgnoreCase))?.Name ?? CultureInfo.CurrentCulture.TextInfo.ToTitleCase(identifier.ToLower());
|
||||
}
|
||||
|
||||
private static string FormatFloat(float value)
|
||||
{
|
||||
return value.ToString("0.00", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
private static string FormatArray<T>(IEnumerable<T> array)
|
||||
{
|
||||
return string.Join(separator, array);
|
||||
}
|
||||
|
||||
private static bool IsRequiredSkill(XElement element, out Skill? skill)
|
||||
{
|
||||
string name = element.Name.ToString();
|
||||
bool isSkill = name.Equals("RequiredSkill", StringComparison.OrdinalIgnoreCase) ||
|
||||
name.Equals("RequiredSkills", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
if (isSkill)
|
||||
{
|
||||
string identifier = element.GetAttributeString(nameof(Skill.Identifier).ToLowerInvariant(), string.Empty);
|
||||
float level = element.GetAttributeFloat(nameof(Skill.Level).ToLowerInvariant(), 0f);
|
||||
skill = new Skill(identifier, level);
|
||||
}
|
||||
else
|
||||
{
|
||||
skill = null;
|
||||
}
|
||||
|
||||
return isSkill;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,324 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public class SpriteRecorder : ISpriteBatch, IDisposable
|
||||
{
|
||||
private struct Command
|
||||
{
|
||||
public readonly Texture2D Texture;
|
||||
public readonly VertexPositionColorTexture VertexBL;
|
||||
public readonly VertexPositionColorTexture VertexBR;
|
||||
public readonly VertexPositionColorTexture VertexTL;
|
||||
public readonly VertexPositionColorTexture VertexTR;
|
||||
public readonly float Depth;
|
||||
public readonly Vector2 Min;
|
||||
public readonly Vector2 Max;
|
||||
public readonly int Index;
|
||||
|
||||
public bool Overlaps(Command other)
|
||||
{
|
||||
return
|
||||
Min.X <= other.Max.X && Max.X >= other.Min.X &&
|
||||
Min.Y <= other.Max.Y && Max.Y >= other.Min.Y;
|
||||
}
|
||||
|
||||
public Command(
|
||||
Texture2D texture,
|
||||
Vector2 pos,
|
||||
Rectangle srcRect,
|
||||
Color color,
|
||||
float rotation,
|
||||
Vector2 origin,
|
||||
Vector2 scale,
|
||||
SpriteEffects effects,
|
||||
float depth,
|
||||
int index)
|
||||
{
|
||||
int srcRectLeft = srcRect.Left;
|
||||
int srcRectRight = srcRect.Right;
|
||||
int srcRectTop = srcRect.Top;
|
||||
int srcRectBottom = srcRect.Bottom;
|
||||
if (effects.HasFlag(SpriteEffects.FlipHorizontally))
|
||||
{
|
||||
var temp = srcRectRight;
|
||||
srcRectRight = srcRectLeft;
|
||||
srcRectLeft = temp;
|
||||
}
|
||||
if (effects.HasFlag(SpriteEffects.FlipVertically))
|
||||
{
|
||||
var temp = srcRectBottom;
|
||||
srcRectBottom = srcRectTop;
|
||||
srcRectTop = temp;
|
||||
}
|
||||
|
||||
rotation = MathHelper.ToRadians(rotation);
|
||||
float sin = (float)Math.Sin(rotation);
|
||||
float cos = (float)Math.Cos(rotation);
|
||||
|
||||
var size = srcRect.Size.ToVector2() * scale;
|
||||
|
||||
Vector2 wAdd = new Vector2(size.X * cos, size.X * sin);
|
||||
Vector2 hAdd = new Vector2(-size.Y * sin, size.Y * cos);
|
||||
pos.X -= origin.X * scale.X * cos - origin.Y * scale.Y * sin;
|
||||
pos.Y -= origin.Y * scale.Y * cos + origin.X * scale.X * sin;
|
||||
|
||||
Texture = texture;
|
||||
|
||||
Depth = depth;
|
||||
|
||||
VertexTL.Color = color;
|
||||
VertexTR.Color = color;
|
||||
VertexBL.Color = color;
|
||||
VertexBR.Color = color;
|
||||
|
||||
VertexTL.Position = new Vector3(pos.X, pos.Y, 0f);
|
||||
VertexTR.Position = new Vector3(pos.X + wAdd.X, pos.Y + wAdd.Y, 0f);
|
||||
VertexBL.Position = new Vector3(pos.X + hAdd.X, pos.Y + hAdd.Y, 0f);
|
||||
VertexBR.Position = new Vector3(pos.X + wAdd.X + hAdd.X, pos.Y + wAdd.Y + hAdd.Y, 0f);
|
||||
|
||||
Min = new Vector2(
|
||||
MathUtils.Min
|
||||
(
|
||||
VertexTL.Position.X,
|
||||
VertexTR.Position.X,
|
||||
VertexBL.Position.X,
|
||||
VertexBR.Position.X
|
||||
),
|
||||
MathUtils.Min
|
||||
(
|
||||
VertexTL.Position.Y,
|
||||
VertexTR.Position.Y,
|
||||
VertexBL.Position.Y,
|
||||
VertexBR.Position.Y
|
||||
));
|
||||
|
||||
Max = new Vector2(
|
||||
MathUtils.Max
|
||||
(
|
||||
VertexTL.Position.X,
|
||||
VertexTR.Position.X,
|
||||
VertexBL.Position.X,
|
||||
VertexBR.Position.X
|
||||
),
|
||||
MathUtils.Max
|
||||
(
|
||||
VertexTL.Position.Y,
|
||||
VertexTR.Position.Y,
|
||||
VertexBL.Position.Y,
|
||||
VertexBR.Position.Y
|
||||
));
|
||||
|
||||
VertexTL.TextureCoordinate = new Vector2((float)srcRectLeft / (float)texture.Width, (float)srcRectTop / (float)texture.Height);
|
||||
VertexTR.TextureCoordinate = new Vector2((float)srcRectRight / (float)texture.Width, (float)srcRectTop / (float)texture.Height);
|
||||
VertexBL.TextureCoordinate = new Vector2((float)srcRectLeft / (float)texture.Width, (float)srcRectBottom / (float)texture.Height);
|
||||
VertexBR.TextureCoordinate = new Vector2((float)srcRectRight / (float)texture.Width, (float)srcRectBottom / (float)texture.Height);
|
||||
|
||||
Index = index;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private struct RecordedBuffer
|
||||
{
|
||||
public readonly Texture2D Texture;
|
||||
public readonly VertexBuffer VertexBuffer;
|
||||
public readonly int PolyCount;
|
||||
|
||||
public RecordedBuffer(List<Command> commandList, int startIndex, int count)
|
||||
{
|
||||
Texture = commandList[startIndex].Texture;
|
||||
|
||||
VertexBuffer = new VertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, count * 4, BufferUsage.WriteOnly);
|
||||
VertexPositionColorTexture[] vertices = new VertexPositionColorTexture[count * 4];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
vertices[(i * 4) + 0] = commandList[startIndex + i].VertexBL;
|
||||
vertices[(i * 4) + 1] = commandList[startIndex + i].VertexBR;
|
||||
vertices[(i * 4) + 2] = commandList[startIndex + i].VertexTL;
|
||||
vertices[(i * 4) + 3] = commandList[startIndex + i].VertexTR;
|
||||
}
|
||||
VertexBuffer.SetData(vertices);
|
||||
|
||||
PolyCount = count * 2;
|
||||
}
|
||||
}
|
||||
|
||||
public static BasicEffect BasicEffect = null;
|
||||
|
||||
private List<RecordedBuffer> recordedBuffers = new List<RecordedBuffer>();
|
||||
private List<Command> commandList = new List<Command>();
|
||||
private SpriteSortMode currentSortMode;
|
||||
|
||||
private IndexBuffer indexBuffer = null;
|
||||
private int maxSpriteCount = 0;
|
||||
|
||||
public volatile bool ReadyToRender = false;
|
||||
private volatile bool isDisposed = false;
|
||||
|
||||
public Vector2 Min { get; private set; }
|
||||
public Vector2 Max { get; private set; }
|
||||
|
||||
public void Begin(SpriteSortMode sortMode)
|
||||
{
|
||||
ReadyToRender = false;
|
||||
currentSortMode = sortMode;
|
||||
}
|
||||
|
||||
public void Draw(Texture2D texture, Vector2 pos, Rectangle? srcRect, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float depth)
|
||||
{
|
||||
if (isDisposed) { return; }
|
||||
|
||||
Command command = new Command(texture, pos, srcRect ?? texture.Bounds, color, rotation, origin, scale, effects, depth, commandList?.Count ?? 0);
|
||||
if (commandList.Count == 0) { Min = command.Min; Max = command.Max; }
|
||||
Min = new Vector2(Math.Min(command.Min.X, Min.X), Math.Min(command.Min.Y, Min.Y));
|
||||
Max = new Vector2(Math.Max(command.Max.X, Max.X), Math.Max(command.Max.Y, Max.Y));
|
||||
|
||||
commandList?.Add(command);
|
||||
}
|
||||
|
||||
public void End()
|
||||
{
|
||||
if (isDisposed) { return; }
|
||||
//sort commands according to the sorting
|
||||
//mode given in the last Begin call
|
||||
switch (currentSortMode)
|
||||
{
|
||||
case SpriteSortMode.FrontToBack:
|
||||
commandList.Sort((c1, c2) =>
|
||||
{
|
||||
return c1.Depth < c2.Depth ? -1
|
||||
: c1.Depth > c2.Depth ? 1
|
||||
: c1.Index < c2.Index ? 1
|
||||
: c1.Index > c2.Index ? -1
|
||||
: 0;
|
||||
});
|
||||
break;
|
||||
case SpriteSortMode.BackToFront:
|
||||
commandList.Sort((c1, c2) =>
|
||||
{
|
||||
return c1.Depth < c2.Depth ? 1
|
||||
: c1.Depth > c2.Depth ? -1
|
||||
: c1.Index < c2.Index ? 1
|
||||
: c1.Index > c2.Index ? -1
|
||||
: 0;
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
//try to place commands of the same texture
|
||||
//contiguously for optimal buffer generation
|
||||
//while maintaining the same visual result
|
||||
for (int i=1;i<commandList.Count;i++)
|
||||
{
|
||||
if (commandList[i].Texture != commandList[i-1].Texture)
|
||||
{
|
||||
for (int j = i - 1; j >= 0; j--)
|
||||
{
|
||||
if (commandList[j].Texture == commandList[i].Texture)
|
||||
{
|
||||
//no commands between i and j overlap with
|
||||
//i, therefore we can safely sift i down to
|
||||
//make a contiguous block
|
||||
commandList.SiftElement(i, j + 1);
|
||||
break;
|
||||
}
|
||||
else if (commandList[j].Overlaps(commandList[i]))
|
||||
{
|
||||
//an overlapping command was found, therefore
|
||||
//attempting to sift this one down would change
|
||||
//the visual result
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isDisposed) { return; }
|
||||
//each contiguous block of commands of the same texture
|
||||
//requires a vertex buffer to be rendered
|
||||
CrossThread.RequestExecutionOnMainThread(() =>
|
||||
{
|
||||
if (commandList.Count == 0) { return; }
|
||||
int startIndex = 0;
|
||||
for (int i = 1; i < commandList.Count; i++)
|
||||
{
|
||||
if (commandList[i].Texture != commandList[startIndex].Texture)
|
||||
{
|
||||
maxSpriteCount = Math.Max(maxSpriteCount, i - startIndex);
|
||||
recordedBuffers.Add(new RecordedBuffer(commandList, startIndex, i - startIndex));
|
||||
startIndex = i;
|
||||
}
|
||||
}
|
||||
recordedBuffers.Add(new RecordedBuffer(commandList, startIndex, commandList.Count - startIndex));
|
||||
maxSpriteCount = Math.Max(maxSpriteCount, commandList.Count - startIndex);
|
||||
});
|
||||
|
||||
commandList.Clear();
|
||||
|
||||
ReadyToRender = true;
|
||||
}
|
||||
|
||||
public void Render(Camera cam)
|
||||
{
|
||||
if (!ReadyToRender) { return; }
|
||||
var gfxDevice = GameMain.Instance.GraphicsDevice;
|
||||
|
||||
BasicEffect ??= new BasicEffect(gfxDevice);
|
||||
BasicEffect.Projection = Matrix.CreateOrthographicOffCenter(new Rectangle(0, 0, cam.Resolution.X, cam.Resolution.Y), -1f, 1f);
|
||||
BasicEffect.View = cam.Transform;
|
||||
BasicEffect.World = Matrix.Identity;
|
||||
BasicEffect.TextureEnabled = true;
|
||||
BasicEffect.VertexColorEnabled = true;
|
||||
BasicEffect.Alpha = 1f;
|
||||
|
||||
int requiredIndexCount = maxSpriteCount * 6;
|
||||
if (requiredIndexCount > 0 && (indexBuffer == null || indexBuffer.IndexCount < requiredIndexCount))
|
||||
{
|
||||
indexBuffer?.Dispose();
|
||||
indexBuffer = new IndexBuffer(gfxDevice, IndexElementSize.SixteenBits, requiredIndexCount * 2, BufferUsage.WriteOnly);
|
||||
ushort[] indices = new ushort[requiredIndexCount * 2];
|
||||
for (int i=0;i<indices.Length;i+=6)
|
||||
{
|
||||
indices[i + 0] = (ushort)((i / 6) * 4 + 1);
|
||||
indices[i + 1] = (ushort)((i / 6) * 4 + 0);
|
||||
indices[i + 2] = (ushort)((i / 6) * 4 + 2);
|
||||
indices[i + 3] = (ushort)((i / 6) * 4 + 1);
|
||||
indices[i + 4] = (ushort)((i / 6) * 4 + 2);
|
||||
indices[i + 5] = (ushort)((i / 6) * 4 + 3);
|
||||
}
|
||||
indexBuffer.SetData(indices);
|
||||
}
|
||||
|
||||
gfxDevice.Indices = indexBuffer;
|
||||
for (int i=0;i<recordedBuffers.Count;i++)
|
||||
{
|
||||
gfxDevice.SetVertexBuffer(recordedBuffers[i].VertexBuffer);
|
||||
BasicEffect.Texture = recordedBuffers[i].Texture;
|
||||
BasicEffect.CurrentTechnique.Passes[0].Apply();
|
||||
gfxDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, recordedBuffers[i].PolyCount);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
isDisposed = true;
|
||||
if (recordedBuffers != null)
|
||||
{
|
||||
foreach (var buffer in recordedBuffers)
|
||||
{
|
||||
buffer.VertexBuffer.Dispose();
|
||||
}
|
||||
recordedBuffers.Clear(); recordedBuffers = null;
|
||||
}
|
||||
commandList?.Clear(); commandList = null;
|
||||
indexBuffer?.Dispose(); indexBuffer = null;
|
||||
ReadyToRender = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -100,38 +100,6 @@ namespace Barotrauma
|
||||
return q1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a HSV value into a RGB value.
|
||||
/// </summary>
|
||||
/// <param name="hue">Value between 0 and 360</param>
|
||||
/// <param name="saturation">Value between 0 and 1</param>
|
||||
/// <param name="value">Value between 0 and 1</param>
|
||||
/// <see href="https://en.wikipedia.org/wiki/HSL_and_HSV#HSV_to_RGB">Reference</see>
|
||||
/// <returns></returns>
|
||||
public static Color HSVToRGB(float hue, float saturation, float value)
|
||||
{
|
||||
float c = value * saturation;
|
||||
|
||||
float h = Math.Clamp(hue, 0, 360) / 60f;
|
||||
|
||||
float x = c * (1 - Math.Abs(h % 2 - 1));
|
||||
|
||||
float r = 0,
|
||||
g = 0,
|
||||
b = 0;
|
||||
|
||||
if (0 <= h && h <= 1) { r = c; g = x; b = 0; }
|
||||
else if (1 < h && h <= 2) { r = x; g = c; b = 0; }
|
||||
else if (2 < h && h <= 3) { r = 0; g = c; b = x; }
|
||||
else if (3 < h && h <= 4) { r = 0; g = x; b = c; }
|
||||
else if (4 < h && h <= 5) { r = x; g = 0; b = c; }
|
||||
else if (5 < h && h <= 6) { r = c; g = 0; b = x; }
|
||||
|
||||
float m = value - c;
|
||||
|
||||
return new Color(r + m, g + m, b + m);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a RGB value into a HSV value.
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user