Ejemplo n.º 1
0
        public void EntityAddOrUpdate(object sender, ISceneEntity entity, UpdateFlags updateFlags, uint extraFlags)
        {
            const float TOLERANCE = 0.01f;
            const float SIGNIFICANT_MOVEMENT_SQ = 2f * 2f;

            bool isNew = false;

            #region Entity Creation

            if (m_sceneGraph.AddOrUpdate(entity))
            {
                isNew = true;

                // If this is a scene presence, fire the callback for a new presence being added
                if (entity is IScenePresence)
                {
                    IScenePresence presence = (IScenePresence)entity;
                    m_log.Debug("Added scene presence " + presence.Name + " to scene " + this.Name);

                    EventHandler <PresenceArgs> presenceCallback = OnPresenceAdd;
                    if (presenceCallback != null)
                    {
                        presenceCallback(sender, new PresenceArgs {
                            Presence = presence
                        });
                    }
                }
            }

            #endregion Entity Creation

            #region Update Damping

            UpdateFlags unchangedFlags = 0;

            if (updateFlags.HasFlag(UpdateFlags.Position) && entity.RelativePosition.ApproxEquals(entity.LastRelativePosition, TOLERANCE))
            {
                unchangedFlags |= UpdateFlags.Position;
            }
            if (updateFlags.HasFlag(UpdateFlags.Rotation) && entity.RelativeRotation.ApproxEquals(entity.LastRelativeRotation, TOLERANCE))
            {
                unchangedFlags |= UpdateFlags.Rotation;
            }

            if (entity is IPhysical)
            {
                IPhysical physical = (IPhysical)entity;

                if (updateFlags.HasFlag(UpdateFlags.Acceleration) && physical.Acceleration == physical.LastAcceleration)
                {
                    unchangedFlags |= UpdateFlags.Acceleration;
                }
                if (updateFlags.HasFlag(UpdateFlags.AngularVelocity) && physical.AngularVelocity == physical.LastAngularVelocity)
                {
                    unchangedFlags |= UpdateFlags.AngularVelocity;
                }
                if (updateFlags.HasFlag(UpdateFlags.Velocity) && physical.Velocity == physical.LastVelocity)
                {
                    unchangedFlags |= UpdateFlags.Velocity;
                }
            }

            if (updateFlags != UpdateFlags.FullUpdate)
            {
                updateFlags &= ~unchangedFlags;
                if (updateFlags == 0 && extraFlags == 0)
                {
                    return;
                }
            }

            #endregion Update Damping

            // If this is a physical entity and the scale or shape changed, reset any cached mass calculations
            if (entity is IPhysical && (updateFlags.HasFlag(UpdateFlags.Scale) || updateFlags.HasFlag(UpdateFlags.Shape)))
            {
                ((IPhysical)entity).ResetMass();
            }

            // Mark updated entities as modified
            if (!isNew)
            {
                entity.MarkAsModified();
            }

            #region Callbacks

            // Fire the callback for an entity being added or updated
            EventHandler <EntityAddOrUpdateArgs> addUpdateCallback = OnEntityAddOrUpdate;
            if (addUpdateCallback != null)
            {
                addUpdateCallback(sender, new EntityAddOrUpdateArgs {
                    Entity = entity, UpdateFlags = updateFlags, ExtraFlags = extraFlags, IsNew = isNew
                });
            }

            // Check for significant movement
            Vector3 scenePosition = entity.ScenePosition;
            if (Vector3.DistanceSquared(entity.LastSignificantPosition, scenePosition) > SIGNIFICANT_MOVEMENT_SQ)
            {
                // Fire the significant movement callback
                EventHandler <EntitySignificantMovementArgs> sigMovementCallback = OnEntitySignificantMovement;
                if (sigMovementCallback != null)
                {
                    sigMovementCallback(sender, new EntitySignificantMovementArgs {
                        Entity = entity
                    });
                }

                // Update LastSignificantPosition after the callback
                entity.LastSignificantPosition = scenePosition;
            }

            #endregion Callbacks

            #region Update ISceneEntity.Last* Properties

            if (!unchangedFlags.HasFlag(UpdateFlags.Position))
            {
                entity.LastRelativePosition = entity.RelativePosition;
            }
            if (!unchangedFlags.HasFlag(UpdateFlags.Rotation))
            {
                entity.LastRelativeRotation = entity.RelativeRotation;
            }

            if (entity is IPhysical)
            {
                IPhysical physical = (IPhysical)entity;

                if (!unchangedFlags.HasFlag(UpdateFlags.Acceleration))
                {
                    physical.LastAcceleration = physical.Acceleration;
                }
                if (!unchangedFlags.HasFlag(UpdateFlags.AngularVelocity))
                {
                    physical.LastAngularVelocity = physical.AngularVelocity;
                }
                if (!unchangedFlags.HasFlag(UpdateFlags.Velocity))
                {
                    physical.LastVelocity = physical.Velocity;
                }
            }

            #endregion Update ISceneEntity.Last* Properties
        }