您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

598 行
20 KiB

using System;
using System.Collections.Generic;
using Unity.UIWidgets.async;
using Unity.UIWidgets.engine;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.scheduler;
using Unity.UIWidgets.service;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;
using UnityEditor;
using UnityEngine;
namespace Unity.UIWidgets.editor {
#if UNITY_EDITOR
public abstract class UIWidgetsEditorWindow : EditorWindow, WindowHost {
WindowAdapter _windowAdapter;
static readonly List<UIWidgetsEditorWindow> _activeEditorWindows = new List<UIWidgetsEditorWindow>();
[InitializeOnLoadMethod]
static void _OnBaseEditorWindowLoaded()
{
EditorApplication.quitting += () =>
{
foreach (var editorWindow in _activeEditorWindows) {
editorWindow.OnDisable();
}
_activeEditorWindows.Clear();
};
}
public UIWidgetsEditorWindow() {
this.wantsMouseMove = true;
this.wantsMouseEnterLeaveWindow = true;
_activeEditorWindows.Add(this);
}
void OnDestroy() {
if (_activeEditorWindows.Contains(this)) {
_activeEditorWindows.Remove(this);
}
}
protected virtual void OnEnable() {
if (this._windowAdapter == null) {
this._windowAdapter = new EditorWindowAdapter(this);
}
this._windowAdapter.OnEnable();
RenderBox rootRenderBox;
using (this._windowAdapter.getScope()) {
rootRenderBox = this.createRenderBox();
}
if (rootRenderBox != null) {
this._windowAdapter.attachRootRenderBox(rootRenderBox);
return;
}
Widget rootWidget;
using (this._windowAdapter.getScope()) {
rootWidget = this.createWidget();
}
this._windowAdapter.attachRootWidget(rootWidget);
}
protected virtual void OnDisable() {
this._windowAdapter.OnDisable();
}
protected virtual void OnGUI() {
this._windowAdapter.OnGUI(Event.current);
}
protected virtual void Update() {
this._windowAdapter.Update();
}
protected virtual RenderBox createRenderBox() {
return null;
}
protected abstract Widget createWidget();
public Window window {
get { return this._windowAdapter; }
}
}
public class EditorWindowAdapter : WindowAdapter {
public readonly EditorWindow editorWindow;
public EditorWindowAdapter(EditorWindow editorWindow) : base(true) {
this.editorWindow = editorWindow;
}
public override void scheduleFrame(bool regenerateLayerTree = true) {
base.scheduleFrame(regenerateLayerTree);
this.editorWindow.Repaint();
}
protected override bool hasFocus() {
return EditorWindow.focusedWindow == this.editorWindow;
}
public override GUIContent titleContent {
get { return this.editorWindow.titleContent; }
}
protected override float queryDevicePixelRatio() {
return EditorGUIUtility.pixelsPerPoint;
}
protected override int queryAntiAliasing() {
return defaultAntiAliasing;
}
protected override Vector2 queryWindowSize() {
return this.editorWindow.position.size;
}
protected override TimeSpan getTime() {
return TimeSpan.FromSeconds(EditorApplication.timeSinceStartup);
}
float? _lastUpdateTime;
protected override void updateDeltaTime() {
if (this._lastUpdateTime == null) {
this._lastUpdateTime = (float) EditorApplication.timeSinceStartup;
}
this.deltaTime = (float) EditorApplication.timeSinceStartup - this._lastUpdateTime.Value;
this.unscaledDeltaTime = this.deltaTime;
this._lastUpdateTime = (float) EditorApplication.timeSinceStartup;
}
}
#endif
public interface WindowHost {
Window window { get; }
}
public abstract class WindowAdapter : Window {
static readonly List<WindowAdapter> _windowAdapters = new List<WindowAdapter>();
public WindowAdapter(bool inEditorWindow = false) {
this.inEditorWindow = inEditorWindow;
}
public static List<WindowAdapter> windowAdapters {
get { return _windowAdapters; }
}
public WidgetInspectorService widgetInspectorService {
get {
D.assert(this._binding != null);
return this._binding.widgetInspectorService;
}
}
internal WidgetsBinding _binding;
float _lastWindowWidth;
float _lastWindowHeight;
bool _viewMetricsChanged;
readonly MicrotaskQueue _microtaskQueue = new MicrotaskQueue();
readonly TimerProvider _timerProvider = new TimerProvider();
readonly Rasterizer _rasterizer = new Rasterizer();
readonly ScrollInput _scrollInput = new ScrollInput();
bool _regenerateLayerTree;
Surface _surface;
bool _alive;
public bool alive {
get { return this._alive; }
}
protected virtual TimeSpan getTime() {
return TimeSpan.FromSeconds(Time.time);
}
protected float deltaTime;
protected float unscaledDeltaTime;
void updatePhysicalSize() {
var size = this.queryWindowSize();
this._physicalSize = new Size(
size.x * this._devicePixelRatio,
size.y * this._devicePixelRatio);
}
protected virtual void updateDeltaTime() {
this.deltaTime = Time.unscaledDeltaTime;
this.unscaledDeltaTime = Time.deltaTime;
}
protected virtual void updateSafeArea() {
}
public void onViewMetricsChanged() {
this._viewMetricsChanged = true;
}
protected abstract bool hasFocus();
public void OnEnable() {
this._devicePixelRatio = this.queryDevicePixelRatio();
this._antiAliasing = this.queryAntiAliasing();
this.updatePhysicalSize();
this.updateSafeArea();
D.assert(this._surface == null);
this._surface = this.createSurface();
this._rasterizer.setup(this._surface);
_windowAdapters.Add(this);
this._alive = true;
}
public void OnDisable() {
using (this.getScope()) {
this._binding.detachRootWidget();
}
_windowAdapters.Remove(this);
this._alive = false;
this._rasterizer.teardown();
D.assert(this._surface != null);
this._surface.Dispose();
this._surface = null;
}
readonly protected bool inEditorWindow;
public override IDisposable getScope() {
WindowAdapter oldInstance = (WindowAdapter) _instance;
_instance = this;
if (this._binding == null) {
this._binding = new WidgetsBinding(this.inEditorWindow);
}
SchedulerBinding._instance = this._binding;
return new WindowDisposable(this, oldInstance);
}
class WindowDisposable : IDisposable {
readonly WindowAdapter _window;
readonly WindowAdapter _oldWindow;
public WindowDisposable(WindowAdapter window, WindowAdapter oldWindow) {
this._window = window;
this._oldWindow = oldWindow;
}
public void Dispose() {
D.assert(_instance == this._window);
_instance = this._oldWindow;
D.assert(SchedulerBinding._instance == this._window._binding);
SchedulerBinding._instance = this._oldWindow?._binding;
}
}
public void postPointerEvents(List<PointerData> data) {
this.withBinding(() => { this.onPointerEvent(new PointerDataPacket(data)); });
}
public void postPointerEvent(PointerData data) {
this.postPointerEvents(new List<PointerData>() {data});
}
public void withBinding(Action fn) {
using (this.getScope()) {
fn();
}
}
public T withBindingFunc<T>(Func<T> fn) {
using (this.getScope()) {
return fn();
}
}
protected bool displayMetricsChanged() {
if (this._devicePixelRatio != this.queryDevicePixelRatio()) {
return true;
}
if (this._antiAliasing != this.queryAntiAliasing()) {
return true;
}
var size = this.queryWindowSize();
if (this._lastWindowWidth != size.x
|| this._lastWindowHeight != size.y) {
return true;
}
if (this._viewMetricsChanged) {
return true;
}
return false;
}
public virtual void OnGUI(Event evt = null) {
evt = evt ?? Event.current;
using (this.getScope()) {
if (this.displayMetricsChanged()) {
this._devicePixelRatio = this.queryDevicePixelRatio();
this._antiAliasing = this.queryAntiAliasing();
var size = this.queryWindowSize();
this._lastWindowWidth = size.x;
this._lastWindowHeight = size.y;
this._physicalSize = new Size(
this._lastWindowWidth * this._devicePixelRatio,
this._lastWindowHeight * this._devicePixelRatio);
this.updateSafeArea();
this._viewMetricsChanged = false;
if (this.onMetricsChanged != null) {
this.onMetricsChanged();
}
}
this._doOnGUI(evt);
}
}
public virtual GUIContent titleContent {
get { return null; }
}
protected abstract float queryDevicePixelRatio();
protected abstract int queryAntiAliasing();
protected abstract Vector2 queryWindowSize();
protected virtual Surface createSurface() {
return new WindowSurfaceImpl();
}
void _beginFrame() {
if (this.onBeginFrame != null) {
this.onBeginFrame(this.getTime());
}
this.flushMicrotasks();
if (this.onDrawFrame != null) {
this.onDrawFrame();
}
}
void _doOnGUI(Event evt) {
if (evt.type == EventType.Repaint) {
if (this._regenerateLayerTree) {
this._regenerateLayerTree = false;
this._beginFrame();
}
else {
this._rasterizer.drawLastLayerTree();
}
return;
}
if (this.onPointerEvent != null) {
PointerData pointerData = null;
if (evt.type == EventType.MouseDown) {
pointerData = new PointerData(
timeStamp: Timer.timespanSinceStartup,
change: PointerChange.down,
kind: PointerDeviceKind.mouse,
device: InputUtils.getMouseButtonKey(evt.button),
physicalX: evt.mousePosition.x * this._devicePixelRatio,
physicalY: evt.mousePosition.y * this._devicePixelRatio
);
}
else if (evt.type == EventType.MouseUp || evt.rawType == EventType.MouseUp) {
pointerData = new PointerData(
timeStamp: Timer.timespanSinceStartup,
change: PointerChange.up,
kind: PointerDeviceKind.mouse,
device: InputUtils.getMouseButtonKey(evt.button),
physicalX: evt.mousePosition.x * this._devicePixelRatio,
physicalY: evt.mousePosition.y * this._devicePixelRatio
);
}
else if (evt.type == EventType.MouseDrag) {
pointerData = new PointerData(
timeStamp: Timer.timespanSinceStartup,
change: PointerChange.move,
kind: PointerDeviceKind.mouse,
device: InputUtils.getMouseButtonKey(evt.button),
physicalX: evt.mousePosition.x * this._devicePixelRatio,
physicalY: evt.mousePosition.y * this._devicePixelRatio
);
}
else if (evt.type == EventType.MouseMove) {
pointerData = new PointerData(
timeStamp: Timer.timespanSinceStartup,
change: PointerChange.hover,
kind: PointerDeviceKind.mouse,
device: InputUtils.getMouseButtonKey(evt.button),
physicalX: evt.mousePosition.x * this._devicePixelRatio,
physicalY: evt.mousePosition.y * this._devicePixelRatio
);
}
else if (evt.type == EventType.ScrollWheel) {
this.onScroll(-evt.delta.x * this._devicePixelRatio,
-evt.delta.y * this._devicePixelRatio,
evt.mousePosition.x * this._devicePixelRatio,
evt.mousePosition.y * this._devicePixelRatio,
InputUtils.getScrollButtonKey()
);
}
else if (evt.type == EventType.DragUpdated) {
pointerData = new PointerData(
timeStamp: Timer.timespanSinceStartup,
change: PointerChange.dragFromEditorMove,
kind: PointerDeviceKind.mouse,
device: InputUtils.getMouseButtonKey(evt.button),
physicalX: evt.mousePosition.x * this._devicePixelRatio,
physicalY: evt.mousePosition.y * this._devicePixelRatio
);
}
else if (evt.type == EventType.DragPerform) {
pointerData = new PointerData(
timeStamp: Timer.timespanSinceStartup,
change: PointerChange.dragFromEditorRelease,
kind: PointerDeviceKind.mouse,
device: InputUtils.getMouseButtonKey(evt.button),
physicalX: evt.mousePosition.x * this._devicePixelRatio,
physicalY: evt.mousePosition.y * this._devicePixelRatio
);
}
if (pointerData != null) {
this.onPointerEvent(new PointerDataPacket(new List<PointerData> {
pointerData
}));
}
}
RawKeyboard.instance._handleKeyEvent(Event.current);
TextInput.OnGUI();
}
public void onScroll(float deltaX, float deltaY, float posX, float posY, int buttonId) {
this._scrollInput.onScroll(deltaX,
deltaY,
posX,
posY,
buttonId
);
}
void _updateScrollInput(float deltaTime) {
var deltaScroll = this._scrollInput.getScrollDelta(deltaTime);
if (deltaScroll == Vector2.zero) {
return;
}
PointerData pointerData = new ScrollData(
timeStamp: Timer.timespanSinceStartup,
change: PointerChange.scroll,
kind: PointerDeviceKind.mouse,
device: this._scrollInput.getDeviceId(),
physicalX: this._scrollInput.getPointerPosX(),
physicalY: this._scrollInput.getPointerPosY(),
scrollX: deltaScroll.x,
scrollY: deltaScroll.y
);
this.onPointerEvent(new PointerDataPacket(new List<PointerData> {
pointerData
}));
}
public void Update() {
if (this._physicalSize == null || this._physicalSize.isEmpty) {
this.updatePhysicalSize();
}
this.updateDeltaTime();
this.updateFPS(this.unscaledDeltaTime);
Timer.update();
bool hasFocus = this.hasFocus();
using (this.getScope()) {
WidgetsBinding.instance.focusManager.focusNone(!hasFocus);
this._updateScrollInput(this.deltaTime);
TextInput.Update();
this._timerProvider.update(this.flushMicrotasks);
this.flushMicrotasks();
}
}
static readonly TimeSpan _coolDownDelay = new TimeSpan(0, 0, 0, 0, 200);
static Timer frameCoolDownTimer;
public override void scheduleFrame(bool regenerateLayerTree = true) {
if (regenerateLayerTree) {
this._regenerateLayerTree = true;
}
onFrameRateSpeedUp();
frameCoolDownTimer?.cancel();
frameCoolDownTimer = instance.run(
_coolDownDelay,
() => {
onFrameRateCoolDown();
frameCoolDownTimer = null;
});
}
public override void render(Scene scene) {
var layerTree = scene.takeLayerTree();
if (layerTree == null) {
return;
}
if (this._physicalSize.isEmpty) {
return;
}
layerTree.frameSize = this._physicalSize;
layerTree.devicePixelRatio = this._devicePixelRatio;
layerTree.antiAliasing = this._antiAliasing;
this._rasterizer.draw(layerTree);
}
public override void scheduleMicrotask(Action callback) {
this._microtaskQueue.scheduleMicrotask(callback);
}
public override void flushMicrotasks() {
this._microtaskQueue.flushMicrotasks();
}
public override Timer run(TimeSpan duration, Action callback, bool periodic = false) {
return periodic
? this._timerProvider.periodic(duration, callback)
: this._timerProvider.run(duration, callback);
}
public override Timer runInMain(Action callback) {
return this._timerProvider.runInMain(callback);
}
public void attachRootRenderBox(RenderBox root) {
using (this.getScope()) {
this._binding.renderView.child = root;
}
}
public void attachRootWidget(Widget root) {
using (this.getScope()) {
this._binding.attachRootWidget(root);
}
}
public void attachRootWidget(Func<Widget> root) {
using (this.getScope()) {
this._binding.attachRootWidget(root());
}
}
internal void _forceRepaint() {
using (this.getScope()) {
RenderObjectVisitor visitor = null;
visitor = (child) => {
child.markNeedsPaint();
child.visitChildren(visitor);
};
this._binding.renderView?.visitChildren(visitor);
}
}
}
}