public static Vector2D?IntersectLineLine(Vector2D s1, Vector2D e1, Vector2D s2, Vector2D e2) { var aabb1 = new Rect2D(s1, e1); var aabb2 = new Rect2D(s2, e2); if (!aabb1.IntersectsWith(aabb2)) { return(null); } double x1 = s1.X; double x2 = e1.X; double x3 = s2.X; double x4 = e2.X; double y1 = s1.Y; double y2 = e1.Y; double y3 = s2.Y; double y4 = e2.Y; double denom = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4); if (Math.Abs(denom) < 1e-4) { return(null); } double px = ((x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4)) / denom; double py = ((x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4)) / denom; var p = new Vector2D(px, py); double l1 = (p - s1).Length; double l2 = (p - e1).Length; if (l1 + l2 > (s1 - e1).Length + 1e-3) { return(null); } return(p); }
public bool IntersectsWith(Rect2D r) { return(!(r.Max.X <= Min.X || r.Max.Y <= Min.Y || Max.Y <= r.Min.Y || Max.X <= r.Min.X)); }
public bool Contains(Rect2D v) { return(v.Min.X >= Min.X && v.Min.Y >= Min.Y && v.Max.Y <= Max.Y && v.Max.X <= Max.X); }
public SkillTree(String treestring, bool displayProgress, UpdateLoadingWindow update) { PoESkillTree inTree = null; if (!_Initialized) { var jss = new JsonSerializerSettings { Error = delegate(object sender, ErrorEventArgs args) { Debug.WriteLine(args.ErrorContext.Error.Message); args.ErrorContext.Handled = true; } }; inTree = JsonConvert.DeserializeObject <PoESkillTree>(treestring.Replace("Additional ", ""), jss); } int qindex = 0; if (!_Initialized) { SkillTree._IconInActiveSkills = new SkillIcons(); //TODO: (SpaceOgre) This is not used atm, so no need to run it. foreach (var obj in inTree.skillSprites) { if (obj.Key.Contains("inactive")) { continue; } _IconInActiveSkills.Images[obj.Value[3].filename] = null; foreach (var o in obj.Value[3].coords) { _IconInActiveSkills.SkillPositions[o.Key + "_" + o.Value.w] = new KeyValuePair <Rect, string>(new Rect(o.Value.x, o.Value.y, o.Value.w, o.Value.h), obj.Value[3].filename); } } } if (!_Initialized) { SkillTree._IconActiveSkills = new SkillIcons(); foreach (var obj in inTree.skillSprites) { if (obj.Key.Contains("active")) { continue; } _IconActiveSkills.Images[obj.Value[3].filename] = null; foreach (var o in obj.Value[3].coords) { _IconActiveSkills.SkillPositions[o.Key + "_" + o.Value.w] = new KeyValuePair <Rect, string>(new Rect(o.Value.x, o.Value.y, o.Value.w, o.Value.h), obj.Value[3].filename); } } } if (!_Initialized) { foreach (var ass in inTree.assets) { _assets[ass.Key] = new Asset(ass.Key, ass.Value.ContainsKey(0.3835f) ? ass.Value[0.3835f] : ass.Value.Values.First()); } } if (!_Initialized) { _rootNodeList = new List <int>(); if (inTree.root != null) { foreach (int i in inTree.root.ot) { _rootNodeList.Add(i); } } else if (inTree.main != null) { foreach (int i in inTree.main.ot) { _rootNodeList.Add(i); } } } if (displayProgress) { update(50, 100); } if (!_Initialized) { _IconActiveSkills.OpenOrDownloadImages(update); } if (displayProgress) { update(75, 100); } if (!_Initialized) { _IconInActiveSkills.OpenOrDownloadImages(update); } if (!_Initialized) { _CharBaseAttributes = new Dictionary <string, float> [7]; foreach (var c in inTree.characterData) { _CharBaseAttributes[c.Key] = new Dictionary <string, float> { { "+# to Strength", c.Value.base_str }, { "+# to Dexterity", c.Value.base_dex }, { "+# to Intelligence", c.Value.base_int } }; } } if (!_Initialized) { _Skillnodes = new Dictionary <ushort, SkillNode>(); foreach (Node nd in inTree.nodes) { _Skillnodes.Add(nd.id, new SkillNode { Id = nd.id, Name = nd.dn, attributes = nd.sd, Orbit = nd.o, OrbitIndex = nd.oidx, Icon = nd.icon, LinkId = nd.ot, G = nd.g, Da = nd.da, Ia = nd.ia, IsKeyStone = nd.ks, IsNotable = nd.not, Sa = nd.sa, IsMastery = nd.m, Spc = nd.spc.Count() > 0 ? (int?)nd.spc[0] : null }); if (_rootNodeList.Contains(nd.id)) { _rootNodeClassDictionary.Add(nd.dn.ToString().ToUpper(), nd.id); foreach (int linkedNode in nd.ot) { _startNodeDictionary.Add(linkedNode, nd.id); } } foreach (int node in nd.ot) { if (!_startNodeDictionary.ContainsKey(nd.id) && _rootNodeList.Contains(node)) { _startNodeDictionary.Add(nd.id, node); } } } foreach (var skillNode in Skillnodes) { foreach (ushort i in skillNode.Value.LinkId) { if ( _links.Count(nd => (nd[0] == i && nd[1] == skillNode.Key) || nd[0] == skillNode.Key && nd[1] == i) == 1) { continue; } _links.Add(new[] { skillNode.Key, i }); } } foreach (var ints in _links) { if (!Skillnodes[ints[0]].Neighbor.Contains(Skillnodes[ints[1]])) { Skillnodes[ints[0]].Neighbor.Add(Skillnodes[ints[1]]); } if (!Skillnodes[ints[1]].Neighbor.Contains(Skillnodes[ints[0]])) { Skillnodes[ints[1]].Neighbor.Add(Skillnodes[ints[0]]); } } } if (!_Initialized) { _NodeGroups = new List <SkillNodeGroup>(); foreach (var gp in inTree.groups) { var ng = new SkillNodeGroup(); ng.OcpOrb = gp.Value.oo; ng.Position = new Vector2D(gp.Value.x, gp.Value.y); foreach (ushort node in gp.Value.n) { ng.Nodes.Add(Skillnodes[node]); } NodeGroups.Add(ng); } foreach (SkillNodeGroup group in NodeGroups) { foreach (SkillNode node in group.Nodes) { node.SkillNodeGroup = group; } } } if (!_Initialized) { _TRect = new Rect2D(new Vector2D(inTree.min_x * 1.1, inTree.min_y * 1.1), new Vector2D(inTree.max_x * 1.1, inTree.max_y * 1.1)); } InitNodeSurround();// DrawNodeSurround(); DrawNodeBaseSurround(); InitSkillIconLayers(); DrawSkillIconLayer(); DrawBackgroundLayer(); InitFaceBrushesAndLayer(); DrawLinkBackgroundLayer(_links); InitOtherDynamicLayers(); CreateCombineVisual(); if (_links != null) { var regexAttrib = new Regex("[0-9]*\\.?[0-9]+"); foreach (var skillNode in Skillnodes) { skillNode.Value.Attributes = new Dictionary <string, List <float> >(); foreach (string s in skillNode.Value.attributes) { var values = new List <float>(); foreach (Match m in regexAttrib.Matches(s)) { if (!AttributeTypes.Contains(regexAttrib.Replace(s, "#"))) { AttributeTypes.Add(regexAttrib.Replace(s, "#")); } if (m.Value == "") { values.Add(float.NaN); } else { values.Add(float.Parse(m.Value, CultureInfo.InvariantCulture)); } } string cs = (regexAttrib.Replace(s, "#")); skillNode.Value.Attributes[cs] = values; } } } if (displayProgress) { update(100, 100); } _Initialized = true; }
private void DrawBackgroundLayer() { picBackground = new DrawingVisual(); using (var drawingContext = picBackground.RenderOpen()) { BitmapImage[] iscr = { _assets["PSGroupBackground1"].PImage, _assets["PSGroupBackground2"].PImage, _assets["PSGroupBackground3"].PImage }; var orbitBrush = new Brush[3]; orbitBrush[0] = new ImageBrush(_assets["PSGroupBackground1"].PImage); orbitBrush[1] = new ImageBrush(_assets["PSGroupBackground2"].PImage); orbitBrush[2] = new ImageBrush(_assets["PSGroupBackground3"].PImage); (orbitBrush[2] as ImageBrush).TileMode = TileMode.FlipXY; (orbitBrush[2] as ImageBrush).Viewport = new Rect(0, 0, 1, .5f); var backgroundBrush = new ImageBrush(_assets["Background1"].PImage); backgroundBrush.TileMode = TileMode.Tile; backgroundBrush.Viewport = new Rect(0, 0, 6 * backgroundBrush.ImageSource.Width / TRect.Width, 6 * backgroundBrush.ImageSource.Height / TRect.Height); drawingContext.DrawRectangle(backgroundBrush, null, TRect); var topGradient = new LinearGradientBrush(); topGradient.GradientStops.Add(new GradientStop(Colors.Black, 1.0)); topGradient.GradientStops.Add(new GradientStop(new Color(), 0.0)); topGradient.StartPoint = new Point(0, 1); topGradient.EndPoint = new Point(0, 0); var leftGradient = new LinearGradientBrush(); leftGradient.GradientStops.Add(new GradientStop(Colors.Black, 1.0)); leftGradient.GradientStops.Add(new GradientStop(new Color(), 0.0)); leftGradient.StartPoint = new Point(1, 0); leftGradient.EndPoint = new Point(0, 0); var bottomGradient = new LinearGradientBrush(); bottomGradient.GradientStops.Add(new GradientStop(Colors.Black, 1.0)); bottomGradient.GradientStops.Add(new GradientStop(new Color(), 0.0)); bottomGradient.StartPoint = new Point(0, 0); bottomGradient.EndPoint = new Point(0, 1); var rightGradient = new LinearGradientBrush(); rightGradient.GradientStops.Add(new GradientStop(Colors.Black, 1.0)); rightGradient.GradientStops.Add(new GradientStop(new Color(), 0.0)); rightGradient.StartPoint = new Point(0, 0); rightGradient.EndPoint = new Point(1, 0); const int gradientWidth = 200; var topRect = new Rect2D(TRect.Left, TRect.Top, TRect.Width, gradientWidth); var leftRect = new Rect2D(TRect.Left, TRect.Top, gradientWidth, TRect.Height); var bottomRect = new Rect2D(TRect.Left, TRect.Bottom - gradientWidth, TRect.Width, gradientWidth); var rightRect = new Rect2D(TRect.Right - gradientWidth, TRect.Top, gradientWidth, TRect.Height); drawingContext.DrawRectangle(topGradient, null, topRect); drawingContext.DrawRectangle(leftGradient, null, leftRect); drawingContext.DrawRectangle(bottomGradient, null, bottomRect); drawingContext.DrawRectangle(rightGradient, null, rightRect); foreach (var skillNodeGroup in NodeGroups) { if (skillNodeGroup.OcpOrb == null) { skillNodeGroup.OcpOrb = new Dictionary <int, bool>(); } var cgrp = skillNodeGroup.OcpOrb.Keys.Where(ng => ng <= 3); if (!cgrp.Any()) { continue; } var maxr = cgrp.Max(ng => ng); if (maxr == 0) { continue; } maxr = maxr > 3 ? 2 : maxr - 1; var maxfac = maxr == 2 ? 2 : 1; drawingContext.DrawRectangle(orbitBrush[maxr], null, new Rect( skillNodeGroup.Position - new Vector2D(iscr[maxr].PixelWidth * 1.25, iscr[maxr].PixelHeight * 1.25 * maxfac), new Size(iscr[maxr].PixelWidth * 2.5, iscr[maxr].PixelHeight * 2.5 * maxfac))); } } }
private void DrawBackgroundLayer() { picBackground = new DrawingVisual(); using (var drawingContext = picBackground.RenderOpen()) { BitmapImage[] iscr = { _assets["PSGroupBackground1"].PImage, _assets["PSGroupBackground2"].PImage, _assets["PSGroupBackground3"].PImage }; var orbitBrush = new Brush[3]; orbitBrush[0] = new ImageBrush(_assets["PSGroupBackground1"].PImage); orbitBrush[1] = new ImageBrush(_assets["PSGroupBackground2"].PImage); orbitBrush[2] = new ImageBrush(_assets["PSGroupBackground3"].PImage); (orbitBrush[2] as ImageBrush).TileMode = TileMode.FlipXY; (orbitBrush[2] as ImageBrush).Viewport = new Rect(0, 0, 1, .5f); var backgroundBrush = new ImageBrush(_assets["Background1"].PImage); backgroundBrush.TileMode = TileMode.Tile; backgroundBrush.Viewport = new Rect(0, 0, 6 * backgroundBrush.ImageSource.Width / TRect.Width, 6 * backgroundBrush.ImageSource.Height / TRect.Height); drawingContext.DrawRectangle(backgroundBrush, null, TRect); var topGradient = new LinearGradientBrush(); topGradient.GradientStops.Add(new GradientStop(Colors.Black, 1.0)); topGradient.GradientStops.Add(new GradientStop(new Color(), 0.0)); topGradient.StartPoint = new Point(0, 1); topGradient.EndPoint = new Point(0, 0); var leftGradient = new LinearGradientBrush(); leftGradient.GradientStops.Add(new GradientStop(Colors.Black, 1.0)); leftGradient.GradientStops.Add(new GradientStop(new Color(), 0.0)); leftGradient.StartPoint = new Point(1, 0); leftGradient.EndPoint = new Point(0, 0); var bottomGradient = new LinearGradientBrush(); bottomGradient.GradientStops.Add(new GradientStop(Colors.Black, 1.0)); bottomGradient.GradientStops.Add(new GradientStop(new Color(), 0.0)); bottomGradient.StartPoint = new Point(0, 0); bottomGradient.EndPoint = new Point(0, 1); var rightGradient = new LinearGradientBrush(); rightGradient.GradientStops.Add(new GradientStop(Colors.Black, 1.0)); rightGradient.GradientStops.Add(new GradientStop(new Color(), 0.0)); rightGradient.StartPoint = new Point(0, 0); rightGradient.EndPoint = new Point(1, 0); const int gradientWidth = 200; var topRect = new Rect2D(TRect.Left, TRect.Top, TRect.Width, gradientWidth); var leftRect = new Rect2D(TRect.Left, TRect.Top, gradientWidth, TRect.Height); var bottomRect = new Rect2D(TRect.Left, TRect.Bottom - gradientWidth, TRect.Width, gradientWidth); var rightRect = new Rect2D(TRect.Right - gradientWidth, TRect.Top, gradientWidth, TRect.Height); drawingContext.DrawRectangle(topGradient, null, topRect); drawingContext.DrawRectangle(leftGradient, null, leftRect); drawingContext.DrawRectangle(bottomGradient, null, bottomRect); drawingContext.DrawRectangle(rightGradient, null, rightRect); foreach (var skillNodeGroup in NodeGroups) { if (skillNodeGroup.OcpOrb == null) skillNodeGroup.OcpOrb = new Dictionary<int, bool>(); var cgrp = skillNodeGroup.OcpOrb.Keys.Where(ng => ng <= 3); if (!cgrp.Any()) continue; var maxr = cgrp.Max(ng => ng); if (maxr == 0) continue; maxr = maxr > 3 ? 2 : maxr - 1; var maxfac = maxr == 2 ? 2 : 1; drawingContext.DrawRectangle(orbitBrush[maxr], null, new Rect( skillNodeGroup.Position - new Vector2D(iscr[maxr].PixelWidth * 1.25, iscr[maxr].PixelHeight * 1.25 * maxfac), new Size(iscr[maxr].PixelWidth * 2.5, iscr[maxr].PixelHeight * 2.5 * maxfac))); } } }
public SkillTree(String treestring, bool displayProgress, UpdateLoadingWindow update) { PoESkillTree inTree = null; if (!_Initialized) { var jss = new JsonSerializerSettings { Error = delegate(object sender, ErrorEventArgs args) { Debug.WriteLine(args.ErrorContext.Error.Message); args.ErrorContext.Handled = true; } }; inTree = JsonConvert.DeserializeObject<PoESkillTree>(treestring, jss); } int qindex = 0; if (!_Initialized) { SkillTree._IconInActiveSkills = new SkillIcons(); //TODO: (SpaceOgre) This is not used atm, so no need to run it. foreach (var obj in inTree.skillSprites) { if (obj.Key.Contains("inactive")) continue; _IconInActiveSkills.Images[obj.Value[3].filename] = null; foreach (var o in obj.Value[3].coords) { _IconInActiveSkills.SkillPositions[o.Key + "_" + o.Value.w] = new KeyValuePair<Rect, string>(new Rect(o.Value.x, o.Value.y, o.Value.w, o.Value.h), obj.Value[3].filename); } } } if (!_Initialized) { SkillTree._IconActiveSkills = new SkillIcons(); foreach (var obj in inTree.skillSprites) { if (obj.Key.Contains("active")) continue; _IconActiveSkills.Images[obj.Value[3].filename] = null; foreach (var o in obj.Value[3].coords) { _IconActiveSkills.SkillPositions[o.Key + "_" + o.Value.w] = new KeyValuePair<Rect, string>(new Rect(o.Value.x, o.Value.y, o.Value.w, o.Value.h), obj.Value[3].filename); } } } if (!_Initialized) { foreach (var ass in inTree.assets) { _assets[ass.Key] = new Asset(ass.Key, ass.Value.ContainsKey(0.3835f) ? ass.Value[0.3835f] : ass.Value.Values.First()); } } if (!_Initialized) { _rootNodeList = new List<int>(); if (inTree.root != null) { foreach (int i in inTree.root.ot) { _rootNodeList.Add(i); } } else if (inTree.main != null) { foreach (int i in inTree.main.ot) { _rootNodeList.Add(i); } } } if (displayProgress) update(50, 100); if (!_Initialized) _IconActiveSkills.OpenOrDownloadImages(update); if (displayProgress) update(75, 100); if (!_Initialized) _IconInActiveSkills.OpenOrDownloadImages(update); if (!_Initialized) { _CharBaseAttributes = new Dictionary<string, float>[7]; foreach (var c in inTree.characterData) { _CharBaseAttributes[c.Key] = new Dictionary<string, float> { {"+# to Strength", c.Value.base_str}, {"+# to Dexterity", c.Value.base_dex}, {"+# to Intelligence", c.Value.base_int} }; } } if (!_Initialized) { _Skillnodes = new Dictionary<ushort, SkillNode>(); _rootNodeClassDictionary = new Dictionary<string, int>(); _startNodeDictionary = new Dictionary<int, int>(); foreach (Node nd in inTree.nodes) { _Skillnodes.Add(nd.id, new SkillNode { Id = nd.id, Name = nd.dn, attributes = nd.dn.Contains("Jewel Socket") ? new string[1] { "+1 Jewel Socket" } : SplitMultilineAttributes(nd.sd), Orbit = nd.o, OrbitIndex = nd.oidx, Icon = nd.icon, LinkId = nd.ot, G = nd.g, Da = nd.da, Ia = nd.ia, IsKeyStone = nd.ks, IsNotable = nd.not, IsJewelSocket = nd.dn.Contains("Jewel Socket"), Sa = nd.sa, IsMastery = nd.m, Spc = nd.spc.Count() > 0 ? (int?)nd.spc[0] : null }); if (_rootNodeList.Contains(nd.id)) { if (!_rootNodeClassDictionary.ContainsKey(nd.dn.ToString().ToUpperInvariant())) { _rootNodeClassDictionary.Add(nd.dn.ToString().ToUpperInvariant(), nd.id); } foreach (int linkedNode in nd.ot) { if (!_startNodeDictionary.ContainsKey(nd.id)) { _startNodeDictionary.Add(linkedNode, nd.id); } } } foreach (int node in nd.ot) { if (!_startNodeDictionary.ContainsKey(nd.id) && _rootNodeList.Contains(node)) { _startNodeDictionary.Add(nd.id, node); } } } foreach (var skillNode in Skillnodes) { foreach (ushort i in skillNode.Value.LinkId) { if ( _links.Count(nd => (nd[0] == i && nd[1] == skillNode.Key) || nd[0] == skillNode.Key && nd[1] == i) == 1) { continue; } _links.Add(new[] { skillNode.Key, i }); } } foreach (var ints in _links) { if (!Skillnodes[ints[0]].Neighbor.Contains(Skillnodes[ints[1]])) Skillnodes[ints[0]].Neighbor.Add(Skillnodes[ints[1]]); if (!Skillnodes[ints[1]].Neighbor.Contains(Skillnodes[ints[0]])) Skillnodes[ints[1]].Neighbor.Add(Skillnodes[ints[0]]); } } if (!_Initialized) { _NodeGroups = new List<SkillNodeGroup>(); foreach (var gp in inTree.groups) { var ng = new SkillNodeGroup(); ng.OcpOrb = gp.Value.oo; ng.Position = new Vector2D(gp.Value.x, gp.Value.y); foreach (ushort node in gp.Value.n) { ng.Nodes.Add(Skillnodes[node]); } NodeGroups.Add(ng); } foreach (SkillNodeGroup group in NodeGroups) { foreach (SkillNode node in group.Nodes) { node.SkillNodeGroup = group; } } } if (!_Initialized) { const int padding = 500; //This is to account for jewel range circles. Might need to find a better way to do it. _TRect = new Rect2D(new Vector2D(inTree.min_x * 1.1 - padding, inTree.min_y * 1.1 - padding), new Vector2D(inTree.max_x * 1.1 + padding, inTree.max_y * 1.1 + padding)); } InitNodeSurround();// DrawNodeSurround(); DrawNodeBaseSurround(); InitSkillIconLayers(); DrawSkillIconLayer(); DrawBackgroundLayer(); InitFaceBrushesAndLayer(); DrawLinkBackgroundLayer(_links); InitOtherDynamicLayers(); CreateCombineVisual(); if (_links != null) { var regexAttrib = new Regex("[0-9]*\\.?[0-9]+"); foreach (var skillNode in Skillnodes) { skillNode.Value.Attributes = new Dictionary<string, List<float>>(); foreach (string s in skillNode.Value.attributes) { var values = new List<float>(); foreach (Match m in regexAttrib.Matches(s)) { if (!AttributeTypes.Contains(regexAttrib.Replace(s, "#"))) AttributeTypes.Add(regexAttrib.Replace(s, "#")); if (m.Value == "") values.Add(float.NaN); else values.Add(float.Parse(m.Value, CultureInfo.InvariantCulture)); } string cs = (regexAttrib.Replace(s, "#")); skillNode.Value.Attributes[cs] = values; } } } if (displayProgress) update(100, 100); _Initialized = true; }
private async Task InitializeAsync(string treestring, string opsstring, [CanBeNull] ProgressDialogController controller, AssetLoader assetLoader) { if (!_initialized) { var jss = new JsonSerializerSettings { Error = (sender, args) => { // This one is known: "515":{"x":_,"y":_,"oo":[],"n":[]}} has an Array in "oo". if (args.ErrorContext.Path != "groups.515.oo") Log.Error("Exception while deserializing Json tree", args.ErrorContext.Error); args.ErrorContext.Handled = true; } }; var inTree = JsonConvert.DeserializeObject<PoESkillTree>(treestring, jss); var inOpts = JsonConvert.DeserializeObject<Opts>(opsstring, jss); controller?.SetProgress(0.25); await assetLoader.DownloadSkillNodeSpritesAsync(inTree, d => controller?.SetProgress(0.25 + d * 0.30)); IconInActiveSkills = new SkillIcons(); IconActiveSkills = new SkillIcons(); foreach (var obj in inTree.skillSprites) { SkillIcons icons; string prefix; if (obj.Key.EndsWith("Active")) { // Adds active nodes to IconActiveSkills icons = IconActiveSkills; prefix = obj.Key.Substring(0, obj.Key.Length - "Active".Length); } else if (obj.Key.EndsWith("Inactive")) { // Adds inactive nodes to IconInActiveSkills icons = IconInActiveSkills; prefix = obj.Key.Substring(0, obj.Key.Length - "Inactive".Length); } else { // Adds masteries to IconInActiveSkills icons = IconInActiveSkills; prefix = obj.Key; } var sprite = obj.Value[AssetZoomLevel]; var path = _assetsFolderPath + sprite.filename; icons.Images[sprite.filename] = ImageHelper.OnLoadBitmapImage(new Uri(path, UriKind.Absolute)); foreach (var o in sprite.coords) { var iconKey = prefix + "_" + o.Key; icons.SkillPositions[iconKey] = new Rect(o.Value.x, o.Value.y, o.Value.w, o.Value.h); icons.SkillImages[iconKey] = sprite.filename; } } controller?.SetProgress(0.55); // The last percent progress is reserved for rounding errors as progress must not get > 1. await assetLoader.DownloadAssetsAsync(inTree, d => controller?.SetProgress(0.55 + d * 0.44)); foreach (var ass in inTree.assets) { var path = _assetsFolderPath + ass.Key + ".png"; Assets[ass.Key] = ImageHelper.OnLoadBitmapImage(new Uri(path, UriKind.Absolute)); } RootNodeList = new List<int>(); if (inTree.root != null) { foreach (int i in inTree.root.ot) { RootNodeList.Add(i); } } else if (inTree.main != null) { foreach (int i in inTree.main.ot) { RootNodeList.Add(i); } } _ascClasses = new AscendancyClasses(); if (inOpts != null) { foreach (KeyValuePair<int, baseToAscClass> ascClass in inOpts.ascClasses) { var classes = new List<AscendancyClasses.Class>(); foreach (KeyValuePair<int, classes> asc in ascClass.Value.classes) { var newClass = new AscendancyClasses.Class { Order = asc.Key, DisplayName = asc.Value.displayName, Name = asc.Value.name, FlavourText = asc.Value.flavourText, FlavourTextColour = asc.Value.flavourTextColour.Split(',').Select(int.Parse).ToArray() }; int[] tempPointList = asc.Value.flavourTextRect.Split(',').Select(int.Parse).ToArray(); newClass.FlavourTextRect = new Vector2D(tempPointList[0], tempPointList[1]); classes.Add(newClass); } AscClasses.Classes.Add(ascClass.Value.name, classes); } } CharBaseAttributes = new Dictionary<string, float>[7]; foreach (var c in inTree.characterData) { CharBaseAttributes[c.Key] = new Dictionary<string, float> { {"+# to Strength", c.Value.base_str}, {"+# to Dexterity", c.Value.base_dex}, {"+# to Intelligence", c.Value.base_int} }; } Skillnodes = new Dictionary<ushort, SkillNode>(); RootNodeClassDictionary = new Dictionary<string, int>(); StartNodeDictionary = new Dictionary<int, int>(); AscRootNodeList = new HashSet<SkillNode>(); foreach (var nd in inTree.nodes) { var skillNode = new SkillNode { Id = nd.id, Name = nd.dn, //this value should not be split on '\n' as it causes the attribute list to seperate nodes attributes = nd.dn.Contains("Jewel Socket") ? new[] { "+1 Jewel Socket" } : nd.sd, Orbit = nd.o, OrbitIndex = nd.oidx, Icon = nd.icon, LinkId = nd.ot, G = nd.g, Da = nd.da, Ia = nd.ia, Sa = nd.sa, Spc = nd.spc.Length > 0 ? (int?)nd.spc[0] : null, IsMultipleChoice = nd.isMultipleChoice, IsMultipleChoiceOption = nd.isMultipleChoiceOption, passivePointsGranted = nd.passivePointsGranted, ascendancyName = nd.ascendancyName, IsAscendancyStart = nd.isAscendancyStart, reminderText = nd.reminderText }; if (nd.ks && !nd.not && !nd.isJewelSocket && !nd.m) { skillNode.Type = NodeType.Keystone; } else if (!nd.ks && nd.not && !nd.isJewelSocket && !nd.m) { skillNode.Type = NodeType.Notable; } else if (!nd.ks && !nd.not && nd.isJewelSocket && !nd.m) { skillNode.Type = NodeType.JewelSocket; } else if (!nd.ks && !nd.not && !nd.isJewelSocket && nd.m) { skillNode.Type = NodeType.Mastery; } else if (!nd.ks && !nd.not && !nd.isJewelSocket && !nd.m) { skillNode.Type = NodeType.Normal; } else { throw new InvalidOperationException($"Invalid node type for node {skillNode.Name}"); } Skillnodes.Add(nd.id, skillNode); if(skillNode.IsAscendancyStart) if(!AscRootNodeList.Contains(skillNode)) AscRootNodeList.Add(skillNode); if (RootNodeList.Contains(nd.id)) { if (!RootNodeClassDictionary.ContainsKey(nd.dn.ToUpperInvariant())) { RootNodeClassDictionary.Add(nd.dn.ToUpperInvariant(), nd.id); } foreach (var linkedNode in nd.ot) { if (!StartNodeDictionary.ContainsKey(nd.id) && !nd.isAscendancyStart) { StartNodeDictionary.Add(linkedNode, nd.id); } } } foreach (var node in nd.ot) { if (!StartNodeDictionary.ContainsKey(nd.id) && RootNodeList.Contains(node)) { StartNodeDictionary.Add(nd.id, node); } } } foreach (var skillNode in Skillnodes) { foreach (var i in skillNode.Value.LinkId) { if (Links.Count(nd => (nd[0] == i && nd[1] == skillNode.Key) || nd[0] == skillNode.Key && nd[1] == i) != 1) Links.Add(new[] { skillNode.Key, i }); } } foreach (var ints in Links) { Regex regexString = new Regex(@"Can Allocate Passives from the .* starting point"); bool isScionAscendancyNotable = false; foreach (var attibute in Skillnodes[ints[0]].attributes) { if (regexString.IsMatch(attibute)) isScionAscendancyNotable = true; } foreach (var attibute in Skillnodes[ints[1]].attributes) { if (regexString.IsMatch(attibute)) isScionAscendancyNotable = true; } if (isScionAscendancyNotable && StartNodeDictionary.Keys.Contains(ints[0])) { if (!Skillnodes[ints[1]].Neighbor.Contains(Skillnodes[ints[0]])) Skillnodes[ints[1]].Neighbor.Add(Skillnodes[ints[0]]); } else if (isScionAscendancyNotable && StartNodeDictionary.Keys.Contains(ints[1])) { if (!Skillnodes[ints[0]].Neighbor.Contains(Skillnodes[ints[1]])) Skillnodes[ints[0]].Neighbor.Add(Skillnodes[ints[1]]); } else { if (!Skillnodes[ints[0]].Neighbor.Contains(Skillnodes[ints[1]])) Skillnodes[ints[0]].Neighbor.Add(Skillnodes[ints[1]]); if (!Skillnodes[ints[1]].Neighbor.Contains(Skillnodes[ints[0]])) Skillnodes[ints[1]].Neighbor.Add(Skillnodes[ints[0]]); } } var regexAttrib = new Regex("[0-9]*\\.?[0-9]+"); foreach (var skillnode in Skillnodes) { //add each other as visible neighbors foreach (var snn in skillnode.Value.Neighbor) { if (snn.IsAscendancyStart && skillnode.Value.LinkId.Contains(snn.Id)) continue; skillnode.Value.VisibleNeighbors.Add(snn); } //populate the Attributes fields with parsed attributes skillnode.Value.Attributes = new Dictionary<string, List<float>>(); foreach (string s in skillnode.Value.attributes) { var values = new List<float>(); foreach (Match m in regexAttrib.Matches(s)) { if (!AttributeTypes.Contains(regexAttrib.Replace(s, "#"))) AttributeTypes.Add(regexAttrib.Replace(s, "#")); if (m.Value == "") values.Add(float.NaN); else values.Add(float.Parse(m.Value, CultureInfo.InvariantCulture)); } string cs = (regexAttrib.Replace(s, "#")); skillnode.Value.Attributes[cs] = values; } } NodeGroups = new List<SkillNodeGroup>(); foreach (var gp in inTree.groups) { var ng = new SkillNodeGroup(); ng.OcpOrb = gp.Value.oo; ng.Position = new Vector2D(gp.Value.x, gp.Value.y); foreach (var node in gp.Value.n) { ng.Nodes.Add(Skillnodes[node]); } NodeGroups.Add(ng); } foreach (SkillNodeGroup group in NodeGroups) { foreach (SkillNode node in group.Nodes) { node.SkillNodeGroup = group; } } const int padding = 500; //This is to account for jewel range circles. Might need to find a better way to do it. SkillTreeRect = new Rect2D(new Vector2D(inTree.min_x * 1.1 - padding, inTree.min_y * 1.1 - padding), new Vector2D(inTree.max_x * 1.1 + padding, inTree.max_y * 1.1 + padding)); } if (_persistentData.Options.ShowAllAscendancyClasses) DrawAscendancy = true; InitialSkillTreeDrawing(); controller?.SetProgress(1); _initialized = true; }
public bool IntersectsWith(Rect2D r) { return !(r.Max.X <= Min.X || r.Max.Y <= Min.Y || Max.Y <= r.Min.Y || Max.X <= r.Min.X); }
public bool Contains(Rect2D v) { return v.Min.X >= Min.X && v.Min.Y >= Min.Y && v.Max.Y <= Max.Y && v.Max.X <= Max.X; }
public static Vector2D? IntersectLineLine(Vector2D s1, Vector2D e1, Vector2D s2, Vector2D e2) { var aabb1 = new Rect2D(s1, e1); var aabb2 = new Rect2D(s2, e2); if (!aabb1.IntersectsWith(aabb2)) return null; double x1 = s1.X; double x2 = e1.X; double x3 = s2.X; double x4 = e2.X; double y1 = s1.Y; double y2 = e1.Y; double y3 = s2.Y; double y4 = e2.Y; double denom = (x1 - x2)*(y3 - y4) - (y1 - y2)*(x3 - x4); if (Math.Abs(denom) < 1e-4) return null; double px = ((x1*y2 - y1*x2)*(x3 - x4) - (x1 - x2)*(x3*y4 - y3*x4))/denom; double py = ((x1*y2 - y1*x2)*(y3 - y4) - (y1 - y2)*(x3*y4 - y3*x4))/denom; var p = new Vector2D(px, py); double l1 = (p - s1).Length; double l2 = (p - e1).Length; if (l1 + l2 > (s1 - e1).Length + 1e-3) return null; return p; }