508 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
			
		
		
	
	
			508 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
| /*
 | |
| 文件名: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);
 | |
| 
 | |
|     }
 | |
| } |