/*
文件名:UI_Core.nut
路径:Core/UI_Class/UI_Core.nut
创建日期:2024-11-08	03:25
文件用途:UI核心类
*/
//窗口队列
_SYS_WINDOW_LIST_ <- [];
//基础窗口类 所有UI类继承与本类
class Yosin_BaseWindow extends Layer {
    //父控件
    ParentFlag = null;
    //子控件
    UI_Childrens = null;
    //刷新函数
    UpdateFunc = null;
    //是否可见
    Visible = true;
    //销毁Flag
    DestroyFlag = false;
    //X坐标
    X = null;
    B_X = null;
    //Y坐标
    Y = null;
    B_Y = null;

    function _typeof() {
        return "Yosin_BaseWindow";
    }

    //构造函数
    constructor(IsWindowFlag = false) {
        local ObjectBuf;
        //如果是游戏窗口类 则以Layer为基类 否则以Actor为基类
        if (IsWindowFlag) {
            ObjectBuf = LayerActor_Create();
            base.constructor(ObjectBuf);
        } else {
            base.constructor();
        }

        //子控件list初始化
        UI_Childrens = [];

        SetVisible(Visible);
    }

    //鼠标事件回调
    function OnMouseProc(MousePos_X, MousePos_Y) {
        foreach(Window in UI_Childrens) {
            Window.OnMouseProc(MousePos_X, MousePos_Y);
        }
    }
    //鼠标左键按下回调
    function OnMouseLbDown(MousePos_X, MousePos_Y) {
        foreach(Window in UI_Childrens) {
            Window.OnMouseLbDown(MousePos_X, MousePos_Y);
        }
    }
    //鼠标左键单击回调
    function OnMouseLbClick(MousePos_X, MousePos_Y) {
        foreach(Window in UI_Childrens) {
            Window.OnMouseLbClick(MousePos_X, MousePos_Y);
        }
    }
    //鼠标左键弹起回调
    function OnMouseLbUp(MousePos_X, MousePos_Y) {
        foreach(Window in UI_Childrens) {
            Window.OnMouseLbUp(MousePos_X, MousePos_Y);
        }
    }
    //鼠标右键按下回调
    function OnMouseRbDown(MousePos_X, MousePos_Y) {
        foreach(Window in UI_Childrens) {
            Window.OnMouseRbDown(MousePos_X, MousePos_Y);
        }
    }
    //鼠标右键单击回调
    function OnMouseRbClick(MousePos_X, MousePos_Y) {
        foreach(Window in UI_Childrens) {
            Window.OnMouseRbClick(MousePos_X, MousePos_Y);
        }
    }
    //鼠标右键弹起回调
    function OnMouseRbUp(MousePos_X, MousePos_Y) {
        foreach(Window in UI_Childrens) {
            Window.OnMouseRbUp(MousePos_X, MousePos_Y);
        }
    }
    //鼠标中键按下回调
    function OnMouseMbDown(MousePos_X, MousePos_Y) {
        foreach(Window in UI_Childrens) {
            Window.OnMouseMbDown(MousePos_X, MousePos_Y);
        }
    }
    //鼠标中键单击回调
    function OnMouseMbClick(MousePos_X, MousePos_Y) {
        foreach(Window in UI_Childrens) {
            Window.OnMouseMbClick(MousePos_X, MousePos_Y);
        }
    }
    //鼠标中键弹起回调
    function OnMouseMbUp(MousePos_X, MousePos_Y) {
        foreach(Window in UI_Childrens) {
            Window.OnMouseMbUp(MousePos_X, MousePos_Y);
        }
    }
    //鼠标滚轮事件回调
    function OnMouseWheel(Wheel, MousePos_X, MousePos_Y) {
        foreach(Window in UI_Childrens) {
            Window.OnMouseWheel(Wheel, MousePos_X, MousePos_Y);
        }
    }
    //设置回调事件
    function SetUpdateFunc(Func) {
        UpdateFunc = Func;
    }
    //逻辑
    function Proc(Dt) {
        foreach(Window in UI_Childrens) {
            if (Window.UpdateFunc) Window.UpdateFunc(Window, Dt);
            Window.Proc(Dt);
        }
    }
    //同步坐标
    function SyncPos(X, Y) {
        this.X = X;
        this.Y = Y;
        SetPosition(X, Y);
    }
    //设置是否可见
    function SetVisible(Flag) {
        Visible = Flag;
        base.SetVisible(Flag);
    }

    /*
     * @函数作用: 添加子对象
     * @参数 name
     */
    function AddUIChild(gChild) {
        this.UI_Childrens.append(gChild);
        Addchild(gChild);
        // gChild.Parent = this;
    }

    /*
     * @函数作用: 移除子对象
     * @参数 name
     */
    function RemoveUIChild(gChild) {
        foreach(pos, buf in this.UI_Childrens) {
            if (buf == gChild) {
                this.UI_Childrens.remove(pos);
                break;
            }
        }
        Removechild(gChild);
        // gChild.Parent = this;
    }
}


//游戏窗口类
class Yosin_Window extends Yosin_BaseWindow {
    //窗口名称
    ObjectId = null;
    //宽度
    Width = null;
    //高度
    Height = null;
    //标题高度
    TitleH = null;

    //调试模式
    DeBugMode = false;
    //鼠标相对位置
    M_Xpos = null;
    M_Ypos = null;
    //移动Flag
    MoveFlag = false;

    //是否为独立窗口
    IsIndependent = true;

    constructor(gObjectId, gX, gY, gWidth, gHeight, gTitleH, IsLayer = false) {
        ObjectId = gObjectId;
        //宽度
        Width = gWidth;
        //高度
        Height = gHeight;
        //标题高度
        TitleH = gTitleH;

        //X坐标
        X = gX;
        //Y坐标
        Y = gY;

        //调用原生方法
        base.constructor(IsLayer);

        SetSize(Width, Height);
        SyncPos(X, Y);
    }

    //切换到最上层窗口 即得到焦点时 全局窗口才调用 子窗口请不要调用此函数
    function ResetFocus() {
        this.Visible = true;
        //遍历全局窗口数组将自己移除重新添加在末尾
        foreach(Index, WindowObj in _SYS_WINDOW_LIST_) {
            WindowObj.SetZOrder(10000000 + Index);
            if (WindowObj.ObjectId == this.ObjectId) {
                _SYS_WINDOW_LIST_.remove(Index);
                break;
            }
        }
        _SYS_WINDOW_LIST_.append(this);
        SetZOrder(10000000 + _SYS_WINDOW_LIST_.len());
    }

    /*
     * @函数作用: 移除子对象
     * @参数 子对象名称
     * @返回值 是否有移除了子对象
     */
    function RemoveUIChild(ChildName) {
        foreach(_Index, _Child in UI_Childrens) {
            if (_Child.ObjectId == ChildName) {
                UI_Childrens.remove(_Index);
                return true;
            }
        }
        return false;
    }
    /*
     * @函数作用: 移除子对象类
     * @参数 类   如果传入第二个参数false 则移除所有非该类的子对象
     * @返回值
     */
    function RemoveUIChilds(ClassName, ...) {
        local RemoveIndexArr = [];
        if (vargc == 1 && vargv[0] == false) {
            foreach(_Index, _Child in UI_Childrens) {
                if (!(_Child instanceof ClassName)) {
                    RemoveIndexArr.append(_Index - RemoveIndexArr.len());
                }
            }
        } else {
            foreach(_Index, _Child in UI_Childrens) {
                if (_Child instanceof ClassName) {
                    RemoveIndexArr.append(_Index - RemoveIndexArr.len());
                }
            }
        }
        foreach(SaveIndex in RemoveIndexArr) {
            UI_Childrens.remove(SaveIndex);
        }
    }

    //关闭窗口 -并没有销毁只是隐藏
    function CloseWindow() {
        this.Visible = false;
    }
    //销毁全局UI中的窗口 子窗口只要父窗口被销毁就会被销毁
    function DestroyWindow() {
        this.Visible = false;
        this.DestroyFlag = true;
    }

    //开启Debug模式
    function OpenDeBug() {
        ShowBorder(true);
    }

    //override
    function OnMouseProc(MousePos_X, MousePos_Y) {
        if (!Visible) return;
        //设定拖动逻辑
        if (MoveFlag) {
            //左键拖动
            X = B_X - (M_Xpos - MousePos_X);
            Y = B_Y - (M_Ypos - MousePos_Y);
        }
        //调用原生方法
        base.OnMouseProc(MousePos_X, MousePos_Y);
    }

    //override
    //鼠标左键按下回调
    function OnMouseLbDown(MousePos_X, MousePos_Y) {
        if (!Visible) return;
        //如果点击事件在窗口内
        if (Math.IsIntersectRect(MousePos_X, MousePos_Y, 1, 1, X, Y, Width, Height)) {
            if (IsIndependent) ResetFocus();
            //如果点下去在标题栏
            if (Math.IsIntersectRect(MousePos_X, MousePos_Y, 1, 1, X, Y, Width, TitleH)) {
                MoveFlag = true;
                M_Xpos = MousePos_X; //原始鼠标位置数据
                M_Ypos = MousePos_Y;
                B_X = X; //原始窗口位置
                B_Y = Y;
            }
        }
        //调用原生方法
        base.OnMouseLbDown(MousePos_X, MousePos_Y);
    }
    //override
    //鼠标左键弹起回调
    function OnMouseLbUp(MousePos_X, MousePos_Y) {
        if (!Visible) return;
        if (MoveFlag) {
            MoveFlag = false;
            M_Xpos = null;
            M_Ypos = null;
            B_X = null;
            B_Y = null;
        }
        //调用原生方法
        base.OnMouseLbUp(MousePos_X, MousePos_Y);
    }
    //override
    //鼠标右键按下回调
    function OnMouseRbDown(MousePos_X, MousePos_Y) {
        if (!Visible) return;
        //调用原生方法
        base.OnMouseRbDown(MousePos_X, MousePos_Y);
    }
    //override
    //鼠标右键弹起回调
    function OnMouseRbUp(MousePos_X, MousePos_Y) {
        if (!Visible) return;
        //调用原生方法
        base.OnMouseRbUp(MousePos_X, MousePos_Y);
    }
    //override
    //鼠标滚轮事件回调
    function OnMouseWheel(Flag, MousePos_X, MousePos_Y) {
        if (!Visible) return;
        //调用原生方法
        base.OnMouseWheel(Flag, MousePos_X, MousePos_Y);
    }


}

