Exemplo n.º 1
0
        protected void FitChildInPixelBox(Control child, UIBox2i pixelBox)
        {
            var topLeft     = pixelBox.TopLeft / UIScale;
            var bottomRight = pixelBox.BottomRight / UIScale;

            FitChildInBox(child, new UIBox2(topLeft, bottomRight));
        }
Exemplo n.º 2
0
        /// <summary>
        ///     Blit an image into another, with the specified offset.
        /// </summary>
        /// <param name="source">The image to copy data from.</param>
        /// <param name="sourceRect">The sub section of <see cref="source"/> that will be copied.</param>
        /// <param name="destinationOffset">
        ///     The offset into <see cref="destination"/> that data will be copied into.
        /// </param>
        /// <param name="destination">The image to copy to.</param>
        /// <typeparam name="T">The type of pixel stored in the images.</typeparam>
        public static void Blit <T>(this Image <T> source, UIBox2i sourceRect,
                                    Image <T> destination, Vector2i destinationOffset)
            where T : struct, IPixel <T>
        {
            // TODO: Bounds checks.

            var srcSpan = source.GetPixelSpan();
            var dstSpan = destination.GetPixelSpan();

            var srcWidth = source.Width;
            var dstWidth = destination.Width;

            var(ox, oy) = destinationOffset;

            for (var y = 0; y < sourceRect.Height; y++)
            {
                var sourceRowOffset = srcWidth * (y + sourceRect.Top) + sourceRect.Left;
                var destRowOffset   = dstWidth * (y + oy) + ox;

                for (var x = 0; x < sourceRect.Width; x++)
                {
                    var pixel = srcSpan[x + sourceRowOffset];
                    dstSpan[x + destRowOffset] = pixel;
                }
            }
        }
