예제 #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Scene" /> class.
        /// </summary>
        public Scene()
        {
            _perFrameData = new CBPerFrame();

            this.TransformMode2D     = Graphics2DTransformMode.Custom;
            this.CustomTransform2D   = Matrix3x2.Identity;
            this.VirtualScreenSize2D = new SizeF();

            _sceneComponents = new SceneComponentFlyweight(this);

            _sceneLayers = new UnsafeList <SceneLayer>();
            _sceneLayers.Add(new SceneLayer(DEFAULT_LAYER_NAME, this));
            this.Layers = new ReadOnlyCollection <SceneLayer>(_sceneLayers);

            _drawing2DLayers = new List <Custom2DDrawingLayer>();

            _asyncInvokesBeforeUpdate          = new ConcurrentQueue <Action>();
            _asyncInvokesUpdateBesideRendering = new ConcurrentQueue <Action>();

            _registeredResourceDicts = new IndexBasedDynamicCollection <ResourceDictionary>();
            _registeredViews         = new IndexBasedDynamicCollection <ViewInformation>();
            _renderParameters        = new IndexBasedDynamicCollection <SceneRenderParameters>();

            this.CachedUpdateState = new SceneRelatedUpdateState();

            // Try to initialize this scene object
            this.InitializeResourceDictionaries();
        }
