public void CreateFhAnchor() { FootholdAnchor fhAnchor = new FootholdAnchor(Board, X, Y, Board.SelectedLayerIndex, false); Board.BoardItems.FHAnchors.Add(fhAnchor); Board.UndoRedoMan.AddUndoBatch(new List <UndoRedoAction> { UndoRedoManager.ItemAdded(fhAnchor) }); if (connectedLines.Count == 0) { Board.BoardItems.FootholdLines.Add(new FootholdLine(Board, fhAnchor)); } else { connectedLines[0].ConnectSecondDot(fhAnchor); Board.BoardItems.FootholdLines.Add(new FootholdLine(Board, fhAnchor)); } }
public virtual void DoSnap() { if (!InputHandler.IsKeyPushedDown(System.Windows.Forms.Keys.ShiftKey) || connectedLines.Count == 0 || !(connectedLines[0] is FootholdLine)) { return; } FootholdAnchor closestAnchor = null; double closestAngle = double.MaxValue; bool xClosest = true; foreach (FootholdLine line in connectedLines) { FootholdAnchor otherAnchor = (FootholdAnchor)(line.FirstDot == this ? line.SecondDot : line.FirstDot); double xAngle = Math.Abs(Math.Atan((double)(Y - otherAnchor.Y) / (double)(X - otherAnchor.X))); double yAngle = Math.Abs(Math.Atan((double)(X - otherAnchor.X) / (double)(Y - otherAnchor.Y))); double minAngle; bool xSmaller = false; if (xAngle < yAngle) { xSmaller = true; minAngle = xAngle; } else { xSmaller = false; minAngle = yAngle; } if (minAngle < closestAngle) { xClosest = xSmaller; closestAnchor = otherAnchor; closestAngle = minAngle; } } if (closestAnchor != null) { if (xClosest) { Y = closestAnchor.Y; } else { X = closestAnchor.X; } } }
public static int FHAnchorSorter(FootholdAnchor c, FootholdAnchor d) { if (c.X > d.X) { return(1); } else if (c.X < d.X) { return(-1); } else { if (c.Y > d.Y) { return(1); } else if (c.Y < d.Y) { return(-1); } else { if (c.LayerNumber > d.LayerNumber) { return(1); } else if (c.LayerNumber < d.LayerNumber) { return(-1); } else { return(0); } } } }
public void CreateFhAnchor() { FootholdAnchor fhAnchor = new FootholdAnchor(Board, X, Y, Board.SelectedLayerIndex, false); Board.BoardItems.FHAnchors.Add(fhAnchor); Board.UndoRedoMan.AddUndoBatch(new List<UndoRedoAction> { UndoRedoManager.ItemAdded(fhAnchor) }); if (connectedLines.Count == 0) { Board.BoardItems.FootholdLines.Add(new FootholdLine(Board, fhAnchor)); } else { connectedLines[0].ConnectSecondDot(fhAnchor); Board.BoardItems.FootholdLines.Add(new FootholdLine(Board, fhAnchor)); } }
public void ParseOffsets(TileInstance instance, Board board, Layer layer, int x, int y) { List<FootholdAnchor> anchors = new List<FootholdAnchor>(); foreach (XNA.Point foothold in footholdOffsets) { FootholdAnchor anchor = new FootholdAnchor(board, x + foothold.X, y + foothold.Y, layer.LayerNumber, false); anchors.Add(anchor); board.BoardItems.FHAnchors.Add(anchor); instance.BindItem(anchor, foothold); } for (int i = 0; i < anchors.Count - 1; i++) { FootholdLine fh = new FootholdLine(board, anchors[i], anchors[i + 1]); board.BoardItems.FootholdLines.Add(fh); } }
public void ParseOffsets(ObjectInstance instance, Layer layer, Board board, int x, int y) { List<FootholdAnchor> anchors = new List<FootholdAnchor>(); bool ladder = l0 == "ladder"; if (footholdOffsets != null || footholdFullOffsets != null) { if (!fullFootholdInfo) { foreach (XNA.Point foothold in footholdOffsets) { FootholdAnchor anchor = new FootholdAnchor(board, x + foothold.X, y + foothold.Y, layer.LayerNumber, false); board.BoardItems.FHAnchors.Add(anchor); instance.BindItem(anchor, foothold); anchors.Add(anchor); } CreateFootholdsFromAnchorList(board, anchors); } else { foreach (List<XNA.Point> anchorList in footholdFullOffsets) { foreach (XNA.Point foothold in anchorList) { FootholdAnchor anchor = new FootholdAnchor(board, x + foothold.X, y + foothold.Y, layer.LayerNumber, false); board.BoardItems.FHAnchors.Add(anchor); instance.BindItem(anchor, foothold); anchors.Add(anchor); } CreateFootholdsFromAnchorList(board, anchors); anchors.Clear(); } } } if (chairOffsets != null) foreach (XNA.Point chairPos in chairOffsets) { Chair chair = new Chair(board, x + chairPos.X, y + chairPos.Y, false); board.BoardItems.Chairs.Add(chair); instance.BindItem(chair, chairPos); } /*foreach (XNA.Point rope in ropeOffsets) //second thought: what the f**k is this even good for? rope origins aren't multilined anyway, why add them as board items? { RopeLadderAnchor ropeAnchor = new RopeLadderAnchor(board, x + rope.X, y + rope.Y, layer.LayerNumber, ladder, false); board.BoardItems.RopeAnchors.Add(ropeAnchor); instance.BindItem(ropeAnchor, rope); }*/ }
public static int FHAnchorSorter(FootholdAnchor c, FootholdAnchor d) { if (c.X > d.X) return 1; else if (c.X < d.X) return -1; else { if (c.Y > d.Y) return 1; else if (c.Y < d.Y) return -1; else { if (c.LayerNumber > d.LayerNumber) return 1; else if (c.LayerNumber < d.LayerNumber) return -1; else return 0; } } }
private static FootholdLine GetOtherFh(FootholdAnchor anchor, FootholdLine source, Hashtable fhListByPoint) { List<FootholdLine> connectedLines = (List<FootholdLine>)fhListByPoint[new Point(anchor.X, anchor.Y)]; if (connectedLines.Count < 2) return null; else if (connectedLines.Count == 2) { return connectedLines[1].FhEquals(source) ? connectedLines[0] : connectedLines[1]; } else //reaching this part means whoever made the map is a f*****g idiot { FootholdLine longestFh = null; int longestFhLenth = 0; foreach (FootholdLine fh in connectedLines) { int length = (int)Math.Sqrt(Math.Pow((fh.SecondDot.X - fh.FirstDot.X), 2) + Math.Pow((fh.SecondDot.Y - fh.FirstDot.Y), 2)); if (!fh.FhEquals(source) && length > longestFhLenth) { longestFh = fh; longestFhLenth = length; } } return longestFh; } }
private static void LoadFootholds(WzImage mapImage, Board mapBoard) { List<FootholdAnchor> anchors = new List<FootholdAnchor>(); WzSubProperty footholdParent = (WzSubProperty)mapImage["foothold"]; int layer; int plat; FootholdAnchor a; FootholdAnchor b; FootholdAnchor c; FootholdAnchor d; foreach (WzSubProperty layerProp in footholdParent.WzProperties) { layer = int.Parse(layerProp.Name); foreach (WzSubProperty platProp in layerProp.WzProperties) { plat = int.Parse(platProp.Name); foreach (WzSubProperty fhProp in platProp.WzProperties) { a = new FootholdAnchor(mapBoard, InfoTool.GetInt(fhProp["x1"]), InfoTool.GetInt(fhProp["y1"]), layer, false, plat); b = new FootholdAnchor(mapBoard, InfoTool.GetInt(fhProp["x2"]), InfoTool.GetInt(fhProp["y2"]), layer, false, plat); int num = int.Parse(fhProp.Name); int next = InfoTool.GetInt(fhProp["next"]); int prev = InfoTool.GetInt(fhProp["prev"]); if (a.X != b.X || a.Y != b.Y) { FootholdLine fh = new FootholdLine(mapBoard, a, b); fh.num = num; fh.prev = prev; fh.next = next; fh.Name = fhProp.Name; mapBoard.BoardItems.FootholdLines.Add(fh); anchors.Add(a); anchors.Add(b); } } } anchors.Sort(new Comparison<FootholdAnchor>(FootholdAnchor.FHAnchorSorter)); int groupStart = 0; //inclusive int groupEnd = 0; //inclusive for (int i = 0; i < anchors.Count - 1; i++) { a = anchors[i]; b = anchors[i + 1]; if (a.Y != b.Y && a.X != b.X && a.LayerNumber == b.LayerNumber) { groupEnd = i; if (groupEnd - groupStart == 1) //there are 2 objects in the group, since groupEnd and groupStart are inclusive { c = anchors[groupStart]; d = anchors[groupEnd]; CheckAnchorPairMerge(c, d); } else if (groupEnd - groupStart != 0) { for (int j = groupStart; j <= groupEnd; j++) { c = anchors[j]; for (int k = groupStart; k <= groupEnd; k++) { if (c.removed) break; d = anchors[k]; if (d.removed) continue; CheckAnchorPairMerge(c, d); } } } groupStart = groupEnd + 1; } } groupEnd = anchors.Count - 1; if (groupEnd - groupStart == 1) //there are 2 objects in the group, since groupEnd and groupStart are inclusive { c = anchors[groupStart]; d = anchors[groupEnd]; CheckAnchorPairMerge(c, d); } else if (groupEnd - groupStart != 0) { for (int j = groupStart; j <= groupEnd; j++) { c = anchors[j]; for (int k = groupStart; k <= groupEnd; k++) { if (c.removed) break; d = anchors[k]; if (d.removed) continue; CheckAnchorPairMerge(c, d); } } } //FootholdAnchor.MergeAnchors(ref anchors); /*if (mapBoard.BoardItems.FHAnchors.Count + anchors.Count > mapBoard.BoardItems.FHAnchors.Capacity) mapBoard.BoardItems.FHAnchors.Capacity = mapBoard.BoardItems.FHAnchors.Count + anchors.Count; anchors.ForEach(X => if mapBoard.BoardItems.FHAnchors.Add(X)); anchors.Clear();*/ mapBoard.BoardItems.FHAnchors.Capacity = mapBoard.BoardItems.FHAnchors.Count + anchors.Count * 2; foreach (FootholdAnchor anchor in anchors) if (!anchor.removed) mapBoard.BoardItems.FHAnchors.Add(anchor); anchors.Clear(); } }
private static int FHAnchorSorter(FootholdAnchor a, FootholdAnchor b) { if (a.X > b.X) return 1; else if (a.X < b.X) return -1; else { if (a.Y > b.Y) return 1; else if (a.Y < b.Y) return -1; else return 0; } }
private static void CheckAnchorPairMerge(FootholdAnchor a, FootholdAnchor b) { if (a.X == b.X && a.Y == b.Y && a.LayerNumber == b.LayerNumber) { FootholdLine lineA = (FootholdLine)a.connectedLines[0]; FootholdLine lineB = (FootholdLine)b.connectedLines[0]; if ((lineA.next == lineB.num && lineB.prev == lineA.num) || (lineA.prev == lineB.num && lineB.next == lineA.num)) { b.removed = true; if (lineB.FirstDot == b) //b is firstdot lineB.FirstDot = a; else lineB.SecondDot = a; a.connectedLines.Add(lineB); } } }
private static void EliminateFootholdTree(FootholdAnchor anchor, int lineIndex, ref List<FootholdLine> footholds) { FootholdLine line = (FootholdLine)anchor.connectedLines[lineIndex]; footholds.Remove(line); line.remove = true; FootholdAnchor otherAnchor = GetOtherAnchor(line, anchor); for (int i = 0; i < otherAnchor.connectedLines.Count; i++) if (otherAnchor.connectedLines[i] != line) EliminateFootholdTree(otherAnchor, i, ref footholds); }
/*private static double CalculateFootholdTreeLength(FootholdAnchor anchor, int lineIndex) { double length = 0; FootholdLine line = (FootholdLine)anchor.connectedLines[lineIndex]; int dx = line.FirstDot.X - line.SecondDot.X; int dy = line.FirstDot.Y - line.SecondDot.Y; length += Math.Sqrt(dx * dx + dy * dy); FootholdAnchor otherAnchor = GetOtherAnchor(line, anchor); for (int i = 0; i < otherAnchor.connectedLines.Count; i++) if (otherAnchor.connectedLines[i] != line) length += CalculateFootholdTreeLength(anchor, i); return length; }*/ private static bool FootholdTreeLengthExceeds(FootholdAnchor anchor, int lineIndex, int max) //max is inclusive { FootholdLine line = (FootholdLine)anchor.connectedLines[0]; int length = 1; while (length <= max) { anchor = GetOtherAnchor(line, anchor); line = GetOtherLine(line, anchor); if (line == null) return false; } return true; }
private static FootholdLine GetOtherLine(FootholdLine line, FootholdAnchor currAnchor) { foreach (FootholdLine currLine in currAnchor.connectedLines) if (line != currLine) return currLine; return null; }
private static FootholdAnchor GetOtherAnchor(FootholdLine line, FootholdAnchor currAnchor) { return (FootholdAnchor)(line.FirstDot == currAnchor ? line.SecondDot : line.FirstDot); }
public static void ConvertToMapleFootholds2(ref MapleList<FootholdLine> oldFootholds, ref MapleList<FootholdAnchor> oldAnchors) { //Part 1 - copying and filtering out unused anchors List<FootholdLine> footholds = new List<FootholdLine>(oldFootholds.Count); List<FootholdAnchor> anchors = new List<FootholdAnchor>(oldAnchors.Count); foreach (FootholdAnchor oldAnchor in oldAnchors) { if (oldAnchor.connectedLines.Count == 0) continue; //if (oldAnchor.IsMoveHandled) throw new Exception(); FootholdAnchor anchor = new FootholdAnchor(oldAnchor.Board, oldAnchor.X, oldAnchor.Y, oldAnchor.LayerNumber, oldAnchor.BeforeAdding); anchor.connectedLines = new List<MapleLine>(oldAnchor.connectedLines.Count); foreach (FootholdLine oldLine in oldAnchor.connectedLines) { if (oldLine.cloneLine == null) { FootholdAnchor firstDot = null; FootholdAnchor secondDot = null; if (oldLine.FirstDot.X > oldLine.SecondDot.X) { firstDot = (FootholdAnchor)oldLine.SecondDot; secondDot = (FootholdAnchor)oldLine.FirstDot; } else if (oldLine.FirstDot.X < oldLine.SecondDot.X) { firstDot = (FootholdAnchor)oldLine.FirstDot; secondDot = (FootholdAnchor)oldLine.SecondDot; } else { if (oldLine.FirstDot.Y > oldLine.SecondDot.Y) { firstDot = (FootholdAnchor)oldLine.SecondDot; secondDot = (FootholdAnchor)oldLine.FirstDot; } else { firstDot = (FootholdAnchor)oldLine.FirstDot; secondDot = (FootholdAnchor)oldLine.SecondDot; } } if (anchor.X == firstDot.X && anchor.Y == firstDot.Y) //we are firstdot { firstDot = anchor; secondDot = null; } else //we are seconddot { firstDot = null; secondDot = anchor; } oldLine.cloneLine = FootholdLine.CreateCustomFootholdLine(oldLine.Board, firstDot, secondDot); footholds.Add(oldLine.cloneLine); } else { if (oldLine.cloneLine.FirstDot == null) oldLine.cloneLine.FirstDot = anchor; else oldLine.cloneLine.SecondDot = anchor; } anchor.connectedLines.Add(oldLine.cloneLine); } anchors.Add(anchor); } foreach (FootholdLine fhLine in oldFootholds) fhLine.cloneLine = null; //Part 2 - combining anchors that are on the exact same position anchors.Sort(new Comparison<FootholdAnchor>(FootholdAnchor.FHAnchorSorter)); int groupStart = 0; //inclusive int groupEnd = 0; //inclusive FootholdAnchor a; FootholdAnchor b; FootholdAnchor c; FootholdAnchor d; FootholdLine line; for (int i = 0; i < anchors.Count - 1; i++) { a = anchors[i]; b = anchors[i + 1]; if (a.Y != b.Y && a.X != b.X && a.LayerNumber == b.LayerNumber) { groupEnd = i; if (groupEnd - groupStart == 1) //there are 2 objects in the group, since groupEnd and groupStart are inclusive { c = anchors[groupStart]; d = anchors[groupEnd]; if (c.connectedLines.Count == 1 && d.connectedLines.Count == 1) { d.removed = true; line = (FootholdLine)d.connectedLines[0]; if (line.FirstDot == d) line.FirstDot = c; else line.SecondDot = c; c.connectedLines.Add(line); } } groupStart = groupEnd + 1; } } groupEnd = anchors.Count - 1; if (groupEnd - groupStart == 1) //there are 2 objects in the group, since groupEnd and groupStart are inclusive { c = anchors[groupStart]; d = anchors[groupEnd]; if (c.connectedLines.Count == 1 && d.connectedLines.Count == 1) { d.removed = true; line = (FootholdLine)d.connectedLines[0]; if (line.FirstDot == d) line.FirstDot = c; else line.SecondDot = c; c.connectedLines.Add(line); } } //Part 3 - connecting footholds to anchors they pass through, selectively //this part is made purely to fix problems in the foothold structure caused //by the auto foothold connection feature for tiles for (int i = 0; i < footholds.Count; i++) { line = footholds[i]; if (line.FirstDot.Y != line.SecondDot.Y) continue; foreach (FootholdAnchor anchor in anchors) { if (anchor.X == line.FirstDot.Y && ((IContainsLayerInfo)line.FirstDot).LayerNumber == anchor.LayerNumber) { if (anchor.connectedLines.Count == 1) line = (FootholdLine)anchor.connectedLines[0]; else line = (FootholdLine)(anchor.connectedLines[0].FirstDot.Y == anchor.connectedLines[0].SecondDot.Y ? anchor.connectedLines[0] : anchor.connectedLines[1]); if (line.FirstDot.Y == line.SecondDot.Y) //blueCave2 tiles, first anchor of sloped tiles { //footholds.RemoveAt(i); line.remove = true; footholds.Add(new FootholdLine(line.Board, line.FirstDot, anchor)); footholds.Add(new FootholdLine(line.Board, anchor, line.SecondDot)); //i--; break; //anchor.keyAnchor = line.FirstDot.Y == line.SecondDot.Y && IsValidKeyAnchor(anchor); } else //junction anchor for sloped tiles { bool direction = line.FirstDot == anchor; //true = anchor is the left dot, so we need to delete the line going to the right //footholds.RemoveAt(i); line.remove = true; if (direction) footholds.Add(new FootholdLine(line.Board, line.FirstDot, anchor)); else footholds.Add(new FootholdLine(line.Board, anchor, line.SecondDot)); break; } } } /* if (((line.FirstDot.X == line.SecondDot.X) && (anchor.X == line.FirstDot.X && anchor.Y > line.FirstDot.Y && anchor.Y < line.SecondDot.Y) || ((line.FirstDot.Y == line.SecondDot.Y) && (anchor.Y == line.FirstDot.Y && anchor.X > line.FirstDot.X && anchor.X < line.SecondDot.X))) && ((IContainsLayerInfo)line.FirstDot).LayerNumber == anchor.LayerNumber)*/ } FootholdLine lineA; FootholdLine lineB; //Part 4 - removing duplicate footholds (caused by step 3, case 1) footholds.Sort(new Comparison<FootholdLine>(FHSorter)); for (int i = 0; i < footholds.Count - 1; i++) { lineA = footholds[i]; lineB = footholds[i + 1]; if (lineA.FirstDot.X == lineB.FirstDot.X && lineA.FirstDot.Y == lineB.FirstDot.Y && lineA.SecondDot.X == lineB.SecondDot.X && lineA.SecondDot.Y == lineB.SecondDot.Y) { //footholds.RemoveAt(i); lineA.remove = true; i--; } } //Part 5 - executing foothold changes and updating anchors foreach (FootholdAnchor anchor in anchors) for (int i = 0; i < anchor.connectedLines.Count; i++) if (((FootholdLine)anchor.connectedLines[i]).remove) anchor.connectedLines.RemoveAt(i); List<FootholdLine> newFootholds = new List<FootholdLine>(footholds.Count); foreach (FootholdLine fh in footholds) if (!fh.remove) newFootholds.Add(fh); footholds = newFootholds; //Part 6 - dealing with 3 way (or more) foothold junctions /*foreach (FootholdAnchor anchor in anchors) { if (anchor.connectedLines.Count > 2) { if (anchor.keyAnchor) { int leftLineIndex = -1; int rightLineIndex = -1; int slopedLineIndex = -1; for(int i=0; i<anchor.connectedLines.Count; i++) { FootholdLine line = (FootholdLine)anchor.connectedLines[i]; if (line.FirstDot.Y == line.SecondDot.Y) { if (anchor == line.FirstDot) rightLineIndex = i; else if (anchor == line.SecondDot) leftLineIndex = i; else { MessageBox.Show("Error at foothold parsing"); //TODO } } else if (line.FirstDot.X != line.SecondDot.X) slopedLineIndex = i; } if (leftLineIndex == -1 || rightLineIndex == -1 || slopedLineIndex == -1) { MessageBox.Show("Error at foothold parsing"); //TODO } FootholdLine slopedLine = (FootholdLine)anchor.connectedLines[slopedLineIndex]; if (slopedLine.FirstDot.Y < slopedLine.SecondDot.Y) { //eliminate left EliminateFootholdTree(anchor, leftLineIndex, ref footholds); } else { //eliminate right EliminateFootholdTree(anchor, rightLineIndex, ref footholds); } } else { double lowestLength = double.MaxValue; int shortestLineIndex = -1; for (int i = 0; i < anchor.connectedLines.Count; i++) { double length = CalculateFootholdTreeLength(anchor, i); if (length < lowestLength) { lowestLength = length; shortestLineIndex = i; } } EliminateFootholdTree(anchor, shortestLineIndex, ref footholds); } } } //Part 7 - executing foothold changes and updating anchors (again) foreach (FootholdAnchor anchor in anchors) for (int i = 0; i < anchor.connectedLines.Count; i++) if (((FootholdLine)anchor.connectedLines[i]).remove) anchor.connectedLines.RemoveAt(i);*/ oldAnchors.Clear(); foreach (FootholdAnchor anchor in anchors) { /*anchor.keyAnchor = false; */oldAnchors.Add(anchor); } oldFootholds.Clear(); foreach (FootholdLine fh in footholds) { /*anchor.keyAnchor = false; */oldFootholds.Add(fh); } }