using UnityEngine; using System.Collections.Generic; 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; } } GGraph _modalLayer; GObject _modalWaitPane; List _popupStack; List _justClosedPopups; 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(); Stage.inst.onTouchBegin.AddCapture(__stageTouchBegin); } /// /// 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(); } /// /// This is called after screen size changed. /// public void ApplyContentScaleFactor() { this.SetSize(Mathf.CeilToInt(Screen.width / UIContentScaler.scaleFactor), Mathf.CeilToInt(Screen.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 (this._modalLayer.parent != null && !win.modal) i = this.GetChildIndex(this._modalLayer) - 1; else i = cnt - 1; for (; i >= 0; i--) { GObject g = this.GetChildAt(i); if (g == win) return; if (g is Window) break; } if (i >= 0) this.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 = 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) 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) 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, null); } /// /// 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, null); } /// /// Show a popup object along with the specific target object. /// 显示一个popup。将popup显示在指定对象的上方或者下方。 /// popup的特点是点击popup对象外的区域,popup对象将自动消失。 /// /// /// /// True to display downwards, false to display upwards, null to display automatically. public void ShowPopup(GObject popup, GObject target, object downward) { 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; ClosePopup(_popupStack[last]); _popupStack.RemoveAt(last); } } } _popupStack.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 && downward == null) return; Vector2 pos = GetPoupPosition(popup, target, downward); popup.xy = pos; } /// /// /// /// /// /// /// public Vector2 GetPoupPosition(GObject popup, GObject target, object downward) { 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 ((downward == null && yy + popup.height > this.height) || downward != null && (bool)downward == false) { 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, null); } /// /// /// /// /// public void TogglePopup(GObject popup, GObject target) { TogglePopup(popup, target, null); } /// /// /// /// /// /// public void TogglePopup(GObject popup, GObject target, object downward) { if (_justClosedPopups.IndexOf(popup) != -1) return; ShowPopup(popup, target, downward); } /// /// 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; ClosePopup(_popupStack[last]); _popupStack.RemoveAt(last); } } } else { foreach (GObject obj in _popupStack) ClosePopup(obj); _popupStack.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) { if (_defaultTooltipWin == null) { 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); } /// /// /// /// public void ShowTooltipsWin(GObject tooltipWin) { HideTooltips(); _tooltipWin = tooltipWin; Timers.inst.Add(0.1f, 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 result = null; DisplayObject mc = Stage.inst.focus; while (mc != Stage.inst && mc != null) { GObject gg = mc.gOwner; if (gg != null && gg.touchable && gg.focusable) { result = gg; break; } mc = mc.parent; } return result; } set { if (value != null && (!value.focusable || !value.onStage)) { Debug.LogError("invalid focus target"); return; } if (value == null) Stage.inst.focus = null; else Stage.inst.focus = value.displayObject; } } void __stageTouchBegin(EventContext context) { if (_tooltipWin != null) HideTooltips(); CheckPopups(); } void CheckPopups() { _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]; ClosePopup(popup); _justClosedPopups.Add(popup); _popupStack.RemoveAt(last); } handled = true; break; } } mc = mc.parent; } if (!handled) { for (int i = _popupStack.Count - 1; i >= 0; i--) { GObject popup = _popupStack[i]; ClosePopup(popup); _justClosedPopups.Add(popup); } _popupStack.Clear(); } } } /// /// /// 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; } } } }