예제 #2
0
        /// <summary>
        /// Performs "update-beside-render" for this layer.
        /// </summary>
        /// <param name="updateState">Current update state.</param>
        internal void UpdateBesideRender(SceneRelatedUpdateState updateState)
        {
            updateState.SceneLayer = this;
            _isInUpdateBeside      = true;
            try
            {
                // Now update all view specific references
                foreach (var actViewSubset in _viewSubsets)
                {
                    actViewSubset.UpdateBesideRender(updateState, _sceneObjectsForSingleUpdateCall);
                }
            }
            finally
            {
                updateState.SceneLayer = null;
                _isInUpdateBeside      = false;

                // Some work after whole update processes
                _sceneObjectsForSingleUpdateCall.Clear();
            }
        }
        /// <summary>
        /// Update logic beside rendering.
        /// </summary>
        /// <param name="updateState">The update state.</param>
        /// <param name="sceneObjectsForSingleUpdateCall">A collection of scene objects for a single update call. These are normally a list of newly inserted static objects.</param>
        internal void UpdateBesideRender(SceneRelatedUpdateState updateState, Queue <SceneObject> sceneObjectsForSingleUpdateCall)
        {
            var filters = this.ViewInformation.FiltersInternal;

            _tmpChangedVisibilities.Clear();

            // Perform some pre-logic on filters
            var anyFilterChanged = false;

            foreach (var actFilter in filters)
            {
                actFilter.SetEnvironmentData(_sceneLayer, this.ViewInformation);
                if (actFilter.ConfigurationChangedInternal)
                {
                    anyFilterChanged = true;
                }
            }

            // Check whether we have to update all objects
            var refreshAllObjects = this.ViewInformation.Camera.StateChanged || anyFilterChanged;

            // Perform filtering for all standard objects
            var allObjects       = _sceneLayer.ObjectsInternal;
            var allObjectsLength = allObjects.Count;

            if (allObjectsLength > 0)
            {
                var allObjectsArray = allObjects.BackingArray;
                for (var loop = 0; loop < allObjectsLength; loop++)
                {
                    var actObject = allObjectsArray[loop];
                    if (actObject == null)
                    {
                        continue;
                    }

                    // Don't handle static objects here if we don't want to handle them
                    if (!refreshAllObjects)
                    {
                        switch (actObject.VisibilityTestMethod)
                        {
                        case VisibilityTestMethod.ByObjectFilters:
                            if (actObject.IsStatic)
                            {
                                continue;
                            }
                            if ((!actObject.TransformationChanged) && (!actObject.VisibilityTestMethodChanged))
                            {
                                continue;
                            }
                            break;
                        }
                    }

                    // Perform culling
                    this.PerformViewDependentFiltering(actObject, filters);
                }
            }

            // Update objects which are passed for a single update call (normally newly inserted static objects)
            var singleUpdateCallCount = sceneObjectsForSingleUpdateCall.Count;

            if (!refreshAllObjects && singleUpdateCallCount > 0)
            {
                var singleUpdateArray = sceneObjectsForSingleUpdateCall.GetBackingArray();
                for (var loop = 0; loop < singleUpdateCallCount; loop++)
                {
                    // Perform culling
                    this.PerformViewDependentFiltering(singleUpdateArray[loop], filters);
                }
            }

            // Handle changed visibility in standard update logic
            if (_tmpChangedVisibilities.Count > 0)
            {
                var startingScene = _scene;

                _changedVisibilitiesAction = () =>
                {
                    if (_disposed)
                    {
                        return;
                    }
                    if (startingScene != _scene)
                    {
                        return;
                    }

                    foreach (var actChangedVisibility in _tmpChangedVisibilities)
                    {
                        // Check whether this object is still here..
                        if (actChangedVisibility.Item1.Scene != _scene)
                        {
                            continue;
                        }
                        if (actChangedVisibility.Item1.SceneLayer != _sceneLayer)
                        {
                            continue;
                        }

                        // Handle changed visibility
                        this.HandleObjectVisibilityChanged(
                            actChangedVisibility.Item1,
                            actChangedVisibility.Item3);
                    }
                };
            }
        }
        /// <summary>
        /// Executes view update using the given update state object.
        /// </summary>
        /// <param name="updateState">The update state.</param>
        internal void UpdateForView(SceneRelatedUpdateState updateState)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException("ViewRelatedLayerSubset");
            }

            var anyOrderChanges = false;
            var camera          = this.ViewInformation.Camera;

            _objectsPassTransparentRender.Subscriptions.Sort((left, right) =>
            {
                var leftSpacial  = left.SceneObject as SceneSpacialObject;
                var rightSpacial = right.SceneObject as SceneSpacialObject;

                if (leftSpacial != null && rightSpacial != null)
                {
                    var leftDistance  = (camera.Position - leftSpacial.Position).LengthSquared();
                    var rightDistance = (camera.Position - rightSpacial.Position).LengthSquared();
                    anyOrderChanges   = true;
                    return(rightDistance.CompareTo(leftDistance));
                }
                if (leftSpacial != null)
                {
                    anyOrderChanges = true; return(-1);
                }
                if (rightSpacial != null)
                {
                    anyOrderChanges = true; return(1);
                }
                {
                    return(0);
                }
            });

            if (anyOrderChanges)
            {
                // Synchronize ordering changes with corresponding scene object
                for (var loop = 0; loop < _objectsPassTransparentRender.Subscriptions.Count; loop++)
                {
                    var actSubscription = _objectsPassTransparentRender.Subscriptions[loop];
                    actSubscription.SubscriptionIndex = loop;
                    actSubscription.SceneObject.UpdateSubscription(actSubscription, this);
                    _objectsPassTransparentRender.Subscriptions[loop] = actSubscription;
                }
            }

            // Update all objects related to this view
            _isSubscribeUnsubscribeAllowed = true;

            try
            {
                // Update subscriptions based on visibility check result
                if (_changedVisibilitiesAction != null)
                {
                    _changedVisibilitiesAction();
                    _changedVisibilitiesAction = null;
                }

                // Unsubscribe all invalid objects
                while (_invalidObjectsToDeregister.Count > 0)
                {
                    var actInvalidObject = _invalidObjectsToDeregister.Dequeue();
                    actInvalidObject.UnsubsribeFromAllPasses(this);
                }

                // Update subscriptions based on object state
                var allObjects       = _sceneLayer.ObjectsInternal;
                var allObjectsLength = allObjects.Count;
                _countVisibleObjects = 0;
                for (var loop = 0; loop < allObjectsLength; loop++)
                {
                    var actSceneObject = allObjects[loop];

                    if (_invalidObjects.ContainsKey(actSceneObject))
                    {
                        continue;
                    }

                    if (actSceneObject.IsLayerViewSubsetRegistered(ViewIndex) &&
                        actSceneObject.IsVisible(this.ViewInformation))
                    {
                        actSceneObject.UpdateForView(updateState, this);
                        _countVisibleObjects++;
                    }
                }
            }
            finally
            {
                _isSubscribeUnsubscribeAllowed = false;
            }

            // Reorganize subscriptions if there is anything unsubscribed
            if (_anythingUnsubscribed)
            {
                _anythingUnsubscribed = false;
                foreach (var actPassProperties in _objectsPerPass)
                {
                    if (actPassProperties.UnsubscribeCallCount <= 0)
                    {
                        continue;
                    }

                    // Variables for consistency checking
                    var givenUnsubscribeCount = actPassProperties.UnsubscribeCallCount;
                    var trueUnsubscribeCount  = 0;

                    // Handle case where we have unsubscribed some
                    //  => Build new subscription list and ignore all with 'IsSubscribed' == false
                    var newSubscriptionList = actPassProperties.SubscriptionsTemp;
                    for (var loop = 0; loop < actPassProperties.Subscriptions.Count; loop++)
                    {
                        var actSubscription = actPassProperties.Subscriptions[loop];

                        if (!actSubscription.IsSubscribed)
                        {
                            actSubscription.SceneObject.ClearSubscriptionsWithoutUnsubscribeCall(this, actSubscription);
                            trueUnsubscribeCount++;
                            continue;
                        }

                        // AddObject this item to new subscription list
                        actSubscription.SubscriptionIndex = newSubscriptionList.Count;
                        newSubscriptionList.Add(actSubscription);

                        actSubscription.SceneObject.UpdateSubscription(actSubscription, this);
                    }
                    actPassProperties.SubscriptionsTemp = actPassProperties.Subscriptions;
                    actPassProperties.SubscriptionsTemp.Clear();
                    actPassProperties.Subscriptions        = newSubscriptionList;
                    actPassProperties.UnsubscribeCallCount = 0;

                    // Check for consistency: Does unsubscribe-count match true unsubscriptions using IsSubscribed flag
                    if (givenUnsubscribeCount != trueUnsubscribeCount)
                    {
                        throw new SeeingSharpException("Inconsistency: Given unsubscribe count does not mach true count of unsubscriptions!");
                    }
                }
            }
        }
 protected sealed override void UpdateForViewInternal(SceneRelatedUpdateState updateState, ViewRelatedSceneLayerSubset layerViewSubset)
 {
     // No resources, so nothing to be done
 }
 protected override void UpdateInternal(SceneRelatedUpdateState updateState)
 {
 }
