diff --git a/GW2EIBuilders/Resources/JS/CR-JS/animator.js b/GW2EIBuilders/Resources/JS/CR-JS/animator.js index 5e86cc55d5..084f1c0857 100644 --- a/GW2EIBuilders/Resources/JS/CR-JS/animator.js +++ b/GW2EIBuilders/Resources/JS/CR-JS/animator.js @@ -112,6 +112,7 @@ class Animator { this.skillMechanicActorData = []; this.actorOrientationData = new Map(); this.backgroundActorData = []; + this.screenSpaceActorData = []; this.backgroundImages = []; this.selectedActor = null; // animation @@ -215,40 +216,43 @@ class Animator { let MetadataClass = null; switch (metadata.type) { case "ActorOrientation": - MetadataClass = ActorOrientationDecorationMetadata; + MetadataClass = ActorOrientationMetadata; break; case "Circle": - MetadataClass = CircleDecorationMetadata; + MetadataClass = CircleMetadata; break; case "Doughnut": - MetadataClass = DoughnutDecorationMetadata; + MetadataClass = DoughnutMetadata; break; case "Line": - MetadataClass = LineDecorationMetadata; + MetadataClass = LineMetadata; break; case "Pie": - MetadataClass = PieDecorationMetadata; + MetadataClass = PieMetadata; break; case "Rectangle": - MetadataClass = RectangleDecorationMetadata; + MetadataClass = RectangleMetadata; break; case "ProgressBar": - MetadataClass = ProgressBarDecorationMetadata; + MetadataClass = ProgressBarMetadata; break; - case "BackgroundIconDecoration": - MetadataClass = IconDecorationMetadata; + case "BackgroundIcon": + MetadataClass = IconMetadata; break; - case "IconDecoration": - MetadataClass = IconDecorationMetadata; + case "Icon": + MetadataClass = IconMetadata; break; - case "IconOverheadDecoration": - MetadataClass = IconOverheadDecorationMetadata; + case "IconOverhead": + MetadataClass = IconOverheadMetadata; break; case "OverheadProgressBar": - MetadataClass = OverheadProgressBarDecorationMetadata; + MetadataClass = OverheadProgressBarMetadata; break; case "MovingPlatform": - MetadataClass = MovingPlatformDecorationMetadata; + MetadataClass = MovingPlatformMetadata; + break; + case "Text": + MetadataClass = TextMetadata; break; default: throw "Unknown decoration type " + metadata.type; @@ -305,7 +309,7 @@ class Animator { case "MovingPlatform": this.backgroundActorData.push(new MovingPlatformDrawable(decorationRendering)); break; - case "BackgroundIconDecoration": + case "BackgroundIcon": this.backgroundActorData.push(new BackgroundIconMechanicDrawable(decorationRendering)); break; default: @@ -314,6 +318,13 @@ class Animator { } else { let DecorationClass; switch (decorationRendering.type) { + case "Text": + if (decorationRendering.connectedTo.isScreenSpace) { + this.screenSpaceActorData.push(new TextDrawable(decorationRendering)); + continue; + } + DecorationClass = TextDrawable; + break; case "Circle": DecorationClass = CircleMechanicDrawable; break; @@ -332,19 +343,19 @@ class Animator { case "Line": DecorationClass = LineMechanicDrawable; break; - case "IconDecoration": + case "Icon": DecorationClass = IconMechanicDrawable; break; - case "IconOverheadDecoration": + case "IconOverhead": this.overheadActorData.push(new IconOverheadMechanicDrawable(decorationRendering)); continue; case "OverheadProgressBar": this.overheadActorData.push(new OverheadProgressBarMechanicDrawable(decorationRendering)); continue; - case "SquadMarkerDecoration": + case "SquadMarker": this.squadMarkerData.push(new IconMechanicDrawable(decorationRendering)); continue; - case "OverheadSquadMarkerDecoration": + case "OverheadSquadMarker": this.overheadSquadMarkerData.push(new IconOverheadMechanicDrawable(decorationRendering)); continue; default: @@ -969,6 +980,15 @@ class Animator { this.overheadSquadMarkerData[i].draw(); } } + ctx.save(); + { + ctx.setTransform(1, 0, 0, 1, 0, 0); + // Screen space actors + for (let i = 0; i < animator.screenSpaceActorData.length; i++) { + animator.screenSpaceActorData[i].draw(); + } + } + ctx.restore() } //ctx.restore(); } diff --git a/GW2EIBuilders/Resources/JS/CR-JS/decorations.js b/GW2EIBuilders/Resources/JS/CR-JS/decorations.js index 9feaa9743f..7709bf1035 100644 --- a/GW2EIBuilders/Resources/JS/CR-JS/decorations.js +++ b/GW2EIBuilders/Resources/JS/CR-JS/decorations.js @@ -4,32 +4,40 @@ /*global animator, ToRadians, overheadAnimationFrame, maxOverheadAnimationFrame, facingIcon, animateCanvas, noUpdateTime, SkillDecorationCategory*/ "use strict"; -class GenericDecorationMetadata { +class GenericMetadata { constructor(params) { } } -class GenericAttachedDecorationMetadata extends GenericDecorationMetadata{ +class TextMetadata extends GenericMetadata{ constructor(params) { super(params); + this.color = params.color; + this.backgroundColor = params.backgroundColor; } } -class ActorOrientationDecorationMetadata extends GenericAttachedDecorationMetadata { +class GenericAttachedMetadata extends GenericMetadata{ constructor(params) { super(params); } } -class FormDecorationMetadata extends GenericAttachedDecorationMetadata { +class ActorOrientationMetadata extends GenericAttachedMetadata { + constructor(params) { + super(params); + } +} + +class FormMetadata extends GenericAttachedMetadata { constructor(params) { super(params); this.color = params.color; } } -class CircleDecorationMetadata extends FormDecorationMetadata { +class CircleMetadata extends FormMetadata { constructor(params) { super(params); this.radius = InchToPixel * params.radius; @@ -37,7 +45,7 @@ class CircleDecorationMetadata extends FormDecorationMetadata { } } -class DoughnutDecorationMetadata extends FormDecorationMetadata { +class DoughnutMetadata extends FormMetadata { constructor(params) { super(params); this.outerRadius = InchToPixel * params.outerRadius; @@ -45,7 +53,7 @@ class DoughnutDecorationMetadata extends FormDecorationMetadata { } } -class LineDecorationMetadata extends FormDecorationMetadata { +class LineMetadata extends FormMetadata { constructor(params) { super(params); this.thickness = params.thickness; @@ -56,7 +64,7 @@ class LineDecorationMetadata extends FormDecorationMetadata { } } -class PieDecorationMetadata extends CircleDecorationMetadata { +class PieMetadata extends CircleMetadata { constructor(params) { super(params); this.openingAngle = params.openingAngle; @@ -65,7 +73,7 @@ class PieDecorationMetadata extends CircleDecorationMetadata { } } -class RectangleDecorationMetadata extends FormDecorationMetadata { +class RectangleMetadata extends FormMetadata { constructor(params) { super(params); this.width = InchToPixel * params.width; @@ -73,14 +81,14 @@ class RectangleDecorationMetadata extends FormDecorationMetadata { } } -class ProgressBarDecorationMetadata extends RectangleDecorationMetadata { +class ProgressBarMetadata extends RectangleMetadata { constructor(params) { super(params); this.secondaryColor = params.secondaryColor; } } -class OverheadProgressBarDecorationMetadata extends ProgressBarDecorationMetadata { +class OverheadProgressBarMetadata extends ProgressBarMetadata { constructor(params) { super(params); this.pixelWidth = params.pixelWidth; @@ -88,7 +96,7 @@ class OverheadProgressBarDecorationMetadata extends ProgressBarDecorationMetadat } } -class GenericIconDecorationMetadata extends GenericAttachedDecorationMetadata{ +class GenericIconMetadata extends GenericAttachedMetadata{ constructor(params) { super(params); this.imageUrl = params.image; @@ -100,32 +108,32 @@ class GenericIconDecorationMetadata extends GenericAttachedDecorationMetadata{ } } -class BackgroundIconDecorationMetadata extends GenericIconDecorationMetadata { +class BackgroundIconMetadata extends GenericIconMetadata { constructor(params) { super(params); } } -class IconDecorationMetadata extends GenericIconDecorationMetadata { +class IconMetadata extends GenericIconMetadata { constructor(params) { super(params); this.opacity = params.opacity; } } -class IconOverheadDecorationMetadata extends IconDecorationMetadata { +class IconOverheadMetadata extends IconMetadata { constructor(params) { super(params); } } -class BackgroundDecorationMetadata extends GenericDecorationMetadata{ +class BackgroundMetadata extends GenericMetadata{ constructor(params) { super(params); } } -class MovingPlatformDecorationMetadata extends BackgroundDecorationMetadata{ +class MovingPlatformMetadata extends BackgroundMetadata{ constructor(params, ) { super(params); this.imageUrl = params.image; @@ -195,9 +203,10 @@ function interpolatedPositionFetcher(connection, master) { } function staticPositionFetcher(connection, master) { + const factor = connection.isScreenSpace ? resolutionMultiplier : 1; return { - x: connection.position[0], - y: connection.position[1] + x: factor * connection.position[0], + y: factor * connection.position[1] }; } @@ -1257,3 +1266,47 @@ class IconOverheadMechanicDrawable extends IconMechanicDrawable { return offset; } } + +// + +class TextDrawable extends MechanicDrawable { + constructor(params) { + super(params); + this.text = params.text; + const bold = !!params.bold; + const fontSize = params.fontSize * resolutionMultiplier + "px"; + const fontType = params.fontType || "Comic Sans MS"; + this.font = (bold ? "bold " : "") + fontSize + " " + fontType; + } + get color() { + return this.metadata.color; + } + get backgroundColor() { + return this.metadata.backgroundColor; + } + + draw() { + if (!this.canDraw()) { + return; + } + const pos = this.getPosition(); + const rot = this.getRotation(); + if (pos === null || rot === null) { + return; + } + + const ctx = animator.mainContext; + ctx.save(); + this.moveContext(ctx, pos, rot); + const normalizedRot = Math.abs((ToRadians(rot + this.rotationOffset) / Math.PI) % 2); + if (0.5 < normalizedRot && normalizedRot < 1.5) { + // make sure the text remains upright + ctx.rotate(-ToRadians(180)); + } + ctx.font = this.font; + ctx.fillStyle = this.color; + ctx.textAlign = "center"; + ctx.fillText(this.text, 0, 0); + ctx.restore(); + } +} diff --git a/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Connector/ConnectorDescription.cs b/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Connector/ConnectorDescription.cs index f64f1e1df2..09bb2fa5d1 100644 --- a/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Connector/ConnectorDescription.cs +++ b/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Connector/ConnectorDescription.cs @@ -11,6 +11,7 @@ namespace GW2EIEvtcParser.EIData; [JsonDerivedType(typeof(PositionConnectorDescription))] [JsonDerivedType(typeof(InterpolationConnectorDescription))] [JsonDerivedType(typeof(AgentConnectorDescription))] +[JsonDerivedType(typeof(ScreenSpaceConnectorDescription))] public abstract class ConnectorDescription { protected ConnectorDescription(Connector connector, CombatReplayMap map, ParsedEvtcLog log) diff --git a/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Connector/GeographicalConnector/GeographicalConnectorDescription.cs b/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Connector/GeographicalConnector/GeographicalConnectorDescription.cs index 2a546bf7c2..472f60a285 100644 --- a/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Connector/GeographicalConnector/GeographicalConnectorDescription.cs +++ b/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Connector/GeographicalConnector/GeographicalConnectorDescription.cs @@ -4,6 +4,7 @@ public abstract class GeographicalConnectorDescription : ConnectorDescription { public readonly IReadOnlyList? Offset; public readonly bool OffsetAfterRotation; + public readonly bool IsScreenSpace; internal GeographicalConnectorDescription(GeographicalConnector connector, CombatReplayMap map, ParsedEvtcLog log) : base(connector, map, log) { if (connector.Offset.HasValue) @@ -14,5 +15,6 @@ internal GeographicalConnectorDescription(GeographicalConnector connector, Comba connector.InvertYOffset ? -connector.Offset.Value.Y : connector.Offset.Value.Y, ]; } + IsScreenSpace = false; } } diff --git a/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Connector/ScreenSpaceConnectorDescription.cs b/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Connector/ScreenSpaceConnectorDescription.cs new file mode 100644 index 0000000000..bf9a4fe982 --- /dev/null +++ b/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Connector/ScreenSpaceConnectorDescription.cs @@ -0,0 +1,12 @@ +namespace GW2EIEvtcParser.EIData; + +public class ScreenSpaceConnectorDescription : ConnectorDescription +{ + public readonly IReadOnlyList Position; + public readonly bool IsScreenSpace; + internal ScreenSpaceConnectorDescription(ScreenSpaceConnector connector, CombatReplayMap map, ParsedEvtcLog log) : base(connector, map, log) + { + IsScreenSpace = true; + Position = [connector.Position.X, connector.Position.Y]; + } +} diff --git a/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Metadata/CombatReplayDecorationMetadataDescription.cs b/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Metadata/CombatReplayDecorationMetadataDescription.cs index 75192ff146..8e31d6a74b 100644 --- a/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Metadata/CombatReplayDecorationMetadataDescription.cs +++ b/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Metadata/CombatReplayDecorationMetadataDescription.cs @@ -15,6 +15,7 @@ namespace GW2EIEvtcParser.EIData; [JsonDerivedType(typeof(RectangleDecorationMetadataDescription))] [JsonDerivedType(typeof(ProgressBarDecorationMetadataDescription))] [JsonDerivedType(typeof(OverheadProgressBarDecorationMetadataDescription))] +[JsonDerivedType(typeof(TextDecorationMetadataDescription))] public abstract class CombatReplayDecorationMetadataDescription : CombatReplayDescription { internal CombatReplayDecorationMetadataDescription() diff --git a/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Metadata/Decorations/Images/BackgroundIconDecorationMetadataDescription.cs b/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Metadata/Decorations/Images/BackgroundIconDecorationMetadataDescription.cs index f7f52287cc..20b8dd17ba 100644 --- a/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Metadata/Decorations/Images/BackgroundIconDecorationMetadataDescription.cs +++ b/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Metadata/Decorations/Images/BackgroundIconDecorationMetadataDescription.cs @@ -7,6 +7,6 @@ public class BackgroundIconDecorationMetadataDescription : ImageDecorationMetada internal BackgroundIconDecorationMetadataDescription(BackgroundIconDecorationMetadata decoration) : base(decoration) { - Type = "BackgroundIconDecoration"; + Type = "BackgroundIcon"; } } diff --git a/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Metadata/Decorations/Images/IconDecorationMetadataDescription.cs b/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Metadata/Decorations/Images/IconDecorationMetadataDescription.cs index bbb796b1d7..a2358080bc 100644 --- a/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Metadata/Decorations/Images/IconDecorationMetadataDescription.cs +++ b/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Metadata/Decorations/Images/IconDecorationMetadataDescription.cs @@ -8,7 +8,7 @@ public class IconDecorationMetadataDescription : ImageDecorationMetadataDescript internal IconDecorationMetadataDescription(IconDecorationMetadata decoration) : base(decoration) { - Type = "IconDecoration"; + Type = "Icon"; Opacity = decoration.Opacity; } } diff --git a/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Metadata/Decorations/Images/IconOverheadDecorationMetadataDescription.cs b/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Metadata/Decorations/Images/IconOverheadDecorationMetadataDescription.cs index ecdb3b9ace..28b98f5365 100644 --- a/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Metadata/Decorations/Images/IconOverheadDecorationMetadataDescription.cs +++ b/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Metadata/Decorations/Images/IconOverheadDecorationMetadataDescription.cs @@ -7,6 +7,6 @@ public class IconOverheadDecorationMetadataDescription : IconDecorationMetadataD internal IconOverheadDecorationMetadataDescription(IconOverheadDecorationMetadata decoration) : base(decoration) { - Type = "IconOverheadDecoration"; + Type = "IconOverhead"; } } diff --git a/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Metadata/Decorations/Text/TextDecorationMetadataDescription.cs b/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Metadata/Decorations/Text/TextDecorationMetadataDescription.cs new file mode 100644 index 0000000000..93d7c8253a --- /dev/null +++ b/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Metadata/Decorations/Text/TextDecorationMetadataDescription.cs @@ -0,0 +1,17 @@ +using static GW2EIEvtcParser.EIData.TextDecoration; + +namespace GW2EIEvtcParser.EIData; + +public class TextDecorationMetadataDescription : DecorationMetadataDescription +{ + + public readonly string Color; + + public readonly string? BackgroundColor; + internal TextDecorationMetadataDescription(TextDecorationMetadata decoration) : base(decoration) + { + Type = "Text"; + Color = decoration.Color; + BackgroundColor = decoration.BackgroundColor; + } +} diff --git a/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Rendering/CombatReplayRenderingDescription.cs b/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Rendering/CombatReplayRenderingDescription.cs index 25bce6e82b..f94c9a9e26 100644 --- a/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Rendering/CombatReplayRenderingDescription.cs +++ b/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Rendering/CombatReplayRenderingDescription.cs @@ -15,6 +15,7 @@ namespace GW2EIEvtcParser.EIData; [JsonDerivedType(typeof(CircleDecorationRenderingDescription))] [JsonDerivedType(typeof(ProgressBarDecorationRenderingDescription))] [JsonDerivedType(typeof(OverheadProgressBarDecorationRenderingDescription))] +[JsonDerivedType(typeof(TextDecorationRenderingDescription))] public abstract class CombatReplayRenderingDescription : CombatReplayDescription { public long Start { get; protected set; } diff --git a/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Rendering/Decorations/Images/BackgroundIconDecorationRenderingDescription.cs b/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Rendering/Decorations/Images/BackgroundIconDecorationRenderingDescription.cs index 5f729de3b9..b6a459df68 100644 --- a/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Rendering/Decorations/Images/BackgroundIconDecorationRenderingDescription.cs +++ b/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Rendering/Decorations/Images/BackgroundIconDecorationRenderingDescription.cs @@ -10,7 +10,7 @@ public class BackgroundIconDecorationRenderingDescription : ImageDecorationRende public readonly IReadOnlyList Heights; internal BackgroundIconDecorationRenderingDescription(ParsedEvtcLog log, BackgroundIconDecorationRenderingData decoration, CombatReplayMap map, Dictionary usedSkills, Dictionary usedBuffs, string metadataSignature) : base(log, decoration, map, usedSkills, usedBuffs, metadataSignature) { - Type = "BackgroundIconDecoration"; //TODO(Rennorb) @cleanup: enum + Type = "BackgroundIcon"; //TODO(Rennorb) @cleanup: enum IsMechanicOrSkill = false; var opacities = new List(decoration.Opacities.Count * 2); foreach (ParametricPoint1D opacity in decoration.Opacities) diff --git a/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Rendering/Decorations/Images/IconDecorationRenderingDescription.cs b/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Rendering/Decorations/Images/IconDecorationRenderingDescription.cs index 85c7ae4a02..f542485cc2 100644 --- a/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Rendering/Decorations/Images/IconDecorationRenderingDescription.cs +++ b/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Rendering/Decorations/Images/IconDecorationRenderingDescription.cs @@ -7,10 +7,10 @@ public class IconDecorationRenderingDescription : ImageDecorationRenderingDescri { internal IconDecorationRenderingDescription(ParsedEvtcLog log, IconDecorationRenderingData decoration, CombatReplayMap map, Dictionary usedSkills, Dictionary usedBuffs, string metadataSignature) : base(log, decoration, map, usedSkills, usedBuffs, metadataSignature) { - Type = "IconDecoration"; + Type = "Icon"; if (decoration.IsSquadMarker) { - Type = "SquadMarkerDecoration"; + Type = "SquadMarker"; } } } diff --git a/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Rendering/Decorations/Images/IconOverheadDecorationRenderingDescription.cs b/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Rendering/Decorations/Images/IconOverheadDecorationRenderingDescription.cs index 9628cb2c36..fac5aa7ec9 100644 --- a/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Rendering/Decorations/Images/IconOverheadDecorationRenderingDescription.cs +++ b/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Rendering/Decorations/Images/IconOverheadDecorationRenderingDescription.cs @@ -8,10 +8,10 @@ public class IconOverheadDecorationRenderingDescription : IconDecorationRenderin internal IconOverheadDecorationRenderingDescription(ParsedEvtcLog log, IconOverheadDecorationRenderingData decoration, CombatReplayMap map, Dictionary usedSkills, Dictionary usedBuffs, string metadataSignature) : base(log, decoration, map, usedSkills, usedBuffs, metadataSignature) { - Type = "IconOverheadDecoration"; + Type = "IconOverhead"; if (decoration.IsSquadMarker) { - Type = "OverheadSquadMarkerDecoration"; + Type = "OverheadSquadMarker"; } } } diff --git a/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Rendering/Decorations/Text/TextDecorationRenderingDescription.cs b/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Rendering/Decorations/Text/TextDecorationRenderingDescription.cs new file mode 100644 index 0000000000..51c1d15b8a --- /dev/null +++ b/GW2EIEvtcParser/EIData/CombatReplay/CombatReplayDescription/Rendering/Decorations/Text/TextDecorationRenderingDescription.cs @@ -0,0 +1,24 @@ +using GW2EIEvtcParser.ParsedData; +using static GW2EIEvtcParser.EIData.TextDecoration; + +namespace GW2EIEvtcParser.EIData; + +public class TextDecorationRenderingDescription : DecorationRenderingDescription +{ + public readonly string Text; + public readonly bool Bold; + public readonly string? FontType; + public readonly uint FontSize; + public readonly ConnectorDescription ConnectedTo; + + internal TextDecorationRenderingDescription(ParsedEvtcLog log, TextDecorationRenderingData decoration, CombatReplayMap map, Dictionary usedSkills, Dictionary usedBuffs, string metadataSignature) : base(decoration, metadataSignature) + { + IsMechanicOrSkill = true; + Type = "Text"; + Text = decoration.Text; + FontType = decoration.FontType; + FontSize = decoration.FontSize; + Bold = decoration.Bold; + ConnectedTo = decoration.ConnectedTo.GetConnectedTo(map, log); + } +} diff --git a/GW2EIEvtcParser/EIData/CombatReplay/Decorations/Connector/ScreenSpaceConnector.cs b/GW2EIEvtcParser/EIData/CombatReplay/Decorations/Connector/ScreenSpaceConnector.cs new file mode 100644 index 0000000000..07e250545a --- /dev/null +++ b/GW2EIEvtcParser/EIData/CombatReplay/Decorations/Connector/ScreenSpaceConnector.cs @@ -0,0 +1,13 @@ +using System.Numerics; + +namespace GW2EIEvtcParser.EIData; + +internal class ScreenSpaceConnector(in Vector2 position) : Connector +{ + public readonly Vector2 Position = position; + + public override ConnectorDescription GetConnectedTo(CombatReplayMap map, ParsedEvtcLog log) + { + return new ScreenSpaceConnectorDescription(this, map, log); + } +} diff --git a/GW2EIEvtcParser/EIData/CombatReplay/Decorations/Text/TextDecoration.cs b/GW2EIEvtcParser/EIData/CombatReplay/Decorations/Text/TextDecoration.cs new file mode 100644 index 0000000000..8b3ba607e1 --- /dev/null +++ b/GW2EIEvtcParser/EIData/CombatReplay/Decorations/Text/TextDecoration.cs @@ -0,0 +1,110 @@ +using GW2EIEvtcParser.ParsedData; + +namespace GW2EIEvtcParser.EIData; + +internal class TextDecoration : Decoration +{ + public class TextDecorationMetadata : _DecorationMetadata + { + public readonly string Color; + + public readonly string? BackgroundColor; // For the future, in case we want to have a backplate for the text + + public TextDecorationMetadata(string color, string? backgroundColor = null) + { + Color = color; + BackgroundColor = backgroundColor; + } + + public override DecorationMetadataDescription GetCombatReplayMetadataDescription() + { + return new TextDecorationMetadataDescription(this); + } + + public override string GetSignature() + { + return "Txt" + Color + BackgroundColor ?? ""; + } + } + public class TextDecorationRenderingData : _DecorationRenderingData + { + public readonly string Text; + public bool Bold { get; private set; } = false; + public string? FontType { get; private set; } + public readonly uint FontSize; + + public readonly Connector ConnectedTo; + + private TextDecorationRenderingData((long, long) lifespan, string text, uint fontSize) : base(lifespan) + { + Text = text; + FontSize = fontSize; + } + + public TextDecorationRenderingData((long, long) lifespan, string text, uint fontSize, GeographicalConnector connector) : this(lifespan, text, fontSize) + { + ConnectedTo = connector; + } + + public TextDecorationRenderingData((long, long) lifespan, string text, uint fontSize, ScreenSpaceConnector connector) : this(lifespan, text, fontSize) + { + ConnectedTo = connector; + } + + public void UsingFontType(string fontType) + { + FontType = fontType; + } + + public void UsingBold(bool bold) + { + Bold = bold; + } + + public override DecorationRenderingDescription GetCombatReplayRenderingDescription(CombatReplayMap map, ParsedEvtcLog log, Dictionary usedSkills, Dictionary usedBuffs, string metadataSignature) + { + return new TextDecorationRenderingDescription(log, this, map, usedSkills, usedBuffs, metadataSignature); + } + } + private new TextDecorationMetadata DecorationMetadata => (TextDecorationMetadata)base.DecorationMetadata; + private new TextDecorationRenderingData DecorationRenderingData => (TextDecorationRenderingData)base.DecorationRenderingData; + + public string Color => DecorationMetadata.Color; + + protected TextDecoration(TextDecorationMetadata metadata, TextDecorationRenderingData renderingData) : base(metadata, renderingData) + { + } + + public TextDecoration((long, long) lifespan, string text, uint fontSize, string color, GeographicalConnector connector) : base(new TextDecorationMetadata(color), new TextDecorationRenderingData(lifespan, text, fontSize, connector)) + { + + } + + + public TextDecoration((long, long) lifespan, string text, uint fontSize, Color color, double opacity, GeographicalConnector connector) : this(lifespan, text, fontSize, color.WithAlpha(opacity).ToString(true), connector) + { + + } + + public TextDecoration((long, long) lifespan, string text, uint fontSize, string color, ScreenSpaceConnector connector) : base(new TextDecorationMetadata(color), new TextDecorationRenderingData(lifespan, text, fontSize, connector)) + { + + } + public TextDecoration((long, long) lifespan, string text, uint fontSize, Color color, double opacity, ScreenSpaceConnector connector) : this(lifespan, text, fontSize, color.WithAlpha(opacity).ToString(true), connector) + { + + } + + public TextDecoration UsingFontType(string fontType) + { + DecorationRenderingData.UsingFontType(fontType); + return this; + } + + public TextDecoration UsingBold(bool bold) + { + DecorationRenderingData.UsingBold(bold); + return this; + } + +} diff --git a/GW2EIEvtcParser/EncounterLogic/Raids/W6/Qadim.cs b/GW2EIEvtcParser/EncounterLogic/Raids/W6/Qadim.cs index 4d9012a86d..c7107fb49a 100644 --- a/GW2EIEvtcParser/EncounterLogic/Raids/W6/Qadim.cs +++ b/GW2EIEvtcParser/EncounterLogic/Raids/W6/Qadim.cs @@ -500,7 +500,6 @@ internal override void ComputeEnvironmentCombatReplayDecorations(ParsedEvtcLog l internal override void ComputeNPCCombatReplayActors(NPC target, ParsedEvtcLog log, CombatReplay replay) { var cls = target.GetCastEvents(log, log.FightData.FightStart, log.FightData.FightEnd); - uint ccRadius = 200; switch (target.ID) { case (int)TargetID.Qadim: diff --git a/GW2EIEvtcParser/EncounterLogic/Raids/W8/DecimaTheStormsinger.cs b/GW2EIEvtcParser/EncounterLogic/Raids/W8/DecimaTheStormsinger.cs index 57e0b89568..aa3726efac 100644 --- a/GW2EIEvtcParser/EncounterLogic/Raids/W8/DecimaTheStormsinger.cs +++ b/GW2EIEvtcParser/EncounterLogic/Raids/W8/DecimaTheStormsinger.cs @@ -149,13 +149,12 @@ internal override void ComputeNPCCombatReplayActors(NPC target, ParsedEvtcLog lo replay.Decorations.Add(new CircleDecoration(700, segment.TimeSpan, Colors.Red, 0.2, new AgentConnector(target)).UsingFilled(false)); } - // Add the Charge Bar on top right of the replay - var chargeSegments = target.GetBuffStatus(log, ChargeDecima, log.FightData.FightStart, log.FightData.FightEnd); - replay.Decorations.Add( - new OverheadProgressBarDecoration(CombatReplayOverheadProgressBarMajorSizeInPixel, lifespan, Colors.Red, 0.6, Colors.Black, 0.4, chargeSegments.Select(x => (x.Start, x.Value * 10)).ToList(), new AgentConnector(target)) - .UsingInterpolationMethod(Connector.InterpolationMethod.Step) - .UsingRotationConnector(new AngleConnector(180)) - ); + // Add the Charge indicator on top right of the replay + var chargeSegments = target.GetBuffStatus(log, ChargeDecima, log.FightData.FightStart, log.FightData.FightEnd).Where(x => x.Value > 0); + foreach (Segment seg in chargeSegments) + { + replay.Decorations.Add(new TextDecoration((seg.Start, seg.End), "Decima Charge(s) " + seg.Value + " out of 10", 15, Colors.Red, 1.0, new ScreenSpaceConnector(new Vector2(600, 60)))); + } // Mainshock - Pizza Indicator if (log.CombatData.TryGetEffectEventsBySrcWithGUID(target.AgentItem, EffectGUIDs.DecimaMainshockIndicator, out var mainshockSlices))