//创建窗口
function Sq_CreateWindow(ClassName, gObjectId, gX, gY, gWidth, gHeight, gTitleH) {
    foreach(Index, WindowObj in _SYS_WINDOW_LIST_) {
        if (WindowObj.ObjectId == gObjectId) {
            return WindowObj;
        }
    }
    local WindowObj = ClassName(gObjectId, gX, gY, gWidth, gHeight, gTitleH);
    WindowObj.ResetFocus();
    return WindowObj;
}


//窗口逻辑入口  C回调
function _Yosin_Windows_Logic_(Dt, Ui_Layer) {
    local UiObject = Actor(Ui_Layer);
    //遍历窗口队列 如果可见则调用Show
    for (local i = 0; i< _SYS_WINDOW_LIST_.len(); i++) {
        local Window = _SYS_WINDOW_LIST_[i];
        //根据是否显示 决定是否添加到舞台
        if (!Window.Visible && Window.ParentFlag) {
            Window.ParentFlag = null;
            UiObject.Removechild(Window);
            if (Window.DestroyFlag) {
                _SYS_WINDOW_LIST_.remove(i);
                i--;
            }
        } else if (Window.Visible && (!Window.ParentFlag)) {
            Window.ParentFlag = true;
            UiObject.Addchild(Window);
        }
        //无论窗口是否显示都需要调用Proc
        Window.Proc(Dt);
        //无论是否显示都调用Update
        Window.OnUpdate(Dt);
    }
}

//鼠标点击Flag
_Mouse_Click_Flag <- {};
//鼠标逻辑入口
function _Yosin_Windows_Mouse_Logic_(MouseState, Wheel, MousePos_X, MousePos_Y) {
    //克隆一遍窗口列表
    local WindowListF = clone(_SYS_WINDOW_LIST_);
    WindowListF.reverse();

    foreach(Window in WindowListF) {
        if (Window.Visible) {
            switch (MouseState) {
                //常规或者拖动事件
                case 0x305: {
                    Window.OnMouseProc(MousePos_X, MousePos_Y);
                    break;
                }
                //左键按下
                case 0x101: {
                    _Mouse_Click_Flag.LbFlag <- true;
                    Window.OnMouseLbDown(MousePos_X, MousePos_Y);
                    break;
                }
                //左键松开
                case 0x001: {
                    //左键单击
                    if (_Mouse_Click_Flag.LbFlag == true) {
                        _Mouse_Click_Flag.LbFlag <- false;
                        Window.OnMouseLbClick(MousePos_X, MousePos_Y);
                    }
                    Window.OnMouseLbUp(MousePos_X, MousePos_Y);
                    break;
                }
                //右键按下
                case 0x102: {
                    _Mouse_Click_Flag.RbFlag <- true;
                    Window.OnMouseRbDown(MousePos_X, MousePos_Y);
                    break;
                }
                //右键松开
                case 0x002: {
                    //右键单击
                    if (_Mouse_Click_Flag.RbFlag == true) {
                        _Mouse_Click_Flag.RbFlag <- false;
                        Window.OnMouseRbClick(MousePos_X, MousePos_Y);
                    }
                    Window.OnMouseRbUp(MousePos_X, MousePos_Y);
                    break;
                }
                //中键按下
                case 0x103: {
                    _Mouse_Click_Flag.MbFlag <- true;
                    Window.OnMouseMbDown(MousePos_X, MousePos_Y);
                    break;
                }
                //中键松开
                case 0x003: {
                    //中键单击
                    if (_Mouse_Click_Flag.MbFlag == true) {
                        _Mouse_Click_Flag.MbFlag <- false;
                        Window.OnMouseMbClick(MousePos_X, MousePos_Y);
                    }
                    Window.OnMouseMbUp(MousePos_X, MousePos_Y);
                    break;
                }
                //滚轮事件
                case 0x406: {
                    Window.OnMouseWheel(Wheel, MousePos_X, MousePos_Y);
                    break;
                }
            }
            if (Math.IsIntersectRect(MousePos_X, MousePos_Y, 1, 1, Window.X, Window.Y, Window.Width, Window.Height)) return;
        }
    }
}

//输入逻辑函数Map
_Imm_Input_Func_ <- {};
//输入逻辑入口
function _Yosin_Imm_Input_Logic_(Str) {
    foreach(Func in _Imm_Input_Func_) {
        Func(Str);
    }
}