Exemplo n.º 3
0
        public HandsGui()
        {
            IoCManager.InjectDependencies(this);

            _handR = new UIBox2i(0, 0, BoxSize, BoxSize);
            _handL = _handR.Translated((BoxSize + BoxSpacing, 0));

            MouseFilter = MouseFilterMode.Stop;

            TextureHandLeft   = _resourceCache.GetTexture("/Textures/UserInterface/Inventory/hand_l.png");
            TextureHandRight  = _resourceCache.GetTexture("/Textures/UserInterface/Inventory/hand_r.png");
            TextureHandActive = _resourceCache.GetTexture("/Textures/UserInterface/Inventory/hand_active.png");

            TexturesCooldownOverlay = new Texture[CooldownLevels];
            for (var i = 0; i < CooldownLevels; i++)
            {
                TexturesCooldownOverlay[i] =
                    _resourceCache.GetTexture($"/Textures/UserInterface/Inventory/cooldown-{i}.png");
            }

            AddChild(new TextureRect
            {
                MouseFilter  = MouseFilterMode.Ignore,
                Texture      = TextureHandLeft,
                Size         = _handL.Size,
                Position     = _handL.TopLeft,
                TextureScale = (2, 2)
            });
Exemplo n.º 4
0
        /// <summary>
        ///     Blit an image into another, with the specified offset.
        /// </summary>
        /// <param name="source">The image to copy data from.</param>
        /// <param name="sourceRect">The sub section of <see cref="source"/> that will be copied.</param>
        /// <param name="destinationOffset">
        ///     The offset into <see cref="destination"/> that data will be copied into.
        /// </param>
        /// <param name="destination">The image to copy to.</param>
        /// <typeparam name="T">The type of pixel stored in the images.</typeparam>
        public static void Blit <T>(this Image <T> source, UIBox2i sourceRect,
                                    Image <T> destination, Vector2i destinationOffset)
            where T : unmanaged, IPixel <T>
        {
            // TODO: Bounds checks.

            Blit(source.GetPixelSpan(), source.Width, sourceRect, destination, destinationOffset);
        }
Exemplo n.º 5
0
        private void OnPostDrawUIRoot(PostDrawUIRootEventArgs eventArgs)
        {
            if (SelectedControl == null || eventArgs.Root != SelectedControl.Root)
            {
                return;
            }

            var rect = UIBox2i.FromDimensions(SelectedControl.GlobalPixelPosition, SelectedControl.PixelSize);

            eventArgs.DrawingHandle.DrawRect(rect, Color.Cyan.WithAlpha(0.35f));
        }
        protected override void Draw(DrawingHandleScreen handle)
        {
            base.Draw(handle);

            handle.UseShader(Shader);

            var leftOffset = 2 * HealthBarScale;
            var box        = new UIBox2i(
                leftOffset,
                -2 + 2 * HealthBarScale,
                leftOffset + (int)(XPixelDiff * Ratio * UIScale),
                -2);

            handle.DrawRect(box, Color);
        }
Exemplo n.º 7
0
        public static void Blit <T>(this ReadOnlySpan <T> source, int sourceWidth, UIBox2i sourceRect,
                                    Image <T> destination, Vector2i destinationOffset) where T : unmanaged, IPixel <T>
        {
            var dstSpan   = destination.GetPixelSpan();
            var dstWidth  = destination.Width;
            var srcHeight = sourceRect.Height;
            var srcWidth  = sourceRect.Width;

            var(ox, oy) = destinationOffset;

            for (var y = 0; y < srcHeight; y++)
            {
                var sourceRowOffset = sourceWidth * (y + sourceRect.Top) + sourceRect.Left;
                var destRowOffset   = dstWidth * (y + oy) + ox;

                var srcRow = source[sourceRowOffset..(sourceRowOffset + srcWidth)];
Exemplo n.º 8
0
        public static void Blit <T>(this ReadOnlySpan <T> source, int sourceWidth, UIBox2i sourceRect,
                                    Image <T> destination, Vector2i destinationOffset) where T : unmanaged, IPixel <T>
        {
            var dstSpan  = destination.GetPixelSpan();
            var dstWidth = destination.Width;

            var(ox, oy) = destinationOffset;

            for (var y = 0; y < sourceRect.Height; y++)
            {
                var sourceRowOffset = sourceWidth * (y + sourceRect.Top) + sourceRect.Left;
                var destRowOffset   = dstWidth * (y + oy) + ox;

                for (var x = 0; x < sourceRect.Width; x++)
                {
                    var pixel = source[x + sourceRowOffset];
                    dstSpan[x + destRowOffset] = pixel;
                }
            }
        }
Exemplo n.º 9
0
        public HandsGui()
        {
            IoCManager.InjectDependencies(this);

            ToolTip = _loc.GetString("Your hands");

            _handR = new UIBox2i(0, 0, BoxSize, BoxSize);
            _handL = _handR.Translated((BoxSize + BoxSpacing, 0));

            MouseFilter = MouseFilterMode.Stop;

            TextureHandLeft   = _resourceCache.GetTexture("/Textures/UserInterface/Inventory/hand_l.png");
            TextureHandRight  = _resourceCache.GetTexture("/Textures/UserInterface/Inventory/hand_r.png");
            TextureHandActive = _resourceCache.GetTexture("/Textures/UserInterface/Inventory/hand_active.png");

            AddChild(new TextureRect
            {
                MouseFilter  = MouseFilterMode.Ignore,
                Texture      = TextureHandLeft,
                Size         = _handL.Size,
                Position     = _handL.TopLeft,
                TextureScale = (2, 2)
            });
Exemplo n.º 10
0
        protected override void Initialize()
        {
            base.Initialize();

            var resMgr          = IoCManager.Resolve <IResourceCache>();
            var handsBoxTexture = resMgr.GetResource <TextureResource>("/Textures/UserInterface/handsbox.png");

            handBox = new StyleBoxTexture()
            {
                Texture = handsBoxTexture,
            };
            handBox.SetPatchMargin(StyleBox.Margin.All, 6);
            inactiveHandBox = new StyleBoxTexture(handBox)
            {
                Modulate = _inactiveColor,
            };
            SetMarginsPreset(LayoutPreset.CenterBottom);
            SetAnchorPreset(LayoutPreset.CenterBottom);

            _handL      = new UIBox2i(0, 0, BOX_SIZE, BOX_SIZE);
            _handR      = _handL.Translated(new Vector2i(BOX_SIZE + BOX_SPACING, 0));
            MouseFilter = MouseFilterMode.Stop;

            LeftSpriteView = new SpriteView {
                MouseFilter = MouseFilterMode.Ignore
            };
            AddChild(LeftSpriteView);
            LeftSpriteView.Size     = _handL.Size;
            LeftSpriteView.Position = _handL.TopLeft;

            RightSpriteView = new SpriteView {
                MouseFilter = MouseFilterMode.Ignore
            };
            AddChild(RightSpriteView);
            RightSpriteView.Size     = _handR.Size;
            RightSpriteView.Position = _handR.TopLeft;
        }
Exemplo n.º 11
0
        protected override void Initialize()
        {
            base.Initialize();

            var _resMgr         = IoCManager.Resolve <IResourceCache>();
            var handsBoxTexture = _resMgr.GetResource <TextureResource>("/Textures/UserInterface/handsbox.png");

            handBox = new StyleBoxTexture()
            {
                Texture = handsBoxTexture,
            };
            handBox.SetMargin(StyleBox.Margin.All, 6);
            inactiveHandBox = new StyleBoxTexture(handBox)
            {
                Modulate = _inactiveColor,
            };
            SetMarginsPreset(LayoutPreset.CenterBottom);
            SetAnchorPreset(LayoutPreset.CenterBottom);

            handL = new UIBox2i(0, 0, BOX_SIZE, BOX_SIZE);
            handR = handL.Translated(new Vector2i(BOX_SIZE + BOX_SPACING, 0));
            SS14.Shared.Log.Logger.Debug($"{handL}, {handR}");
            MouseFilter = MouseFilterMode.Stop;
        }
Exemplo n.º 12
0
        protected override void LayoutUpdateOverride()
        {
            var separation = (int)(ActualSeparation * UIScale);

            // Step one: figure out the sizes of all our children and whether they want to stretch.
            var sizeList          = new List <(Control control, int minSize, int finalSize, bool stretch)>(ChildCount);
            var totalStretchRatio = 0f;
            // Amount of space not available for stretching.
            var stretchMin = 0;

            foreach (var child in Children)
            {
                if (!child.Visible)
                {
                    continue;
                }
                var(minX, minY) = child.CombinedPixelMinimumSize;
                int  minSize;
                bool stretch;

                if (Vertical)
                {
                    minSize = minY;
                    stretch = (child.SizeFlagsVertical & SizeFlags.Expand) == SizeFlags.Expand;
                }
                else
                {
                    minSize = minX;
                    stretch = (child.SizeFlagsHorizontal & SizeFlags.Expand) == SizeFlags.Expand;
                }

                if (!stretch)
                {
                    stretchMin += minSize;
                }
                else
                {
                    totalStretchRatio += child.SizeFlagsStretchRatio;
                }

                sizeList.Add((child, minSize, minSize, stretch));
            }

            var stretchMax = Vertical ? PixelHeight : PixelWidth;

            stretchMax -= separation * (ChildCount - 1);
            // This is the amount of space allocated for stretchable children.
            var stretchAvail = Math.Max(0, stretchMax - stretchMin);

            // Step two: figure out which that want to stretch need to suck it,
            // because due to their stretch ratio they would be smaller than minSize.
            // Treat those as non-stretching.
            for (var i = 0; i < sizeList.Count; i++)
            {
                var(control, minSize, _, stretch) = sizeList[i];
                if (!stretch)
                {
                    continue;
                }

                var share = (int)(stretchAvail * (control.SizeFlagsStretchRatio / totalStretchRatio));
                if (share < minSize)
                {
                    sizeList[i]        = (control, minSize, minSize, false);
                    stretchAvail      -= minSize;
                    totalStretchRatio -= control.SizeFlagsStretchRatio;
                }
            }

            // Step three: allocate space for all the stretchable children.
            var stretchingAtAll = false;

            for (var i = 0; i < sizeList.Count; i++)
            {
                var(control, minSize, _, stretch) = sizeList[i];
                if (!stretch)
                {
                    continue;
                }

                stretchingAtAll = true;

                var share = (int)(stretchAvail * (control.SizeFlagsStretchRatio / totalStretchRatio));
                sizeList[i] = (control, minSize, share, false);
            }

            // Step four: actually lay them out one by one.
            var offset = 0;

            if (!stretchingAtAll)
            {
                switch (Align)
                {
                case AlignMode.Begin:
                    break;

                case AlignMode.Center:
                    offset = stretchAvail / 2;
                    break;

                case AlignMode.End:
                    offset = stretchAvail;
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            var first = true;

            foreach (var(control, _, size, _) in sizeList)
            {
                if (!first)
                {
                    offset += separation;
                }

                first = false;

                UIBox2i targetBox;
                if (Vertical)
                {
                    targetBox = new UIBox2i(0, offset, PixelWidth, offset + size);
                }
                else
                {
                    targetBox = new UIBox2i(offset, 0, offset + size, PixelHeight);
                }

                FitChildInPixelBox(control, targetBox);

                offset += size;
            }
        }
        protected override Vector2 ArrangeOverride(Vector2 finalSize)
        {
            var separation = (int)(ActualSeparation * UIScale);

            #region Scroll
            var cHeight  = _totalHeight;
            var vBarSize = _vScrollBar.DesiredSize.X;
            var(sWidth, sHeight) = finalSize;

            try
            {
                // Suppress events to avoid weird recursion.
                _suppressScrollValueChanged = true;

                if (sHeight < cHeight)
                {
                    sWidth -= vBarSize;
                }

                if (sHeight < cHeight)
                {
                    _vScrollBar.Visible  = true;
                    _vScrollBar.Page     = sHeight;
                    _vScrollBar.MaxValue = cHeight;
                }
                else
                {
                    _vScrollBar.Visible = false;
                }
            }
            finally
            {
                _suppressScrollValueChanged = false;
            }

            if (_vScrollBar.Visible)
            {
                _vScrollBar.Arrange(UIBox2.FromDimensions(Vector2.Zero, finalSize));
            }
            #endregion

            #region Rebuild Children

            /*
             * Example:
             *
             * var _itemHeight = 32;
             * var separation = 3;
             *  32 | 32 | Control.Size.Y 0
             *  35 |  3 | Padding
             *  67 | 32 | Control.Size.Y 1
             *  70 |  3 | Padding
             * 102 | 32 | Control.Size.Y 2
             * 105 |  3 | Padding
             * 137 | 32 | Control.Size.Y 3
             *
             * If viewport height is 60
             * visible should be 2 items (start = 0, end = 1)
             *
             * scroll.Y = 11
             * visible should be 3 items (start = 0, end = 2)
             *
             * start expected: 11 (item: 0)
             * var start = (int) (scroll.Y
             *
             * if (scroll == 32) then { start = 1 }
             * var start = (int) (scroll.Y + separation / (_itemHeight + separation));
             * var start = (int) (32 + 3 / (32 + 3));
             * var start = (int) (35 / 35);
             * var start = (int) (1);
             *
             * scroll = 0, height = 36
             * if (scroll + height == 36) then { end = 2 }
             * var end = (int) Math.Ceiling(scroll.Y + height / (_itemHeight + separation));
             * var end = (int) Math.Ceiling(0 + 36 / (32 + 3));
             * var end = (int) Math.Ceiling(36 / 35);
             * var end = (int) Math.Ceiling(1.02857);
             * var end = (int) 2;
             *
             */
            var scroll      = GetScrollValue();
            var oldTopIndex = _topIndex;
            _topIndex = (int)((scroll.Y + separation) / (_itemHeight + separation));
            if (_topIndex != oldTopIndex)
            {
                _updateChildren = true;
            }

            var oldBottomIndex = _bottomIndex;
            _bottomIndex = (int)Math.Ceiling((scroll.Y + Height) / (_itemHeight + separation));
            _bottomIndex = Math.Min(_bottomIndex, _count);
            if (_bottomIndex != oldBottomIndex)
            {
                _updateChildren = true;
            }

            // When scrolling only rebuild visible list when a new item should be visible
            if (_updateChildren)
            {
                _updateChildren = false;

                foreach (var child in Children.ToArray())
                {
                    if (child == _vScrollBar)
                    {
                        continue;
                    }
                    RemoveChild(child);
                }

                if (_entityUids != null)
                {
                    for (var i = _topIndex; i < _bottomIndex; i++)
                    {
                        var entity = _entityUids[i];

                        var button = new EntityContainerButton(entity);
                        button.OnPressed += OnItemPressed;

                        GenerateItem?.Invoke(entity, button);
                        AddChild(button);
                    }
                }

                _vScrollBar.SetPositionLast();
            }
            #endregion

            #region Layout Children
            // Use pixel position
            var pixelWidth = (int)(sWidth * UIScale);

            var offset = (int)-((scroll.Y - _topIndex * (_itemHeight + separation)) * UIScale);
            var first  = true;
            foreach (var child in Children)
            {
                if (child == _vScrollBar)
                {
                    continue;
                }
                if (!first)
                {
                    offset += separation;
                }
                first = false;

                var size      = child.DesiredPixelSize.Y;
                var targetBox = new UIBox2i(0, offset, pixelWidth, offset + size);
                child.ArrangePixel(targetBox);

                offset += size;
            }
            #endregion

            return(finalSize);
        }
Exemplo n.º 14
0
        public override void Load(IResourceCache cache, ResourcePath path)
        {
            var    manifestPath = path / "meta.json";
            string manifestContents;

            using (var manifestFile = cache.ContentFileRead(manifestPath))
                using (var reader = new StreamReader(manifestFile))
                {
                    manifestContents = reader.ReadToEnd();
                }

#if DEBUG
            if (RSISchema != null)
            {
                var errors = RSISchema.Validate(manifestContents);
                if (errors.Count != 0)
                {
                    Logger.Error($"Unable to load RSI from '{path}', {errors.Count} errors:");

                    foreach (var error in errors)
                    {
                        Logger.Error("{0}", error.ToString());
                    }

                    throw new RSILoadException($"{errors.Count} errors while loading RSI. See console.");
                }
            }
#endif

            // Ok schema validated just fine.
            var manifestJson = JObject.Parse(manifestContents);

            var toAtlas = new List <(Image <Rgba32> src, Texture[][] output, int[][] indices, int totalFrameCount)>();

            var metaData  = ParseMetaData(manifestJson);
            var frameSize = metaData.Size;
            var rsi       = new RSI(frameSize);

            // Do every state.
            foreach (var stateObject in metaData.States)
            {
                // Load image from disk.
                var texPath   = path / (stateObject.StateId + ".png");
                var image     = Image.Load(cache.ContentFileRead(texPath));
                var sheetSize = new Vector2i(image.Width, image.Height);

                if (sheetSize.X % frameSize.X != 0 || sheetSize.Y % frameSize.Y != 0)
                {
                    throw new RSILoadException("State image size is not a multiple of the icon size.");
                }

                // Load all frames into a list so we can operate on it more sanely.
                var frameCount = stateObject.Delays.Sum(delayList => delayList.Length);

                var(foldedDelays, foldedIndices) = FoldDelays(stateObject.Delays);

                var textures = new Texture[foldedIndices.Length][];

                for (var i = 0; i < textures.Length; i++)
                {
                    textures[i] = new Texture[foldedIndices[0].Length];
                }

                var state = new RSI.State(frameSize, stateObject.StateId, stateObject.DirType, foldedDelays, textures);
                rsi.AddState(state);

                toAtlas.Add((image, textures, foldedIndices, frameCount));
            }

            // Poorly hacked in texture atlas support here.
            {
                var totalFrameCount = toAtlas.Sum(p => p.totalFrameCount);

                // Generate atlas.
                var dimensionX = (int)MathF.Ceiling(MathF.Sqrt(totalFrameCount));
                var dimensionY = (int)MathF.Ceiling((float)totalFrameCount / dimensionX);

                using var sheet = new Image <Rgba32>(dimensionX * frameSize.X, dimensionY * frameSize.Y);

                var sheetIndex = 0;
                foreach (var(src, _, _, frameCount) in toAtlas)
                {
                    // Blit all the frames over.
                    for (var i = 0; i < frameCount; i++)
                    {
                        var srcWidth  = (src.Width / frameSize.X);
                        var srcColumn = i % srcWidth;
                        var srcRow    = i / srcWidth;
                        var srcPos    = (srcColumn * frameSize.X, srcRow *frameSize.Y);

                        var sheetColumn = (sheetIndex + i) % dimensionX;
                        var sheetRow    = (sheetIndex + i) / dimensionX;
                        var sheetPos    = (sheetColumn * frameSize.X, sheetRow *frameSize.Y);

                        var srcBox = UIBox2i.FromDimensions(srcPos, frameSize);

                        src.Blit(srcBox, sheet, sheetPos);
                    }

                    sheetIndex += frameCount;
                }

                // Load atlas.
                var texture = Texture.LoadFromImage(sheet, path.ToString());

                var sheetOffset = 0;
                foreach (var(src, output, indices, frameCount) in toAtlas)
                {
                    for (var i = 0; i < indices.Length; i++)
                    {
                        var dirIndices = indices[i];
                        var dirOutput  = output[i];

                        for (var j = 0; j < dirIndices.Length; j++)
                        {
                            var index = sheetOffset + dirIndices[j];

                            var sheetColumn = index % dimensionX;
                            var sheetRow    = index / dimensionX;
                            var sheetPos    = (sheetColumn * frameSize.X, sheetRow *frameSize.Y);

                            dirOutput[j] = new AtlasTexture(texture, UIBox2.FromDimensions(sheetPos, frameSize));
                        }
                    }

                    sheetOffset += frameCount;
                }
            }

            foreach (var(image, _, _, _) in toAtlas)
            {
                image.Dispose();
            }

            RSI = rsi;
        }
Exemplo n.º 15
0
        private static void _render(IRenderHandle renderHandle, Control control, Vector2i position, Color modulate,
                                    UIBox2i?scissorBox)
        {
            if (!control.Visible)
            {
                return;
            }

            // Manual clip test with scissor region as optimization.
            var controlBox = UIBox2i.FromDimensions(position, control.PixelSize);

            if (scissorBox != null)
            {
                var clipMargin  = control.RectDrawClipMargin;
                var clipTestBox = new UIBox2i(controlBox.Left - clipMargin, controlBox.Top - clipMargin,
                                              controlBox.Right + clipMargin, controlBox.Bottom + clipMargin);

                if (!scissorBox.Value.Intersects(clipTestBox))
                {
                    return;
                }
            }

            var handle = renderHandle.DrawingHandleScreen;

            handle.SetTransform(position, Angle.Zero, Vector2.One);
            modulate       *= control.Modulate;
            handle.Modulate = modulate * control.ActualModulateSelf;
            var clip          = control.RectClipContent;
            var scissorRegion = scissorBox;

            if (clip)
            {
                scissorRegion = controlBox;
                if (scissorBox != null)
                {
                    // Make the final scissor region a sub region of scissorBox
                    var s      = scissorBox.Value;
                    var result = s.Intersection(scissorRegion.Value);
                    if (result == null)
                    {
                        // Uhm... No intersection so... don't draw anything at all?
                        return;
                    }

                    scissorRegion = result.Value;
                }

                renderHandle.SetScissor(scissorRegion);
            }

            control.DrawInternal(renderHandle);
            foreach (var child in control.Children)
            {
                _render(renderHandle, child, position + child.PixelPosition, modulate, scissorRegion);
            }

            if (clip)
            {
                renderHandle.SetScissor(scissorBox);
            }
        }
Exemplo n.º 16
0
        public void Render()
        {
            // Basic pre-render busywork.
            // Clear screen to black.
            ClearFramebuffer(Color.Black);

            // Update shared UBOs.
            _updateUniformConstants();

            _setSpace(CurrentSpace.ScreenSpace);

            // Short path to render only the splash.
            if (_drawingSplash)
            {
                _drawSplash(_renderHandle);
                _flushRenderHandle(_renderHandle);
                _window.SwapBuffers();
                return;
            }

            void RenderOverlays(OverlaySpace space)
            {
                using (DebugGroup($"Overlays: {space}"))
                {
                    foreach (var overlay in _overlayManager.AllOverlays
                             .Where(o => o.Space == space)
                             .OrderBy(o => o.ZIndex))
                    {
                        overlay.ClydeRender(_renderHandle);
                    }

                    _flushRenderHandle(_renderHandle);
                }
            }

            if (!_lite)
            {
                RenderOverlays(OverlaySpace.ScreenSpaceBelowWorld);

                _setSpace(CurrentSpace.WorldSpace);

                using (DebugGroup("Lights"))
                {
                    _drawLights();
                }

                using (DebugGroup("Grids"))
                {
                    _drawGrids();
                }

                using (DebugGroup("Entities"))
                {
                    var entityList = new List <SpriteComponent>(100);
                    var map        = _eyeManager.CurrentMap;

                    foreach (var entity in _entityManager.GetEntities())
                    {
                        if (!entity.Transform.IsMapTransform || entity.Transform.MapID != map ||
                            !entity.TryGetComponent(out SpriteComponent sprite) || !sprite.Visible)
                        {
                            continue;
                        }

                        entityList.Add(sprite);
                    }

                    entityList.Sort((a, b) =>
                    {
                        var cmp = ((int)a.DrawDepth).CompareTo((int)b.DrawDepth);
                        if (cmp != 0)
                        {
                            return(cmp);
                        }

                        cmp = a.RenderOrder.CompareTo(b.RenderOrder);

                        if (cmp != 0)
                        {
                            return(cmp);
                        }

                        return(a.Owner.Uid.CompareTo(b.Owner.Uid));
                    });

                    foreach (var sprite in entityList)
                    {
                        Vector2i roundedPos = default;
                        if (sprite.PostShader != null)
                        {
                            _renderHandle.UseRenderTarget(EntityPostRenderTarget);
                            _renderHandle.Clear(new Color());
                            // Calculate viewport so that the entity thinks it's drawing to the same position,
                            // which is necessary for light application,
                            // but it's ACTUALLY drawing into the center of the render target.
                            var spritePos = sprite.Owner.Transform.WorldPosition;
                            var screenPos = _eyeManager.WorldToScreen(spritePos);
                            var(roundedX, roundedY) = roundedPos = (Vector2i)screenPos;
                            var flippedPos = new Vector2i(roundedX, ScreenSize.Y - roundedY);
                            flippedPos -= EntityPostRenderTarget.Size / 2;
                            _renderHandle.Viewport(Box2i.FromDimensions(-flippedPos, ScreenSize));
                        }

                        sprite.OpenGLRender(_renderHandle.DrawingHandleWorld);

                        if (sprite.PostShader != null)
                        {
                            _renderHandle.UseRenderTarget(null);
                            _renderHandle.Viewport(Box2i.FromDimensions(Vector2i.Zero, ScreenSize));

                            _renderHandle.UseShader(sprite.PostShader);
                            _renderHandle.SetSpace(CurrentSpace.ScreenSpace);
                            _renderHandle.SetModelTransform(Matrix3.Identity);

                            var rounded = roundedPos - EntityPostRenderTarget.Size / 2;

                            var box = UIBox2i.FromDimensions(rounded, EntityPostRenderTarget.Size);

                            _renderHandle.DrawTexture(EntityPostRenderTarget.Texture, box.BottomLeft,
                                                      box.TopRight, Color.White, null, 0);

                            _renderHandle.SetSpace(CurrentSpace.WorldSpace);
                            _renderHandle.UseShader(null);
                        }
                    }

                    _flushRenderHandle(_renderHandle);
                }

                RenderOverlays(OverlaySpace.WorldSpace);

                _lightingReady = false;

                _setSpace(CurrentSpace.ScreenSpace);

                RenderOverlays(OverlaySpace.ScreenSpace);
            }

            using (DebugGroup("UI"))
            {
                _userInterfaceManager.Render(_renderHandle);
                _flushRenderHandle(_renderHandle);
            }

            // And finally, swap those buffers!
            _window.SwapBuffers();
        }
Exemplo n.º 17
0
 internal static Vector2i ClampSubRegion(Vector2i size, UIBox2i?subRegionSpecified)
 {
     return(subRegionSpecified == null
         ? size
         : UIBox2i.FromDimensions(Vector2i.Zero, size).Intersection(subRegionSpecified.Value)?.Size ?? default);
 }
Exemplo n.º 18
0
        public void Render()
        {
            _debugStats.Reset();

            // Basic pre-render busywork.
            // Clear screen to black.
            ClearFramebuffer(Color.Black);

            // Update shared UBOs.
            _updateUniformConstants();

            _setSpace(CurrentSpace.ScreenSpace);

            // Short path to render only the splash.
            if (_drawingSplash)
            {
                _drawSplash(_renderHandle);
                _flushRenderHandle(_renderHandle);
                _window.SwapBuffers();
                return;
            }

            void RenderOverlays(OverlaySpace space)
            {
                using (DebugGroup($"Overlays: {space}"))
                {
                    foreach (var overlay in _overlayManager.AllOverlays
                             .Where(o => o.Space == space)
                             .OrderBy(o => o.ZIndex))
                    {
                        overlay.ClydeRender(_renderHandle);
                    }

                    _flushRenderHandle(_renderHandle);
                }
            }

            if (!_lite)
            {
                RenderOverlays(OverlaySpace.ScreenSpaceBelowWorld);

                _setSpace(CurrentSpace.WorldSpace);

                // Calculate world-space AABB for camera, to cull off-screen things.
                var eye         = _eyeManager.CurrentEye;
                var worldBounds = Box2.CenteredAround(eye.Position.Position,
                                                      _screenSize / EyeManager.PIXELSPERMETER * eye.Zoom);

                using (DebugGroup("Lights"))
                {
                    _drawLights(worldBounds);
                }

                using (DebugGroup("Grids"))
                {
                    _drawGrids(worldBounds);
                }

                using (DebugGroup("Entities"))
                {
                    _sortingSpritesList.Clear();
                    var map = _eyeManager.CurrentMap;

                    // So we could calculate the correct size of the entities based on the contents of their sprite...
                    // Or we can just assume that no entity is larger than 10x10 and get a stupid easy check.
                    // TODO: Make this check more accurate.
                    var widerBounds = worldBounds.Enlarged(5);

                    foreach (var sprite in _componentManager.GetAllComponents <SpriteComponent>())
                    {
                        var entity = sprite.Owner;
                        if (!entity.Transform.IsMapTransform || entity.Transform.MapID != map ||
                            !widerBounds.Contains(entity.Transform.WorldPosition) || !sprite.Visible)
                        {
                            continue;
                        }

                        _sortingSpritesList.Add(sprite);
                    }

                    _sortingSpritesList.Sort((a, b) =>
                    {
                        var cmp = ((int)a.DrawDepth).CompareTo((int)b.DrawDepth);
                        if (cmp != 0)
                        {
                            return(cmp);
                        }

                        cmp = a.RenderOrder.CompareTo(b.RenderOrder);

                        if (cmp != 0)
                        {
                            return(cmp);
                        }

                        return(a.Owner.Uid.CompareTo(b.Owner.Uid));
                    });

                    foreach (var sprite in _sortingSpritesList)
                    {
                        Vector2i roundedPos = default;
                        if (sprite.PostShader != null)
                        {
                            _renderHandle.UseRenderTarget(EntityPostRenderTarget);
                            _renderHandle.Clear(new Color());
                            // Calculate viewport so that the entity thinks it's drawing to the same position,
                            // which is necessary for light application,
                            // but it's ACTUALLY drawing into the center of the render target.
                            var spritePos = sprite.Owner.Transform.WorldPosition;
                            var screenPos = _eyeManager.WorldToScreen(spritePos);
                            var(roundedX, roundedY) = roundedPos = (Vector2i)screenPos;
                            var flippedPos = new Vector2i(roundedX, ScreenSize.Y - roundedY);
                            flippedPos -= EntityPostRenderTarget.Size / 2;
                            _renderHandle.Viewport(Box2i.FromDimensions(-flippedPos, ScreenSize));
                        }

                        sprite.OpenGLRender(_renderHandle.DrawingHandleWorld);

                        if (sprite.PostShader != null)
                        {
                            _renderHandle.UseRenderTarget(null);
                            _renderHandle.Viewport(Box2i.FromDimensions(Vector2i.Zero, ScreenSize));

                            _renderHandle.UseShader(sprite.PostShader);
                            _renderHandle.SetSpace(CurrentSpace.ScreenSpace);
                            _renderHandle.SetModelTransform(Matrix3.Identity);

                            var rounded = roundedPos - EntityPostRenderTarget.Size / 2;

                            var box = UIBox2i.FromDimensions(rounded, EntityPostRenderTarget.Size);

                            _renderHandle.DrawTexture(EntityPostRenderTarget.Texture, box.BottomLeft,
                                                      box.TopRight, Color.White, null, 0);

                            _renderHandle.SetSpace(CurrentSpace.WorldSpace);
                            _renderHandle.UseShader(null);
                        }
                    }

                    _flushRenderHandle(_renderHandle);
                }

                RenderOverlays(OverlaySpace.WorldSpace);

                _lightingReady = false;

                _setSpace(CurrentSpace.ScreenSpace);

                RenderOverlays(OverlaySpace.ScreenSpace);
            }

            using (DebugGroup("UI"))
            {
                _userInterfaceManager.Render(_renderHandle);
                _flushRenderHandle(_renderHandle);
            }

            // And finally, swap those buffers!
            _window.SwapBuffers();
        }
Exemplo n.º 19
0
        protected override void FrameUpdate(FrameEventArgs args)
        {
            if (!VisibleInTree)
            {
                return;
            }

            var stringBuilder = new StringBuilder();

            var mouseScreenPos = _inputManager.MouseScreenPosition;
            var screenSize     = _displayManager.ScreenSize;

            MapCoordinates    mouseWorldMap;
            EntityCoordinates mouseGridPos;
            TileRef           tile;

            mouseWorldMap = _eyeManager.ScreenToMap(mouseScreenPos);

            if (_mapManager.TryFindGridAt(mouseWorldMap, out var mouseGrid))
            {
                mouseGridPos = mouseGrid.MapToGrid(mouseWorldMap);
                tile         = mouseGrid.GetTileRef(mouseGridPos);
            }
            else
            {
                mouseGridPos = new EntityCoordinates(_mapManager.GetMapEntityId(mouseWorldMap.MapId), mouseWorldMap.Position);
                tile         = new TileRef(mouseWorldMap.MapId, GridId.Invalid, mouseGridPos.ToVector2i(_entityManager, _mapManager), Tile.Empty);
            }

            var controlHovered = UserInterfaceManager.CurrentlyHovered;

            stringBuilder.AppendFormat(@"Positioning Debug:
Screen Size: {0}
Mouse Pos:
    Screen: {1}
    {2}
    {3}
    {4}
    GUI: {5}", screenSize, mouseScreenPos, mouseWorldMap, mouseGridPos,
                                       tile, controlHovered);

            stringBuilder.AppendLine("\nAttached Entity:");
            if (_playerManager.LocalPlayer?.ControlledEntity == null)
            {
                stringBuilder.AppendLine("No attached entity.");
            }
            else
            {
                var entityTransform   = _playerManager.LocalPlayer.ControlledEntity.Transform;
                var playerWorldOffset = entityTransform.MapPosition;
                var playerScreen      = _eyeManager.WorldToScreen(playerWorldOffset.Position);

                var playerCoordinates = _playerManager.LocalPlayer.ControlledEntity.Transform.Coordinates;

                stringBuilder.AppendFormat(@"    Screen: {0}
    {1}
    {2}
    EntId: {3}
    GridID: {4}", playerScreen, playerWorldOffset, playerCoordinates, entityTransform.Owner.Uid, entityTransform.GridID);
            }

            if (controlHovered != null)
            {
                _uiBox = UIBox2i.FromDimensions(controlHovered.GlobalPixelPosition, controlHovered.PixelSize);
            }

            _contents.Text = stringBuilder.ToString();
            MinimumSizeChanged();
        }