游戏开发论坛

 找回密码
 立即注册
搜索
查看: 45639|回复: 1

一个简单的UI库

[复制链接]

362

主题

3023

帖子

3553

积分

论坛元老

Rank: 8Rank: 8

积分
3553
发表于 2022-5-4 03:31:17 | 显示全部楼层 |阅读模式
源代码 UITest.zip (22.22 KB, 下载次数: 183)
UITest.PNG


代码summary:

namespace UI
{
    abstract class Element
    {
        public int X, Y, DX, DY;
        public CachedVar<int> FullX, FullY;
        public CachedVar<int> MouseX, MouseY;
        public CachedVar<bool> MouseInside, MouseInsideTmp;
        public bool Visible, Enabled;
        public CachedVar<bool> TrueVisible, TrueEnabled;

        public Element Parent; // controls
        public List<Element> Children = new List<Element>(); // forms

        public CachedVar<bool> OnMouseButtonDown, OnMouseButtonUp, OnMouseButtonDownTmp;

        public Element(int x, int y, int dx, int dy)
        {
            X = x;
            Y = y;
            DX = dx;
            DY = dy;

            FullX = new CachedVar<int>(() => Parent == null ? X : Parent.X + X);
            FullY = new CachedVar<int>(() => Parent == null ? Y : Parent.Y + Y);

            MouseX = new CachedVar<int>(() => Core.TheCore.MouseX - (Parent == null ? 0 : Parent.X) - X);
            MouseY = new CachedVar<int>(() => Core.TheCore.MouseY - (Parent == null ? 0 : Parent.Y) - Y);

            MouseInside = new CachedVar<bool>(() =>
                {
                    if (MouseX.v() < 0 || MouseX.v() >= DX || MouseY.v() < 0 || MouseY.v() >= DY
                        || (!TrueVisible.v()))
                        return false;
                    // truely visible:
                    if (Parent == null) // a form
                    {
                        for (int i = Core.TheCore.Root.Count - 1; i >= 0; i--)
                        {
                            Element e = Core.TheCore.Root;
                            if (e == this)
                                break;
                            else
                                if (e.MouseX.v() >= 0 && e.MouseX.v() < e.DX && e.MouseY.v() >= 0 && e.MouseY.v() < e.DY
                                    && e.TrueVisible.v())
                                    return false;
                        }
                        for (int i = Children.Count - 1; i >= 0; i--)
                        {
                            Element e = Children;
                            if (e.MouseX.v() >= 0 && e.MouseX.v() < e.DX && e.MouseY.v() >= 0 && e.MouseY.v() < e.DY
                                && e.TrueVisible.v())
                                return false;
                        }
                        return MouseX.v() >= 0 && MouseX.v() < DX && MouseY.v() >= 0 && MouseY.v() < DY;
                    }
                    else // a control
                    {
                        for (int i = Core.TheCore.Root.Count - 1; i >= 0; i--)
                        {
                            Element e = Core.TheCore.Root;
                            if (e == Parent)
                                break;
                            else
                                if (e.MouseX.v() >= 0 && e.MouseX.v() < e.DX && e.MouseY.v() >= 0 && e.MouseY.v() < e.DY
                                    && e.TrueVisible.v())
                                    return false;
                        }
                        return MouseX.v() >= 0 && MouseX.v() < DX && MouseY.v() >= 0 && MouseY.v() < DY;                        
                    }
                });

            MouseInsideTmp = new CachedVar<bool>(() =>
                {
                    if (MouseX.v() < 0 || MouseX.v() >= DX || MouseY.v() < 0 || MouseY.v() >= DY
                           || (!TrueVisible.v()))
                        return false;
                    // truely visible:
                    if (Parent == null) // a form
                    {
                        for (int i = Core.TheCore.Root.Count - 1; i >= 0; i--)
                        {
                            Element e = Core.TheCore.Root;
                            if (e == this)
                                return MouseX.v() >= 0 && MouseX.v() < DX && MouseY.v() >= 0 && MouseY.v() < DY;
                            else
                                if (e.MouseX.v() >= 0 && e.MouseX.v() < e.DX && e.MouseY.v() >= 0 && e.MouseY.v() < e.DY
                                    && e.TrueVisible.v())
                                    return false;
                        }
                        return false;
                    }
                    else // a control
                        return MouseInside.v();
                });

            Visible = true;
            Enabled = true;

            TrueVisible = new CachedVar<bool>(() => (Parent == null ? true : Parent.Visible) && Visible);
            TrueEnabled = new CachedVar<bool>(() => (Parent == null ? true : Parent.Enabled) && Enabled);

            OnMouseButtonDown = new CachedVar<bool>(() => (TrueEnabled.v() && MouseInside.v()) ? Core.TheCore.MouseButtonDown : false);
            OnMouseButtonUp = new CachedVar<bool>(() => (TrueEnabled.v() && MouseInside.v()) ? Core.TheCore.MouseButtonUp : false);
            OnMouseButtonDownTmp = new CachedVar<bool>(() => (TrueEnabled.v() && MouseInsideTmp.v()) ? Core.TheCore.MouseButtonDown : false);
        }

        public abstract Element Update(); // returns a form to be bringed to the top
        public abstract void Render(Surface backSurface);
    }

    class Core
    {
        public static Core TheCore;

        public int DX, DY;

        public int MouseDX, MouseDY, MouseDZ, MouseX, MouseY;
        public bool MouseLeftButton, MouseRightButton, MouseMiddleButton;
        public bool MouseButtonDown, MouseButtonUp;

        public List<Element> Root = new List<Element>();

        public Core(int dx, int dy)
        {
            DX = dx;
            DY = dy;
        }

        public void Update()
        {
            List<Element> tmps = new List<Element>();
            foreach (Element e in Root)
            {
                Element tmp = e.Update();
                if (tmp != null)
                    tmps.Add(tmp);

                foreach (Element f in e.Children)
                    f.Update();
            }
            foreach (Element tmp in tmps)
            {
                Root.Remove(tmp);
                Root.Add(tmp);
            }
        }

        public void Render(Surface backSurface)
        {
            foreach (Element e in Root)
            {
                if (e.TrueVisible.v())
                    e.Render(backSurface);

                foreach (Element f in e.Children)
                    if (f.TrueVisible.v())
                        f.Render(backSurface);
            }
        }
    }

4

主题

14

帖子

124

积分

灌水组

积分
124
发表于 2024-5-25 13:32:56 | 显示全部楼层
修正一下Button的OnMouseClick的问题
(之前的OnMouseClick一次点击两次)

public enum ButtonState
    {
        Normal,
        Hovered,
        Pressed,

        PressedToHovered,
    }

Diff<ButtonState>.FuncSub = new Func<ButtonState, ButtonState, ButtonState>((a, b) => (a == ButtonState.Hovered && b == ButtonState.Pressed) ? ButtonState.PressedToHovered : a);

dState = new Diff<ButtonState>(ButtonState.Normal, () => State);

OnMouseClick = new Cached<bool>(() => dState == ButtonState.PressedToHovered ? true : false);
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2024-12-22 14:58

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表