|
|
|
|
|
|
using UIWidgets.painting; |
|
|
|
using UIWidgets.ui; |
|
|
|
using UIWidgets.widgets; |
|
|
|
using UnityEditor; |
|
|
|
using UnityEngine.EventSystems; |
|
|
|
using UnityEngine.UI; |
|
|
|
using Image = UnityEngine.UI.Image; |
|
|
|
|
|
|
|
public class WidgetCanvas: MonoBehaviour |
|
|
|
public class UIWidgetWindowAdapter : WindowAdapter |
|
|
|
{ |
|
|
|
private WidgetCanvas _widgetCanvas; |
|
|
|
|
|
|
|
public UIWidgetWindowAdapter(WidgetCanvas widgetCanvas) |
|
|
|
{ |
|
|
|
this._widgetCanvas = widgetCanvas; |
|
|
|
} |
|
|
|
|
|
|
|
protected override Surface createSurface() |
|
|
|
{ |
|
|
|
return new EditorWindowSurface(_widgetCanvas.applyRenderTexture); |
|
|
|
} |
|
|
|
|
|
|
|
public override GUIContent titleContent |
|
|
|
{ |
|
|
|
get { return new GUIContent(_widgetCanvas.gameObject.name); } |
|
|
|
} |
|
|
|
|
|
|
|
protected override double queryDevicePixelRatio() |
|
|
|
{ |
|
|
|
return _widgetCanvas.canvas.scaleFactor; |
|
|
|
} |
|
|
|
|
|
|
|
protected override Vector2 queryWindowSize() |
|
|
|
{ |
|
|
|
return _widgetCanvas.rectTransform.rect.size; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
[RequireComponent(typeof(RectTransform))] |
|
|
|
public abstract class WidgetCanvas : MaskableGraphic, IPointerDownHandler, IPointerUpHandler, IDragHandler, |
|
|
|
IPointerEnterHandler, IPointerExitHandler |
|
|
|
|
|
|
|
[SerializeField] |
|
|
|
private int _canvasWidth = 1000; |
|
|
|
|
|
|
|
[SerializeField] |
|
|
|
private int _canvasHeight = 800; |
|
|
|
|
|
|
|
private RenderTexture _renderTexture; |
|
|
|
|
|
|
|
void OnEnable() |
|
|
|
private Texture _texture; |
|
|
|
private Vector2 _lastMouseMove; |
|
|
|
private bool _mouseEntered; |
|
|
|
|
|
|
|
protected override void OnEnable() |
|
|
|
base.OnEnable(); |
|
|
|
|
|
|
|
_windowAdapter = new CanvasWindowAdapter(this); |
|
|
|
var root = new WidgetsApp(null, getWidget()); |
|
|
|
_windowAdapter.attachRootWidget(root); |
|
|
|
_windowAdapter = new UIWidgetWindowAdapter(this); |
|
|
|
|
|
|
|
_windowAdapter.OnEnable(); |
|
|
|
var root = new WidgetsApp(null, getWidget()); |
|
|
|
_windowAdapter.attachRootWidget(root); |
|
|
|
|
|
|
|
_lastMouseMove = Input.mousePosition; |
|
|
|
} |
|
|
|
setupMeshRenderer(); |
|
|
|
var boxColider = gameObject.AddComponent(typeof(BoxCollider)) as BoxCollider; |
|
|
|
boxColider.size = new Vector3(1, 1, 0.00001f); // very thin box
|
|
|
|
private void OnDisable() |
|
|
|
{ |
|
|
|
this._windowAdapter.OnDisable(); |
|
|
|
base.OnDisable(); |
|
|
|
protected virtual Widget getWidget() |
|
|
|
protected abstract Widget getWidget(); |
|
|
|
|
|
|
|
public override Texture mainTexture |
|
|
|
return new AsScreen(); |
|
|
|
get { return _texture; } |
|
|
|
private void setupMeshRenderer() |
|
|
|
internal void applyRenderTexture(Rect screenRect, Texture texture, Material mat) |
|
|
|
var meshRenderer = gameObject.AddComponent(typeof(MeshRenderer)) as MeshRenderer; |
|
|
|
var shader = Shader.Find("UI/Default"); // todo
|
|
|
|
var material = new Material(shader); |
|
|
|
meshRenderer.material = material; |
|
|
|
|
|
|
|
var meshFilter = gameObject.AddComponent(typeof(MeshFilter)) as MeshFilter; |
|
|
|
|
|
|
|
var mesh = new Mesh(); |
|
|
|
meshFilter.mesh = mesh; |
|
|
|
|
|
|
|
|
|
|
|
var vertices = new Vector3[4]; |
|
|
|
|
|
|
|
float minX = -0.5f; |
|
|
|
float minY = -0.5f; |
|
|
|
float maxX = 0.5f; |
|
|
|
float maxY = 0.5f; |
|
|
|
vertices[0] = new Vector3(minX, minY, 0); |
|
|
|
vertices[1] = new Vector3(maxX, minY, 0); |
|
|
|
vertices[2] = new Vector3(minX, maxY, 0); |
|
|
|
vertices[3] = new Vector3(maxX, maxY, 0); |
|
|
|
|
|
|
|
mesh.vertices = vertices; |
|
|
|
|
|
|
|
var tri = new int[6]; |
|
|
|
|
|
|
|
tri[0] = 0; |
|
|
|
tri[1] = 2; |
|
|
|
tri[2] = 1; |
|
|
|
|
|
|
|
tri[3] = 2; |
|
|
|
tri[4] = 3; |
|
|
|
tri[5] = 1; |
|
|
|
|
|
|
|
mesh.triangles = tri; |
|
|
|
|
|
|
|
var uv = new Vector2[4]; |
|
|
|
uv[0] = new Vector2(0, 0); |
|
|
|
uv[1] = new Vector2(1, 0); |
|
|
|
uv[2] = new Vector2(0, 1); |
|
|
|
uv[3] = new Vector2(1, 1); |
|
|
|
mesh.uv = uv; |
|
|
|
_texture = texture; |
|
|
|
SetMaterialDirty(); |
|
|
|
if (_renderTexture != null) |
|
|
|
{ |
|
|
|
_renderTexture.Release(); |
|
|
|
_renderTexture = null; |
|
|
|
} |
|
|
|
Destroy(GetComponent<MeshRenderer>()); |
|
|
|
Destroy(GetComponent<MeshFilter>()); |
|
|
|
Destroy(GetComponent<BoxCollider>()); |
|
|
|
} |
|
|
|
|
|
|
|
private void Update() { |
|
|
|
if (this._windowAdapter != null) { |
|
|
|
this._windowAdapter.Update(); |
|
|
|
} |
|
|
|
base.OnDestroy(); |
|
|
|
private void ensureRenderTexture() |
|
|
|
private void Update() |
|
|
|
if (_renderTexture != null && _renderTexture.IsCreated() && |
|
|
|
_renderTexture.width == getCanvasWidth() && _renderTexture.height == getCanvasHeight()) |
|
|
|
if (_mouseEntered && (_lastMouseMove.x != Input.mousePosition.x || _lastMouseMove.y != Input.mousePosition.y)) |
|
|
|
return; |
|
|
|
this.OnMouseOver(); |
|
|
|
if (_renderTexture != null) |
|
|
|
_lastMouseMove = Input.mousePosition; |
|
|
|
if (this._windowAdapter != null) |
|
|
|
_renderTexture.Release(); |
|
|
|
this._windowAdapter.Update(); |
|
|
|
_renderTexture = new RenderTexture(getCanvasWidth(), getCanvasHeight(), 24); |
|
|
|
|
|
|
|
|
|
|
|
var effectiveWidth = getCanvasWidth(); |
|
|
|
var effectiveHeight = getCanvasHeight(); |
|
|
|
GL.PushMatrix(); |
|
|
|
GL.LoadIdentity(); |
|
|
|
Matrix4x4 m =Matrix4x4.Scale(new Vector3(2.0f / effectiveWidth, -2.0f / effectiveHeight, 1.0f)) |
|
|
|
* Matrix4x4.Translate(new Vector3(-effectiveWidth / 2.0f, -effectiveHeight / 2.0f, 0)); |
|
|
|
GL.LoadProjectionMatrix(m); |
|
|
|
this._windowAdapter.OnGUI(); |
|
|
|
} |
|
|
|
ensureRenderTexture(); |
|
|
|
var renderer = GetComponent<MeshRenderer>(); |
|
|
|
renderer.material.mainTexture = _renderTexture; |
|
|
|
RenderTexture currentActiveRT = RenderTexture.active; |
|
|
|
try |
|
|
|
{ |
|
|
|
RenderTexture.active = _renderTexture; |
|
|
|
GL.Clear(true, true, new UnityEngine.Color(0,0,0,0)); |
|
|
|
this._windowAdapter.OnGUI(); |
|
|
|
} |
|
|
|
finally |
|
|
|
{ |
|
|
|
RenderTexture.active = currentActiveRT; |
|
|
|
} |
|
|
|
|
|
|
|
GL.PopMatrix(); |
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
if (this._windowAdapter != null) { |
|
|
|
if (this._windowAdapter != null) |
|
|
|
{ |
|
|
|
void OnMouseEnter() |
|
|
|
private void OnMouseOver() |
|
|
|
var pos = convertPosition(Input.mousePosition); |
|
|
|
|
|
|
|
var pos = getPointPosition(Input.mousePosition); |
|
|
|
// Debug.Log(string.Format("mouse move {0} {1}", pos.x, pos.y));
|
|
|
|
this._windowAdapter.PostPointerEvent(new PointerData( |
|
|
|
timeStamp: DateTime.Now, |
|
|
|
change: PointerChange.hover, |
|
|
|
|
|
|
)); |
|
|
|
} |
|
|
|
|
|
|
|
void OnMouseExit() |
|
|
|
private int getMouseButtonDown() |
|
|
|
var pos = convertPosition(Input.mousePosition); |
|
|
|
this._windowAdapter.PostPointerEvent(new PointerData( |
|
|
|
timeStamp: DateTime.Now, |
|
|
|
change: PointerChange.hover, |
|
|
|
kind: PointerDeviceKind.mouse, |
|
|
|
device: getMouseButtonDown(), |
|
|
|
physicalX: pos.x, |
|
|
|
physicalY: pos.y |
|
|
|
)); |
|
|
|
for (int key = 0; key < 3; key++) |
|
|
|
{ |
|
|
|
if (Input.GetMouseButton(key)) |
|
|
|
{ |
|
|
|
return key; |
|
|
|
} |
|
|
|
} |
|
|
|
return 0; |
|
|
|
|
|
|
|
void OnMouseOver() |
|
|
|
|
|
|
|
public void OnPointerDown(PointerEventData eventData) |
|
|
|
var pos = convertPosition(Input.mousePosition); |
|
|
|
var position = getPointPosition(eventData); |
|
|
|
change: PointerChange.hover, |
|
|
|
change: PointerChange.down, |
|
|
|
device: getMouseButtonDown(), |
|
|
|
physicalX: pos.x, |
|
|
|
physicalY: pos.y |
|
|
|
device: (int) eventData.button, |
|
|
|
physicalX: position.x, |
|
|
|
physicalY: position.y |
|
|
|
void OnMouseDown() |
|
|
|
public void OnPointerUp(PointerEventData eventData) |
|
|
|
int x = Screen.width; |
|
|
|
int y = Screen.height; |
|
|
|
var pos = convertPosition(Input.mousePosition); |
|
|
|
this._windowAdapter.PostPointerEvent(new PointerData( |
|
|
|
timeStamp: DateTime.Now, |
|
|
|
change: PointerChange.down, |
|
|
|
kind: PointerDeviceKind.mouse, |
|
|
|
device: getMouseButtonDown(), |
|
|
|
physicalX: pos.x, |
|
|
|
physicalY: pos.y |
|
|
|
)); |
|
|
|
} |
|
|
|
|
|
|
|
void OnMouseUp() |
|
|
|
{ |
|
|
|
var pos = convertPosition(Input.mousePosition); |
|
|
|
var position = getPointPosition(eventData); |
|
|
|
device: getMouseButtonDown(), |
|
|
|
physicalX: pos.x, |
|
|
|
physicalY: pos.y |
|
|
|
device: (int) eventData.button, |
|
|
|
physicalX: position.x, |
|
|
|
physicalY: position.y |
|
|
|
void OnMouseDrag() |
|
|
|
public Vector2 getPointPosition(PointerEventData eventData) |
|
|
|
var pos = convertPosition(Input.mousePosition); |
|
|
|
this._windowAdapter.PostPointerEvent(new PointerData( |
|
|
|
timeStamp: DateTime.Now, |
|
|
|
change: PointerChange.move, |
|
|
|
kind: PointerDeviceKind.mouse, |
|
|
|
device: getMouseButtonDown(), |
|
|
|
physicalX: pos.x, |
|
|
|
physicalY: pos.y |
|
|
|
)); |
|
|
|
Vector2 localPoint; |
|
|
|
RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, eventData.position, |
|
|
|
eventData.enterEventCamera, out localPoint); |
|
|
|
localPoint.x = localPoint.x - rectTransform.rect.min.x; |
|
|
|
localPoint.y = rectTransform.rect.max.y - localPoint.y; |
|
|
|
return localPoint; |
|
|
|
|
|
|
|
Vector2d convertPosition(Vector2 mousePos) |
|
|
|
{ |
|
|
|
var cam = Camera.main; |
|
|
|
var plan = new Plane(transform.TransformDirection(0, 0, 1), transform.TransformPoint(0, 0, 0)); |
|
|
|
var ray = cam.ScreenPointToRay(new Vector3(mousePos.x, mousePos.y, 0)); |
|
|
|
float enter; |
|
|
|
Vector3 hitPoint; |
|
|
|
if (plan.Raycast(ray, out enter)) |
|
|
|
{ |
|
|
|
hitPoint = ray.GetPoint(enter); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
ray.direction = -ray.direction; |
|
|
|
plan.Raycast(ray, out enter); |
|
|
|
hitPoint = ray.GetPoint(enter); |
|
|
|
} |
|
|
|
var localPoint = transform.InverseTransformPoint(hitPoint); |
|
|
|
return new Vector2d( |
|
|
|
(localPoint.x + 0.5) * getCanvasWidth() * _windowAdapter.devicePixelRatio, |
|
|
|
(-localPoint.y + 0.5) * getCanvasHeight() * _windowAdapter.devicePixelRatio |
|
|
|
); |
|
|
|
} |
|
|
|
public Vector2 getPointPosition(Vector2 position) |
|
|
|
{ |
|
|
|
// Debug.Log("mouse posse " + position.x + " " + position.y);
|
|
|
|
Vector2 localPoint; |
|
|
|
Camera eventCamera = null; |
|
|
|
private int getMouseButtonDown() |
|
|
|
{ |
|
|
|
for (int key = 0; key < 3; key++) |
|
|
|
if (canvas.renderMode != RenderMode.ScreenSpaceCamera) |
|
|
|
if (Input.GetMouseButton(key)) |
|
|
|
{ |
|
|
|
return key; |
|
|
|
} |
|
|
|
eventCamera = canvas.GetComponent<GraphicRaycaster>().eventCamera; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
private int getCanvasWidth() |
|
|
|
{ |
|
|
|
return _canvasWidth; |
|
|
|
} |
|
|
|
|
|
|
|
private int getCanvasHeight() |
|
|
|
{ |
|
|
|
return _canvasHeight; |
|
|
|
RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, position, |
|
|
|
eventCamera, out localPoint); |
|
|
|
localPoint.x = localPoint.x - rectTransform.rect.min.x; |
|
|
|
localPoint.y = rectTransform.rect.max.y - localPoint.y; |
|
|
|
return localPoint; |
|
|
|
public Vector2 size |
|
|
|
public void OnDrag(PointerEventData eventData) |
|
|
|
get |
|
|
|
{ |
|
|
|
return new Vector2(_canvasWidth, _canvasHeight); |
|
|
|
} |
|
|
|
var position = getPointPosition(eventData); |
|
|
|
this._windowAdapter.PostPointerEvent(new PointerData( |
|
|
|
timeStamp: DateTime.Now, |
|
|
|
change: PointerChange.move, |
|
|
|
kind: PointerDeviceKind.mouse, |
|
|
|
device: (int) eventData.button, |
|
|
|
physicalX: position.x, |
|
|
|
physicalY: position.y |
|
|
|
)); |
|
|
|
public double devicePixelRatio |
|
|
|
public void OnPointerEnter(PointerEventData eventData) |
|
|
|
get { return 1; } |
|
|
|
} |
|
|
|
|
|
|
|
public void scheduleFrame() |
|
|
|
{ |
|
|
|
_mouseEntered = true; |
|
|
|
_lastMouseMove = eventData.position; |
|
|
|
var position = getPointPosition(eventData); |
|
|
|
this._windowAdapter.PostPointerEvent(new PointerData( |
|
|
|
timeStamp: DateTime.Now, |
|
|
|
change: PointerChange.hover, |
|
|
|
kind: PointerDeviceKind.mouse, |
|
|
|
device: (int) eventData.button, |
|
|
|
physicalX: position.x, |
|
|
|
physicalY: position.y |
|
|
|
)); |
|
|
|
public GUIContent titleContent |
|
|
|
public void OnPointerExit(PointerEventData eventData) |
|
|
|
get |
|
|
|
{ |
|
|
|
return new GUIContent(gameObject.name); |
|
|
|
} |
|
|
|
_mouseEntered = false; |
|
|
|
var position = getPointPosition(eventData); |
|
|
|
this._windowAdapter.PostPointerEvent(new PointerData( |
|
|
|
timeStamp: DateTime.Now, |
|
|
|
change: PointerChange.hover, |
|
|
|
kind: PointerDeviceKind.mouse, |
|
|
|
device: (int) eventData.button, |
|
|
|
physicalX: position.x, |
|
|
|
physicalY: position.y |
|
|
|
)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |