using System;
using System.Collections.Generic;
using UnityEngine;
namespace FairyGUI
{
///
/// GRoot is a topmost component of UI display list.You dont need to create GRoot. It is created automatically.
///
public class GRoot : GComponent
{
///
///
///
public static float contentScaleFactor
{
get { return UIContentScaler.scaleFactor; }
}
///
///
///
public static int contentScaleLevel
{
get { return UIContentScaler.scaleLevel; }
}
GGraph _modalLayer;
GObject _modalWaitPane;
List _popupStack;
List _justClosedPopups;
HashSet _specialPopups;
GObject _tooltipWin;
GObject _defaultTooltipWin;
internal static GRoot _inst;
public static GRoot inst
{
get
{
if (_inst == null)
Stage.Instantiate();
return _inst;
}
}
public GRoot()
{
this.name = this.rootContainer.name = this.rootContainer.gameObject.name = "GRoot";
this.opaque = false;
_popupStack = new List();
_justClosedPopups = new List();
_specialPopups = new HashSet();
Stage.inst.onTouchBegin.AddCapture(__stageTouchBegin);
Stage.inst.onTouchEnd.AddCapture(__stageTouchEnd);
}
override public void Dispose()
{
base.Dispose();
Stage.inst.onTouchBegin.RemoveCapture(__stageTouchBegin);
Stage.inst.onTouchEnd.RemoveCapture(__stageTouchEnd);
}
///
/// Set content scale factor.
///
/// Design resolution of x axis.
/// Design resolution of y axis.
public void SetContentScaleFactor(int designResolutionX, int designResolutionY)
{
SetContentScaleFactor(designResolutionX, designResolutionY, UIContentScaler.ScreenMatchMode.MatchWidthOrHeight);
}
///
/// Set content scale factor.
///
/// Design resolution of x axis.
/// Design resolution of y axis.
/// Match mode.
public void SetContentScaleFactor(int designResolutionX, int designResolutionY, UIContentScaler.ScreenMatchMode screenMatchMode)
{
UIContentScaler scaler = Stage.inst.gameObject.GetComponent();
scaler.designResolutionX = designResolutionX;
scaler.designResolutionY = designResolutionY;
scaler.scaleMode = UIContentScaler.ScaleMode.ScaleWithScreenSize;
scaler.screenMatchMode = screenMatchMode;
scaler.ApplyChange();
ApplyContentScaleFactor();
}
///
///
///
///
public void SetContentScaleFactor(float constantScaleFactor)
{
UIContentScaler scaler = Stage.inst.gameObject.GetComponent();
scaler.scaleMode = UIContentScaler.ScaleMode.ConstantPixelSize;
scaler.constantScaleFactor = constantScaleFactor;
scaler.ApplyChange();
ApplyContentScaleFactor();
}
///
/// This is called after screen size changed.
///
public void ApplyContentScaleFactor()
{
this.SetSize(Mathf.CeilToInt(Stage.inst.width / UIContentScaler.scaleFactor), Mathf.CeilToInt(Stage.inst.height / UIContentScaler.scaleFactor));
this.SetScale(UIContentScaler.scaleFactor, UIContentScaler.scaleFactor);
}
///
/// Display a window.
///
///
public void ShowWindow(Window win)
{
AddChild(win);
AdjustModalLayer();
}
///
/// Call window.Hide
/// 关闭一个窗口。将调用Window.Hide方法。
///
///
public void HideWindow(Window win)
{
win.Hide();
}
///
/// Remove a window from stage immediatelly. window.Hide/window.OnHide will never be called.
///立刻关闭一个窗口。不会调用Window.Hide方法,Window.OnHide也不会被调用。
///
///
public void HideWindowImmediately(Window win)
{
HideWindowImmediately(win, false);
}
///
/// Remove a window from stage immediatelly. window.Hide/window.OnHide will never be called.
/// 立刻关闭一个窗口。不会调用Window.Hide方法,Window.OnHide也不会被调用。
///
///
/// True to dispose the window.
public void HideWindowImmediately(Window win, bool dispose)
{
if (win.parent == this)
RemoveChild(win, dispose);
else if (dispose)
win.Dispose();
AdjustModalLayer();
}
///
/// 将一个窗口提到所有窗口的最前面
///
///
public void BringToFront(Window win)
{
int cnt = this.numChildren;
int i;
if (_modalLayer != null && _modalLayer.parent != null && !win.modal)
i = GetChildIndex(_modalLayer) - 1;
else
i = cnt - 1;
for (; i >= 0; i--)
{
GObject g = GetChildAt(i);
if (g == win)
return;
if (g is Window)
break;
}
if (i >= 0)
SetChildIndex(win, i);
}
///
/// Display a modal layer and a waiting sign in the front.
/// 显示一个半透明层和一个等待标志在最前面。半透明层的颜色可以通过UIConfig.modalLayerColor设定。
/// 等待标志的资源可以通过UIConfig.globalModalWaiting。等待标志组件会设置为屏幕大小,请内部做好关联。
///
public void ShowModalWait()
{
if (UIConfig.globalModalWaiting != null)
{
if (_modalWaitPane == null || _modalWaitPane.isDisposed)
{
_modalWaitPane = UIPackage.CreateObjectFromURL(UIConfig.globalModalWaiting);
_modalWaitPane.SetHome(this);
}
_modalWaitPane.SetSize(this.width, this.height);
_modalWaitPane.AddRelation(this, RelationType.Size);
AddChild(_modalWaitPane);
}
}
///
/// Hide modal layer and waiting sign.
///
public void CloseModalWait()
{
if (_modalWaitPane != null && _modalWaitPane.parent != null)
RemoveChild(_modalWaitPane);
}
///
/// Close all windows except modal windows.
///
public void CloseAllExceptModals()
{
GObject[] arr = _children.ToArray();
foreach (GObject g in arr)
{
if ((g is Window) && !(g as Window).modal)
HideWindowImmediately(g as Window);
}
}
///
/// Close all windows.
///
public void CloseAllWindows()
{
GObject[] arr = _children.ToArray();
foreach (GObject g in arr)
{
if (g is Window)
HideWindowImmediately(g as Window);
}
}
///
/// Get window on top.
///
///
public Window GetTopWindow()
{
int cnt = this.numChildren;
for (int i = cnt - 1; i >= 0; i--)
{
GObject g = this.GetChildAt(i);
if (g is Window)
{
return (Window)(g);
}
}
return null;
}
///
///
///
public GGraph modalLayer
{
get
{
if (_modalLayer == null || _modalLayer.isDisposed)
CreateModalLayer();
return _modalLayer;
}
}
void CreateModalLayer()
{
_modalLayer = new GGraph();
_modalLayer.DrawRect(this.width, this.height, 0, Color.white, UIConfig.modalLayerColor);
_modalLayer.AddRelation(this, RelationType.Size);
_modalLayer.name = _modalLayer.gameObjectName = "ModalLayer";
_modalLayer.SetHome(this);
}
///
/// Return true if a modal window is on stage.
///
public bool hasModalWindow
{
get { return _modalLayer != null && _modalLayer.parent != null; }
}
///
/// Return true if modal waiting layer is on stage.
///
public bool modalWaiting
{
get
{
return (_modalWaitPane != null) && _modalWaitPane.onStage;
}
}
///
/// Get current touch target. (including hover)
///
public GObject touchTarget
{
get
{
return DisplayObjectToGObject(Stage.inst.touchTarget);
}
}
///
///
///
///
///
public GObject DisplayObjectToGObject(DisplayObject obj)
{
while (obj != null)
{
if (obj.gOwner != null)
return obj.gOwner;
obj = obj.parent;
}
return null;
}
private void AdjustModalLayer()
{
if (_modalLayer == null || _modalLayer.isDisposed)
CreateModalLayer();
int cnt = this.numChildren;
if (_modalWaitPane != null && _modalWaitPane.parent != null)
SetChildIndex(_modalWaitPane, cnt - 1);
for (int i = cnt - 1; i >= 0; i--)
{
GObject g = this.GetChildAt(i);
if ((g is Window) && (g as Window).modal)
{
if (_modalLayer.parent == null)
AddChildAt(_modalLayer, i);
else
SetChildIndexBefore(_modalLayer, i);
return;
}
}
if (_modalLayer.parent != null)
RemoveChild(_modalLayer);
}
///
/// Show a popup object.
/// 显示一个popup。
/// popup的特点是点击popup对象外的区域,popup对象将自动消失。
///
///
public void ShowPopup(GObject popup)
{
ShowPopup(popup, null, PopupDirection.Auto, false);
}
///
/// Show a popup object along with the specific target object.
/// 显示一个popup。将popup显示在指定对象的上边或者下边。
/// popup的特点是点击popup对象外的区域,popup对象将自动消失。
///
///
///
public void ShowPopup(GObject popup, GObject target)
{
ShowPopup(popup, target, PopupDirection.Auto, false);
}
[Obsolete]
public void ShowPopup(GObject popup, GObject target, object downward)
{
ShowPopup(popup, target,
downward == null ? PopupDirection.Auto : ((bool)downward == true ? PopupDirection.Down : PopupDirection.Up),
false);
}
///
/// Show a popup object along with the specific target object.
/// 显示一个popup。将popup显示在指定对象的上方或者下方。
/// popup的特点是点击popup对象外的区域,popup对象将自动消失。
///
///
///
///
public void ShowPopup(GObject popup, GObject target, PopupDirection dir)
{
ShowPopup(popup, target, dir, false);
}
///
/// Show a popup object along with the specific target object.
/// 显示一个popup。将popup显示在指定对象的上方或者下方。
/// popup的特点是点击popup对象外的区域,popup对象将自动消失。
/// 默认情况下,popup在touchEnd事件中关闭;特别设置closeUntilUpEvent=true则可使该popup在touchEnd中才关闭。
///
///
///
///
///
public void ShowPopup(GObject popup, GObject target, PopupDirection dir, bool closeUntilUpEvent)
{
if (_popupStack.Count > 0)
{
int k = _popupStack.IndexOf(popup);
if (k != -1)
{
for (int i = _popupStack.Count - 1; i >= k; i--)
{
int last = _popupStack.Count - 1;
GObject obj = _popupStack[last];
ClosePopup(obj);
_popupStack.RemoveAt(last);
_specialPopups.Remove(obj);
}
}
}
_popupStack.Add(popup);
if (closeUntilUpEvent)
_specialPopups.Add(popup);
if (target != null)
{
GObject p = target;
while (p != null)
{
if (p.parent == this)
{
if (popup.sortingOrder < p.sortingOrder)
{
popup.sortingOrder = p.sortingOrder;
}
break;
}
p = p.parent;
}
}
AddChild(popup);
AdjustModalLayer();
if ((popup is Window) && target == null && dir == PopupDirection.Auto)
return;
Vector2 pos = GetPoupPosition(popup, target, dir);
popup.xy = pos;
}
[Obsolete]
public Vector2 GetPoupPosition(GObject popup, GObject target, object downward)
{
return GetPoupPosition(popup, target,
downward == null ? PopupDirection.Auto : ((bool)downward == true ? PopupDirection.Down : PopupDirection.Up));
}
///
///
///
///
///
///
///
public Vector2 GetPoupPosition(GObject popup, GObject target, PopupDirection dir)
{
Vector2 pos;
Vector2 size = Vector2.zero;
if (target != null)
{
pos = target.LocalToRoot(Vector2.zero, this);
size = target.LocalToRoot(target.size, this) - pos;
}
else
{
pos = this.GlobalToLocal(Stage.inst.touchPosition);
}
float xx, yy;
xx = pos.x;
if (xx + popup.width > this.width)
xx = xx + size.x - popup.width;
yy = pos.y + size.y;
if ((dir == PopupDirection.Auto && yy + popup.height > this.height)
|| dir == PopupDirection.Up)
{
yy = pos.y - popup.height - 1;
if (yy < 0)
{
yy = 0;
xx += size.x / 2;
}
}
return new Vector2(Mathf.RoundToInt(xx), Mathf.RoundToInt(yy));
}
///
/// If a popup is showing, then close it; otherwise, open it.
///
///
public void TogglePopup(GObject popup)
{
TogglePopup(popup, null, PopupDirection.Auto, false);
}
///
///
///
///
///
public void TogglePopup(GObject popup, GObject target)
{
TogglePopup(popup, target, PopupDirection.Auto, false);
}
[Obsolete]
public void TogglePopup(GObject popup, GObject target, object downward)
{
TogglePopup(popup, target,
downward == null ? PopupDirection.Auto : ((bool)downward == true ? PopupDirection.Down : PopupDirection.Up),
false);
}
///
///
///
///
///
///
public void TogglePopup(GObject popup, GObject target, PopupDirection dir)
{
TogglePopup(popup, target, dir, false);
}
///
///
///
///
///
///
///
public void TogglePopup(GObject popup, GObject target, PopupDirection dir, bool closeUntilUpEvent)
{
if (_justClosedPopups.IndexOf(popup) != -1)
return;
ShowPopup(popup, target, dir, closeUntilUpEvent);
}
///
/// Close all popups.
///
public void HidePopup()
{
HidePopup(null);
}
///
/// Close a popup.
///
///
public void HidePopup(GObject popup)
{
if (popup != null)
{
int k = _popupStack.IndexOf(popup);
if (k != -1)
{
for (int i = _popupStack.Count - 1; i >= k; i--)
{
int last = _popupStack.Count - 1;
GObject obj = _popupStack[last];
ClosePopup(obj);
_popupStack.RemoveAt(last);
_specialPopups.Remove(obj);
}
}
}
else
{
foreach (GObject obj in _popupStack)
ClosePopup(obj);
_popupStack.Clear();
_specialPopups.Clear();
}
}
///
///
///
public bool hasAnyPopup
{
get { return _popupStack.Count > 0; }
}
void ClosePopup(GObject target)
{
if (target.parent != null)
{
if (target is Window)
((Window)target).Hide();
else
RemoveChild(target);
}
}
///
///
///
///
public void ShowTooltips(string msg)
{
ShowTooltips(msg, 0.1f);
}
///
///
///
///
///
public void ShowTooltips(string msg, float delay)
{
if (_defaultTooltipWin == null || _defaultTooltipWin.isDisposed)
{
string resourceURL = UIConfig.tooltipsWin;
if (string.IsNullOrEmpty(resourceURL))
{
Debug.LogWarning("FairyGUI: UIConfig.tooltipsWin not defined");
return;
}
_defaultTooltipWin = UIPackage.CreateObjectFromURL(resourceURL);
_defaultTooltipWin.SetHome(this);
_defaultTooltipWin.touchable = false;
}
_defaultTooltipWin.text = msg;
ShowTooltipsWin(_defaultTooltipWin, delay);
}
///
///
///
///
public void ShowTooltipsWin(GObject tooltipWin)
{
ShowTooltipsWin(tooltipWin, 0.1f);
}
///
///
///
///
///
public void ShowTooltipsWin(GObject tooltipWin, float delay)
{
HideTooltips();
_tooltipWin = tooltipWin;
Timers.inst.Add(delay, 1, __showTooltipsWin);
}
void __showTooltipsWin(object param)
{
if (_tooltipWin == null)
return;
float xx = Stage.inst.touchPosition.x + 10;
float yy = Stage.inst.touchPosition.y + 20;
Vector2 pt = this.GlobalToLocal(new Vector2(xx, yy));
xx = pt.x;
yy = pt.y;
if (xx + _tooltipWin.width > this.width)
xx = xx - _tooltipWin.width;
if (yy + _tooltipWin.height > this.height)
{
yy = yy - _tooltipWin.height - 1;
if (yy < 0)
yy = 0;
}
_tooltipWin.x = Mathf.RoundToInt(xx);
_tooltipWin.y = Mathf.RoundToInt(yy);
AddChild(_tooltipWin);
}
///
///
///
public void HideTooltips()
{
if (_tooltipWin != null)
{
if (_tooltipWin.parent != null)
RemoveChild(_tooltipWin);
_tooltipWin = null;
}
}
///
///
///
public GObject focus
{
get
{
GObject obj = DisplayObjectToGObject(Stage.inst.focus);
if (obj != null && !IsAncestorOf(obj))
return null;
else
return obj;
}
set
{
if (value == null)
Stage.inst.focus = null;
else
Stage.inst.focus = value.displayObject;
}
}
void __stageTouchBegin(EventContext context)
{
if (_tooltipWin != null)
HideTooltips();
CheckPopups(true);
}
void __stageTouchEnd(EventContext context)
{
CheckPopups(false);
}
void CheckPopups(bool touchBegin)
{
if (touchBegin)
_justClosedPopups.Clear();
if (_popupStack.Count > 0)
{
DisplayObject mc = Stage.inst.touchTarget as DisplayObject;
bool handled = false;
while (mc != Stage.inst && mc != null)
{
if (mc.gOwner != null)
{
int k = _popupStack.IndexOf(mc.gOwner);
if (k != -1)
{
for (int i = _popupStack.Count - 1; i > k; i--)
{
int last = _popupStack.Count - 1;
GObject popup = _popupStack[last];
if (touchBegin == _specialPopups.Contains(popup))
continue;
ClosePopup(popup);
_justClosedPopups.Add(popup);
_popupStack.RemoveAt(last);
_specialPopups.Remove(popup);
}
handled = true;
break;
}
}
mc = mc.parent;
}
if (!handled)
{
for (int i = _popupStack.Count - 1; i >= 0; i--)
{
GObject popup = _popupStack[i];
if (touchBegin == _specialPopups.Contains(popup))
continue;
ClosePopup(popup);
_justClosedPopups.Add(popup);
_popupStack.RemoveAt(i);
_specialPopups.Remove(popup);
}
}
}
}
///
///
///
public void EnableSound()
{
Stage.inst.EnableSound();
}
///
///
///
public void DisableSound()
{
Stage.inst.DisableSound();
}
///
///
///
///
///
public void PlayOneShotSound(AudioClip clip, float volumeScale)
{
Stage.inst.PlayOneShotSound(clip, volumeScale);
}
///
///
///
///
public void PlayOneShotSound(AudioClip clip)
{
Stage.inst.PlayOneShotSound(clip);
}
///
///
///
public float soundVolume
{
get { return Stage.inst.soundVolume; }
set { Stage.inst.soundVolume = value; }
}
}
}