Example #1
0
        /// <summary>
        /// Calculates the texture rect fr the given texture and the view size.
        /// </summary>
        /// <param name="textureSize">Size of the texture.</param>
        /// <param name="viewSize">Size of the view.</param>
        /// <param name="result">The result.</param>
        protected static void CalculateTextureRect(Float2 textureSize, Float2 viewSize, out Rectangle result)
        {
            Float2 size        = Float2.Max(textureSize, Float2.One);
            float  aspectRatio = size.X / size.Y;
            float  h           = viewSize.X / aspectRatio;
            float  w           = viewSize.Y * aspectRatio;

            if (w > h)
            {
                float diff = (viewSize.Y - h) * 0.5f;
                result = new Rectangle(0, diff, viewSize.X, h);
            }
            else
            {
                float diff = (viewSize.X - w) * 0.5f;
                result = new Rectangle(diff, 0, w, viewSize.Y);
            }
        }
Example #2
0
        /// <summary>
        /// 裁剪挡格数据
        /// </summary>
        /// <param name="ar"></param>
        /// <param name="listblock"></param>
        /// <param name="minPos"></param>
        /// <param name="maxPos"></param>
        /// <returns></returns>
        public bool CutBlockArea(StageGateArea ar, ref List <Short2> listblock, ref Short2 minPos, ref Short2 maxPos)
        {
            if (ar == null)
            {
                return(false);
            }
            Float2 min = Float2.Min(ar.leftBottom, ar.rightUp);
            Float2 max = Float2.Max(ar.leftBottom, ar.rightUp);

            Short2 min2 = GetIndex(min);
            Short2 max2 = GetIndex(max);

            Short2 diff   = max2 - min2;
            int    width  = diff.x + 1;
            int    height = diff.y + 1;

            maxPos = min2;
            minPos = max2;
            List <Short2> list = new List <Short2>();

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    Short2 pos = new Short2(x + min2.x, y + min2.y);
                    if (CheckBlock(pos) == true)
                    {
                        list.Add(new Short2(x, y));
                        minPos = Short2.Min(minPos, pos);
                        maxPos = Short2.Max(maxPos, pos);
                    }
                }
            }
            if (listblock == null)
            {
                listblock = new List <Short2>();
            }
            listblock.Clear();
            foreach (Short2 pos in list)
            {
                listblock.Add(pos - (minPos - min2));
            }
            return(true);
        }
Example #3
0
        /// <inheritdoc />
        public override void Draw()
        {
            var style           = Style.Current;
            var mediaBackground = _timeline.MediaBackground;
            var tracks          = _timeline.Tracks;
            var linesColor      = style.BackgroundNormal;
            var areaLeft        = -X;
            var areaRight       = Parent.Width + mediaBackground.ControlsBounds.BottomRight.X;
            var height          = Height;

            // Calculate the timeline range in the view to optimize background drawing
            Render2D.PeekClip(out var globalClipping);
            Render2D.PeekTransform(out var globalTransform);
            var globalRect         = new Rectangle(globalTransform.M31 + areaLeft, globalTransform.M32, areaRight * globalTransform.M11, height * globalTransform.M22);
            var globalMask         = Rectangle.Shared(globalClipping, globalRect);
            var globalTransformInv = Matrix3x3.Invert(globalTransform);
            var localRect          = Rectangle.FromPoints(Matrix3x3.Transform2D(globalMask.UpperLeft, globalTransformInv), Matrix3x3.Transform2D(globalMask.BottomRight, globalTransformInv));
            var localRectMin       = localRect.UpperLeft;
            var localRectMax       = localRect.BottomRight;

            // Draw lines between tracks
            Render2D.DrawLine(new Float2(areaLeft, 0.5f), new Float2(areaRight, 0.5f), linesColor);
            for (int i = 0; i < tracks.Count; i++)
            {
                var track = tracks[i];
                if (track.Visible)
                {
                    var top = track.Bottom + 0.5f;
                    Render2D.DrawLine(new Float2(areaLeft, top), new Float2(areaRight, top), linesColor);
                }
            }

            // Highlight selected tracks
            for (int i = 0; i < tracks.Count; i++)
            {
                var track = tracks[i];
                if (track.Visible && _timeline.SelectedTracks.Contains(track) && _timeline.ContainsFocus)
                {
                    Render2D.FillRectangle(new Rectangle(areaLeft, track.Top, areaRight, track.Height), style.BackgroundSelected.RGBMultiplied(0.4f));
                }
            }

            // Setup time axis ticks
            var minDistanceBetweenTicks = 50.0f;
            var maxDistanceBetweenTicks = 100.0f;
            var zoom         = Timeline.UnitsPerSecond * _timeline.Zoom;
            var left         = Float2.Min(localRectMin, localRectMax).X;
            var right        = Float2.Max(localRectMin, localRectMax).X;
            var leftFrame    = Mathf.Floor((left - Timeline.StartOffset) / zoom) * _timeline.FramesPerSecond;
            var rightFrame   = Mathf.Ceil((right - Timeline.StartOffset) / zoom) * _timeline.FramesPerSecond;
            var min          = leftFrame;
            var max          = rightFrame;
            int smallestTick = 0;
            int biggestTick  = _tickSteps.Length - 1;

            for (int i = _tickSteps.Length - 1; i >= 0; i--)
            {
                // Calculate how far apart these modulo tick steps are spaced
                float tickSpacing = _tickSteps[i] * _timeline.Zoom;

                // Calculate the strength of the tick markers based on the spacing
                _tickStrengths[i] = Mathf.Saturate((tickSpacing - minDistanceBetweenTicks) / (maxDistanceBetweenTicks - minDistanceBetweenTicks));

                // Beyond threshold the ticks don't get any bigger or fatter
                if (_tickStrengths[i] >= 1)
                {
                    biggestTick = i;
                }

                // Do not show small tick markers
                if (tickSpacing <= minDistanceBetweenTicks)
                {
                    smallestTick = i;
                    break;
                }
            }
            int tickLevels = biggestTick - smallestTick + 1;

            // Draw vertical lines for time axis
            for (int level = 0; level < tickLevels; level++)
            {
                float strength = _tickStrengths[smallestTick + level];
                if (strength <= Mathf.Epsilon)
                {
                    continue;
                }

                // Draw all ticks
                int   l         = Mathf.Clamp(smallestTick + level, 0, _tickSteps.Length - 1);
                var   lStep     = _tickSteps[l];
                var   lNextStep = _tickSteps[l + 1];
                int   startTick = Mathf.FloorToInt(min / lStep);
                int   endTick   = Mathf.CeilToInt(max / lStep);
                Color lineColor = style.ForegroundDisabled.RGBMultiplied(0.7f).AlphaMultiplied(strength);
                for (int i = startTick; i <= endTick; i++)
                {
                    if (l < biggestTick && (i % Mathf.RoundToInt(lNextStep / lStep) == 0))
                    {
                        continue;
                    }
                    var tick = i * lStep;
                    var time = tick / _timeline.FramesPerSecond;
                    var x    = time * zoom + Timeline.StartOffset;

                    // Draw line
                    Render2D.FillRectangle(new Rectangle(x - 0.5f, 0, 1.0f, height), lineColor);
                }
            }

            // Draw selection rectangle
            if (_isSelecting)
            {
                var selectionRect = Rectangle.FromPoints(_selectingStartPos, _mousePos);
                Render2D.FillRectangle(selectionRect, Color.Orange * 0.4f);
                Render2D.DrawRectangle(selectionRect, Color.Orange);
            }

            DrawChildren();

            // Disabled overlay
            for (int i = 0; i < tracks.Count; i++)
            {
                var track = tracks[i];
                if (track.DrawDisabled && track.IsExpandedAll)
                {
                    Render2D.FillRectangle(new Rectangle(areaLeft, track.Top, areaRight, track.Height), new Color(0, 0, 0, 100));
                }
            }

            // Darken area outside the duration
            {
                var outsideDurationAreaColor = new Color(0, 0, 0, 100);
                var leftSideMin  = PointFromParent(Float2.Zero);
                var leftSideMax  = BottomLeft;
                var rightSideMin = UpperRight;
                var rightSideMax = PointFromParent(Parent.BottomRight) + mediaBackground.ControlsBounds.BottomRight;
                Render2D.FillRectangle(new Rectangle(leftSideMin, leftSideMax.X - leftSideMin.X, height), outsideDurationAreaColor);
                Render2D.FillRectangle(new Rectangle(rightSideMin, rightSideMax.X - rightSideMin.X, height), outsideDurationAreaColor);
            }

            // Draw time axis header
            var timeAxisHeaderOffset      = -_timeline.MediaBackground.ViewOffset.Y;
            var verticalLinesHeaderExtend = Timeline.HeaderTopAreaHeight * 0.5f;
            var timeShowMode = _timeline.TimeShowMode;

            Render2D.FillRectangle(new Rectangle(areaLeft, timeAxisHeaderOffset - Timeline.HeaderTopAreaHeight, areaRight - areaLeft, Timeline.HeaderTopAreaHeight), style.Background.RGBMultiplied(0.7f));
            for (int level = 0; level < tickLevels; level++)
            {
                float strength = _tickStrengths[smallestTick + level];
                if (strength <= Mathf.Epsilon)
                {
                    continue;
                }

                // Draw all ticks
                int   l          = Mathf.Clamp(smallestTick + level, 0, _tickSteps.Length - 1);
                var   lStep      = _tickSteps[l];
                var   lNextStep  = _tickSteps[l + 1];
                int   startTick  = Mathf.FloorToInt(min / lStep);
                int   endTick    = Mathf.CeilToInt(max / lStep);
                Color lineColor  = style.Foreground.RGBMultiplied(0.8f).AlphaMultiplied(strength);
                Color labelColor = style.ForegroundDisabled.AlphaMultiplied(strength);
                for (int i = startTick; i <= endTick; i++)
                {
                    if (l < biggestTick && (i % Mathf.RoundToInt(lNextStep / lStep) == 0))
                    {
                        continue;
                    }
                    var tick = i * lStep;
                    var time = tick / _timeline.FramesPerSecond;
                    var x    = time * zoom + Timeline.StartOffset;

                    // Header line
                    var lineRect = new Rectangle(x - 0.5f, -verticalLinesHeaderExtend + timeAxisHeaderOffset, 1.0f, verticalLinesHeaderExtend);
                    Render2D.FillRectangle(lineRect, lineColor);

                    // Time label
                    string labelText;
                    switch (timeShowMode)
                    {
                    case Timeline.TimeShowModes.Frames:
                        labelText = tick.ToString("###0", CultureInfo.InvariantCulture);
                        break;

                    case Timeline.TimeShowModes.Seconds:
                        labelText = time.ToString("###0.##'s'", CultureInfo.InvariantCulture);
                        break;

                    case Timeline.TimeShowModes.Time:
                        labelText = TimeSpan.FromSeconds(time).ToString("g");
                        break;

                    default: throw new ArgumentOutOfRangeException();
                    }
                    var labelRect = new Rectangle(x + 2, -verticalLinesHeaderExtend + timeAxisHeaderOffset, 50, verticalLinesHeaderExtend);
                    Render2D.DrawText(style.FontSmall, labelText, labelRect, labelColor, TextAlignment.Near, TextAlignment.Center, TextWrapping.NoWrap, 1.0f, 0.8f);
                }
            }
        }
        /// <summary>
        /// Shows the primary menu.
        /// </summary>
        /// <param name="location">The location in the Surface Space.</param>
        /// <param name="moveSurface">If the surface should be moved to accommodate for the menu.</param>
        /// <param name="input">The user text input for nodes search.</param>
        public virtual void ShowPrimaryMenu(Float2 location, bool moveSurface = false, string input = null)
        {
            if (!CanEdit)
            {
                return;
            }

            // Check if need to create default context menu (no override specified)
            if (_activeVisjectCM == null && _cmPrimaryMenu == null)
            {
                _activeVisjectCM = _cmPrimaryMenu = CreateDefaultPrimaryMenu();

                _activeVisjectCM.ItemClicked    += OnPrimaryMenuButtonClick;
                _activeVisjectCM.VisibleChanged += OnPrimaryMenuVisibleChanged;
            }

            if (moveSurface)
            {
                const float leftPadding = 20;
                var         delta       = Float2.Min(location - leftPadding, Float2.Zero) + Float2.Max((location + _activeVisjectCM.Size) - Size, Float2.Zero);

                location -= delta;
                _rootControl.Location -= delta;
            }

            _cmStartPos = location;

            // Offset added in case the user doesn't like the box and wants to quickly get rid of it by clicking
            OnShowPrimaryMenu(_activeVisjectCM, _cmStartPos + ContextMenuOffset, _connectionInstigator as Box);

            if (!string.IsNullOrEmpty(input))
            {
                foreach (char character in input)
                {
                    // OnKeyDown -> VisjectCM focuses on the text-thingy
                    _activeVisjectCM.OnKeyDown(KeyboardKeys.None);
                    _activeVisjectCM.OnCharInput(character);
                    _activeVisjectCM.OnKeyUp(KeyboardKeys.None);
                }
            }
        }
        private void TryConnect(Box startBox, Box endBox)
        {
            if (startBox == null || endBox == null)
            {
                if (IsConnecting)
                {
                    ConnectingEnd(null);
                }
                return;
            }

            // If the user is patiently waiting for his box to get connected to the newly created one fulfill his wish!

            _connectionInstigator = startBox;

            if (!IsConnecting)
            {
                ConnectingStart(startBox);
            }
            ConnectingEnd(endBox);

            // Smart-Select next box

            /*
             * Output and Output => undefined
             * Output and Input => Connect and move to next on input-node
             * Input and Output => Connect and move to next on input-node
             * Input and Input => undefined, cannot happen
             */
            Box inputBox = endBox.IsOutput ? startBox : endBox;
            Box nextBox  = inputBox.ParentNode.GetNextBox(inputBox);

            // If we are going backwards and the end-node has an input box we want to edit backwards
            if (!startBox.IsOutput)
            {
                Box endNodeInputBox = endBox.ParentNode.GetBoxes().DefaultIfEmpty(null).FirstOrDefault(b => !b.IsOutput);
                if (endNodeInputBox != null)
                {
                    nextBox = endNodeInputBox;
                }
            }

            // TODO: What if we reached the end (nextBox == null)? Do we travel along the nodes?

            /*
             * while (nextBox == null && _inputBoxStack.Count > 0)
             *  {
             *      // We found the last box on this node but there are still boxes on previous nodes on the stack
             *      nextBox = GetNextBox(_inputBoxStack.Pop());
             *  }
             */

            if (nextBox != null)
            {
                Select(nextBox.ParentNode);
                nextBox.ParentNode.SelectBox(nextBox);

                var padding = new Float2(20);
                var delta   = Float2.Min(_rootControl.PointToParent(nextBox.ParentNode.Location) - padding, Float2.Zero) + Float2.Max((_rootControl.PointToParent(nextBox.ParentNode.BottomRight) + padding) - Size, Float2.Zero);

                _rootControl.Location -= delta;
            }
        }