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

489 行
16 KiB

using System;
using System.Collections;
using System.Collections.Generic;
using Unity.UIWidgets.external.simplejson;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Profiling;
using UnityEngine.Scripting;
using UnityEngine.UI;
using RawImage = UnityEngine.UI.RawImage;
namespace Unity.UIWidgets.engine {
public enum UIWidgetsWindowType {
InvalidPanel = 0,
GameObjectPanel = 1,
EditorWindowPanel = 2
}
[Serializable]
public struct Font {
public string asset;
public int weight;
}
[Serializable]
public struct TextFont {
public string family;
[SerializeField] public Font[] fonts;
}
public interface IUIWidgetsWindow {
Offset windowPosToScreenPos(Offset offset);
void startCoroutine(IEnumerator routing);
bool isActive();
void mainEntry();
void onNewFrameScheduled();
UIWidgetsWindowType getWindowType();
}
public class Configurations {
private Dictionary<string, TextFont> _textFonts = new Dictionary<string, TextFont>();
public void Clear() {
_textFonts.Clear();
}
public void AddFont(string family, TextFont font) {
_textFonts[key: family] = font;
}
public object fontsToObject() {
Dictionary<string, TextFont> settings = _textFonts;
if (settings == null || settings.Count == 0) {
return null;
}
var result = new object[settings.Count];
var i = 0;
foreach (var setting in settings) {
var font = new Dictionary<string, object>();
font.Add("family", value: setting.Key);
var dic = new Dictionary<string, object>[setting.Value.fonts.Length];
for (var j = 0; j < setting.Value.fonts.Length; j++) {
dic[j] = new Dictionary<string, object>();
if (setting.Value.fonts[j].asset.Length > 0) {
dic[j].Add("asset", value: setting.Value.fonts[j].asset);
}
if (setting.Value.fonts[j].weight > 0) {
dic[j].Add("weight", value: setting.Value.fonts[j].weight);
}
}
font.Add("fonts", value: dic);
result[i] = font;
i++;
}
return result;
}
}
public partial class UIWidgetsPanel : RawImage, IUIWidgetsWindow {
static List<UIWidgetsPanel> panels = new List<UIWidgetsPanel>();
static public Isolate anyIsolate {
get {
if (panels.Count == 0) {
return null;
}
return panels[0]._wrapper.isolate;
}
}
static void registerPanel(UIWidgetsPanel panel) {
panels.Add(panel);
}
static void unregisterPanel(UIWidgetsPanel panel) {
panels.Remove(panel);
}
float _devicePixelRatioOverride;
public bool hardwareAntiAliasing;
public TextFont[] fonts;
Configurations _configurations;
UIWidgetsPanelWrapper _wrapper;
int _currentWidth {
get { return Mathf.RoundToInt(rectTransform.rect.width * canvas.scaleFactor); }
}
int _currentHeight {
get { return Mathf.RoundToInt(rectTransform.rect.height * canvas.scaleFactor); }
}
float _currentDevicePixelRatio {
get {
#if !UNITY_EDITOR
return _wrapper.displayMetrics.DevicePixelRatioByDefault;
#endif
var currentDpi = Screen.dpi;
if (currentDpi == 0) {
currentDpi = canvas.GetComponent<CanvasScaler>().fallbackScreenDPI;
}
return currentDpi / 96;
}
}
bool _viewMetricsCallbackRegistered;
void _handleViewMetricsChanged(string method, List<JSONNode> args) {
using (Isolate.getScope(anyIsolate)) {
_wrapper.displayMetrics.onViewMetricsChanged();
Window.instance.updateSafeArea();
Window.instance.onMetricsChanged?.Invoke();
}
}
protected virtual void Update() {
if (!_viewMetricsCallbackRegistered) {
_viewMetricsCallbackRegistered = true;
UIWidgetsMessageManager.instance?.AddChannelMessageDelegate("ViewportMetricsChanged",
_handleViewMetricsChanged);
}
#if !UNITY_EDITOR
CollectGarbageOnDemand();
#endif
Input_Update();
}
#region OnDemandGC
#if !UNITY_EDITOR
// 8 MB
const long kCollectAfterAllocating = 8 * 1024 * 1024;
long lastFrameMemory = 0;
long nextCollectAt = 0;
void TryEnableOnDemandGC()
{
if (UIWidgetsGlobalConfiguration.EnableIncrementalGC)
{
GarbageCollector.GCMode = GarbageCollector.Mode.Disabled;
Application.lowMemory += GC.Collect;
}
}
void CollectGarbageOnDemand()
{
if (!UIWidgetsGlobalConfiguration.EnableIncrementalGC)
{
return;
}
var mem = Profiler.GetMonoUsedSizeLong();
if (mem < lastFrameMemory)
{
// GC happened.
nextCollectAt = mem + kCollectAfterAllocating;
}
else if (mem >= nextCollectAt)
{
// Trigger incremental GC
GarbageCollector.CollectIncremental(1000);
lastFrameMemory = mem + kCollectAfterAllocating;
}
lastFrameMemory = mem;
}
#endif
#endregion
#if !UNITY_EDITOR && UNITY_ANDROID
bool AndroidInitialized = true;
IEnumerator DoInitAndroid() {
yield return new WaitForEndOfFrame();
AndroidPlatformUtil.Init();
yield return new WaitForEndOfFrame();
enabled = true;
}
bool IsAndroidInitialized() {
if (AndroidInitialized) {
enabled = false;
AndroidInitialized = false;
startCoroutine(DoInitAndroid());
return false;
}
return true;
}
#endif
protected void OnEnable() {
#if !UNITY_EDITOR && UNITY_ANDROID
if (!IsAndroidInitialized()) {return ;}
#endif
#if !UNITY_EDITOR && UNITY_IOS
//the hook API cannot be automatically called on IOS, so we need try hook it here
Hooks.tryHook();
#endif
#if !UNITY_EDITOR
TryEnableOnDemandGC();
#endif
base.OnEnable();
D.assert(_wrapper == null);
_configurations = new Configurations();
_wrapper = new UIWidgetsPanelWrapper();
onEnable();
if (fonts != null && fonts.Length > 0) {
foreach (var font in fonts) {
AddFont(family: font.family, font: font);
}
}
_wrapper.Initiate(this, width: _currentWidth, height: _currentHeight, dpr: _currentDevicePixelRatio,
_configurations: _configurations);
_configurations.Clear();
texture = _wrapper.renderTexture;
Input_OnEnable();
registerPanel(this);
}
protected override void OnDisable() {
unregisterPanel(this);
D.assert(_wrapper != null);
_wrapper?.Destroy();
_wrapper = null;
texture = null;
Input_OnDisable();
base.OnDisable();
}
protected virtual void OnGUI() {
Input_OnGUI();
}
protected override void OnRectTransformDimensionsChange() {
if (_wrapper != null && _wrapper.didDisplayMetricsChanged(width: _currentWidth, height: _currentHeight,
dpr: _currentDevicePixelRatio)) {
_wrapper.OnDisplayMetricsChanged(width: _currentWidth, height: _currentHeight,
dpr: _currentDevicePixelRatio);
texture = _wrapper.renderTexture;
}
}
public UIWidgetsWindowType getWindowType() {
return UIWidgetsWindowType.GameObjectPanel;
}
public bool isActive() {
return IsActive();
}
public void startCoroutine(IEnumerator routing) {
StartCoroutine(routine: routing);
}
public void onNewFrameScheduled() {
}
public Offset windowPosToScreenPos(Offset offset) {
Camera camera = null;
if (canvas.renderMode != RenderMode.ScreenSpaceCamera) {
camera = canvas.GetComponent<GraphicRaycaster>().eventCamera;
}
var pos = new Vector2(x: offset.dx, y: offset.dy);
pos = pos * _currentDevicePixelRatio / canvas.scaleFactor;
var rect = rectTransform.rect;
pos.x += rect.min.x;
pos.y = rect.max.y - pos.y;
var worldPos = rectTransform.TransformPoint(new Vector2(x: pos.x, y: pos.y));
var screenPos = RectTransformUtility.WorldToScreenPoint(cam: camera, worldPoint: worldPos);
return new Offset(dx: screenPos.x, Screen.height - screenPos.y);
}
public void mainEntry() {
main();
}
protected virtual void onEnable() {
}
protected void AddFont(string family, TextFont font) {
_configurations.AddFont(family,font);
}
protected void AddFont(string family, List<string> assets, List<int> weights) {
if (assets.Count != weights.Count) {
Debug.LogError($"The size of {family}‘s assets should be equal to the weights'.");
return;
}
var textFont = new TextFont {family = family};
var fonts = new Font[assets.Count];
for (var j = 0; j < assets.Count; j++) {
var font = new Font {asset = assets[index: j], weight = weights[index: j]};
fonts[j] = font;
}
textFont.fonts = fonts;
AddFont(family: family, font: textFont);
}
protected virtual void main() {
}
}
enum UIWidgetsInputMode
{
Mouse,
Touch
}
public partial class UIWidgetsPanel : IPointerDownHandler, IPointerUpHandler,
IPointerEnterHandler, IPointerExitHandler, IDragHandler {
bool _isEntered;
Vector2 _lastMousePosition;
UIWidgetsInputMode _inputMode;
void _convertPointerData(PointerEventData evt, out Vector2? position, out int pointerId) {
position = _inputMode == UIWidgetsInputMode.Mouse
? _getPointerPosition(Input.mousePosition)
: _getPointerPosition(evt);
pointerId = _inputMode == UIWidgetsInputMode.Mouse ? evt.pointerId : (-1 - evt.pointerId);
}
Vector2? _getPointerPosition(Vector2 position) {
var worldCamera = canvas.worldCamera;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(
rect: rectTransform, screenPoint: position, cam: worldCamera, out var localPoint)) {
var scaleFactor = canvas.scaleFactor;
localPoint.x = (localPoint.x - rectTransform.rect.min.x) * scaleFactor;
localPoint.y = (rectTransform.rect.max.y - localPoint.y) * scaleFactor;
return localPoint;
}
return null;
}
Vector2? _getPointerPosition(PointerEventData eventData) {
//refer to: https://zhuanlan.zhihu.com/p/37127981
Camera eventCamera = null;
if (canvas.renderMode != RenderMode.ScreenSpaceOverlay) {
eventCamera = canvas.GetComponent<GraphicRaycaster>().eventCamera;
}
Vector2 localPoint;
RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, eventData.position,
eventCamera, out localPoint);
var scaleFactor = canvas.scaleFactor;
localPoint.x = (localPoint.x - rectTransform.rect.min.x) * scaleFactor;
localPoint.y = (rectTransform.rect.max.y - localPoint.y) * scaleFactor;
return localPoint;
}
void Input_OnEnable() {
_inputMode = Input.mousePresent ? UIWidgetsInputMode.Mouse : UIWidgetsInputMode.Touch;
}
void Input_OnDisable() {
}
void Input_Update() {
//we only process hover events for desktop applications
if (_inputMode == UIWidgetsInputMode.Mouse) {
if (_isEntered) {
if (!Input.GetMouseButton(0) && !Input.GetMouseButton(1) && !Input.GetMouseButton(2)) {
if (_lastMousePosition.x != Input.mousePosition.x ||
_lastMousePosition.y != Input.mousePosition.y) {
_lastMousePosition = Input.mousePosition;
_onMouseMove();
}
}
else {
_lastMousePosition = Input.mousePosition;
}
if (Input.mouseScrollDelta.magnitude != 0) {
_onScroll();
}
}
}
#if UNITY_ANDROID && !UNITY_EDITOR
if (Input.GetKeyDown(KeyCode.Escape)) {
using (Isolate.getScope(anyIsolate)) {
WidgetsBinding.instance.handlePopRoute();
}
}
#endif
}
void Input_OnGUI() {
var e = Event.current;
if (e.isKey) {
_wrapper.OnKeyDown(e: e);
}
}
void _onMouseMove() {
if (_inputMode != UIWidgetsInputMode.Mouse) {
return;
}
var pos = _getPointerPosition(Input.mousePosition);
_wrapper.OnMouseMove(pos);
}
void _onScroll() {
if (_inputMode != UIWidgetsInputMode.Mouse) {
return;
}
var pos = _getPointerPosition(Input.mousePosition);
_wrapper.OnMouseScroll(Input.mouseScrollDelta, pos);
}
public void OnPointerEnter(PointerEventData eventData) {
if (_inputMode != UIWidgetsInputMode.Mouse) {
return;
}
D.assert(eventData.pointerId < 0);
_isEntered = true;
_lastMousePosition = Input.mousePosition;
}
public void OnPointerExit(PointerEventData eventData) {
if (_inputMode != UIWidgetsInputMode.Mouse) {
return;
}
D.assert(eventData.pointerId < 0);
_isEntered = false;
_wrapper.OnPointerLeave();
}
public void OnPointerDown(PointerEventData eventData) {
_convertPointerData(eventData, out var pos, out var pointerId);
_wrapper.OnPointerDown(pos, pointerId);
}
public void OnPointerUp(PointerEventData eventData) {
_convertPointerData(eventData, out var pos, out var pointerId);
_wrapper.OnPointerUp(pos, pointerId);
}
public void OnDrag(PointerEventData eventData) {
_convertPointerData(eventData, out var pos, out var pointerId);
_wrapper.OnDrag(pos, pointerId);
}
}
}