using System;
using UnityEngine;
namespace FairyGUI
{
///
///
///
[ExecuteInEditMode]
[AddComponentMenu("FairyGUI/UI Painter")]
[RequireComponent(typeof(MeshCollider), typeof(MeshRenderer))]
public class UIPainter : MonoBehaviour, EMRenderTarget
{
///
///
///
public Container container { get; private set; }
///
///
///
public string packageName;
///
///
///
public string componentName;
///
///
///
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());
SetSortingOrder(this.sortingOrder, true);
this.container.layer = CaptureCamera.hiddenLayer;
}
///
/// Change the sorting order of the panel in runtime.
///
/// sorting order value
/// false if you dont want the default sorting behavior.
public void SetSortingOrder(int value, bool apply)
{
this.sortingOrder = value;
container._panelOrder = value;
if (apply)
Stage.inst.ApplyPanelOrder(container);
}
///
///
///
public GComponent ui
{
get
{
if (!_created && Application.isPlaying)
CreateUI();
return _ui;
}
}
///
///
///
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();
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.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();
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
}
}