You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
555 lines
16 KiB
555 lines
16 KiB
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); |
|
} |
|
} |
|
}
|
|
|