/// <summary> /// Pushes the specified navigable to the top of the stack. /// </summary> /// <param name="navigable">The navigable to push to the top ofthe stack</param> public void Push(INavigable navigable) { if (!NavigationStack.ToList().Any(nav => nav.NavigableID == navigable.NavigableID)) { NavigationStack.Push(navigable); } }
public static void MoveToAggroTarget(Entity entity, Entity target, INavigable navigator) { if (target == null) { var closestEnemyBuilding = GetClosestEnemyBuilding(entity); if (closestEnemyBuilding != null) { navigator.MoveTo(closestEnemyBuilding.transform.position); } else { navigator.CancelMove(); } } else { var targetPositionIgnoreY = target.transform.position; targetPositionIgnoreY.y = entity.transform.position.y; // At this point, if we have an aggro target, move to attack it. var distance = Vector3.Distance(entity.transform.position, targetPositionIgnoreY); if (distance < entity.AttackRange) { navigator.CancelMove(); // Attack! } else { navigator.MoveTo(target.transform.position); } } }
private void ValidateINavigableExists(INavigable iNavigagble, string definition) { if (!iNavigagble.WaitForExists()) { throw new Exception($"The {definition} \"{iNavigagble.ToString()}\" was not found."); } }
/// <summary>Retrieve the Nth child of a given type</summary> /// <typeparam name="T">The desired node type</typeparam> /// <param name="_this">The parent node</param> /// <param name="idx">Zero-based index, 0 = first child, 1 = second child</param> /// <returns>The Nth child of a given type</returns> public static T GetChildOfType <T>(this INavigable _this, int idx = 0) where T : class { if (_this.Children == null) { return(null); } int i = 0; foreach (INavigable child in _this.Children) { if (child is T) { if (i == idx) { return(child as T); } else { i++; } } } return(null); }
/// <summary> /// Navigate to a new screen that implements INavigable. /// The new screen is initialized with the given state. /// The previous screen is saved on the screen stack /// </summary> /// <param name="screen"></param> /// <param name="state"></param> public static void navigate(UserControl screen, MovieSource source, params object[] state) { //Check if the window has been set checkWindowSet(); //Check if the screen is actually navigable INavigable navScreen = screen as INavigable; if (navScreen == null) { throw new Exception("UserControl is not INavigable"); } //Save the previous screen if (currentScreenSet) { screenStack.Push(currentScreen); } //Set the new screen setCurrentScreen(screen); //Set the screens state navScreen.useState(state); navScreen.setSource(source); navScreen.resume(); }
private INavigable GetFirstINavigableExisting(IEnumerable <INavigable> iNavigables, CancellationToken cancellationToken) { INavigable match = null; using (var internalCts = new CancellationTokenSource()) using (var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(internalCts.Token, cancellationToken)) { ParallelOptions po = new ParallelOptions(); po.CancellationToken = linkedCts.Token; try { Parallel.ForEach(iNavigables, po, (x, state) => { var neighbor = GetExistingNavigable(x, po.CancellationToken); if (neighbor != null) { state.Break(); match = neighbor; internalCts.Cancel(); } }); } catch (OperationCanceledException) { cancellationToken.ThrowIfCancellationRequested(); } } if (match == null) { throw new NavigableNotFoundException(iNavigables); } return(match); }
/// <inheritdoc /> public IObservable <Unit> PushPage( INavigable navigableViewModel, INavigationParameter parameter, string contract = null, bool resetStack = false, bool animate = true) { if (navigableViewModel == null) { throw new ArgumentNullException(nameof(navigableViewModel)); } if (parameter == null) { throw new ArgumentNullException(nameof(parameter)); } return(View .PushPage(navigableViewModel, contract, resetStack, animate) .Do(_ => { navigableViewModel .WhenNavigatingTo(parameter) .ObserveOn(View.MainThreadScheduler) .Subscribe(navigating => Logger.Debug($"Called `WhenNavigatingTo` on '{navigableViewModel.Id}' passing parameter {parameter}")); AddToStackAndTick(PageSubject, navigableViewModel, resetStack); Logger.Debug($"Added page '{navigableViewModel.Id}' (contract '{contract}') to stack."); navigableViewModel .WhenNavigatedTo(parameter) .ObserveOn(View.MainThreadScheduler) .Subscribe(navigated => Logger.Debug($"Called `WhenNavigatedTo` on '{navigableViewModel.Id}' passing parameter {parameter}")); })); }
/// <summary>Retrieve all children nodes of the given node that match the specified type</summary> /// <typeparam name="T">The type we wish to find</typeparam> /// <param name="node">The root node of the subtree we are searching</param> /// <returns>A list containing all nodes matching the criteria</returns> public static List <T> FindAllChildren <T>(this INavigable node) where T : class { List <T> results = new List <T>(); FindAllChildrenHelper <T>(node, results); return(results); }
public void WhenNoPathGraphShouldNoPath(HashSet <INavigable> nodes, INavigable origin, INavigable destination, List <INavigable> expected) { IGraph iut = new Graph(nodes); var actual = iut.GetShortestPath(origin, destination); Assert.Equal(expected, actual); }
/// <summary> /// Performs action to step to the next Navigable in the resolve path. /// The next Navigable can be a consecutive or rebased to the current Navigable. /// </summary> /// <param name="actionToNextINavigable">A Dictionary of actions to step to the next Navigable.</param> /// <param name="next">The next Navigable.</param> /// <param name="cancellationToken">The CancellationToken to interrupt the task as soon as possible.</param> /// <returns>If <c>None</c> or <c>null</c> then the GlobalCancellationToken will be used.</param> /// <returns>The next Navigable or <see cref="Last"/> if the final destination has been reached /// in the action to next Navigable (in case of Resolve() for example).</returns> /// <exception cref="UnregistredNeighborException">Throws when next Navigable is not registred in Nodes.</exception> public INavigable StepToNext( INavigable currentNode, INavigable next, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var navigableAndAction = currentNode.GetActionToNext().Where(x => x.Key == next).SingleOrDefault(); if (navigableAndAction.Key == null) { throw new UnregistredNeighborException(next, MethodBase.GetCurrentMethod().DeclaringType); } var actionToOpen = navigableAndAction.Value; actionToOpen.Invoke(cancellationToken); if (gotoDestination != null) { var dynamicPath = Map.DynamicNeighbors.Where(x => x.Origin == currentNode).SingleOrDefault(); if (dynamicPath != null) { Resolve(dynamicPath.Alternatives, next, cancellationToken); } WaitForExist(next, cancellationToken); return(next); } else { return(Log.Last); // in case Resolve() was executed in last Invoke, destination is already reached. } }
static NavigationPoint GetNavPointForDoc(Document doc) { if (doc == null) { return(null); } NavigationPoint point = null; INavigable navigable = doc.GetContent <INavigable> (); if (navigable != null) { point = navigable.BuildNavigationPoint(); if (point != null) { return(point); } } IEditableTextBuffer editBuf = doc.GetContent <IEditableTextBuffer> (); if (editBuf != null) { point = new TextFileNavigationPoint(doc, editBuf); if (point != null) { return(point); } } return(new DocumentNavigationPoint(doc)); }
/// <inheritdoc/> public IObservable <Unit> PushPopup( INavigable viewModel, INavigationParameter navigationParameter, string?contract = null, bool animate = true) { if (viewModel == null) { throw new ArgumentNullException(nameof(viewModel)); } if (navigationParameter == null) { throw new ArgumentNullException(nameof(navigationParameter)); } return(Observable .Start(() => LocatePopupFor(viewModel, contract), CurrentThreadScheduler.Instance) .ObserveOn(CurrentThreadScheduler.Instance) .Do(popup => popup.ViewModel.InvokeViewModelAction <INavigating>(x => x.WhenNavigatingTo(navigationParameter))) .Select(popup => Observable .FromAsync(() => _popupNavigation.PushAsync(popup, animate)) .Do(_ => popup.ViewModel.InvokeViewModelAction <INavigated>(x => x.WhenNavigatedTo(navigationParameter)))) .Switch() .Do(_ => { AddToStackAndTick(PopupSubject, viewModel, false); Logger.Debug($"Added page '{viewModel.Id}' (contract '{contract}') to stack."); })); }
/// <summary> /// Go to the destination from the last Navigable, using the shortest way. /// </summary> /// <param name="destination">The destination.</param> /// <param name="timeout">A timeout to interrupt the task as soon as possible, /// in concurrence of GlobalCancellationToken.</param> /// <returns>This Browser.</returns> /// <exception cref="UninitializedGraphException">Thrown when the Graph is unitialized.</exception> /// <exception cref="PathNotFoundException">Thrown when no path was found between the origin and the destination.</exception> public IBrowser Goto( INavigable destination, TimeSpan timeout) { using var cancellationTokenSource = new CancellationTokenSource(timeout); return(Goto(destination, cancellationTokenSource.Token)); }
/// <inheritdoc /> public IObservable <Unit> PushModal(INavigable navigableModal, INavigationParameter parameter, string?contract = null, bool withNavigationPage = true) { if (navigableModal == null) { throw new ArgumentNullException(nameof(navigableModal)); } if (parameter == null) { throw new ArgumentNullException(nameof(parameter)); } navigableModal .WhenNavigatingTo(parameter) .ObserveOn(View.MainThreadScheduler) .Subscribe(navigating => Logger.Debug($"Called `WhenNavigatingTo` on '{navigableModal.Id}' passing parameter {parameter}")); return(View .PushModal(navigableModal, contract, withNavigationPage) .Do(_ => { AddToStackAndTick(ModalSubject, navigableModal, false); Logger.Debug("Added modal '{modal.Id}' (contract '{contract}') to stack."); navigableModal .WhenNavigatedTo(parameter) .ObserveOn(View.MainThreadScheduler) .Subscribe(navigated => Logger.Debug($"Called `WhenNavigatedTo` on '{navigableModal.Id}' passing parameter {parameter}")); })); }
public static bool CanCompleat(INavigable navigable, INode start) { if (FindPath(navigable, start) != null) { return(true); } return(false); }
/// <summary> /// Wait until this navigable is ready. /// </summary> /// <param name="navigable">The Navigable.</param> /// <param name="cancellationToken">A CancellationToken to interrupt the task as soon as possible, /// in concurrence of GlobalCancellationToken.</param> /// <returns><c>true</c> if ready before any CancellationToken is canceled. /// Otherwise <c>false</c>.</returns> public bool WaitForReady(INavigable navigable, CancellationToken cancellationToken) { using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource( GlobalCancellationToken, cancellationToken); Navigator.WaitForReady(navigable, linkedCts.Token); return(!linkedCts.Token.IsCancellationRequested); }
/// <summary> /// Get the shortest path from the origin to the destination. /// </summary> /// <param name="origin">The origin.</param> /// <param name="destination">The destination.</param> /// <returns>The List of Navigable from the origin to the destination.</returns> /// <exception cref="UninitializedGraphException">Thrown when the Graph is unitialized.</exception> public List <INavigable> GetShortestPath(INavigable origin, INavigable destination) { if (Map.Graph == null) { throw new UninitializedGraphException(); } return(Map.Graph.GetShortestPath(origin, destination)); }
private Models.Navigation ConvertToNavItem(INavigable navigable) { return(new Models.Navigation { NavigationTitle = new HtmlString(mvcContext.GlassHtml.Editable(navigable, x => x.Title)), NavigationUrl = navigable.NavigationUrl != null ? navigable.NavigationUrl.Url : "", Navigations = navigable.Children.Any() ? navigable.Children.Select(nav => ConvertToNavItem(nav)).ToList() : null }); }
private void closeToolStripMenuItem_Click(object sender, EventArgs e) { openFile = null; fileNavigator.Nodes.Clear(); propertyGrid1.SelectedObject = null; this.Text = ApplicationName; fileNavigator_AfterSelect(null, null); }
/// <summary> /// Get a INavigagble that exists from a List >INavigable< after the UI action is completed. /// </summary> /// <param name="origin">The origin.</param> /// <param name="onActionAlternatives">The OnActionAlternatives.</param> /// <returns>The matching INavigable, otherwise <c>null</c>.</returns> public virtual INavigable GetINavigableAfterAction(INavigable origin, IOnActionAlternatives onActionAlternatives) { ValidateINavigableExists(origin, "origin"); INavigable match = null; onActionAlternatives.UIAction.Invoke(); match = GetFirstINavigableExisting(onActionAlternatives.INavigables); return(match); }
private INavigable GetExistingNavigable(INavigable navigable, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return(null); } bool exists = navigable.PublishStatus().Exist.Value; return(exists ? navigable : null); }
// TODO: 11. Diseñar la vista de detalle con Gorilla Player // TODO: 12. Assign the Binding Context in the xaml page MovieDetailView public MovieDetailView(uint movieId) { InitializeComponent(); _vm = App.Locator.MovieDetail; _vm.Activate(movieId); _vm.Start(); this.BindingContext = _vm; }
/// <summary> /// Wait until the navigable is ready. /// </summary> /// <param name="navigable">The navigable.</param> /// <param name="cancellationToken">The CancellationToken to interrupt the task as soon as possible.</param> public void WaitForReady(INavigable navigable, CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { if (navigable.PublishStatus().Ready.Value) { return; } } }
/// <inheritdoc/> public IObservable<Unit> PushPopup( INavigable viewModel, INavigationParameter navigationParameter, string? contract = null, bool animate = true) => Observable.Create<Unit>(observer => { if (viewModel == null) { throw new ArgumentNullException(nameof(viewModel)); } if (navigationParameter == null) { throw new ArgumentNullException(nameof(navigationParameter)); } var compositeDisposable = new CompositeDisposable(); Observable .Start(() => LocatePopupFor(viewModel, contract), CurrentThreadScheduler.Instance) .ObserveOn(CurrentThreadScheduler.Instance) .Select(popup => { popup .ViewModel? .InvokeViewModelAction<INavigating>(x => x.WhenNavigatingTo(navigationParameter) .Subscribe() .DisposeWith(compositeDisposable)); return popup; }) .Select(popup => Observable .FromAsync(() => _popupNavigation.PushAsync(popup, animate)) .Select(_ => popup .ViewModel? .InvokeViewModelAction<INavigated>(x => x.WhenNavigatedTo(navigationParameter) .Subscribe() .DisposeWith(compositeDisposable)))) .Switch() .Do(_ => { AddToStackAndTick(PopupSubject, viewModel, false); Logger.Debug($"Added page '{viewModel.Id}' (contract '{contract}') to stack."); }) .Select(_ => Unit.Default) .Subscribe(observer) .DisposeWith(compositeDisposable); return Disposable.Create(() => compositeDisposable.Dispose()); });
// TODO: 11. Diseñar la vista de detalle con Gorilla Player // TODO: 12. Assign the Binding Context in the xaml page MovieDetailView public MovieDetailView (uint movieId) { InitializeComponent (); _vm = App.Locator.MovieDetail; _vm.Activate (movieId); _vm.Start (); this.BindingContext = _vm; }
private async Task HandleDeactivationAsync(INavigable viewModel) { string viewModelName = viewModel.GetType().Name; _logging.WriteLine($"Executing {nameof(INavigable.DeactivateAsync)} from new ViewModel ({viewModelName})."); var suspensionState = GetSuspensionStateForPage(viewModelName); await viewModel.DeactivateAsync(suspensionState); SetTimestampForSuspensionState(suspensionState); }
private static void PageLoaded(object sender, RoutedEventArgs e) { Page page = (Page)sender; INavigable navSource = GetSource(page); if (navSource != null) { navSource.NavigationService = new NavigationService(page.NavigationService); } }
// after navigate async Task NavigateFromAsync(Page page, INavigable dataContext, bool suspending) { DebugWrite($"Suspending: {suspending}"); dataContext.NavigationService = this; dataContext.Dispatcher = this.GetDispatcherWrapper(); dataContext.SessionState = BootStrapper.Current.SessionState; var pageState = FrameFacadeInternal.PageStateSettingsService(page.GetType()).Values; await dataContext.OnNavigatedFromAsync(pageState, suspending); }
/// <summary>Recursive function to implement FindAllChildren{T}</summary> private static void FindAllChildrenHelper <T>(INavigable node, List <T> results) where T : class { if (node is T) { results.Add(node as T); } if (node.Children == null) { return; } node.Children.ForEach(x => FindAllChildrenHelper <T>(x, results)); }
public async Task SetupViewModelAsync(INavigationService service, INavigable viewmodel) { Services.NavigationService.NavigationService.DebugWrite(); if (viewmodel == null) { return; } viewmodel.NavigationService = service; viewmodel.Dispatcher = service.GetDispatcherWrapper(); viewmodel.SessionState = await Services.StateService.StateService.GetStateAsync(StateService.StateTypes.Session); }
/// <summary>Attempts to load a section by guessing based on the next 8 bytes</summary> /// <param name="reader">A BinaryReaderEx positioned at the start of a section</param> /// <returns>A newly created and loaded section</returns> public static SectionBase LoadSection(BinaryReaderEx reader, INavigable parent) { SectionBase result = CreateSection(reader); if (result != null) { result.Parent = parent; result.LoadSection(reader); } return(result); }
public static void NavigateTo(INavigable item) { if (item != null && item.NavigationInfo != null) { if (item.NavigationInfo.NavigationType == NavigationType.Page) { var navParam = item.NavigationInfo.IncludeState ? item : null; NavigationService.NavigateToPage(item.NavigationInfo.TargetPage, navParam); } else if (item.NavigationInfo.NavigationType == NavigationType.DeepLink) { NavigationService.NavigateTo(item.NavigationInfo.TargetUri).RunAndForget(); } else { throw new NotSupportedException("Navigation type provided is not supported."); } } }
public static void NavigateTo(INavigable item) { if (item != null && item.NavigationInfo != null) { if (item.NavigationInfo.Type == NavigationType.Page) { var navParam = item.NavigationInfo.IncludeState ? item : null; NavigationService.NavigateToPage(item.NavigationInfo.TargetPage, navParam); } else if (item.NavigationInfo.Type == NavigationType.DeepLink) { NavigationService.NavigateTo(item.NavigationInfo.TargetUri).FireAndForget(); } else { throw new ArgumentOutOfRangeException("NavigationInfo.Type"); } } }
private void __ValidateItemWithinSystem(SystemItem system, INavigable item) { float systemRadiusSqrd = system.Radius * system.Radius; float itemDistanceFromSystemCenterSqrd = Vector3.SqrMagnitude(item.Position - system.Position); if (itemDistanceFromSystemCenterSqrd > systemRadiusSqrd) { D.Warn("ItemDistanceFromSystemCenterSqrd: {0} > SystemRadiusSqrd: {1}!", itemDistanceFromSystemCenterSqrd, systemRadiusSqrd); } }
private void openToolStripMenuItem_Click(object sender, EventArgs e) { if (openFileDialog.ShowDialog() != System.Windows.Forms.DialogResult.OK) { return; } var result = DatDigger.Sections.SectionLoader.OpenFile(openFileDialog.FileName); if (result == null) { MessageBox.Show("Unable to open file " + openFileDialog.FileName); return; } openFile = result; // Build Tree View TreeNode rootNode = BuildNavigator(openFile); rootNode.ExpandAll(); fileNavigator.Nodes.Add(rootNode); this.Text = String.Format("{0} - {1}", ApplicationName, openFileDialog.FileName); }
private TreeNode BuildNavigator(INavigable item) { TreeNode node = new TreeNode(item.DisplayName); node.Tag = item; if (item.Children != null) { foreach (INavigable child in item.Children) { if (child != null) { TreeNode childNode = BuildNavigator(child); node.Nodes.Add(childNode); } } } return node; }
/// <summary> /// Records the AutoPilot values needed to plot a course. /// </summary> /// <param name="autoPilotTgt">The target this AutoPilot is being engaged to reach.</param> /// <param name="autoPilotSpeed">The speed the autopilot should travel at.</param> protected void RecordAutoPilotCourseValues(INavigable autoPilotTgt, Speed autoPilotSpeed) { Utility.ValidateNotNull(autoPilotTgt); D.Assert(!_inValidAutoPilotSpeeds.Contains(autoPilotSpeed), "{0} speed of {1} for autopilot is invalid.".Inject(Name, autoPilotSpeed.GetValueName())); AutoPilotTarget = autoPilotTgt; AutoPilotSpeed = autoPilotSpeed; }
/// <summary> /// Checks for an obstacle enroute to the provided <c>destination</c>. Returns true if one /// is found that requires immediate action and provides the detour to avoid it, false otherwise. /// </summary> /// <param name="destination">The current destination. May be the AutoPilotTarget or an obstacle detour.</param> /// <param name="castingDistanceSubtractor">The distance to subtract from the casted Ray length to avoid /// detecting any ObstacleZoneCollider around the destination.</param> /// <param name="detour">The obstacle detour.</param> /// <param name="destinationOffset">The offset from destination.Position that is our destinationPoint.</param> /// <returns> /// <c>true</c> if an obstacle was found and a detour generated, false if the way is effectively clear. /// </returns> protected bool TryCheckForObstacleEnrouteTo(INavigable destination, float castingDistanceSubtractor, out INavigable detour, Vector3 destinationOffset = default(Vector3)) { Utility.ValidateNotNegative(castingDistanceSubtractor); int iterationCount = Constants.Zero; return TryCheckForObstacleEnrouteTo(destination, castingDistanceSubtractor, destinationOffset, out detour, ref iterationCount); }
private bool TryCheckForObstacleEnrouteTo(INavigable destination, float castingDistanceSubtractor, Vector3 destinationOffset, out INavigable detour, ref int iterationCount) { D.AssertException(iterationCount++ < 10, "IterationCount {0} >= 10.", iterationCount); detour = null; Vector3 vectorToDestPoint = (destination.Position + destinationOffset) - Position; float currentDestPtDistance = vectorToDestPoint.magnitude; if (currentDestPtDistance <= castingDistanceSubtractor) { return false; } Vector3 currentDestPtBearing = vectorToDestPoint.normalized; float rayLength = currentDestPtDistance - castingDistanceSubtractor; Ray ray = new Ray(Position, currentDestPtBearing); RaycastHit hitInfo; if (Physics.Raycast(ray, out hitInfo, rayLength, _avoidableObstacleZoneOnlyLayerMask.value)) { // there is an AvoidableObstacleZone in the way. Warning: hitInfo.transform returns the rigidbody parent since // the obstacleZone trigger collider is static. UNCLEAR if this means it forms a compound collider as this is a raycast var obstacleZoneGo = hitInfo.collider.gameObject; var obstacleZoneHitDistance = hitInfo.distance; IAvoidableObstacle obstacle = obstacleZoneGo.GetSafeFirstInterfaceInParents<IAvoidableObstacle>(excludeSelf: true); if (obstacle == destination) { D.LogBold(ShowDebugLog, "{0} encountered obstacle {1} which is the destination. \nRay length = {2:0.00}, DistanceToHit = {3:0.00}, DestOffset = {4}, CastSubtractor = {5:0.00}.", Name, obstacle.FullName, rayLength, obstacleZoneHitDistance, destinationOffset, castingDistanceSubtractor); HandleObstacleFoundIsTarget(obstacle); return false; } else { D.Log(ShowDebugLog, "{0} encountered obstacle {1} at {2} when checking approach to {3}. \nRay length = {4:0.#}, DistanceToHit = {5:0.#}.", Name, obstacle.FullName, obstacle.Position, destination.FullName, rayLength, obstacleZoneHitDistance); } if (!TryGenerateDetourAroundObstacle(obstacle, hitInfo, out detour)) { return false; } INavigable newDetour; float detourCastingDistanceSubtractor = Constants.ZeroF; // obstacle detours don't have ObstacleZones Vector3 detourOffset = destinationOffset; if (TryCheckForObstacleEnrouteTo(detour, detourCastingDistanceSubtractor, detourOffset, out newDetour, ref iterationCount)) { D.Log(ShowDebugLog, "{0} found another obstacle on the way to detour {1}.", Name, detour.FullName); detour = newDetour; } return true; } return false; }
/// <summary> /// Tries to generate a detour around the provided obstacle. Returns <c>true</c> if a detour was generated, <c>false</c> otherwise. /// </summary> /// <param name="obstacle">The obstacle.</param> /// <param name="zoneHitInfo">The zone hit information.</param> /// <param name="detour">The detour.</param> /// <returns></returns> protected abstract bool TryGenerateDetourAroundObstacle(IAvoidableObstacle obstacle, RaycastHit zoneHitInfo, out INavigable detour);
/// <summary> /// Refreshes the course. /// </summary> /// <param name="mode">The mode.</param> /// <param name="waypoint">The optional waypoint.</param> protected abstract void RefreshCourse(CourseRefreshMode mode, INavigable waypoint = null);
protected float GetDistanceTo(INavigable target) { return Vector3.Distance(PositionForDistanceMeasurements, target.Position); }
public static void SetSource(DependencyObject obj, INavigable value) { obj.SetValue(SourceProperty, value); }