Initial commit

This commit is contained in:
AbstractConcept 2022-09-13 00:36:34 -05:00
commit 3c7cc0c973
8391 changed files with 704313 additions and 0 deletions

View file

@ -0,0 +1,3 @@
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Unity.2D.PixelPerfect.Tests")]
[assembly: InternalsVisibleTo("Unity.2D.PixelPerfect.Editor")]

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7f8cac0e0dac99c4f94b966e2bbdb52c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,17 @@
namespace UnityEngine.U2D
{
/// <summary>
/// (Deprecated) An add-on module for Cinemachine Virtual Camera that tweaks the orthographic size
/// of the virtual camera. It detects the presence of the Pixel Perfect Camera component and use the
/// settings from that Pixel Perfect Camera to correct the orthographic size so that pixel art
/// sprites would appear pixel perfect when the virtual camera becomes live.
/// </summary>
[AddComponentMenu("")] // Hide in menu
public class CinemachinePixelPerfect : MonoBehaviour
{
void OnEnable()
{
Debug.LogError("CinemachinePixelPerfect is now deprecated and doesn't function properly. Instead, use the one from Cinemachine v2.4.0 or newer.");
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3e7d23639bb969a4281b83c40743b6f5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: -1
icon: {fileID: 2800000, guid: 8dafc8bde78edde44bf6e6aab96eb100, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,309 @@
namespace UnityEngine.U2D
{
/// <summary>
/// The Pixel Perfect Camera component ensures your pixel art remains crisp and clear at different resolutions, and stable in motion.
/// </summary>
[DisallowMultipleComponent]
[AddComponentMenu("Rendering/Pixel Perfect Camera")]
[RequireComponent(typeof(Camera))]
public class PixelPerfectCamera : MonoBehaviour, IPixelPerfectCamera
{
/// <summary>
/// Match this value to to the Pixels Per Unit values of all Sprites within the Scene.
/// </summary>
public int assetsPPU { get { return m_AssetsPPU; } set { m_AssetsPPU = value > 0 ? value : 1; } }
/// <summary>
/// The original horizontal resolution your Assets are designed for.
/// </summary>
public int refResolutionX { get { return m_RefResolutionX; } set { m_RefResolutionX = value > 0 ? value : 1; } }
/// <summary>
/// Original vertical resolution your Assets are designed for.
/// </summary>
public int refResolutionY { get { return m_RefResolutionY; } set { m_RefResolutionY = value > 0 ? value : 1; } }
/// <summary>
/// Set to true to have the Scene rendered to a temporary texture set as close as possible to the Reference Resolution,
/// while maintaining the full screen aspect ratio. This temporary texture is then upscaled to fit the full screen.
/// </summary>
public bool upscaleRT { get { return m_UpscaleRT; } set { m_UpscaleRT = value; } }
/// <summary>
/// Set to true to prevent subpixel movement and make Sprites appear to move in pixel-by-pixel increments.
/// Only applicable when upscaleRT is false.
/// </summary>
public bool pixelSnapping { get { return m_PixelSnapping; } set { m_PixelSnapping = value; } }
/// <summary>
/// Set to true to crop the viewport with black bars to match refResolutionX in the horizontal direction.
/// </summary>
public bool cropFrameX { get { return m_CropFrameX; } set { m_CropFrameX = value; } }
/// <summary>
/// Set to true to crop the viewport with black bars to match refResolutionY in the vertical direction.
/// </summary>
public bool cropFrameY { get { return m_CropFrameY; } set { m_CropFrameY = value; } }
/// <summary>
/// Set to true to expand the viewport to fit the screen resolution while maintaining the viewport's aspect ratio.
/// Only applicable when both cropFrameX and cropFrameY are true.
/// </summary>
public bool stretchFill { get { return m_StretchFill; } set { m_StretchFill = value; } }
/// <summary>
/// Ratio of the rendered Sprites compared to their original size (readonly).
/// </summary>
public int pixelRatio
{
get
{
if (m_CinemachineCompatibilityMode)
{
if (m_UpscaleRT)
return m_Internal.zoom * m_Internal.cinemachineVCamZoom;
else
return m_Internal.cinemachineVCamZoom;
}
else
{
return m_Internal.zoom;
}
}
}
/// <summary>
/// Round a arbitrary position to an integer pixel position. Works in world space.
/// </summary>
/// <param name="position"> The position you want to round.</param>
/// <returns>
/// The rounded pixel position.
/// Depending on the values of upscaleRT and pixelSnapping, it could be a screen pixel position or an art pixel position.
/// </returns>
public Vector3 RoundToPixel(Vector3 position)
{
float unitsPerPixel = m_Internal.unitsPerPixel;
if (unitsPerPixel == 0.0f)
return position;
Vector3 result;
result.x = Mathf.Round(position.x / unitsPerPixel) * unitsPerPixel;
result.y = Mathf.Round(position.y / unitsPerPixel) * unitsPerPixel;
result.z = Mathf.Round(position.z / unitsPerPixel) * unitsPerPixel;
return result;
}
/// <summary>
/// Find a pixel-perfect orthographic size as close to targetOrthoSize as possible. Used by Cinemachine to solve compatibility issues with Pixel Perfect Camera.
/// </summary>
/// <param name="targetOrthoSize">Orthographic size from the live Cinemachine Virtual Camera.</param>
/// <returns>The corrected orthographic size.</returns>
public float CorrectCinemachineOrthoSize(float targetOrthoSize)
{
m_CinemachineCompatibilityMode = true;
if (m_Internal == null)
return targetOrthoSize;
else
return m_Internal.CorrectCinemachineOrthoSize(targetOrthoSize);
}
[SerializeField]
int m_AssetsPPU = 100;
[SerializeField]
int m_RefResolutionX = 320;
[SerializeField]
int m_RefResolutionY = 180;
[SerializeField]
bool m_UpscaleRT = false;
[SerializeField]
bool m_PixelSnapping = false;
[SerializeField]
bool m_CropFrameX = false;
[SerializeField]
bool m_CropFrameY = false;
[SerializeField]
bool m_StretchFill = false;
Camera m_Camera;
PixelPerfectCameraInternal m_Internal;
bool m_CinemachineCompatibilityMode;
// Snap camera position to pixels using Camera.worldToCameraMatrix.
void PixelSnap()
{
Vector3 cameraPosition = m_Camera.transform.position;
Vector3 roundedCameraPosition = RoundToPixel(cameraPosition);
Vector3 offset = roundedCameraPosition - cameraPosition;
offset.z = -offset.z;
Matrix4x4 offsetMatrix = Matrix4x4.TRS(-offset, Quaternion.identity, new Vector3(1.0f, 1.0f, -1.0f));
m_Camera.worldToCameraMatrix = offsetMatrix * m_Camera.transform.worldToLocalMatrix;
}
void Awake()
{
m_Camera = GetComponent<Camera>();
m_Internal = new PixelPerfectCameraInternal(this);
m_Internal.originalOrthoSize = m_Camera.orthographicSize;
m_Internal.hasPostProcessLayer = GetComponent("PostProcessLayer") != null; // query the component by name to avoid hard dependency
if (m_Camera.targetTexture != null)
Debug.LogWarning("Render to texture is not supported by Pixel Perfect Camera.", m_Camera);
}
void LateUpdate()
{
#if UNITY_EDITOR
if (!UnityEditor.EditorApplication.isPaused)
#endif
{
// Reset the Cinemachine compatibility mode every frame.
// If any CinemachinePixelPerfect extension is present, they will turn this on
// at a later time (during CinemachineBrain's LateUpdate(), which is
// guaranteed to be after PixelPerfectCamera's LateUpdate()).
m_CinemachineCompatibilityMode = false;
}
m_Internal.CalculateCameraProperties(Screen.width, Screen.height);
// To be effective immediately this frame, forceIntoRenderTexture should be set before any camera rendering callback.
// An exception of this is when the editor is paused, where we call LateUpdate() manually in OnPreCall().
// In this special case, you'll see one frame of glitch when toggling renderUpscaling on and off.
m_Camera.forceIntoRenderTexture = m_Internal.hasPostProcessLayer || m_Internal.useOffscreenRT;
}
void OnPreCull()
{
#if UNITY_EDITOR
// LateUpdate() is not called while the editor is paused, but OnPreCull() is.
// So call LateUpdate() manually here.
if (UnityEditor.EditorApplication.isPaused)
LateUpdate();
#endif
PixelSnap();
if (m_Internal.pixelRect != Rect.zero)
m_Camera.pixelRect = m_Internal.pixelRect;
else
m_Camera.rect = new Rect(0.0f, 0.0f, 1.0f, 1.0f);
// In Cinemachine compatibility mode the control over orthographic size should
// be given to the virtual cameras, whose orthographic sizes will be corrected to
// be pixel-perfect. This way when there's blending between virtual cameras, we
// can have temporary not-pixel-perfect but smooth transitions.
if (!m_CinemachineCompatibilityMode)
{
m_Camera.orthographicSize = m_Internal.orthoSize;
}
}
void OnPreRender()
{
// Clear the screen to black so that we can see black bars.
// Need to do it before anything is drawn if we're rendering directly to the screen.
if (m_Internal.cropFrameXOrY && !m_Camera.forceIntoRenderTexture && !m_Camera.allowMSAA)
GL.Clear(false, true, Color.black);
PixelPerfectRendering.pixelSnapSpacing = m_Internal.unitsPerPixel;
}
void OnPostRender()
{
PixelPerfectRendering.pixelSnapSpacing = 0.0f;
// Clear the screen to black so that we can see black bars.
// If a temporary offscreen RT is used, we do the clear after we're done with that RT to avoid an unnecessary RT switch.
if (m_Camera.activeTexture != null)
{
Graphics.SetRenderTarget(null as RenderTexture);
GL.Viewport(new Rect(0.0f, 0.0f, Screen.width, Screen.height));
GL.Clear(false, true, Color.black);
}
if (!m_Internal.useOffscreenRT)
return;
RenderTexture activeRT = m_Camera.activeTexture;
if (activeRT != null)
activeRT.filterMode = m_Internal.useStretchFill ? FilterMode.Bilinear : FilterMode.Point;
m_Camera.pixelRect = m_Internal.CalculatePostRenderPixelRect(m_Camera.aspect, Screen.width, Screen.height);
}
#if UNITY_EDITOR
void OnEnable()
{
if (!UnityEditor.EditorApplication.isPlaying)
UnityEditor.EditorApplication.playModeStateChanged += OnPlayModeChanged;
}
#endif
internal void OnDisable()
{
m_Camera.rect = new Rect(0.0f, 0.0f, 1.0f, 1.0f);
m_Camera.orthographicSize = m_Internal.originalOrthoSize;
m_Camera.forceIntoRenderTexture = m_Internal.hasPostProcessLayer;
m_Camera.ResetAspect();
m_Camera.ResetWorldToCameraMatrix();
#if UNITY_EDITOR
if (!UnityEditor.EditorApplication.isPlaying)
UnityEditor.EditorApplication.playModeStateChanged -= OnPlayModeChanged;
#endif
}
#if DEVELOPMENT_BUILD || UNITY_EDITOR
// Show on-screen warning about invalid render resolutions.
void OnGUI()
{
#if UNITY_EDITOR
if (!UnityEditor.EditorApplication.isPlaying && !runInEditMode)
return;
#endif
Color oldColor = GUI.color;
GUI.color = Color.red;
Vector2Int renderResolution = Vector2Int.zero;
renderResolution.x = m_Internal.useOffscreenRT ? m_Internal.offscreenRTWidth : m_Camera.pixelWidth;
renderResolution.y = m_Internal.useOffscreenRT ? m_Internal.offscreenRTHeight : m_Camera.pixelHeight;
if (renderResolution.x % 2 != 0 || renderResolution.y % 2 != 0)
{
string warning = string.Format("Rendering at an odd-numbered resolution ({0} * {1}). Pixel Perfect Camera may not work properly in this situation.", renderResolution.x, renderResolution.y);
GUILayout.Box(warning);
}
if (Screen.width < refResolutionX || Screen.height < refResolutionY)
{
GUILayout.Box("Screen resolution is smaller than the reference resolution. Image may appear stretched or cropped.");
}
GUI.color = oldColor;
}
#endif
#if UNITY_EDITOR
void OnPlayModeChanged(UnityEditor.PlayModeStateChange state)
{
// Stop running in edit mode when entering play mode.
if (state == UnityEditor.PlayModeStateChange.ExitingEditMode)
{
runInEditMode = false;
OnDisable();
}
}
#endif
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6a160d838ff8b4b4693ac20007e008c7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 08a04b12dd0d5ec4da08f074806d5bf7, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,236 @@
using System;
namespace UnityEngine.U2D
{
internal interface IPixelPerfectCamera
{
int assetsPPU { get; set; }
int refResolutionX { get; set; }
int refResolutionY { get; set; }
bool upscaleRT { get; set; }
bool pixelSnapping { get; set; }
bool cropFrameX { get; set; }
bool cropFrameY { get; set; }
bool stretchFill { get; set; }
}
[Serializable]
internal class PixelPerfectCameraInternal : ISerializationCallbackReceiver
{
// Case 1061634:
// In order for this class to survive hot reloading, we need to make the fields serializable.
// Unity can't serialize an interface object, but does properly serialize UnityEngine.Object.
// So we cast the reference to PixelPerfectCamera (which inherits UnityEngine.Object)
// before serialization happens, and restore the interface reference after deserialization.
[NonSerialized]
IPixelPerfectCamera m_Component;
PixelPerfectCamera m_SerializableComponent;
internal float originalOrthoSize;
internal bool hasPostProcessLayer;
internal bool cropFrameXAndY = false;
internal bool cropFrameXOrY = false;
internal bool useStretchFill = false;
internal int zoom = 1;
internal bool useOffscreenRT = false;
internal int offscreenRTWidth = 0;
internal int offscreenRTHeight = 0;
internal Rect pixelRect = Rect.zero;
internal float orthoSize = 1.0f;
internal float unitsPerPixel = 0.0f;
internal int cinemachineVCamZoom = 1;
internal PixelPerfectCameraInternal(IPixelPerfectCamera component)
{
m_Component = component;
}
public void OnBeforeSerialize()
{
m_SerializableComponent = m_Component as PixelPerfectCamera;
}
public void OnAfterDeserialize()
{
if (m_SerializableComponent != null)
m_Component = m_SerializableComponent;
}
internal void CalculateCameraProperties(int screenWidth, int screenHeight)
{
int assetsPPU = m_Component.assetsPPU;
int refResolutionX = m_Component.refResolutionX;
int refResolutionY = m_Component.refResolutionY;
bool upscaleRT = m_Component.upscaleRT;
bool pixelSnapping = m_Component.pixelSnapping;
bool cropFrameX = m_Component.cropFrameX;
bool cropFrameY = m_Component.cropFrameY;
bool stretchFill = m_Component.stretchFill;
cropFrameXAndY = cropFrameY && cropFrameX;
cropFrameXOrY = cropFrameY || cropFrameX;
useStretchFill = cropFrameXAndY && stretchFill;
// zoom level (PPU scale)
int verticalZoom = screenHeight / refResolutionY;
int horizontalZoom = screenWidth / refResolutionX;
zoom = Math.Max(1, Math.Min(verticalZoom, horizontalZoom));
// off-screen RT
useOffscreenRT = false;
offscreenRTWidth = 0;
offscreenRTHeight = 0;
if (cropFrameXOrY)
{
if (!upscaleRT)
{
if (useStretchFill)
{
useOffscreenRT = true;
offscreenRTWidth = zoom * refResolutionX;
offscreenRTHeight = zoom * refResolutionY;
}
}
else
{
useOffscreenRT = true;
if (cropFrameXAndY)
{
offscreenRTWidth = refResolutionX;
offscreenRTHeight = refResolutionY;
}
else if (cropFrameY)
{
offscreenRTWidth = screenWidth / zoom / 2 * 2; // Make sure it's an even number by / 2 * 2.
offscreenRTHeight = refResolutionY;
}
else // crop frame X
{
offscreenRTWidth = refResolutionX;
offscreenRTHeight = screenHeight / zoom / 2 * 2; // Make sure it's an even number by / 2 * 2.
}
}
}
else if (upscaleRT && zoom > 1)
{
useOffscreenRT = true;
offscreenRTWidth = screenWidth / zoom / 2 * 2; // Make sure it's an even number by / 2 * 2.
offscreenRTHeight = screenHeight / zoom / 2 * 2;
}
// viewport
pixelRect = Rect.zero;
if (cropFrameXOrY && !upscaleRT && !useStretchFill)
{
if (cropFrameXAndY)
{
pixelRect.width = zoom * refResolutionX;
pixelRect.height = zoom * refResolutionY;
}
else if (cropFrameY)
{
pixelRect.width = screenWidth;
pixelRect.height = zoom * refResolutionY;
}
else // crop frame X
{
pixelRect.width = zoom * refResolutionX;
pixelRect.height = screenHeight;
}
pixelRect.x = (screenWidth - (int)pixelRect.width) / 2;
pixelRect.y = (screenHeight - (int)pixelRect.height) / 2;
}
else if (useOffscreenRT)
{
// When Camera.forceIntoRenderTexture is true, the size of the internal RT is determined by VP size.
// That's why we set the VP size to be (m_OffscreenRTWidth, m_OffscreenRTHeight) here.
pixelRect = new Rect(0.0f, 0.0f, offscreenRTWidth, offscreenRTHeight);
}
// orthographic size
if (cropFrameY)
orthoSize = (refResolutionY * 0.5f) / assetsPPU;
else if (cropFrameX)
{
float aspect = (pixelRect == Rect.zero) ? (float)screenWidth / screenHeight : pixelRect.width / pixelRect.height;
orthoSize = ((refResolutionX / aspect) * 0.5f) / assetsPPU;
}
else if (upscaleRT && zoom > 1)
orthoSize = (offscreenRTHeight * 0.5f) / assetsPPU;
else
{
float pixelHeight = (pixelRect == Rect.zero) ? screenHeight : pixelRect.height;
orthoSize = (pixelHeight * 0.5f) / (zoom * assetsPPU);
}
// Camera pixel grid spacing
if (upscaleRT || (!upscaleRT && pixelSnapping))
unitsPerPixel = 1.0f / assetsPPU;
else
unitsPerPixel = 1.0f / (zoom * assetsPPU);
}
internal Rect CalculatePostRenderPixelRect(float cameraAspect, int screenWidth, int screenHeight)
{
// This VP is used when the internal temp RT is blitted back to screen.
Rect pixelRect = new Rect();
if (useStretchFill)
{
// stretch (fit either width or height)
float screenAspect = (float)screenWidth / screenHeight;
if (screenAspect > cameraAspect)
{
pixelRect.height = screenHeight;
pixelRect.width = screenHeight * cameraAspect;
pixelRect.x = (screenWidth - (int)pixelRect.width) / 2;
pixelRect.y = 0;
}
else
{
pixelRect.width = screenWidth;
pixelRect.height = screenWidth / cameraAspect;
pixelRect.y = (screenHeight - (int)pixelRect.height) / 2;
pixelRect.x = 0;
}
}
else
{
// center
pixelRect.height = zoom * offscreenRTHeight;
pixelRect.width = zoom * offscreenRTWidth;
pixelRect.x = (screenWidth - (int)pixelRect.width) / 2;
pixelRect.y = (screenHeight - (int)pixelRect.height) / 2;
}
return pixelRect;
}
// Find a pixel-perfect orthographic size as close to targetOrthoSize as possible.
internal float CorrectCinemachineOrthoSize(float targetOrthoSize)
{
float correctedOrthoSize;
if (m_Component.upscaleRT)
{
cinemachineVCamZoom = Math.Max(1, Mathf.RoundToInt(orthoSize / targetOrthoSize));
correctedOrthoSize = orthoSize / cinemachineVCamZoom;
}
else
{
cinemachineVCamZoom = Math.Max(1, Mathf.RoundToInt(zoom * orthoSize / targetOrthoSize));
correctedOrthoSize = zoom * orthoSize / cinemachineVCamZoom;
}
// In this case the actual zoom level is cinemachineVCamZoom instead of zoom.
if (!m_Component.upscaleRT && !m_Component.pixelSnapping)
unitsPerPixel = 1.0f / (cinemachineVCamZoom * m_Component.assetsPPU);
return correctedOrthoSize;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e2681bc983b426e4e97502d23e3d66b4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,13 @@
{
"name": "Unity.2D.PixelPerfect",
"references": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 476f7c6c6dfeed041b063446a926e656
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: