/* 文件名:6_PlayerChat.nut 路径:User/UI/Window/6_PlayerChat.nut 创建日期:2025-01-20 18:03 文件用途: */ // 消息分类按钮 class PlayerChat_SplicingButton extends Yosin_CommonUi { //按钮状态 State = 0; Sprite = null; SpriteState = -1; FrameList = null; Select = false; cacheY = null; //大按钮 BigButton = null; //三角按钮 TriangleButton = null; //左键按下回调 LBDown = null; //左键单击回调 LBDownOnClick = null; //三角按钮单击回调 OnTriangleClick = null; constructor(X, Y, W, H, Idx, title, titleColor) { base.constructor(X, Y, W, H); cacheY = Y; FrameList = []; Sprite = CL_SpriteObject(); Addchild(Sprite); for (local i = 0; i< 3; i++) { local canvas = Yosin_EmeStretch(W, H, "sprite/interface/lenheartwindowcommon.img", 160 + i * 3); local Sf = canvas.ExportSpriteFrame(); FrameList.push(Sf); } ChangeFrame(); // 文字 local Text = FontAssetManager.GenerateNormal(title, true, { color = titleColor }); Text.SetPosition(12, 1); Addchild(Text); // 三角 local triangle = CL_SpriteObject("sprite/interface/newstyle/windows/chatting/chatting_new.img", Idx); triangle.SetPosition(W - 15, 8); Addchild(triangle); // 按钮 BigButton = Yosin_BaseButton(0, 0, W - 15, H, "sprite/interface/lenheartwindowcommon.img", 70); AddUIChild(BigButton); BigButton.OnClick = function(btn) { if (LBDownOnClick) { LBDownOnClick(this); }; }.bindenv(this); // 三角按钮 TriangleButton = Yosin_BaseButton(W - 15, 0, 15, H, "sprite/interface/lenheartwindowcommon.img", 70); AddUIChild(TriangleButton); TriangleButton.OnClick = function(btn) { if (OnTriangleClick) { OnTriangleClick(this); }; }.bindenv(this); } function ChangeFrame() { //状态更改 刷新精灵帧 if (State != SpriteState) { if (State == 2) { Y = cacheY - 1; SyncPos(X, Y); } else if (SpriteState == 2) { Y = cacheY; SyncPos(X, Y); } SpriteState = State; Sprite.SetFrame(FrameList[SpriteState]); Sprite.SetPosition(0, 0); } } //override //鼠标事件回调 function OnMouseProc(MousePos_X, MousePos_Y, WindowInteractiveFlag) { base.OnMouseProc(MousePos_X, MousePos_Y, WindowInteractiveFlag); if (Select) return; if (isInRect) { State = 1; } else { State = 0; } ChangeFrame(); } //override //鼠标左键按下回调 function OnMouseLbDown(MousePos_X, MousePos_Y, WindowInteractiveFlag) { base.OnMouseLbDown(MousePos_X, MousePos_Y, WindowInteractiveFlag); if (isLBDown && !TriangleButton.isInRect) { ChangeSelectState(true); LBDown(this); } } //更改选中状态 function ChangeSelectState(Flag) { if (Flag) { State = 2; Select = true; ChangeFrame(); } else { State = 0; Select = false; ChangeFrame(); } } } class PlayerChat_InputBox extends Yosin_CommonUi { //表情按钮 EmotionButton = null; //框背景 BoxBackground = null; //聊天信息类型 ChatType = 0; //文本 TextObject = null; Text = ""; //输入光标 InputCursor = null; //输入位置 InputPos = 0; //是否获取焦点 IsFocus = false; constructor() { base.constructor(0, 0, 321, 28); // 按钮 EmotionButton = Yosin_BaseButton(0, 0, 24, 24, "sprite/interface/newstyle/windows/chatting/chatting_new.img", 37); EmotionButton.DownSimulateOffset = false; AddUIChild(EmotionButton); EmotionButton.OnClick = function(btn) { }.bindenv(this); //输入框 BoxBackground = Yosin_NineBoxStretch(297, 25, "sprite/interface/newstyle/windows/chatting/chatting_ver4.img", 265); BoxBackground.SetPosition(24, 0); Addchild(BoxBackground); //文本 TextObject = FontAssetManager.GenerateNormal("", false, { color = sq_RGBA(255, 255, 255, 250) }); TextObject.SetPosition(28, 3); Addchild(TextObject); //输入光标 InputCursor = CreateCursor(); InputCursor.SetUpdateFunc(function(Object, Dt) { //处于焦点中执行 if (IsFocus) { //光标闪烁逻辑 { if (!(Object.Var.rawin("TimeFlag"))) { Object.Var.TimeFlag <- 0; Object.Var.VisibleFlag <- false; } Object.Var.TimeFlag += Dt; if (Object.Var.TimeFlag >= 500) { Object.Var.TimeFlag <- 0; Object.SetVisible(Object.Var.VisibleFlag); Object.Var.VisibleFlag <- !Object.Var.VisibleFlag; } } //同步光标位置逻辑 { Object.SetPosition(TextObject.X + TextObject.GetSize().w, 4); } } }.bindenv(this)); Addchild(InputCursor); _Imm_Input_Func_.rawset(C_Object, Imm_Input.bindenv(this)); } //判断是否中文字符 function IsChineseChar(code) { return (code & 0x80) != 0; } //接收文本数据 function Imm_Input(str) { if (!this) return -1; if (!IsFocus) return; //退格键 if (str == "\b") { if (this.Text.len() > 0) { this.Text = Sq_RemoveStringLast(this.Text); } } //换行符去掉 else if (str != "\r") this.Text += str; //同步文本对象数据 TextObject.SetText(this.Text); //每次设置文本时确保光标显示 InputCursor.SetVisible(true); InputCursor.Var.TimeFlag <- 0; InputCursor.Var.VisibleFlag <- false; } function CreateCursor() { local Canvas = CL_CanvasObject(); // 重设大小并清空 Canvas.ResizeAndClear(1, 15); // 开始绘制 Canvas.BeginDraw(); Canvas.SetFillBrush(sq_RGBA(255, 255, 255, 250)); Canvas.SetStrokeBrush(sq_RGBA(255, 255, 255, 250)); Canvas.DrawLine(1, 1, 1, 15); // 结束绘制 Canvas.EndDraw(); Canvas.SetVisible(false); return Canvas; } //鼠标左键单击回调 function OnMouseLbClick(MousePos_X, MousePos_Y, WindowInteractiveFlag) { local Pos = GetWorldPosition(); if (Math.IsIntersectRect(MousePos_X, MousePos_Y, 1, 1, Pos.x, Pos.y, Width, Height)) { SetFocus(true); } else { SetFocus(false); } } //设置焦点模式 function SetFocus(Flag) { IsFocus = Flag; InputCursor.SetVisible(Flag); Sq_SetImmEnabled(Flag); } //回车键回调 function OnEnter() { SetFocus(!IsFocus); //发送消息了 if (!IsFocus && this.Text.len() > 0) { MySocket.Send(PACKET_ID.SEND_CHAT_MESSAGE, { msg = this.Text, type = this.ChatType }); this.Text = ""; TextObject.SetText(this.Text); //还原光标位置避免闪烁 InputCursor.SetPosition(TextObject.X, 4); } } } //消息渲染窗口 class _PlayerChat_RenderMsg_Window extends Yosin_Window { //是否为独立窗口 IsIndependent = false; //是否为图层窗口 IsLayer = true; //消息文本对象 MsgTextObject = null; //文本Y轴偏移量 TextYposOffset = 0; constructor(gObjectId, gX, gY, gWidth, gHeight, gTitleH) { base.constructor(gObjectId, gX, gY, gWidth, gHeight, gTitleH); SetClipRect(0, 0, 321, 534); MsgTextObject = CL_CanvasObject(); Addchild(MsgTextObject); } //渲染消息 function RenderMsg() { MsgTextObject.ResizeAndClear(321, 5000); MsgTextObject.BeginDraw(); TextYposOffset = 0; foreach(Index, Msg in Parent.MsgManager) { local Name = FontAssetManager.GenerateNormal(Msg.name + ": ", false, { color = sq_RGBA(255, 255, 255, 255), }); MsgTextObject.DrawActor(Name, 0, TextYposOffset); local Text = FontAssetManager.GenerateNormal(Msg.msg, false, { color = sq_RGBA(255, 255, 255, 255), wrap_width = 300 - Name.GetSize().w }); MsgTextObject.DrawActor(Text, Name.GetSize().w, TextYposOffset); //绘制完成后增加Y轴的偏移量 TextYposOffset += Text.GetSize().h; } if (TextYposOffset > 534) { Parent.ScrollObject.SetScrollBarHeight(534.0 / TextYposOffset.tofloat() * 534.0); } MsgTextObject.EndDraw(); } //设置滚动位置 function SetScrollPos(Rate) { MsgTextObject.SetPosition(0, -(TextYposOffset - 534) * Rate); } } //主类 class _PlayerChat extends Yosin_Window { //是否为顶层窗口 IsTop = true; //消息分类按钮List SplicingButtonList = null; //消息管理器 MsgManager = null; //消息文本对象 MsgTextWindow = null; //聊天输入框 InputBox = null; //滚动条 ScrollObject = null; constructor(gObjectId, gX, gY, gWidth, gHeight, gTitleH) { SplicingButtonList = []; MsgManager = []; base.constructor(gObjectId, gX, gY, gWidth, gHeight, gTitleH); //渲染背景 RenderBackground(); //注册组件 RegisterWidget(); //注册按键回调事件 Input.RegisterGameKeyCode(CONTROLLER.OPTION_HOTKEY_ENTER, function(Flag) { //抬起的时候 if (Flag == 0) { InputBox.OnEnter(); } }.bindenv(this)); getroottable().ClientChatWindow <- this; } function RenderBackground() { local Bg = CL_CanvasObject(); // 重设大小并清空 Bg.ResizeAndClear(332, 600); // 开始绘制 Bg.BeginDraw(); local topLine = CL_SpriteFrameObject("sprite/interface/newstyle/windows/chatting/chatting_ver4.img", 159); Bg.DrawSpriteFrame(topLine, 0, 0); local topBg = CL_SpriteObject("sprite/interface/newstyle/windows/chatting/chatting_ver4.img", 160); topBg.SetPosition(0, 2); topBg.SetScale(1, 28); Bg.DrawSprite(topBg); local bimg = CL_SpriteFrameObject("sprite/interface/newstyle/windows/chatting/chatting_ver4.img", 161); Bg.DrawSpriteFrame(bimg, 0, 30); local bottomBg = CL_SpriteObject("sprite/interface/newstyle/windows/chatting/chatting_ver4.img", 162); bottomBg.SetPosition(0, 561); bottomBg.SetScale(1, 38); Bg.DrawSprite(bottomBg); local bottomLine = CL_SpriteFrameObject("sprite/interface/newstyle/windows/chatting/chatting_ver4.img", 163); Bg.DrawSpriteFrame(bottomLine, 0, 598); // 消息 local PlayerChatBround = Yosin_NineBoxStretch(321, 544, "sprite/interface/newstyle/windows/chatting/chatting_ver4.img", 265); PlayerChatBround.SetPosition(6, 29); Bg.DrawSprite(PlayerChatBround); // 结束绘制 Bg.EndDraw(); Addchild(Bg); } function RegisterWidget() { // 普通 local ordinary = PlayerChat_SplicingButton(6, 10, 53, 20, 8, "普通", sq_RGBA(255, 255, 255, 255)); ordinary.ChangeSelectState(true); AddUIChild(ordinary); ordinary.LBDown = function(btn) { ChangeSplicing(0); }.bindenv(this); ordinary.LBDownOnClick = function(btn) {}.bindenv(this); ordinary.OnTriangleClick = function(btn) {}.bindenv(this); SplicingButtonList.push(ordinary); // 公会 local notice = PlayerChat_SplicingButton(60, 10, 53, 20, 47, "公会", sq_RGBA(254, 77, 245, 255)); AddUIChild(notice); notice.LBDown = function(btn) { ChangeSplicing(1); }.bindenv(this); notice.LBDownOnClick = function(btn) {}.bindenv(this); notice.OnTriangleClick = function(btn) {}.bindenv(this); SplicingButtonList.push(notice); // 频道 local channel = PlayerChat_SplicingButton(114, 10, 53, 20, 48, "频道", sq_RGBA(221, 153, 197, 255)); AddUIChild(channel); channel.LBDown = function(btn) { ChangeSplicing(2); }.bindenv(this); channel.LBDownOnClick = function(btn) {}.bindenv(this); channel.OnTriangleClick = function(btn) {}.bindenv(this); SplicingButtonList.push(channel); // 募集 local raise = PlayerChat_SplicingButton(168, 10, 53, 20, 49, "募集", sq_RGBA(105, 212, 238, 255)); AddUIChild(raise); raise.LBDown = function(btn) { ChangeSplicing(3); }.bindenv(this); raise.LBDownOnClick = function(btn) {}.bindenv(this); raise.OnTriangleClick = function(btn) {}.bindenv(this); SplicingButtonList.push(raise); //滚动条 ScrollObject = Yosin_ScrollBar(315, 32, 537, 20); ScrollObject.SetScrollBarState(false); ScrollObject.SetChangeCallBack(function(Value) { MsgTextWindow.SetScrollPos(Value); }.bindenv(this)); AddUIChild(ScrollObject); //聊天输入框 InputBox = PlayerChat_InputBox(); InputBox.SetPosition(6, Height - 28); AddUIChild(InputBox); //信息画布窗口 MsgTextWindow = _PlayerChat_RenderMsg_Window("聊天信息渲染窗口", 12, 34, 321, 550, 0); MsgTextWindow.SetPosition(12, 34); AddUIChild(MsgTextWindow); } function ChangeSplicing(Idx) { foreach(Index, Button in SplicingButtonList) { if (Index == Idx) continue; Button.Select = false; Button.State = 0; Button.ChangeFrame(); } } //push消息 function PushMsg(Msg) { MsgManager.push(Msg); local Flag = (ScrollObject.Controller.CurPos >= 0.8) || ScrollObject.ScrollButton == null; //渲染消息 MsgTextWindow.RenderMsg(); if (Flag) { ScrollObject.SetScrollBarValue(1); } } //override //鼠标滚轮事件回调 function OnMouseWheel(Wheel, MousePos_X, MousePos_Y, WindowInteractiveFlag) { if (!Visible) return; base.OnMouseWheel(Wheel, MousePos_X, MousePos_Y, WindowInteractiveFlag); local Pos = GetWorldPosition(); if (MousePos_X > Pos.x) { if (Wheel == -1) { ScrollObject.SetScroll(true); } if (Wheel == 1) { ScrollObject.SetScroll(false); } } } //逻辑入口 function Proc(Dt) { SyncPos(X, Y); base.Proc(Dt); } }