1. Deleted zenject 2. created new entry scene Main 3. experimented with map viewer. 4.broke the Fmod initialisation, if it ever worked in the first place.

This commit is contained in:
alexiscatnip
2022-01-03 01:45:22 +08:00
parent 17ab1c190f
commit 226f4979eb
2084 changed files with 31047 additions and 113209 deletions
+13
View File
@@ -0,0 +1,13 @@
# Default ignored files
/shelf/
/workspace.xml
# Rider ignored files
/modules.xml
/projectSettingsUpdater.xml
/.idea.LMV_unity.iml
/contentModel.xml
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/
+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
</project>
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="UserContentModel">
<attachedFolders />
<explicitIncludes />
<explicitExcludes />
</component>
</project>
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
+107
View File
@@ -0,0 +1,107 @@
using Raindrop.UI.Views;
using Raindrop.Utilities;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//Add the panning behavior to the current GO.
public class AddTouchGesturesHandler : MonoBehaviour
{
[SerializeField]
private MapUI mapUI;
public GameObject mapUIGO;
[SerializeField]
public GameObject cameraGO;
private Camera camera;
[SerializeField]
public GameObject pannableFrame;
[SerializeField]
public float panningSpeed;
public float prevCameraSize;
public Vector2 startPoint;
private void Awake()
{
camera = cameraGO.GetComponent<Camera>();
//mapUI = Raindrop.Globals.GetUI().Get //mapUIGO.GetComponent<MapUI>();
}
// Start is called before the first frame update
void Start()
{
if (true)
{
var recognizer = new TKPanRecognizer(0.5f);
// when using in conjunction with a pinch or rotation recognizer setting the min touches to 2 smoothes movement greatly
if (Application.platform == RuntimePlatform.IPhonePlayer)
recognizer.minimumNumberOfTouches = 2;
Rect rect = pannableFrame.GetComponent<RectTransform>().rect;
recognizer.boundaryFrame = new TKRect(rect.x, rect.y, rect.width, rect.height);
recognizer.gestureRecognizedEvent += (r) =>
{
Vector2 start = recognizer.startPoint;
startPoint = start;
if (false)
{
//do nothing.
} else {
camera.transform.position -= new Vector3(recognizer.deltaTranslation.x, 0, recognizer.deltaTranslation.y) / panningSpeed * camera.orthographicSize;
}
Debug.Log("pan recognizer fired: " + r.ToString());
};
// continuous gestures have a complete event so that we know when they are done recognizing
recognizer.gestureCompleteEvent += r =>
{
//Debug.Log("pan gesture complete");
};
TouchKit.addGestureRecognizer(recognizer);
}
if (true)
{
var recognizer = new TKPinchRecognizer();
recognizer.gestureRecognizedEvent += (r) =>
{
camera.orthographicSize = prevCameraSize / recognizer.accumulatedScale;
//Debug.Log("pinch recognizer fired: " + r);
};
TouchKit.addGestureRecognizer(recognizer);
recognizer.gestureCompleteEvent += (r) =>
{
prevCameraSize = camera.orthographicSize;
//Debug.Log("pinch gesture complete");
};
}
if (true)
{
var recognizer = new TKTapRecognizer();
recognizer.gestureRecognizedEvent += (r) =>
{
Vector3 worldPoint = camera.ScreenToWorldPoint((Vector2)recognizer.touchLocation());
ulong regionCoords = Coverters.getRegionFromWorldPoint(worldPoint);
mapUI.getPresenter().OnMapClick(regionCoords);
//Debug.Log("tap recognizer fired: " + r);
};
TouchKit.addGestureRecognizer(recognizer);
}
}
}
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 7d508ea865710a541926ea78ecd7f988
guid: d40caf415b9dac141964277c09d665e8
MonoImporter:
externalObjects: {}
serializedVersion: 2
+2 -2
View File
@@ -234,8 +234,8 @@ MonoBehaviour:
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 24
m_fontSizeBase: 24
m_fontSize: 32
m_fontSizeBase: 32
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
File diff suppressed because one or more lines are too long
@@ -0,0 +1,93 @@
Copyright 2011-2016 The Varela Round Project Authors (https://github.com/alefalefalef/Varela-Round-Hebrew/), with Reserved Font Names 'Varela' and Varela Round.
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -1,6 +1,6 @@
fileFormatVersion: 2
guid: 4917e73af158b1e4782b175c0568afcf
timeCreated: 1452175972
guid: c5d93bc2f677e234cbed4af1d1353513
timeCreated: 1474722481
licenseType: Store
TextScriptImporter:
userData:
-2
View File
@@ -92,8 +92,6 @@ namespace Lean.Common.Editor
[UnityEditor.CustomEditor(typeof(TARGET))]
public class LeanRoll_Editor : LeanEditor
{
private bool showUnusedEvents;
protected override void OnInspector()
{
TARGET tgt; TARGET[] tgts; GetTargets(out tgt, out tgts);
@@ -60,6 +60,8 @@ namespace Lean.Common.Editor
if (updateColor == true)
{
serializedObject.ApplyModifiedProperties();
Each(tgts, t => t.UpdateColor(), true);
}
}
+16 -15
View File
@@ -1,4 +1,5 @@
using UnityEngine;
using FSA = UnityEngine.Serialization.FormerlySerializedAsAttribute;
namespace Lean.Common
{
@@ -15,22 +16,22 @@ namespace Lean.Common
}
/// <summary>The prefab that this component can spawn.</summary>
public Transform Prefab;
public Transform Prefab { set { prefab = value; } get { return prefab; } } [FSA("Prefab")] [SerializeField] private Transform prefab;
/// <summary>If you call <b>Spawn()</b>, where should the position come from?</summary>
public SourceType DefaultPosition;
public SourceType DefaultPosition { set { defaultPosition = value; } get { return defaultPosition; } } [FSA("DefaultPosition")] [SerializeField] private SourceType defaultPosition;
/// <summary>If you call <b>Spawn()</b>, where should the rotation come from?</summary>
public SourceType DefaultRotation;
public SourceType DefaultRotation { set { defaultRotation = value; } get { return defaultRotation; } } [FSA("DefaultRotation")] [SerializeField] private SourceType defaultRotation;
/// <summary>This will spawn <b>Prefab</b> at the current <b>Transform.position</b>.</summary>
public void Spawn()
{
if (Prefab != null)
if (prefab != null)
{
var position = DefaultPosition == SourceType.Prefab ? Prefab.position : transform.position;
var rotation = DefaultRotation == SourceType.Prefab ? Prefab.rotation : transform.rotation;
var clone = Instantiate(Prefab, position, rotation);
var position = defaultPosition == SourceType.Prefab ? prefab.position : transform.position;
var rotation = defaultRotation == SourceType.Prefab ? prefab.rotation : transform.rotation;
var clone = Instantiate(prefab, position, rotation);
clone.gameObject.SetActive(true);
}
@@ -39,10 +40,10 @@ namespace Lean.Common
/// <summary>This will spawn <b>Prefab</b> at the specified position in world space.</summary>
public void Spawn(Vector3 position)
{
if (Prefab != null)
if (prefab != null)
{
var rotation = DefaultRotation == SourceType.Prefab ? Prefab.rotation : transform.rotation;
var clone = Instantiate(Prefab, position, rotation);
var rotation = defaultRotation == SourceType.Prefab ? prefab.rotation : transform.rotation;
var clone = Instantiate(prefab, position, rotation);
clone.gameObject.SetActive(true);
}
@@ -59,15 +60,15 @@ namespace Lean.Common.Editor
[UnityEditor.CustomEditor(typeof(TARGET))]
public class LeanSpawn_Editor : LeanEditor
{
private bool showUnusedEvents;
protected override void OnInspector()
{
TARGET tgt; TARGET[] tgts; GetTargets(out tgt, out tgts);
Draw("Prefab", "The prefab that this component can spawn.");
Draw("DefaultPosition", "If you call Spawn(), where should the position come from?");
Draw("DefaultRotation", "If you call Spawn(), where should the rotation come from?");
BeginError(Any(tgts, t => t.Prefab == null));
Draw("prefab", "The prefab that this component can spawn.");
EndError();
Draw("defaultPosition", "If you call Spawn(), where should the position come from?");
Draw("defaultRotation", "If you call Spawn(), where should the rotation come from?");
}
}
}
+43 -21
View File
@@ -8,7 +8,9 @@ namespace Lean.Common
/// <summary>This is the base class for all inspectors.</summary>
public abstract class LeanEditor : UnityEditor.Editor
{
private static SerializedObject data;
private static SerializedObject dataA;
private static SerializedProperty dataB;
private static GUIContent customContent = new GUIContent();
@@ -27,7 +29,20 @@ namespace Lean.Common
public static void SetData(SerializedObject newData)
{
data = newData;
dataA = newData;
dataB = null;
}
public static void SetData(SerializedProperty newData)
{
dataA = null;
dataB = newData;
}
public static void ClearData()
{
dataA = null;
dataB = null;
}
public override void OnInspectorGUI()
@@ -44,17 +59,7 @@ namespace Lean.Common
serializedObject.ApplyModifiedProperties();
data = null;
}
public virtual void OnSceneGUI()
{
OnScene();
if (GUI.changed == true)
{
EditorUtility.SetDirty(target);
}
ClearData();
}
protected void Each<T>(T[] tgts, System.Action<T> update, bool dirty = false)
@@ -393,6 +398,22 @@ namespace Lean.Common
return false;
}
public static SerializedProperty GetProperty(string propertyPath)
{
var property = default(SerializedProperty);
if (dataA != null)
{
property = dataA.FindProperty(propertyPath);
}
else if (dataB != null)
{
property = dataB.FindPropertyRelative(propertyPath);
}
return property;
}
protected void DirtyAndUpdate()
{
for (var i = targets.Length - 1; i >= 0; i--)
@@ -405,10 +426,10 @@ namespace Lean.Common
private static SerializedProperty GetPropertyAndSetCustomContent(string propertyPath, string overrideTooltip, string overrideText)
{
var property = data.FindProperty(propertyPath);
var property = GetProperty(propertyPath);
customContent.text = string.IsNullOrEmpty(overrideText ) == false ? overrideText : property.displayName;
customContent.tooltip = string.IsNullOrEmpty(overrideTooltip) == false ? overrideTooltip : property.tooltip;
customContent.text = string.IsNullOrEmpty(overrideText ) == false || property == null ? overrideText : property.displayName;
customContent.tooltip = string.IsNullOrEmpty(overrideTooltip) == false || property == null ? overrideTooltip : property.tooltip;
customContent.tooltip = StripRichText(customContent.tooltip); // Tooltips can't display rich text for some reason, so strip it
return property;
@@ -416,16 +437,17 @@ namespace Lean.Common
private static string StripRichText(string s)
{
return s.Replace("<b>", "").Replace("</b>", "");
if (s != null)
{
s = s.Replace("<b>", "").Replace("</b>", "");
}
return s;
}
protected virtual void OnInspector()
{
}
protected virtual void OnScene()
{
}
}
}
#endif
+1 -1
View File
@@ -11,7 +11,7 @@ namespace Lean.Common
#if ENABLE_INPUT_SYSTEM
private static System.Collections.Generic.Dictionary<KeyCode, NewCode> keyMapping = new System.Collections.Generic.Dictionary<KeyCode, NewCode>()
{
{ KeyCode.None, NewCode.None },
//{ KeyCode.None, NewCode.None },
{ KeyCode.Backspace, NewCode.Backspace },
{ KeyCode.Tab, NewCode.Tab },
{ KeyCode.Clear, NewCode.None },
File diff suppressed because one or more lines are too long
+50 -1
View File
@@ -13,6 +13,18 @@ namespace Lean.Gui
[AddComponentMenu(LeanGui.ComponentMenuPrefix + "Button")]
public class LeanButton : LeanSelectable, IPointerDownHandler, IBeginDragHandler, IDragHandler, IEndDragHandler, ISubmitHandler
{
[System.Flags]
public enum ButtonTypes
{
LeftMouse = 1 << 0,
RightMouse = 1 << 1,
MiddleMouse = 1 << 2,
Touch = 1 << 5
}
/// <summary>Which buttons should this component react to?</summary>
public ButtonTypes RequiredButtons { set { requiredButtons = value; } get { return requiredButtons; } } [SerializeField] private ButtonTypes requiredButtons = (ButtonTypes)~0;
/// <summary>If you enable this then OnDown + DownTransition be invoked once for each finger that begins touching the button.
/// If you disable this then OnDown + DownTransition will only be invoked for the first finger that begins touching the button.</summary>
public bool MultiDown { set { multiDown = value; } get { return multiDown; } } [SerializeField] private bool multiDown;
@@ -59,8 +71,13 @@ namespace Lean.Gui
{
base.OnPointerDown(eventData);
if (IsInteractable() == true && eventData.button == PointerEventData.InputButton.Left)
if (IsInteractable() == true)
{
if (RequiredButtonPressed(eventData) == false)
{
return;
}
totalDelta = Vector2.zero;
downPointers.Add(eventData.pointerId);
@@ -188,6 +205,37 @@ namespace Lean.Gui
onClick.Invoke();
}
}
private bool RequiredButtonPressed(PointerEventData eventData)
{
if (LeanInput.GetMouseExists() == true)
{
if ((requiredButtons & ButtonTypes.LeftMouse) != 0 && eventData.button == PointerEventData.InputButton.Left)
{
return true;
}
if ((requiredButtons & ButtonTypes.RightMouse) != 0 && eventData.button == PointerEventData.InputButton.Right)
{
return true;
}
if ((requiredButtons & ButtonTypes.MiddleMouse) != 0 && eventData.button == PointerEventData.InputButton.Middle)
{
return true;
}
}
if (LeanInput.GetTouchCount() > 0)
{
if ((requiredButtons & ButtonTypes.Touch) != 0 && eventData.button == PointerEventData.InputButton.Left)
{
return true;
}
}
return false;
}
}
}
@@ -205,6 +253,7 @@ namespace Lean.Gui.Editor
base.DrawSelectableSettings();
Draw("dragThreshold", "If your finger presses down on the button and drags more than this many pixels, then selection will be canceled.\n\n-1 = Unlimited drag distance.\n\n0 = Until the finger exits the button graphic.");
Draw("requiredButtons", "Which buttons should this component react to?");
Draw("multiDown", "If you press multiple fingers on this button at the same time, should OnDown and DownTransition be invoked multiple times?");
}
+18
View File
@@ -49,6 +49,9 @@ namespace Lean.Gui
/// If you enable this, then the joystick will be placed relative to the place you first touch this UI element.</summary>
public bool RelativeToOrigin { set { relativeToOrigin = value; } get { return relativeToOrigin; } } [SerializeField] private bool relativeToOrigin;
/// <summary>When the mouse/finger releases from the joystick, should the joystick value reset to the center, or stay where it is?</summary>
public bool CenterOnRelease { set { centerOnRelease = value; } get { return centerOnRelease; } } [SerializeField] private bool centerOnRelease = true;
/// <summary>If you want to show the boundary of the joystick relative to the origin, then you can make a new child GameObject graphic, and set its RectTransform here.</summary>
public RectTransform RelativeRect { set { relativeRect = value; } get { return relativeRect; } } [SerializeField] private RectTransform relativeRect;
@@ -88,6 +91,12 @@ namespace Lean.Gui
[System.NonSerialized]
private bool cachedRectTransformSet;
[System.NonSerialized]
private Vector2 lastValue;
[System.NonSerialized]
private bool lastValueSet;
public RectTransform CachedRectTransform
{
get
@@ -106,6 +115,11 @@ namespace Lean.Gui
{
var value = Vector2.zero;
if (centerOnRelease == false && lastValueSet == true)
{
value = lastValue;
}
if (pointer != null)
{
if (IsInteractable() == true)
@@ -139,6 +153,9 @@ namespace Lean.Gui
}
}
lastValue = value;
lastValueSet = true;
// Update scaledValue
if (shape == ShapeType.Box)
{
@@ -267,6 +284,7 @@ namespace Lean.Gui.Editor
Separator();
Draw("relativeToOrigin", "By default, the joystick will be placed relative to the center of this UI element.\n\nIf you enable this, then the joystick will be placed relative to the place you first touch this UI element.");
Draw("centerOnRelease", "When the mouse/finger releases from the joystick, should the joystick value reset to the center, or stay where it is?");
if (Any(tgts, t => t.RelativeToOrigin == true))
{
+8 -3
View File
@@ -11,6 +11,8 @@ namespace Lean.Gui
[AddComponentMenu(LeanGui.ComponentMenuPrefix + "Pulse")]
public class LeanPulse : MonoBehaviour
{
[System.Serializable] public class IntEvent : UnityEvent<int> {}
/// <summary>This stores all active and enabled LeanPulse instances, so you can manually pulse them by name from anywhere.</summary>
public static LinkedList<LeanPulse> Instances = new LinkedList<LeanPulse>();
@@ -33,8 +35,9 @@ namespace Lean.Gui
/// For example, the <b>LeanPlaySound (Play Sound Transition)</b> component can be used to play a pulse sound.</summary>
public LeanPlayer PulseTransitions { get { if (pulseTransitions == null) pulseTransitions = new LeanPlayer(); return pulseTransitions; } } [SerializeField] private LeanPlayer pulseTransitions;
/// <summary>This allows you to perform an action when this UI element pulses.</summary>
public UnityEvent OnPulse { get { if (onPulse == null) onPulse = new UnityEvent(); return onPulse; } } [SerializeField] private UnityEvent onPulse;
/// <summary>This allows you to perform an action when this UI element pulses.
/// int = RemainingPulses</summary>
public IntEvent OnPulse { get { if (onPulse == null) onPulse = new IntEvent(); return onPulse; } } [SerializeField] private IntEvent onPulse;
[System.NonSerialized]
private LinkedListNode<LeanPulse> link;
@@ -55,6 +58,8 @@ namespace Lean.Gui
}
}
remainingTime = timeInterval;
Pulse();
}
@@ -69,7 +74,7 @@ namespace Lean.Gui
if (onPulse != null)
{
onPulse.Invoke();
onPulse.Invoke(remainingPulses);
}
}
+42 -18
View File
@@ -26,8 +26,8 @@ namespace Lean.Gui
public enum BoundaryType
{
None,
Pivot,
Position
FlipPivot,
ShiftPosition
}
public enum ActivationType
@@ -49,7 +49,10 @@ namespace Lean.Gui
/// <summary>Move the attached Transform when the tooltip is open?</summary>
public bool Move { set { move = value; } get { return move; } } [SerializeField] private bool move = true;
/// <summary>This allows you to control how the tooltip will behave when it goes outside the screen bounds.</summary>
/// <summary>This allows you to control how the tooltip will behave when it goes outside the screen bounds.
/// FlipPivot = If the tooltip goes outside one of the screen boundaries, flip its pivot point on that axis so it goes the other way.
/// ShiftPosition = If the tooltip goes outside of the screen boundaries, shift its position until it's back inside.
/// NOTE: If <b>FlipPivot</b> is used and the tooltip is larger than the screen size, then it will revert to <b>ShiftPosition</b>.</summary>
public BoundaryType Boundary { set { boundary = value; } get { return boundary; } } [SerializeField] private BoundaryType boundary;
/// <summary>This allows you to perform a transition when this tooltip appears.
@@ -161,28 +164,49 @@ namespace Lean.Gui
{
cachedRectTransform.GetWorldCorners(corners);
var min = Vector2.Min(corners[0], Vector2.Min(corners[1], Vector2.Min(corners[2], corners[3])));
var max = Vector2.Max(corners[0], Vector2.Max(corners[1], Vector2.Max(corners[2], corners[3])));
var min = Vector2.Min(corners[0], Vector2.Min(corners[1], Vector2.Min(corners[2], corners[3])));
var max = Vector2.Max(corners[0], Vector2.Max(corners[1], Vector2.Max(corners[2], corners[3])));
var pivot = cachedRectTransform.pivot;
var position = cachedRectTransform.position;
var boundaryX = boundary;
var boundaryY = boundary;
if (boundary == BoundaryType.Pivot)
// If the tooltip cannot be flipped at its current position & size, revert to Boundary = Position?
if (boundary == BoundaryType.FlipPivot)
{
var pivot = cachedRectTransform.pivot;
var size = max - min;
if (finalPoint.x - size.x < 0 && finalPoint.x + size.x > Screen.width)
{
boundaryX = BoundaryType.ShiftPosition;
}
if (finalPoint.y - size.y < 0 && finalPoint.y + size.y > Screen.height)
{
boundaryY = BoundaryType.ShiftPosition;
}
}
if (boundaryX == BoundaryType.FlipPivot)
{
if (min.x < 0.0f) pivot.x = 0.0f; else if (max.x > Screen.width ) pivot.x = 1.0f;
if (min.y < 0.0f) pivot.y = 0.0f; else if (max.y > Screen.height) pivot.y = 1.0f;
cachedRectTransform.pivot = pivot;
}
if (boundary == BoundaryType.Position)
else if (boundaryX == BoundaryType.ShiftPosition)
{
var position = cachedRectTransform.position;
if (min.x < 0.0f) position.x -= min.x; else if (max.x > Screen.width ) position.x -= max.x - Screen.width;
if (min.y < 0.0f) position.y -= min.y; else if (max.y > Screen.height) position.y -= max.y - Screen.height;
cachedRectTransform.position = position;
}
if (boundaryY == BoundaryType.FlipPivot)
{
if (min.y < 0.0f) pivot.y = 0.0f; else if (max.y > Screen.height) pivot.y = 1.0f;
}
else if (boundaryY == BoundaryType.ShiftPosition)
{
if (min.y < 0.0f) position.y -= min.y; else if (max.y > Screen.height) position.y -= max.y - Screen.height;
}
cachedRectTransform.pivot = pivot;
cachedRectTransform.position = position;
}
}
@@ -238,7 +262,7 @@ namespace Lean.Gui.Editor
if (Any(tgts, t => t.Move == true))
{
BeginIndent();
Draw("boundary", "This allows you to control how the tooltip will behave when it goes outside the screen bounds.");
Draw("boundary", "This allows you to control how the tooltip will behave when it goes outside the screen bounds.\n\nFlipPivot = If the tooltip goes outside one of the screen boundaries, flip its pivot point on that axis so it goes the other way.\n\nShiftPosition = If the tooltip goes outside of the screen boundaries, shift its position until it's back inside.\n\nNOTE: If <b>FlipPivot</b> is used and the tooltip is larger than the screen size, then it will revert to <b>ShiftPosition</b>.");
EndIndent();
}
+99
View File
@@ -0,0 +1,99 @@
This package contains third-party software components governed by the license(s) indicated below:
Component Name: Common/Examples/Fonts/VarelaRound-Regular
License Types: SIL OPEN FONT LICENSE Version 1.1
Copyright 2011-2016 The Varela Round Project Authors (https://github.com/alefalefalef/Varela-Round-Hebrew/), with Reserved Font Names 'Varela' and 'Varela Round'.
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 78cde942f7000eb41900aa4d3c9249d7
guid: 0e61dc046618c394d8d69f70fda62ce1
TextScriptImporter:
externalObjects: {}
userData:
File diff suppressed because one or more lines are too long
+12
View File
@@ -0,0 +1,12 @@
{
"name": "com.cwilkes.lean",
"displayName": "Lean",
"version": "1.0.0",
"author": {
"name": "Carlos Wilkes",
"email": "carlos.wilkes@gmail.com",
"url": "https://carloswilkes.com"
},
"unity": "2019.4",
"description": "Lightweight extensions for all projects."
}
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: b5ee7f1788474bd44a48b0a201461151
guid: 32dcfd6f0d58c7642bcc6fb2b1e7c8ff
TextScriptImporter:
externalObjects: {}
userData:
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 170727669b453a54cabcdf28b2c6de9e
guid: 6860f9f51a4b1d7499390505ab3689cd
folderAsset: yes
DefaultImporter:
externalObjects: {}
+151
View File
@@ -0,0 +1,151 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2.0.0] - 2021-12-31
### Changed
- Minimum version is now 2019.4 LTS, eliminating all Unity version scripting defines in the code. (Previously, .1 is the minimum, .2 enables `cutouts` API, and .3 enables Unity device simulator integration.) Being on LTS version positions this package for better future. This is a **breaking change** for those on lower than 2019.4 LTS.
- Author name in `package.json` changed from "Sirawat Pitaksarit / 5argon - Exceed7 Experiments" to just "Exceed7 Experiments". I found that Unity Package Manager has a drop down that group by this string. Now it is consistent with my other works and is also shorter.
- `Unity.ugui` removed from `E7.NotchSolution.asmdef` and `E7.NotchSolution.Editor.asmdef`. It is no longer needed to be explicitly referenced in 2019.4. (Thank god)
- XML code documentation refactors. API tab in the Website is also reflected.
### Fixed
Merged many PR fixes from contributors in the GitHub repository over the years where I took a break from this package. Thank you!
- [Notch Simulator automatically resizes Game window and configurable device orientation in Notch Simulator Window #54](https://github.com/5argon/NotchSolution/pull/54). (Contributed by [yasirkula](https://github.com/yasirkula).)
- [Fix GC allocation (96 byte) #55](https://github.com/5argon/NotchSolution/pull/55). (Contributed by [JohannesDeml](https://github.com/JohannesDeml).)
- [Gracefully handle a null mockupImage on reload #57](https://github.com/5argon/NotchSolution/pull/57). (Contributed by [BenWoodford](https://github.com/BenWoodford).)
- [Fix safe area calculations for Unity Standalone builds #60](https://github.com/5argon/NotchSolution/pull/60). (Contributed by [jollyMZ](https://github.com/jollyMZ).)
- [Fix bug on Unity 2019.3 where SafePadding Editor Labels (Left, Bottom,Top and Right) were not being shown! #63](https://github.com/5argon/NotchSolution/pull/63). (Contributed by [wagenheimer](https://github.com/wagenheimer).)
- [Handle new Unity Device Simulator window name #64](https://github.com/5argon/NotchSolution/pull/64). (Contributed by [robinnorth](https://github.com/robinnorth).)
## [1.9.0] - 2019-11-25
### Added
- Asset Store version is now available! It's been almost a year since start, right now I think I am quite confident about the package.
- New dedicated website http://exceed7.com/notch-solution which sync with the also new offline `Documentation~` hidden folder of this package.
- The debug scene is now compatible with UPM's import samples button.
### Changed
- Massive documentation structure change. They are now able to be used with [DocFx](https://dotnet.github.io/docfx/) while still quite readable from code editor. (But instead we could make a static site or even a PDF now.)
- XML triple slash code comments update across all files so DocFx could generate an online documentation correctly.
- Access modifiers revised, many wrong `public` are now properly `internal` for example. It also make DocFx generates only what the user should care about. If you were using some of those wrong `public` your code may break, however.
- The debug scene is moved to `/Samples~` to support [UPM sample importing](https://forum.unity.com/threads/samples-in-packages-manual-setup.623080/). (To maintainers : remove `~` when you want to edit, then add back when finished.) More scene which will actually be a sample of how to build the UI will be added in this proper format. Tutorial is also added to [the website](http://exceed7.com/notch-solution/simulator/debug-scene.html).
- `LICENSE` changed to `LICENSE.md` because otherwise the "license" link in UPM will not link to it.
### Fixed
- Fixed a problem that Device Simulator was simulating `Screen.currentResolution` instead of `Screen.width/height` and Notch Solution components were looking to `Screen.width/height` and getting wrong modifications.
## [1.8.0] - 2019-10-30
### Added
- Configuration system : you are given 2 configurations for each build platform. In each one it can remember its own overlay. This is used in a workflow where you constantly check between two extreme setups (e.g. iPhone - iPad) while iterating on the game UI.
- It now use asset file in `ProjectSettings` instead of `EditorPrefs`. Settings is now persisted per-project. Code related to `EditorPrefs` has been refactored everywhere.
- Device database migrated to definition file based in the same format as Unity Device Simulator package in 2019.3 is using. (Contributed by [06Games](https://github.com/06Games))
### Removed
- Alt+M to switch Game View between 2 settings has been removed along with `EditorPrefs`. This funtionality will be added back to the new configuration system later.
## [1.7.0] - 2019-10-24
### Added
- Added support for 2019.3 in general.
- Added support for [Unity Device Simulator package](https://docs.unity3d.com/Packages/com.unity.device-simulator@latest). If we detected that, all the components that wants a safe area simply ignores Notch Simulator simulated values and go back to follow `Screen.safeArea` just like in runtime, but it is now modified in edit time from inside-out by Device Simulator package. The package is 2019.3 or above only.
- Galaxy Note 10 Plus device overlay added. (Contributed by [06Games](https://github.com/06Games))
## [1.6.0] - 2019-06-22
### Added
- Add an editor button for creating all required assets for adaptation components.
- Add an editor button for temporarily assign the controller asset so you could design the adaptation in Animation panel. (Usable with asset created from the prior button.)
- Documentation structure refactored. (Contributed by [06Games](https://github.com/06Games))
## [1.5.0] - 2019-06-20
### Added
- "Adaptation" components added. This series of components could adapt anything including non-UI stuff with help from **animation playables API**. This is needed because with `SafePadding` we were relying on uGUI layout system to move the entire hierarchy tree, and it is not usable outside of uGUI. The adaptation component is more flexible, as long as something is animation keyable, it could be responsive to a presence of notch & other things.
- `SafeAdaptation` : Adapt according to relative screen space taken by a selectable single side of safe area.
- `AspectRatioAdaptation` : Like `SafeAdaptation` but use aspect ratio number of the screen. Doesn't sounds notch-related, but it is a part of "notch solution" because I have use this together to solve arrangement problems.
- New script icon for `SafePadding` since I lose the original vector project file, and I want the newly made component icons to look similar to it. ([Affinity Designer](https://affinity.serif.com/en-gb/designer/) icon project file is also added to `Icons` folder in the repo now to prevent losing it again.)
- Cutout information propagated to layout components, but currently unused. (Contributed by [06Games](https://github.com/06Games))
### Fixed
- Code refactor throughout.
- Sometimes the overlay mockup didn't update its overlay graphic. Added a new destroy-create routine to force refresh it. (Contributed by [06Games](https://github.com/06Games))
## [1.4.0] - 2019-06-04
### Added
![preference](Documentation~/simulator/images/pref.png)
- Preference item added under "Notch Solution". You can adjust overlay color of prefab mode there.
- New shortcut to quick switch between 2 Game view aspect ratio. Set this up in the preference menu. This is ideal for mobile development where if you could ensure that narrowest and widest screen looks nice, everything in-between should also work.
- Overlay for Samsung Galaxy S10 and S10+ added. (Contributed by [06Games](https://github.com/06Games))
- Tree simulation device enum selector for 2019.2+ (Contributed by [06Games](https://github.com/06Games))
## [1.3.0] - 2019-05-28
### Added
- `influence` added to `SafePadding`, it is default to 1 that means the safe area taking full effect. It applies to all sides.
- "Dual Orientation" choice now only show up in Inspector if in your Player Settings, Resolution and Presentation section, you have Orientation settings in a way that it is possible to get both portrait and landscape orientation.
- Shortcut for toggling notch simulation added with the new `UnityEditor.ShortcutManagement` shortcut API. Bound to `Alt+N` by default.
- Cutout database for all available devices. Although they are not used yet currently.
### Fixed
- Removed `[ExecuteInEditMode]` from `SafePadding`.
- Simulation database for One Plus 6T and Huawei Mate 20 Pro was incorrect. It is now updated according to submitted debug data in [this thread](https://github.com/5argon/NotchSolution/issues/2).
- `HideFlags` mistake fixed.
## [1.2.0] - 2019-05-18
### Added
- Prefab mode ([`PrefabStage`](https://docs.unity3d.com/ScriptReference/Experimental.SceneManagement.PrefabStage.html)) suppport added. There is now an overlay while editing a prefab, so you could design "full screen canvas as a prefab" in isolation while preview the notch. Previously you must save the prefab first, the see the update in Game tab while Scene tab is still in prefab mode. Note that `PrefabStage` is in experimental namespace, it is bound to break in future version.
- New simulation device : iPad Pro. From running screen query on the Xcode simulator, the iPad Pro do have a safe area of 40px for that black line at the bottom (both orientations), plus small curved corners.
- Added a changelog.
### Fixed
- Aspect ratio number in the Notch Simulator warning help box is rounded to nice number.
- `SafePadding`'s delayed update is now using `WaitForEndOfFrame` instead of wait for the next frame.
## [1.1.0] - 2019-02-11
This is not an actual version since I just keep a changelog starting from 1.2.0, but I will list notable changes here off the top of my head.
### Added
- Debug scene added. It is now possible to distribute a test APK to collect cutout data of various phone. 2019.2's `Screen.cutouts` is supported in the debug scene, but no actual use by the `SafePadding` yet.
- Overlay color matches Personal and Professional skin.
- Two new devices: Huawei Mate 20 Pro & OnePlus 6T. (Contributed by [06Games](https://github.com/06Games))
- Added a warning about wrong Game tab aspect not matching notch preview device.
- Added a `README.md` documentation.
### Fixed
- `OnEnable` of `SafePadding` changed to delayed update. (Contributed by [Froghut](https://github.com/Froghut))
- Screen ratio function fixed. (Contributed by [06Games](https://github.com/06Games))
- Get the correct root canvas when you have multiple nested `Canvas` on the hierarchy. (Contributed by [mmatvein](https://github.com/mmatvein))
## [1.0.0] - 2018-12-27
The first version!!
+7
View File
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 82598f6f3d95b4956808fc44781676cd
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 3d9bd58f4dad04d4aa76be96981ea7d1
guid: d6f4ea58d0568461e8a9c85a325c2517
DefaultImporter:
externalObjects: {}
userData:
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 120d8012b493a1b47aa4dd9cae7ae71e
guid: 871c6c22734d24a9dae444a043614aa9
folderAsset: yes
DefaultImporter:
externalObjects: {}
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: f6caf5b6d3f510041b368113d86f4459
guid: e6ee4d37d64882c4fac2dc0b3aad29cb
folderAsset: yes
DefaultImporter:
externalObjects: {}
@@ -0,0 +1,266 @@
{
"Meta": {
"friendlyName": "Apple/ iPad Pro 12.9 (2018)",
"overlay": "",
"overlayOffset": {
"x": 80.0,
"y": 80.0,
"z": 80.0,
"w": 80.0
},
"overlayImage": {
"instanceID": 0
}
},
"Screens": [
{
"width": 2048,
"height": 2732,
"navigationBarHeight": 0,
"dpi": 264.0,
"orientationKeys": [
1,
2,
3,
4
],
"orientationValues": [
{
"safeArea": {
"serializedVersion": "2",
"x": 0.0,
"y": 40.0,
"width": 2048.0,
"height": 2692.0
},
"cutouts": []
},
{
"safeArea": {
"serializedVersion": "2",
"x": 0.0,
"y": 40.0,
"width": 2048.0,
"height": 2692.0
},
"cutouts": []
},
{
"safeArea": {
"serializedVersion": "2",
"x": 0.0,
"y": 40.0,
"width": 2732.0,
"height": 2008.0
},
"cutouts": []
},
{
"safeArea": {
"serializedVersion": "2",
"x": 0.0,
"y": 40.0,
"width": 2732.0,
"height": 2008.0
},
"cutouts": []
}
]
}
],
"SystemInfo": {
"deviceModel": "iPad8,5",
"deviceType": 1,
"operatingSystem": "iOS 12.1.1",
"operatingSystemFamily": 0,
"processorCount": 8,
"processorFrequency": 0,
"processorType": "arm64e",
"supportsAccelerometer": true,
"supportsAudio": true,
"supportsGyroscope": true,
"supportsLocationService": true,
"supportsVibration": false,
"systemMemorySize": 3735,
"unsupportedIdentifier": "n/a",
"GraphicsDependentData": [
{
"graphicsDeviceType": 16,
"graphicsMemorySize": 1024,
"graphicsDeviceName": "Apple A12X GPU",
"graphicsDeviceVendor": "Apple",
"graphicsDeviceID": 0,
"graphicsDeviceVendorID": 0,
"graphicsUVStartsAtTop": true,
"graphicsDeviceVersion": "Metal",
"graphicsShaderLevel": 50,
"graphicsMultiThreaded": true,
"renderingThreadingMode": 0,
"hasHiddenSurfaceRemovalOnGPU": true,
"hasDynamicUniformArrayIndexingInFragmentShaders": true,
"supportsShadows": true,
"supportsRawShadowDepthSampling": true,
"supportsMotionVectors": true,
"supports3DTextures": true,
"supports2DArrayTextures": true,
"supports3DRenderTextures": true,
"supportsCubemapArrayTextures": true,
"copyTextureSupport": 31,
"supportsComputeShaders": true,
"supportsGeometryShaders": false,
"supportsTessellationShaders": true,
"supportsInstancing": true,
"supportsHardwareQuadTopology": false,
"supports32bitsIndexBuffer": true,
"supportsSparseTextures": false,
"supportedRenderTargetCount": 8,
"supportsSeparatedRenderTargetsBlend": true,
"supportedRandomWriteTargetCount": 8,
"supportsMultisampledTextures": 1,
"supportsMultisampleAutoResolve": false,
"supportsTextureWrapMirrorOnce": 0,
"usesReversedZBuffer": true,
"npotSupport": 2,
"maxTextureSize": 16384,
"maxCubemapSize": 16384,
"maxComputeBufferInputsVertex": 8,
"maxComputeBufferInputsFragment": 8,
"maxComputeBufferInputsGeometry": 0,
"maxComputeBufferInputsDomain": 8,
"maxComputeBufferInputsHull": 8,
"maxComputeBufferInputsCompute": 8,
"maxComputeWorkGroupSize": 1024,
"maxComputeWorkGroupSizeX": 1024,
"maxComputeWorkGroupSizeY": 1024,
"maxComputeWorkGroupSizeZ": 1024,
"supportsAsyncCompute": false,
"supportsGraphicsFence": true,
"supportsAsyncGPUReadback": true,
"supportsRayTracing": false,
"supportsSetConstantBuffer": true,
"minConstantBufferOffsetAlignment": true,
"hasMipMaxLevel": true,
"supportsMipStreaming": true,
"usesLoadStoreActions": true
},
{
"graphicsDeviceType": 11,
"graphicsMemorySize": 1024,
"graphicsDeviceName": "Apple A12X GPU",
"graphicsDeviceVendor": "Apple Inc.",
"graphicsDeviceID": 0,
"graphicsDeviceVendorID": 0,
"graphicsUVStartsAtTop": false,
"graphicsDeviceVersion": "OpenGL ES 3.0 Metal - 58.4",
"graphicsShaderLevel": 35,
"graphicsMultiThreaded": true,
"renderingThreadingMode": 0,
"hasHiddenSurfaceRemovalOnGPU": true,
"hasDynamicUniformArrayIndexingInFragmentShaders": true,
"supportsShadows": true,
"supportsRawShadowDepthSampling": true,
"supportsMotionVectors": true,
"supports3DTextures": true,
"supports2DArrayTextures": true,
"supports3DRenderTextures": true,
"supportsCubemapArrayTextures": false,
"copyTextureSupport": 0,
"supportsComputeShaders": false,
"supportsGeometryShaders": false,
"supportsTessellationShaders": false,
"supportsInstancing": true,
"supportsHardwareQuadTopology": false,
"supports32bitsIndexBuffer": true,
"supportsSparseTextures": false,
"supportedRenderTargetCount": 4,
"supportsSeparatedRenderTargetsBlend": false,
"supportedRandomWriteTargetCount": 0,
"supportsMultisampledTextures": 0,
"supportsMultisampleAutoResolve": false,
"supportsTextureWrapMirrorOnce": 0,
"usesReversedZBuffer": false,
"npotSupport": 2,
"maxTextureSize": 16384,
"maxCubemapSize": 16384,
"maxComputeBufferInputsVertex": 0,
"maxComputeBufferInputsFragment": 0,
"maxComputeBufferInputsGeometry": 0,
"maxComputeBufferInputsDomain": 0,
"maxComputeBufferInputsHull": 0,
"maxComputeBufferInputsCompute": 0,
"maxComputeWorkGroupSize": 0,
"maxComputeWorkGroupSizeX": 0,
"maxComputeWorkGroupSizeY": 0,
"maxComputeWorkGroupSizeZ": 0,
"supportsAsyncCompute": false,
"supportsGraphicsFence": true,
"supportsAsyncGPUReadback": false,
"supportsRayTracing": false,
"supportsSetConstantBuffer": false,
"minConstantBufferOffsetAlignment": true,
"hasMipMaxLevel": true,
"supportsMipStreaming": true,
"usesLoadStoreActions": true
},
{
"graphicsDeviceType": 8,
"graphicsMemorySize": 1024,
"graphicsDeviceName": "Apple A12X GPU",
"graphicsDeviceVendor": "Apple Inc.",
"graphicsDeviceID": 0,
"graphicsDeviceVendorID": 0,
"graphicsUVStartsAtTop": false,
"graphicsDeviceVersion": "OpenGL ES 2.0 Metal - 58.4",
"graphicsShaderLevel": 30,
"graphicsMultiThreaded": true,
"renderingThreadingMode": 0,
"hasHiddenSurfaceRemovalOnGPU": true,
"hasDynamicUniformArrayIndexingInFragmentShaders": true,
"supportsShadows": true,
"supportsRawShadowDepthSampling": true,
"supportsMotionVectors": true,
"supports3DTextures": false,
"supports2DArrayTextures": false,
"supports3DRenderTextures": false,
"supportsCubemapArrayTextures": false,
"copyTextureSupport": 0,
"supportsComputeShaders": false,
"supportsGeometryShaders": false,
"supportsTessellationShaders": false,
"supportsInstancing": false,
"supportsHardwareQuadTopology": false,
"supports32bitsIndexBuffer": true,
"supportsSparseTextures": false,
"supportedRenderTargetCount": 1,
"supportsSeparatedRenderTargetsBlend": false,
"supportedRandomWriteTargetCount": 0,
"supportsMultisampledTextures": 0,
"supportsMultisampleAutoResolve": false,
"supportsTextureWrapMirrorOnce": 0,
"usesReversedZBuffer": false,
"npotSupport": 1,
"maxTextureSize": 4096,
"maxCubemapSize": 4096,
"maxComputeBufferInputsVertex": 0,
"maxComputeBufferInputsFragment": 0,
"maxComputeBufferInputsGeometry": 0,
"maxComputeBufferInputsDomain": 0,
"maxComputeBufferInputsHull": 0,
"maxComputeBufferInputsCompute": 0,
"maxComputeWorkGroupSize": 0,
"maxComputeWorkGroupSizeX": 0,
"maxComputeWorkGroupSizeY": 0,
"maxComputeWorkGroupSizeZ": 0,
"supportsAsyncCompute": false,
"supportsGraphicsFence": true,
"supportsAsyncGPUReadback": false,
"supportsRayTracing": false,
"supportsSetConstantBuffer": false,
"minConstantBufferOffsetAlignment": false,
"hasMipMaxLevel": true,
"supportsMipStreaming": true,
"usesLoadStoreActions": true
}
]
}
}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: f210251c8c25e7d4b86dba2a2896a94f
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,54 @@
{
"Meta": {
"friendlyName": "Apple/ iPhone X",
"overlay": "AppleiPhoneX_Overlay.png"
},
"Screens": [
{
"width": 1125,
"height": 2436,
"orientationKeys": [
1,
3
],
"orientationValues": [
{
"safeArea": {
"serializedVersion": "2",
"x": 0.0,
"y": 102.0,
"width": 1125.0,
"height": 2202.0
},
"cutouts": [
{
"serializedVersion": "2",
"x": 250.0,
"y": 2346.0,
"width": 625.0,
"height": 90.0
}
]
},
{
"safeArea": {
"serializedVersion": "2",
"x": 132.0,
"y": 63.0,
"width": 2172.0,
"height": 1062.0
},
"cutouts": [
{
"serializedVersion": "2",
"x": 0.0,
"y": 250.0,
"width": 90.0,
"height": 625.0
}
]
}
]
}
]
}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 43069765f1e8bae4f9f66b00bc7ee800
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

@@ -0,0 +1,112 @@
fileFormatVersion: 2
guid: d1774c1b79ad8d242967ab0cb83e67a6
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 10
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 0
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,170 @@
{
"Meta": {
"friendlyName": "Huawei/ Mate 20 Pro",
"overlay": "HuaweiMate20Pro_Overlay.png"
},
"Screens": [
{
"width": 1440,
"height": 3120,
"navigationBarHeight": 0,
"dpi": 640.0,
"orientationKeys": [
1,
2,
3,
4
],
"orientationValues": [
{
"safeArea": {
"serializedVersion": "2",
"x": 0.0,
"y": 0.0,
"width": 1440.0,
"height": 3020.0
},
"cutouts": [
{
"serializedVersion": "2",
"x": 374.0,
"y": 3020.0,
"width": 693.0,
"height": 100.0
}
]
},
{
"safeArea": {
"serializedVersion": "2",
"x": 0.0,
"y": 100.0,
"width": 1440.0,
"height": 3020.0
},
"cutouts": [
{
"serializedVersion": "2",
"x": 373.0,
"y": 0.0,
"width": 693.0,
"height": 100.0
}
]
},
{
"safeArea": {
"serializedVersion": "2",
"x": 100.0,
"y": 0.0,
"width": 3020.0,
"height": 1440.0
},
"cutouts": [
{
"serializedVersion": "2",
"x": 0.0,
"y": 374.0,
"width": 100.0,
"height": 693.0
}
]
},
{
"safeArea": {
"serializedVersion": "2",
"x": 0.0,
"y": 0.0,
"width": 3020.0,
"height": 1440.0
},
"cutouts": [
{
"serializedVersion": "2",
"x": 3020.0,
"y": 373.0,
"width": 100.0,
"height": 693.0
}
]
}
]
}
],
"SystemInfo": {
"deviceModel": "HUAWEI LYA-L29",
"deviceType": 1,
"operatingSystem": "Android OS 9 / API-28 (HUAWEILYA-L29/338C432)",
"operatingSystemFamily": 0,
"processorCount": 8,
"processorFrequency": 2600,
"processorType": "ARMv7 VFPv3 NEON",
"supportsAccelerometer": true,
"supportsAudio": true,
"supportsGyroscope": true,
"supportsLocationService": true,
"supportsVibration": true,
"systemMemorySize": 5597,
"unsupportedIdentifier": "",
"GraphicsDependentData": [
{
"graphicsDeviceType": 21,
"graphicsMemorySize": 5530,
"graphicsDeviceName": "Mali-G76",
"graphicsDeviceVendor": "ARM",
"graphicsDeviceID": 1913716736,
"graphicsDeviceVendorID": 5045,
"graphicsUVStartsAtTop": true,
"graphicsDeviceVersion": "Vulkan 1.1.82 [0x04000000]",
"graphicsShaderLevel": 50,
"graphicsMultiThreaded": true,
"hasHiddenSurfaceRemovalOnGPU": false,
"hasDynamicUniformArrayIndexingInFragmentShaders": true,
"supportsShadows": true,
"supportsRawShadowDepthSampling": true,
"supportsMotionVectors": true,
"supports3DTextures": true,
"supports2DArrayTextures": true,
"supports3DRenderTextures": true,
"supportsCubemapArrayTextures": true,
"copyTextureSupport": 31,
"supportsComputeShaders": true,
"supportsGeometryShaders": false,
"supportsTessellationShaders": false,
"supportsInstancing": true,
"supportsHardwareQuadTopology": false,
"supports32bitsIndexBuffer": true,
"supportsSparseTextures": false,
"supportedRenderTargetCount": 8,
"supportsSeparatedRenderTargetsBlend": true,
"supportedRandomWriteTargetCount": 0,
"supportsMultisampledTextures": 1,
"supportsMultisampleAutoResolve": true,
"supportsTextureWrapMirrorOnce": 0,
"usesReversedZBuffer": true,
"npotSupport": 2,
"maxTextureSize": 8192,
"maxCubemapSize": 8192,
"maxComputeBufferInputsVertex": 0,
"maxComputeBufferInputsFragment": 0,
"maxComputeBufferInputsGeometry": 0,
"maxComputeBufferInputsDomain": 0,
"maxComputeBufferInputsHull": 0,
"maxComputeBufferInputsCompute": 0,
"maxComputeWorkGroupSize": 0,
"maxComputeWorkGroupSizeX": 0,
"maxComputeWorkGroupSizeY": 0,
"maxComputeWorkGroupSizeZ": 0,
"supportsAsyncCompute": false,
"supportsGraphicsFence": true,
"supportsAsyncGPUReadback": true,
"supportsRayTracing": false,
"supportsSetConstantBuffer": true,
"minConstantBufferOffsetAlignment": true,
"hasMipMaxLevel": true,
"supportsMipStreaming": true,
"usesLoadStoreActions": false
}
]
}
}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 6356145d8034d1d4c8e5ad5a7b8a745d
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

@@ -0,0 +1,112 @@
fileFormatVersion: 2
guid: 1aa5677cacc3d014bbeb51b0531f8192
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 10
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 0
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,170 @@
{
"Meta": {
"friendlyName": "OnePlus/ 6T",
"overlay": "OnePlus6T_Overlay.png"
},
"Screens": [
{
"width": 1080,
"height": 2340,
"navigationBarHeight": 0,
"dpi": 420.0,
"orientationKeys": [
1,
2,
3,
4
],
"orientationValues": [
{
"safeArea": {
"serializedVersion": "2",
"x": 0.0,
"y": 0.0,
"width": 1080.0,
"height": 2261.0
},
"cutouts": [
{
"serializedVersion": "2",
"x": 372.0,
"y": 2261.0,
"width": 334.0,
"height": 79.0
}
]
},
{
"safeArea": {
"serializedVersion": "2",
"x": 0.0,
"y": 79.0,
"width": 1080.0,
"height": 2261.0
},
"cutouts": [
{
"serializedVersion": "2",
"x": 374.0,
"y": 0.0,
"width": 334.0,
"height": 79.0
}
]
},
{
"safeArea": {
"serializedVersion": "2",
"x": 79.0,
"y": 0.0,
"width": 2261.0,
"height": 1080.0
},
"cutouts": [
{
"serializedVersion": "2",
"x": 0.0,
"y": 372.0,
"width": 79.0,
"height": 334.0
}
]
},
{
"safeArea": {
"serializedVersion": "2",
"x": 0.0,
"y": 0.0,
"width": 2261.0,
"height": 1080.0
},
"cutouts": [
{
"serializedVersion": "2",
"x": 2261.0,
"y": 374.0,
"width": 79.0,
"height": 334.0
}
]
}
]
}
],
"SystemInfo": {
"deviceModel": "OnePlus ONEPLUS A6013",
"deviceType": 1,
"operatingSystem": "Android OS 9 / API-28 (PKQ1.180716.001/1909112330)",
"operatingSystemFamily": 0,
"processorCount": 8,
"processorFrequency": 2803,
"processorType": "ARMv7 VFPv3 NEON",
"supportsAccelerometer": true,
"supportsAudio": true,
"supportsGyroscope": true,
"supportsLocationService": true,
"supportsVibration": true,
"systemMemorySize": 7637,
"unsupportedIdentifier": "",
"GraphicsDependentData": [
{
"graphicsDeviceType": 21,
"graphicsMemorySize": 3796,
"graphicsDeviceName": "Adreno (TM) 630",
"graphicsDeviceVendor": "Qualcomm",
"graphicsDeviceID": 100859905,
"graphicsDeviceVendorID": 20803,
"graphicsUVStartsAtTop": true,
"graphicsDeviceVersion": "Vulkan 1.1.66 [512.324.0]",
"graphicsShaderLevel": 45,
"graphicsMultiThreaded": true,
"hasHiddenSurfaceRemovalOnGPU": true,
"hasDynamicUniformArrayIndexingInFragmentShaders": true,
"supportsShadows": true,
"supportsRawShadowDepthSampling": true,
"supportsMotionVectors": true,
"supports3DTextures": true,
"supports2DArrayTextures": true,
"supports3DRenderTextures": true,
"supportsCubemapArrayTextures": true,
"copyTextureSupport": 31,
"supportsComputeShaders": true,
"supportsGeometryShaders": false,
"supportsTessellationShaders": false,
"supportsInstancing": true,
"supportsHardwareQuadTopology": false,
"supports32bitsIndexBuffer": true,
"supportsSparseTextures": false,
"supportedRenderTargetCount": 8,
"supportsSeparatedRenderTargetsBlend": true,
"supportedRandomWriteTargetCount": 0,
"supportsMultisampledTextures": 1,
"supportsMultisampleAutoResolve": true,
"supportsTextureWrapMirrorOnce": 1,
"usesReversedZBuffer": true,
"npotSupport": 2,
"maxTextureSize": 16384,
"maxCubemapSize": 16384,
"maxComputeBufferInputsVertex": 0,
"maxComputeBufferInputsFragment": 0,
"maxComputeBufferInputsGeometry": 0,
"maxComputeBufferInputsDomain": 0,
"maxComputeBufferInputsHull": 0,
"maxComputeBufferInputsCompute": 0,
"maxComputeWorkGroupSize": 0,
"maxComputeWorkGroupSizeX": 0,
"maxComputeWorkGroupSizeY": 0,
"maxComputeWorkGroupSizeZ": 0,
"supportsAsyncCompute": false,
"supportsGraphicsFence": true,
"supportsAsyncGPUReadback": true,
"supportsRayTracing": false,
"supportsSetConstantBuffer": true,
"minConstantBufferOffsetAlignment": true,
"hasMipMaxLevel": true,
"supportsMipStreaming": true,
"usesLoadStoreActions": false
}
]
}
}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: e85d0962651aa4b46a89e6c5e4b67091
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

@@ -0,0 +1,112 @@
fileFormatVersion: 2
guid: e80b151305ab37a48b09f8691505ee2d
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 10
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 0
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,54 @@
{
"Meta": {
"friendlyName": "Samsung/ Galaxy Note 10+",
"overlay": "SamsungGalaxyNote10Plus_Overlay.png"
},
"Screens": [
{
"width": 1080,
"height": 2280,
"orientationKeys": [
1,
3
],
"orientationValues": [
{
"safeArea": {
"serializedVersion": "2",
"x": 0.0,
"y": 0.0,
"width": 1080.0,
"height": 2195.0
},
"cutouts": [
{
"serializedVersion": "2",
"x": 479.0,
"y": 2195.0,
"width": 122.0,
"height": 85.0
}
]
},
{
"safeArea": {
"serializedVersion": "2",
"x": 85.0,
"y": 0.0,
"width": 2195.0,
"height": 1080.0
},
"cutouts": [
{
"serializedVersion": "2",
"x": 0.0,
"y": 479.0,
"width": 85.0,
"height": 122.0
}
]
}
]
}
]
}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 434e756bb46dfde4e86d62a9efa9bdaa
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,298 @@
{
"Meta": {
"friendlyName": "Samsung/ Galaxy S10+",
"overlay": "SamsungGalaxyS10Plus_Overlay.png",
"overlayOffset": {
"x": 30.0,
"y": 60.0,
"z": 30.0,
"w": 100.0
},
"overlayImage": {
"instanceID": 0
}
},
"Screens": [
{
"width": 1440,
"height": 3040,
"navigationBarHeight": 172,
"dpi": 560.0,
"orientationKeys": [
1,
2,
3,
4
],
"orientationValues": [
{
"safeArea": {
"serializedVersion": "2",
"x": 0.0,
"y": 0.0,
"width": 1440.0,
"height": 2898.0
},
"cutouts": [
{
"serializedVersion": "2",
"x": 1114.0,
"y": 2898.0,
"width": 326.0,
"height": 142.0
}
]
},
{
"safeArea": {
"serializedVersion": "2",
"x": 0.0,
"y": 142.0,
"width": 1440.0,
"height": 2898.0
},
"cutouts": [
{
"serializedVersion": "2",
"x": 1.0,
"y": 0.0,
"width": 325.0,
"height": 142.0
}
]
},
{
"safeArea": {
"serializedVersion": "2",
"x": 142.0,
"y": 0.0,
"width": 2898.0,
"height": 1440.0
},
"cutouts": [
{
"serializedVersion": "2",
"x": 0.0,
"y": 1114.0,
"width": 142.0,
"height": 326.0
}
]
},
{
"safeArea": {
"serializedVersion": "2",
"x": 0.0,
"y": 0.0,
"width": 2898.0,
"height": 1440.0
},
"cutouts": [
{
"serializedVersion": "2",
"x": 2898.0,
"y": 0.0,
"width": 142.0,
"height": 326.0
}
]
}
]
}
],
"SystemInfo": {
"deviceModel": "samsung SM-G975F",
"deviceType": 1,
"operatingSystem": "Android OS 9 / API-28 (PPR1.180610.011/G975FXXS3ASH1)",
"operatingSystemFamily": 0,
"processorCount": 8,
"processorFrequency": 2730,
"processorType": "ARM64 FP ASIMD AES",
"supportsAccelerometer": true,
"supportsAudio": true,
"supportsGyroscope": true,
"supportsLocationService": true,
"supportsVibration": true,
"systemMemorySize": 7408,
"unsupportedIdentifier": "n/a",
"GraphicsDependentData": [
{
"graphicsDeviceType": 21,
"graphicsMemorySize": 7398,
"graphicsDeviceName": "Mali-G76",
"graphicsDeviceVendor": "ARM",
"graphicsDeviceID": 1913716736,
"graphicsDeviceVendorID": 5045,
"graphicsUVStartsAtTop": true,
"graphicsDeviceVersion": "Vulkan 1.0.97 [0x04000000]",
"graphicsShaderLevel": 50,
"graphicsMultiThreaded": true,
"renderingThreadingMode": 0,
"hasHiddenSurfaceRemovalOnGPU": false,
"hasDynamicUniformArrayIndexingInFragmentShaders": true,
"supportsShadows": true,
"supportsRawShadowDepthSampling": true,
"supportsMotionVectors": true,
"supports3DTextures": true,
"supports2DArrayTextures": true,
"supports3DRenderTextures": true,
"supportsCubemapArrayTextures": true,
"copyTextureSupport": 31,
"supportsComputeShaders": true,
"supportsGeometryShaders": true,
"supportsTessellationShaders": true,
"supportsInstancing": true,
"supportsHardwareQuadTopology": false,
"supports32bitsIndexBuffer": true,
"supportsSparseTextures": false,
"supportedRenderTargetCount": 8,
"supportsSeparatedRenderTargetsBlend": true,
"supportedRandomWriteTargetCount": 8,
"supportsMultisampledTextures": 1,
"supportsMultisampleAutoResolve": true,
"supportsTextureWrapMirrorOnce": 0,
"usesReversedZBuffer": true,
"npotSupport": 2,
"maxTextureSize": 8192,
"maxCubemapSize": 8192,
"maxComputeBufferInputsVertex": 35,
"maxComputeBufferInputsFragment": 35,
"maxComputeBufferInputsGeometry": 35,
"maxComputeBufferInputsDomain": 35,
"maxComputeBufferInputsHull": 35,
"maxComputeBufferInputsCompute": 32,
"maxComputeWorkGroupSize": 384,
"maxComputeWorkGroupSizeX": 384,
"maxComputeWorkGroupSizeY": 384,
"maxComputeWorkGroupSizeZ": 384,
"supportsAsyncCompute": false,
"supportsGraphicsFence": true,
"supportsAsyncGPUReadback": true,
"supportsRayTracing": false,
"supportsSetConstantBuffer": true,
"minConstantBufferOffsetAlignment": true,
"hasMipMaxLevel": true,
"supportsMipStreaming": true,
"usesLoadStoreActions": true
},
{
"graphicsDeviceType": 11,
"graphicsMemorySize": 2048,
"graphicsDeviceName": "Mali-G76",
"graphicsDeviceVendor": "ARM",
"graphicsDeviceID": 0,
"graphicsDeviceVendorID": 0,
"graphicsUVStartsAtTop": false,
"graphicsDeviceVersion": "OpenGL ES 3.2 v1.r16p0-01rel0.###other-sha0123456789ABCDEF0###",
"graphicsShaderLevel": 50,
"graphicsMultiThreaded": true,
"renderingThreadingMode": 0,
"hasHiddenSurfaceRemovalOnGPU": false,
"hasDynamicUniformArrayIndexingInFragmentShaders": true,
"supportsShadows": true,
"supportsRawShadowDepthSampling": true,
"supportsMotionVectors": true,
"supports3DTextures": true,
"supports2DArrayTextures": true,
"supports3DRenderTextures": true,
"supportsCubemapArrayTextures": true,
"copyTextureSupport": 31,
"supportsComputeShaders": true,
"supportsGeometryShaders": true,
"supportsTessellationShaders": true,
"supportsInstancing": true,
"supportsHardwareQuadTopology": false,
"supports32bitsIndexBuffer": true,
"supportsSparseTextures": false,
"supportedRenderTargetCount": 4,
"supportsSeparatedRenderTargetsBlend": true,
"supportedRandomWriteTargetCount": 8,
"supportsMultisampledTextures": 1,
"supportsMultisampleAutoResolve": true,
"supportsTextureWrapMirrorOnce": 0,
"usesReversedZBuffer": false,
"npotSupport": 2,
"maxTextureSize": 8192,
"maxCubemapSize": 4096,
"maxComputeBufferInputsVertex": 0,
"maxComputeBufferInputsFragment": 24,
"maxComputeBufferInputsGeometry": 0,
"maxComputeBufferInputsDomain": 0,
"maxComputeBufferInputsHull": 0,
"maxComputeBufferInputsCompute": 24,
"maxComputeWorkGroupSize": 128,
"maxComputeWorkGroupSizeX": 128,
"maxComputeWorkGroupSizeY": 128,
"maxComputeWorkGroupSizeZ": 128,
"supportsAsyncCompute": false,
"supportsGraphicsFence": true,
"supportsAsyncGPUReadback": false,
"supportsRayTracing": false,
"supportsSetConstantBuffer": true,
"minConstantBufferOffsetAlignment": true,
"hasMipMaxLevel": true,
"supportsMipStreaming": true,
"usesLoadStoreActions": true
},
{
"graphicsDeviceType": 8,
"graphicsMemorySize": 2048,
"graphicsDeviceName": "Mali-G76",
"graphicsDeviceVendor": "ARM",
"graphicsDeviceID": 0,
"graphicsDeviceVendorID": 0,
"graphicsUVStartsAtTop": false,
"graphicsDeviceVersion": "OpenGL ES 3.2 v1.r16p0-01rel0.###other-sha0123456789ABCDEF0###",
"graphicsShaderLevel": 46,
"graphicsMultiThreaded": true,
"renderingThreadingMode": 0,
"hasHiddenSurfaceRemovalOnGPU": false,
"hasDynamicUniformArrayIndexingInFragmentShaders": true,
"supportsShadows": true,
"supportsRawShadowDepthSampling": true,
"supportsMotionVectors": true,
"supports3DTextures": true,
"supports2DArrayTextures": false,
"supports3DRenderTextures": false,
"supportsCubemapArrayTextures": false,
"copyTextureSupport": 31,
"supportsComputeShaders": false,
"supportsGeometryShaders": true,
"supportsTessellationShaders": true,
"supportsInstancing": false,
"supportsHardwareQuadTopology": false,
"supports32bitsIndexBuffer": true,
"supportsSparseTextures": false,
"supportedRenderTargetCount": 1,
"supportsSeparatedRenderTargetsBlend": false,
"supportedRandomWriteTargetCount": 0,
"supportsMultisampledTextures": 0,
"supportsMultisampleAutoResolve": true,
"supportsTextureWrapMirrorOnce": 0,
"usesReversedZBuffer": false,
"npotSupport": 2,
"maxTextureSize": 8192,
"maxCubemapSize": 4096,
"maxComputeBufferInputsVertex": 0,
"maxComputeBufferInputsFragment": 0,
"maxComputeBufferInputsGeometry": 0,
"maxComputeBufferInputsDomain": 0,
"maxComputeBufferInputsHull": 0,
"maxComputeBufferInputsCompute": 0,
"maxComputeWorkGroupSize": 0,
"maxComputeWorkGroupSizeX": 0,
"maxComputeWorkGroupSizeY": 0,
"maxComputeWorkGroupSizeZ": 0,
"supportsAsyncCompute": false,
"supportsGraphicsFence": true,
"supportsAsyncGPUReadback": false,
"supportsRayTracing": false,
"supportsSetConstantBuffer": false,
"minConstantBufferOffsetAlignment": false,
"hasMipMaxLevel": false,
"supportsMipStreaming": true,
"usesLoadStoreActions": true
}
]
}
}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: a38324582a7abce4596b501e4d5e2982
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,54 @@
{
"Meta": {
"friendlyName": "Samsung/ Galaxy S10",
"overlay": "SamsungGalaxyS10_Overlay.png"
},
"Screens": [
{
"width": 1080,
"height": 2280,
"orientationKeys": [
1,
3
],
"orientationValues": [
{
"safeArea": {
"serializedVersion": "2",
"x": 0.0,
"y": 0.0,
"width": 1080.0,
"height": 2168.0
},
"cutouts": [
{
"serializedVersion": "2",
"x": 928.0,
"y": 2168.0,
"width": 152.0,
"height": 112.0
}
]
},
{
"safeArea": {
"serializedVersion": "2",
"x": 112.0,
"y": 0.0,
"width": 2168.0,
"height": 1080.0
},
"cutouts": [
{
"serializedVersion": "2",
"x": 0.0,
"y": 928.0,
"width": 112.0,
"height": 152.0
}
]
}
]
}
]
}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 744afe68bd0bc0348b1f8f9fa02f10fe
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

@@ -0,0 +1,112 @@
fileFormatVersion: 2
guid: 68480b27794c6a246a38b415bae85ecd
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 10
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 0
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

@@ -0,0 +1,112 @@
fileFormatVersion: 2
guid: aa818ba913f6b1243aeae8cf02ee688a
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 10
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 0
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

@@ -0,0 +1,112 @@
fileFormatVersion: 2
guid: c1914b42a1a19f849b4c14f9991815ba
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 10
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 0
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: cd981829e31c35d4bbe895a05254cdb0
guid: 9e81cfc52d9f9494b8206cb0908beb45
folderAsset: yes
DefaultImporter:
externalObjects: {}
@@ -0,0 +1,161 @@
using System.IO;
using UnityEditor;
using UnityEditor.Animations;
using UnityEngine;
namespace E7.NotchSolution.Editor
{
internal class AdaptationBaseDrawer : UnityEditor.Editor
{
private void DrawGenButton(AdaptationBase ab, bool forPortrait)
{
var animator = ab.GetComponent<Animator>();
if (ab.TryGetLinkedControllerAsset(forPortrait, out var controllerAsset))
{
var controllerNull = animator.runtimeAnimatorController == null ||
animator.runtimeAnimatorController != controllerAsset;
var miniMod = new GUIStyle(EditorStyles.miniButton);
GUI.backgroundColor = !controllerNull ? Color.red : Color.white;
var toggleText = !controllerNull ? "Editing Adaptation..." : "Edit Adaptation";
var newToggle = GUILayout.Toggle(
!controllerNull,
new GUIContent(toggleText, "Toggle on to assign an animator controller asset temporarily, " +
"so you could edit its clips in the Animation panel."),
EditorStyles.miniButton
);
GUI.backgroundColor = Color.white;
if (newToggle == controllerNull)
{
animator.runtimeAnimatorController = controllerNull ? controllerAsset : null;
EditorApplication.RepaintAnimationWindow();
}
}
else
{
if (ab.IsAdaptable(forPortrait) == false)
{
if (GUILayout.Button("Generate Adaptation Assets", EditorStyles.miniButton))
{
CreateAnimator(forPortrait);
}
}
}
}
private void CreateAnimator(bool forPortrait)
{
var adaptation = (AdaptationBase) target;
var animator = adaptation.gameObject.GetComponent<Animator>();
var incompletePath = GetSaveControllerPath(adaptation.gameObject);
if (string.IsNullOrEmpty(incompletePath))
{
return;
}
var prefix = Path.GetFileNameWithoutExtension(incompletePath);
var path =
$"{Path.GetDirectoryName(incompletePath)}{Path.DirectorySeparatorChar}{prefix}Adaptation.controller";
var controller = AnimatorController.CreateAnimatorControllerAtPath(path);
AssetDatabase.ImportAsset(path);
animator.runtimeAnimatorController = controller;
var normalStateClip = AnimatorController.AllocateAnimatorClip($"{prefix}NormalState");
var adaptedStateClip = AnimatorController.AllocateAnimatorClip($"{prefix}AdaptedState");
AssetDatabase.AddObjectToAsset(normalStateClip, controller);
AssetDatabase.AddObjectToAsset(adaptedStateClip, controller);
AssetDatabase.ImportAsset(path);
adaptation.AssignAdaptationClips(normalStateClip, adaptedStateClip, forPortrait);
var ly = controller.layers[0].stateMachine;
var emptyState = ly.AddState("Empty State");
ly.defaultState = emptyState;
var normalGraphState = controller.AddMotion(normalStateClip, 0);
var adaptedGraphState = controller.AddMotion(adaptedStateClip, 0);
string GetSaveControllerPath(GameObject go)
{
var defaultName = go.name;
var message =
$"Create a new adaptation assets for the game object '{defaultName}'\nThis name will be a prefix for all assets.";
return EditorUtility.SaveFilePanelInProject("New Animation Contoller", defaultName, "", message);
}
}
/// <summary>
/// Draw the part of fields in <see cref="AdaptationBase"/>.
/// </summary>
//public static void Draw(SerializedObject serializedObject)
public override void OnInspectorGUI()
{
var adaptation = (AdaptationBase) target;
var supportedProp = serializedObject.FindProperty("supportedOrientations");
var portraitProp = serializedObject.FindProperty("portraitOrDefaultAdaptation");
var landscapeProp = serializedObject.FindProperty("landscapeAdaptation");
var (landscapeCompatible, portraitCompatible) =
NotchSolutionUtilityEditor.GetOrientationCompatibility();
if (portraitCompatible && landscapeCompatible)
{
EditorGUILayout.PropertyField(supportedProp);
EditorGUILayout.Separator();
}
var dual = supportedProp.enumValueIndex == (int) SupportedOrientations.Dual;
if (dual)
{
EditorGUILayout.LabelField("Portrait Orientation", EditorStyles.boldLabel);
}
portraitProp.Next(true);
if (portraitCompatible && landscapeCompatible)
{
EditorGUI.indentLevel++;
}
DrawGenButton(adaptation, true);
for (var i = 0; i < 3; i++)
{
EditorGUILayout.PropertyField(portraitProp);
portraitProp.Next(false);
}
if (portraitCompatible && landscapeCompatible)
{
EditorGUI.indentLevel--;
}
if (dual)
{
EditorGUILayout.Separator();
EditorGUILayout.LabelField("Landscape Orientation", EditorStyles.boldLabel);
landscapeProp.Next(true);
EditorGUI.indentLevel++;
DrawGenButton(adaptation, false);
for (var i = 0; i < 3; i++)
{
EditorGUILayout.PropertyField(landscapeProp);
landscapeProp.Next(false);
}
EditorGUI.indentLevel--;
}
serializedObject.ApplyModifiedProperties();
}
}
}
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 10bd100e62c99514e88e3cd2307a03d1
guid: 427fe6f33a7994b20a5c6414d0aa6ef6
MonoImporter:
externalObjects: {}
serializedVersion: 2
@@ -0,0 +1,9 @@
using UnityEditor;
namespace E7.NotchSolution.Editor
{
[CustomEditor(typeof(AspectRatioAdaptation))]
internal class AspectRatioAdaptationDrawer : AdaptationBaseDrawer
{
}
}
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 34ab85155eb4dee4bb2020fd10405b6a
guid: 66cd14c982c394e4fbf05b299513820d
MonoImporter:
externalObjects: {}
serializedVersion: 2
@@ -0,0 +1,71 @@
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace E7.NotchSolution.Editor
{
internal class EnumButtonsDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
DrawEnumAsButtons(position, property);
}
public static void DrawEnumAsButtons(Rect position, SerializedProperty property)
{
var actualLabel = EditorGUI.BeginProperty(position, null, property);
var insideRect = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), actualLabel);
var contents = property.enumDisplayNames.Select(x => new GUIContent(x)).ToArray();
property.enumValueIndex = GUI.Toolbar(insideRect, property.enumValueIndex, contents,
EditorStyles.miniButton, GUI.ToolbarButtonSize.Fixed);
EditorGUI.EndProperty();
}
/*
public static VisualElement CreateToolbar(SerializedProperty property)
{
var contents = property.enumDisplayNames.Select(x => new GUIContent(x)).ToArray();
var toolbarRoot = new VisualElement();
toolbarRoot.AddToClassList("unity-base-field");
var toolbar = new Toolbar();
var label = new Label(property.displayName);
label.AddToClassList("unity-base-field__label");
toolbarRoot.Add(label);
toolbarRoot.Add(toolbar);
for (int i = 0; i < contents.Length; i++)
{
var keep = i;
var tb = new ToolbarToggle();
tb.value = property.enumValueIndex == keep;
tb.RegisterValueChangedCallback((evc) =>
{
property.enumValueIndex = keep;
property.serializedObject.ApplyModifiedProperties();
foreach (var t in toolbar.Query<ToolbarToggle>().ToList())
{
if (t != tb)
{
t.SetValueWithoutNotify(false);
}
else
{
t.SetValueWithoutNotify(true);
}
}
});
tb.text = contents[i].text;
toolbar.Add(tb);
}
return toolbarRoot;
}
*/
}
}
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 1560852d6d249eb41bd6df86187186f0
guid: f6dcc8bbfaadf4732a6d7b8bf2b47b98
MonoImporter:
externalObjects: {}
serializedVersion: 2
@@ -0,0 +1,42 @@
using UnityEditor;
using UnityEngine;
namespace E7.NotchSolution.Editor
{
[CustomEditor(typeof(SafeAdaptation))]
internal class SafeAdaptationDrawer : AdaptationBaseDrawer
{
public override void OnInspectorGUI()
{
var adaptToEdgeProp = serializedObject.FindProperty("adaptToEdge");
var evalModeProp = serializedObject.FindProperty("evaluationMode");
var rect = EditorGUILayout.GetControlRect(true);
EditorGUI.BeginProperty(rect, new GUIContent(adaptToEdgeProp.displayName), adaptToEdgeProp);
EnumButtonsDrawer.DrawEnumAsButtons(rect, adaptToEdgeProp);
EditorGUI.EndProperty();
EditorGUILayout.PropertyField(evalModeProp);
base.OnInspectorGUI();
//WIP evaluated value debugger
// var p = serializedObject.FindProperty("portraitOrDefaultAdaptation").FindPropertyRelative("adaptationCurve");
// var p2 = serializedObject.FindProperty("landscapeAdaptation").FindPropertyRelative("adaptationCurve");
// var latest = Selection.activeGameObject.GetComponent<SafeAreaAdaptation>().latestSimulatedSpaceTakenRelative;
// var minValue = p.animationCurveValue.keys[0].value;
// var maxValue = p.animationCurveValue.keys[p.animationCurveValue.length - 1].value;
// var r = EditorGUILayout.GetControlRect(hasLabel: true, EditorGUIUtility.singleLineHeight * 3);
// EditorGUIUtility.DrawCurveSwatch(r,AnimationCurve.EaseInOut(0, 0, 1, 2), p, Color.green, Color.gray);
// Handles.color = Color.red;
// Handles.DrawAAPolyLine(new Vector3(0,0,0), new Vector3(100,100,0));
// Handles.color = Color.yellow;
// Handles.ArrowHandleCap(0, new Vector3(50,50,0), Random.rotation, 3, EventType.DragPerform);
//serializedObject.ApplyModifiedProperties();
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d94319ecc23f948dc92b0515c0b3fd6e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,9 @@
using UnityEditor;
namespace E7.NotchSolution.Editor
{
[CustomPropertyDrawer(typeof(EdgeEvaluationMode))]
internal class SafeAreaEvaluationModeDrawer : EnumButtonsDrawer
{
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dcab3f8f0285444c8a9e150dddc3145a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,71 @@
using UnityEditor;
using UnityEngine;
namespace E7.NotchSolution.Editor
{
[CustomEditor(typeof(SafePadding))]
internal class SafePaddingDrawer : UnityEditor.Editor
{
public override void OnInspectorGUI()
{
var orientationType = serializedObject.FindProperty("orientationType");
var portrait = serializedObject.FindProperty("portraitOrDefaultPaddings");
var landscape = serializedObject.FindProperty("landscapePaddings");
var influence = serializedObject.FindProperty("influence");
var flipPadding = serializedObject.FindProperty("flipPadding");
var (landscapeCompatible, portraitCompatible) =
NotchSolutionUtilityEditor.GetOrientationCompatibility();
if (portraitCompatible && landscapeCompatible)
{
EditorGUILayout.PropertyField(orientationType);
EditorGUILayout.Separator();
}
var dual = orientationType.enumValueIndex == (int) SupportedOrientations.Dual;
if (dual)
{
EditorGUILayout.LabelField("Portrait Orientation", EditorStyles.boldLabel);
}
if (portraitCompatible && landscapeCompatible)
{
EditorGUI.indentLevel++;
}
for (var i = 0; i < 4; i++)
{
portrait.Next(true);
EditorGUILayout.PropertyField(portrait, new GUIContent(portrait.displayName));
}
if (portraitCompatible && landscapeCompatible)
{
EditorGUI.indentLevel--;
}
if (dual)
{
EditorGUILayout.Separator();
EditorGUILayout.LabelField("Landscape Orientation", EditorStyles.boldLabel);
EditorGUI.indentLevel++;
for (var i = 0; i < 4; i++)
{
landscape.Next(true);
EditorGUILayout.PropertyField(landscape);
}
EditorGUI.indentLevel--;
}
EditorGUILayout.Separator();
EditorGUILayout.PropertyField(influence);
EditorGUILayout.PropertyField(flipPadding);
serializedObject.ApplyModifiedProperties();
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d53eb9c34306b4ba2923138f521f940e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,9 @@
using UnityEditor;
namespace E7.NotchSolution.Editor
{
[CustomPropertyDrawer(typeof(SupportedOrientations))]
internal class SupportedOrientationsDrawer : EnumButtonsDrawer
{
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e1fbdac7a134945a99fa67cde69a0e6a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,17 @@
{
"name": "E7.NotchSolution.Editor",
"references": [
"GUID:06dd7692457a446f7a9de9613998f95d"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}
@@ -1,7 +1,5 @@
fileFormatVersion: 2
guid: b4d325adfafa9454b8d5f7d62eca2a8a
timeCreated: 1531969489
licenseType: Store
guid: 99e2f6ff9839f476ea1d7beb9ff1bb68
AssemblyDefinitionImporter:
externalObjects: {}
userData:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c7f23f0a4076f4a328ed7f483b116d9b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,105 @@
using System.IO;
using UnityEngine;
namespace E7.NotchSolution.Editor
{
/// <summary>
/// Helper base class to handle IO between any Unity-serializable class and the ProjectSettings folder.
/// Uses Unity <see cref="JsonUtility"/> with the class instance. A subclass of <see cref="ScriptableObject"/>
/// is not really needed but may increases compatibility with something like inspector editor code.
/// </summary>
/// <remarks>
/// I saw a public <c>UnityEditor.ScriptableSingleton</c> with almost identical purpose
/// except that <c>FilePathAttribute</c> required for it is <c>internal</c>. WHY??
/// </remarks>
internal abstract class GenericProjectSettings<T> where T : GenericProjectSettings<T>, new()
{
private static T cachedSettings;
private static T cachedDummy;
/// <summary>
/// Point this to a constant number. It allows you to deprecate the old serialized file and start over.
/// If file loaded has <see cref="SerializedVersion"/> lower than this, the loaded instance will be
/// a new instance instead.
/// </summary>
protected abstract int DataVersion { get; }
/// <summary>
/// Point this to a field that is serialized. When loading back this can be used to compare with
/// <see cref="DataVersion"/> if we should trust the serialized file or not.
/// </summary>
protected abstract int SerializedVersion { get; set; }
/// <summary>
/// Overridable file name to use for the settings file.
/// </summary>
protected virtual string FileName => typeof(T).Name;
private string settingsPath => "ProjectSettings/" + FileName + ".asset";
private static T dummy
{
get
{
if (cachedDummy == null)
{
cachedDummy = new T();
}
return cachedDummy;
}
}
/// <summary>
/// A singleton of the saved settings file. Can create a new one automatically or return
/// a cached instance in the case of repeated use.
/// </summary>
public static T Instance
{
get
{
if (cachedSettings != null && cachedSettings.SerializedVersion >= dummy.DataVersion)
{
return cachedSettings;
}
var settings = new T();
if (File.Exists(dummy.settingsPath))
{
var assetJson = File.ReadAllText(dummy.settingsPath);
JsonUtility.FromJsonOverwrite(assetJson, settings);
if (settings.SerializedVersion < dummy.DataVersion)
{
settings = new T();
}
}
cachedSettings = settings;
return settings;
}
}
/// <summary>
/// Return the settings to the initial state and save to disk.
/// </summary>
public void Reset()
{
cachedSettings = new T();
Save();
}
/// <summary>
/// Commit all changes of this instance to disk.
/// </summary>
public void Save()
{
if (cachedSettings != null)
{
SerializedVersion = dummy.DataVersion;
File.WriteAllText(settingsPath, JsonUtility.ToJson(cachedSettings, true));
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9e98f8d05471d455dba36a0a433251c2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,67 @@
using System.Collections.Generic;
using System.Diagnostics;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
namespace E7.NotchSolution.Editor
{
internal class NotchSolutionPreferences : SettingsProvider
{
public NotchSolutionPreferences(string path, SettingsScope scopes, IEnumerable<string> keywords = null) : base(
path, scopes, keywords)
{
}
public override void OnTitleBarGUI()
{
EditorGUI.LabelField(new Rect(100, 100, 100, 100), "Notch Solution");
}
public override void OnActivate(string searchContext, VisualElement root)
{
var padRect = new VisualElement();
var padding = 10;
padRect.style.paddingBottom = padding;
padRect.style.paddingLeft = padding;
padRect.style.paddingRight = padding;
padRect.style.paddingTop = padding - 5;
root.Add(padRect);
var title = new Label("Notch Solution");
title.style.fontSize = 15;
title.style.unityFontStyleAndWeight = FontStyle.Bold;
padRect.Add(title);
var repo = new Label("https://github.com/5argon/NotchSolution");
repo.style.paddingBottom = 15;
repo.style.unityFontStyleAndWeight = FontStyle.Bold;
repo.RegisterCallback((MouseDownEvent ev) => { Process.Start("https://github.com/5argon/NotchSolution"); });
padRect.Add(repo);
var devicesPath = new TextField("Device Directory");
devicesPath.SetEnabled(false);
devicesPath.value = NotchSimulatorUtility.DevicesFolder;
padRect.Add(devicesPath);
var colorField = new ColorField("Prefab mode overlay color");
colorField.value = Settings.Instance.PrefabModeOverlayColor;
colorField.RegisterValueChangedCallback(ev =>
{
var settings = Settings.Instance;
settings.PrefabModeOverlayColor = ev.newValue;
settings.Save();
NotchSimulator.UpdateAllMockups();
NotchSimulator.UpdateSimulatorTargets();
});
padRect.Add(colorField);
}
[SettingsProvider]
public static SettingsProvider Pref()
{
return new NotchSolutionPreferences("Preferences/Notch Solution", SettingsScope.User, new[] {"UI"});
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: eb6701755b54f4ca69c7935845dc162a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace E7.NotchSolution.Editor
{
/// <summary>
/// When switching platforms the list of aspect ratio index changes completely.
/// Therefore we need a new set for each platforms.
/// </summary>
[Serializable]
internal class PerPlatformConfigurations
{
[SerializeField]
private BuildTarget buildTarget;
/// <summary>
/// You can switch between multiple configurations for A-B testing while designing, for example.
/// </summary>
[SerializeField] private List<NotchSimulatorConfiguration> configurations;
public PerPlatformConfigurations(BuildTarget buildTarget)
{
this.buildTarget = buildTarget;
configurations = new List<NotchSimulatorConfiguration>
{
new NotchSimulatorConfiguration("Config A"),
new NotchSimulatorConfiguration("Config B"),
};
}
internal BuildTarget BuildTarget => buildTarget;
internal int ConfigurationCount => configurations.Count;
internal NotchSimulatorConfiguration this[int i] => configurations[i];
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 23d441da232134b34b095d8d34bda590
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,96 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace E7.NotchSolution.Editor
{
[Serializable]
internal class Settings : GenericProjectSettings<Settings>
{
private const string fileName = "NotchSolutionSettings";
[SerializeField] private int activeConfigurationIndex;
[SerializeField] private int version;
[SerializeField] private List<PerPlatformConfigurations> perPlatformConfigurations;
public Settings()
{
perPlatformConfigurations = new List<PerPlatformConfigurations>();
PrefabModeOverlayColor = new Color(0.297F, 0.405F, 0.481F, 1);
}
protected override int DataVersion => 1;
protected override int SerializedVersion
{
get => version;
set => version = value;
}
protected override string FileName => fileName;
[field: SerializeField] internal bool EnableSimulation { get; set; }
[field: SerializeField] internal Color PrefabModeOverlayColor { get; set; }
internal bool FlipOrientation => ActiveConfiguration.Orientation == PreviewOrientation.LandscapeRight ||
ActiveConfiguration.Orientation == PreviewOrientation.PortraitUpsideDown;
/// <summary>
/// Get a configuration depending on the current build target and configuration index.
/// </summary>
internal NotchSimulatorConfiguration ActiveConfiguration
{
get
{
EnsureValidConfigurationIndex();
return PlatformConfigurations[activeConfigurationIndex];
}
}
/// <summary>
/// Get a configuration depending on the current build target.
/// </summary>
private PerPlatformConfigurations PlatformConfigurations
{
get
{
var conf = perPlatformConfigurations.FirstOrDefault(x =>
x.BuildTarget == EditorUserBuildSettings.activeBuildTarget);
if (conf == default(PerPlatformConfigurations))
{
var newConfig = new PerPlatformConfigurations(EditorUserBuildSettings.activeBuildTarget);
perPlatformConfigurations.Add(newConfig);
Save();
return newConfig;
}
return conf;
}
}
/// <summary>
/// Cause <see cref="ActiveConfiguration"/> to go forward or wrap around to the first one when it can't.
/// </summary>
public NotchSimulatorConfiguration NextConfiguration()
{
EnsureValidConfigurationIndex();
var count = PlatformConfigurations.ConfigurationCount;
activeConfigurationIndex = (activeConfigurationIndex + 1) % count;
Save();
return ActiveConfiguration;
}
private void EnsureValidConfigurationIndex()
{
var count = PlatformConfigurations.ConfigurationCount;
if (activeConfigurationIndex >= count)
{
activeConfigurationIndex = 0;
Save();
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1501f303ae54146459a7b33781126d7d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 36206ffcd3fc845b2b2facef4f6700ec
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,295 @@
using System;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace E7.NotchSolution.Editor
{
public static class GameViewResolution
{
private const string TEMPORARY_RESOLUTION_LABEL = "Notch Simulator Device";
private const string PREVIOUS_RESOLUTION_PREF = "NotchSimPrevRes";
private static object m_customResolution;
private static int mockupRefreshTime;
private static object GameViewSizes =>
GetType("GameViewSizes").FetchProperty("instance").FetchProperty("currentGroup");
private static object FixedResolutionMode => Enum.Parse(GetType("GameViewSizeType"), "FixedResolution");
private static object AspectRatioMode => Enum.Parse(GetType("GameViewSizeType"), "AspectRatio");
private static object CustomResolution
{
get
{
if (m_customResolution != null)
{
if ((int) GameViewSizes.CallMethod("IndexOf", m_customResolution) < 0)
{
m_customResolution = null;
}
}
else
{
var totalSizeCount = (int) GameViewSizes.CallMethod("GetTotalCount");
var builtinSizeCount = (int) GameViewSizes.CallMethod("GetBuiltinCount");
for (var i = totalSizeCount - 1; i >= builtinSizeCount; i--)
{
var size = GameViewSizes.CallMethod("GetGameViewSize", i);
if ((string) size.FetchProperty("baseText") == TEMPORARY_RESOLUTION_LABEL)
{
m_customResolution = size;
break;
}
}
}
return m_customResolution;
}
set => m_customResolution = value;
}
private static int CustomResolutionIndex => m_customResolution == null
? -1
: (int) GameViewSizes.CallMethod("IndexOf", m_customResolution) +
(int) GameViewSizes.CallMethod("GetBuiltinCount");
public static void SetResolution(int width, int height, bool aspectRatioMode)
{
var gameView = GetGameView();
if (!gameView)
{
if (!NotchSolutionUtilityEditor.UnityDeviceSimulatorActive)
{
var sceneView = SceneView.lastActiveSceneView
? SceneView.lastActiveSceneView
: SceneView.currentDrawingSceneView;
if (sceneView)
{
sceneView.CallMethod("SetMainPlayModeViewSize", new Vector2(width, height));
RefreshMockups();
}
}
return;
}
var customResolution = CustomResolution;
if (customResolution != null)
{
var isModified = false;
if (customResolution.FetchProperty("sizeType").Equals(AspectRatioMode) != aspectRatioMode)
{
customResolution.ModifyProperty("sizeType",
aspectRatioMode ? AspectRatioMode : FixedResolutionMode);
isModified = true;
}
if ((int) customResolution.FetchProperty("width") != width)
{
customResolution.ModifyProperty("width", width);
isModified = true;
}
if ((int) customResolution.FetchProperty("height") != height)
{
customResolution.ModifyProperty("height", height);
isModified = true;
}
if (!isModified)
{
return;
}
if (CustomResolutionIndex == (int) gameView.FetchProperty("selectedSizeIndex"))
{
ZoomOutGameView();
RefreshMockups();
return;
}
}
else
{
CustomResolution = customResolution = GetType("GameViewSize")
.CreateInstance(aspectRatioMode ? AspectRatioMode : FixedResolutionMode, width, height,
TEMPORARY_RESOLUTION_LABEL);
GameViewSizes.CallMethod("AddCustomSize", customResolution);
}
PlayerPrefs.SetInt(PREVIOUS_RESOLUTION_PREF, (int) gameView.FetchProperty("selectedSizeIndex"));
gameView.CallMethod("SizeSelectionCallback", CustomResolutionIndex, null);
ZoomOutGameView();
RefreshMockups();
}
public static void ClearResolution()
{
if (CustomResolution != null)
{
var gameView = GetGameView();
var customResolutionActive =
gameView && CustomResolutionIndex == (int) gameView.FetchProperty("selectedSizeIndex");
GameViewSizes.CallMethod("RemoveCustomSize", CustomResolutionIndex);
CustomResolution = null;
if (customResolutionActive)
{
gameView.CallMethod("SizeSelectionCallback",
Mathf.Clamp(PlayerPrefs.GetInt(PREVIOUS_RESOLUTION_PREF), 0,
(int) GameViewSizes.CallMethod("GetTotalCount") - 1), null);
ZoomOutGameView();
RefreshMockups();
}
}
}
private static EditorWindow GetGameView()
{
var windows = Resources.FindObjectsOfTypeAll(GetType("GameView"));
return windows.Length > 0 ? (EditorWindow) windows[0] : null;
}
private static void ZoomOutGameView()
{
var gameView = GetGameView();
// Find the currently active tab on Game view's panel
var activeTab = gameView.FetchField("m_Parent")?.FetchProperty("actualView") as EditorWindow;
gameView.Focus();
gameView.CallMethod("UpdateZoomAreaAndParent");
gameView.CallMethod("SnapZoom", (float) gameView.FetchProperty("minScale"));
// Restore the active tab
if (activeTab && activeTab != gameView)
{
activeTab.Focus();
}
}
private static void RefreshMockups()
{
// Sometimes we need to respawn the mockups after a couple of frames in order to synchronize the mockups
// with the new game view resolution
if (!NotchSimulator.IsOpen)
{
mockupRefreshTime = 2;
EditorApplication.update -= RefreshMockupsInternal;
EditorApplication.update += RefreshMockupsInternal;
}
}
private static void RefreshMockupsInternal()
{
if (--mockupRefreshTime <= 0)
{
EditorApplication.update -= RefreshMockupsInternal;
NotchSimulator.RespawnMockup();
}
}
#region Reflection Functions
private static Type GetType(string type)
{
return typeof(EditorWindow).Assembly.GetType("UnityEditor." + type);
}
private static object FetchField(this Type type, string field)
{
return type.GetFieldRecursive(field, true).GetValue(null);
}
private static object FetchField(this object obj, string field)
{
return obj.GetType().GetFieldRecursive(field, false).GetValue(obj);
}
private static object FetchProperty(this Type type, string property)
{
return type.GetPropertyRecursive(property, true).GetValue(null, null);
}
private static object FetchProperty(this object obj, string property)
{
return obj.GetType().GetPropertyRecursive(property, false).GetValue(obj, null);
}
private static void ModifyProperty(this object obj, string property, object value)
{
obj.GetType().GetPropertyRecursive(property, false).SetValue(obj, value, null);
}
private static object CallMethod(this object obj, string method, params object[] parameters)
{
return obj.GetType().GetMethod(method, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Invoke(obj, parameters);
}
private static object CreateInstance(this Type type, params object[] parameters)
{
Type[] parameterTypes;
if (parameters == null)
{
parameterTypes = null;
}
else
{
parameterTypes = new Type[parameters.Length];
for (var i = 0; i < parameters.Length; i++)
{
parameterTypes[i] = parameters[i].GetType();
}
}
return type.GetConstructor(parameterTypes).Invoke(parameters);
}
private static FieldInfo GetFieldRecursive(this Type type, string field, bool isStatic)
{
var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly |
(isStatic ? BindingFlags.Static : BindingFlags.Instance);
do
{
var fieldInfo = type.GetField(field, flags);
if (fieldInfo != null)
{
return fieldInfo;
}
type = type.BaseType;
} while (type != null);
return null;
}
private static PropertyInfo GetPropertyRecursive(this Type type, string property, bool isStatic)
{
var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly |
(isStatic ? BindingFlags.Static : BindingFlags.Instance);
do
{
var propertyInfo = type.GetProperty(property, flags);
if (propertyInfo != null)
{
return propertyInfo;
}
type = type.BaseType;
} while (type != null);
return null;
}
#endregion
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f35e2ac1ee0087741937a773d3ca6667
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,186 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &3673283291737537849
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3673283291737537848}
- component: {fileID: 3673283291737537829}
- component: {fileID: 3673283291737537850}
- component: {fileID: 3673283291737537828}
m_Layer: 5
m_Name: NoSo-MockupCanvas
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3673283291737537848
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3673283291737537849}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 0, y: 0, z: 0}
m_Children:
- {fileID: 3673283292801682477}
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0, y: 0}
--- !u!223 &3673283291737537829
Canvas:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3673283291737537849}
m_Enabled: 1
serializedVersion: 3
m_RenderMode: 0
m_Camera: {fileID: 0}
m_PlaneDistance: 100
m_PixelPerfect: 0
m_ReceivesEvents: 1
m_OverrideSorting: 0
m_OverridePixelPerfect: 0
m_SortingBucketNormalizedSize: 0
m_AdditionalShaderChannelsFlag: 0
m_SortingLayerID: 0
m_SortingOrder: 32767
m_TargetDisplay: 0
--- !u!114 &3673283291737537850
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3673283291737537849}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 1980459831, guid: f70555f144d8491a825f0804e09c671c, type: 3}
m_Name:
m_EditorClassIdentifier:
m_UiScaleMode: 0
m_ReferencePixelsPerUnit: 100
m_ScaleFactor: 1
m_ReferenceResolution: {x: 1792, y: 828}
m_ScreenMatchMode: 0
m_MatchWidthOrHeight: 0
m_PhysicalUnit: 0
m_FallbackScreenDPI: 95.7
m_DefaultSpriteDPI: 319.6
m_DynamicPixelsPerUnit: 1
--- !u!114 &3673283291737537828
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3673283291737537849}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 83b8ec99fbf59473891f0f467ac098e7, type: 3}
m_Name:
m_EditorClassIdentifier:
mockupImage: {fileID: 5972286580999522443}
--- !u!1 &3673283292801682466
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3673283292801682477}
- component: {fileID: 3673283292801682479}
- component: {fileID: 5972286580999522443}
- component: {fileID: 7255171786964198428}
m_Layer: 5
m_Name: MockupImage
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3673283292801682477
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3673283292801682466}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 3673283291737537848}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &3673283292801682479
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3673283292801682466}
m_CullTransparentMesh: 0
--- !u!114 &5972286580999522443
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3673283292801682466}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0, g: 0, b: 0, a: 1}
m_RaycastTarget: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
m_Sprite: {fileID: 21300000, guid: aa818ba913f6b1243aeae8cf02ee688a, type: 3}
m_Type: 0
m_PreserveAspect: 1
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
--- !u!114 &7255171786964198428
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3673283292801682466}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: -1254083943, guid: f70555f144d8491a825f0804e09c671c, type: 3}
m_Name:
m_EditorClassIdentifier:
m_AspectMode: 4
m_AspectRatio: 1
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: e4218a6a58a6f447c81a3ce821d5016f
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,573 @@
//#define NOTCH_SOLUTION_DEBUG_TRANSITIONS
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using UnityEditor.Callbacks;
using UnityEditor.Experimental.SceneManagement;
using UnityEditor.SceneManagement;
using UnityEditor.ShortcutManagement;
using UnityEngine;
//For bugfix hack
//For bugfix hack
namespace E7.NotchSolution.Editor
{
/// <summary>
/// Notch Solution components can receive simulated device values in editor from this
/// instead of the usual <see cref="Screen"/> API. Also the mockup overlay is provided by
/// an invisible full screen canvas game object with <see cref="HideFlags.HideAndDontSave"/>.
/// </summary>
internal class NotchSimulator : EditorWindow, IHasCustomMenu, IPreprocessBuildWithReport //For bugfix hack
{
private const string prefix = "NoSo";
private const string mockupCanvasName = prefix + "-MockupCanvas";
private const HideFlags overlayCanvasFlag = HideFlags.HideAndDontSave;
private static NotchSimulator win;
private static Vector2 gameviewResolution;
private static MockupCanvas mockupCanvas;
private static MockupCanvas prefabMockupCanvas;
private static bool eventAdded;
private Vector2 scrollPos;
internal static bool IsOpen => win;
/// <summary>
/// This need to return both from normal scene and prefab environment scene.
/// </summary>
internal static IEnumerable<MockupCanvas> AllMockupCanvases
{
get
{
if (mockupCanvas == null)
{
mockupCanvas = GameObject.Find(mockupCanvasName)?.GetComponent<MockupCanvas>();
}
if (mockupCanvas != null)
{
yield return mockupCanvas;
}
if (prefabMockupCanvas == null)
{
var prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
if (prefabStage != null)
{
prefabMockupCanvas = prefabStage.stageHandle.FindComponentOfType<MockupCanvas>();
}
}
if (prefabMockupCanvas != null)
{
yield return prefabMockupCanvas;
}
}
}
[ExecuteInEditMode]
private void OnEnable()
{
SimulationDatabase.Refresh();
EditorApplication.update += RespawnMockup;
}
[ExecuteInEditMode] private void OnDisable()
{
EditorApplication.update -= RespawnMockup;
}
/// <summary>
/// It is currently active only when Notch Simulator tab is present.
/// </summary>
private void OnGUI()
{
win = this;
//Sometimes even with flag I can see it in hierarchy until I move a mouse over it??
EditorApplication.RepaintHierarchyWindow();
scrollPos = EditorGUILayout.BeginScrollView(scrollPos);
EditorGUI.BeginChangeCheck();
var settings = Settings.Instance;
var switchConfigShortcut = ShortcutManager.instance
.GetShortcutBinding(NotchSolutionShortcuts.switchConfigurationShortcut).ToString();
if (string.IsNullOrEmpty(switchConfigShortcut))
{
switchConfigShortcut = "None";
}
var simulateShortcut = ShortcutManager.instance
.GetShortcutBinding(NotchSolutionShortcuts.toggleSimulationShortcut).ToString();
if (string.IsNullOrEmpty(simulateShortcut))
{
simulateShortcut = "None";
}
settings.EnableSimulation =
EditorGUILayout.BeginToggleGroup($"Simulate ({simulateShortcut})", settings.EnableSimulation);
var previousIndex = settings.ActiveConfiguration.DeviceIndex;
var currentIndex = Mathf.Clamp(settings.ActiveConfiguration.DeviceIndex, 0,
SimulationDatabase.KeyList.Length - 1);
var selectedIndex = EditorGUILayout.Popup(currentIndex, SimulationDatabase.KeyList);
settings.ActiveConfiguration.Orientation =
(PreviewOrientation) EditorGUILayout.EnumPopup("Orientation", settings.ActiveConfiguration.Orientation);
settings.ActiveConfiguration.GameViewSize =
(GameViewSizePolicy) EditorGUILayout.EnumPopup("Game View Size",
settings.ActiveConfiguration.GameViewSize);
if (GUILayout.Button($"{settings.ActiveConfiguration.ConfigurationName} ({switchConfigShortcut})",
EditorStyles.helpBox))
{
NotchSolutionShortcuts.SwitchConfiguration();
}
EditorGUILayout.EndToggleGroup();
settings.ActiveConfiguration.DeviceIndex = selectedIndex;
var simulationDevice = SimulationDatabase.Get(SimulationDatabase.KeyList[selectedIndex]);
//Draw warning about wrong aspect ratio
if (settings.EnableSimulation && simulationDevice != null)
{
if (NotchSolutionUtilityEditor.UnityDeviceSimulatorActive)
{
EditorGUILayout.HelpBox(
"Device preview won't resize automatically because Unity Device Simulator window is open.",
MessageType.Warning);
}
var gameViewOrientation = NotchSimulatorUtility.GetGameViewOrientation();
var gameViewSize = NotchSimulatorUtility.GetMainGameViewSize();
if (gameViewOrientation == ScreenOrientation.Landscape)
{
var flip = gameViewSize.x;
gameViewSize.x = gameViewSize.y;
gameViewSize.y = flip;
}
var screen = simulationDevice.Screens.FirstOrDefault();
if (screen != null)
{
var simAspect = NotchSolutionUtilityEditor.ScreenRatio(new Vector2(screen.width, screen.height));
var gameViewAspect = NotchSolutionUtilityEditor.ScreenRatio(gameViewSize);
var aspectDiff = Math.Abs(simAspect.x / simAspect.y - gameViewAspect.x / gameViewAspect.y);
if (aspectDiff > 0.01f)
{
EditorGUILayout.HelpBox(
"The selected simulation device has an aspect ratio of " +
$"{simAspect.y}:{simAspect.x} ({screen.height}x{screen.width}) but your game view is currently " +
$"in aspect {gameViewAspect.y}:{gameViewAspect.x} ({gameViewSize.y}x{gameViewSize.x}). " +
"The overlay mockup won't be displayed correctly.",
MessageType.Warning);
}
}
}
var changed = EditorGUI.EndChangeCheck();
if (changed)
{
UpdateAllMockups();
settings.Save();
}
EditorGUILayout.EndScrollView();
UpdateSimulatorTargets();
}
//IHasCustomMenu
public void AddItemsToMenu(GenericMenu menu)
{
menu.AddItem(new GUIContent("Reset Settings"), false, ResetSettings);
menu.AddItem(new GUIContent("Refresh Device List"), false, SimulationDatabase.Refresh);
}
/// <summary>
/// Part of the IPreprocessBuildWithReport
/// </summary>
public int callbackOrder => 0;
/// <summary>
/// Bugfix hack
/// https://github.com/5argon/NotchSolution/issues/11
/// https://fogbugz.unity3d.com/default.asp?1157422_sfvtcfi1jmvc3702
/// https://fogbugz.unity3d.com/default.asp?1167068_4884utp26ji27ro0
/// </summary>
public void OnPreprocessBuild(BuildReport report)
{
//Unity has a bug that any scene change not ordered by you (building, or execute a test)
//could not destroy a DontSave game object (Hide or not doesn't matter) and instead logs some errors.
//This is a problem on building since any console error will fail the build.
//We will hack it to destroy it ourselve first before the scene could change.
//However this destroy we are doing is also subjected to the same error, and will fail the build as this
//preprocess build callback is called when you are already in a build. To counter this, we set a hide flag
//to None (risk of being baked in the scene? I think not as long as we didn't save it) to not cause the bug
//then quickly destroy it without errors.
//The error when you run a Test Runner is still there though, because Unity didn't provide a callback
//when entering test for me to hack my way into it. At least you can build the game while NoSo is running.
//I have submitted the bug since 2019.1 release, now 2019.2 is here but it is still not fixed.
if (mockupCanvas != null)
{
mockupCanvas.gameObject.hideFlags = HideFlags.None;
DestroyImmediate(mockupCanvas.gameObject);
mockupCanvas = null;
}
if (prefabMockupCanvas != null)
{
prefabMockupCanvas.gameObject.hideFlags = HideFlags.None;
DestroyImmediate(prefabMockupCanvas.gameObject);
prefabMockupCanvas = null;
}
}
[MenuItem("Window/General/Notch Simulator")]
public static void ShowWindow()
{
win = (NotchSimulator) GetWindow(typeof(NotchSimulator));
win.titleContent = new GUIContent("Notch Simulator");
}
private void ResetSettings()
{
Settings.Instance.Reset();
Debug.Log("Reset all Notch Solution settings.");
}
internal static void RespawnMockup()
{
//When the game view is changed, the mockup sometimes disappears or isn't scaled correctly
if (gameviewResolution != NotchSimulatorUtility.GetMainGameViewSize())
{
DestroyHiddenCanvas(); //So we delete the old canvas
UpdateAllMockups(); //And we respawn it
UpdateSimulatorTargets();
gameviewResolution = NotchSimulatorUtility.GetMainGameViewSize(); //Update the saved game view
}
}
internal static void Redraw()
{
win?.Repaint();
}
/// <summary>
/// Get all <see cref="INotchSimulatorTarget"/> and update them.
/// </summary>
internal static void UpdateSimulatorTargets()
{
var enableSimulation = Settings.Instance.EnableSimulation;
var selectedDevice = SimulationDatabase.ByIndex(Settings.Instance.ActiveConfiguration.DeviceIndex);
var simulatedRectRelative = enableSimulation && selectedDevice != null
? NotchSimulatorUtility.CalculateSimulatorSafeAreaRelative(selectedDevice)
: NotchSolutionUtility.defaultSafeArea;
var simulatedCutoutsRelative = enableSimulation && selectedDevice != null
? NotchSimulatorUtility.CalculateSimulatorCutoutsRelative(selectedDevice)
: NotchSolutionUtility.defaultCutouts;
var normalSceneSimTargets = FindObjectsOfType<MonoBehaviour>().OfType<INotchSimulatorTarget>();
foreach (var nst in normalSceneSimTargets)
{
nst.SimulatorUpdate(simulatedRectRelative, simulatedCutoutsRelative);
}
//Now find one in the prefab mode scene as well
var prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
if (prefabStage != null)
{
var prefabSceneSimTargets = prefabStage.stageHandle.FindComponentsOfType<MonoBehaviour>()
.OfType<INotchSimulatorTarget>();
foreach (var nst in prefabSceneSimTargets)
{
nst.SimulatorUpdate(simulatedRectRelative, simulatedCutoutsRelative);
}
}
}
/// <summary>
/// We lose all events on entering play mode, use this to register the event and also make a canvas again
/// after it was destroyed by the event (that now disappeared)
/// </summary>
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
private static void AddOverlayInPlayMode()
{
UpdateAllMockups();
}
/// <summary>
/// This is called even if Notch Simulator tab is not present on the screen.
/// Also have to handle if we reload scripts while in prefab mode.
/// </summary>
[DidReloadScripts]
private static void OnScriptsReloaded()
{
//DebugTransitions($"Script reloaded PLAY {EditorApplication.isPlaying} PLAY or WILL CHANGE {EditorApplication.isPlayingOrWillChangePlaymode}");
//Avoid script reload due to entering playmode
if (EditorApplication.isPlayingOrWillChangePlaymode == false)
{
UpdateAllMockups();
}
}
private static void DestroyHiddenCanvas()
{
foreach (var mockup in AllMockupCanvases)
{
if (EditorApplication.isPlaying)
{
Destroy(mockup.gameObject);
}
else
{
DestroyImmediate(mockup.gameObject, false);
}
}
}
internal static void UpdateAllMockups()
{
//When building, the scene may open-close multiple times and brought back the mockup canvas,
//which combined with bugs mentioned at https://github.com/5argon/NotchSolution/issues/11,
//will fail the build. This `if` prevents mockup refresh while building.
if (BuildPipeline.isBuildingPlayer)
{
return;
}
EnsureCanvasAndEventSetup();
//Make the editing environment contains an another copy of mockup canvas.
var prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
if (prefabStage != null)
{
EnsureCanvasAndEventSetup(prefabStage);
}
var settings = Settings.Instance;
var enableSimulation = settings.EnableSimulation;
var selectedDevice = SimulationDatabase.ByIndex(Settings.Instance.ActiveConfiguration.DeviceIndex);
var landscape = Settings.Instance.ActiveConfiguration.Orientation == PreviewOrientation.LandscapeLeft ||
Settings.Instance.ActiveConfiguration.Orientation == PreviewOrientation.LandscapeRight;
if (enableSimulation && selectedDevice != null)
{
var screen = selectedDevice.Screens.FirstOrDefault();
GameViewResolution.SetResolution(landscape ? screen.height : screen.width,
landscape ? screen.width : screen.height,
Settings.Instance.ActiveConfiguration.GameViewSize == GameViewSizePolicy.MatchAspectRatio);
var name = selectedDevice.Meta.overlay;
Sprite mockupSprite = null;
if (!string.IsNullOrEmpty(name))
{
var filePath = Path.Combine(NotchSimulatorUtility.DevicesFolder, name);
mockupSprite = AssetDatabase.LoadAssetAtPath<Sprite>(filePath);
if (mockupSprite == null)
{
if (File.Exists(filePath))
{
var tex = new Texture2D(1, 1);
tex.LoadImage(File.ReadAllBytes(filePath));
mockupSprite = Sprite.Create(tex, new Rect(0.0f, 0.0f, tex.width, tex.height),
new Vector2(0.5f, 0.5f), 100.0f);
}
else
{
Debug.LogWarning(
$"No mockup image named {name} in {NotchSimulatorUtility.DevicesFolder} folder!");
}
}
}
foreach (var mockup in AllMockupCanvases)
{
mockup.UpdateMockupSprite(
mockupSprite,
NotchSimulatorUtility.GetGameViewOrientation(),
enableSimulation,
settings.FlipOrientation,
Settings.Instance.PrefabModeOverlayColor
);
}
}
else
{
DestroyHiddenCanvas();
GameViewResolution.ClearResolution();
}
}
private static void DebugTransitions(string s)
{
#if NOTCH_SOLUTION_DEBUG_TRANSITIONS
Debug.Log(s);
#endif
}
/// <param name="prefabStage">
/// If not <c>null</c>, look for the mockup canvas on environment scene
/// for editing a prefab <b>instead</b> of normal scenes.
/// </param>
private static void EnsureCanvasAndEventSetup(PrefabStage prefabStage = null)
{
//Create the hidden canvas if not already.
var prefabMode = prefabStage != null;
var selectedMockupCanvas = prefabMode ? prefabMockupCanvas : mockupCanvas;
if (selectedMockupCanvas == null)
{
//Find existing in the case of assembly reload
//For some reason GameObject.FindObjectOfType could not get the canvas on main scene, it is active also, but by name works...
var canvasObject = prefabMode
? prefabStage.stageHandle.FindComponentOfType<MockupCanvas>()
: GameObject.Find(mockupCanvasName)?.GetComponent<MockupCanvas>();
if (canvasObject != null)
{
DebugTransitions($"[Notch Solution] Found existing (Prefab mode {prefabMode})");
}
else
{
var prefabGuids = AssetDatabase.FindAssets(mockupCanvasName);
if (prefabGuids.Length == 0)
{
return;
}
DebugTransitions($"[Notch Solution] Creating canvas (Prefab mode {prefabMode})");
var mockupCanvasPrefab =
AssetDatabase.LoadAssetAtPath<GameObject>(AssetDatabase.GUIDToAssetPath(prefabGuids.First()));
var instantiated =
prefabMode
? (GameObject) PrefabUtility.InstantiatePrefab(mockupCanvasPrefab, prefabStage.scene)
: (GameObject) PrefabUtility.InstantiatePrefab(mockupCanvasPrefab);
//It sometimes instantiated into null on script reloading when starting Unity?
if (instantiated != null)
{
canvasObject = instantiated.GetComponent<MockupCanvas>();
instantiated.hideFlags = overlayCanvasFlag;
if (Application.isPlaying)
{
DontDestroyOnLoad(canvasObject);
}
canvasObject.PrefabStage = prefabMode;
if (prefabMode)
{
prefabMockupCanvas = canvasObject;
}
else
{
mockupCanvas = canvasObject;
}
}
if (eventAdded == false)
{
eventAdded = true;
//Add clean up event.
EditorApplication.playModeStateChanged += PlayModeStateChangeAction;
// EditorSceneManager.sceneClosing += (a, b) =>
// {
// DebugTransitions($"Scene closing {a} {b}");
// };
// EditorSceneManager.sceneClosed += (a) =>
// {
// DebugTransitions($"Scene closed {a}");
// };
// EditorSceneManager.sceneLoaded += (a, b) =>
// {
// DebugTransitions($"Scene loaded {a} {b}");
// };
// EditorSceneManager.sceneUnloaded += (a) =>
// {
// DebugTransitions($"Scene unloaded {a}");
// };
PrefabStage.prefabStageOpened += ps =>
{
DebugTransitions(
$"Prefab opening {ps.scene.GetRootGameObjects().First().name} {ps.prefabContentsRoot.name}");
//On open prefab, the "dont save" objects on the main scene will disappear too.
//So that we could still see it in the game view WHILE editing a prefab, we make it back.
//Along with this the prefab mode canvas will also be updated.
UpdateAllMockups();
//On entering prefab mode, the Notch Simulator panel did not get OnGUI().
UpdateSimulatorTargets();
};
PrefabStage.prefabStageClosing += ps =>
{
DebugTransitions(
$"Prefab closing {ps.scene.GetRootGameObjects().First().name} {ps.prefabContentsRoot.name}");
//There is no problem on closing prefab stage, no need to restore the outer mockup.
};
EditorSceneManager.sceneOpening += (a, b) =>
{
DebugTransitions($"Scene opening {a} {b}");
DestroyHiddenCanvas();
};
EditorSceneManager.sceneOpened += (a, b) =>
{
DebugTransitions($"Scene opened {a} {b}");
UpdateAllMockups();
};
void PlayModeStateChangeAction(PlayModeStateChange state)
{
DebugTransitions(
$"Changed state PLAY {EditorApplication.isPlaying} PLAY or WILL CHANGE {EditorApplication.isPlayingOrWillChangePlaymode}");
switch (state)
{
case PlayModeStateChange.EnteredEditMode:
DebugTransitions($"Entered Edit {canvasObject}");
AddOverlayInPlayMode(); //For when coming back from play mode.
break;
case PlayModeStateChange.EnteredPlayMode:
DebugTransitions($"Entered Play {canvasObject}");
break;
case PlayModeStateChange.ExitingEditMode:
DebugTransitions($"Exiting Edit {canvasObject}");
DestroyHiddenCanvas(); //Clean up the DontSave canvas we made in edit mode.
break;
case PlayModeStateChange.ExitingPlayMode:
DebugTransitions($"Exiting Play {canvasObject}");
DestroyHiddenCanvas(); //Clean up the DontSave canvas we made in play mode.
break;
}
}
}
}
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 39883f5206c9a4b74bb72858f01fce79
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,50 @@
using System;
using UnityEngine;
namespace E7.NotchSolution.Editor
{
public enum PreviewOrientation
{
Portrait,
PortraitUpsideDown,
LandscapeLeft,
LandscapeRight,
}
public enum GameViewSizePolicy
{
MatchResolution,
MatchAspectRatio,
}
/// <summary>
/// Notch Solution can be in only 1 configuration at any point.
/// </summary>
[Serializable]
internal class NotchSimulatorConfiguration
{
[SerializeField] private string configurationName;
public NotchSimulatorConfiguration(string configurationName)
{
this.configurationName = configurationName;
}
internal string ConfigurationName => configurationName;
/// <summary>
/// The device selected when linearize the simulator database and count from the beginning.
/// </summary>
[field: SerializeField] internal int DeviceIndex { get; set; }
/// <summary>
/// Screen orientation of the preview device.
/// </summary>
[field: SerializeField] internal PreviewOrientation Orientation { get; set; }
/// <summary>
/// Whether the game view's size should match the device's exact resolution or only its aspect ratio.
/// </summary>
[field: SerializeField] internal GameViewSizePolicy GameViewSize { get; set; }
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 997fdbece1022428b9b65b7af3738474
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,141 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace E7.NotchSolution.Editor
{
internal static class NotchSimulatorUtility
{
internal static Rect CalculateSimulatorSafeAreaRelative(SimulationDevice device)
{
var firstScreen = device.Screens.FirstOrDefault();
// Should not happen, but just to be safe.
if (firstScreen == null)
{
return default;
}
var orientation = GetGameViewOrientation();
var safe = firstScreen.orientations[orientation].safeArea;
var screenSize = new Vector2(firstScreen.width, firstScreen.height);
if (orientation == ScreenOrientation.Landscape)
{
var swap = screenSize.x;
screenSize.x = screenSize.y;
screenSize.y = swap;
}
return GetRectRelativeToScreenSize(safe, screenSize);
}
internal static Rect[] CalculateSimulatorCutoutsRelative(SimulationDevice device)
{
var firstScreen = device.Screens.FirstOrDefault();
// Should not happen, but just to be safe.
if (firstScreen == null)
{
return default;
}
var orientation = GetGameViewOrientation();
var cutouts = firstScreen.orientations[orientation].cutouts;
if (cutouts is null)
{
return new Rect[0];
}
var screenSize = new Vector2(firstScreen.width, firstScreen.height);
if (orientation == ScreenOrientation.Landscape)
{
var swap = screenSize.x;
screenSize.x = screenSize.y;
screenSize.y = swap;
}
var rects = new List<Rect>();
foreach (var cutout in cutouts)
{
rects.Add(GetRectRelativeToScreenSize(cutout, screenSize));
}
return rects.ToArray();
}
/// <param name="original">Must be inside of a rect positioned at 0,0 that has width and height as <paramref name="screenSize"></param>
private static Rect GetRectRelativeToScreenSize(Rect original, Vector2 screenSize)
{
var relativeCutout = new Rect(original.xMin / screenSize.x, original.yMin / screenSize.y,
original.width / screenSize.x, original.height / screenSize.y);
//Debug.Log($"Calc relative {original} {screenSize} {relativeCutout}");
if (Settings.Instance.FlipOrientation)
{
return new Rect(
1 - (relativeCutout.width + relativeCutout.xMin),
1 - (relativeCutout.height + relativeCutout.yMin),
relativeCutout.width,
relativeCutout.height
);
}
return relativeCutout;
}
internal static ScreenOrientation GetGameViewOrientation()
{
var gameViewSize = GetMainGameViewSize();
return gameViewSize.x > gameViewSize.y ? ScreenOrientation.Landscape : ScreenOrientation.Portrait;
}
#if UNITY_2019_3_OR_NEWER
private static readonly Type T = Type.GetType("UnityEditor.PlayModeView,UnityEditor");
private static readonly MethodInfo GetSizeOfMainGameView =
T.GetMethod("GetMainPlayModeViewTargetSize", BindingFlags.NonPublic | BindingFlags.Static);
#else
static System.Type T = System.Type.GetType("UnityEditor.GameView,UnityEditor");
static System.Reflection.MethodInfo GetSizeOfMainGameView =
T.GetMethod("GetMainGameViewTargetSizeNoBox", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
#endif
private static object[] argsForOut = new object[1];
internal static Vector2 GetMainGameViewSize()
{
#if UNITY_2019_3_OR_NEWER
var result = (Vector2) GetSizeOfMainGameView.Invoke(null, null);
if (result == new Vector2(640f, 480f) && !NotchSolutionUtilityEditor.PlayModeViewOpen)
{
// Neither Game window nor Unity Device Simulator window is open (can happen if Scene view is maximized)
// In this case, the last open game window's size can be determined by looking at the mockup canvas' size
foreach (var mockupCanvas in NotchSimulator.AllMockupCanvases)
{
result = ((RectTransform) mockupCanvas.GetComponent<Canvas>().transform).sizeDelta;
break;
}
}
return result;
#else
System.Object Res = GetSizeOfMainGameView.Invoke(null, argsForOut);
return (Vector2)argsForOut[0];
#endif
}
internal static string devicesFolderCached;
internal static string DevicesFolder
{
get
{
if (string.IsNullOrEmpty(devicesFolderCached))
{
devicesFolderCached = AssetDatabase.GUIDToAssetPath("e6ee4d37d64882c4fac2dc0b3aad29cb");
}
return devicesFolderCached;
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cb519e4c9ebee4469a3f8f446ced9671
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,67 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine;
namespace E7.NotchSolution.Editor
{
/// <summary>
/// Please add more! [How to get device's safe area and cutouts](https://github.com/5argon/NotchSolution/issues/2).
/// </summary>
internal static class SimulationDatabase
{
private static Dictionary<string, SimulationDevice> db;
internal static string[] KeyList;
internal static void Refresh()
{
if (db == null)
{
db = new Dictionary<string, SimulationDevice>();
}
db.Clear();
var deviceDirectory = new DirectoryInfo(NotchSimulatorUtility.DevicesFolder);
if (!deviceDirectory.Exists)
{
return;
}
var deviceDefinitions = deviceDirectory.GetFiles("*.device.json");
foreach (var deviceDefinition in deviceDefinitions)
{
SimulationDevice deviceInfo;
using (var sr = deviceDefinition.OpenText())
{
deviceInfo = JsonUtility.FromJson<SimulationDevice>(sr.ReadToEnd());
}
db.Add(deviceInfo.Meta.friendlyName, deviceInfo);
}
KeyList = db.Keys.ToArray();
}
internal static SimulationDevice Get(string device)
{
if (db == null)
{
Refresh();
}
return db.TryGetValue(device, out var found) ? found : default;
}
internal static SimulationDevice ByIndex(int index)
{
if (KeyList == null)
{
Refresh();
}
return index < KeyList.Length ? db[KeyList[index]] : default;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 51bab01d600234d4ba7ec6da86190da2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e45a50b1409f546f9a91af0b90cf6d4c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,46 @@
using UnityEditor;
using UnityEditor.ShortcutManagement;
using UnityEngine;
namespace E7.NotchSolution.Editor
{
internal static class NotchSolutionShortcuts
{
private const string notchSolutionPrefPrefix = "Notch Solution/";
internal const string toggleSimulationShortcut = notchSolutionPrefPrefix + "Toggle Notch Simulator";
internal const string switchConfigurationShortcut = notchSolutionPrefPrefix + "Switch configuration";
/// <summary>
/// Switch between narrowest and widest aspect specified in the preferences to validate design.
/// Switch to the narrowest if currently on neither aspects.
/// </summary>
[Shortcut(switchConfigurationShortcut, null, KeyCode.M, ShortcutModifiers.Alt)]
internal static void SwitchConfiguration()
{
Settings.Instance.NextConfiguration();
NotchSimulator.Redraw();
NotchSimulator.UpdateAllMockups();
NotchSimulator.UpdateSimulatorTargets();
// Using shortcut to change aspect ratio actually will not proc the [ExecuteAlways] Update()
// of adaptation components, unlike using the drop down.
// But it mostly do so because we always have some uGUI components which indirectly cause
// those updates on ratio change. While the scene with no uGUI at all maybe rare,
// it never hurts to proc them manually.. just in case.
EditorApplication.QueuePlayerLoopUpdate();
}
[Shortcut(toggleSimulationShortcut, null, KeyCode.N, ShortcutModifiers.Alt)]
private static void ToggleSimulation()
{
var settings = Settings.Instance;
settings.EnableSimulation = !settings.EnableSimulation;
settings.Save();
NotchSimulator.UpdateAllMockups();
NotchSimulator.UpdateSimulatorTargets();
NotchSimulator.Redraw();
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c41ab3240cd4a40bd9befb3c6eff264b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Some files were not shown because too many files have changed in this diff Show More