/// <summary> /// Triggers scene manipulation using the given lambda action. /// The action gets processed directly before scene update process. /// /// Be careful: The action is called by worker-threads of SeeingSharp! /// </summary> /// <param name="manipulatorAction">The action which is able to manipulate the scene.</param> public Task ManipulateSceneAsync(Action <SceneManipulator> manipulatorAction) { manipulatorAction.EnsureNotNull(nameof(manipulatorAction)); var manipulator = new SceneManipulator(this); return(this.PerformBeforeUpdateAsync(() => { try { manipulator.IsValid = true; manipulatorAction(manipulator); } finally { manipulator.IsValid = false; } })); }
internal override void DetachInternal(SceneManipulator manipulator, ViewInformation?correspondingView, object?componentContext) { this.Detach(manipulator, correspondingView); }
/// <summary> /// Detaches this component from a scene. /// Be careful, this method gets called from a background thread of SeeingSharp! /// It may also be called from multiple scenes in parallel. /// </summary> /// <param name="manipulator">The manipulator of the scene we attach to.</param> /// <param name="correspondingView">The view which attached this component.</param> protected abstract void Detach(SceneManipulator manipulator, ViewInformation?correspondingView);
internal override object?AttachInternal(SceneManipulator manipulator, ViewInformation?correspondingView) { this.Attach(manipulator, correspondingView); return(null); }
/// <summary> /// Internal method for updating all scene components. /// </summary> /// <param name="updateState">Current update state.</param> internal void UpdateSceneComponents(SceneRelatedUpdateState updateState) { // Update all components var attachedComponentsCount = _attachedComponents.Count; for (var loop = 0; loop < attachedComponentsCount; loop++) { _attachedComponents[loop].Component.UpdateInternal( updateState, _attachedComponents[loop].CorrespondingView, _attachedComponents[loop].Context); } // Attach all components which are coming in while (_componentRequests.TryDequeue(out var actRequest)) { SceneComponentInfo actComponent; int actComponentIndex; switch (actRequest.RequestType) { case SceneComponentRequestType.Attach: if (actRequest.Component == null) { continue; } if (this.TryGetAttachedComponent( actRequest.Component, actRequest.CorrespondingView, out actComponent, out actComponentIndex)) { // We've already attached this component, so skip this request continue; } // Trigger removing of all components with the same group like the new one // (new components replace old components with same group name) if (!string.IsNullOrEmpty(actRequest.Component.ComponentGroup)) { foreach (var actObsoleteComponent in this.GetExistingComponentsByGroup( actRequest.Component.ComponentGroup, actRequest.Component.IsViewSpecific ? actRequest.CorrespondingView : null)) { _componentRequests.Enqueue(new SceneComponentRequest { RequestType = SceneComponentRequestType.Detach, Component = actObsoleteComponent.Component, CorrespondingView = actObsoleteComponent.CorrespondingView }); } } var actManipulator = new SceneManipulator(_owner); actManipulator.IsValid = true; try { var newRegisteredComponentInfo = new SceneComponentInfo { Component = actRequest.Component, CorrespondingView = actRequest.CorrespondingView, Context = actRequest.Component.AttachInternal( actManipulator, actRequest.CorrespondingView) }; // Register the component on local list of attached ones _attachedComponents.Add(newRegisteredComponentInfo); } finally { actManipulator.IsValid = false; } break; case SceneComponentRequestType.Detach: if (actRequest.Component == null) { continue; } if (!this.TryGetAttachedComponent( actRequest.Component, actRequest.CorrespondingView, out actComponent, out actComponentIndex)) { // We don't have any component that is like the requested one continue; } actManipulator = new SceneManipulator(_owner); actManipulator.IsValid = true; try { actComponent.Component.DetachInternal( actManipulator, actComponent.CorrespondingView, actComponent.Context); // RemoveObject the component _attachedComponents.RemoveAt(actComponentIndex); } finally { actManipulator.IsValid = false; } break; case SceneComponentRequestType.DetachAll: while (_attachedComponents.Count > 0) { actManipulator = new SceneManipulator(_owner) { IsValid = true }; try { actComponent = _attachedComponents[0]; actComponent.Component.DetachInternal( actManipulator, actComponent.CorrespondingView, actComponent.Context); // RemoveObject the component _attachedComponents.RemoveAt(0); } finally { actManipulator.IsValid = false; } } break; default: throw new SeeingSharpException($"Unknown {nameof(SceneComponentRequestType)}: {actRequest.RequestType}"); } } }