diff --git a/SquirrelFileConfig.cfg b/SquirrelFileConfig.cfg index c86c899..3b0e61f 100644 --- a/SquirrelFileConfig.cfg +++ b/SquirrelFileConfig.cfg @@ -17,12 +17,17 @@ UI/ObjectClass/BaseNode.nut UI/ObjectClass/Actor.nut UI/ObjectClass/WindowNode.nut UI/ObjectClass/GameWindow.nut +UI/ObjectClass/GameWidget.nut UI/ObjectClass/Sprite.nut +UI/Windows/Widget/BaseWidget.nut + + UI/Windows/System/Cursor.nut +UI/Windows/System/NotiBox.nut UI/Windows/HUD/Window_hud.nut UI/MainUI.nut diff --git a/UI/MainUI.nut b/UI/MainUI.nut index 4fa248f..0bb45f0 100644 --- a/UI/MainUI.nut +++ b/UI/MainUI.nut @@ -15,6 +15,10 @@ function _MainUI_Enter_(UI_Scene) { local TestWindow = sq_CreaterWindowInstance("HUD窗口", Window_hud, 0, 0, 1280, 720, 0); TestWindow.ResetFoucus(); + + local Test1 = sq_CreaterWindowInstance("测试窗口", Window_NotiBox, 150, 150, 364, 356, 20); + Test1.ResetFoucus(); + } //主界面UI事件回调 function _MainUI_HandleEvents_(EventType, EventData) { diff --git a/UI/ObjectClass/Actor.nut b/UI/ObjectClass/Actor.nut index acf084c..52a3e29 100644 --- a/UI/ObjectClass/Actor.nut +++ b/UI/ObjectClass/Actor.nut @@ -43,4 +43,17 @@ class Actor extends BaseNode { sq_SetPos(this.C_Object, Value, vargv[0]); } } + + function GetSize(){ + + } + + function SetVisible(Flag) { + sq_SetVisible(this.C_Object, Flag); + } + + + function GetWorldPos(){ + return sq_GetWorldPos(this.C_Object); + } } diff --git a/UI/ObjectClass/GameWidget.nut b/UI/ObjectClass/GameWidget.nut new file mode 100644 index 0000000..aa4a6e9 --- /dev/null +++ b/UI/ObjectClass/GameWidget.nut @@ -0,0 +1,80 @@ +/* +文件名:GameWidget.nut +路径:UI/ObjectClass/GameWidget.nut +创建日期:2025-10-21 22:05 +文件用途: +*/ +class GameWidget extends WindowNode { + //组件ID + ObjectId = null; + + //本地坐标 + Localtion_X = 0; + Localtion_Y = 0; + + //是否按下 + isLBDown = false; + //是否悬停 + isInRect = false; + + //点击事件 + OnClick = null; + //点击音效 + ClickSound = null; + //悬停音效 + HoverSound = null; + HoverSoundFlag = false; + + constructor(x, y, width, height) { + this.Localtion_X = x; + this.Localtion_Y = y; + this.Width = width; + this.Height = height; + this.X = x; + this.Y = y; + + ObjectId = clock(); + base.constructor(); + SetPos(x, y); + } + + function OnMouseEvent(Type, Data, EventInteractiveFlag) { + if (!Visible) return; + //鼠标移动事件 + if (Type == UI_EVENT.MOUSEMOTION) { + local Pos = GetWorldPos(); + if (Math.IsIntersectRect(Data[0], Data[1], 1, 1, Pos.x, Pos.y, Width, Height)) { + //如果有配置悬停音效 + if (HoverSound && !HoverSoundFlag) { + HoverSoundFlag = true; + //TODO 音效系统 + // Sq_PlaySoundEffect(HoverSound); + } + isInRect = true; + } else { + HoverSoundFlag = false; + isInRect = false; + } + } else if (Type == UI_EVENT.MOUSEBUTTONDOWN) { + local IMouse = Game_Cursor.GetInstance(); + local Pos = GetWorldPos(); + if (Math.IsIntersectRect(IMouse.MouseX, IMouse.MouseY, 1, 1, Pos.x, Pos.y, Width, Height)) { + isLBDown = true; + } + } else if (Type == UI_EVENT.MOUSEBUTTONUP) { + local IMouse = Game_Cursor.GetInstance(); + local Pos = GetWorldPos(); + if (isLBDown && Math.IsIntersectRect(IMouse.MouseX, IMouse.MouseY, 1, 1, Pos.x, Pos.y, Width, Height)) { + if (OnClick) this.OnClick(this); + if (ClickSound) { + //TODO 音效系统 + // Sq_PlaySoundEffect(ClickSound); + } + } + isLBDown = false; + } + foreach (Window in Childrens) { + if (Window instanceof WindowNode) Window.OnMouseEvent(Type, Data); + } + } +} diff --git a/UI/ObjectClass/GameWindow.nut b/UI/ObjectClass/GameWindow.nut index 60978e9..e2f6d62 100644 --- a/UI/ObjectClass/GameWindow.nut +++ b/UI/ObjectClass/GameWindow.nut @@ -4,8 +4,6 @@ 创建日期:2025-10-18 20:58 文件用途:游戏窗口类 */ -_SYS_UI_SCENE_Instance_ <- null; -_SYS_WINDOW_LIST_ <- []; class GameWindow extends WindowNode { //窗口名称 @@ -13,12 +11,39 @@ class GameWindow extends WindowNode { //是否活动窗口Flag IsActiveFlag = false; + //标题高度 + TitleH = null; + //鼠标相对位置 + M_Xpos = null; + M_Ypos = null; + //移动Flag + MoveFlag = false; + + //是否为独立窗口 + IsIndependent = true; + //是否为顶层窗口 + IsTop = false; + function _typeof() { return "GameWindow"; } constructor(WindowName, gX, gY, gWidth, gHeight, gTitleHeight) { base.constructor(); + //窗口名字 + this.WindowName = WindowName; + //宽度 + Width = gWidth; + //高度 + Height = gHeight; + //标题高度 + TitleH = gTitleHeight; + + //X坐标 + X = gX; + //Y坐标 + Y = gY; + SetPos(X, Y); } function ResetFoucus() { @@ -34,83 +59,71 @@ class GameWindow extends WindowNode { SetZOrder(_SYS_WINDOW_LIST_.len()); } - function Proc(Dt) {} + //关闭窗口 -并没有销毁只是隐藏 + function CloseWindow() { + this.Visible = false; + } + + //销毁全局UI中的窗口 子窗口只要父窗口被销毁就会被销毁 + function DestroyWindow() { + this.Visible = false; + this.DestroyFlag = true; + } + + function Proc(Dt) { + base.Proc(Dt); + foreach (Window in Childrens) { + if (Window instanceof WindowNode) Window.Proc(Dt); + } + } //鼠标事件回调 - function OnMouseEvent(Type, Data) { + function OnMouseEvent(Type, Data, EventInteractiveFlag) { if (!Visible) return; foreach (Window in Childrens) { - if (Window instanceof WindowNode) Window.OnMouseEvent(Type, Data); + if ("OnMouseEvent" in Window) Window.OnMouseEvent(Type, Data,EventInteractiveFlag); + } + //鼠标移动事件 + if (Type == UI_EVENT.MOUSEMOTION) { + if (MoveFlag) { + //左键拖动 + X = B_X - (M_Xpos - Data[0]); + Y = B_Y - (M_Ypos - Data[1]); + } + } + //鼠标按下事件 + else if (Type == UI_EVENT.MOUSEBUTTONDOWN) { + local IMouse = Game_Cursor.GetInstance(); + //如果点击事件在窗口内 + if (Math.IsIntersectRect(IMouse.MouseX, IMouse.MouseY, 1, 1, X, Y, Width, Height) && !EventInteractiveFlag) { + if (IsIndependent) ResetFoucus(); + //如果点下去在标题栏 + if (Math.IsIntersectRect(IMouse.MouseX, IMouse.MouseY, 1, 1, X, Y, Width, TitleH)) { + MoveFlag = true; + M_Xpos = IMouse.MouseX; //原始鼠标位置数据 + M_Ypos = IMouse.MouseY; + B_X = X; //原始窗口位置 + B_Y = Y; + } + } + } + //鼠标弹起事件 + else if (Type == UI_EVENT.MOUSEBUTTONUP) { + if (MoveFlag) { + MoveFlag = false; + M_Xpos = null; + M_Ypos = null; + B_X = null; + B_Y = null; + } } } //键盘事件回调 - function OnKeyEvent(Type, Data) { + function OnKeyEvent(Type, Data, EventInteractiveFlag) { if (!Visible) return; foreach (Window in Childrens) { - if (Window instanceof WindowNode) Window.OnKeyEvent(Type, Data); - } - } -} - -/** - * - * @function - * @param {any} WindowName - * @param {GameWindow} WindowClass - * @returns {any} - */ -function sq_CreaterWindowInstance(WindowName, WindowClass, gX, gY, gWidth, gHeight, gTitleHeight) { - foreach (idx, val in _SYS_WINDOW_LIST_) { - if (val.WindowName == WindowName) return val; - } - - local NewWindow = WindowClass(WindowName, gX, gY, gWidth, gHeight, gTitleHeight); - getroottable()._SYS_WINDOW_LIST_.push(NewWindow); - return NewWindow; -} - -/** - * - * @function - * @param {float} Dt - * @returns {void} - */ -function _Global_Windows_Logic_(Dt) { - if (_SYS_UI_SCENE_Instance_) { - for (local i = 0; i < _SYS_WINDOW_LIST_.len(); i++) { - local Window = _SYS_WINDOW_LIST_[i]; - //如果窗口不可见并且 处于演出状态 - if (!Window.Visible && Window.PerformanceState) { - Window.PerformanceState = false; - _SYS_UI_SCENE_Instance_.RemoveChild(Window); - if (Window.DestroyFlag) { - _SYS_WINDOW_LIST_.remove(i); - i--; - } - } else if (Window.Visible && !Window.PerformanceState) { - _SYS_UI_SCENE_Instance_.AddChild(Window); - Window.PerformanceState = true; - } - //无论窗口是否显示都需要调用Proc - Window.Proc(Dt); - } - } -} - -function _Global_Windows_Events_(EventType, EventData) { - //先传递鼠标事件 - Game_Cursor.GetInstance().Event(EventType, EventData); - //事件是否被响应Flag - local EventInteractiveFlag = false; - for (local i = _SYS_WINDOW_LIST_.len() - 1; i > -1; i--) { - local Window = _SYS_WINDOW_LIST_[i]; - if (Window.Visible) { - if (EventType == UI_EVENT.MOUSEMOTION || EventType == UI_EVENT.MOUSEBUTTONDOWN || EventType == UI_EVENT.MOUSEBUTTONUP) { - Window.OnMouseEvent(EventType, EventData); - } else if (EventType == UI_EVENT.KEYDOWN || EventType == UI_EVENT.KEYUP) { - Window.OnKeyEvent(EventType, EventData); - } + if ("OnKeyEvent" in Window) Window.OnKeyEvent(Type, Data); } } } diff --git a/UI/ObjectClass/WindowNode.nut b/UI/ObjectClass/WindowNode.nut index 1d04b4d..233a994 100644 --- a/UI/ObjectClass/WindowNode.nut +++ b/UI/ObjectClass/WindowNode.nut @@ -4,6 +4,8 @@ 创建日期:2025-10-18 20:54 文件用途:窗口节点类 */ +_SYS_UI_SCENE_Instance_ <- null; +_SYS_WINDOW_LIST_ <- []; class WindowNode extends Actor { //演出状态 PerformanceState = false; @@ -20,6 +22,13 @@ class WindowNode extends Actor { //销毁Flag DestroyFlag = false; + //X坐标 + X = null; + B_X = null; + //Y坐标 + Y = null; + B_Y = null; + function _typeof() { return "WindowNode"; } @@ -33,10 +42,85 @@ class WindowNode extends Actor { function SetVisible(Flag) { Visible = Flag; + base.SetVisible(Flag); } function AddChild(Act) { - if (!(Act instanceof WindowNode)) base.AddChild(Act); + base.AddChild(Act); Childrens.push(Act); } + + function Proc(Dt){ + if (UpdateFunc != null) this.UpdateFunc(Dt); + SetPos(X, Y); + } +} + + +/** + * + * @function + * @param {any} WindowName + * @param {GameWindow} WindowClass + * @returns {any} + */ +function sq_CreaterWindowInstance(WindowName, WindowClass, gX, gY, gWidth, gHeight, gTitleHeight) { + foreach (idx, val in _SYS_WINDOW_LIST_) { + if (val.WindowName == WindowName) { + return val; + } + } + + local NewWindow = WindowClass(WindowName, gX, gY, gWidth, gHeight, gTitleHeight); + getroottable()._SYS_WINDOW_LIST_.push(NewWindow); + return NewWindow; +} + +/** + * + * @function + * @param {float} Dt + * @returns {void} + */ +function _Global_Windows_Logic_(Dt) { + if (_SYS_UI_SCENE_Instance_) { + for (local i = 0; i < _SYS_WINDOW_LIST_.len(); i++) { + local Window = _SYS_WINDOW_LIST_[i]; + //如果窗口不可见并且 处于演出状态 + if (!Window.Visible && Window.PerformanceState) { + Window.PerformanceState = false; + _SYS_UI_SCENE_Instance_.RemoveChild(Window); + if (Window.DestroyFlag) { + _SYS_WINDOW_LIST_.remove(i); + i--; + } + } else if (Window.Visible && !Window.PerformanceState) { + _SYS_UI_SCENE_Instance_.AddChild(Window); + Window.PerformanceState = true; + } + //无论窗口是否显示都需要调用Proc + Window.Proc(Dt); + } + } +} + +function _Global_Windows_Events_(EventType, EventData) { + //先传递鼠标事件 + local IMouse = Game_Cursor.GetInstance(); + IMouse.Event(EventType, EventData); + //事件是否被响应Flag + local EventInteractiveFlag = false; + for (local i = _SYS_WINDOW_LIST_.len() - 1; i > -1; i--) { + local Window = _SYS_WINDOW_LIST_[i]; + if (Window.Visible) { + if (EventType == UI_EVENT.MOUSEMOTION || EventType == UI_EVENT.MOUSEBUTTONDOWN || EventType == UI_EVENT.MOUSEBUTTONUP) { + Window.OnMouseEvent(EventType, EventData, EventInteractiveFlag); + } else if (EventType == UI_EVENT.KEYDOWN || EventType == UI_EVENT.KEYUP) { + Window.OnKeyEvent(EventType, EventData, EventInteractiveFlag); + } + if (Math.IsIntersectRect(IMouse.MouseX, IMouse.MouseY, 1, 1, Window.X, Window.Y, Window.Width, Window.Height)) { + EventInteractiveFlag = Window; + } + } + } } diff --git a/UI/Windows/System/NotiBox.nut b/UI/Windows/System/NotiBox.nut new file mode 100644 index 0000000..6cab33a --- /dev/null +++ b/UI/Windows/System/NotiBox.nut @@ -0,0 +1,25 @@ +/* +文件名:NotiBox.nut +路径:UI/Windows/System/NotiBox.nut +创建日期:2025-10-21 21:50 +文件用途: +*/ + +class Window_NotiBox extends GameWindow { + constructor(Name, gX, gY, gWidth, gHeight, gTitleHeight) { + base.constructor(Name, gX, gY, gWidth, gHeight, gTitleHeight); + + InitSprite(); + InitButton(); + } + + function InitSprite() { + local Sp = Sprite("sprite/hud/newantonui.img", 0); + AddChild(Sp); + } + + function InitButton() { + local Btn = GameWidget_BaseButton(40, 40, 56, 24, "sprite/interface/lenheartwindowcommon.img", 12); + AddChild(Btn); + } +} diff --git a/UI/Windows/Widget/BaseWidget.nut b/UI/Windows/Widget/BaseWidget.nut new file mode 100644 index 0000000..087f8b4 --- /dev/null +++ b/UI/Windows/Widget/BaseWidget.nut @@ -0,0 +1,78 @@ +/* +文件名:BaseWidget.nut +路径:UI/Windows/Widget/BaseWidget.nut +创建日期:2025-10-21 22:29 +文件用途:基础控件 +*/ + +class GameWidget_BaseButton extends GameWidget { + //按钮状态 + ButtonState = 0; + //Img路径 + Path = null; + //Img索引 + Idx = null; + + //帧集合 + FrameList = null; + //精灵状态 + SpriteState = -1; + + //按下时的模拟偏移 + DownSimulateOffset = true; + + constructor(X, Y, W, H, Path, Idx) { + this.Path = Path; + this.Idx = Idx; + base.constructor(X, Y, W, H); + + FrameList = []; + + //构造4个精灵 + for (local i = 0; i < 4; i++) { + local Buffer = Sprite(this.Path, this.Idx + i); + Buffer.SetVisible(false); + FrameList.push(Buffer); + AddChild(Buffer); + } + } + + function ChangeFrame() { + //状态更改 刷新精灵帧 + if (ButtonState != SpriteState) { + //按下时模拟偏移的Flag 如果按下 调整Y坐标向下一个单位 + if (DownSimulateOffset) { + if (ButtonState == 2) { + Y += 1; + SetPos(X, Y); + } else if (SpriteState == 2) { + Y -= 1; + SetPos(X, Y); + } + } + if (SpriteState != -1) FrameList[SpriteState].SetVisible(false); + SpriteState = ButtonState; + FrameList[SpriteState].SetVisible(true); + } + } + + function Proc(Dt) { + //不可用 + if (ButtonState == 3) { + } else { + //按下 + if (isLBDown) { + ButtonState = 2; + } + //悬停 + else if (isInRect) { + ButtonState = 1; + } + //普通 + else { + ButtonState = 0; + } + } + ChangeFrame(); + } +} diff --git a/folder-alias.json b/folder-alias.json index e6f26b8..2453007 100644 --- a/folder-alias.json +++ b/folder-alias.json @@ -64,5 +64,11 @@ }, "UI/Windows/System/Cursor.nut": { "description": "鼠标" + }, + "UI/Windows/Widget": { + "description": "控件" + }, + "UI/Windows/Widget/BaseWidget.nut": { + "description": "基础控件" } } \ No newline at end of file diff --git a/internalInterfaceDoc/func.nut b/internalInterfaceDoc/func.nut index eef7b81..e19c360 100644 --- a/internalInterfaceDoc/func.nut +++ b/internalInterfaceDoc/func.nut @@ -110,3 +110,6 @@ function sq_SetScale(a,...){} */ function pow(a,b){} + +function sq_GetWorldPos(a){} +function sq_SetVisible(a,b){} \ No newline at end of file