/// <summary>Creates a new instance of NodeDestDistInt.</summary> /// <param name="node">The source Node.</param> /// <param name="dest">The destination of the new node.</param> /// <param name="dist">The distance from the source node to the nearest intersection.</param> /// <param name="intersections">The number of intersections.</param> public NodeDestDistInt(Node node, VectorF dest, FInt dist, int intersections) { this.Node = node; this.Dest = dest; this.Dist = dist; this.Intersections = intersections; }
/// <summary>Clones the provided node. All references to other nodes or segments are deep.</summary> /// <param name="toClone">The node to clone.</param> public Node(Node toClone) : this(toClone.InWorld) { this.IsParent = toClone.IsParent; this.Radius = toClone.Radius; this.Spacing = toClone.Spacing; this.GenSpacing = toClone.GenSpacing; this.SightDistance = toClone.SightDistance; this.ID = toClone.ID; this.NType = toClone.NType; this.Pos = toClone.Pos; this.owner = toClone.Owner; this.Parents = new List<Node>(toClone.Parents); this.ParentFromSeg = new List<int>(toClone.ParentFromSeg); this.Segments = (Segment[])toClone.Segments.Clone(); this.NumSegments = toClone.NumSegments; this.SegNumPeople = (int[])toClone.SegNumPeople.Clone(); this.SegCapacity = (FInt[])toClone.SegCapacity.Clone(); this.PeopleToSort = toClone.PeopleToSort; this.GenCountDown = toClone.GenCountDown; this.Destroyed = toClone.Destroyed; this.Active = toClone.Active; this.OwnsHotspot = toClone.OwnsHotspot; }
private static string translateValue(string val, string context, World map, Node node, Segment segment) { string result = null; switch (context) { case "[World]": switch (val) { case "WindowWidth": result = Graphics.PreferredBackBufferWidth.ToString(); break; case "WindowHeight": result = Graphics.PreferredBackBufferHeight.ToString(); break; default: result = val; break; } break; case "[Camera]": switch (val) { case "CenterX": result = ((double)(map.Width / FInt.F2)).ToString(); break; case "CenterY": result = ((double)(map.Height / FInt.F2)).ToString(); break; case "WindowWidth": result = Graphics.PreferredBackBufferWidth.ToString(); break; case "WindowHeight": result = Graphics.PreferredBackBufferHeight.ToString(); break; default: result = val; break; } break; case "[Grid]": case "[FogOfWar]": case "[Geo]": case "[Player]": case "[NodeType]": case "[PathFinder]": case "[Hotspot]": result = val; break; case "[Node]": switch (val) { case "GenSpacing": result = node.GenSpacing.DblValue.ToString(); break; case "GenCountDown": result = node.GenCountDown.DblValue.ToString(); break; default: result = val; break; } break; case "[Segment]": switch (val) { case "Length": result = segment.Length.DblValue.ToString(); break; default: result = val; break; } break; default: throw new Exception("Unrecognized context: " + context); } return result; }
/// <summary>Removes the selected node from the world.</summary> private void removeSelNode() { // disconnect segments foreach (Segment seg in world.Segments) { for (int i = 0; i < 2; i++) { if (seg.Nodes[i] == selectedNode) { int oppLane = 1 - i; if (seg.State[oppLane] == SegmentSkel.SegState.Complete) seg.State[oppLane] = SegmentSkel.SegState.Retracting; break; } } } world.removeNode(selectedNode); selectedNode = null; loadObjectEditor(); }
/// <summary>Loads the currently selected file in lsbLoadSaveFile into the editor.</summary> private void loadSelectedFile() { StringBuilder path = new StringBuilder(); foreach (ButtonText b in btnSaveLoadPath) { path.Append(b.Text); path.Append('\\'); } path.Append(lsbSaveLoadFiles.SelectedItem); hoveredNode = null; selectedNode = null; hoveredSeg = null; selectedSeg = null; hoveredSegEnd = null; hoveredSegEndOwner = null; selectedSegEnd = null; hoveredGeo = null; selectedGeo = null; world = WorldLoader.loadWorld(path.ToString(), Graphics); refreshSideBar(); }
/// <summary>Adds the specified node to the world.</summary> /// <param name="node">The node to add.</param> public void addNode(Node node) { if (node.ID == null) node.ID = getNextNodeID(); NodeByID.Add(node.ID, node); Nodes.Add(node); Grid.Point(node.Pos, node, gridAddNode); node.Visible = node.Owner != null && (node.Owner.Type == Player.PlayerType.Human || (node.Active && HumanPlayer.Fog.isVisible(node))); if (!EditorMode) addEvent(node.ID, WorldEvent.EventType.AddNode); }
/// <summary>Removes the specified node from the world.</summary> /// <param name="node">The node to remove.</param> public void removeNode(Node node) { removeNode(Nodes.IndexOf(node)); }
/// <summary>Applies the visibility for a node.</summary> /// <param name="node">The node to apply.</param> public void applyVisibility(Node node) { if (!node.Active || node.Owner != Owner) return; int leftCol = Math.Max(0, (int)((node.X - node.SightDistance) / SqrWidth)); int topRow = Math.Max(0, (int)((node.Y - node.SightDistance) / SqrHeight)); int rightCol = Math.Min(NumCols - 1, (int)Calc.RoundUp((node.X + node.SightDistance) / SqrWidth)); int bottomRow = Math.Min(NumRows - 1, (int)Calc.RoundUp((node.Y + node.SightDistance) / SqrHeight)); for (int col = leftCol; col <= rightCol; col++) { for (int row = topRow; row <= bottomRow; row++) { // don't do the math again if it's already visible if (Grid[row, col] == VisOption.Visible) continue; // find closest point in the square VectorF testPoint = VectorF.Zero; VectorF topLeft = new VectorF(SqrWidth * (FInt)col, SqrHeight * (FInt)row); VectorF bottomRight = topLeft + SqrSize; if (topLeft.X >= node.X) testPoint.X = topLeft.X; else if (bottomRight.X <= node.X) testPoint.X = bottomRight.X; else testPoint.X = node.X; if (topLeft.Y >= node.Y) testPoint.Y = topLeft.Y; else if (bottomRight.Y <= node.Y) testPoint.Y = bottomRight.Y; else testPoint.Y = node.Y; // test the point if (VectorF.Distance(testPoint, node.Pos) <= node.SightDistance) Grid[row, col] = VisOption.Visible; } } }
/// <summary>Updates all game variables in this mode.</summary> /// <param name="gameTime">The current game time.</param> public override void Update(GameTime gameTime) { base.Update(gameTime); FInt elapsed = (FInt)gameTime.ElapsedGameTime.TotalSeconds; hoveredNode = null; hoveredSeg = null; hoveredHotspot = null; Player hPlayer = null; Player cPlayer = null; foreach (Player p in map.Players) { if (p.Type == Player.PlayerType.Human) { hPlayer = p; break; } } foreach (Player p in map.Players) { if (p.Type == Player.PlayerType.Computer) { cPlayer = p; break; } } // prepare grid manager map.Grid.startNewUpdate(gameTime); // move camera if (Inp.Key.IsKeyDown(Keys.OemPlus)) map.Cam.Zoom += map.Cam.Zoom * elapsed; if (Inp.Key.IsKeyDown(Keys.OemMinus)) map.Cam.Zoom -= map.Cam.Zoom * elapsed; if (Inp.Key.IsKeyDown(Keys.A)) map.Cam.CenterX -= (700 / map.Cam.Zoom) * elapsed; if (Inp.Key.IsKeyDown(Keys.D)) map.Cam.CenterX += (700 / map.Cam.Zoom) * elapsed; if (Inp.Key.IsKeyDown(Keys.W)) map.Cam.CenterY -= (700 / map.Cam.Zoom) * elapsed; if (Inp.Key.IsKeyDown(Keys.S)) map.Cam.CenterY += (700 / map.Cam.Zoom) * elapsed; map.Cam.Zoom += (FInt)(Inp.Mse.ScrollWheelValue - Inp.OldMse.ScrollWheelValue) / (FInt)120 * (FInt).1d * map.Cam.Zoom; map.Cam.refreshCorners(); // get cursor world coordinates VectorF cursorPos = map.Cam.screenToWorld(new Vector2((float)Inp.Mse.X, (float)Inp.Mse.Y)); /*/ find path if (!tempBool) { Node fromNode = cPlayer.Nodes[cPlayer.Nodes.Count - 1]; VectorF fromPos = fromNode.Pos; // find path VectorF nde = fromPos / cPlayer.Path.NodeSpacing; nde.X = (FInt)Math.Round((double)nde.X); nde.Y = (FInt)Math.Round((double)nde.Y); int srcNode = (int)nde.Y * cPlayer.Path.NumCols + (int)nde.X; nde = (hPlayer.Nodes[0].Pos + hPlayer.Nodes[1].Pos) / FInt.F2 / cPlayer.Path.NodeSpacing; nde.X = (FInt)Math.Round((double)nde.X); nde.Y = (FInt)Math.Round((double)nde.Y); int destNode = (int)nde.Y * cPlayer.Path.NumCols + (int)nde.X; shortest = cPlayer.Path.search(cPlayer.Path.Nodes[srcNode], cPlayer.Path.Nodes[destNode]); tempBool = true; }*/ if (Inp.OldMse.Position != Inp.Mse.Position) desktop.mouseMove(Inp.Mse.Position); GUI.Desktop.Event evnt = Desktop.Event.MouseRightUp; bool evntHappened = true; if (Inp.OldMse.LeftButton == ButtonState.Pressed && Inp.Mse.LeftButton == ButtonState.Released) evnt = Desktop.Event.MouseLeftUp; else if (Inp.OldMse.LeftButton == ButtonState.Released && Inp.Mse.LeftButton == ButtonState.Pressed) evnt = Desktop.Event.MouseLeftDown; else if (Inp.OldMse.RightButton == ButtonState.Pressed && Inp.Mse.RightButton == ButtonState.Released) evnt = Desktop.Event.MouseRightUp; else if (Inp.OldMse.RightButton == ButtonState.Released && Inp.Mse.RightButton == ButtonState.Pressed) evnt = Desktop.Event.MouseRightUp; else evntHappened = false; if (selectedNode != null) hoveredHotspot = map.HotspotAtPoint(cursorPos); if (selectedNode == null && evntHappened && desktop.PerformMouseEvent(evnt, Inp.Mse.Position, Inp)) { hoveredNode = null; } else { // check for hovered node and segment hoveredNode = map.NodeAtPoint(cursorPos, true); hoveredSeg = (hoveredNode == null) ? map.segmentAtPoint(cursorPos, hPlayer) : null; // if node is selected, determine which node type may be built at the selected distance selNodeType = (selectedNode == null) ? null : map.getNodeType(selectedNode.Pos, cursorPos); // if the user just released the left mouse button if (Inp.OldMse.LeftButton == ButtonState.Pressed && Inp.Mse.LeftButton == ButtonState.Released) { if (selectedNode != null) { if (hoveredNode == null) { if (hoveredHotspot != null) map.PlayerActions.Add(new PlayerAction(hPlayer, PlayerAction.ActionType.BuildSeg, selectedNode.ID, true, hoveredHotspot.ID)); else if (selNodeType != null) map.PlayerActions.Add(new PlayerAction(hPlayer, PlayerAction.ActionType.BuildSeg, selectedNode.ID, false, cursorPos)); } else if (hoveredNode != selectedNode) { map.PlayerActions.Add(new PlayerAction(hPlayer, PlayerAction.ActionType.ClaimNode, selectedNode.ID, hoveredNode.ID)); } selectedNode = null; } } // user just pressed the left mouse button else if ((Inp.OldMse.LeftButton == ButtonState.Released && Inp.Mse.LeftButton == ButtonState.Pressed) || (Inp.OldMse.RightButton == ButtonState.Released && Inp.Mse.RightButton == ButtonState.Pressed)) { if (hoveredNode != null && hoveredNode.Owner == hPlayer && (Inp.Mse.RightButton == ButtonState.Pressed || hoveredNode.NumSegments < hoveredNode.Segments.Length)) selectedNode = hoveredNode; } // if the left mouse button is still pressed else if (Inp.OldMse.LeftButton == ButtonState.Pressed && Inp.Mse.LeftButton == ButtonState.Pressed) { if (selectedNode != null && cursorPos.Y >= FInt.F0 && cursorPos.X >= FInt.F0 && cursorPos.X < map.Width && cursorPos.Y < map.Height) { List<SegmentSkel> ignoreSeg = new List<SegmentSkel>(selectedNode.Segments.Length); foreach (Segment seg in selectedNode.Segments) { if (seg != null) ignoreSeg.Add(seg); } List<NodeSkel> ignoreNode = new List<NodeSkel>(1) { selectedNode }; SegmentSkel segColl; NodeSkel nodeColl; GeoSkel geoColl; map.Collision.segCollisionIntPoint(selectedNode.Pos, cursorPos, ignoreSeg, ignoreNode, out segColl, out nodeColl, out geoColl, out intersectPoint); } } // if the player just released the right mouse button else if (Inp.OldMse.RightButton == ButtonState.Pressed && Inp.Mse.RightButton == ButtonState.Released) { if (selectedNode != null && hoveredNode == selectedNode) { map.PlayerActions.Add(new PlayerAction(hPlayer, PlayerAction.ActionType.DestroyNode, selectedNode.ID)); } else if (hoveredSeg != null) { map.PlayerActions.Add(new PlayerAction(hPlayer, PlayerAction.ActionType.SplitSeg, hoveredSeg.ID, cursorPos)); hoveredSeg = null; } selectedNode = null; } // if the player just pressed the spacebar else if (!Inp.OldKey.IsKeyDown(Keys.Space) && Inp.Key.IsKeyDown(Keys.Space)) { paused = !paused; } } // update world if (!paused && !cntMsgBox.Visible) map.update(gameTime); // execute action queue if (map.FrontEndActions.Count > 0 && !cntMsgBox.Visible) { FrontEndAction action = map.FrontEndActions.Dequeue(); switch (action.Action) { case FrontEndAction.ActionType.LoadMap: loadWorld((string)action.Params[0]); break; case FrontEndAction.ActionType.Message: showMsg((string)action.Params[0]); break; } } }
/// <summary>Loads the specified world.</summary> /// <param name="path">The path of the world to load.</param> public void loadWorld(string path) { hoveredNode = null; selectedNode = null; hoveredSeg = null; map = WorldLoader.loadWorld(path.ToString(), Graphics); }
/// <summary>Creates a new instance of PlayMode.</summary> /// <param name="graphics">The graphics device manager to use.</param> /// <param name="content">The content manager to use.</param> /// <param name="batch">The sprite batch to use.</param> /// <param name="bEffect">The basic effect to use.</param> public PlayMode(GraphicsDeviceManager graphics, ContentManager content, SpriteBatch batch, BasicEffect bEffect) : base(graphics, content, batch, bEffect) { hoveredNode = null; hoveredSeg = null; hoveredHotspot = null; selectedNode = null; desktop = new Desktop(); lblCursorPos = new Label(); lblCursorPos.Left = 0; lblCursorPos.Top = 0; lblCursorPos.Width = 0; lblCursorPos.Height = 0; lblCursorPos.ForeColor = Color.White; desktop.Controls.Add(lblCursorPos); /* TEMPORARY */ loadWorld(@"..\..\..\testscripting.txt");//testLevel.txt"); //map = WorldLoader.loadWorld(@"..\..\..\testLevel.txt", Graphics); /* TEMPORARY */ }
private static void readSegmentVars2(List<string[]> commands, World map, Segment segment, Dictionary<string, Node> nodes) { int tempInt = 0; double tempDbl = 0d; for (int j = 1; j < commands.Count; j++) { string value = translateValue(commands[j][2], "[Segment]", map, segment); bool valueValid = true; switch (commands[j][0]) { case "ID": // do nothing break; case "Node": valueValid = int.TryParse(commands[j][1], out tempInt); segment.Nodes[tempInt] = nodes[value]; break; case "End": valueValid = int.TryParse(commands[j][1], out tempInt); Node newNode = new Node(map); string[] coords = value.Split(','); if (valueValid && coords.Length == 2 && double.TryParse(coords[0], out tempDbl)) { newNode.X = (FInt)tempDbl; if (double.TryParse(coords[1], out tempDbl)) newNode.Y = (FInt)tempDbl; else valueValid = false; } else valueValid = false; if (valueValid) segment.Nodes[tempInt] = newNode; break; case "EndLength": case "Owner": case "State": case "Person": // do nothing break; default: throw new Exception("Segment variable not recognized: " + commands[j][0]); } if (!valueValid) throw new Exception("Value '" + commands[j][2] + "' not valid for variable '" + commands[j][0] + "'."); } segment.refreshMath(); }
private static void readNodeVars3(List<string[]> commands, World map, Node node, Dictionary<string, Segment> segments, List<Node> nodeNoID) { int tempInt = 0; for (int j = 1; j < commands.Count; j++) { string value = translateValue(commands[j][2], "[Node]", map, node); bool valueValid = true; switch (commands[j][0]) { case "ID": case "SegCap": // do nothing break; case "Seg": valueValid = int.TryParse(commands[j][1], out tempInt); node.Segments[tempInt] = segments[value]; break; case "IsParent": case "GenSpacing": case "GenCountDown": case "X": case "Y": case "Owner": case "Radius": case "SightDistance": case "Active": case "Spacing": case "Type": case "OwnsHotspot": // do nothing break; default: throw new Exception("Node variable not recognized: " + commands[j][0]); } if (!valueValid) throw new Exception("Value '" + commands[j][2] + "' not valid for variable '" + commands[j][0] + "'."); } node.updateNumSegments(); if (node.ID != null) map.addNode(node); else nodeNoID.Add(node); }
private static void readNodeVars2(List<string[]> commands, World map, Node node, Dictionary<string, Node> nodes, Dictionary<string, Player> players) { double tempDbl = 0d; int tempInt = 0; for (int j = 1; j < commands.Count; j++) { string value = translateValue(commands[j][2], "[Node]", map, node); bool valueValid = true; switch (commands[j][0]) { case "ID": // do nothing break; case "SegCap": valueValid = int.TryParse(value, out tempInt); node.initSegArrays(tempInt); break; case "Seg": // do nothing until next step break; case "IsParent": valueValid = value == "true" || value == "false"; node.IsParent = value == "true"; break; case "GenSpacing": valueValid = double.TryParse(value, out tempDbl); node.GenSpacing = (FInt)tempDbl; break; case "GenCountDown": valueValid = double.TryParse(value, out tempDbl); node.GenCountDown = (FInt)tempDbl; break; case "X": case "Y": case "Owner": // do nothing break; case "Radius": valueValid = double.TryParse(value, out tempDbl); node.Radius = (FInt)tempDbl; break; case "SightDistance": valueValid = double.TryParse(value, out tempDbl); node.SightDistance = (FInt)tempDbl; break; case "Active": // do nothing break; case "Spacing": valueValid = double.TryParse(value, out tempDbl); node.Spacing = (FInt)tempDbl; break; case "Type": case "OwnsHotspot": // do nothing break; default: throw new Exception("Node variable not recognized: " + commands[j][0]); } if (!valueValid) throw new Exception("Value '" + commands[j][2] + "' not valid for variable '" + commands[j][0] + "'."); } }
private static void readNodeVars1(List<string[]> commands, World map, List<Node> nodeList, Dictionary<string, Node> nodes, Dictionary<string, Player> players, Dictionary<string, NodeType> nodeTypes, Dictionary<string, Hotspot> hotspots) { double tempDouble = 0d; Node node = new Node(map); for (int j = 1; j < commands.Count; j++) { string value = translateValue(commands[j][2], "[Node]", map, node); bool valueValid = true; switch (commands[j][0]) { case "ID": node.ID = value; nodes.Add(value, node); break; case "SegCap": case "Seg": case "IsParent": case "GenSpacing": case "GenCountDown": // do nothing until next step break; case "X": valueValid = double.TryParse(value, out tempDouble); node.X = (FInt)tempDouble; break; case "Y": valueValid = double.TryParse(value, out tempDouble); node.Y = (FInt)tempDouble; break; case "Owner": node.Owner = players[value]; break; case "Radius": case "SightDistance": // do nothing until next step break; case "Active": valueValid = value == "true" || value == "false"; node.Active = value == "true"; break; case "Spacing": // do nothing until next step break; case "Type": node.setNodeType(nodeTypes[value]); break; case "OwnsHotspot": node.OwnsHotspot = hotspots[value]; break; default: throw new Exception("Node variable not recognized: " + commands[j][0]); } if (!valueValid) throw new Exception("Value '" + commands[j][2] + "' not valid for variable '" + commands[j][0] + "'."); } nodeList.Add(node); }
/// <summary>Gets the index of the provided node within the segment.</summary> /// <param name="node">The node to search for.</param> /// <returns>The index of the provided node within the segment.</returns> public int getNodeIndex(Node node) { if (Nodes[0] == node) return 0; #if DEBUG else if (Nodes[1] == node) return 1; else throw new Exception("Provided node is not connected to this segment."); #else return 1; #endif }
/// <summary>Gets the node opposite the one provided.</summary> /// <param name="node">The node to search for.</param> /// <returns>The node opposite the one provided.</returns> public Node getOppNode(Node node) { if (Nodes[0] == node) return Nodes[1]; #if DEBUG else if (Nodes[1] == node) return Nodes[0]; else throw new Exception("Provided node is not connected to this segment."); #else return Nodes[0]; #endif }
/// <summary>Attempt to claim this node for the specified segment.</summary> /// <param name="segment">The segment attempting to claim the node.</param> /// <returns>Whether or not the claim was successful.</returns> public bool claim(Segment segment) { bool claimed = false; int relSegIndex = -1; int lane = segment.getNodeIndex(this); int oppLane = 1 - lane; Node oppNode = segment.Nodes[oppLane]; // Determine whether or not the claim is successful if (Destroyed || Owner != segment.Owner) { // can't claim destroyed nodes or nodes owned by someone else } else if (!Active) // if the node is inactive... { if (InWorld.Collision.nodeCollision(Pos, Radius, new List<SegmentSkel>(1) { segment }, new List<NodeSkel>(1) { this }) || InWorld.Collision.nodeCollNodeSpacing(Pos, Radius, Spacing, Owner, new List<NodeSkel>(1) { this }, false)) destroy(); else claimed = true; } else if ((relSegIndex = relatedSeg(oppNode)) != -1) // if the node is related { claimed = true; // make sure the connection is more than one segment away foreach (Segment seg in Segments) { if (seg != null && seg.getOppNode(this) == oppNode) { claimed = false; break; } } if (claimed) severSegment(relSegIndex); } else if (NumSegments < Segments.Length) // if same owner, but unrelated { claimed = true; } if (!claimed) { segment.State[oppLane] = Segment.SegState.Retracting; } else { // complete the segment segment.State[oppLane] = Segment.SegState.Complete; // prepare to invalidate visibility for old owner // and apply new visibility to new owner Player invalOwner = (Active && Owner != segment.Owner && Owner.Type == Player.PlayerType.Human) ? Owner : null; bool applyVisibility = (!Active || Owner != segment.Owner) && segment.Owner.Type == Player.PlayerType.Human; Active = true; addSegment(segment, true); Owner = segment.Owner; // exchange parentage and density if (segment.State[lane] == Segment.SegState.Complete) { // exchange density int peopleToSend = 0; FInt capacityToSend = FInt.F0; for (int i = 0; i < Segments.Length; i++) { if (Segments[i] != null) { peopleToSend += SegNumPeople[i]; capacityToSend += SegCapacity[i]; } } int peopleToReceive = oppNode.PeopleToSort; FInt capacityToReceive = FInt.F0; for (int i = 0; i < oppNode.Segments.Length; i++) { if (oppNode.Segments[i] != null) { peopleToReceive += oppNode.SegNumPeople[i]; capacityToReceive += oppNode.SegCapacity[i]; } } alterDensity(peopleToReceive, capacityToReceive, segment); oppNode.alterDensity(peopleToSend, capacityToSend, segment); // exchange parentage Node[] parentsToSend = null; if (Parents.Count > 0 || IsParent) { parentsToSend = new Node[Parents.Count + (IsParent ? 1 : 0)]; Parents.CopyTo(parentsToSend); if (IsParent) parentsToSend[parentsToSend.Length - 1] = this; } if (oppNode.Parents.Count > 0 || oppNode.IsParent) { if (!oppNode.IsParent) { addParents(segment, oppNode.Parents); } else { List<Node> parentsToReceive = new List<Node>(oppNode.Parents.Count + 1); parentsToReceive.AddRange(oppNode.Parents); parentsToReceive.Add(oppNode); addParents(segment, parentsToReceive); } } if (parentsToSend != null) oppNode.addParents(segment, parentsToSend); } else // get segment's density { int peopleToReceive = segment.NumPeople; FInt capacityToReceive = (segment.State[lane] != Segment.SegState.Retracting) ? segment.Capacity : FInt.F0; alterDensity(peopleToReceive, capacityToReceive, segment); } // update visibility if (invalOwner != null) { invalOwner.Fog.invalidate(new VectorF(X - SightDistance, Y - SightDistance), new VectorF(X + SightDistance, Y + SightDistance)); InWorld.refreshVisibility(new VectorF(X - SightDistance, Y - SightDistance), new VectorF(X + Radius, Y + Radius)); } if (applyVisibility) { Owner.Fog.applyVisibility(this); InWorld.refreshVisibility(new VectorF(X - SightDistance, Y - SightDistance), new VectorF(X + SightDistance, Y + SightDistance)); } Visible = Owner.Type == Player.PlayerType.Human || (Active && InWorld.HumanPlayer.Fog.isVisible(this)); // add event InWorld.addEvent(ID, WorldEvent.EventType.NodeChangeState); // run script if on hotspot if (OwnsHotspot != null && !string.IsNullOrWhiteSpace(OwnsHotspot.Script)) InWorld.Script.runScript(OwnsHotspot.Script); } // add event if (!Destroyed) InWorld.addEvent(segment.ID, WorldEvent.EventType.SegChangeState); return claimed; }
/// <summary>Gets a skeleton version of this grid manager.</summary> /// <param name="forPlayer">The player that will use it. His nodes and segments are full instead of skeletons.</param> /// <param name="playerNodes">A list of all of the player's nodes.</param> /// <param name="playerSegs">A list of all of the player's segments.</param> /// <param name="allSegs">A list of all segments.</param> /// <param name="allNodes">A list of all nodes.</param> /// <returns>A skeleton version of this grid manager.</returns> public GridManager getSkeleton(Player forPlayer, out Node[] playerNodes, out Segment[] playerSegs, out NodeSkel[] allNodes, out SegmentSkel[] allSegs) { playerNodes = new Node[forPlayer.Nodes.Count]; playerSegs = new Segment[forPlayer.Segments.Count]; allNodes = new NodeSkel[InWorld.Nodes.Count]; allSegs = new SegmentSkel[InWorld.Segments.Count]; int nextPlyrNode = 0; int nextPlyrSeg = 0; int nextAllNode = 0; int nextAllSeg = 0; GridManager skeleton = new GridManager(NumCols, NumRows, InWorld, false); Dictionary<string, NodeSkel> nodes = new Dictionary<string, NodeSkel>(InWorld.Nodes.Count); Dictionary<string, SegmentSkel> segments = new Dictionary<string, SegmentSkel>(InWorld.Segments.Count); Dictionary<string, GeoSkel> geos = new Dictionary<string, GeoSkel>(InWorld.Geos.Count); // add nodes, segments, and geos to dictionary foreach (Node node in InWorld.Nodes) { if (node.Owner == forPlayer) { Node clone = new Node(node); nodes.Add(clone.ID, clone); playerNodes[nextPlyrNode] = clone; nextPlyrNode++; allNodes[nextAllNode] = clone; } else if (!node.Destroyed) { NodeSkel skel = node.getSkeleton(); nodes.Add(node.ID, skel); allNodes[nextAllNode] = skel; } nextAllNode++; } foreach (Segment seg in InWorld.Segments) { if (seg.Owner == forPlayer) { Segment clone = new Segment(seg); segments.Add(clone.ID, clone); playerSegs[nextPlyrSeg] = clone; nextPlyrSeg++; allSegs[nextAllSeg] = clone; nextAllSeg++; } else if (!seg.Destroyed) { SegmentSkel skel = seg.getSkeleton(); segments.Add(seg.ID, skel); allSegs[nextAllSeg] = skel; nextAllSeg++; } } foreach (Geo geo in InWorld.Geos) { geos.Add(geo.ID, geo.getSkeleton()); } // connect cloned nodes and segments to each other foreach (Node node in playerNodes) { for (int i = 0; i < node.Segments.Length; i++) { Segment seg = node.Segments[i]; if (seg != null) node.Segments[i] = (Segment)segments[seg.ID]; } for (int i = 0; i < node.Parents.Count; i++) { Node n = node.Parents[i]; node.Parents[i] = (Node)nodes[n.ID]; } } foreach (Segment seg in playerSegs) { for (int i = 0; i < seg.Nodes.Length; i++) { Node node = seg.Nodes[i]; if (!node.Destroyed) seg.Nodes[i] = (Node)nodes[node.ID]; else seg.Nodes[i] = new Node(node); } } // build grid skeleton.SqrSize = this.SqrSize; for (int row = 0; row < NumRows; row++) { for (int col = 0; col < NumRows; col++) { GridSqr sqr = Squares[row, col]; skeleton.Squares[row, col] = new GridSqr(new List<NodeSkel>(sqr.Nodes.Count), new List<SegmentSkel>(sqr.Segments.Count), new List<GeoSkel>(sqr.Geos.Count), new List<Hotspot>(sqr.Hotspots.Count), false); foreach (NodeSkel node in sqr.Nodes) { if (((Node)node).Active && !((Node)node).Destroyed) skeleton.Squares[row, col].Nodes.Add(nodes[node.ID]); } foreach (SegmentSkel seg in sqr.Segments) { if (!((Segment)seg).Destroyed) skeleton.Squares[row, col].Segments.Add(segments[seg.ID]); } foreach (GeoSkel geo in sqr.Geos) { skeleton.Squares[row, col].Geos.Add(geos[geo.ID]); } } } return skeleton; }
/// <summary>Creates a segment to connect to the specified node.</summary> /// <param name="node">The node to connect to.</param> public void createSegment(Node node) { Segment segment = new Segment(InWorld); segment.Owner = Owner; segment.Nodes[0] = this; segment.Nodes[1] = node; segment.refreshMath(); segment.EndLength[1] = segment.Length; segment.refreshEndLoc(0); segment.State[0] = Segment.SegState.Building; segment.State[1] = Segment.SegState.Complete; InWorld.addSegment(segment); addSegment(segment, true); alterDensity(0, segment.Capacity, segment); }
//// <summary>Determines whether or not the provided node is visible.</summary> /// <param name="node">The node to test.</param> /// <returns>Whether or not the provided node is visible.</returns> public bool isVisible(Node node) { if (node.Owner == Owner) return true; return isVisible((NodeSkel)node); }
/// <summary>Gets the index of the parent that's shared with the provided node. If non-existent, returns -1.</summary> /// <param name="relative">The potentially related node.</param> /// <returns>The index of the parent that's shared with the provided node. If non-existent, returns -1.</returns> public int relatedParentIndex(Node relative) { for (int i = 0; i < Parents.Count; i++) { foreach (Node parent in relative.Parents) { if (Parents[i] == parent) return i; } } return -1; }
/// <summary>Updates the world.</summary> /// <param name="elapsed">The time elapsed since the last update</param> public void update(GameTime gt) { FInt elapsed = (FInt)gt.ElapsedGameTime.TotalSeconds; // gather AI actions foreach (Player player in Players) { if (player.Type == Player.PlayerType.Computer) { lock (player.AIThreadBase.Actions) { if (player.AIThreadBase.Actions.Count > 0) { PlayerActions.AddRange(player.AIThreadBase.Actions); player.AIThreadBase.Actions.Clear(); } } } } // run begin update script if (!string.IsNullOrEmpty(ScriptBeginUpdate)) Script.runScript(ScriptBeginUpdate); VectorF tempV2 = new VectorF(); Node tempNode0 = null; Node tempNode1 = null; // execute player actions foreach (PlayerAction action in PlayerActions) { switch (action.Action) { case PlayerAction.ActionType.BuildSeg: // don't execute if the node no longer exists or if it has no more open segment slots if (NodeByID.TryGetValue((string)action.Arguments[0], out tempNode0) && tempNode0.NumSegments < tempNode0.Segments.Length) { bool onHotspot = (bool)action.Arguments[1]; if (onHotspot) { Hotspot hs = HotspotByID[(string)action.Arguments[2]]; tempNode1 = new Node(this, getNodeType(tempNode0.Pos, hs.Pos)); tempNode1.OwnsHotspot = hs; tempNode1.Owner = action.Actor; tempNode1.Pos = hs.Pos; addNode(tempNode1); } else { tempV2 = (VectorF)action.Arguments[2]; tempNode1 = new Node(this, getNodeType(tempNode0.Pos, tempV2)); tempNode1.Owner = action.Actor; tempNode1.Pos = tempV2; addNode(tempNode1); } tempNode0.createSegment(tempNode1); } break; case PlayerAction.ActionType.DestroyNode: if (NodeByID.TryGetValue((string)action.Arguments[0], out tempNode0)) tempNode0.destroy(); break; case PlayerAction.ActionType.SplitSeg: Segment seg = null; if (SegByID.TryGetValue((string)action.Arguments[0], out seg)) { tempV2 = (VectorF)action.Arguments[1]; seg.split(Calc.getAdj(VectorF.Distance(tempV2, seg.Nodes[0].Pos), Calc.LinePointDistance(tempV2, seg.EndLoc[0], seg.EndLoc[1]))); } break; case PlayerAction.ActionType.ClaimNode: if (NodeByID.TryGetValue((string)action.Arguments[0], out tempNode0) && NodeByID.TryGetValue((string)action.Arguments[1], out tempNode1)) tempNode0.createSegment(tempNode1); break; default: throw new Exception("Unrecognized player action: " + action.ToString()); } } PlayerActions.Clear(); // update segments for (int i = 0; i < Segments.Count; i++) { #if DEBUG if (Segments[i].Destroyed) throw new Exception("Segment was marked as destroyed before it was updated."); #endif Segments[i].update(elapsed); if (Segments[i].Destroyed) { removeSegment(i); i--; } } // update nodes for (int i = 0; i < Nodes.Count; i++) { if (Nodes[i].Destroyed) { removeNode(i); i--; continue; } Nodes[i].update(elapsed); if (Nodes[i].Destroyed) { removeNode(i); i--; } } // sync AI threads for (int i = 0; i < Players.Count; i++) { Player player = Players[i]; // start thread if not started if (player.Type == Player.PlayerType.Computer && player.AIThreadBase.TheThread == null) player.AIThreadBase.startThread(gt); else if (player.Type != Player.PlayerType.Computer || !player.AIThreadBase.Waiting || player.AIThreadBase.SyncFinished) continue; lock (player.AIThreadBase.Actions) { PlayerActions.AddRange(player.AIThreadBase.Actions); player.AIThreadBase.Actions.Clear(); } EventsToSend.Clear(); // sync segments foreach (KeyValuePair<string, WorldEvent.EventType> e in SegEvents[i]) { string id = e.Key; WorldEvent.EventType evnt = e.Value; Segment tempSeg = null; switch (evnt) { case WorldEvent.EventType.AddSeg: tempSeg = SegByID[id]; if (tempSeg.Owner == player) EventsToSend.Add(new WorldEvent(evnt, true, new Segment(tempSeg))); else EventsToSend.Add(new WorldEvent(evnt, false, id, tempSeg.EndLoc[0], tempSeg.State[0], tempSeg.EndLoc[1], tempSeg.State[1])); break; case WorldEvent.EventType.RemSeg: EventsToSend.Add(new WorldEvent(evnt, id)); break; case WorldEvent.EventType.SegChangeState: tempSeg = SegByID[id]; if (tempSeg.Owner == player) EventsToSend.Add(new WorldEvent(evnt, id, tempSeg.EndLength[0], tempSeg.State[0], tempSeg.EndLength[1], tempSeg.State[1])); else EventsToSend.Add(new WorldEvent(evnt, id, tempSeg.EndLoc[0], tempSeg.State[0], tempSeg.EndLoc[1], tempSeg.State[1])); break; default: throw new Exception("Unrecognized segment event: " + evnt.ToString()); } } SegEvents[i].Clear(); // sync nodes foreach (KeyValuePair<string, WorldEvent.EventType> e in NodeEvents[i]) { string id = e.Key; WorldEvent.EventType evnt = e.Value; Node tempNode = null; switch (evnt) { case WorldEvent.EventType.AddNode: tempNode = NodeByID[id]; if (tempNode.Owner == player) EventsToSend.Add(new WorldEvent(evnt, true, new Node(tempNode))); else EventsToSend.Add(new WorldEvent(evnt, false, id, tempNode.IsParent, tempNode.Pos, tempNode.Radius)); break; case WorldEvent.EventType.RemNode: EventsToSend.Add(new WorldEvent(evnt, id)); break; case WorldEvent.EventType.NodeChangeState: tempNode = NodeByID[id]; if (tempNode.Owner != player) EventsToSend.Add(new WorldEvent(evnt, id, tempNode.Active)); else EventsToSend.Add(new WorldEvent(evnt, id, tempNode.Active, new List<Segment>(tempNode.Segments))); break; default: throw new Exception("Unrecognized node event: " + evnt.ToString()); } } NodeEvents[i].Clear(); lock (player.AIThreadBase.Events) player.AIThreadBase.Events.AddRange(EventsToSend); EventsToSend.Clear(); // sync density for player's system foreach (Node node in player.AIThreadBase.Nodes) { Node wNode = null; if (NodeByID.TryGetValue(node.ID, out wNode)) { for (int j = 0; j < node.Segments.Length; j++) { node.SegNumPeople[j] = wNode.SegNumPeople[j]; node.SegCapacity[j] = wNode.SegCapacity[j]; } } } player.AIThreadBase.SyncFinished = true; } }
/// <summary>Finds the segment that relates to the specified node.</summary> /// <param name="relative">The node to search for.</param> /// <returns>The segment that relates to the specified node.</returns> public int relatedSeg(Node relative) { Stack<Node> nodes = new Stack<Node>(); Stack<Segment> fromSegs = new Stack<Segment>(); for (int i = 0; i < Segments.Length; i++) { int lane = -1; if (Segments[i] == null || Segments[i].State[lane = Segments[i].getNodeIndex(this)] != SegmentSkel.SegState.Complete) continue; Node firstNode = Segments[i].Nodes[1 - lane]; nodes.Clear(); fromSegs.Clear(); foreach (Segment seg in firstNode.Segments) { if (seg != null && seg != Segments[i] && seg.State[lane = seg.getNodeIndex(firstNode)] == SegmentSkel.SegState.Complete) { nodes.Push(seg.Nodes[1 - lane]); fromSegs.Push(seg); } } while (nodes.Count != 0) { Node node = nodes.Pop(); Segment fromSeg = fromSegs.Pop(); if (node == relative) return i; foreach (Segment seg in node.Segments) { if (seg != null && seg != fromSeg && seg.State[lane = seg.getNodeIndex(node)] == SegmentSkel.SegState.Complete) { nodes.Push(seg.Nodes[1 - lane]); fromSegs.Push(seg); } } } } return -1; }
/// <summary>Creates a new instance of LevelEditorMode.</summary> /// <param name="graphics">The graphics device manager to use.</param> /// <param name="content">The content manager to use.</param> /// <param name="batch">The sprite batch to use.</param> /// <param name="bEffect">The basic effect to use.</param> public LevelEditorMode(GraphicsDeviceManager graphics, ContentManager content, SpriteBatch batch, BasicEffect bEffect) : base(graphics, content, batch, bEffect) { world = new World(true); world.Grid = new GridManager(1, 1, world); hoveredNode = null; selectedNode = null; hoveredSeg = null; selectedSeg = null; hoveredSegEnd = null; hoveredSegEndOwner = null; selectedSegEnd = null; hoveredGeo = null; hoveredGeoVertex = -1; hoveredGeoIsLine = false; selectedGeo = null; selectedGeoVertex = -1; selectedGeoIsLine = false; desktop = new Desktop(); lastClickedPoint = new VectorF(); dragOffset = new VectorF(); isDragging = false; }
/// <summary>Adds a person to the lane leading from the specified node.</summary> /// <param name="fromNode">The node from which the person should come.</param> public void addPerson(Node fromNode) { addPerson(getNodeIndex(fromNode)); }
/// <summary>Moves the provided node to the specified coordinates.</summary> /// <param name="node">The node to move.</param> /// <param name="to">The coordinates to move the node to.</param> private void moveNode(Node node, VectorF to) { // remove from grid world.Grid.Point(node.Pos, node, world.gridRemoveNode); // remove attached segments from the grid foreach (Segment seg in world.Segments) { if (seg.Nodes[0] == node || seg.Nodes[1] == node) world.Grid.Line(seg.Nodes[0].Pos, seg.Nodes[1].Pos, seg, world.gridRemoveSegment); } node.Pos = to; // add back into grid if (world.Nodes.Contains(node)) world.Grid.Point(node.Pos, node, world.gridAddNode); // add attached segments back into the grid foreach (Segment seg in world.Segments) { if (seg.Nodes[0] == node || seg.Nodes[1] == node) { double q0 = (double)seg.EndLength[0] / (double)seg.Length; double q1 = (double)seg.EndLength[1] / (double)seg.Length; seg.refreshMath(); seg.EndLength[0] = (seg.State[0] == SegmentSkel.SegState.Complete) ? seg.Length : (FInt)((double)seg.Length * q0); seg.EndLength[1] = (seg.State[1] == SegmentSkel.SegState.Complete) ? seg.Length : (FInt)((double)seg.Length * q1); seg.refreshEndLocs(); world.Grid.Line(seg.Nodes[0].Pos, seg.Nodes[1].Pos, seg, world.gridAddSegment); } } }
/// <summary>Resets all values to their defaults.</summary> public override void clear() { base.clear(); InWorld = null; Length = FInt.F0; EndLength = new FInt[2]; Nodes = new Node[2]; People = new LList<FInt>[2]; People[0] = new LList<FInt>(); People[1] = new LList<FInt>(); NumPeople = 0; Capacity = FInt.F0; CurLaneCapacity = FInt.F0; Direction = VectorF.Zero; Direction = VectorF.Zero; Angle = FInt.F0; Destroyed = false; }
/// <summary>Updates all variables in this mode.</summary> /// <param name="gameTime">The current game time.</param> public override void Update(GameTime gameTime) { base.Update(gameTime); FInt elapsed = (FInt)gameTime.ElapsedGameTime.TotalSeconds; // update gui if (Inp.OldMse.Position != Inp.Mse.Position) desktop.mouseMove(Inp.Mse.Position); GUI.Desktop.Event evnt = Desktop.Event.MouseRightUp; bool guiOwnedInput = false; if (Inp.OldMse.LeftButton == ButtonState.Pressed && Inp.Mse.LeftButton == ButtonState.Released) guiOwnedInput |= desktop.PerformMouseEvent(Desktop.Event.MouseLeftUp, Inp.Mse.Position, Inp); if (Inp.OldMse.LeftButton == ButtonState.Released && Inp.Mse.LeftButton == ButtonState.Pressed) guiOwnedInput |= desktop.PerformMouseEvent(Desktop.Event.MouseLeftDown, Inp.Mse.Position, Inp); if (Inp.OldMse.RightButton == ButtonState.Pressed && Inp.Mse.RightButton == ButtonState.Released) guiOwnedInput |= desktop.PerformMouseEvent(Desktop.Event.MouseRightUp, Inp.Mse.Position, Inp); if (Inp.OldMse.RightButton == ButtonState.Released && Inp.Mse.RightButton == ButtonState.Pressed) guiOwnedInput |= desktop.PerformMouseEvent(Desktop.Event.MouseRightUp, Inp.Mse.Position, Inp); Keys[] newKeys = Inp.Key.GetPressedKeys(); if (newKeys.Length != 0) guiOwnedInput |= desktop.PerformKeyEvent(newKeys, Inp); if (guiOwnedInput) { hoveredNode = null; hoveredSeg = null; hoveredSegEnd = null; hoveredSegEndOwner = null; hoveredGeo = null; hoveredHotspot = null; isDragging = false; } else { // prepare grid manager world.Grid.startNewUpdate(gameTime); // move camera if (Inp.Key.IsKeyDown(Keys.OemPlus)) world.Cam.Zoom += world.Cam.Zoom * elapsed; if (Inp.Key.IsKeyDown(Keys.OemMinus)) world.Cam.Zoom -= world.Cam.Zoom * elapsed; if (Inp.Key.IsKeyDown(Keys.A)) world.Cam.CenterX -= (700 / world.Cam.Zoom) * elapsed; if (Inp.Key.IsKeyDown(Keys.D)) world.Cam.CenterX += (700 / world.Cam.Zoom) * elapsed; if (Inp.Key.IsKeyDown(Keys.W)) world.Cam.CenterY -= (700 / world.Cam.Zoom) * elapsed; if (Inp.Key.IsKeyDown(Keys.S)) world.Cam.CenterY += (700 / world.Cam.Zoom) * elapsed; world.Cam.Zoom += (FInt)(Inp.Mse.ScrollWheelValue - Inp.OldMse.ScrollWheelValue) / (FInt)120 * (FInt).1d * world.Cam.Zoom; world.Cam.refreshCorners(); // get cursor world coordinates VectorF cursorPos = world.Cam.screenToWorld(new Vector2((float)Inp.Mse.X, (float)Inp.Mse.Y)); // check for hovered node, segment, segment end, and hotspot hoveredNode = world.NodeAtPoint(cursorPos, false); hoveredSeg = (hoveredNode == null) ? world.segmentAtPoint(cursorPos, null) : null; hoveredSegEnd = world.SegmentEndAtPoint(cursorPos); if (hoveredSegEnd != null) { foreach (Segment seg in world.Segments) { if (seg.Nodes[0] == hoveredSegEnd || seg.Nodes[1] == hoveredSegEnd) { hoveredSegEndOwner = seg.Owner; break; } } } else { hoveredSegEndOwner = null; } hoveredHotspot = world.HotspotAtPoint(cursorPos); // test geo vertices hoveredGeo = world.geoAtPoint(cursorPos, out hoveredGeoVertex, true); // test geo lines if (hoveredGeo == null) { hoveredGeo = world.geoAtPoint(cursorPos, out hoveredGeoVertex, false); hoveredGeoIsLine = true; } else { hoveredGeoIsLine = false; } // if the user just released the left mouse button if (Inp.OldMse.LeftButton == ButtonState.Pressed && Inp.Mse.LeftButton == ButtonState.Released) { if (selectedSegEnd != null) { // do nothing } // add node else if (btnAddNode.Pressed && cmbNodeTypes.SelectedIndex != -1 && selectedGeo == null && (selectedNode == null || isDragging) && selectedSeg == null && selectedHotspot == null) { bool useHoveredEnd = (hoveredSegEnd != null && (selectedNode == null || selectedNode.Owner == hoveredSegEndOwner)); // add node Node node = new Node(world, world.NodeTypes[cmbEditorAddNodeType.SelectedIndex]); node.Pos = useHoveredEnd ? hoveredSegEnd.Pos : cursorPos; node.Active = true; if (selectedNode != null && isDragging) { node.Owner = selectedNode.Owner; if (selectedNode.NumSegments < selectedNode.Segments.Length) // add segment too { Segment seg = new Segment(world); seg.Owner = selectedNode.Owner; seg.Nodes[0] = selectedNode; seg.Nodes[1] = node; selectedNode.addSegment(seg, false); node.addSegment(seg, false); seg.refreshMath(); seg.EndLength[0] = seg.Length; seg.EndLength[1] = seg.Length; seg.refreshEndLocs(); world.addSegment(seg); } } else if (selectedNode == null && hoveredSegEnd != null) { node.Owner = hoveredSegEndOwner; } else if (cmbEditorAddNodeOwner.SelectedIndex != 0) { node.Owner = world.Players[cmbEditorAddNodeOwner.SelectedIndex - 1]; } if (useHoveredEnd) { // link segments to it foreach (Segment seg in (hoveredSegEndOwner == null ? world.Segments : hoveredSegEndOwner.Segments)) { for (int i = 0; i < 2; i++) { if (seg.Nodes[i] == hoveredSegEnd) { seg.Nodes[i] = node; break; } } } } world.addNode(node); selectedNode = node; selectedSeg = null; loadObjectEditor(); } // add segment else if (btnAddSeg.Pressed && isDragging && selectedSeg == null && selectedGeo == null && (selectedNode == null || selectedNode.NumSegments < selectedNode.Segments.Length) && selectedHotspot == null) { Segment seg = new Segment(world); seg.Owner = (selectedNode != null) ? selectedNode.Owner : (hoveredNode != null) ? hoveredNode.Owner : (cmbEditorAddSegOwner.SelectedIndex > 0) ? world.Players[cmbEditorAddSegOwner.SelectedIndex - 1] : null; if (selectedNode != null) { seg.Nodes[0] = selectedNode; seg.Owner = selectedNode.Owner; selectedNode.addSegment(seg, false); } else { seg.State[1] = SegmentSkel.SegState.Retracting; seg.Nodes[0] = new Node(world); seg.Nodes[0].Pos = lastClickedPoint; seg.Nodes[0].Active = false; seg.Nodes[0].Destroyed = true; seg.Nodes[0].initSegArrays(0); } if (hoveredNode != null && hoveredNode.NumSegments != hoveredNode.Segments.Length && (selectedNode == null || (hoveredNode != selectedNode && hoveredNode.Owner == selectedNode.Owner && hoveredNode.relatedSeg(selectedNode) == -1))) { seg.Nodes[1] = hoveredNode; hoveredNode.addSegment(seg, false); } else { seg.State[0] = SegmentSkel.SegState.Building; seg.Nodes[1] = new Node(world); seg.Nodes[1].Pos = cursorPos; seg.Nodes[1].Active = false; seg.Nodes[1].Destroyed = true; seg.Nodes[1].initSegArrays(0); } seg.refreshMath(); seg.EndLength[0] = seg.Length; seg.EndLength[1] = seg.Length; seg.refreshEndLocs(); world.addSegment(seg); selectedNode = null; selectedSeg = seg; loadObjectEditor(); } // add geo vertex else if (btnAddGeo.Pressed && selectedNode == null && selectedSeg == null && selectedSegEnd == null && selectedHotspot == null) { // add vertex to existing geo if (selectedGeo != null && !selectedGeoIsLine && isDragging && (selectedGeoVertex == 0 || selectedGeoVertex == selectedGeo.Vertices.Length - 1)) { VectorF[] vertices; if (selectedGeo.Vertices.Length == 1) { vertices = new VectorF[selectedGeo.Vertices.Length + 1]; vertices[0] = cursorPos; vertices[1] = selectedGeo.Vertices[0]; } else if (selectedGeoVertex == 0) { vertices = new VectorF[selectedGeo.Vertices.Length + 2]; selectedGeo.Vertices.CopyTo(vertices, 2); vertices[0] = cursorPos; vertices[1] = selectedGeo.Vertices[0]; } else { vertices = new VectorF[selectedGeo.Vertices.Length + 2]; selectedGeo.Vertices.CopyTo(vertices, 0); vertices[selectedGeo.Vertices.Length] = selectedGeo.Vertices[selectedGeo.Vertices.Length - 1]; vertices[selectedGeo.Vertices.Length + 1] = cursorPos; selectedGeoVertex = vertices.Length - 1; } world.Grid.Rect(selectedGeo.UpperLeft, selectedGeo.LowerRight, selectedGeo, world.gridRemoveGeo); selectedGeo.Vertices = vertices; selectedGeo.refreshMath(new Vector2((float)tGeo.Width, (float)tGeo.Height)); world.Grid.Rect(selectedGeo.UpperLeft, selectedGeo.LowerRight, selectedGeo, world.gridAddGeo); selectedGeoIsLine = false; loadObjectEditor(); } // add vertex in the middle of a line else if (hoveredGeo != null && hoveredGeoIsLine) { VectorF[] vertices = new VectorF[hoveredGeo.Vertices.Length + 2]; int v2 = (hoveredGeoVertex == hoveredGeo.Vertices.Length - 1) ? 0 : hoveredGeoVertex + 1; float dist = (float)Calc.getAdj(VectorF.Distance(cursorPos, hoveredGeo.Vertices[hoveredGeoVertex]), Calc.LinePointDistance(cursorPos, hoveredGeo.Vertices[hoveredGeoVertex], hoveredGeo.Vertices[v2])); Vector2 dir = Vector2.Normalize((Vector2)(hoveredGeo.Vertices[v2] - hoveredGeo.Vertices[hoveredGeoVertex])); VectorF pos = (VectorF)((Vector2)hoveredGeo.Vertices[hoveredGeoVertex] + (dir * dist)); for (int i = 0; i <= hoveredGeoVertex; i++) { vertices[i] = hoveredGeo.Vertices[i]; } if (hoveredGeoVertex == selectedGeo.Vertices.Length - 1) { vertices[hoveredGeoVertex + 1] = selectedGeo.Vertices[selectedGeo.Vertices.Length - 1]; vertices[hoveredGeoVertex + 2] = pos; } else { vertices[hoveredGeoVertex + 1] = pos; vertices[hoveredGeoVertex + 2] = pos; for (int i = hoveredGeoVertex + 1; i < hoveredGeo.Vertices.Length; i++) { vertices[i + 2] = hoveredGeo.Vertices[i]; } } world.Grid.Rect(hoveredGeo.UpperLeft, hoveredGeo.LowerRight, hoveredGeo, world.gridRemoveGeo); hoveredGeo.Vertices = vertices; hoveredGeo.refreshMath(new Vector2((float)tGeo.Width, (float)tGeo.Height)); world.Grid.Rect(hoveredGeo.UpperLeft, hoveredGeo.LowerRight, hoveredGeo, world.gridAddGeo); hoveredGeoIsLine = false; hoveredGeoVertex += 2; selectedGeo = hoveredGeo; selectedGeoIsLine = false; selectedGeoVertex = hoveredGeoVertex; loadObjectEditor(); } // add new geo else if (hoveredGeo == null) { Geo geo = new Geo(world); geo.Vertices = new VectorF[] { cursorPos }; geo.CloseLoop = false; geo.Display = false; geo.refreshMath(new Vector2((float)tGeo.Width, (float)tGeo.Height)); world.addGeo(geo); selectedGeo = geo; selectedGeoIsLine = false; selectedGeoVertex = 0; loadObjectEditor(); } } else if (btnAddHotspot.Pressed && selectedNode == null && selectedSeg == null && selectedSegEnd == null && selectedGeo == null) { // add hotspot Hotspot hotspot = new Hotspot(world); hotspot.Pos = cursorPos; world.addHotspot(hotspot); selectedHotspot = hotspot; loadObjectEditor(); } selectedSegEnd = null; isDragging = false; } // if the player just released the right mouse button else if (Inp.OldMse.RightButton == ButtonState.Pressed && Inp.Mse.RightButton == ButtonState.Released) { } // user just pressed the left mouse button else if (Inp.OldMse.LeftButton == ButtonState.Released && Inp.Mse.LeftButton == ButtonState.Pressed) { lastClickedPoint = world.Cam.screenToWorld(new Vector2((float)Inp.Mse.X, (float)Inp.Mse.Y)); isDragging = false; // check for selected node selectedNode = hoveredNode; // check for selected segment end selectedSegEnd = (selectedNode == null) ? hoveredSegEnd : null; // check for selected segment selectedSeg = (selectedNode == null && selectedSegEnd == null) ? hoveredSeg : null; // check for selected hotspot selectedHotspot = (selectedNode == null && selectedSegEnd == null && selectedSeg == null) ? hoveredHotspot : null; // check for selected geo if (selectedNode == null && selectedSeg == null && selectedSegEnd == null && selectedHotspot == null) { selectedGeo = hoveredGeo; selectedGeoIsLine = hoveredGeoIsLine; selectedGeoVertex = hoveredGeoVertex; } else { selectedGeo = null; } loadObjectEditor(); } // user just pressed the right mouse button else if (Inp.OldMse.RightButton == ButtonState.Released && Inp.Mse.RightButton == ButtonState.Pressed) { } // if the left mouse button is still pressed else if (desktop.Focused == null && Inp.OldMse.LeftButton == ButtonState.Pressed && Inp.Mse.LeftButton == ButtonState.Pressed) { if (!isDragging && Vector2.Distance(world.Cam.worldToScreen(lastClickedPoint), new Vector2((float)Inp.Mse.X, (float)Inp.Mse.Y)) >= distToDrag) { isDragging = true; if (selectedNode != null) dragOffset = selectedNode.Pos - lastClickedPoint; else if (selectedSegEnd != null) dragOffset = selectedSegEnd.Pos - lastClickedPoint; else if (selectedSeg != null) dragOffset = selectedSeg.Nodes[0].Pos - lastClickedPoint; else if (selectedHotspot != null) dragOffset = selectedHotspot.Pos - lastClickedPoint; else if (selectedGeo != null) { if (selectedGeoVertex == -1) dragOffset = selectedGeo.Center - lastClickedPoint; else dragOffset = selectedGeo.Vertices[selectedGeoVertex] - lastClickedPoint; } } } // if [Del] key is pressed else if (!Inp.OldKey.IsKeyDown(Keys.Delete) && Inp.Key.IsKeyDown(Keys.Delete)) { if (selectedNode != null) removeSelNode(); else if (selectedSeg != null) removeSelSeg(); else if (selectedHotspot != null) removeSelHotspot(); else if (selectedGeo != null) removeSelGeo(); } // drag if (isDragging) { // move node if (selectedNode != null && !btnAddSeg.Pressed && (!btnAddNode.Pressed || cmbEditorAddNodeType.SelectedIndex < 0)) { moveNode(selectedNode, cursorPos + dragOffset); } // move segment end else if (selectedSegEnd != null) { moveNode(selectedSegEnd, cursorPos + dragOffset); } // move segment else if (selectedSeg != null) { VectorF moveVect = cursorPos + dragOffset - selectedSeg.Nodes[0].Pos; moveNode(selectedSeg.Nodes[0], selectedSeg.Nodes[0].Pos + moveVect); moveNode(selectedSeg.Nodes[1], selectedSeg.Nodes[1].Pos + moveVect); } // move hotspot else if (selectedHotspot != null) { moveHotspot(selectedHotspot, cursorPos + dragOffset); } // move geo/vertex else if (selectedGeo != null && !btnAddGeo.Pressed) { world.Grid.Rect(selectedGeo.UpperLeft, selectedGeo.LowerRight, selectedGeo, world.gridRemoveGeo); if (selectedGeoIsLine) { if (selectedGeoVertex == selectedGeo.Vertices.Length - 1) { selectedGeo.Vertices[0] += cursorPos + dragOffset - selectedGeo.Vertices[selectedGeoVertex]; } else { if (selectedGeoVertex != 0) selectedGeo.Vertices[selectedGeoVertex - 1] = cursorPos + dragOffset; selectedGeo.Vertices[selectedGeoVertex + 1] += cursorPos + dragOffset - selectedGeo.Vertices[selectedGeoVertex]; if (selectedGeoVertex != selectedGeo.Vertices.Length - 2) selectedGeo.Vertices[selectedGeoVertex + 2] += cursorPos + dragOffset - selectedGeo.Vertices[selectedGeoVertex]; } selectedGeo.Vertices[selectedGeoVertex] = cursorPos + dragOffset; } else if (selectedGeoVertex == -1) { VectorF toMove = cursorPos + dragOffset - selectedGeo.Center; for (int i = 0; i < selectedGeo.Vertices.Length; i++) { selectedGeo.Vertices[i] += toMove; } } else { if (selectedGeoVertex != 0 && selectedGeoVertex != selectedGeo.Vertices.Length - 1) selectedGeo.Vertices[selectedGeoVertex - 1] = cursorPos + dragOffset; selectedGeo.Vertices[selectedGeoVertex] = cursorPos + dragOffset; } selectedGeo.refreshMath(new Vector2((float)tGeo.Width, (float)tGeo.Height)); world.Grid.Rect(selectedGeo.UpperLeft, selectedGeo.LowerRight, selectedGeo, world.gridAddGeo); } } } }
private static string translateValue(string val, string context, World map, Node node) { return translateValue(val, context, map, node, null); }