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); } }
public FootholdEditor(FootholdLine[] footholds) { this.footholds = footholds; InitializeComponent(); int? force = footholds[0].Force; int? piece = footholds[0].Piece; bool cantThrough = footholds[0].CantThrough; bool forbidFallDown = footholds[0].ForbidFallDown; bool indeterminate = false; for (int i = 1; i < footholds.Length; i++) if (footholds[i].Force != force) { indeterminate = true; break; } if (indeterminate) forceEnable.CheckState = CheckState.Indeterminate; else if (forceEnable.Checked = force != null) forceInt.Value = (int)force; indeterminate = false; for (int i = 1; i < footholds.Length; i++) if (footholds[i].Piece != piece) { indeterminate = true; break; } if (indeterminate) pieceEnable.CheckState = CheckState.Indeterminate; else if (pieceEnable.Checked = force != null) pieceInt.Value = (int)piece; indeterminate = false; for (int i = 1; i < footholds.Length; i++) if (footholds[i].CantThrough != cantThrough) { indeterminate = true; break; } if (indeterminate) cantThroughBox.CheckState = CheckState.Indeterminate; else cantThroughBox.Checked = cantThrough; indeterminate = false; for (int i = 1; i < footholds.Length; i++) if (footholds[i].ForbidFallDown != forbidFallDown) { indeterminate = true; break; } if (indeterminate) forbidFallDownBox.CheckState = CheckState.Indeterminate; else forbidFallDownBox.Checked = forbidFallDown; }
private void CreateFootholdsFromAnchorList(Board board, List <FootholdAnchor> anchors) { 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(TileInstance instance, Board board, 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, instance.LayerNumber, instance.PlatformNumber, true); 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); } }
private bool IsAnchorPrevOfFoothold(FootholdAnchor a, FootholdLine x) { int prevnum = x.prev; int nextnum = x.next; foreach (FootholdLine l in a.connectedLines) { if (l.num == prevnum) { return(true); } else if (l.num == nextnum) { return(false); } } throw new Exception("Could not match anchor to foothold"); }
public void Clear() { lock (Board.ParentControl) { if (currAddedObj != null) { currAddedObj.RemoveItem(null); currAddedObj = null; } if (state == MouseState.Ropes || state == MouseState.Tooltip) { if (state == MouseState.Ropes) { ((RopeAnchor)BoundItems.Keys.ElementAt(0)).RemoveItem(null); } else { ((ToolTipDot)BoundItems.Keys.ElementAt(0)).ParentTooltip.RemoveItem(null); } } else if (state == MouseState.Footholds && connectedLines.Count > 0) { FootholdLine fh = (FootholdLine)connectedLines[0]; fh.Remove(false, null); Board.BoardItems.FootholdLines.Remove(fh); } else if (state == MouseState.Clock) { List <BoardItem> items = BoundItems.Keys.ToList(); foreach (BoardItem item in items) { item.RemoveItem(null); } } InputHandler.ClearBoundItems(Board); InputHandler.ClearSelectedItems(Board); IsDown = false; } }
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); } } }
public void TryConnectFoothold() { lock (Board.ParentControl) { Xna.Point pos = new Xna.Point(X, Y); SelectionInfo sel = board.GetUserSelectionInfo(); foreach (FootholdAnchor anchor in Board.BoardItems.FHAnchors) { if (MultiBoard.IsPointInsideRectangle(pos, anchor.Left, anchor.Top, anchor.Right, anchor.Bottom) && anchor.CheckIfLayerSelected(sel)) { if (anchor.connectedLines.Count > 1) { continue; } if (connectedLines.Count > 0) // Are we already holding a foothold? { // We are, so connect the two ends // Check that we are not connecting a foothold to itself, or creating duplicate footholds if (connectedLines[0].FirstDot != anchor && !FootholdLine.Exists(anchor.X, anchor.Y, connectedLines[0].FirstDot.X, connectedLines[0].FirstDot.Y, Board)) { Board.UndoRedoMan.AddUndoBatch(new List <UndoRedoAction> { UndoRedoManager.LineAdded(connectedLines[0], connectedLines[0].FirstDot, anchor) }); connectedLines[0].ConnectSecondDot(anchor); // Now that we finished the previous foothold, create a new one between the anchor and the mouse FootholdLine fh = new FootholdLine(Board, anchor); Board.BoardItems.FootholdLines.Add(fh); } } else // Construct a footholdline between the anchor and the mouse { Board.BoardItems.FootholdLines.Add(new FootholdLine(Board, anchor)); } } } } }
//false = prev is in second point, true = prev is in first point private static bool GetVerticalFootholdDirection(FootholdLine fh, Hashtable fhListByPoint) { FootholdLine oldFh = null; FootholdLine currFh = fh; while (currFh.FirstDot.X == currFh.SecondDot.X) { oldFh = currFh; currFh = GetOtherFh(GetTopAnchor(currFh), currFh, fhListByPoint); if (currFh == null) { goto try_other_side; //no more connections, try from other side } } FootholdAnchor oldFhConnectAnchor = GetTopAnchor(oldFh); FootholdAnchor otherAnchor = oldFhConnectAnchor == currFh.FirstDot ? (FootholdAnchor)currFh.SecondDot : (FootholdAnchor)currFh.FirstDot; return(!((otherAnchor.X > oldFhConnectAnchor.X) ^ (fh.FirstDot.Y > fh.SecondDot.Y))); try_other_side: oldFh = null; currFh = fh; while (currFh.FirstDot.X == currFh.SecondDot.X) { oldFh = currFh; currFh = GetOtherFh(GetBottomAnchor(currFh), currFh, fhListByPoint); if (currFh == null) { return(false); //no more connections, return false (could be true too) because this foothold is 100% wall } } oldFhConnectAnchor = GetBottomAnchor(oldFh); otherAnchor = oldFhConnectAnchor == currFh.FirstDot ? (FootholdAnchor)currFh.SecondDot : (FootholdAnchor)currFh.FirstDot; return(!((otherAnchor.X > oldFhConnectAnchor.X) ^ (fh.FirstDot.Y < fh.SecondDot.Y))); }
private static FootholdAnchor GetBottomAnchor(FootholdLine fh) { return(fh.FirstDot.Y < fh.SecondDot.Y ? (FootholdAnchor)fh.SecondDot : (FootholdAnchor)fh.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 {
public void LoadFootholds(WzImage mapImage, Board mapBoard) { List <FootholdAnchor> anchors = new List <FootholdAnchor>(); WzSubProperty footholdParent = (WzSubProperty)mapImage["foothold"]; int layer; FootholdAnchor a; FootholdAnchor b; Dictionary <int, FootholdLine> fhs = new Dictionary <int, FootholdLine>(); foreach (WzSubProperty layerProp in footholdParent.WzProperties) { layer = int.Parse(layerProp.Name); Layer l = mapBoard.Layers[layer]; foreach (WzSubProperty platProp in layerProp.WzProperties) { int zM = int.Parse(platProp.Name); l.zMList.Add(zM); foreach (WzSubProperty fhProp in platProp.WzProperties) { a = new FootholdAnchor(mapBoard, InfoTool.GetInt(fhProp["x1"]), InfoTool.GetInt(fhProp["y1"]), layer, zM, false); b = new FootholdAnchor(mapBoard, InfoTool.GetInt(fhProp["x2"]), InfoTool.GetInt(fhProp["y2"]), layer, zM, false); int num = int.Parse(fhProp.Name); int next = InfoTool.GetInt(fhProp["next"]); int prev = InfoTool.GetInt(fhProp["prev"]); MapleBool cantThrough = InfoTool.GetOptionalBool(fhProp["cantThrough"]); MapleBool forbidFallDown = InfoTool.GetOptionalBool(fhProp["forbidFallDown"]); int? piece = InfoTool.GetOptionalInt(fhProp["piece"]); int? force = InfoTool.GetOptionalInt(fhProp["force"]); if (a.X != b.X || a.Y != b.Y) { FootholdLine fh = new FootholdLine(mapBoard, a, b, forbidFallDown, cantThrough, piece, force); fh.num = num; fh.prev = prev; fh.next = next; mapBoard.BoardItems.FootholdLines.Add(fh); fhs[num] = fh; anchors.Add(a); anchors.Add(b); } } } anchors.Sort(new Comparison <FootholdAnchor>(FootholdAnchor.FHAnchorSorter)); for (int i = 0; i < anchors.Count - 1; i++) { a = anchors[i]; b = anchors[i + 1]; if (a.X == b.X && a.Y == b.Y) { FootholdAnchor.MergeAnchors(a, b); // Transfer lines from b to a anchors.RemoveAt(i + 1); // Remove b i--; // Fix index after we removed b } } foreach (FootholdAnchor anchor in anchors) { if (anchor.connectedLines.Count > 2) { foreach (FootholdLine line in anchor.connectedLines) { if (IsAnchorPrevOfFoothold(anchor, line)) { if (fhs.ContainsKey(line.prev)) { line.prevOverride = fhs[line.prev]; } } else { if (fhs.ContainsKey(line.next)) { line.nextOverride = fhs[line.next]; } } } } mapBoard.BoardItems.FHAnchors.Add(anchor); } anchors.Clear(); } }
private bool TryGetSimpleFootholdOrientation(FootholdLine line, out FootholdOrientation result) { if (line.prevOverride != null && line.FirstDot.connectedLines.Contains(line.prevOverride)) { result = FootholdOrientation.PrevFirstNextSecond; return true; } else if (line.prevOverride != null && line.SecondDot.connectedLines.Contains(line.prevOverride)) { result = FootholdOrientation.NextFirstPrevSecond; return true; } else if (line.nextOverride != null && line.FirstDot.connectedLines.Contains(line.nextOverride)) { result = FootholdOrientation.NextFirstPrevSecond; return true; } else if (line.nextOverride != null && line.SecondDot.connectedLines.Contains(line.nextOverride)) { result = FootholdOrientation.PrevFirstNextSecond; return true; } else if (!line.IsWall) { result = GetNonverticalFootholdOrientation(line); return true; } else { // Result doesn't really matter here since we're returning false result = FootholdOrientation.PrevFirstNextSecond; return false; } }
private bool IsAnchorPrevOfFoothold(FootholdAnchor a, FootholdLine x) { int prevnum = x.prev; int nextnum = x.next; foreach (FootholdLine l in a.connectedLines) { if (l.num == prevnum) { return true; } else if (l.num == nextnum) { return false; } } throw new Exception("Could not match anchor to foothold"); }
public void LoadFootholds(WzImage mapImage, Board mapBoard) { List<FootholdAnchor> anchors = new List<FootholdAnchor>(); WzSubProperty footholdParent = (WzSubProperty)mapImage["foothold"]; int layer; FootholdAnchor a; FootholdAnchor b; Dictionary<int, FootholdLine> fhs = new Dictionary<int, FootholdLine>(); foreach (WzSubProperty layerProp in footholdParent.WzProperties) { layer = int.Parse(layerProp.Name); Layer l = mapBoard.Layers[layer]; foreach (WzSubProperty platProp in layerProp.WzProperties) { int zM = int.Parse(platProp.Name); l.zMList.Add(zM); foreach (WzSubProperty fhProp in platProp.WzProperties) { a = new FootholdAnchor(mapBoard, InfoTool.GetInt(fhProp["x1"]), InfoTool.GetInt(fhProp["y1"]), layer, zM, false); b = new FootholdAnchor(mapBoard, InfoTool.GetInt(fhProp["x2"]), InfoTool.GetInt(fhProp["y2"]), layer, zM, false); int num = int.Parse(fhProp.Name); int next = InfoTool.GetInt(fhProp["next"]); int prev = InfoTool.GetInt(fhProp["prev"]); MapleBool cantThrough = InfoTool.GetOptionalBool(fhProp["cantThrough"]); MapleBool forbidFallDown = InfoTool.GetOptionalBool(fhProp["forbidFallDown"]); int? piece = InfoTool.GetOptionalInt(fhProp["piece"]); int? force = InfoTool.GetOptionalInt(fhProp["force"]); if (a.X != b.X || a.Y != b.Y) { FootholdLine fh = new FootholdLine(mapBoard, a, b, forbidFallDown, cantThrough, piece, force); fh.num = num; fh.prev = prev; fh.next = next; mapBoard.BoardItems.FootholdLines.Add(fh); fhs[num] = fh; anchors.Add(a); anchors.Add(b); } } } anchors.Sort(new Comparison<FootholdAnchor>(FootholdAnchor.FHAnchorSorter)); for (int i = 0; i < anchors.Count - 1; i++) { a = anchors[i]; b = anchors[i + 1]; if (a.X == b.X && a.Y == b.Y) { FootholdAnchor.MergeAnchors(a, b); // Transfer lines from b to a anchors.RemoveAt(i + 1); // Remove b i--; // Fix index after we removed b } } foreach (FootholdAnchor anchor in anchors) { if (anchor.connectedLines.Count > 2) { foreach (FootholdLine line in anchor.connectedLines) { if (IsAnchorPrevOfFoothold(anchor, line)) { if (fhs.ContainsKey(line.prev)) { line.prevOverride = fhs[line.prev]; } } else { if (fhs.ContainsKey(line.next)) { line.nextOverride = fhs[line.next]; } } } } mapBoard.BoardItems.FHAnchors.Add(anchor); } anchors.Clear(); } }
private void multiBoard_OnEditInstanceClicked(BoardItem item) { InputHandler.ClearBoundItems(multiBoard.SelectedBoard); switch (item.GetType().Name) { case "ObjectInstance": new InstanceEditor.ObjectInstanceEditor((ObjectInstance)item).ShowDialog(); multiBoard.RenderFrame(); break; case "TileInstance": case "Chair": new InstanceEditor.GeneralInstanceEditor(item).ShowDialog(); multiBoard.RenderFrame(); break; case "FootholdAnchor": FootholdLine[] selectedFootholds = FootholdLine.GetSelectedFootholds(item.Board); if (selectedFootholds.Length > 0) { new InstanceEditor.FootholdEditor(selectedFootholds).ShowDialog(); } else { new InstanceEditor.GeneralInstanceEditor(item).ShowDialog(); } multiBoard.RenderFrame(); break; case "RopeAnchor": new InstanceEditor.RopeInstanceEditor((RopeAnchor)item).ShowDialog(); multiBoard.RenderFrame(); break; case "LifeInstance": new InstanceEditor.LifeInstanceEditor((LifeInstance)item).ShowDialog(); multiBoard.RenderFrame(); break; case "ReactorInstance": new InstanceEditor.ReactorInstanceEditor((ReactorInstance)item).ShowDialog(); multiBoard.RenderFrame(); break; case "BackgroundInstance": multiBoard.RenderFrame(); break; case "PortalInstance": new InstanceEditor.PortalInstanceEditor((PortalInstance)item).ShowDialog(); multiBoard.RenderFrame(); break; case "ToolTip": break; default: break; } }
private FootholdOrientation GetFootholdOrientation(FootholdLine line) { FootholdOrientation result; if (TryGetSimpleFootholdOrientation(line, out result)) { return result; } else { // Vertical foothold, search for near nonvertical foothold as orientation reference // Obtain vertical orientation of the foothold FootholdAnchor top, bottom; if (line.FirstDot.Y < line.SecondDot.Y) { top = (FootholdAnchor)line.FirstDot; bottom = (FootholdAnchor)line.SecondDot; } else if (line.FirstDot.Y > line.SecondDot.Y) { bottom = (FootholdAnchor)line.FirstDot; top = (FootholdAnchor)line.SecondDot; } else { throw new Exception("Zero length foothold in saving"); } // For starters, we search the footholds linking downards from us. // This is because we are looking for the conventional foothold U scheme: // // | | // | | // |_ _ _| // // or the Z/S schemes: //_ _ _ _ _ _ // | | // | | // |_ _ _ or _ _ _| FootholdEnumerator referenceEnumerator = new FootholdEnumerator(line, top); foreach (FootholdLine reference in referenceEnumerator) { if (!reference.IsWall) { // We found a suiting foothold reference, find what is our orientation return GetVerticalFootholdOrientationByReference(line, top, reference, referenceEnumerator.CurrentAnchor); } } // If downard-search failed, search upwards, to resolve the n scheme: // _ _ _ // | | // | | // | | // // Note that the order of searches is important; we MUST search downwards before upwards, to resolve schemes such as the tower scheme: // // | | // | | // |_ _ _ _| // | | // | | // |_ _ _ _ _ _| // // If we searched upwards-first, the footholds between the two tower "floors" would be treated as n scheme footholds, while they should be U schemed. referenceEnumerator = new FootholdEnumerator(line, bottom); foreach (FootholdLine reference in referenceEnumerator) { if (!reference.IsWall) { // We found a suiting foothold reference, find what is our orientation return GetVerticalFootholdOrientationByReference(line, bottom, reference, referenceEnumerator.CurrentAnchor); } } // If all else failed, we are dealing with a pure-wall foothold platform (i.e. a foothold graph consisting only of vertical footholds) // In this case, we arbitrarily select the Normal orientation, since there's no more actual logic we can perform to know what is the correct orientation. return FootholdOrientation.PrevFirstNextSecond; } }
public static Hashtable ConvertToMapleFootholds2(List <FootholdLine> footholds, List <FootholdAnchor> anchors) { Hashtable fhListByPoint = new Hashtable(); foreach (FootholdAnchor anchor in anchors) { Point anchorPos = new Point(anchor.X, anchor.Y); List <FootholdLine> fhList = (List <FootholdLine>)fhListByPoint[anchorPos]; if (fhList == null) { fhList = new List <FootholdLine>(2); fhListByPoint.Add(anchorPos, fhList); } fhList.AddRange(anchor.connectedLines.Cast <FootholdLine>()); } Hashtable fhByNum = new Hashtable(); for (int i = 1; i <= footholds.Count; i++) { FootholdLine fhClass = footholds[i - 1]; if (fhClass.FirstDot.X == fhClass.SecondDot.X && fhClass.FirstDot.Y == fhClass.SecondDot.Y) { continue; } fhClass.num = i; Foothold mapleFh = new Foothold(); mapleFh.num = i; mapleFh.layer = ((FootholdAnchor)fhClass.FirstDot).LayerNumber; fhByNum[i] = mapleFh; } for (int i = 1; i <= footholds.Count; i++) { FootholdLine fhClass = footholds[i - 1]; Foothold mapleFh = (Foothold)fhByNum[i]; FootholdLine firstOtherFh = GetOtherFh((FootholdAnchor)fhClass.FirstDot, fhClass, fhListByPoint); FootholdLine secondOtherFh = GetOtherFh((FootholdAnchor)fhClass.SecondDot, fhClass, fhListByPoint); if (fhClass.FirstDot.X < fhClass.SecondDot.X) { mapleFh.x1 = fhClass.FirstDot.X; mapleFh.x2 = fhClass.SecondDot.X; mapleFh.y1 = fhClass.FirstDot.Y; mapleFh.y2 = fhClass.SecondDot.Y; mapleFh.prev = firstOtherFh == null ? 0 : firstOtherFh.num; mapleFh.next = secondOtherFh == null ? 0 : secondOtherFh.num; } else if (fhClass.FirstDot.X > fhClass.SecondDot.X) { mapleFh.x1 = fhClass.SecondDot.X; mapleFh.x2 = fhClass.FirstDot.X; mapleFh.y1 = fhClass.SecondDot.Y; mapleFh.y2 = fhClass.FirstDot.Y; mapleFh.prev = secondOtherFh == null ? 0 : secondOtherFh.num; mapleFh.next = firstOtherFh == null ? 0 : firstOtherFh.num; } else { bool fhDir = GetVerticalFootholdDirection(fhClass, fhListByPoint); if (fhDir) //prev = firstdot { mapleFh.x1 = fhClass.FirstDot.X; mapleFh.x2 = fhClass.SecondDot.X; mapleFh.y1 = fhClass.FirstDot.Y; mapleFh.y2 = fhClass.SecondDot.Y; mapleFh.prev = firstOtherFh == null ? 0 : firstOtherFh.num; mapleFh.next = secondOtherFh == null ? 0 : secondOtherFh.num; } else //prev = seconddot { mapleFh.x1 = fhClass.SecondDot.X; mapleFh.x2 = fhClass.FirstDot.X; mapleFh.y1 = fhClass.SecondDot.Y; mapleFh.y2 = fhClass.FirstDot.Y; mapleFh.prev = secondOtherFh == null ? 0 : secondOtherFh.num; mapleFh.next = firstOtherFh == null ? 0 : firstOtherFh.num; } } fhByNum[i] = mapleFh; } return(fhByNum); }
private static void LoadFootholds(WzImage mapImage, Board mapBoard) { List <FootholdAnchor> anchors = new List <FootholdAnchor>(); WzSubProperty footholdParent = (WzSubProperty)mapImage["foothold"]; int layer; 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) { foreach (WzSubProperty fhProp in platProp.WzProperties) { a = new FootholdAnchor(mapBoard, InfoTool.GetInt(fhProp["x1"]), InfoTool.GetInt(fhProp["y1"]), layer, false); b = new FootholdAnchor(mapBoard, InfoTool.GetInt(fhProp["x2"]), InfoTool.GetInt(fhProp["y2"]), layer, false); 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; 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 FootholdOrientation GetVerticalFootholdOrientationByReference(FootholdLine line, FootholdAnchor anchor, FootholdLine reference, FootholdAnchor referenceAnchor) { FootholdOrientation referenceOrientation = GetNonverticalFootholdOrientation(reference); bool leadingAnchorIsFirst = referenceAnchor == reference.FirstDot; bool firstIsPrev = referenceOrientation == FootholdOrientation.PrevFirstNextSecond; bool startAnchorIsFirst = anchor == line.FirstDot; // LAIF | FIP | RESULT (leadingAnchorIsPrev "LAIP") // 1 | 1 | 1 // 1 | 0 | 0 // 0 | 1 | 0 // 0 | 0 | 1 // LAIP | SAIF | RESULT (Orientation: 0 normal, 1 inverted) // 1 | 1 | 0 // 1 | 0 | 1 // 0 | 1 | 1 // 0 | 0 | 0 return !(leadingAnchorIsFirst ^ firstIsPrev) ^ startAnchorIsFirst ? FootholdOrientation.NextFirstPrevSecond : FootholdOrientation.PrevFirstNextSecond; }
private FootholdOrientation GetNonverticalFootholdOrientation(FootholdLine line) { if (line.FirstDot.X < line.SecondDot.X) { // Normal foothold orientation return FootholdOrientation.PrevFirstNextSecond; } else // (line.FirstDot.X > line.SecondDot.X) { // Inverted foothold orientation return FootholdOrientation.NextFirstPrevSecond; } }
private int GetFootholdPrevNext(FootholdLine line, FootholdOrientation orientation, FootholdDirection dir) { FootholdLine overrideLine = dir == FootholdDirection.Prev ? line.prevOverride : line.nextOverride; if (overrideLine != null && (line.FirstDot.connectedLines.Contains(overrideLine) || line.SecondDot.connectedLines.Contains(overrideLine))) { return overrideLine.num; } else { FootholdAnchor anchor = (FootholdAnchor)((orientation == FootholdOrientation.PrevFirstNextSecond) ^ (dir == FootholdDirection.Next) ? line.FirstDot : line.SecondDot); if (anchor.connectedLines.Count < 2) { return 0; } else { return anchor.GetOtherLine(line).num; } } }