using System; using UnityEngine; namespace FairyGUI { /// <summary> /// /// </summary> [ExecuteInEditMode] [AddComponentMenu("FairyGUI/UI Painter")] [RequireComponent(typeof(MeshCollider), typeof(MeshRenderer))] public class UIPainter : MonoBehaviour, EMRenderTarget { /// <summary> /// /// </summary> public Container container { get; private set; } /// <summary> /// /// </summary> public string packageName; /// <summary> /// /// </summary> public string componentName; /// <summary> /// /// </summary> public int sortingOrder; [SerializeField] string packagePath; [SerializeField] Camera renderCamera = null; [SerializeField] bool fairyBatching = false; [SerializeField] bool touchDisabled = false; GComponent _ui; [NonSerialized] bool _created; [NonSerialized] bool _captured; [NonSerialized] Renderer _renderer; [NonSerialized] RenderTexture _texture; Action _captureDelegate; void OnEnable() { if (Application.isPlaying) { if (this.container == null) { CreateContainer(); if (!string.IsNullOrEmpty(packagePath) && UIPackage.GetByName(packageName) == null) UIPackage.AddPackage(packagePath); } } else { EMRenderSupport.Add(this); } } void OnDisable() { if (!Application.isPlaying) EMRenderSupport.Remove(this); } void OnGUI() { if (!Application.isPlaying) EM_BeforeUpdate(); } void Start() { useGUILayout = false; if (!_created && Application.isPlaying) CreateUI(); } void OnDestroy() { if (Application.isPlaying) { if (_ui != null) { _ui.Dispose(); _ui = null; } container.Dispose(); container = null; } else { EMRenderSupport.Remove(this); } DestroyTexture(); } void CreateContainer() { this.container = new Container("UIPainter"); this.container.renderMode = RenderMode.WorldSpace; this.container.renderCamera = renderCamera; this.container.touchable = !touchDisabled; this.container.fairyBatching = fairyBatching; this.container._panelOrder = sortingOrder; this.container.hitArea = new MeshColliderHitTest(this.gameObject.GetComponent<MeshCollider>()); SetSortingOrder(this.sortingOrder, true); this.container.layer = CaptureCamera.hiddenLayer; } /// <summary> /// Change the sorting order of the panel in runtime. /// </summary> /// <param name="value">sorting order value</param> /// <param name="apply">false if you dont want the default sorting behavior.</param> public void SetSortingOrder(int value, bool apply) { this.sortingOrder = value; container._panelOrder = value; if (apply) Stage.inst.ApplyPanelOrder(container); } /// <summary> /// /// </summary> public GComponent ui { get { if (!_created && Application.isPlaying) CreateUI(); return _ui; } } /// <summary> /// /// </summary> public void CreateUI() { if (_ui != null) { _ui.Dispose(); _ui = null; DestroyTexture(); } _created = true; if (string.IsNullOrEmpty(packageName) || string.IsNullOrEmpty(componentName)) return; _ui = (GComponent)UIPackage.CreateObject(packageName, componentName); if (_ui != null) { this.container.AddChild(_ui.displayObject); this.container.size = _ui.size; _texture = CaptureCamera.CreateRenderTexture(Mathf.RoundToInt(_ui.width), Mathf.RoundToInt(_ui.height), UIConfig.depthSupportForPaintingMode); _renderer = this.GetComponent<Renderer>(); if (_renderer != null) { _renderer.sharedMaterial.mainTexture = _texture; _captureDelegate = Capture; if (_renderer.sharedMaterial.renderQueue == 3000) //Set in transpare queue only { this.container.onUpdate += () => { UpdateContext.OnEnd += _captureDelegate; }; } } } else Debug.LogError("Create " + componentName + "@" + packageName + " failed!"); } void Capture() { CaptureCamera.Capture(this.container, _texture, this.container.size.y, Vector2.zero); if (_renderer != null) _renderer.sortingOrder = container.renderingOrder; } void DestroyTexture() { if (_texture != null) { if (Application.isPlaying) RenderTexture.Destroy(_texture); else RenderTexture.DestroyImmediate(_texture); _texture = null; if (_renderer != null) _renderer.sharedMaterial.mainTexture = null; } } #region edit mode functions void CaptureInEditMode() { if (!EMRenderSupport.packageListReady || UIPackage.GetByName(packageName) == null) return; _captured = true; DisplayObject.hideFlags = HideFlags.DontSaveInEditor; GComponent view = (GComponent)UIPackage.CreateObject(packageName, componentName); if (view != null) { DestroyTexture(); _texture = CaptureCamera.CreateRenderTexture(Mathf.RoundToInt(view.width), Mathf.RoundToInt(view.height), false); Container root = (Container)view.displayObject; root.layer = CaptureCamera.layer; root.gameObject.hideFlags = HideFlags.None; root.gameObject.SetActive(true); GameObject cameraObject = new GameObject("Temp Capture Camera"); Camera camera = cameraObject.AddComponent<Camera>(); camera.depth = 0; camera.cullingMask = 1 << CaptureCamera.layer; camera.clearFlags = CameraClearFlags.Depth; camera.orthographic = true; camera.nearClipPlane = -30; camera.farClipPlane = 30; camera.enabled = false; camera.targetTexture = _texture; float halfHeight = (float)_texture.height / 2; camera.orthographicSize = halfHeight; cameraObject.transform.localPosition = root.cachedTransform.TransformPoint(halfHeight * camera.aspect, -halfHeight, 0); UpdateContext context = new UpdateContext(); //run two times context.Begin(); view.displayObject.Update(context); context.End(); context.Begin(); view.displayObject.Update(context); context.End(); RenderTexture old = RenderTexture.active; RenderTexture.active = _texture; GL.Clear(true, true, Color.clear); camera.Render(); RenderTexture.active = old; camera.targetTexture = null; view.Dispose(); GameObject.DestroyImmediate(cameraObject); if (_renderer != null) _renderer.sharedMaterial.mainTexture = _texture; } } public void ApplyModifiedProperties(bool sortingOrderChanged) { if (sortingOrderChanged) { if (Application.isPlaying) SetSortingOrder(sortingOrder, true); else EMRenderSupport.orderChanged = true; } } public void OnUpdateSource(object[] data) { if (Application.isPlaying) return; this.packageName = (string)data[0]; this.packagePath = (string)data[1]; this.componentName = (string)data[2]; if ((bool)data[3]) _captured = false; } public int EM_sortingOrder { get { return sortingOrder; } } public void EM_BeforeUpdate() { if (_renderer == null) _renderer = this.GetComponent<Renderer>(); if (_renderer != null && _renderer.sharedMaterial.mainTexture != _texture) _renderer.sharedMaterial.mainTexture = _texture; if (packageName != null && componentName != null && !_captured) CaptureInEditMode(); } public void EM_Update(UpdateContext context) { if (_renderer != null) _renderer.sortingOrder = context.renderingOrder++; } public void EM_Reload() { _captured = false; } #endregion } }