281 lines
9.4 KiB
C#
281 lines
9.4 KiB
C#
using System;
|
|
using System.Linq;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using UnityEngine.Networking;
|
|
using Random = UnityEngine.Random;
|
|
|
|
// Shapes © Freya Holmér - https://twitter.com/FreyaHolmer/
|
|
// Website & Documentation - https://acegikmo.com/shapes/
|
|
namespace Shapes {
|
|
|
|
public class AboutWindow : EditorWindow {
|
|
|
|
class Center : IDisposable {
|
|
public Center() => Noot();
|
|
public void Dispose() => Noot();
|
|
static void Noot() => GUILayout.Label( GUIContent.none, GUILayout.ExpandWidth( true ) );
|
|
}
|
|
|
|
class CenterVertical : IDisposable {
|
|
public CenterVertical() => Noot();
|
|
public void Dispose() => Noot();
|
|
static void Noot() => GUILayout.Label( GUIContent.none, GUILayout.ExpandHeight( true ) );
|
|
}
|
|
|
|
class Doot {
|
|
public Doot( float angOffset, float angSpeed, float radialOffset ) {
|
|
this.angOffset = angOffset;
|
|
this.angSpeed = angSpeed;
|
|
this.radialOffset = radialOffset;
|
|
}
|
|
|
|
public float angOffset;
|
|
public float angSpeed;
|
|
public float radialOffset;
|
|
public Vector2 pos;
|
|
|
|
}
|
|
|
|
const float DOOT_MAX_RADIUS = 0.95f;
|
|
static Doot[] doots;
|
|
static Color colMain = new Color( 1, 1, 1, 1f );
|
|
static Color colFade = new Color( 0f, 0.1f, 0.1f, 0f );
|
|
static Color colF15 = new Color( 1f, 0.0666666f, 0.333333f, 1f );
|
|
|
|
GUIStyle labelStyle;
|
|
GUIStyle LabelStyle => labelStyle ?? ( labelStyle = new GUIStyle( GUI.skin.label ) { active = { textColor = Color.white }, normal = { textColor = Color.white } } );
|
|
GUIStyle linkStyle;
|
|
GUIStyle LinkStyle => linkStyle ?? ( linkStyle = new GUIStyle( LabelStyle ) { hover = { textColor = colF15 } } );
|
|
GUIStyle titleStyle;
|
|
GUIStyle TitleStyle => titleStyle ?? ( titleStyle = new GUIStyle( EditorStyles.boldLabel ) { fontSize = 26, alignment = TextAnchor.MiddleCenter, active = { textColor = Color.white }, normal = { textColor = Color.white } } );
|
|
GUIStyle labelCentered;
|
|
GUIStyle LabelCentered => labelCentered ?? ( labelCentered = new GUIStyle( GUI.skin.label ) { alignment = TextAnchor.MiddleCenter, active = { textColor = Color.white }, normal = { textColor = Color.white } } );
|
|
|
|
[NonSerialized] string newVersionAvailable = null;
|
|
[NonSerialized] UnityWebRequest req;
|
|
|
|
bool WebRequestHasErrors {
|
|
get {
|
|
#if UNITY_2020_1_OR_NEWER
|
|
return req.result == UnityWebRequest.Result.ProtocolError || req.result == UnityWebRequest.Result.ConnectionError;
|
|
#else
|
|
return req.isHttpError || req.isNetworkError;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void OnEnable() {
|
|
req = UnityWebRequest.Get( ShapesInfo.LINK_LATEST_VERSION );
|
|
req.SendWebRequest();
|
|
|
|
const int count = 16;
|
|
doots = new Doot[count];
|
|
for( int i = 0; i < count; i++ ) {
|
|
const float maxSpeed = 0.3f;
|
|
const float minSpeed = 0.1f;
|
|
float speed = Random.Range( minSpeed, maxSpeed ) * Mathf.Sign( Random.value - 0.5f );
|
|
doots[i] = new Doot( Random.value * ShapesMath.TAU, speed, Random.Range( 0.5f, DOOT_MAX_RADIUS ) );
|
|
}
|
|
|
|
EditorApplication.update += Update;
|
|
}
|
|
|
|
void OnDisable() => EditorApplication.update -= Update;
|
|
|
|
void Update() {
|
|
if( req != null && req.isDone ) {
|
|
if( WebRequestHasErrors == false ) {
|
|
OnReceiveLatestVersion( req.downloadHandler.text );
|
|
req.Dispose();
|
|
req = null;
|
|
} else if( WebRequestHasErrors ) {
|
|
Debug.LogWarning( $"Shapes failed to check for updates. Reason: {req.error}" );
|
|
req.Dispose();
|
|
req = null;
|
|
}
|
|
}
|
|
|
|
Repaint();
|
|
}
|
|
|
|
void OnReceiveLatestVersion( string latestVersion ) {
|
|
int[] GetVersionNums( string str ) => str.Split( '.' ).Select( int.Parse ).ToArray();
|
|
int[] latest = GetVersionNums( latestVersion );
|
|
int[] current = GetVersionNums( ShapesInfo.Version );
|
|
newVersionAvailable = null;
|
|
for( int i = 0; i < 3; i++ ) {
|
|
if( current[i] > latest[i] )
|
|
return; // local version is newer somehow. you're probably freya. or a hacker >:I
|
|
if( latest[i] > current[i] ) {
|
|
newVersionAvailable = latestVersion;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void OnGUI() {
|
|
if( Event.current.type == EventType.Repaint )
|
|
DrawShapes();
|
|
DrawText();
|
|
if( Event.current.type == EventType.MouseDown ) {
|
|
GUI.FocusControl( null );
|
|
Repaint();
|
|
}
|
|
}
|
|
|
|
void DrawText() {
|
|
using( new CenterVertical() ) {
|
|
GUI.color = colMain;
|
|
|
|
if( newVersionAvailable != null ) {
|
|
using( ShapesUI.Horizontal ) {
|
|
using( new Center() ) {
|
|
float t = (float)EditorApplication.timeSinceStartup;
|
|
float wave = ShapesMath.SmoothCos01( Mathf.PingPong( t, 0.5f ) * 2 );
|
|
wave = Mathf.Lerp( 0.5f, 1f, wave );
|
|
GUI.color = Color.Lerp( Color.white, colF15, wave );
|
|
LinkLabel( newVersionAvailable + " now available", ShapesInfo.LINK_CHANGELOG );
|
|
GUI.color = Color.white;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
GUILayout.Label( $"Shapes {ShapesInfo.Version}", TitleStyle );
|
|
using( ShapesUI.Horizontal ) {
|
|
using( new Center() ) {
|
|
int year = Mathf.Max( DateTime.Now.Year, 2020 ); // just in case your computer clock is wonky~
|
|
GUILayout.Label( $"© {year}", LabelStyle, GUILayout.ExpandWidth( false ) );
|
|
LinkLabel( "Freya Holmér", ShapesInfo.LINK_TWITTER );
|
|
}
|
|
}
|
|
|
|
GUI.color = Color.white;
|
|
GUILayout.Space( 8 );
|
|
GUILayout.Label( "made possible thanks to\nthe wonderful supporters on", LabelCentered, GUILayout.ExpandWidth( true ) );
|
|
using( ShapesUI.Horizontal ) {
|
|
using( new Center() ) {
|
|
LinkLabel( "Patreon", ShapesInfo.LINK_PATREON );
|
|
}
|
|
}
|
|
|
|
GUI.color = colF15;
|
|
GUILayout.Label( "♥", TitleStyle, GUILayout.ExpandWidth( true ) );
|
|
GUI.color = Color.white;
|
|
}
|
|
}
|
|
|
|
float mouseDootT = 0f;
|
|
|
|
void DrawShapes() {
|
|
Vector2 center = position.size / 2;
|
|
float fitRadius = Mathf.Min( position.width, position.height ) / 2 - 8;
|
|
|
|
// set doot positions
|
|
float t = (float)EditorApplication.timeSinceStartup / 2;
|
|
foreach( Doot doot in doots ) {
|
|
float ang = doot.angSpeed * t * ShapesMath.TAU + doot.angOffset;
|
|
Vector2 dir = ShapesMath.AngToDir( ang );
|
|
doot.pos = dir * ( fitRadius * doot.radialOffset );
|
|
}
|
|
|
|
// mouse doot~
|
|
Vector2 mouseRawPos = Event.current.mousePosition - center;
|
|
float maxRadius = fitRadius * DOOT_MAX_RADIUS;
|
|
Vector2 mouseTargetPos = Vector2.ClampMagnitude( mouseRawPos, maxRadius );
|
|
doots[0].pos = Vector2.Lerp( doots[0].pos, mouseTargetPos, mouseDootT );
|
|
bool mouseOver = mouseOverWindow == this;
|
|
mouseDootT = Mathf.Lerp( mouseDootT, mouseOver ? 1f : 0f, 0.05f );
|
|
|
|
|
|
Draw.Push(); // save state
|
|
Draw.ResetAllDrawStates();
|
|
|
|
// draw setup
|
|
Draw.Matrix = Matrix4x4.TRS( new Vector3( center.x, center.y, 1f ), Quaternion.identity, Vector3.one );
|
|
Draw.BlendMode = ShapesBlendMode.Transparent;
|
|
Draw.RadiusSpace = ThicknessSpace.Meters;
|
|
Draw.ThicknessSpace = ThicknessSpace.Meters;
|
|
Draw.LineGeometry = LineGeometry.Flat2D;
|
|
Draw.LineEndCaps = LineEndCap.Round;
|
|
|
|
// Drawing
|
|
Draw.Ring( Vector3.zero, fitRadius, fitRadius * 0.1f, DiscColors.Radial( Color.black, new Color( 0, 0, 0, 0 ) ) );
|
|
Draw.Disc( Vector3.zero, fitRadius, Color.black );
|
|
|
|
// edge noodles
|
|
const int noodCount = 64;
|
|
for( int i = 0; i < noodCount; i++ ) {
|
|
float tDir = i / ( (float)noodCount );
|
|
float tAng = ShapesMath.TAU * tDir;
|
|
Vector2 dir = ShapesMath.AngToDir( tAng );
|
|
if( Mathf.Abs( dir.y ) > 0.75f )
|
|
continue;
|
|
Vector2 root = dir * fitRadius;
|
|
float distToNearest = float.MaxValue;
|
|
for( int j = 0; j < doots.Length; j++ )
|
|
distToNearest = Mathf.Min( distToNearest, Vector2.Distance( doots[j].pos, root ) );
|
|
float distMod = Mathf.InverseLerp( fitRadius * 0.5f, fitRadius * 0.1f, distToNearest );
|
|
float noodMaxOffset = fitRadius * ( 1 + 0.1f * distMod );
|
|
Draw.Line( root, dir * noodMaxOffset, fitRadius * Mathf.Lerp( 0.07f, 0.04f, distMod ) );
|
|
}
|
|
|
|
// ring
|
|
Draw.Ring( Vector3.zero, fitRadius, fitRadius * 0.0125f, colMain );
|
|
|
|
// connecting lines
|
|
for( int i = 0; i < doots.Length; i++ ) {
|
|
Vector2 a = doots[i].pos;
|
|
for( int j = i; j < doots.Length; j++ ) {
|
|
Vector2 b = doots[j].pos;
|
|
float dist = Vector2.Distance( a, b );
|
|
float rangeValue = Mathf.InverseLerp( fitRadius * 1f, fitRadius * 0.02f, dist );
|
|
if( rangeValue > 0 ) {
|
|
Color col = Color.Lerp( colFade, colMain, rangeValue );
|
|
Draw.Line( a, b, fitRadius * 0.015f * rangeValue, LineEndCap.Round, col );
|
|
}
|
|
}
|
|
}
|
|
|
|
// doots~
|
|
foreach( Doot doot in doots ) {
|
|
Draw.BlendMode = ShapesBlendMode.Transparent;
|
|
Draw.Disc( doot.pos, fitRadius * 0.025f, Color.black );
|
|
Draw.Disc( doot.pos, fitRadius * 0.015f, colMain );
|
|
Draw.BlendMode = ShapesBlendMode.Additive;
|
|
Color innerColor = colMain;
|
|
innerColor.a = 0.25f;
|
|
Color outerColor = Color.clear;
|
|
Draw.Disc( doot.pos, fitRadius * 0.18f, DiscColors.Radial( innerColor, outerColor ) );
|
|
}
|
|
|
|
Draw.BlendMode = ShapesBlendMode.Multiplicative;
|
|
Draw.Disc( Vector3.zero, fitRadius * 0.5f, DiscColors.Radial( Color.black, Color.clear ) );
|
|
|
|
Draw.Pop(); // restore state
|
|
}
|
|
|
|
|
|
void LinkLabel( string label, string url ) {
|
|
GUIContent content = new GUIContent( label );
|
|
if( GUILayout.Button( content, LinkStyle, GUILayout.ExpandWidth( false ) ) )
|
|
Application.OpenURL( url );
|
|
Rect r = GUILayoutUtility.GetLastRect();
|
|
EditorGUIUtility.AddCursorRect( r, MouseCursor.Link );
|
|
Handles.BeginGUI();
|
|
Color c = GUI.color;
|
|
c.a = 0.5f;
|
|
Handles.color = c;
|
|
float y = r.yMax - 1;
|
|
float margin = 2;
|
|
Handles.DrawLine( new Vector3( r.xMin + margin, y ), new Vector3( r.xMax - margin, y ) );
|
|
Handles.color = Color.white;
|
|
Handles.EndGUI();
|
|
}
|
|
|
|
|
|
}
|
|
|
|
} |