public string RemapWaypointGroupName(string currentName) { string name = currentName; uint endNumber = 0; // if the group exists, make another group name by adding _1, _2, _3, ... while (MyWayPointGraph.GetPath(name) != null) { endNumber++; if (endNumber == 1) { name += "_1"; } else { int last_ = name.LastIndexOf('_'); name = name.Substring(0, last_ + 1) + endNumber.ToString(); } // name length cap: hashing if (name.Length > MyWaypointConstants.MAXIMUM_WAYPOINT_PATH_NAME_LENGTH) { endNumber = (uint)name.GetHashCode(); name = "G_" + endNumber.ToString(); } } return(name); }
// Return true if the given waypoints are connected by a path. O(n) (or O(1) if connected components were unchanged) /// <summary>This function needs to be called with EntityCloseLock already acquired, or not an issue.</summary> public static bool Connected(MyWayPoint v1, MyWayPoint v2) { int c1 = MyWayPointGraph.GetConnectedComponentId(v1); int c2 = MyWayPointGraph.GetConnectedComponentId(v2); return(c1 == c2 && c1 != -1); }
// Return true if the given waypoints are connected by a path. O(n) (or O(1) if connected components were unchanged) /// <summary>This function needs to be called with EntityCloseLock already acquired, or not an issue.</summary> public static bool Connected(IEnumerable <MyWayPoint> vertices) { int component = -1; bool first = true; foreach (var v in vertices) { if (first) { component = MyWayPointGraph.GetConnectedComponentId(v); first = false; } else { int c = MyWayPointGraph.GetConnectedComponentId(v); if (c != component) { return(false); } else if (c == -1) { return(false); // two vertices that don't lie in the waypoint graph must be unconnected } } } return(true); // 0 or 1 vertices are always connected }
protected override void OnCancelClick(MyGuiControlButton sender) { if (m_waypointPath != null) { if (m_newlyAdded) { MyWayPointGraph.RemovePath(MyWayPointGraph.SelectedPath); } } CloseScreen(); }
// Remove all edges from this. O(deg(this)) public void DisconnectFromAllNeighbors() { using (NeighborsLock.AcquireExclusiveUsing()) { MyWayPointGraph.MakeConnectedComponentsDirty(); foreach (var v in m_neighbors) { v.m_neighbors.Remove(this); } m_neighbors.Clear(); } }
// Add a symmetric edge between two vertices. O(1) public static void Connect(MyWayPoint v1, MyWayPoint v2) { if (v1 == v2) { return; } using (NeighborsLock.AcquireExclusiveUsing()) { MyWayPointGraph.MakeConnectedComponentsDirty(); v1.m_neighbors.Add(v2); v2.m_neighbors.Add(v1); } }
private void LoadWaypointEdges() { m_edges.Clear(); BoundingBox bb = BoundingBoxHelper.InitialBox; foreach (var part in m_parts) { if (part != null) { BoundingBoxHelper.AddBBox(part.WorldAABB, ref bb); } } m_edges.AddRange(MyWayPointGraph.GetAllEdgesInBox(ref bb)); }
/// <summary> /// Create entities from action object builders /// </summary> void AddOrCreate() { MyEditorGizmo.ClearSelection(); // Once entities has been created in this action, they remain and if needed, are only removed/added to scene if (ActionEntities != null && ActionEntities.Count > 0) { foreach (MyEntity actionEntity in ActionEntities) { AddToScene(actionEntity); } } else { // If no ActionEntites are present, create them from provided object builders foreach (ObjectBuilderCreate crate in ActionObjectBuilders) { CreateFromObjectBuilder(crate.ObjectBuilder, crate.Matrix, crate.ScreenPosition); } } // Link the new entities and clean up waypoint vertices foreach (var e in ActionEntities) { e.Link(); } MyWayPointGraph.DeleteNullVerticesFromPaths(); // When copying a single waypoint, connect it to its source if (this is MyEditorActionEntityCopy && ActionEntities.Count == 1 && ActionEntities[0] is MyWayPoint) { var source = (this as MyEditorActionEntityCopy).SourceEntities[0] as MyWayPoint; if (source != null) { MyWayPoint.Connect(source, ActionEntities[0] as MyWayPoint); } } // When copying prefabs, connect snap points connections if (this is MyEditorActionEntityCopy) { MyEditor.Static.CopySnapPointLinks((this as MyEditorActionEntityCopy).SourceEntities, (this as MyEditorActionEntityCopy).RemapContext); } MyEditor.Static.IssueCheckAllCollidingObjects(); }
public virtual void Init(string hudLabelText, MyMwcObjectBuilder_WaypointNew ob, Matrix matrix) { StringBuilder hudLabelTextSb = (hudLabelText == null) ? null : new StringBuilder(hudLabelText); base.Init(hudLabelTextSb, ob); objectBuilder = ob; SetWorldMatrix(matrix); MyWayPointGraph.AddVertex(this); this.LocalVolume = new BoundingSphere(Vector3.Zero, MAX_RADIUS_WAYPOINT); //VisibleInGame = false; Visible = true; Flags |= EntityFlags.EditableInEditor; CastShadows = false; UpdateRenderObject(Visible); }
/// <summary> /// This method is called when sector and all entities are loaded (created from object builder - or generated other way). /// It raises LinkEntities event, and calls method MyEntities.Link. /// </summary> public void AfterLoad(MyMwcObjectBuilder_Checkpoint checkpoint) { CheckpointName = checkpoint.CheckpointName; MyEntityIdentifier.AllocationSuspended = false; var handler = LinkEntities; if (handler != null) { handler(); } MyEntities.Link(); MyWayPointGraph.DeleteNullVerticesFromPaths(); MyWayPointGraph.RemoveWaypointsAroundLargeStaticObjects(); FactionRelationChanges.Init(checkpoint.FactionRelationChangesBuilder); // GPS waypoints must be created after the first physics pass: see end of MyGuiScreenGamePlay.Update() }
private void SetBotPath(MySmallShipBot bot) { bot.WaypointPath = MyWayPointGraph.GetPath(m_wayPointPath); bot.PatrolMode = PatrolMode; //check if any leader present Bot leader = m_botShips.Find(s => (s.Ship != null && s.Ship.Leader == null)); if (leader != null) { bot.Follow(leader.Ship); } else if (bot.WaypointPath != null) { bot.Patrol(); } if (Leader != null) { bot.Follow(Leader); } }
public override bool DebugDraw() { /* * int i = MyWayPointGraph.GetConnectedComponentId(this); * var vertexColor = HsvToRgb((0.36f + i * 0.618034f) % 1.0f, 0.8f, 0.75f); * * DrawWaypointVertex(WorldMatrix.Translation, vertexColor); // draw only edges for generated waypoints * * * // draw edges * foreach (var neighbor in Neighbors) * { * //DrawWaypointEdge(wp.WorldMatrix.Translation, neighbor.WorldMatrix.Translation, Color.Red, Color.Green); // selected path: red-green edges * * if (neighbor.WorldMatrix.Translation != WorldMatrix.Translation) * { * Vector3 direction = neighbor.WorldMatrix.Translation - WorldMatrix.Translation; * float lineLength = direction.Length(); * direction.Normalize(); * MyTransparentGeometry.AddLineBillboard(MyTransparentMaterialEnum.ProjectileTrailLine, Color.Yellow.ToVector4(), WorldMatrix.Translation, direction, lineLength, 0.25f); * } * * } */ if (((MyHud.ShowDebugWaypoints) || (MyGuiScreenGamePlay.Static.IsEditorActive() && !MyGuiScreenGamePlay.Static.IsIngameEditorActive())) && (MyFakes.ENABLE_GENERATED_WAYPOINTS_IN_EDITOR || MyHud.ShowDebugGeneratedWaypoints || Save)) { // color by connected components int i = MyWayPointGraph.GetConnectedComponentId(this); var vertexColor = HsvToRgb((0.36f + i * 0.618034f) % 1.0f, 0.8f, 0.75f); if (MyWayPointGraph.SelectedPath != null && MyWayPointGraph.SelectedPath.WayPoints.Contains(this)) { vertexColor = Color.Orange.ToVector3(); // selected path: orange vertices } if (IsSecret) { vertexColor *= 0.25f; } // draw vertices if (MyEditorGizmo.SelectedEntities.Contains(this)) { DrawWaypointVertex(WorldMatrix.Translation, vertexColor + (IsSecret ? 1 : 3) * GetHighlightColor()); var name = new StringBuilder(); if (MyWayPointGraph.SelectedPath != null && MyWayPointGraph.SelectedPath.WayPoints.Contains(this)) { name.Append(MyWayPointGraph.SelectedPath.Name).Append(": ").Append(MyWayPointGraph.SelectedPath.WayPoints.IndexOf(this) + 1); } else { name.Append(MyWayPoint.FilterWayPoints(MyEditorGizmo.SelectedEntities).IndexOf(this) + 1); } MyDebugDraw.DrawText(WorldMatrix.Translation, name, Color.White, 1); } else { if (Save) { DrawWaypointVertex(WorldMatrix.Translation, vertexColor); // for generated waypoints, draw only edges } } // draw edges if (Save || MyHud.ShowDebugGeneratedWaypoints) { using (MyWayPoint.NeighborsLock.AcquireSharedUsing()) { foreach (var neighbor in Neighbors) { if (MyWayPointGraph.SelectedPath != null && MyWayPointGraph.SelectedPath.ContainsEdge(this, neighbor)) { DrawWaypointEdge(WorldMatrix.Translation, neighbor.WorldMatrix.Translation, Color.Yellow, Color.White); // on selected path: yellow-white continue; } if (neighbor.Save || MyHud.ShowDebugGeneratedWaypoints) { using (MyWayPoint.BlockedEdgesLock.AcquireSharedUsing()) { // blocked for player (by a locked indestructible door: white-gray) if (BlockedEdgesForPlayer.Contains(Tuple.Create(this, neighbor)) || BlockedEdgesForPlayer.Contains(Tuple.Create(neighbor, this))) { DrawWaypointEdge(WorldMatrix.Translation, neighbor.WorldMatrix.Translation, Color.White, Color.Gray); continue; } // blocked for bots by a locked door: black-gray if (BlockedEdgesForBots.Contains(Tuple.Create(this, neighbor)) || BlockedEdgesForBots.Contains(Tuple.Create(neighbor, this))) { DrawWaypointEdge(WorldMatrix.Translation, neighbor.WorldMatrix.Translation, Color.Black, Color.Gray); continue; } } // obstructed: violet-white if (MyHud.ShowDebugWaypointsCollisions && Position != neighbor.Position) { var line = new MyLine(Position, neighbor.Position, true); if (MyEntities.GetAnyIntersectionWithLine(ref line, null, null, true, true, true, false) != null) { DrawWaypointEdge(WorldMatrix.Translation, neighbor.WorldMatrix.Translation, Color.Violet, Color.White); continue; } } // normal-normal: red-green // generated-normal: orange-green (normally invisible) // generated-generated: yellow-green (normally invisible) bool generated = !(Save && neighbor.Save); bool fullyGenerated = !Save && !neighbor.Save; DrawWaypointEdge(WorldMatrix.Translation, neighbor.WorldMatrix.Translation, generated ? fullyGenerated ? Color.Yellow : Color.Orange : Color.Red, Color.Green); continue; } } } } } return(base.DebugDraw()); }
public override void Close() { MyWayPointGraph.RemoveVertex(this); base.Close(); }
// Resolve EntityId links. public void ResolveLinks() { // parent entities (prefabs) if (objectBuilder.ParentEntityId != null && MyEntities.GetEntities().Contains(this)) { var parent = MyEntities.GetEntityByIdOrNull(new MyEntityIdentifier((uint)objectBuilder.ParentEntityId.Value)); if (parent != null) { var worldMatrix = WorldMatrix; MyEntities.Remove(this); //parent.Children.Add(this); // remove it and add back through the parent parent.AddChild(this); this.Activate(true, false); SetWorldMatrix(worldMatrix); } } // neighbors foreach (var neighborId in objectBuilder.NeighborEntityIds) { var neighbor = MyEntities.GetEntityByIdOrNull(new MyEntityIdentifier((uint)neighborId)); if (neighbor != null && neighbor is MyWayPoint) { Connect(this, (MyWayPoint)neighbor); } } // path placing for (int i = 0; i < objectBuilder.GroupPlacings.Count; i++) { var name = objectBuilder.GroupNames[i]; var placing = objectBuilder.GroupPlacings[i]; // resolve path by name: create it if it didn't exist MyWayPointPath path = MyWayPointGraph.GetPath(name); if (path == null) { path = new MyWayPointPath(name); } // make enough empty waypoints to make it fit while (placing >= path.WayPoints.Count) { path.WayPoints.Add(null); } path.WayPoints[placing] = this; } // can't delete object builder // This function is reentrant and sometimes we need both runs. //objectBuilder = null; // but we can delete neighbor and path info if (MyGuiScreenGamePlay.Static.IsGameActive()) { objectBuilder.GroupNames.Clear(); objectBuilder.GroupPlacings.Clear(); objectBuilder.NeighborEntityIds.Clear(); } }
public void InsertRequiredActors() { MyMwcLog.WriteLine("InsertRequiredActors - START"); foreach (MyActorEnum actor in RequiredActors) { switch (actor) { //Insert Madelyn case MyActorEnum.MADELYN: { if (!MyEntities.EntityExists("Madelyn")) { MyMwcLog.WriteLine("Insert Madelyne - START"); // Holds ids for remap IMyEntityIdRemapContext remapContext = new MyEntityIdRemapContext(); //MyMwcObjectBuilder_SectorObjectGroups groups = MySectorGenerator.LoadSectorGroups(MyTemplateGroups.GetGroupSector(MyTemplateGroupEnum.Madelyn)); MyMwcObjectBuilder_SectorObjectGroups groups = MySession.Static.LoadSectorGroups(MyTemplateGroups.GetGroupSector(MyTemplateGroupEnum.Madelyn)); System.Diagnostics.Debug.Assert(groups.Groups.Count > 0); MyMwcObjectBuilder_ObjectGroup madelynGroup = groups.Groups[0]; groups.RemapEntityIds(remapContext); IEnumerable <MyMwcObjectBuilder_Base> rootObjects = madelynGroup.GetRootBuilders(groups.Entities); List <MyMwcObjectBuilder_Base> clonedList = new List <MyMwcObjectBuilder_Base>(); foreach (MyMwcObjectBuilder_Base o in rootObjects) { // Clone var clone = o.Clone() as MyMwcObjectBuilder_Base; // we want Madelyn's prefab container as first builder if (clone is MyMwcObjectBuilder_PrefabContainer) { clonedList.Insert(0, clone); } else { clonedList.Add(clone); } } System.Diagnostics.Debug.Assert(clonedList.Count > 0 && clonedList[0] is MyMwcObjectBuilder_PrefabContainer); // create Madelyn's prefab container MyEntity madelynMothership = MyEntities.CreateFromObjectBuilder(MyTextsWrapper.Get(MyTextsWrapperEnum.Actor_Madelyn).ToString(), clonedList[0], ((MyMwcObjectBuilder_Object3dBase)clonedList[0]).PositionAndOrientation.GetMatrix()); madelynMothership.FindChild(MyMissionLocation.MADELYN_HANGAR).DisplayName = MyTextsWrapper.Get(MyTextsWrapperEnum.Sapho).ToString(); madelynMothership.SetName(MyActorConstants.GetActorName(MyActorEnum.MADELYN)); Matrix madelynMothershipWorldInv = Matrix.Invert(madelynMothership.WorldMatrix); List <MinerWars.AppCode.Game.Entities.WayPoints.MyWayPoint> waypoints = new List <Entities.WayPoints.MyWayPoint>(); // create other entities as children of Madelyn's prefab container for (int i = 1; i < clonedList.Count; i++) { System.Diagnostics.Debug.Assert(clonedList[i] is MyMwcObjectBuilder_Object3dBase); MyEntity childEntity = MyEntities.CreateFromObjectBuilder(null, clonedList[i], ((MyMwcObjectBuilder_Object3dBase)clonedList[i]).PositionAndOrientation.GetMatrix()); childEntity.SetLocalMatrix(childEntity.WorldMatrix * madelynMothershipWorldInv); madelynMothership.Children.Add(childEntity); if (childEntity is MinerWars.AppCode.Game.Entities.WayPoints.MyWayPoint) { waypoints.Add(childEntity as MinerWars.AppCode.Game.Entities.WayPoints.MyWayPoint); } } // connect waypoints of Madelyn's prefab container foreach (var waypoint in waypoints) { waypoint.ResolveLinks(); } // set correct Madelyn's position and add to scene madelynMothership.SetWorldMatrix(MyPlayer.FindMothershipPosition()); madelynMothership.Link(); MyEntities.Add(madelynMothership); MyMwcLog.WriteLine("Insert Madelyne - END"); } else { MyMwcLog.WriteLine("Insert Madelyne - Madelyne already loaded"); } MyWayPointGraph.RecreateWaypointsAroundMadelyn(); } break; //Insert Marcus case MyActorEnum.MARCUS: InsertFriend(MyActorEnum.MARCUS); break; //Insert RavenGirl case MyActorEnum.TARJA: InsertFriend(MyActorEnum.TARJA); break; //Insert RavenGuy case MyActorEnum.VALENTIN: InsertFriend(MyActorEnum.VALENTIN, MyMwcObjectBuilder_SmallShip_TypesEnum.HAMMER); break; default: System.Diagnostics.Debug.Assert(false, "Uknown actor to insert!"); break; } } MyMwcLog.WriteLine("InsertRequiredActors - END"); }
private static List <Vector3> FindPath(Vector3 start, Vector3 end, bool useRaycasts) { using (MyEntities.EntityCloseLock.AcquireSharedUsing()) { var closestToStart = MyWayPointGraph.GetClosestWaypointReachableByShip(start, null, MyAIConstants.PATHFINDING_MAX_START_RAYCASTS, MyAIConstants.PATHFINDING_SHIP_RADIUS); if (closestToStart == null) { return(null); } var closestToEnd = MyWayPointGraph.GetClosestWaypointReachableByShip(end, null, MyAIConstants.PATHFINDING_MAX_END_RAYCASTS, MyAIConstants.PATHFINDING_SHIP_RADIUS); if (closestToEnd == null) { return(null); } if (useRaycasts) { HashSet <Tuple <MyWayPoint, MyWayPoint> > blockedEdges = null; HashSet <Tuple <MyWayPoint, MyWayPoint> > unblockedEdges = null; using (MyWayPoint.BlockedEdgesLock.AcquireSharedUsing()) { blockedEdges = new HashSet <Tuple <MyWayPoint, MyWayPoint> >(MyWayPoint.BlockedEdgesForBots); // TODO: do we need to copy this every time? unblockedEdges = new HashSet <Tuple <MyWayPoint, MyWayPoint> >(); } for (int retryCount = 0; retryCount < 30; retryCount++) { var pathWaypoints = closestToStart.GetShortestPathTo(closestToEnd, blockedEdges, true, true); if (pathWaypoints == null || pathWaypoints.Count == 0) { return(null); // no path (we can exit right away since we only *add* blocked edges) } bool blocked = false; for (int i = 0; i < pathWaypoints.Count - 2; i++) { var tuple = Tuple.Create(pathWaypoints[i], pathWaypoints[i + 1]); if (unblockedEdges.Contains(tuple)) // already tested and it was ok { } else if (pathWaypoints[i + 1].IsVisibleFrom(pathWaypoints[i].Position)) { unblockedEdges.Add(tuple); unblockedEdges.Add(Tuple.Create(pathWaypoints[i + 1], pathWaypoints[i])); } else { blockedEdges.Add(tuple); blockedEdges.Add(Tuple.Create(pathWaypoints[i + 1], pathWaypoints[i])); blocked = true; break; } } if (blocked) { continue; } var path = new List <Vector3>(); path.Add(start); foreach (var waypoint in pathWaypoints) { path.Add(waypoint.Position); } path.Add(end); return(path); } return(null); // no path found after many tries } else { List <MyWayPoint> pathWaypoints = null; using (MyWayPoint.BlockedEdgesLock.AcquireSharedUsing()) { pathWaypoints = closestToStart.GetShortestPathTo(closestToEnd, MyWayPoint.BlockedEdgesForBots, true, true); } if (pathWaypoints == null || pathWaypoints.Count == 0) { return(null); // no path } var path = new List <Vector3>(); path.Add(start); foreach (var waypoint in pathWaypoints) { path.Add(waypoint.Position); } path.Add(end); return(path); } } }
void OnAddSelected(MyGuiControlButton sender) { CloseScreen(); // Holds ids for remap IMyEntityIdRemapContext remapContext = new MyEntityIdRemapContext(); var newEntities = new List <MyEntity>(); foreach (var item in m_objectList.GetSelectedItems()) { var builder = m_sectorBuilder.SectorObjects[item.Key]; builder.RemapEntityIds(remapContext); //builder.EntityId = null; // reset entityId because it's new object //builder.Name = null; //var container = builder as MyMwcObjectBuilder_PrefabContainer; // reset entityIds also on prefabs in container //if (container != null) //{ // foreach (var prefabBuilder in container.Prefabs) // { // prefabBuilder.EntityId = null; // prefabBuilder.Name = null; // } //} var entity = CreateFromObjectBuilder(builder); if (entity != null) { newEntities.Add(entity); } } foreach (var e in newEntities) { e.Link(); } // recreate snap point links var snapPointLinks = m_sectorBuilder.SnapPointLinks; foreach (var item in snapPointLinks) { List <MySnapPointLink> group = new List <MySnapPointLink>(); foreach (var link in item.Links) { MyEntity entity; if (!MyEntities.TryGetEntityById(new MyEntityIdentifier(remapContext.RemapEntityId(link.EntityId).Value), out entity)) { continue; } var prefab = entity as MyPrefabBase; if (prefab == null) { continue; } if (string.IsNullOrEmpty(link.SnapPointName)) { if (prefab != null && link.Index < prefab.SnapPoints.Count) { group.Add(new MySnapPointLink(prefab.SnapPoints[link.Index])); } } else { foreach (var snapPoint in prefab.SnapPoints) { if (snapPoint.Name == link.SnapPointName) { group.Add(new MySnapPointLink(snapPoint)); } } } } if (group.Count >= 2) { MyEditor.Static.AddLinkedSnapPoints(group); } } MyWayPointGraph.DeleteNullVerticesFromPaths(); }
public void DoWork() { try { MyEntities.EntityCloseLock.AcquireShared(); if (m_goalEntity == null) { return; } // try the direct path { var directLine = new MyLine(m_startPos, m_goalPos, true); if (MyEntities.GetAnyIntersectionWithLine(ref directLine, m_goalEntity, null, true, true, true, false) == null) { Path.Add(m_startPos); Path.Add(m_goalPos); Message = new StringBuilder().AppendFormat(MyTextsWrapper.Get(MyTextsWrapperEnum.GPSDistance).ToString(), Vector3.Distance(m_startPos, m_goalPos)); return; } } // get the closest waypoint to the goal (ignore visibility) MyWayPoint goal = MyWayPointGraph.GetClosestNonGeneratedWaypoint(m_goalPos); if (goal == null) { return; } // remember which waypoints were visible/invisible from startPos // remember blocked/unblocked edges var visibleFromStartPosCache = new Dictionary <MyWayPoint, bool>(); //var blockedEdges = new HashSet<Tuple<MyWayPoint, MyWayPoint>>(); HashSet <Tuple <MyWayPoint, MyWayPoint> > blockedEdges = null; using (MyWayPoint.BlockedEdgesLock.AcquireSharedUsing()) { blockedEdges = new HashSet <Tuple <MyWayPoint, MyWayPoint> >(MyWayPoint.BlockedEdgesForPlayer); } var unblockedEdges = new HashSet <Tuple <MyWayPoint, MyWayPoint> >(); // get 7 closest visible waypoints to startPos and compute shortest paths from them // first try 7 closest var closestVisibleWaypoints = MyWayPointGraph.GetClosestVisibleWaypoints(m_startPos, m_goalEntity, 7, 7, visibleFromStartPosCache); if (closestVisibleWaypoints.Count == 0 || !FindPathBetweenWaypoints(closestVisibleWaypoints, goal, visibleFromStartPosCache, blockedEdges, unblockedEdges)) { // failure: try 50 closest closestVisibleWaypoints = MyWayPointGraph.GetClosestVisibleWaypoints(m_startPos, m_goalEntity, 12, 50, visibleFromStartPosCache); if (closestVisibleWaypoints.Count == 0 || !FindPathBetweenWaypoints(closestVisibleWaypoints, goal, visibleFromStartPosCache, blockedEdges, unblockedEdges)) { return; // no use } } } finally { if (m_goalEntity != null) { m_goalEntity.OnClose -= goalEntity_OnClose; } MyEntities.EntityCloseLock.ReleaseShared(); } }
// Get the shortest path to the goal vertex using the A* algorithm. Return an empty list if the goal is unreachable. /// <summary>This function needs to be called with EntityCloseLock already acquired, or not an issue.</summary> public List <MyWayPoint> GetShortestPathTo(MyWayPoint goal, HashSet <Tuple <MyWayPoint, MyWayPoint> > blockedEdges = null, bool useGeneratedWaypoints = true, bool useSecretWaypoints = true) { lock (m_shortestPathLock) { if (Connected(this, goal) && (useGeneratedWaypoints || (Save && goal.Save)) && (useSecretWaypoints || (!IsSecret && !goal.IsSecret))) { // use next search id, handle overflow m_searchId++; if (m_searchId == int.MaxValue) { MyWayPointGraph.ResetAllVisitedSearchIds(); m_searchId = 1; } // seen but yet unvisited vertices; add start vertex m_openSet.Clear(); m_fScore = Distance(this, goal); // estimate distance to goal as Euclidean (= consistent) m_gScore = 0; m_cameFrom = this; m_openSet.Add(this); int num = 0; while (m_openSet.Count != 0) { if (num++ > MyWayPointGraph.WaypointCount() + 10) { int maxSearchId = 0; foreach (var v in MyWayPointGraph.GetCopyOfAllWaypoints()) { maxSearchId = Math.Max(maxSearchId, v.m_visitedSearchId); } Debug.Fail(string.Format( "Infinite path search... contact JanK! \nDebug info: set_count={0} start_end_connected={1} current_search_id={2} max_search_id={3}", m_openSet.Count, Connected(this, goal), m_searchId, maxSearchId )); break; } var current = m_openSet.Min; // get vertex with the smallest f (ties: highest g) m_openSet.Remove(current); if (current == goal) { return(ReconstructPath(goal)); // found the shortest path, return it } current.m_visitedSearchId = m_searchId; // mark current as visited using (NeighborsLock.AcquireSharedUsing()) { // look at all neighbors foreach (var neighbor in current.m_neighbors) { if (!useGeneratedWaypoints && !neighbor.Save) { continue; // generated } if (!useSecretWaypoints && neighbor.IsSecret) { continue; // secret } if (neighbor.m_visitedSearchId == m_searchId) { continue; // already visited } if (blockedEdges != null && blockedEdges.Contains(Tuple.Create(current, neighbor))) { continue; // blocked } var gScoreThroughCurrent = current.m_gScore + Distance(current, neighbor); if (m_openSet.Contains(neighbor)) // already seen { if (gScoreThroughCurrent < neighbor.m_gScore) { m_openSet.Remove(neighbor); // path through current is better: remove neighbor and put it back with updated score } else { continue; } } neighbor.m_fScore = gScoreThroughCurrent + Distance(neighbor, goal); neighbor.m_gScore = gScoreThroughCurrent; neighbor.m_cameFrom = current; m_openSet.Add(neighbor); } } } } } return(new List <MyWayPoint>()); // unreachable }
private void ShowWayPoints(MyGuiControlCheckbox sender) { MyHud.ShowDebugWaypoints = !MyHud.ShowDebugWaypoints; MyWayPointGraph.SetVisibilityOfAllWaypoints(MyHud.ShowDebugWaypoints); }
public static Matrix UpdateShapePosition() { if (DetachedVoxelHand != null) { VoxelHandShape.MoveAndRotate(DetachedVoxelHand.WorldMatrix.Translation, DetachedVoxelHand.WorldMatrix); return(DetachedVoxelHand.WorldMatrix); } Matrix world = Matrix.Identity; float minDist = 2 * VoxelHandShape.LocalVolume.Radius; float dist = 2 * minDist; Vector3 from = MyCamera.Position - MyCamera.UpVector * minDist * 0.5f; if (IsProjected) { if (!MyFakes.MWBUILDER) { var line = new MyLine(from, from + MyCamera.ForwardVector * 10000, true); var hit = MyEntities.GetIntersectionWithLine_IgnoreOtherThanSpecifiedClass(ref line, new System.Type[] { typeof(MyVoxelMap) }); if (hit != null) { dist = Vector3.Distance(MyCamera.Position, hit.Value.IntersectionPointInWorldSpace); } else { dist = 5000; } m_conePosition = from + MyCamera.ForwardVector * minDist * 0.7f; Vector3 shapePosition = from + MyCamera.ForwardVector * (dist + VoxelHandShape.LocalVolume.Radius * m_distance * 2); Vector3 shapeForward = Vector3.Normalize(MyCamera.UpVector * minDist * 0.5f + shapePosition - from); Vector3 shapeUp = shapeForward - MyCamera.ForwardVector + MyCamera.UpVector; world = Matrix.CreateWorld(shapePosition, shapeForward, shapeUp); VoxelHandShape.MoveAndRotate(shapePosition, world); return(world); } else { var line = new MyLine(from, from + MyCamera.ForwardVector * 10000, true); var hit = MyEntities.GetIntersectionWithLine_IgnoreOtherThanSpecifiedClass(ref line, new System.Type[] { typeof(MyVoxelMap) }); Vector3 normal = Vector3.Up; dist = 5000; Vector3 shapePosition = from + MyCamera.ForwardVector * dist; if (hit != null) { dist = Vector3.Distance(MyCamera.Position, hit.Value.IntersectionPointInWorldSpace); normal = hit.Value.NormalInWorldSpace; shapePosition = hit.Value.IntersectionPointInWorldSpace; } m_conePosition = from + MyCamera.ForwardVector * minDist * 0.7f; Vector3 shapeUp = normal; Vector3 shapeForward = Vector3.Cross(-MyCamera.LeftVector, shapeUp); float dot = Vector3.Dot(shapeUp, shapeForward); if ((dot > 0.9f) || (dot < -0.9f)) { shapeForward = Vector3.Forward; } shapePosition.X = MyEditorGrid.GetGridStepInMeters() * (float)Math.Round(shapePosition.X / MyEditorGrid.GetGridStepInMeters()); shapePosition.Y = MyEditorGrid.GetGridStepInMeters() * (float)Math.Round(shapePosition.Y / MyEditorGrid.GetGridStepInMeters()); shapePosition.Z = MyEditorGrid.GetGridStepInMeters() * (float)Math.Round(shapePosition.Z / MyEditorGrid.GetGridStepInMeters()); world = Matrix.CreateWorld(shapePosition, shapeForward, shapeUp); VoxelHandShape.MoveAndRotate(shapePosition, world); return(world); } } else if (IsProjectedToWaypoints) { //Lets find projection on closest collision with waypoint edge from = MyCamera.Position - MyCamera.UpVector * 10.5f; m_conePosition = from + MyCamera.ForwardVector * 10.7f; Vector3 shapePosition = from + MyCamera.ForwardVector * m_distance; List <Tuple <MyWayPoint, MyWayPoint> > edges = MyWayPointGraph.GetAllEdgesInSphere(shapePosition, VoxelHandShape.LocalVolume.Radius * 2); Tuple <MyWayPoint, MyWayPoint> closestEdge = null; float minDistance = float.MaxValue; Vector3 closestPoint = shapePosition; float distFromFirstWaypoint = 0; foreach (Tuple <MyWayPoint, MyWayPoint> edge in edges) { Vector3 linePos1 = edge.Item1.Position; Vector3 linePos2 = edge.Item2.Position; Vector3 point = MyUtils.GetClosestPointOnLine(ref linePos1, ref linePos2, ref shapePosition, out distFromFirstWaypoint); float distance = Vector3.Distance(shapePosition, point); if (distance < minDistance) { minDistance = distance; closestEdge = edge; closestPoint = point; } } if (closestEdge != null) { shapePosition = closestPoint; Vector3 shapeForward = Vector3.Normalize(shapePosition - from); Vector3 shapeUp = MyCamera.UpVector; world = Matrix.CreateWorld(shapePosition, shapeForward, shapeUp); VoxelHandShape.MoveAndRotate(shapePosition, world); MyWayPoint firstWaypoint = null; MyWayPoint secondWaypoint = null; float edgeDistance = Vector3.Distance(closestEdge.Item1.Position, closestEdge.Item2.Position); if (closestEdge.Item1.Position.Y < closestEdge.Item2.Position.Y) { firstWaypoint = closestEdge.Item1; secondWaypoint = closestEdge.Item2; } else { firstWaypoint = closestEdge.Item2; secondWaypoint = closestEdge.Item1; distFromFirstWaypoint = edgeDistance - distFromFirstWaypoint; } float edgeRatio = edgeDistance > 0 ? distFromFirstWaypoint / edgeDistance : 0; Quaternion quaternion1 = Quaternion.CreateFromRotationMatrix(closestEdge.Item1.WorldMatrix); Quaternion quaternion2 = Quaternion.CreateFromRotationMatrix(closestEdge.Item2.WorldMatrix); Quaternion resultQuaternion = Quaternion.Lerp(quaternion1, quaternion2, edgeRatio); Matrix resultMatrix = Matrix.CreateFromQuaternion(resultQuaternion); resultMatrix.Translation = shapePosition; VoxelHandShape.MoveAndRotate(shapePosition, resultMatrix); return(resultMatrix); } } if (MyFakes.MWBUILDER) { from = MyCamera.Position; m_conePosition = from + MyCamera.ForwardVector * 10.7f; /* * //Vector3 planeNormal = new Vector3(MyCamera.ForwardVector.X, 0, MyCamera.ForwardVector.Z); * Vector3 planeNormal = new Vector3(0, MyCamera.ForwardVector.Y, MyCamera.ForwardVector.Z); * * * planeNormal.Normalize(); * Vector3 planePoint = planePoint = from + planeNormal * m_distance; * planeNormal = -planeNormal; * * Plane plane = new Plane(planeNormal, -Vector3.Dot(planeNormal, planePoint)); * * Ray r = new Ray(from, MyCamera.ForwardVector); * float? intr = r.Intersects(plane); */ // if (intr.HasValue) { Vector3 shapePosition = from + MyCamera.ForwardVector * m_distance; Vector3 shapeForward = Vector3.Forward; Vector3 shapeUp = Vector3.Up; shapePosition.X = MyEditorGrid.GetGridStepInMeters() * (float)Math.Round(shapePosition.X / MyEditorGrid.GetGridStepInMeters()); shapePosition.Y = MyEditorGrid.GetGridStepInMeters() * (float)Math.Round(shapePosition.Y / MyEditorGrid.GetGridStepInMeters()); shapePosition.Z = MyEditorGrid.GetGridStepInMeters() * (float)Math.Round(shapePosition.Z / MyEditorGrid.GetGridStepInMeters()); world = Matrix.CreateWorld(shapePosition, shapeForward, shapeUp); VoxelHandShape.MoveAndRotate(shapePosition, world); } } else { from = MyCamera.Position - MyCamera.UpVector * 10.5f; m_conePosition = from + MyCamera.ForwardVector * 10.7f; Vector3 shapePosition = from + MyCamera.ForwardVector * m_distance; Vector3 shapeForward = Vector3.Normalize(/*MyCamera.UpVector * minDist * 0.5f*/ shapePosition - from); Vector3 shapeUp = /*shapeForward - MyCamera.ForwardVector +*/ MyCamera.UpVector; world = Matrix.CreateWorld(shapePosition, shapeForward, shapeUp); VoxelHandShape.MoveAndRotate(shapePosition, world); } return(world); }