예제 #1
0
        private bool MoveSnapFilter(IEvent testEvent, TimelineControl.SnapOptions options)
        {
            ITimelineReference movingReference = options.FilterContext as ITimelineReference;

            if (movingReference == null)
            {
                return(true);
            }

            IHierarchicalTimeline movingTimeline = movingReference.Target;

            if (movingTimeline == null)
            {
                return(true);
            }

            ITimeline owningTimeline = null;

            if (testEvent is ITimelineReference)
            {
                owningTimeline = ((ITimelineReference)testEvent).Parent;
            }
            else if (testEvent is IInterval)
            {
                owningTimeline = ((IInterval)testEvent).Track.Group.Timeline;
            }
            else if (testEvent is IKey)
            {
                owningTimeline = ((IKey)testEvent).Track.Group.Timeline;
            }
            else if (testEvent is IMarker)
            {
                owningTimeline = ((IMarker)testEvent).Timeline;
            }

            // Is the reference being compared to an object that it owns? Never snap!
            if (owningTimeline == movingTimeline)
            {
                return(false);
            }

            // Is the reference being compared against a sibling object? Snap away.
            if (owningTimeline == movingReference.Parent)
            {
                return(true);
            }

            // to-do: support a true hierarchy. We can't support directed acyclic graphs because
            //  the Layout implementation uses a Dictionary of ITimelineObjects and the same object
            //  can't have multiple layout rectangles. We could support a tree hierarchy, though.
            //// The test object may be a grandchild of the moving reference. Look for a parent.
            //owningTimeline = owningTimeline.Parent;

            return(true);
        }
예제 #2
0
        /// <summary>
        /// Event handler for a mouse move event on the owning TimelineControl</summary>
        /// <param name="sender">Sender</param>
        /// <param name="e">Event args</param>
        protected virtual void MouseMoveHandler(object sender, MouseEventArgs e)
        {
            if (IsMoving)
            {
                Matrix worldToView = Owner.Transform;
                float  newPosition = Sce.Atf.GdiUtil.InverseTransform(worldToView, e.Location.X);

                if (Control.ModifierKeys == Keys.Shift)
                {
                    // Get snap-from point in world coordinates.
                    float[] movingPoints = new[] { newPosition };
                    TimelineControl.SnapOptions options = new TimelineControl.SnapOptions();
                    options.IncludeScrubber   = false;
                    options.CheckModifierKeys = false;
                    float snapOffset = Owner.GetSnapOffset(movingPoints, options);
                    newPosition += snapOffset;
                }

                Position = newPosition;
            }
        }
예제 #3
0
        /// <summary>
        /// Gets the offset from one of the world snap points to the closest non-selected object's edge</summary>
        /// <param name="movingPoints">The x-coordinates to snap "from", in world coordinates</param>
        /// <param name="options">The options to control the behavior. If null, the defaults are used.</param>
        /// <returns>The value to be added, to GetDragOffset().X, for example. Is in world coordinates.</returns>
        private float GetSnapOffset(IEnumerable <float> movingPoints, TimelineControl.SnapOptions options)
        {
            //we want to recalculate m_snapInfo and reflect changes to the snap-to lines
            m_snapInfo.Clear();
            m_owner.Invalidate();

            if (options == null)
            {
                options = new TimelineControl.SnapOptions();
            }

            // Check for user-forced snapping and no-snapping.
            if (options.CheckModifierKeys)
            {
                Keys modKeys = Control.ModifierKeys;
                if (s_deactivatorKeys != Keys.None &&
                    (modKeys & s_deactivatorKeys) == s_deactivatorKeys)
                {
                    return(0.0f);
                }
                if (s_activatorKeys != Keys.None &&
                    (modKeys & s_activatorKeys) != s_activatorKeys)
                {
                    return(0.0f);
                }
            }

            // Prepare helper object on each moving point.
            foreach (float snapping in movingPoints)
            {
                m_snapInfo.Add(new SnapOffsetInfo(snapping));
            }
            if (m_snapInfo.Count == 0)
            {
                return(0.0f);
            }

            // Find the closest IEvent.
            float worldSnapTolerance = GdiUtil.InverseTransformVector(m_owner.Transform, s_snapTolerance);

            List <TimelinePath> events = new List <TimelinePath>(
                TimelineControl.GetObjects <IEvent>(m_owner.Timeline));

            // Allow for snapping to a scrubber manipulator.
            if (m_scrubber != null && options.IncludeScrubber)
            {
                events.Add(new TimelinePath(m_scrubber));
            }

            foreach (TimelinePath path in events)
            {
                if (options.IncludeSelected ||
                    !m_owner.Selection.SelectionContains(path))
                {
                    IEvent snapToEvent = (IEvent)path.Last;

                    if (options.Filter == null ||
                        options.Filter(snapToEvent, options))
                    {
                        Matrix localToWorld = TimelineControl.CalculateLocalToWorld(path);
                        float  start, length;
                        GetEventDimensions(snapToEvent, localToWorld, out start, out length);

                        foreach (SnapOffsetInfo info in m_snapInfo)
                        {
                            info.Update(start, snapToEvent, worldSnapTolerance);
                            if (length > 0)
                            {
                                info.Update(start + length, snapToEvent, worldSnapTolerance);
                            }
                        }
                    }
                }
            }

            // Keep only the shortest distance snap-to points. Could be multiple in case of tie.
            SnapOffsetInfo.RemoveInvalid(m_snapInfo);
            if (m_snapInfo.Count == 0)
            {
                return(0.0f);
            }

            SnapOffsetInfo topInfo = m_snapInfo[0];

            return(topInfo.Offset);
        }
예제 #4
0
 static SplitManipulator()
 {
     s_snapOptions = new TimelineControl.SnapOptions();
     s_snapOptions.IncludeSelected = true;
 }
예제 #5
0
        /// <summary>
        /// Gets the offset from one of the world snap points to the closest non-selected object's edge</summary>
        /// <param name="movingPoints">The x-coordinates to snap "from", in world coordinates</param>
        /// <param name="options">The options to control the behavior. If null, the defaults are used.</param>
        /// <returns>The value to be added, to GetDragOffset().X, for example. Is in world coordinates.</returns>
        private float GetSnapOffset(IEnumerable<float> movingPoints, TimelineControl.SnapOptions options)
        {
            //we want to recalculate m_snapInfo and reflect changes to the snap-to lines
            m_snapInfo.Clear();
            m_owner.Invalidate();

            if (options == null)
                options = new TimelineControl.SnapOptions();

            // Check for user-forced snapping and no-snapping.
            if (options.CheckModifierKeys)
            {
                Keys modKeys = Control.ModifierKeys;
                if (s_deactivatorKeys != Keys.None &&
                    (modKeys & s_deactivatorKeys) == s_deactivatorKeys)
                    return 0.0f;
                if (s_activatorKeys != Keys.None &&
                    (modKeys & s_activatorKeys) != s_activatorKeys)
                    return 0.0f;
            }

            // Prepare helper object on each moving point.
            foreach (float snapping in movingPoints)
            {
                m_snapInfo.Add(new SnapOffsetInfo(snapping));
            }
            if (m_snapInfo.Count == 0)
                return 0.0f;
            
            // Find the closest IEvent.
            float worldSnapTolerance = GdiUtil.InverseTransformVector(m_owner.Transform, s_snapTolerance);

            List<TimelinePath> events = new List<TimelinePath>(
                TimelineControl.GetObjects<IEvent>(m_owner.Timeline));

            // Allow for snapping to a scrubber manipulator.
            if (m_scrubber != null && options.IncludeScrubber)
                events.Add(new TimelinePath(m_scrubber));

            foreach (TimelinePath path in events)
            {
                if (options.IncludeSelected ||
                    !m_owner.Selection.SelectionContains(path))
                {
                    IEvent snapToEvent = (IEvent)path.Last;

                    if (options.Filter == null ||
                        options.Filter(snapToEvent, options))
                    {
                        Matrix localToWorld = TimelineControl.CalculateLocalToWorld(path);
                        float start, length;
                        GetEventDimensions(snapToEvent, localToWorld, out start, out length);

                        foreach (SnapOffsetInfo info in m_snapInfo)
                        {
                            info.Update(start, snapToEvent, worldSnapTolerance);
                            if (length > 0)
                                info.Update(start + length, snapToEvent, worldSnapTolerance);
                        }
                    }
                }
            }

            // Keep only the shortest distance snap-to points. Could be multiple in case of tie.
            SnapOffsetInfo.RemoveInvalid(m_snapInfo);
            if (m_snapInfo.Count == 0)
                return 0.0f;

            SnapOffsetInfo topInfo = m_snapInfo[0];
            return topInfo.Offset;
        }
예제 #6
0
        /// <summary>
        /// Event handler for a mouse move event on the owning TimelineControl</summary>
        /// <param name="sender">Sender</param>
        /// <param name="e">Event args</param>
        protected virtual void MouseMoveHandler(object sender, MouseEventArgs e)
        {
            if (IsMoving)
            {
                Matrix worldToView = Owner.Transform;
                float newPosition = Sce.Atf.GdiUtil.InverseTransform(worldToView, e.Location.X);

                if (Control.ModifierKeys == Keys.Shift)
                {
                    // Get snap-from point in world coordinates.
                    float[] movingPoints = new[] { newPosition };
                    TimelineControl.SnapOptions options = new TimelineControl.SnapOptions();
                    options.IncludeScrubber = false;
                    options.CheckModifierKeys = false;
                    float snapOffset = Owner.GetSnapOffset(movingPoints, options);
                    newPosition += snapOffset;
                }

                Position = newPosition;
            }
        }
예제 #7
0
 static SplitManipulator()
 {
     s_snapOptions = new TimelineControl.SnapOptions();
     s_snapOptions.IncludeSelected = true;
 }