diff --git a/Telesto/Doodle.cs b/Telesto/Doodle.cs index 8f1b061..9e817df 100644 --- a/Telesto/Doodle.cs +++ b/Telesto/Doodle.cs @@ -16,7 +16,7 @@ namespace Telesto { - internal abstract class Doodle + internal abstract class Doodle : IDisposable { internal class Coordinate @@ -34,6 +34,11 @@ internal enum CoordinateTypeEnum internal Doodle doo { get; set; } internal CoordinateTypeEnum ct { get; set; } internal Vector3 cp { get; set; } + float ofsx, ofsy, ofsz; + + internal string OffsetX { get; set; } + internal string OffsetY { get; set; } + internal string OffsetZ { get; set; } internal string X { get; set; } internal string Y { get; set; } @@ -41,23 +46,36 @@ internal enum CoordinateTypeEnum internal ulong id { get; set; } internal string name { get; set; } - internal Vector3 UnadjustedPosition(Plugin p) + internal Vector3 UntranslatedPosition(Plugin p) { + ofsx = ofsy = ofsz = 0.0f; + if (OffsetX != "") + { + ofsx = (float)p.EvaluateNumericExpression(doo, OffsetX); + } + if (OffsetY != "") + { + ofsy = (float)p.EvaluateNumericExpression(doo, OffsetY); + } + if (OffsetZ != "") + { + ofsz = (float)p.EvaluateNumericExpression(doo, OffsetZ); + } switch (ct) { default: case CoordinateTypeEnum.Screen: return new Vector3( - (float)p.EvaluateNumericExpression(doo, X), - (float)p.EvaluateNumericExpression(doo, Y), - (float)p.EvaluateNumericExpression(doo, Z) + ofsx + (float)p.EvaluateNumericExpression(doo, X), + ofsy + (float)p.EvaluateNumericExpression(doo, Y), + ofsz + (float)p.EvaluateNumericExpression(doo, Z) ); break; case CoordinateTypeEnum.World: return new Vector3( - (float)p.EvaluateNumericExpression(doo, X), - (float)p.EvaluateNumericExpression(doo, Y), - (float)p.EvaluateNumericExpression(doo, Z) + ofsx + (float)p.EvaluateNumericExpression(doo, X), + ofsy + (float)p.EvaluateNumericExpression(doo, Y), + ofsz + (float)p.EvaluateNumericExpression(doo, Z) ); break; case CoordinateTypeEnum.Entity: @@ -73,17 +91,17 @@ internal Vector3 UnadjustedPosition(Plugin p) if (go != null) { return new Vector3( - go.Position.X, - go.Position.Y, - go.Position.Z + ofsx + go.Position.X, + ofsy + go.Position.Y, + ofsz + go.Position.Z ); } else { return new Vector3( - (float)p.EvaluateNumericExpression(doo, X), - (float)p.EvaluateNumericExpression(doo, Y), - (float)p.EvaluateNumericExpression(doo, Z) + ofsx + (float)p.EvaluateNumericExpression(doo, X), + ofsy + (float)p.EvaluateNumericExpression(doo, Y), + ofsz + (float)p.EvaluateNumericExpression(doo, Z) ); } break; @@ -95,7 +113,7 @@ internal Vector3 UnadjustedPosition(Plugin p) Coordinate c = d.GetCoordinateByName(spl.Length > 1 ? spl[1] : ""); if (c != null) { - return c.UnadjustedPosition(p); + return c.UntranslatedPosition(p); } } return new Vector3(); @@ -104,9 +122,9 @@ internal Vector3 UnadjustedPosition(Plugin p) if (wm != null && wm.Active == true) { return new Vector3( - wm.X_Float, - wm.Y_Float, - wm.Z_Float + ofsx + wm.X_Float, + ofsy + wm.Y_Float, + ofsz + wm.Z_Float ); } return new Vector3(); @@ -115,20 +133,33 @@ internal Vector3 UnadjustedPosition(Plugin p) internal void RefreshVector(Plugin p) { + ofsx = ofsy = ofsz = 0.0f; + if (OffsetX != "") + { + ofsx = (float)p.EvaluateNumericExpression(doo, OffsetX); + } + if (OffsetY != "") + { + ofsy = (float)p.EvaluateNumericExpression(doo, OffsetY); + } + if (OffsetZ != "") + { + ofsz = (float)p.EvaluateNumericExpression(doo, OffsetZ); + } switch (ct) { case CoordinateTypeEnum.Screen: cp = new Vector3( - (float)p.EvaluateNumericExpression(doo, X), - (float)p.EvaluateNumericExpression(doo, Y), - (float)p.EvaluateNumericExpression(doo, Z) + ofsx + (float)p.EvaluateNumericExpression(doo, X), + ofsy + (float)p.EvaluateNumericExpression(doo, Y), + ofsz + (float)p.EvaluateNumericExpression(doo, Z) ); break; case CoordinateTypeEnum.World: cp = p.TranslateToScreen( - p.EvaluateNumericExpression(doo, X), - p.EvaluateNumericExpression(doo, Y), - p.EvaluateNumericExpression(doo, Z) + ofsx + p.EvaluateNumericExpression(doo, X), + ofsy + p.EvaluateNumericExpression(doo, Y), + ofsz + p.EvaluateNumericExpression(doo, Z) ); break; case CoordinateTypeEnum.Entity: @@ -144,17 +175,17 @@ internal void RefreshVector(Plugin p) if (go != null) { cp = p.TranslateToScreen( - go.Position.X, - go.Position.Y, - go.Position.Z + ofsx + go.Position.X, + ofsy + go.Position.Y, + ofsz + go.Position.Z ); } else { cp = p.TranslateToScreen( - p.EvaluateNumericExpression(doo, X), - p.EvaluateNumericExpression(doo, Y), - p.EvaluateNumericExpression(doo, Z) + ofsx + p.EvaluateNumericExpression(doo, X), + ofsy + p.EvaluateNumericExpression(doo, Y), + ofsz + p.EvaluateNumericExpression(doo, Z) ); } break; @@ -166,11 +197,11 @@ internal void RefreshVector(Plugin p) Coordinate c = d.GetCoordinateByName(spl.Length > 1 ? spl[1] : ""); if (c != null) { - Vector3 uap = c.UnadjustedPosition(p); + Vector3 uap = c.UntranslatedPosition(p); cp = p.TranslateToScreen( - uap.X, - uap.Y, - uap.Z + ofsx + uap.X, + ofsy + uap.Y, + ofsz + uap.Z ); } else @@ -188,9 +219,9 @@ internal void RefreshVector(Plugin p) if (wm != null && wm.Active == true) { cp = p.TranslateToScreen( - wm.X_Float, - wm.Y_Float, - wm.Z_Float + ofsx + wm.X_Float, + ofsy + wm.Y_Float, + ofsz + wm.Z_Float ); } else @@ -225,6 +256,9 @@ internal void Initialize(Dictionary d) X = (d.ContainsKey("x") == true) ? d["x"].ToString() : "0"; Y = (d.ContainsKey("y") == true) ? d["y"].ToString() : "0"; Z = (d.ContainsKey("z") == true) ? d["z"].ToString() : "0"; + OffsetX = (d.ContainsKey("offsetx") == true) ? d["offsetx"].ToString() : ""; + OffsetY = (d.ContainsKey("offsety") == true) ? d["offsety"].ToString() : ""; + OffsetZ = (d.ContainsKey("offsetz") == true) ? d["offsetz"].ToString() : ""; id = 0; if (d.ContainsKey("id") == true) { @@ -264,15 +298,24 @@ internal enum ExpiryTypeEnum internal string B { get; set; } internal string A { get; set; } - abstract internal Coordinate GetCoordinateByName(string id); + internal virtual string DefaultR { get; } = "0"; + internal virtual string DefaultG { get; } = "0"; + internal virtual string DefaultB { get; } = "0"; + internal virtual string DefaultA { get; } = "1"; + + abstract internal Coordinate GetCoordinateByName(string id); + + public virtual void Dispose() + { + } internal virtual void Initialize(Dictionary d) { Name = d["name"].ToString(); - R = (d.ContainsKey("r") == true) ? d["r"].ToString() : "0"; - G = (d.ContainsKey("g") == true) ? d["g"].ToString() : "0"; - B = (d.ContainsKey("b") == true) ? d["b"].ToString() : "0"; - A = (d.ContainsKey("a") == true) ? d["a"].ToString() : "1"; + R = (d.ContainsKey("r") == true) ? d["r"].ToString() : DefaultR; + G = (d.ContainsKey("g") == true) ? d["g"].ToString() : DefaultG; + B = (d.ContainsKey("b") == true) ? d["b"].ToString() : DefaultB; + A = (d.ContainsKey("a") == true) ? d["a"].ToString() : DefaultA; if (d.ContainsKey("expireson") == true) { ExpiryTypeEnum nt = 0; @@ -325,6 +368,9 @@ internal static Doodle Deserialize(Dictionary d) case "beam": doo = new Doodles.Beam(); break; + case "image": + doo = new Doodles.Image(); + break; } if (doo != null) { diff --git a/Telesto/Doodles/Arrow.cs b/Telesto/Doodles/Arrow.cs index 25978e7..9907aa3 100644 --- a/Telesto/Doodles/Arrow.cs +++ b/Telesto/Doodles/Arrow.cs @@ -79,8 +79,8 @@ internal override void Draw() } else { - Vector3 tf = from.UnadjustedPosition(p); - Vector3 tt = to.UnadjustedPosition(p); + Vector3 tf = from.UntranslatedPosition(p); + Vector3 tt = to.UntranslatedPosition(p); float distance = Vector3.Distance(tf, tt); double anglexz = Math.Atan2(tf.Z - tt.Z, tf.X - tt.X); float head = distance * 0.7f; diff --git a/Telesto/Doodles/Beam.cs b/Telesto/Doodles/Beam.cs index 273e345..f0b6456 100644 --- a/Telesto/Doodles/Beam.cs +++ b/Telesto/Doodles/Beam.cs @@ -87,8 +87,8 @@ internal override void Draw() } else { - Vector3 tf = from.UnadjustedPosition(p); - Vector3 tt = at.UnadjustedPosition(p); + Vector3 tf = from.UntranslatedPosition(p); + Vector3 tt = at.UntranslatedPosition(p); float distance = Vector3.Distance(tf, tt); float length; length = lengthchonk < 0.0 ? distance : lengthchonk; diff --git a/Telesto/Doodles/Circle.cs b/Telesto/Doodles/Circle.cs index 2169744..e071369 100644 --- a/Telesto/Doodles/Circle.cs +++ b/Telesto/Doodles/Circle.cs @@ -97,7 +97,7 @@ internal override void Draw() } else { - Vector3 temp = position.UnadjustedPosition(p); + Vector3 temp = position.UntranslatedPosition(p); for (int i = 0; i <= 48; i++) { Vector3 mauw = p.TranslateToScreen( diff --git a/Telesto/Doodles/Image.cs b/Telesto/Doodles/Image.cs new file mode 100644 index 0000000..5b50ffb --- /dev/null +++ b/Telesto/Doodles/Image.cs @@ -0,0 +1,179 @@ +using ImGuiNET; +using ImGuiScene; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using Vector2 = System.Numerics.Vector2; + +namespace Telesto.Doodles +{ + + internal class Image : Doodle + { + + internal enum AlignmentEnum + { + Near, + Center, + Far + } + + internal override string DefaultR => "1"; + internal override string DefaultG => "1"; + internal override string DefaultB => "1"; + internal override string DefaultA => "1"; + + internal string Width { get; set; } + internal string Height { get; set; } + + internal Regex rex = new Regex(@"^(?\d*)%$"); + internal AlignmentEnum halign = AlignmentEnum.Near; + internal AlignmentEnum valign = AlignmentEnum.Near; + internal Coordinate position { get; set; } + internal uint IconId = 0; + internal TextureWrap? Texture { get; set; } = null; + + internal int calcWidth; + internal int calcHeight; + + public override void Dispose() + { + base.Dispose(); + if (Texture != null) + { + Texture.Dispose(); + Texture = null; + } + } + + internal override Coordinate GetCoordinateByName(string id) + { + switch (id.ToLower()) + { + default: + case "position": return position; + } + } + + internal override void Initialize(Dictionary d) + { + base.Initialize(d); + Width = (d.ContainsKey("width") == true) ? d["width"].ToString() : "100%"; + Height = (d.ContainsKey("height") == true) ? d["height"].ToString() : "100%"; + if (d.ContainsKey("icon") == true) + { + uint.TryParse(d["icon"].ToString(), out IconId); + } + if (d.ContainsKey("halign") == true) + { + switch (d["halign"].ToString().ToLower()) + { + default: + case "left": + case "near": + halign = AlignmentEnum.Near; + break; + case "center": + case "middle": + halign = AlignmentEnum.Center; + break; + case "right": + case "far": + halign = AlignmentEnum.Far; + break; + } + } + if (d.ContainsKey("valign") == true) + { + switch (d["valign"].ToString().ToLower()) + { + default: + case "top": + case "near": + valign = AlignmentEnum.Near; + break; + case "center": + case "middle": + valign = AlignmentEnum.Center; + break; + case "bottom": + case "far": + valign = AlignmentEnum.Far; + break; + } + } + position = new Coordinate() { doo = this }; + if (d.ContainsKey("position") == true) + { + position.Initialize((Dictionary)d["position"]); + } + } + + internal override bool Update() + { + if (base.Update() == false) + { + return false; + } + position.RefreshVector(p); + if (Texture == null && IconId != 0) + { + Texture = p.GetTexture(IconId); + IconId = 0; + } + Match m; + m = rex.Match(Width); + if (m.Success == true) + { + calcWidth = (int)Math.Ceiling((float)Texture.Width * (float)int.Parse(m.Groups["val"].Value) / 100.0f); + } + else + { + calcWidth = (int)Math.Ceiling(p.EvaluateNumericExpression(this, Width)); + } + m = rex.Match(Height); + if (m.Success == true) + { + calcHeight = (int)Math.Ceiling((float)Texture.Height * (float)int.Parse(m.Groups["val"].Value) / 100.0f); + } + else + { + calcHeight = (int)Math.Ceiling(p.EvaluateNumericExpression(this, Height)); + } + return true; + } + + internal override void Draw() + { + if (Texture == null) + { + return; + } + Vector2 pt = new Vector2(position.cp.X, position.cp.Y); + if (halign != AlignmentEnum.Near || valign != AlignmentEnum.Near) + { + if (halign == AlignmentEnum.Center) + { + pt.X -= calcWidth / 2.0f; + } + if (halign == AlignmentEnum.Far) + { + pt.X -= calcWidth; + } + if (valign == AlignmentEnum.Center) + { + pt.Y -= calcHeight / 2.0f; + } + if (valign == AlignmentEnum.Far) + { + pt.Y -= calcHeight; + } + } + ImGui.SetCursorPos(pt); + ImGui.Image(Texture.ImGuiHandle, new Vector2(calcWidth, calcHeight), new Vector2(0.0f, 0.0f), new Vector2(1.0f, 1.0f), col); + } + + } + +} diff --git a/Telesto/Doodles/Rectangle.cs b/Telesto/Doodles/Rectangle.cs index 9e24876..2426668 100644 --- a/Telesto/Doodles/Rectangle.cs +++ b/Telesto/Doodles/Rectangle.cs @@ -103,8 +103,8 @@ internal override void Draw() } else { - Vector3 t1 = pos1.UnadjustedPosition(p); - Vector3 t3 = pos2.UnadjustedPosition(p); + Vector3 t1 = pos1.UntranslatedPosition(p); + Vector3 t3 = pos2.UntranslatedPosition(p); Vector3 t2 = new Vector3(t3.X, (t1.Y + t3.Y) / 2.0f, t1.Z); Vector3 t4 = new Vector3(t1.X, (t1.Y + t3.Y) / 2.0f, t3.Z); Vector3 v1 = p.TranslateToScreen(t1.X, t1.Y, t1.Z); diff --git a/Telesto/Doodles/Text.cs b/Telesto/Doodles/Text.cs index 185c5cf..97f73df 100644 --- a/Telesto/Doodles/Text.cs +++ b/Telesto/Doodles/Text.cs @@ -1,4 +1,5 @@ using ImGuiNET; +using System.Collections; using System.Collections.Generic; using Vector2 = System.Numerics.Vector2; @@ -8,6 +9,15 @@ namespace Telesto.Doodles internal class Text : Doodle { + internal enum AlignmentEnum + { + Near, + Center, + Far + } + + internal AlignmentEnum halign = AlignmentEnum.Near; + internal AlignmentEnum valign = AlignmentEnum.Near; internal Coordinate position { get; set; } internal string DisplayedString { get; set; } internal float chonkiness { get; set; } @@ -26,6 +36,44 @@ internal override void Initialize(Dictionary d) { base.Initialize(d); Size = (d.ContainsKey("size") == true) ? d["size"].ToString() : "10"; + if (d.ContainsKey("halign") == true) + { + switch (d["halign"].ToString().ToLower()) + { + default: + case "left": + case "near": + halign = AlignmentEnum.Near; + break; + case "center": + case "middle": + halign = AlignmentEnum.Center; + break; + case "right": + case "far": + halign = AlignmentEnum.Far; + break; + } + } + if (d.ContainsKey("valign") == true) + { + switch (d["valign"].ToString().ToLower()) + { + default: + case "top": + case "near": + valign = AlignmentEnum.Near; + break; + case "center": + case "middle": + valign = AlignmentEnum.Center; + break; + case "bottom": + case "far": + valign = AlignmentEnum.Far; + break; + } + } position = new Coordinate() { doo = this }; if (d.ContainsKey("position") == true) { @@ -47,10 +95,35 @@ internal override bool Update() internal override void Draw() { + Vector2 pt = new Vector2(position.cp.X, position.cp.Y); + if (halign != AlignmentEnum.Near || valign != AlignmentEnum.Near) + { + float defSize = ImGui.GetFontSize(); + float mul = chonkiness / defSize; + Vector2 sz = ImGui.CalcTextSize(DisplayedString); + sz.X *= mul; + sz.Y *= mul; + if (halign == AlignmentEnum.Center) + { + pt.X -= sz.X / 2.0f; + } + if (halign == AlignmentEnum.Far) + { + pt.X -= sz.X; + } + if (valign == AlignmentEnum.Center) + { + pt.Y -= sz.Y / 2.0f; + } + if (valign == AlignmentEnum.Far) + { + pt.Y -= sz.Y; + } + } ImGui.GetWindowDrawList().AddText( ImGui.GetFont(), chonkiness, - new Vector2(position.cp.X, position.cp.Y), + pt, ImGui.GetColorU32(col), DisplayedString ); diff --git a/Telesto/Doodles/Waymark.cs b/Telesto/Doodles/Waymark.cs index aabdbf2..76b4adc 100644 --- a/Telesto/Doodles/Waymark.cs +++ b/Telesto/Doodles/Waymark.cs @@ -49,7 +49,7 @@ internal Int64 Turninator() internal override void Draw() { - Vector3 temp = position.UnadjustedPosition(p); + Vector3 temp = position.UntranslatedPosition(p); Vector3 me = p.GetLocalPosition(); float distance = Vector3.Distance(temp, me); float alpha = col.W / 4.0f; diff --git a/Telesto/Plugin.cs b/Telesto/Plugin.cs index 182f194..445efa2 100644 --- a/Telesto/Plugin.cs +++ b/Telesto/Plugin.cs @@ -37,6 +37,8 @@ using System.Net; using static System.Net.WebRequestMethods; using System.Threading.Tasks; +using Dalamud.Data; +using FFXIVClientStructs.FFXIV.Client.Game.Fate; namespace Telesto { @@ -226,6 +228,7 @@ public void Dispose() private ClientState _cs { get; init; } private ObjectTable _ot { get; init; } private PartyList _pl { get; init; } + private DataManager _dm { get; init; } private Dictionary Subscriptions = new Dictionary(); private ManualResetEvent SendPendingEvent = new ManualResetEvent(false); private ManualResetEvent StopEvent = new ManualResetEvent(false); @@ -276,7 +279,8 @@ public Plugin( [RequiredVersion("1.0")] ObjectTable objectTable, [RequiredVersion("1.0")] GameGui gameGui, [RequiredVersion("1.0")] ChatGui chatGui, - [RequiredVersion("1.0")] PartyList partylist + [RequiredVersion("1.0")] PartyList partylist, + [RequiredVersion("1.0")] DataManager dataManager ) { _pi = pluginInterface; @@ -286,6 +290,7 @@ public Plugin( _gg = gameGui; _cg = chatGui; _pl = partylist; + _dm = dataManager; _cfg = _pi.GetPluginConfig() as Config ?? new Config(); _pi.UiBuilder.Draw += DrawUI; _pi.UiBuilder.OpenConfigUi += OpenConfigUI; @@ -340,6 +345,11 @@ private void FindSigs() } } + internal ImGuiScene.TextureWrap? GetTexture(uint id) + { + return _dm.GetImGuiTextureIcon(id); + } + private IntPtr SearchForSig(string sig) { return TargetModuleScanner.ScanText(sig); @@ -402,6 +412,16 @@ public void Dispose() catch (Exception) { } + foreach (KeyValuePair kp in Doodles) + { + try + { + kp.Value.Dispose(); + } + catch (Exception) + { + } + } _cm.RemoveHandler("/telesto"); _cs.Logout -= _cs_Logout; _cs.Login -= _cs_Login; @@ -1066,6 +1086,42 @@ public string ExpandVariables(Context ctx, string expr) found = true; } } + else if (x.IndexOf("_sin") == 0) + { + mx = rexlidx.Match(x); + if (mx.Success == true) + { + string freqs = mx.Groups["index"].Value.Replace(",", "."); + if (double.TryParse(freqs, CultureInfo.InvariantCulture, out double freq) == true) + { + long ms = ((long)(DateTime.UtcNow - new DateTime(2023, 1, 1, 0, 0, 0)).TotalMilliseconds); + val = ((float)Math.Round(Math.Sin(ms / 1000.0 * freq * 2.0 * Math.PI), 3)).ToString(CultureInfo.InvariantCulture); + } + else + { + val = "0"; + } + found = true; + } + } + else if (x.IndexOf("_cos") == 0) + { + mx = rexlidx.Match(x); + if (mx.Success == true) + { + string freqs = mx.Groups["index"].Value.Replace(",", "."); + if (double.TryParse(freqs, CultureInfo.InvariantCulture, out double freq) == true) + { + long ms = ((long)(DateTime.UtcNow - new DateTime(2023, 1, 1, 0, 0, 0)).TotalMilliseconds); + val = ((float)Math.Round(Math.Cos(ms / 1000.0 * freq * 2.0 * Math.PI), 3)).ToString(CultureInfo.InvariantCulture); + } + else + { + val = "0"; + } + found = true; + } + } else if (x.IndexOf("_ffxiventity") == 0) { mx = rexnump.Match(x); @@ -1155,7 +1211,9 @@ private object HandleDisableDoodle(object o) { if (Doodles.ContainsKey(id) == true) { + Doodle dee = Doodles[id]; Doodles.Remove(id); + dee.Dispose(); } } return null; @@ -1177,7 +1235,9 @@ private object HandleDisableDoodleRegex(object o) } foreach (string key in toRem) { + Doodle dee = Doodles[key]; Doodles.Remove(key); + dee.Dispose(); } } return null; @@ -1341,6 +1401,7 @@ private void DrawDoodles() { Doodles.Remove(d.Name); } + d.Dispose(); } } }