123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534 |
- using System.Collections;
- using System.Collections.Generic;
- using System.IO;
- using UnityEngine;
- using UnityEditor;
- using UnityEngine.SceneManagement;
- namespace Funly.SkyStudio
- {
- public abstract class SkyEditorUtility
- {
- public const float KEY_GRIP_HEIGHT = 18.0f;
- public const float KEY_GRIP_WIDTH = 18.0f;
- public const string KEY_GRIP_ACTIVE = "TriangleGripActive";
- public const string KEY_GRIP_INACTIVE = "TriangleGripInactive";
- public const string GENERATED_CONTENT_DIR = "Data";
- public const string PACKAGE_DIR_NAME = "FunlySkyStudio";
- public static Dictionary<string, Texture2D> _imageCache = new Dictionary<string, Texture2D>();
- // Keyframe time is pretty much zero.
- public static bool IsKeyFrameAtStart(IBaseKeyframe keyframe)
- {
- return keyframe.time >= 0 && keyframe.time < .00001f;
- }
- // Keyframe time is pretty much 1.0f.
- public static bool IsKeyFrameAtEnd(IBaseKeyframe keyframe)
- {
- return keyframe.time >= .99999f;
- }
- public static float GetWidthBetweenTimes(Rect rect, float fromTime, float toTime)
- {
- if (toTime < fromTime) {
- toTime = 1.0f;
- }
- return GetXPositionForPercent(rect, toTime) - GetXPositionForPercent(rect, fromTime);
- }
- // Get the xPosition that's a percent inside the rect.
- public static float GetXPositionForPercent(Rect rect, float percent)
- {
- float distance = rect.width * percent;
- return rect.x + distance;
- }
- public static float GetYPositionForPercent(Rect rect, float percent)
- {
- return rect.y + (rect.height * percent);
- }
- // Get the percentage this xPosition is inside the rect.
- public static float GetPercentForXPosition(Rect rect, float xPosition)
- {
- return Mathf.Clamp01((xPosition - rect.x) / rect.width);
- }
- public static float GetPercentForYPosition(Rect rect, float yPosition)
- {
- return Mathf.Clamp01((yPosition - rect.y) / rect.height);
- }
- public static void CancelKeyframeDrag() {
- TimelineSelection.selectedControlUUID = null;
- }
- // Cancel drag operations, useful for when mouse leaves window.
- public static void CancelTimelineDrags() {
- TimelineSelection.selectedControlUUID = null;
- TimelineSelection.isDraggingTimeline = false;
- }
- public static bool IsKeyframeSelected(IBaseKeyframe keyframe) {
- if (keyframe == null || TimelineSelection.selectedControlUUID == null ||
- TimelineSelection.selectedControlUUID != keyframe.id) {
- return false;
- }
- return true;
- }
- // Sticks to bottom of rect, and can slide horizontally only.
- public static void DrawHorizontalKeyMarker(
- Rect fullSliderRect, BaseKeyframe keyFrame, UnityEngine.Object undoObject, out bool didSingleClick, out bool isDragging, out bool keyFrameTimeChanged)
- {
- Rect markerRect = new Rect(
- SkyEditorUtility.GetXPositionForPercent(fullSliderRect, keyFrame.time) - (KEY_GRIP_WIDTH / 2),
- fullSliderRect.y + fullSliderRect.height - (KEY_GRIP_HEIGHT) / 2.0f,
- KEY_GRIP_WIDTH,
- KEY_GRIP_HEIGHT);
-
- bool wasDragging = TimelineSelection.selectedControlUUID != null && TimelineSelection.selectedControlUUID == keyFrame.id;
- bool isMouseOverControl = markerRect.Contains(Event.current.mousePosition);
- didSingleClick = false;
- isDragging = wasDragging;
- keyFrameTimeChanged = false;
- // Single Click.
- if (Event.current.isMouse) {
- // Check for single click, with no drag.
- if (Event.current.type == EventType.MouseUp && TimelineSelection.selectedControlUUID == null && isMouseOverControl) {
- Event.current.Use();
- didSingleClick = true;
- }
- // Start slide.
- if (TimelineSelection.selectedControlUUID == null && isMouseOverControl && Event.current.type == EventType.MouseDrag) {
- TimelineSelection.selectedControlUUID = keyFrame.id;
- Event.current.Use();
- isDragging = true;
- }
- // End Slide.
- if (wasDragging && Event.current.type == EventType.MouseUp) {
- TimelineSelection.selectedControlUUID = null;
- Event.current.Use();
- isDragging = false;
- }
- // If we're dragging this keyframe grip, move it's position.
- if (isDragging || wasDragging) {
- // Update key frame time value and reposition rectangle.
- Undo.RecordObject(undoObject, "Keyframe time position changed.");
- keyFrame.time = SkyEditorUtility.GetPercentForXPosition(fullSliderRect, Event.current.mousePosition.x);
- keyFrameTimeChanged = true;
- isDragging = true;
- // Position the marker rect.
- markerRect.x = SkyEditorUtility.GetXPositionForPercent(fullSliderRect, keyFrame.time) - (KEY_GRIP_WIDTH / 2);
- Event.current.Use();
- }
- }
- bool showAsActive = IsKeyframeActiveInInspector(keyFrame) || isDragging;
- // Draw the marker at this location.
- SkyEditorUtility.DrawKeyMarker(markerRect, showAsActive);
- }
- public static void DrawNumericKeyMarker(Rect fullSliderRect, NumberKeyframe keyFrame, NumberKeyframeGroup group,
- UnityEngine.Object undoObject, out bool didSingleClick, out bool isDragging, out bool keyFrameTimeChanged)
- {
- Rect markerRect = new Rect(
- SkyEditorUtility.GetXPositionForPercent(fullSliderRect, keyFrame.time) - (KEY_GRIP_WIDTH / 2),
- GetYPositionForPercent(fullSliderRect, 1 - group.ValueToPercent(keyFrame.value)),
- KEY_GRIP_WIDTH,
- KEY_GRIP_HEIGHT);
- bool wasDragging = TimelineSelection.selectedControlUUID != null && TimelineSelection.selectedControlUUID == keyFrame.id;
- bool isMouseOverControl = markerRect.Contains(Event.current.mousePosition);
- didSingleClick = false;
- keyFrameTimeChanged = false;
- isDragging = wasDragging;
- // Single Click.
- if (Event.current.isMouse) {
- // Check for single click, with no drag.
- if (Event.current.type == EventType.MouseUp && TimelineSelection.selectedControlUUID == null && isMouseOverControl) {
- didSingleClick = true;
- Event.current.Use();
- }
- // Start slide.
- if (TimelineSelection.selectedControlUUID == null && isMouseOverControl && Event.current.type == EventType.MouseDrag) {
- TimelineSelection.selectedControlUUID = keyFrame.id;
- // Find the position of the current value and record the offset so we can drag the keygrip relative from here.
- Vector2 valuePosition = new Vector2(
- GetXPositionForPercent(fullSliderRect, keyFrame.time),
- GetYPositionForPercent(fullSliderRect, 1 - group.ValueToPercent(keyFrame.value)));
- TimelineSelection.startingMouseOffset = valuePosition - Event.current.mousePosition;
- isDragging = true;
- Event.current.Use();
- }
- // End Slide.
- if (wasDragging && Event.current.type == EventType.MouseUp) {
- TimelineSelection.selectedControlUUID = null;
- isDragging = false;
- Event.current.Use();
- }
- // If we're dragging this keyframe grip, move it's position.
- if (wasDragging || isDragging) {
- // Update key frame time value and reposition rectangle.
- Undo.RecordObject(undoObject, "Keyframe time and value changed.");
- Vector2 adjustedMousePosition = Event.current.mousePosition + TimelineSelection.startingMouseOffset;
- keyFrame.time = GetPercentForXPosition(fullSliderRect, adjustedMousePosition.x);
- float adjustedValuePercent = 1 - GetPercentForYPosition(fullSliderRect, adjustedMousePosition.y);
- keyFrame.value = group.PercentToValue(adjustedValuePercent);
- keyFrameTimeChanged = true;
- isDragging = true;
- // Position the marker rect.
- markerRect.x = SkyEditorUtility.GetXPositionForPercent(fullSliderRect, keyFrame.time) - (KEY_GRIP_WIDTH / 2);
- markerRect.y = GetYPositionForPercent(fullSliderRect, 1 - group.ValueToPercent(keyFrame.value));
- Event.current.Use();
- }
- }
- bool showAsActive = IsKeyframeActiveInInspector(keyFrame) || isDragging;
- // Draw the marker at this location.
- SkyEditorUtility.DrawKeyMarker(markerRect, showAsActive);
- }
- // True if the keyframe is shown in the inspector window.
- public static bool IsKeyframeActiveInInspector(BaseKeyframe keyFrame) {
- if (KeyframeInspectorWindow.inspectorEnabled && KeyframeInspectorWindow.GetActiveKeyframeId() == keyFrame.id)
- {
- return true;
- } else {
- return false;
- }
- }
- // True if group is selected on timeline.
- public static bool IsGroupSelectedOnTimeline(string groupId) {
- if (TimelineSelection.selectedGroupUUID != null && TimelineSelection.selectedGroupUUID == groupId) {
- return true;
- } else {
- return false;
- }
- }
- public static void DrawKeyMarker(Rect rect, bool isActive)
- {
- if (Event.current.type != EventType.Repaint)
- {
- return;
- }
- Texture2D gripTexture = null;
- if (isActive) {
- gripTexture = GetActiveKeyframeMarkerTexture();
- } else {
- gripTexture = GetInactiveKeyframeMarkerTexture();
- }
- GUI.DrawTexture(rect, gripTexture, ScaleMode.ScaleAndCrop, true);
- }
- public static Texture2D GetActiveKeyframeMarkerTexture()
- {
- return LoadEditorResourceTexture(KEY_GRIP_ACTIVE);
- }
- public static Texture2D GetInactiveKeyframeMarkerTexture()
- {
- return LoadEditorResourceTexture(KEY_GRIP_INACTIVE);
- }
- public static Texture2D LoadEditorResourceTexture(string textureName) {
- return LoadEditorResourceTexture(textureName, true);
- }
- public static Texture2D LoadEditorResourceTexture(string textureName, bool useCache)
- {
- if (textureName == null) {
- Debug.LogError("Can't load null texture name");
- return null;
- }
- if (useCache && _imageCache.ContainsKey(textureName))
- {
- return _imageCache[textureName];
- }
- string[] guids = AssetDatabase.FindAssets(textureName);
- if (guids.Length == 0) {
- Debug.LogError("Failed to located editor keyframe texture, asset is in unknown location.");
- return null;
- }
- foreach (string guid in guids)
- {
- // Return first image located inside our asset directory.
- string assetPath = AssetDatabase.GUIDToAssetPath(guid);
- if (assetPath.Contains(PACKAGE_DIR_NAME))
- {
- Texture2D tex = AssetDatabase.LoadAssetAtPath<Texture2D>(assetPath);
- if (useCache) {
- _imageCache.Add(textureName, tex);
- }
- return tex;
- }
- }
- return null;
- }
- public static GameObject LoadEditorPrefab(string prefabName)
- {
- string[] guids = AssetDatabase.FindAssets("t:prefab " + prefabName);
- if (guids.Length == 0) {
- Debug.LogError("Failed to located editor keyframe texture, asset is in unknown location.");
- return null;
- }
- foreach (string guid in guids) {
- string assetPath = AssetDatabase.GUIDToAssetPath(guid);
- if (assetPath.Contains(PACKAGE_DIR_NAME)) {
- return AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);
- }
- }
- return null;
- }
- public static void WriteTextureToJpgFile(RenderTexture renderTexture, string filename)
- {
- Texture2D tex = new Texture2D(renderTexture.width, renderTexture.height);
- tex.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
- tex.Apply();
- Debug.Log("Writing out texture width:" + tex.width + " height:" + tex.height);
- File.WriteAllBytes(filename, tex.EncodeToJPG());
- }
- public static void WriteTextureToFile(RenderTexture renderTexture, string filename)
- {
- Texture2D tex = new Texture2D(renderTexture.width, renderTexture.height);
- tex.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
- tex.Apply();
- WriteTextureToFile(tex, filename);
- }
- public static void WriteTextureToFile(RenderTexture renderTexture, string filename, TextureFormat textureFormat)
- {
- Texture2D tex = new Texture2D(renderTexture.width, renderTexture.height, textureFormat, false);
- tex.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
- tex.Apply();
- WriteTextureToFile(tex, filename);
- }
- public static void WriteTextureToFile(Texture2D tex, string filename)
- {
- File.WriteAllBytes(filename, tex.EncodeToPNG());
- }
- public static void CreateSkyDataDirectory(SkyProfile profile)
- {
- string profilePath = AssetDatabase.GetAssetPath(profile);
- if (profilePath == null) {
- Debug.LogError("Failed to locate sky profile on disk, is it saved yet?");
- return;
- }
- string containingDir = Path.GetDirectoryName(profilePath);
- string fullSkyDataPath = containingDir + "/" + GENERATED_CONTENT_DIR;
- if (AssetDatabase.IsValidFolder(fullSkyDataPath) == false) {
- AssetDatabase.CreateFolder(containingDir, GENERATED_CONTENT_DIR);
- }
- }
- public static string GetDirectoryForAssetGUID(string guid)
- {
- string assetPath = AssetDatabase.GUIDToAssetPath(guid);
- return Path.GetDirectoryName(assetPath);
- }
-
- public static string GetProfileSkyboxPath(string dataDirPath)
- {
- return dataDirPath + "/Skybox.mat";
- }
- public static string GetProfileSkyResourcesDirPath(string dataDirPath)
- {
- return dataDirPath + "/Sky-Resources";
- }
- public static string GetProfileSkyResourceFilePath(string dataDirPath, string assetName)
- {
- return GetProfileSkyResourcesDirPath(dataDirPath) + "/" + assetName;
- }
- public static string CreateSkyDataFolderWithScene(Scene scene, string skyProfileName)
- {
- string dataDir = Path.GetDirectoryName(scene.path);
- if (AssetDatabase.IsValidFolder(dataDir) == false) {
- AssetDatabase.CreateFolder(Path.GetDirectoryName(dataDir), Path.GetFileName(dataDir));
- }
- return dataDir;
- }
- public static string GenerateUniqueFolder(string parentFolder, string folderName, bool create)
- {
- const int maxTries = 200;
- int currentTry = 0;
- // Verify directory exists.
- if (!AssetDatabase.IsValidFolder(parentFolder)) {
- Debug.LogWarning("Invalid parent directory: " + parentFolder);
- return null;
- }
- while (currentTry < maxTries) {
- string tryDirName = null;
- if (currentTry == 0) {
- tryDirName = folderName;
- } else {
- tryDirName = folderName + "-" + currentTry;
- }
- string tryAssetPath = parentFolder + "/" + tryDirName;
- if (AssetDatabase.IsValidFolder(tryAssetPath) == false) {
- if (create) {
- AssetDatabase.CreateFolder(parentFolder, tryDirName);
- }
- return tryAssetPath;
- }
- currentTry += 1;
- }
- Debug.LogError("Failed to generate a unique filename after " + maxTries + " tries.");
- return null;
- }
- public static string GenerateUniqueFilename(string directoryPath, string filename, string extension)
- {
- const int maxTries = 200;
- int currentTry = 0;
- // Verify directory exists.
- if (!AssetDatabase.IsValidFolder(directoryPath)) {
- Debug.LogWarning("Filename is already unique since root directory does not exist: " + directoryPath);
- return directoryPath + "/" + filename + extension;
- }
- while (currentTry < maxTries) {
- string tryFilename = null;
- if (currentTry == 0) {
- tryFilename = filename;
- } else {
- tryFilename = filename + "-" + currentTry;
- }
- string tryAssetPath = directoryPath + "/" + tryFilename + extension;
- string guid = AssetDatabase.AssetPathToGUID(tryAssetPath);
- if ( guid == null || guid.Length == 0) {
- return tryAssetPath;
- }
- currentTry += 1;
- }
- Debug.LogError("Failed to generate a unique filename after " + maxTries + " tries.");
- return null;
- }
- public static string GetSkyProfileAssetPath(SkyProfile profile, string assetName)
- {
- CreateSkyDataDirectory(profile);
- string profileAssetPath = AssetDatabase.GetAssetPath(profile);
- if (profileAssetPath == null || profileAssetPath.Length == 0) {
- Debug.LogError("Can't return asset path that doesn't exist in database");
- return null;
- }
- string skyResourceDir = Path.GetDirectoryName(profileAssetPath);
- return skyResourceDir + "/Data/" + assetName + ".asset";
- }
- public static void RemoveSkyDataResource(SkyProfile profile, string textureName)
- {
- string texturePath = GetSkyProfileAssetPath(profile, textureName);
- AssetDatabase.DeleteAsset(texturePath);
- }
- public static void AddSkyResource(SkyProfile profile, Texture texture)
- {
- CreateSkyDataDirectory(profile);
- string texturePath = GetSkyProfileAssetPath(profile, texture.name);
-
- if (AssetDatabase.IsValidFolder(Path.GetDirectoryName(texturePath)) == false) {
- AssetDatabase.CreateFolder(Path.GetDirectoryName(texturePath), Path.GetFileName(texturePath));
- }
- AssetDatabase.CreateAsset(texture, texturePath);
- }
- // Converts back slashes to forward slashes.
- public static string WindowsPathToUnixPath(string path) {
- return path.Replace('\\', '/');
- }
- // Returns true if this asset path is inside the Sky Studio folder.
- public static bool IsAssetPathInsideSkyStudio(string assetPath) {
- return assetPath.Contains(PACKAGE_DIR_NAME);
- }
- public static string GetBestDefaultShaderNameForUnityVersion() {
- #if UNITY_2019_1_OR_NEWER
- return SkyProfile.DefaultShaderName;
- #else
- return SkyProfile.DefaultLegacyShaderName;
- #endif
- }
- // Does this version of unity support local keywords in shaders.
- public static bool SupportsLocalKeywords() {
- #if UNITY_2019_1_OR_NEWER
- return true;
- #else
- return false;
- #endif
- }
- }
- }
|