2025-06-07 17:43:34 +08:00

556 lines
16 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using UnityEngine;
namespace FairyGUI
{
/// <summary>
/// Window class.
/// 窗口使用前首先要设置窗口中需要显示的内容这通常是在编辑器里制作好的可以直接使用Window.contentPane进行设置。
/// 建议把设置contentPane等初始化操作放置到Window.onInit方法中。
/// 另外FairyGUI还提供了一套机制用于窗口动态创建。动态创建是指初始时仅指定窗口需要使用的资源等窗口需要显示时才实际开始构建窗口的内容。
/// 首先需要在窗口的构造函数中调用Window.addUISource。这个方法需要一个IUISource类型的参数而IUISource是一个接口
/// 用户需要自行实现载入相关UI包的逻辑。当窗口第一次显示之前IUISource的加载方法将会被调用并等待载入完成后才返回执行Window.OnInit然后窗口才会显示。
///
/// 如果你需要窗口显示时播放动画效果那么覆盖doShowAnimation编写你的动画代码并且在动画结束后调用onShown。覆盖onShown编写其他需要在窗口显示时处理的业务逻辑。
/// 如果你需要窗口隐藏时播放动画效果那么覆盖doHideAnimation编写你的动画代码并且在动画结束时调用Window.hideImmediately注意不是直接调用onHide。覆盖onHide编写其他需要在窗口隐藏时处理的业务逻辑。
/// </summary>
public class Window : GComponent
{
/// <summary>
///
/// </summary>
public bool bringToFontOnClick;
GComponent _frame;
GComponent _contentPane;
GObject _modalWaitPane;
GObject _closeButton;
GObject _dragArea;
GObject _contentArea;
bool _modal;
List<IUISource> _uiSources;
bool _inited;
bool _loading;
protected int _requestingCmd;
#if FAIRYGUI_PUERTS
public Action __onInit;
public Action __onShown;
public Action __onHide;
public Action __doShowAnimation;
public Action __doHideAnimation;
#endif
public Window()
: base()
{
_uiSources = new List<IUISource>();
this.tabStopChildren = true;
bringToFontOnClick = UIConfig.bringWindowToFrontOnClick;
displayObject.onAddedToStage.Add(__addedToStage);
displayObject.onRemovedFromStage.Add(__removeFromStage);
displayObject.onTouchBegin.AddCapture(__touchBegin);
this.gameObjectName = "Window";
SetHome(GRoot.inst);
}
/// <summary>
/// Set a UISource to this window. It must call before the window is shown. When the window is first time to show,
/// UISource.Load is called. Only after all UISource is loaded, the window will continue to init.
/// 为窗口添加一个源。这个方法建议在构造函数调用。当窗口第一次显示前UISource的Load方法将被调用然后只有所有的UISource
/// 都ready后窗口才会继续初始化和显示。
/// </summary>
/// <param name="source"></param>
public void AddUISource(IUISource source)
{
_uiSources.Add(source);
}
/// <summary>
///
/// </summary>
public GComponent contentPane
{
set
{
if (_contentPane != value)
{
if (_contentPane != null)
RemoveChild(_contentPane);
_contentPane = value;
if (_contentPane != null)
{
this.gameObjectName = "Window - " + _contentPane.gameObjectName;
_contentPane.gameObjectName = "ContentPane";
AddChild(_contentPane);
this.SetSize(_contentPane.width, _contentPane.height);
_contentPane.AddRelation(this, RelationType.Size);
_contentPane.fairyBatching = true;
_frame = _contentPane.GetChild("frame") as GComponent;
if (_frame != null)
{
this.closeButton = _frame.GetChild("closeButton");
this.dragArea = _frame.GetChild("dragArea");
this.contentArea = _frame.GetChild("contentArea");
}
}
else
{
_frame = null;
this.gameObjectName = "Window";
}
}
}
get
{
return _contentPane;
}
}
/// <summary>
///
/// </summary>
public GComponent frame
{
get { return _frame; }
}
/// <summary>
///
/// </summary>
public GObject closeButton
{
get { return _closeButton; }
set
{
if (_closeButton != null)
_closeButton.onClick.Remove(closeEventHandler);
_closeButton = value;
if (_closeButton != null)
_closeButton.onClick.Add(closeEventHandler);
}
}
/// <summary>
///
/// </summary>
public GObject dragArea
{
get { return _dragArea; }
set
{
if (_dragArea != value)
{
if (_dragArea != null)
{
_dragArea.draggable = false;
_dragArea.onDragStart.Remove(__dragStart);
}
_dragArea = value;
if (_dragArea != null)
{
GGraph graph = _dragArea as GGraph;
if (graph != null && graph.shape.isEmpty)
graph.DrawRect(_dragArea.width, _dragArea.height, 0, Color.clear, Color.clear);
_dragArea.draggable = true;
_dragArea.onDragStart.Add(__dragStart);
}
}
}
}
/// <summary>
///
/// </summary>
public GObject contentArea
{
get { return _contentArea; }
set { _contentArea = value; }
}
/// <summary>
///
/// </summary>
public GObject modalWaitingPane
{
get { return _modalWaitPane; }
}
/// <summary>
///
/// </summary>
public void Show()
{
GRoot.inst.ShowWindow(this);
}
/// <summary>
///
/// </summary>
/// <param name="r"></param>
public void ShowOn(GRoot r)
{
r.ShowWindow(this);
}
/// <summary>
///
/// </summary>
public void Hide()
{
if (this.isShowing)
DoHideAnimation();
}
/// <summary>
/// Hide window immediately, no OnHide will be called.
/// </summary>
public void HideImmediately()
{
this.root.HideWindowImmediately(this);
}
/// <summary>
/// Make the window be center of the screen.
/// </summary>
/// <param name="r"></param>
/// <param name="restraint">Add relations to ensure keeping center on screen size changed.</param>
public void CenterOn(GRoot r, bool restraint)
{
this.SetXY((int)((r.width - this.width) / 2), (int)((r.height - this.height) / 2));
if (restraint)
{
this.AddRelation(r, RelationType.Center_Center);
this.AddRelation(r, RelationType.Middle_Middle);
}
}
/// <summary>
/// Switch show and hide status.
/// </summary>
public void ToggleStatus()
{
if (isTop)
Hide();
else
Show();
}
/// <summary>
///
/// </summary>
public bool isShowing
{
get { return parent != null; }
}
/// <summary>
///
/// </summary>
public bool isTop
{
get { return parent != null && parent.GetChildIndex(this) == parent.numChildren - 1; }
}
/// <summary>
///
/// </summary>
public bool modal
{
get { return _modal; }
set { _modal = value; }
}
/// <summary>
///
/// </summary>
public void BringToFront()
{
this.root.BringToFront(this);
}
/// <summary>
///
/// </summary>
public void ShowModalWait()
{
ShowModalWait(0);
}
/// <summary>
/// Display a modal waiting sign in the front.
/// 显示一个等待标志在最前面。等待标志的资源可以通过UIConfig.windowModalWaiting。等待标志组件会设置为屏幕大小请内部做好关联。
/// 还可以设定一个requestingCmd作为等待的命令字在CloseModalWait里传入相同的命令字ModalWait将结束否则CloseModalWait无效。
/// </summary>
/// <param name="requestingCmd"></param>
public void ShowModalWait(int requestingCmd)
{
if (requestingCmd != 0)
_requestingCmd = requestingCmd;
if (UIConfig.windowModalWaiting != null)
{
if (_modalWaitPane == null)
{
_modalWaitPane = UIPackage.CreateObjectFromURL(UIConfig.windowModalWaiting);
_modalWaitPane.SetHome(this);
}
LayoutModalWaitPane();
AddChild(_modalWaitPane);
}
}
virtual protected void LayoutModalWaitPane()
{
if (_contentArea != null)
{
Vector2 pt = _frame.LocalToGlobal(Vector2.zero);
pt = this.GlobalToLocal(pt);
_modalWaitPane.SetXY((int)pt.x + _contentArea.x, (int)pt.y + _contentArea.y);
_modalWaitPane.SetSize(_contentArea.width, _contentArea.height);
}
else
_modalWaitPane.SetSize(this.width, this.height);
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public bool CloseModalWait()
{
return CloseModalWait(0);
}
/// <summary>
/// Close modal waiting. If rquestingCmd is equal to the value you transfer in ShowModalWait, mowal wait will be closed.
/// Otherwise, this function has no effect.
/// 关闭模式等待。如果requestingCmd和ShowModalWait传入的不相同则这个函数没有任何动作立即返回。
/// </summary>
/// <param name="requestingCmd"></param>
/// <returns></returns>
public bool CloseModalWait(int requestingCmd)
{
if (requestingCmd != 0)
{
if (_requestingCmd != requestingCmd)
return false;
}
_requestingCmd = 0;
if (_modalWaitPane != null && _modalWaitPane.parent != null)
RemoveChild(_modalWaitPane);
return true;
}
/// <summary>
///
/// </summary>
public bool modalWaiting
{
get { return (_modalWaitPane != null) && _modalWaitPane.inContainer; }
}
/// <summary>
///
/// </summary>
public void Init()
{
if (_inited || _loading)
return;
if (_uiSources.Count > 0)
{
_loading = false;
int cnt = _uiSources.Count;
for (int i = 0; i < cnt; i++)
{
IUISource lib = _uiSources[i];
if (!lib.loaded)
{
lib.Load(__uiLoadComplete);
_loading = true;
}
}
if (!_loading)
_init();
}
else
_init();
}
/// <summary>
///
/// </summary>
virtual protected void OnInit()
{
#if FAIRYGUI_TOLUA
CallLua("OnInit");
#endif
#if FAIRYGUI_PUERTS
if (__onInit != null)
__onInit();
#endif
}
/// <summary>
///
/// </summary>
virtual protected void OnShown()
{
#if FAIRYGUI_TOLUA
CallLua("OnShown");
#endif
#if FAIRYGUI_PUERTS
if (__onShown != null)
__onShown();
#endif
}
/// <summary>
///
/// </summary>
virtual protected void OnHide()
{
#if FAIRYGUI_TOLUA
CallLua("OnHide");
#endif
#if FAIRYGUI_PUERTS
if (__onHide != null)
__onHide();
#endif
}
/// <summary>
///
/// </summary>
virtual protected void DoShowAnimation()
{
#if FAIRYGUI_TOLUA
if (!CallLua("DoShowAnimation"))
OnShown();
#elif FAIRYGUI_PUERTS
if (__doShowAnimation != null)
__doShowAnimation();
else
OnShown();
#else
OnShown();
#endif
}
/// <summary>
///
/// </summary>
virtual protected void DoHideAnimation()
{
#if FAIRYGUI_TOLUA
if (!CallLua("DoHideAnimation"))
HideImmediately();
#elif FAIRYGUI_PUERTS
if (__doHideAnimation != null)
__doHideAnimation();
else
HideImmediately();
#else
HideImmediately();
#endif
}
void __uiLoadComplete()
{
int cnt = _uiSources.Count;
for (int i = 0; i < cnt; i++)
{
IUISource lib = _uiSources[i];
if (!lib.loaded)
return;
}
_loading = false;
_init();
}
void _init()
{
_inited = true;
OnInit();
if (this.isShowing)
DoShowAnimation();
}
override public void Dispose()
{
if (_modalWaitPane != null && _modalWaitPane.parent == null)
_modalWaitPane.Dispose();
//正在加载资源的异步过程中发生意外关闭 应该取消正在加载的load
if (_loading)
{
for (int i = 0; i < _uiSources.Count; ++i)
{
_uiSources[i].Cancel();
}
}
#if FAIRYGUI_PUERTS
__onInit = null;
__onShown = null;
__onHide = null;
__doShowAnimation = null;
__doHideAnimation = null;
#endif
base.Dispose();
}
virtual protected void closeEventHandler(EventContext context)
{
Hide();
}
void __addedToStage()
{
if (!_inited)
Init();
else
DoShowAnimation();
}
void __removeFromStage()
{
CloseModalWait();
OnHide();
}
private void __touchBegin(EventContext context)
{
if (this.isShowing && bringToFontOnClick)
{
BringToFront();
}
}
private void __dragStart(EventContext context)
{
context.PreventDefault();
this.StartDrag((int)context.data);
}
}
}