예제 #7
0
 internal override void UpdateInternal(SceneRelatedUpdateState updateState, ViewInformation?correspondingView, object?componentContext)
 {
     this.Update(updateState, correspondingView);
 }
예제 #8
0
 /// <summary>
 /// This update method gets called on each update pass for each scenes
 /// this component is attached to.
 /// </summary>
 /// <param name="updateState">Current update state.</param>
 /// <param name="correspondingView">The view which attached this component (may be null).</param>
 protected virtual void Update(SceneRelatedUpdateState updateState, ViewInformation?correspondingView)
 {
 }
예제 #9
0
        /// <summary>
        /// Updates the layer.
        /// </summary>
        /// <param name="updateState">Current update state.</param>
        internal void Update(SceneRelatedUpdateState updateState)
        {
            updateState.SceneLayer = this;
            _isInUpdate            = true;
            try
            {
                // Update all objects which are registered for initial update call
                var initialUpdateCallCount = _sceneObjectsForSingleUpdateCall.Count;
                if (initialUpdateCallCount > 0)
                {
                    var initialUpdateCallItems = _sceneObjectsForSingleUpdateCall.GetBackingArray();
                    for (var loop = 0; loop < initialUpdateCallCount; loop++)
                    {
                        initialUpdateCallItems[loop].Update(updateState);
                    }
                }

                // Call default update method for each object
                var updateListLength = _sceneObjectsNotStatic.Count;
                var updateList       = _sceneObjectsNotStatic.BackingArray;
                for (var actIndex = 0; actIndex < updateListLength; actIndex++)
                {
                    var actObject = updateList[actIndex];
                    if (actObject == null)
                    {
                        continue;
                    }

                    if (!actObject.HasParent)
                    {
                        actObject.Update(updateState);
                    }
                }

                // Call overall updates on all objects
                for (var actIndex = 0; actIndex < updateListLength; actIndex++)
                {
                    var actObject = updateList[actIndex];
                    if (actObject == null)
                    {
                        continue;
                    }

                    if (!actObject.HasParent)
                    {
                        actObject.UpdateOverall(updateState);
                    }
                }

                // Now update all view specific references
                foreach (var actViewSubset in _viewSubsets)
                {
                    actViewSubset.UpdateForView(updateState);
                }
            }
            finally
            {
                updateState.SceneLayer = null;
                _isInUpdate            = false;
            }
        }
예제 #10
0
        /// <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}");
                }
            }
        }