fishnet installed
This commit is contained in:
118
Assets/FishNet/Runtime/Editor/CodeStripping.cs
Normal file
118
Assets/FishNet/Runtime/Editor/CodeStripping.cs
Normal file
@ -0,0 +1,118 @@
|
||||
|
||||
using FishNet.Configuring;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using FishNet.Editing.PrefabCollectionGenerator;
|
||||
using UnityEditor.Compilation;
|
||||
using UnityEditor.Build.Reporting;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Build;
|
||||
#endif
|
||||
|
||||
namespace FishNet.Configuring
|
||||
{
|
||||
|
||||
|
||||
public class CodeStripping
|
||||
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// True if making a release build for client.
|
||||
/// </summary>
|
||||
public static bool ReleasingForClient => (Configuration.Configurations.CodeStripping.IsBuilding && !Configuration.Configurations.CodeStripping.IsHeadless && !Configuration.Configurations.CodeStripping.IsDevelopment);
|
||||
/// <summary>
|
||||
/// True if making a release build for server.
|
||||
/// </summary>
|
||||
public static bool ReleasingForServer => (Configuration.Configurations.CodeStripping.IsBuilding && Configuration.Configurations.CodeStripping.IsHeadless && !Configuration.Configurations.CodeStripping.IsDevelopment);
|
||||
/// <summary>
|
||||
/// Returns if to remove server logic.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static bool RemoveServerLogic
|
||||
{
|
||||
get
|
||||
{
|
||||
|
||||
|
||||
/* This is to protect non pro users from enabling this
|
||||
* without the extra logic code. */
|
||||
#pragma warning disable CS0162 // Unreachable code detected
|
||||
return false;
|
||||
#pragma warning restore CS0162 // Unreachable code detected
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// True if building and stripping is enabled.
|
||||
/// </summary>
|
||||
public static bool StripBuild
|
||||
{
|
||||
get
|
||||
{
|
||||
|
||||
|
||||
/* This is to protect non pro users from enabling this
|
||||
* without the extra logic code. */
|
||||
#pragma warning disable CS0162 // Unreachable code detected
|
||||
return false;
|
||||
#pragma warning restore CS0162 // Unreachable code detected
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Technique to strip methods.
|
||||
/// </summary>
|
||||
public static StrippingTypes StrippingType => (StrippingTypes)Configuration.Configurations.CodeStripping.StrippingType;
|
||||
|
||||
private static object _compilationContext;
|
||||
public int callbackOrder => 0;
|
||||
#if UNITY_EDITOR
|
||||
|
||||
public void OnPreprocessBuild(BuildReport report)
|
||||
{
|
||||
Generator.IgnorePostProcess = true;
|
||||
Generator.GenerateFull();
|
||||
CompilationPipeline.compilationStarted += CompilationPipelineOnCompilationStarted;
|
||||
CompilationPipeline.compilationFinished += CompilationPipelineOnCompilationFinished;
|
||||
|
||||
|
||||
}
|
||||
/* Solution for builds ending with errors and not triggering OnPostprocessBuild.
|
||||
* Link: https://gamedev.stackexchange.com/questions/181611/custom-build-failure-callback
|
||||
*/
|
||||
private void CompilationPipelineOnCompilationStarted(object compilationContext)
|
||||
{
|
||||
_compilationContext = compilationContext;
|
||||
}
|
||||
|
||||
private void CompilationPipelineOnCompilationFinished(object compilationContext)
|
||||
{
|
||||
if (compilationContext != _compilationContext)
|
||||
return;
|
||||
|
||||
_compilationContext = null;
|
||||
|
||||
CompilationPipeline.compilationStarted -= CompilationPipelineOnCompilationStarted;
|
||||
CompilationPipeline.compilationFinished -= CompilationPipelineOnCompilationFinished;
|
||||
|
||||
BuildingEnded();
|
||||
}
|
||||
|
||||
private void BuildingEnded()
|
||||
{
|
||||
|
||||
|
||||
Generator.IgnorePostProcess = false;
|
||||
}
|
||||
|
||||
public void OnPostprocessBuild(BuildReport report)
|
||||
{
|
||||
|
||||
BuildingEnded();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
11
Assets/FishNet/Runtime/Editor/CodeStripping.cs.meta
Normal file
11
Assets/FishNet/Runtime/Editor/CodeStripping.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0c7409efe2f84e7428d5c6c97ed7d32e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/FishNet/Runtime/Editor/Configuring.meta
Normal file
8
Assets/FishNet/Runtime/Editor/Configuring.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e789fd90a3d65864bbead2949dbdbb36
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
146
Assets/FishNet/Runtime/Editor/Configuring/ConfigurationData.cs
Normal file
146
Assets/FishNet/Runtime/Editor/Configuring/ConfigurationData.cs
Normal file
@ -0,0 +1,146 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
namespace FishNet.Configuring
|
||||
{
|
||||
|
||||
public enum StrippingTypes : int
|
||||
{
|
||||
Redirect = 0,
|
||||
Empty_Experimental = 1,
|
||||
}
|
||||
public enum SearchScopeType : int
|
||||
{
|
||||
EntireProject = 0,
|
||||
SpecificFolders = 1,
|
||||
}
|
||||
|
||||
public class PrefabGeneratorConfigurations
|
||||
{
|
||||
public bool Enabled = true;
|
||||
public bool LogToConsole = true;
|
||||
public bool FullRebuild = false;
|
||||
public bool SaveChanges = true;
|
||||
public string DefaultPrefabObjectsPath = Path.Combine("Assets", "DefaultPrefabObjects.asset");
|
||||
public int SearchScope = (int)SearchScopeType.EntireProject;
|
||||
public List<string> ExcludedFolders = new List<string>();
|
||||
public List<string> IncludedFolders = new List<string>();
|
||||
}
|
||||
|
||||
public class CodeStrippingConfigurations
|
||||
{
|
||||
public bool IsBuilding = false;
|
||||
public bool IsDevelopment = false;
|
||||
public bool IsHeadless = false;
|
||||
public bool StripReleaseBuilds = false;
|
||||
public int StrippingType = (int)StrippingTypes.Redirect;
|
||||
}
|
||||
|
||||
|
||||
public class ConfigurationData
|
||||
{
|
||||
//Non serialized doesn't really do anything, its just for me.
|
||||
[System.NonSerialized]
|
||||
public bool Loaded;
|
||||
|
||||
public PrefabGeneratorConfigurations PrefabGenerator = new PrefabGeneratorConfigurations();
|
||||
public CodeStrippingConfigurations CodeStripping = new CodeStrippingConfigurations();
|
||||
}
|
||||
|
||||
public static class ConfigurationDataExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns if a differs from b.
|
||||
/// </summary>
|
||||
public static bool HasChanged(this ConfigurationData a, ConfigurationData b)
|
||||
{
|
||||
return (a.CodeStripping.StripReleaseBuilds != b.CodeStripping.StripReleaseBuilds);
|
||||
}
|
||||
/// <summary>
|
||||
/// Copies all values from source to target.
|
||||
/// </summary>
|
||||
public static void CopyTo(this ConfigurationData source, ConfigurationData target)
|
||||
{
|
||||
target.CodeStripping.StripReleaseBuilds = source.CodeStripping.StripReleaseBuilds;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Writes a configuration data.
|
||||
/// </summary>
|
||||
public static void Write(this ConfigurationData cd, bool refreshAssetDatabase)
|
||||
{
|
||||
/* Why is this a thing you ask? Because Unity makes it VERY difficult to read values from
|
||||
* memory during builds since on some Unity versions the building application is on a different
|
||||
* processor. In result instead of using memory to read configurationdata the values
|
||||
* must be written to disk then load the disk values as needed.
|
||||
*
|
||||
* Fortunatelly the file is extremely small and this does not occur often at all. The disk read
|
||||
* will occur once per script save, and once per assembly when building. */
|
||||
try
|
||||
{
|
||||
string path = Configuration.GetAssetsPath(Configuration.CONFIG_FILE_NAME);
|
||||
XmlSerializer serializer = new XmlSerializer(typeof(ConfigurationData));
|
||||
TextWriter writer = new StreamWriter(path);
|
||||
serializer.Serialize(writer, cd);
|
||||
writer.Close();
|
||||
#if UNITY_EDITOR
|
||||
if (refreshAssetDatabase)
|
||||
{
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception($"An error occurred while writing ConfigurationData. Message: {ex.Message}");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Writes a configuration data.
|
||||
/// </summary>
|
||||
public static void Write(this ConfigurationData cd, string path, bool refreshAssetDatabase)
|
||||
{
|
||||
/* Why is this a thing you ask? Because Unity makes it VERY difficult to read values from
|
||||
* memory during builds since on some Unity versions the building application is on a different
|
||||
* processor. In result instead of using memory to read configurationdata the values
|
||||
* must be written to disk then load the disk values as needed.
|
||||
*
|
||||
* Fortunatelly the file is extremely small and this does not occur often at all. The disk read
|
||||
* will occur once per script save, and once per assembly when building. */
|
||||
try
|
||||
{
|
||||
XmlSerializer serializer = new XmlSerializer(typeof(ConfigurationData));
|
||||
TextWriter writer = new StreamWriter(path);
|
||||
serializer.Serialize(writer, cd);
|
||||
writer.Close();
|
||||
#if UNITY_EDITOR
|
||||
if (refreshAssetDatabase)
|
||||
{
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception($"An error occurred while writing ConfigurationData. Message: {ex.Message}");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4be37e1b0afd29944ad4fa0b92ed8c7e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
126
Assets/FishNet/Runtime/Editor/Configuring/ConfigurationEditor.cs
Normal file
126
Assets/FishNet/Runtime/Editor/Configuring/ConfigurationEditor.cs
Normal file
@ -0,0 +1,126 @@
|
||||
#if UNITY_EDITOR
|
||||
using FishNet.Editing.PrefabCollectionGenerator;
|
||||
using FishNet.Object;
|
||||
using FishNet.Utility.Extension;
|
||||
using FishNet.Utility.Performance;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace FishNet.Editing
|
||||
{
|
||||
public class ConfigurationEditor : EditorWindow
|
||||
{
|
||||
|
||||
[MenuItem("Fish-Networking/Configuration", false, 0)]
|
||||
public static void ShowConfiguration()
|
||||
{
|
||||
SettingsService.OpenProjectSettings("Project/Fish-Networking/Configuration");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class RebuildSceneIdMenu : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// Rebuilds sceneIds for open scenes.
|
||||
/// </summary>
|
||||
[MenuItem("Fish-Networking/Rebuild SceneIds", false, 20)]
|
||||
public static void RebuildSceneIds()
|
||||
{
|
||||
int generatedCount = 0;
|
||||
for (int i = 0; i < SceneManager.sceneCount; i++)
|
||||
{
|
||||
Scene s = SceneManager.GetSceneAt(i);
|
||||
|
||||
ListCache<NetworkObject> nobs;
|
||||
SceneFN.GetSceneNetworkObjects(s, false, out nobs);
|
||||
for (int z = 0; z < nobs.Written; z++)
|
||||
{
|
||||
NetworkObject nob = nobs.Collection[z];
|
||||
nob.TryCreateSceneID();
|
||||
EditorUtility.SetDirty(nob);
|
||||
}
|
||||
generatedCount += nobs.Written;
|
||||
|
||||
ListCaches.StoreCache(nobs);
|
||||
}
|
||||
|
||||
Debug.Log($"Generated sceneIds for {generatedCount} objects over {SceneManager.sceneCount} scenes. Please save your open scenes.");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class RefreshDefaultPrefabsMenu : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// Rebuilds the DefaultPrefabsCollection file.
|
||||
/// </summary>
|
||||
[MenuItem("Fish-Networking/Refresh Default Prefabs", false, 22)]
|
||||
public static void RebuildDefaultPrefabs()
|
||||
{
|
||||
Debug.Log("Refreshing default prefabs.");
|
||||
Generator.GenerateFull(null, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class RemoveDuplicateNetworkObjectsMenu : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// Iterates all network object prefabs in the project and open scenes, removing NetworkObject components which exist multiple times on a single object.
|
||||
/// </summary>
|
||||
[MenuItem("Fish-Networking/Remove Duplicate NetworkObjects", false, 21)]
|
||||
|
||||
public static void RemoveDuplicateNetworkObjects()
|
||||
{
|
||||
List<NetworkObject> foundNobs = new List<NetworkObject>();
|
||||
|
||||
foreach (string path in Generator.GetPrefabFiles("Assets", new HashSet<string>(), true))
|
||||
{
|
||||
NetworkObject nob = AssetDatabase.LoadAssetAtPath<NetworkObject>(path);
|
||||
if (nob != null)
|
||||
foundNobs.Add(nob);
|
||||
}
|
||||
|
||||
//Now add scene objects.
|
||||
for (int i = 0; i < SceneManager.sceneCount; i++)
|
||||
{
|
||||
Scene s = SceneManager.GetSceneAt(i);
|
||||
|
||||
ListCache<NetworkObject> nobs;
|
||||
SceneFN.GetSceneNetworkObjects(s, false, out nobs);
|
||||
for (int z = 0; z < nobs.Written; z++)
|
||||
{
|
||||
NetworkObject nob = nobs.Collection[z];
|
||||
nob.TryCreateSceneID();
|
||||
EditorUtility.SetDirty(nob);
|
||||
}
|
||||
for (int z = 0; z < nobs.Written; z++)
|
||||
foundNobs.Add(nobs.Collection[i]);
|
||||
|
||||
ListCaches.StoreCache(nobs);
|
||||
}
|
||||
|
||||
//Remove duplicates.
|
||||
int removed = 0;
|
||||
foreach (NetworkObject nob in foundNobs)
|
||||
{
|
||||
int count = nob.RemoveDuplicateNetworkObjects();
|
||||
if (count > 0)
|
||||
removed += count;
|
||||
}
|
||||
|
||||
Debug.Log($"Removed {removed} duplicate NetworkObjects. Please save your open scenes and project.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
#endif
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8135b3a4c31cfb74896f1e9e77059c89
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
102
Assets/FishNet/Runtime/Editor/Configuring/Configuring.cs
Normal file
102
Assets/FishNet/Runtime/Editor/Configuring/Configuring.cs
Normal file
@ -0,0 +1,102 @@
|
||||
using System.IO;
|
||||
using System.Xml.Serialization;
|
||||
using UnityEngine;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor.Compilation;
|
||||
using UnityEditor.Build.Reporting;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Build;
|
||||
#endif
|
||||
|
||||
namespace FishNet.Configuring
|
||||
{
|
||||
|
||||
|
||||
public class Configuration
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
private static ConfigurationData _configurations;
|
||||
/// <summary>
|
||||
/// ConfigurationData to use.
|
||||
/// </summary>
|
||||
public static ConfigurationData Configurations
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_configurations == null)
|
||||
_configurations = LoadConfigurationData();
|
||||
if (_configurations == null)
|
||||
throw new System.Exception("Fish-Networking Configurations could not be loaded. Certain features such as code-stripping may not function.");
|
||||
return _configurations;
|
||||
}
|
||||
private set
|
||||
{
|
||||
_configurations = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// File name for configuration disk data.
|
||||
/// </summary>
|
||||
public const string CONFIG_FILE_NAME = "FishNet.Config.XML";
|
||||
|
||||
/// <summary>
|
||||
/// Returns the path for the configuration file.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal static string GetAssetsPath(string additional = "")
|
||||
{
|
||||
string a = Path.Combine(System.IO.Directory.GetCurrentDirectory(), "Assets");
|
||||
if (additional != "")
|
||||
a = Path.Combine(a, additional);
|
||||
return a;
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns FishNetworking ConfigurationData.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal static ConfigurationData LoadConfigurationData()
|
||||
{
|
||||
//return new ConfigurationData();
|
||||
if (_configurations == null || !_configurations.Loaded)
|
||||
{
|
||||
string configPath = GetAssetsPath(CONFIG_FILE_NAME);
|
||||
//string configPath = string.Empty;
|
||||
//File is on disk.
|
||||
if (File.Exists(configPath))
|
||||
{
|
||||
FileStream fs = null;
|
||||
try
|
||||
{
|
||||
XmlSerializer serializer = new XmlSerializer(typeof(ConfigurationData));
|
||||
fs = new FileStream(configPath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
_configurations = (ConfigurationData)serializer.Deserialize(fs);
|
||||
}
|
||||
finally
|
||||
{
|
||||
fs?.Close();
|
||||
}
|
||||
_configurations.Loaded = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//If null then make a new instance.
|
||||
if (_configurations == null)
|
||||
_configurations = new ConfigurationData();
|
||||
//Don't unset loaded, if its true then it should have proper info.
|
||||
//_configurationData.Loaded = false;
|
||||
}
|
||||
}
|
||||
|
||||
return _configurations;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8d05bf07ec9af2c46a1fe6c24871cccb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,172 @@
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FishNet.Editing
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Contributed by YarnCat! Thank you!
|
||||
/// </summary>
|
||||
public class FishNetGettingStartedEditor : EditorWindow
|
||||
{
|
||||
private Texture2D _fishnetLogo, _reviewButtonBg, _reviewButtonBgHover;
|
||||
private GUIStyle _labelStyle, _reviewButtonStyle;
|
||||
|
||||
private const string SHOWED_GETTING_STARTED = "ShowedFishNetGettingStarted";
|
||||
|
||||
[MenuItem("Fish-Networking/Getting Started")]
|
||||
public static void GettingStartedMenu()
|
||||
{
|
||||
FishNetGettingStartedEditor window = (FishNetGettingStartedEditor)EditorWindow.GetWindow(typeof(FishNetGettingStartedEditor));
|
||||
window.position = new Rect(0, 0, 320, 355);
|
||||
Rect mainPos;
|
||||
#if UNITY_2020_1_OR_NEWER
|
||||
mainPos = EditorGUIUtility.GetMainWindowPosition();
|
||||
#else
|
||||
mainPos = new Rect(Vector2.zero, Vector2.zero);
|
||||
#endif
|
||||
var pos = window.position;
|
||||
float w = (mainPos.width - pos.width) * 0.5f;
|
||||
float h = (mainPos.height - pos.height) * 0.5f;
|
||||
pos.x = mainPos.x + w;
|
||||
pos.y = mainPos.y + h;
|
||||
window.position = pos;
|
||||
|
||||
window._fishnetLogo = (Texture2D)AssetDatabase.LoadAssetAtPath("Assets/FishNet/Runtime/Editor/Textures/UI/Logo_With_Text.png", typeof(Texture));
|
||||
window._labelStyle = new GUIStyle("label");
|
||||
window._labelStyle.fontSize = 24;
|
||||
window._labelStyle.wordWrap = true;
|
||||
//window.labelStyle.alignment = TextAnchor.MiddleCenter;
|
||||
window._labelStyle.normal.textColor = new Color32(74, 195, 255, 255);
|
||||
|
||||
window._reviewButtonBg = MakeBackgroundTexture(1, 1, new Color32(52, 111, 255, 255));
|
||||
window._reviewButtonBgHover = MakeBackgroundTexture(1, 1, new Color32(99, 153, 255, 255));
|
||||
window._reviewButtonStyle = new GUIStyle("button");
|
||||
window._reviewButtonStyle.fontSize = 18;
|
||||
window._reviewButtonStyle.fontStyle = FontStyle.Bold;
|
||||
window._reviewButtonStyle.normal.background = window._reviewButtonBg;
|
||||
window._reviewButtonStyle.active.background = window._reviewButtonBgHover;
|
||||
window._reviewButtonStyle.focused.background = window._reviewButtonBgHover;
|
||||
window._reviewButtonStyle.onFocused.background = window._reviewButtonBgHover;
|
||||
window._reviewButtonStyle.hover.background = window._reviewButtonBgHover;
|
||||
window._reviewButtonStyle.onHover.background = window._reviewButtonBgHover;
|
||||
window._reviewButtonStyle.alignment = TextAnchor.MiddleCenter;
|
||||
window._reviewButtonStyle.normal.textColor = new Color(1, 1, 1, 1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static bool _subscribed;
|
||||
|
||||
[InitializeOnLoadMethod]
|
||||
private static void Initialize()
|
||||
{
|
||||
SubscribeToUpdate();
|
||||
}
|
||||
|
||||
private static void SubscribeToUpdate()
|
||||
{
|
||||
if (Application.isBatchMode)
|
||||
return;
|
||||
|
||||
if (!_subscribed && !EditorApplication.isPlayingOrWillChangePlaymode)
|
||||
{
|
||||
_subscribed = true;
|
||||
EditorApplication.update += ShowGettingStarted;
|
||||
}
|
||||
}
|
||||
|
||||
private static void ShowGettingStarted()
|
||||
{
|
||||
EditorApplication.update -= ShowGettingStarted;
|
||||
|
||||
bool shown = EditorPrefs.GetBool(SHOWED_GETTING_STARTED, false);
|
||||
if (!shown)
|
||||
{
|
||||
EditorPrefs.SetBool(SHOWED_GETTING_STARTED, true);
|
||||
ReviewReminderEditor.ResetDateTimeReminded();
|
||||
GettingStartedMenu();
|
||||
}
|
||||
//If was already shown then check review reminder instead.
|
||||
else
|
||||
{
|
||||
ReviewReminderEditor.CheckRemindToReview();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OnGUI()
|
||||
{
|
||||
|
||||
|
||||
GUILayout.Box(_fishnetLogo, GUILayout.Width(this.position.width), GUILayout.Height(128));
|
||||
GUILayout.Space(20);
|
||||
|
||||
GUILayout.Label("Have you considered leaving us a review?", _labelStyle, GUILayout.Width(280));
|
||||
|
||||
GUILayout.Space(10);
|
||||
|
||||
if (GUILayout.Button("Leave us a review!", _reviewButtonStyle))
|
||||
{
|
||||
Application.OpenURL("https://assetstore.unity.com/packages/tools/network/fish-net-networking-evolved-207815");
|
||||
}
|
||||
|
||||
GUILayout.Space(20);
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
if (GUILayout.Button("Documentation", GUILayout.Width(this.position.width * 0.485f)))
|
||||
{
|
||||
Application.OpenURL("https://fish-networking.gitbook.io/docs/");
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Discord", GUILayout.Width(this.position.width * 0.485f)))
|
||||
{
|
||||
Application.OpenURL("https://discord.gg/Ta9HgDh4Hj");
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
if (GUILayout.Button("FishNet Pro", GUILayout.Width(this.position.width * 0.485f)))
|
||||
{
|
||||
Application.OpenURL("https://fish-networking.gitbook.io/docs/master/pro");
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Github", GUILayout.Width(this.position.width * 0.485f)))
|
||||
{
|
||||
Application.OpenURL("https://github.com/FirstGearGames/FishNet");
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
if (GUILayout.Button("Pro Downloads", GUILayout.Width(this.position.width * 0.485f)))
|
||||
{
|
||||
Application.OpenURL("https://www.firstgeargames.com/");
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Examples", GUILayout.Width(this.position.width * 0.485f)))
|
||||
{
|
||||
Application.OpenURL("https://fish-networking.gitbook.io/docs/manual/tutorials/example-projects");
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
//GUILayout.Space(20);
|
||||
//_showOnStartupSelected = EditorGUILayout.Popup("Show on Startup", _showOnStartupSelected, showOnStartupOptions);
|
||||
}
|
||||
//private string[] showOnStartupOptions = new string[] { "Always", "On new version", "Never", };
|
||||
//private int _showOnStartupSelected = 1;
|
||||
|
||||
private static Texture2D MakeBackgroundTexture(int width, int height, Color color)
|
||||
{
|
||||
Color[] pixels = new Color[width * height];
|
||||
for (int i = 0; i < pixels.Length; i++)
|
||||
pixels[i] = color;
|
||||
Texture2D backgroundTexture = new Texture2D(width, height);
|
||||
backgroundTexture.SetPixels(pixels);
|
||||
backgroundTexture.Apply();
|
||||
return backgroundTexture;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 335aec9a9dce4944994cb57ac704ba5a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,171 @@
|
||||
#if UNITY_EDITOR
|
||||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FishNet.Editing
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Contributed by YarnCat! Thank you!
|
||||
/// </summary>
|
||||
public class ReviewReminderEditor : EditorWindow
|
||||
{
|
||||
private Texture2D _fishnetLogo, _reviewButtonBg, _reviewButtonBgHover;
|
||||
private GUIStyle _labelStyle, _reviewButtonStyle;
|
||||
|
||||
private const string DATETIME_REMINDED = "ReviewDateTimeReminded";
|
||||
private const string CHECK_REMIND_COUNT = "CheckRemindCount";
|
||||
private const string IS_ENABLED = "ReminderEnabled";
|
||||
|
||||
private static ReviewReminderEditor _window;
|
||||
|
||||
internal static void CheckRemindToReview()
|
||||
{
|
||||
bool reminderEnabled = EditorPrefs.GetBool(IS_ENABLED, true);
|
||||
if (!reminderEnabled)
|
||||
return;
|
||||
|
||||
/* Require at least two opens and 10 days
|
||||
* to be passed before reminding. */
|
||||
int checkRemindCount = (EditorPrefs.GetInt(CHECK_REMIND_COUNT, 0) + 1);
|
||||
EditorPrefs.SetInt(CHECK_REMIND_COUNT, checkRemindCount);
|
||||
|
||||
//Not enough checks.
|
||||
if (checkRemindCount < 2)
|
||||
return;
|
||||
|
||||
string dtStr = EditorPrefs.GetString(DATETIME_REMINDED, string.Empty);
|
||||
//Somehow got cleared. Reset.
|
||||
if (string.IsNullOrWhiteSpace(dtStr))
|
||||
{
|
||||
ResetDateTimeReminded();
|
||||
return;
|
||||
}
|
||||
long binary;
|
||||
//Failed to parse.
|
||||
if (!long.TryParse(dtStr, out binary))
|
||||
{
|
||||
ResetDateTimeReminded();
|
||||
return;
|
||||
}
|
||||
//Not enough time passed.
|
||||
DateTime dt = DateTime.FromBinary(binary);
|
||||
if ((DateTime.Now - dt).TotalDays < 10)
|
||||
return;
|
||||
|
||||
//If here then the reminder can be shown.
|
||||
EditorPrefs.SetInt(CHECK_REMIND_COUNT, 0);
|
||||
|
||||
ShowReminder();
|
||||
}
|
||||
|
||||
internal static void ResetDateTimeReminded()
|
||||
{
|
||||
EditorPrefs.SetString(DATETIME_REMINDED, DateTime.Now.ToBinary().ToString());
|
||||
}
|
||||
|
||||
private static void ShowReminder()
|
||||
{
|
||||
InitializeWindow();
|
||||
}
|
||||
|
||||
static void InitializeWindow()
|
||||
{
|
||||
if (_window != null)
|
||||
return;
|
||||
_window = (ReviewReminderEditor)EditorWindow.GetWindow(typeof(ReviewReminderEditor));
|
||||
_window.position = new Rect(0f, 0f, 320f, 300f);
|
||||
Rect mainPos;
|
||||
#if UNITY_2020_1_OR_NEWER
|
||||
mainPos = EditorGUIUtility.GetMainWindowPosition();
|
||||
#else
|
||||
mainPos = new Rect(Vector2.zero, Vector2.zero);
|
||||
#endif
|
||||
var pos = _window.position;
|
||||
float w = (mainPos.width - pos.width) * 0.5f;
|
||||
float h = (mainPos.height - pos.height) * 0.5f;
|
||||
pos.x = mainPos.x + w;
|
||||
pos.y = mainPos.y + h;
|
||||
_window.position = pos;
|
||||
}
|
||||
|
||||
static void StyleWindow()
|
||||
{
|
||||
InitializeWindow();
|
||||
_window._fishnetLogo = (Texture2D)AssetDatabase.LoadAssetAtPath("Assets/FishNet/Runtime/Editor/Textures/UI/Logo_With_Text.png", typeof(Texture));
|
||||
_window._labelStyle = new GUIStyle("label");
|
||||
_window._labelStyle.fontSize = 24;
|
||||
_window._labelStyle.wordWrap = true;
|
||||
//window.labelStyle.alignment = TextAnchor.MiddleCenter;
|
||||
_window._labelStyle.normal.textColor = new Color32(74, 195, 255, 255);
|
||||
|
||||
_window._reviewButtonBg = MakeBackgroundTexture(1, 1, new Color32(52, 111, 255, 255));
|
||||
_window._reviewButtonBgHover = MakeBackgroundTexture(1, 1, new Color32(99, 153, 255, 255));
|
||||
_window._reviewButtonStyle = new GUIStyle("button");
|
||||
_window._reviewButtonStyle.fontSize = 18;
|
||||
_window._reviewButtonStyle.fontStyle = FontStyle.Bold;
|
||||
_window._reviewButtonStyle.normal.background = _window._reviewButtonBg;
|
||||
_window._reviewButtonStyle.active.background = _window._reviewButtonBgHover;
|
||||
_window._reviewButtonStyle.focused.background = _window._reviewButtonBgHover;
|
||||
_window._reviewButtonStyle.onFocused.background = _window._reviewButtonBgHover;
|
||||
_window._reviewButtonStyle.hover.background = _window._reviewButtonBgHover;
|
||||
_window._reviewButtonStyle.onHover.background = _window._reviewButtonBgHover;
|
||||
_window._reviewButtonStyle.alignment = TextAnchor.MiddleCenter;
|
||||
_window._reviewButtonStyle.normal.textColor = new Color(1, 1, 1, 1);
|
||||
|
||||
}
|
||||
|
||||
void OnGUI()
|
||||
{
|
||||
float thisWidth = this.position.width;
|
||||
StyleWindow();
|
||||
GUILayout.Box(_fishnetLogo, GUILayout.Width(this.position.width), GUILayout.Height(160f));
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.Space(8f);
|
||||
GUILayout.Label("Have you considered leaving us a review?", _labelStyle, GUILayout.Width(thisWidth * 0.95f));
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
if (GUILayout.Button("Don't Ask Again", GUILayout.Width(this.position.width)))
|
||||
{
|
||||
this.Close();
|
||||
EditorPrefs.SetBool(IS_ENABLED, false);
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
if (GUILayout.Button("Ask Later", GUILayout.Width(this.position.width)))
|
||||
{
|
||||
this.Close();
|
||||
Application.OpenURL("https://discord.gg/Ta9HgDh4Hj");
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
if (GUILayout.Button("Leave A Review", GUILayout.Width(this.position.width)))
|
||||
{
|
||||
this.Close();
|
||||
EditorPrefs.SetBool(IS_ENABLED, false);
|
||||
Application.OpenURL("https://assetstore.unity.com/packages/tools/network/fish-net-networking-evolved-207815");
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
//GUILayout.Space(20);
|
||||
//_showOnStartupSelected = EditorGUILayout.Popup("Show on Startup", _showOnStartupSelected, showOnStartupOptions);
|
||||
}
|
||||
|
||||
private static Texture2D MakeBackgroundTexture(int width, int height, Color color)
|
||||
{
|
||||
Color[] pixels = new Color[width * height];
|
||||
for (int i = 0; i < pixels.Length; i++)
|
||||
pixels[i] = color;
|
||||
Texture2D backgroundTexture = new Texture2D(width, height);
|
||||
backgroundTexture.SetPixels(pixels);
|
||||
backgroundTexture.Apply();
|
||||
return backgroundTexture;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4260206b6a57e4243b56437f8f283084
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,86 @@
|
||||
#if UNITY_EDITOR
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using FishNet.Configuring;
|
||||
|
||||
using UnitySettingsProviderAttribute = UnityEditor.SettingsProviderAttribute;
|
||||
using UnitySettingsProvider = UnityEditor.SettingsProvider;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FishNet.Configuring.Editing
|
||||
{
|
||||
internal static class SettingsProvider
|
||||
{
|
||||
private static Vector2 _scrollView;
|
||||
|
||||
[UnitySettingsProvider]
|
||||
private static UnitySettingsProvider Create()
|
||||
{
|
||||
return new UnitySettingsProvider("Project/Fish-Networking/Configuration", SettingsScope.Project)
|
||||
{
|
||||
label = "Configuration",
|
||||
|
||||
guiHandler = OnGUI,
|
||||
|
||||
keywords = new string[]
|
||||
{
|
||||
"Fish",
|
||||
"Networking",
|
||||
"Configuration",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private static void OnGUI(string searchContext)
|
||||
{
|
||||
ConfigurationData configuration = Configuration.LoadConfigurationData();
|
||||
|
||||
if (configuration == null)
|
||||
{
|
||||
EditorGUILayout.HelpBox("Unable to load configuration data.", MessageType.Error);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
GUIStyle scrollViewStyle = new GUIStyle()
|
||||
{
|
||||
padding = new RectOffset(10, 10, 10, 10),
|
||||
};
|
||||
|
||||
_scrollView = GUILayout.BeginScrollView(_scrollView, scrollViewStyle);
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
GUIStyle toggleStyle = new GUIStyle(EditorStyles.toggle)
|
||||
{
|
||||
richText = true,
|
||||
};
|
||||
|
||||
configuration.CodeStripping.StripReleaseBuilds = GUILayout.Toggle(configuration.CodeStripping.StripReleaseBuilds, $"{ObjectNames.NicifyVariableName(nameof(configuration.CodeStripping.StripReleaseBuilds))} <color=yellow>(Pro Only)</color>", toggleStyle);
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
if (configuration.CodeStripping.StripReleaseBuilds)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
//Stripping Method.
|
||||
List<string> enumStrings = new List<string>();
|
||||
foreach (string item in System.Enum.GetNames(typeof(StrippingTypes)))
|
||||
enumStrings.Add(item);
|
||||
configuration.CodeStripping.StrippingType = EditorGUILayout.Popup($"{ObjectNames.NicifyVariableName(nameof(configuration.CodeStripping.StrippingType))}", (int)configuration.CodeStripping.StrippingType, enumStrings.ToArray());
|
||||
|
||||
EditorGUILayout.HelpBox("Development builds will not have code stripped. Additionally, if you plan to run as host disable code stripping.", MessageType.Warning);
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
|
||||
GUILayout.EndScrollView();
|
||||
|
||||
if (EditorGUI.EndChangeCheck()) Configuration.Configurations.Write(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b3d7d3c45d53dea4e8a0a7da73d64021
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
13
Assets/FishNet/Runtime/Editor/Constants.cs
Normal file
13
Assets/FishNet/Runtime/Editor/Constants.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using FishNet.Documenting;
|
||||
|
||||
namespace FishNet.Editing
|
||||
{
|
||||
[APIExclude]
|
||||
public static class EditingConstants
|
||||
{
|
||||
public const string PRO_ASSETS_LOCKED_TEXT = "Fields marked with * are only active with Fish-Networking Pro.";
|
||||
public const string PRO_ASSETS_UNLOCKED_TEXT = "Thank you for supporting Fish-Networking! Pro asset features are unlocked.";
|
||||
|
||||
}
|
||||
|
||||
}
|
11
Assets/FishNet/Runtime/Editor/Constants.cs.meta
Normal file
11
Assets/FishNet/Runtime/Editor/Constants.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1d2683b3becd2c5488c1f338972d49e0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
126
Assets/FishNet/Runtime/Editor/DefaultPrefabsFinder.cs
Normal file
126
Assets/FishNet/Runtime/Editor/DefaultPrefabsFinder.cs
Normal file
@ -0,0 +1,126 @@
|
||||
//#if UNITY_EDITOR
|
||||
//using FishNet.Managing.Object;
|
||||
//using FishNet.Object;
|
||||
//using System.Collections.Generic;
|
||||
//using System.IO;
|
||||
//using UnityEditor;
|
||||
//using UnityEngine;
|
||||
|
||||
//namespace FishNet.Editing
|
||||
//{
|
||||
|
||||
// [InitializeOnLoad]
|
||||
// internal static class DefaultPrefabsFinder
|
||||
// {
|
||||
// /// <summary>
|
||||
// /// True if initialized.
|
||||
// /// </summary>
|
||||
// [System.NonSerialized]
|
||||
// private static bool _initialized;
|
||||
// /// <summary>
|
||||
// /// Found default prefabs.
|
||||
// /// </summary>
|
||||
// private static DefaultPrefabObjects _defaultPrefabs;
|
||||
|
||||
// static DefaultPrefabsFinder()
|
||||
// {
|
||||
// EditorApplication.update += InitializeOnce;
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Finds and sets the default prefabs reference.
|
||||
// /// </summary>
|
||||
// internal static DefaultPrefabObjects GetDefaultPrefabsFile(out bool justPopulated)
|
||||
// {
|
||||
// if (_defaultPrefabs == null)
|
||||
// {
|
||||
// List<UnityEngine.Object> results = Finding.GetScriptableObjects<DefaultPrefabObjects>(true, true);
|
||||
// if (results.Count > 0)
|
||||
// _defaultPrefabs = (DefaultPrefabObjects)results[0];
|
||||
// }
|
||||
|
||||
// justPopulated = false;
|
||||
// //If not found then try to create file.
|
||||
// if (_defaultPrefabs == null)
|
||||
// {
|
||||
// if (DefaultPrefabObjects.CanAutomate)
|
||||
// {
|
||||
// DefaultPrefabObjects dpo = ScriptableObject.CreateInstance<DefaultPrefabObjects>();
|
||||
// //Get save directory.
|
||||
// string savePath = Finding.GetFishNetRuntimePath(true);
|
||||
// AssetDatabase.CreateAsset(dpo, Path.Combine(savePath, $"{nameof(DefaultPrefabObjects)}.asset"));
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// Debug.LogError($"Cannot create DefaultPrefabs because auto create is blocked.");
|
||||
// }
|
||||
// }
|
||||
|
||||
// //If still null.
|
||||
// if (_defaultPrefabs == null)
|
||||
// Debug.LogWarning($"DefaultPrefabObjects not found. Prefabs list will not be automatically populated.");
|
||||
// else
|
||||
// justPopulated = PopulateDefaultPrefabs();
|
||||
|
||||
// return _defaultPrefabs;
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Initializes the default prefab.
|
||||
// /// </summary>
|
||||
// private static void InitializeOnce()
|
||||
// {
|
||||
// if (_initialized)
|
||||
// return;
|
||||
// _initialized = true;
|
||||
|
||||
// Finding.GetFishNetRuntimePath(false);
|
||||
// GetDefaultPrefabsFile(out _);
|
||||
|
||||
// if (_defaultPrefabs != null)
|
||||
// {
|
||||
// //Populate any missing.
|
||||
// if (_defaultPrefabs.GetObjectCount() == 0)
|
||||
// PopulateDefaultPrefabs();
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// /// <summary>
|
||||
// /// Finds all NetworkObjects in project and adds them to defaultPrefabs.
|
||||
// /// </summary>
|
||||
// /// <returns>True if was populated from assets.</returns>
|
||||
// internal static bool PopulateDefaultPrefabs(bool log = true, bool clear = false)
|
||||
// {
|
||||
// if (_defaultPrefabs == null)
|
||||
// return false;
|
||||
// if (!DefaultPrefabObjects.CanAutomate)
|
||||
// return false;
|
||||
// if (clear)
|
||||
// _defaultPrefabs.Clear();
|
||||
// if (_defaultPrefabs.GetObjectCount() > 0)
|
||||
// return false;
|
||||
|
||||
// List<GameObject> gameObjects = Finding.GetGameObjects(true, true, false);
|
||||
// foreach (GameObject go in gameObjects)
|
||||
// {
|
||||
// if (go.TryGetComponent(out NetworkObject nob))
|
||||
// _defaultPrefabs.AddObject(nob);
|
||||
// }
|
||||
|
||||
// _defaultPrefabs.Sort();
|
||||
|
||||
// int entriesAdded = _defaultPrefabs.GetObjectCount();
|
||||
// //Only print if some were added.
|
||||
// if (log && entriesAdded > 0)
|
||||
// Debug.Log($"Default prefabs was populated with {entriesAdded} prefabs.");
|
||||
|
||||
// EditorUtility.SetDirty(_defaultPrefabs);
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
|
||||
//}
|
||||
//#endif
|
11
Assets/FishNet/Runtime/Editor/DefaultPrefabsFinder.cs.meta
Normal file
11
Assets/FishNet/Runtime/Editor/DefaultPrefabsFinder.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2bd002f6c85dd4341bcaf163eaaa3ddf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
216
Assets/FishNet/Runtime/Editor/Finding.cs
Normal file
216
Assets/FishNet/Runtime/Editor/Finding.cs
Normal file
@ -0,0 +1,216 @@
|
||||
#if UNITY_EDITOR
|
||||
using FishNet.Utility.Constant;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace FishNet.Editing
|
||||
{
|
||||
public static class Finding
|
||||
{
|
||||
#region Private.
|
||||
/// <summary>
|
||||
/// Path where the FishNet.Runtime assembly is.
|
||||
/// </summary>
|
||||
[System.NonSerialized]
|
||||
private static string _fishNetRuntimePath = string.Empty;
|
||||
/// <summary>
|
||||
/// Path where the FishNet.Generated assembly is.
|
||||
/// </summary>
|
||||
private static string _fishNetGeneratedPath = string.Empty;
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Sets FishNet assembly paths.
|
||||
/// </summary>
|
||||
/// <param name="error"></param>
|
||||
private static void SetPaths(bool error)
|
||||
{
|
||||
if (_fishNetGeneratedPath != string.Empty && _fishNetRuntimePath != string.Empty)
|
||||
return;
|
||||
|
||||
string[] guids = AssetDatabase.FindAssets("t:asmdef", new string[] { "Assets" });
|
||||
string[] objectPaths = new string[guids.Length];
|
||||
for (int i = 0; i < guids.Length; i++)
|
||||
objectPaths[i] = AssetDatabase.GUIDToAssetPath(guids[i]);
|
||||
|
||||
string runtimeName = (UtilityConstants.RUNTIME_ASSEMBLY_NAME + ".asmdef").ToLower();
|
||||
string generatedName = (UtilityConstants.GENERATED_ASSEMBLY_NAME + ".asmdef").ToLower();
|
||||
/* Find all network managers which use Single prefab linking
|
||||
* as well all network object prefabs. */
|
||||
foreach (string item in objectPaths)
|
||||
{
|
||||
//Found directory to create object in.
|
||||
if (item.ToLower().Contains(runtimeName))
|
||||
_fishNetRuntimePath = System.IO.Path.GetDirectoryName(item);
|
||||
else if (item.ToLower().Contains(generatedName))
|
||||
_fishNetGeneratedPath = System.IO.Path.GetDirectoryName(item);
|
||||
|
||||
if (_fishNetGeneratedPath != string.Empty && _fishNetRuntimePath != string.Empty)
|
||||
return;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets path for where the FishNet.Runtime assembly is.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static string GetFishNetRuntimePath(bool error)
|
||||
{
|
||||
SetPaths(error);
|
||||
return _fishNetRuntimePath;
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets path for where the FishNet.Generated assembly is.
|
||||
/// </summary>
|
||||
/// <param name="error"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetFishNetGeneratedPath(bool error)
|
||||
{
|
||||
SetPaths(error);
|
||||
return _fishNetGeneratedPath;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all GameObjects in Assets and optionally scenes.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static List<GameObject> GetGameObjects(bool userAssemblies, bool fishNetAssembly, bool includeScenes, string[] ignoredPaths = null)
|
||||
{
|
||||
List<GameObject> results = new List<GameObject>();
|
||||
|
||||
string[] guids;
|
||||
string[] objectPaths;
|
||||
|
||||
guids = AssetDatabase.FindAssets("t:GameObject", null);
|
||||
objectPaths = new string[guids.Length];
|
||||
for (int i = 0; i < guids.Length; i++)
|
||||
objectPaths[i] = AssetDatabase.GUIDToAssetPath(guids[i]);
|
||||
|
||||
foreach (string item in objectPaths)
|
||||
{
|
||||
bool inFishNet = item.Contains(_fishNetRuntimePath);
|
||||
if (inFishNet && !fishNetAssembly)
|
||||
continue;
|
||||
if (!inFishNet && !userAssemblies)
|
||||
continue;
|
||||
if (ignoredPaths != null)
|
||||
{
|
||||
bool ignore = false;
|
||||
foreach (string path in ignoredPaths)
|
||||
{
|
||||
if (item.Contains(path))
|
||||
{
|
||||
ignore = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ignore)
|
||||
continue;
|
||||
}
|
||||
|
||||
GameObject go = (GameObject)AssetDatabase.LoadAssetAtPath(item, typeof(GameObject));
|
||||
results.Add(go);
|
||||
}
|
||||
|
||||
if (includeScenes)
|
||||
results.AddRange(GetSceneGameObjects());
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all GameObjects in all open scenes.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static List<GameObject> GetSceneGameObjects()
|
||||
{
|
||||
List<GameObject> results = new List<GameObject>();
|
||||
|
||||
for (int i = 0; i < SceneManager.sceneCount; i++)
|
||||
results.AddRange(GetSceneGameObjects(SceneManager.GetSceneAt(i)));
|
||||
|
||||
return results;
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets all GameObjects in a scene.
|
||||
/// </summary>
|
||||
private static List<GameObject> GetSceneGameObjects(Scene s)
|
||||
{
|
||||
List<GameObject> results = new List<GameObject>();
|
||||
List<Transform> buffer = new List<Transform>();
|
||||
//Iterate all root objects for the scene.
|
||||
GameObject[] gos = s.GetRootGameObjects();
|
||||
for (int i = 0; i < gos.Length; i++)
|
||||
{
|
||||
/* Get GameObjects within children of each
|
||||
* root object then add them to the cache. */
|
||||
gos[i].GetComponentsInChildren<Transform>(true, buffer);
|
||||
foreach (Transform t in buffer)
|
||||
results.Add(t.gameObject);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets created ScriptableObjects of T.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static List<UnityEngine.Object> GetScriptableObjects<T>(bool fishNetAssembly, bool breakOnFirst = false)
|
||||
{
|
||||
System.Type tType = typeof(T);
|
||||
List<UnityEngine.Object> results = new List<UnityEngine.Object>();
|
||||
|
||||
string[] guids = AssetDatabase.FindAssets("t:ScriptableObject", new string[] { "Assets" });
|
||||
string[] objectPaths = new string[guids.Length];
|
||||
for (int i = 0; i < guids.Length; i++)
|
||||
objectPaths[i] = AssetDatabase.GUIDToAssetPath(guids[i]);
|
||||
|
||||
|
||||
/* This might be faster than using directory comparers.
|
||||
* Don't really care since this occurs only at edit. */
|
||||
List<string> fishNetPaths = new List<string>();
|
||||
fishNetPaths.Add(_fishNetGeneratedPath.Replace(@"/", @"\"));
|
||||
fishNetPaths.Add(_fishNetGeneratedPath.Replace(@"\", @"/"));
|
||||
fishNetPaths.Add(_fishNetRuntimePath.Replace(@"/", @"\"));
|
||||
fishNetPaths.Add(_fishNetRuntimePath.Replace(@"\", @"/"));
|
||||
/* Find all network managers which use Single prefab linking
|
||||
* as well all network object prefabs. */
|
||||
foreach (string item in objectPaths)
|
||||
{
|
||||
//This will skip hidden unity types.
|
||||
if (!item.EndsWith(".asset"))
|
||||
continue;
|
||||
if (fishNetAssembly)
|
||||
{
|
||||
bool found = false;
|
||||
foreach (string path in fishNetPaths)
|
||||
{
|
||||
if (item.Contains(path))
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
continue;
|
||||
}
|
||||
UnityEngine.Object obj = AssetDatabase.LoadAssetAtPath(item, tType);
|
||||
if (obj != null && tType != null && obj.GetType() == tType)
|
||||
{
|
||||
results.Add(obj);
|
||||
if (breakOnFirst)
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
11
Assets/FishNet/Runtime/Editor/Finding.cs.meta
Normal file
11
Assets/FishNet/Runtime/Editor/Finding.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b777233d19062274f9eec6a982d8ff37
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
51
Assets/FishNet/Runtime/Editor/PlayModeTracker.cs
Normal file
51
Assets/FishNet/Runtime/Editor/PlayModeTracker.cs
Normal file
@ -0,0 +1,51 @@
|
||||
#if UNITY_EDITOR
|
||||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FishNet.Editing
|
||||
{
|
||||
|
||||
[InitializeOnLoad]
|
||||
public class PlayModeTracker
|
||||
{
|
||||
static PlayModeTracker()
|
||||
{
|
||||
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
|
||||
}
|
||||
|
||||
~PlayModeTracker()
|
||||
{
|
||||
EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DateTime when the editor last exited playmode.
|
||||
/// </summary>
|
||||
private static DateTime _quitTime = DateTime.MaxValue;
|
||||
|
||||
/// <summary>
|
||||
/// True if the editor has exited playmode within past.
|
||||
/// </summary>
|
||||
/// <param name="past"></param>
|
||||
/// <returns></returns>
|
||||
internal static bool QuitRecently(float past)
|
||||
{
|
||||
past *= 1000;
|
||||
return ((DateTime.Now - _quitTime).TotalMilliseconds < past);
|
||||
}
|
||||
|
||||
private static void OnPlayModeStateChanged(PlayModeStateChange stateChange)
|
||||
{
|
||||
switch (stateChange)
|
||||
{
|
||||
case (PlayModeStateChange.ExitingPlayMode):
|
||||
_quitTime = DateTime.Now;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
11
Assets/FishNet/Runtime/Editor/PlayModeTracker.cs.meta
Normal file
11
Assets/FishNet/Runtime/Editor/PlayModeTracker.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d4a1d20c6a03a524ab21c7aebed106d0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3da51acfc7419a544887f9eab923b0a7
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,619 @@
|
||||
#if UNITY_EDITOR
|
||||
|
||||
using FishNet.Configuring;
|
||||
using FishNet.Managing.Object;
|
||||
using FishNet.Object;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityDebug = UnityEngine.Debug;
|
||||
|
||||
namespace FishNet.Editing.PrefabCollectionGenerator
|
||||
{
|
||||
internal sealed class Generator : AssetPostprocessor
|
||||
{
|
||||
public Generator()
|
||||
{
|
||||
if (!_subscribed)
|
||||
{
|
||||
_subscribed = true;
|
||||
EditorApplication.update += OnEditorUpdate;
|
||||
}
|
||||
}
|
||||
~Generator()
|
||||
{
|
||||
if (_subscribed)
|
||||
{
|
||||
_subscribed = false;
|
||||
EditorApplication.update -= OnEditorUpdate;
|
||||
}
|
||||
}
|
||||
|
||||
#region Types.
|
||||
private struct SpecifiedFolder
|
||||
{
|
||||
public string Path;
|
||||
public bool Recursive;
|
||||
|
||||
public SpecifiedFolder(string path, bool recursive)
|
||||
{
|
||||
Path = path;
|
||||
Recursive = recursive;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public.
|
||||
/// <summary>
|
||||
/// True to ignore post process changes.
|
||||
/// </summary>
|
||||
public static bool IgnorePostProcess = false;
|
||||
#endregion
|
||||
|
||||
#region Private.
|
||||
/// <summary>
|
||||
/// Last asset to import when there was only one imported asset and no other changes.
|
||||
/// </summary>
|
||||
private static string _lastSingleImportedAsset = string.Empty;
|
||||
/// <summary>
|
||||
/// Cached DefaultPrefabObjects reference.
|
||||
/// </summary>
|
||||
private static DefaultPrefabObjects _cachedDefaultPrefabs;
|
||||
/// <summary>
|
||||
/// True to refresh prefabs next update.
|
||||
/// </summary>
|
||||
private static bool _retryRefreshDefaultPrefabs;
|
||||
/// <summary>
|
||||
/// True if already subscribed to EditorApplication.Update.
|
||||
/// </summary>
|
||||
private static bool _subscribed;
|
||||
/// <summary>
|
||||
/// True if ran once since editor started.
|
||||
/// </summary>
|
||||
[System.NonSerialized]
|
||||
private static bool _ranOnce;
|
||||
/// <summary>
|
||||
/// Last paths of updated nobs during a changed update.
|
||||
/// </summary>
|
||||
[System.NonSerialized]
|
||||
private static List<string> _lastUpdatedNamePaths = new List<string>();
|
||||
/// <summary>
|
||||
/// Last frame changed was updated.
|
||||
/// </summary>
|
||||
[System.NonSerialized]
|
||||
private static int _lastUpdatedFrame = -1;
|
||||
/// <summary>
|
||||
/// Length of assets strings during the last update.
|
||||
/// </summary>
|
||||
[System.NonSerialized]
|
||||
private static int _lastUpdatedLengths = -1;
|
||||
#endregion
|
||||
|
||||
public static string[] GetPrefabFiles(string startingPath, HashSet<string> excludedPaths, bool recursive)
|
||||
{
|
||||
//Opportunity to exit early if there are no excluded paths.
|
||||
if (excludedPaths.Count == 0)
|
||||
{
|
||||
string[] strResults = Directory.GetFiles(startingPath, "*.prefab", SearchOption.AllDirectories);
|
||||
return strResults;
|
||||
}
|
||||
//starting path is excluded.
|
||||
if (excludedPaths.Contains(startingPath))
|
||||
return new string[0];
|
||||
|
||||
//Folders remaining to be iterated.
|
||||
List<string> enumeratedCollection = new List<string>() { startingPath };
|
||||
//Only check other directories if recursive.
|
||||
if (recursive)
|
||||
{
|
||||
//Find all folders which aren't excluded.
|
||||
for (int i = 0; i < enumeratedCollection.Count; i++)
|
||||
{
|
||||
string[] allFolders = Directory.GetDirectories(enumeratedCollection[i], "*", SearchOption.TopDirectoryOnly);
|
||||
for (int z = 0; z < allFolders.Length; z++)
|
||||
{
|
||||
string current = allFolders[z];
|
||||
//Not excluded.
|
||||
if (!excludedPaths.Contains(current))
|
||||
enumeratedCollection.Add(current);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Valid prefab files.
|
||||
List<string> results = new List<string>();
|
||||
//Build files from folders.
|
||||
int count = enumeratedCollection.Count;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
string[] r = Directory.GetFiles(enumeratedCollection[i], "*.prefab", SearchOption.TopDirectoryOnly);
|
||||
results.AddRange(r);
|
||||
}
|
||||
|
||||
return results.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes paths which may overlap each other, such as sub directories.
|
||||
/// </summary>
|
||||
private static void RemoveOverlappingFolders(List<SpecifiedFolder> folders)
|
||||
{
|
||||
for (int z = 0; z < folders.Count; z++)
|
||||
{
|
||||
for (int i = 0; i < folders.Count; i++)
|
||||
{
|
||||
//Do not check against self.
|
||||
if (i == z)
|
||||
continue;
|
||||
|
||||
//Duplicate.
|
||||
if (folders[z].Path.Equals(folders[i].Path, System.StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
UnityDebug.LogError($"The same path is specified multiple times in the DefaultPrefabGenerator settings. Remove the duplicate to clear this error.");
|
||||
folders.RemoveAt(i);
|
||||
break;
|
||||
}
|
||||
|
||||
/* We are checking if i can be within
|
||||
* z. This is only possible if i is longer
|
||||
* than z. */
|
||||
if (folders[i].Path.Length < folders[z].Path.Length)
|
||||
continue;
|
||||
/* Do not need to check if not recursive.
|
||||
* Only recursive needs to be checked because
|
||||
* a shorter recursive path could contain
|
||||
* a longer path. */
|
||||
if (!folders[z].Recursive)
|
||||
continue;
|
||||
|
||||
//Compare paths.
|
||||
string zPath = GetPathWithSeparator(folders[z].Path);
|
||||
string iPath = zPath.Substring(0, zPath.Length);
|
||||
//If paths match.
|
||||
if (iPath.Equals(zPath, System.StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
UnityDebug.LogError($"Path {folders[i].Path} is included within recursive path {folders[z].Path}. Remove path {folders[i].Path} to clear this error.");
|
||||
folders.RemoveAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string GetPathWithSeparator(string txt)
|
||||
{
|
||||
return txt.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)
|
||||
+ Path.DirectorySeparatorChar;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a message to attach to logs if objects were dirtied.
|
||||
/// </summary>
|
||||
private static string GetDirtiedMessage(PrefabGeneratorConfigurations settings, bool dirtied)
|
||||
{
|
||||
if (!settings.SaveChanges && dirtied)
|
||||
return " One or more NetworkObjects were dirtied. Please save your project.";
|
||||
else
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates prefabs by using only changed information.
|
||||
/// </summary>
|
||||
public static void GenerateChanged(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths, PrefabGeneratorConfigurations settings = null)
|
||||
{
|
||||
if (settings == null)
|
||||
settings = Configuration.Configurations.PrefabGenerator;
|
||||
if (!settings.Enabled)
|
||||
return;
|
||||
|
||||
bool log = settings.LogToConsole;
|
||||
Stopwatch sw = (log) ? Stopwatch.StartNew() : null;
|
||||
|
||||
DefaultPrefabObjects prefabCollection = GetDefaultPrefabObjects(settings);
|
||||
//No need to error if nto found, GetDefaultPrefabObjects will.
|
||||
if (prefabCollection == null)
|
||||
return;
|
||||
|
||||
int assetsLength = (importedAssets.Length + deletedAssets.Length + movedAssets.Length + movedFromAssetPaths.Length);
|
||||
List<string> changedNobPaths = new List<string>();
|
||||
|
||||
System.Type goType = typeof(UnityEngine.GameObject);
|
||||
IterateAssetCollection(importedAssets);
|
||||
IterateAssetCollection(movedAssets);
|
||||
|
||||
//True if dirtied by changes.
|
||||
bool dirtied;
|
||||
//First remove null entries.
|
||||
int startCount = prefabCollection.GetObjectCount();
|
||||
prefabCollection.RemoveNull();
|
||||
dirtied = (prefabCollection.GetObjectCount() != startCount);
|
||||
//First index which new objects will be added to.
|
||||
int firstAddIndex = (prefabCollection.GetObjectCount() - 1);
|
||||
|
||||
//Iterates strings adding prefabs to collection.
|
||||
void IterateAssetCollection(string[] c)
|
||||
{
|
||||
foreach (string item in c)
|
||||
{
|
||||
System.Type assetType = AssetDatabase.GetMainAssetTypeAtPath(item);
|
||||
if (assetType != goType)
|
||||
continue;
|
||||
|
||||
NetworkObject nob = AssetDatabase.LoadAssetAtPath<NetworkObject>(item);
|
||||
if (nob != null)
|
||||
{
|
||||
changedNobPaths.Add(item);
|
||||
prefabCollection.AddObject(nob, true);
|
||||
dirtied = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//To prevent out of range.
|
||||
if (firstAddIndex < 0 || firstAddIndex >= prefabCollection.GetObjectCount())
|
||||
firstAddIndex = 0;
|
||||
dirtied |= prefabCollection.SetAssetPathHashes(firstAddIndex);
|
||||
|
||||
if (log && dirtied)
|
||||
UnityDebug.Log($"Default prefab generator updated prefabs in {sw.ElapsedMilliseconds}ms.{GetDirtiedMessage(settings, dirtied)}");
|
||||
|
||||
//Check for redundancy.
|
||||
int frameCount = Time.frameCount;
|
||||
int changedCount = changedNobPaths.Count;
|
||||
if (frameCount == _lastUpdatedFrame && assetsLength == _lastUpdatedLengths && (changedCount == _lastUpdatedNamePaths.Count) && changedCount > 0)
|
||||
{
|
||||
bool allMatch = true;
|
||||
for (int i = 0; i < changedCount; i++)
|
||||
{
|
||||
if (changedNobPaths[i] != _lastUpdatedNamePaths[i])
|
||||
{
|
||||
allMatch = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the import results are the same as the last attempt, on the same frame
|
||||
* then there is likely an issue saving the assets. */
|
||||
if (allMatch)
|
||||
{
|
||||
//Unset dirtied to prevent a save.
|
||||
dirtied = false;
|
||||
//Log this no matter what, it's critical.
|
||||
UnityDebug.LogError($"Default prefab generator had a problem saving one or more assets. " +
|
||||
$"This usually occurs when the assets cannot be saved due to missing scripts or serialization errors. " +
|
||||
$"Please see above any prefabs which could not save any make corrections.");
|
||||
}
|
||||
|
||||
}
|
||||
//Set last values.
|
||||
_lastUpdatedFrame = Time.frameCount;
|
||||
_lastUpdatedNamePaths = changedNobPaths;
|
||||
_lastUpdatedLengths = assetsLength;
|
||||
|
||||
EditorUtility.SetDirty(prefabCollection);
|
||||
if (dirtied && settings.SaveChanges)
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates prefabs by iterating all files within settings parameters.
|
||||
/// </summary>
|
||||
public static void GenerateFull(PrefabGeneratorConfigurations settings = null, bool forced = false)
|
||||
{
|
||||
if (settings == null)
|
||||
settings = Configuration.Configurations.PrefabGenerator;
|
||||
if (!forced && !settings.Enabled)
|
||||
return;
|
||||
bool log = settings.LogToConsole;
|
||||
|
||||
Stopwatch sw = (log) ? Stopwatch.StartNew() : null;
|
||||
List<NetworkObject> foundNobs = new List<NetworkObject>();
|
||||
HashSet<string> excludedPaths = new HashSet<string>(settings.ExcludedFolders);
|
||||
|
||||
//If searching the entire project.
|
||||
if (settings.SearchScope == (int)SearchScopeType.EntireProject)
|
||||
{
|
||||
foreach (string path in GetPrefabFiles("Assets", excludedPaths, true))
|
||||
{
|
||||
NetworkObject nob = AssetDatabase.LoadAssetAtPath<NetworkObject>(path);
|
||||
if (nob != null)
|
||||
foundNobs.Add(nob);
|
||||
}
|
||||
}
|
||||
//Specific folders.
|
||||
else if (settings.SearchScope == (int)SearchScopeType.SpecificFolders)
|
||||
{
|
||||
List<SpecifiedFolder> folders = GetSpecifiedFolders(settings.IncludedFolders.ToList());
|
||||
RemoveOverlappingFolders(folders);
|
||||
|
||||
foreach (SpecifiedFolder sf in folders)
|
||||
{
|
||||
//If specified folder doesn't exist then continue.
|
||||
if (!Directory.Exists(sf.Path))
|
||||
continue;
|
||||
|
||||
foreach (string path in GetPrefabFiles(sf.Path, excludedPaths, sf.Recursive))
|
||||
{
|
||||
NetworkObject nob = AssetDatabase.LoadAssetAtPath<NetworkObject>(path);
|
||||
if (nob != null)
|
||||
foundNobs.Add(nob);
|
||||
}
|
||||
}
|
||||
}
|
||||
//Unhandled.
|
||||
else
|
||||
{
|
||||
UnityDebug.LogError($"{settings.SearchScope} is not handled; default prefabs will not generator properly.");
|
||||
}
|
||||
|
||||
DefaultPrefabObjects prefabCollection = GetDefaultPrefabObjects(settings);
|
||||
//No need to error if not found, GetDefaultPrefabObjects will throw.
|
||||
if (prefabCollection == null)
|
||||
return;
|
||||
|
||||
//Clear and add built list.
|
||||
prefabCollection.Clear();
|
||||
prefabCollection.AddObjects(foundNobs, false);
|
||||
bool dirtied = prefabCollection.SetAssetPathHashes(0);
|
||||
|
||||
int newCount = prefabCollection.GetObjectCount();
|
||||
if (log)
|
||||
{
|
||||
string dirtiedMessage = (newCount > 0) ? GetDirtiedMessage(settings, dirtied) : string.Empty;
|
||||
UnityDebug.Log($"Default prefab generator found {newCount} prefabs in {sw.ElapsedMilliseconds}ms.{dirtiedMessage}");
|
||||
}
|
||||
//Only set dirty if and save if prefabs were found.
|
||||
if (newCount > 0)
|
||||
{
|
||||
EditorUtility.SetDirty(prefabCollection);
|
||||
if (settings.SaveChanges)
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Iterates folders building them into SpecifiedFolders.
|
||||
/// </summary>
|
||||
private static List<SpecifiedFolder> GetSpecifiedFolders(List<string> folders)
|
||||
{
|
||||
List<SpecifiedFolder> results = new List<SpecifiedFolder>();
|
||||
//Remove astericks.
|
||||
foreach (string path in folders)
|
||||
{
|
||||
int pLength = path.Length;
|
||||
if (pLength == 0)
|
||||
continue;
|
||||
|
||||
bool recursive;
|
||||
string p;
|
||||
//If the last character indicates resursive.
|
||||
if (path.Substring(pLength - 1, 1) == "*")
|
||||
{
|
||||
p = path.Substring(0, pLength - 1);
|
||||
recursive = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
p = path;
|
||||
recursive = false;
|
||||
}
|
||||
|
||||
results.Add(new SpecifiedFolder(p, recursive));
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the DefaultPrefabObjects file.
|
||||
/// </summary>
|
||||
private static DefaultPrefabObjects GetDefaultPrefabObjects(PrefabGeneratorConfigurations settings = null)
|
||||
{
|
||||
if (settings == null)
|
||||
settings = Configuration.Configurations.PrefabGenerator;
|
||||
|
||||
//Load the prefab collection
|
||||
string defaultPrefabsPath = settings.DefaultPrefabObjectsPath;
|
||||
defaultPrefabsPath = defaultPrefabsPath.Replace(@"\", "/");
|
||||
string fullDefaultPrefabsPath = (defaultPrefabsPath.Length > 0) ? Path.GetFullPath(defaultPrefabsPath) : string.Empty;
|
||||
|
||||
//If cached prefabs is not the same path as assetPath.
|
||||
if (_cachedDefaultPrefabs != null)
|
||||
{
|
||||
string unityAssetPath = AssetDatabase.GetAssetPath(_cachedDefaultPrefabs);
|
||||
string fullCachedPath = (unityAssetPath.Length > 0) ? Path.GetFullPath(unityAssetPath) : string.Empty;
|
||||
if (fullCachedPath != fullDefaultPrefabsPath)
|
||||
_cachedDefaultPrefabs = null;
|
||||
}
|
||||
|
||||
//If cached is null try to get it.
|
||||
if (_cachedDefaultPrefabs == null)
|
||||
{
|
||||
//Only try to load it if file exist.
|
||||
if (File.Exists(fullDefaultPrefabsPath))
|
||||
{
|
||||
_cachedDefaultPrefabs = AssetDatabase.LoadAssetAtPath<DefaultPrefabObjects>(defaultPrefabsPath);
|
||||
if (_cachedDefaultPrefabs == null)
|
||||
{
|
||||
//If already retried then throw an error.
|
||||
if (_retryRefreshDefaultPrefabs)
|
||||
{
|
||||
UnityDebug.LogError("DefaultPrefabObjects file exists but it could not be loaded by Unity. Use the Fish-Networking menu to Refresh Default Prefabs.");
|
||||
}
|
||||
else
|
||||
{
|
||||
UnityDebug.Log("DefaultPrefabObjects file exists but it could not be loaded by Unity. Trying to reload the file next frame.");
|
||||
_retryRefreshDefaultPrefabs = true;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_cachedDefaultPrefabs == null)
|
||||
{
|
||||
string fullPath = Path.GetFullPath(defaultPrefabsPath);
|
||||
UnityDebug.Log($"Creating a new DefaultPrefabsObject at {fullPath}.");
|
||||
string directory = Path.GetDirectoryName(fullPath);
|
||||
|
||||
if (!Directory.Exists(directory))
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
_cachedDefaultPrefabs = ScriptableObject.CreateInstance<DefaultPrefabObjects>();
|
||||
AssetDatabase.CreateAsset(_cachedDefaultPrefabs, defaultPrefabsPath);
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
|
||||
if (_cachedDefaultPrefabs != null && _retryRefreshDefaultPrefabs)
|
||||
UnityDebug.Log("DefaultPrefabObjects found on the second iteration.");
|
||||
return _cachedDefaultPrefabs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called every frame the editor updates.
|
||||
/// </summary>
|
||||
private static void OnEditorUpdate()
|
||||
{
|
||||
if (!_retryRefreshDefaultPrefabs)
|
||||
return;
|
||||
|
||||
GenerateFull();
|
||||
_retryRefreshDefaultPrefabs = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by Unity when assets are modified.
|
||||
/// </summary>
|
||||
private static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
|
||||
{
|
||||
if (Application.isPlaying)
|
||||
return;
|
||||
//If retrying next frame don't bother updating, next frame will do a full refresh.
|
||||
if (_retryRefreshDefaultPrefabs)
|
||||
return;
|
||||
//Post process is being ignored. Could be temporary or user has disabled this feature.
|
||||
if (IgnorePostProcess)
|
||||
return;
|
||||
/* Don't iterate if updating or compiling as that could cause an infinite loop
|
||||
* due to the prefabs being generated during an update, which causes the update
|
||||
* to start over, which causes the generator to run again, which... you get the idea. */
|
||||
if (EditorApplication.isCompiling)
|
||||
return;
|
||||
|
||||
DefaultPrefabObjects prefabCollection = GetDefaultPrefabObjects();
|
||||
if (prefabCollection == null)
|
||||
return;
|
||||
PrefabGeneratorConfigurations settings = Configuration.Configurations.PrefabGenerator;
|
||||
|
||||
if (prefabCollection.GetObjectCount() == 0)
|
||||
{
|
||||
//If there are no prefabs then do a full rebuild. Odds of there being none are pretty much nill.
|
||||
GenerateFull(settings);
|
||||
}
|
||||
else
|
||||
{
|
||||
int totalChanges = importedAssets.Length + deletedAssets.Length + movedAssets.Length + movedFromAssetPaths.Length;
|
||||
//Nothing has changed. This shouldn't occur but unity is funny so we're going to check anyway.
|
||||
if (totalChanges == 0)
|
||||
return;
|
||||
|
||||
//normalizes path.
|
||||
string dpoPath = Path.GetFullPath(settings.DefaultPrefabObjectsPath);
|
||||
//If total changes is 1 and the only changed file is the default prefab collection then do nothing.
|
||||
if (totalChanges == 1)
|
||||
{
|
||||
//Do not need to check movedFromAssetPaths because that's not possible for this check.
|
||||
if ((importedAssets.Length == 1 && Path.GetFullPath(importedAssets[0]) == dpoPath)
|
||||
|| (deletedAssets.Length == 1 && Path.GetFullPath(deletedAssets[0]) == dpoPath)
|
||||
|| (movedAssets.Length == 1 && Path.GetFullPath(movedAssets[0]) == dpoPath))
|
||||
return;
|
||||
|
||||
/* If the only change is an import then check if the imported file
|
||||
* is the same as the last, and if so check into returning early.
|
||||
* For some reason occasionally when files are saved unity runs postprocess
|
||||
* multiple times on the same file. */
|
||||
string imported = (importedAssets.Length == 1) ? importedAssets[0] : null;
|
||||
if (imported != null && imported == _lastSingleImportedAsset)
|
||||
{
|
||||
//If here then the file is the same. Make sure it's already in the collection before returning.
|
||||
System.Type assetType = AssetDatabase.GetMainAssetTypeAtPath(imported);
|
||||
//Not a gameObject, no reason to continue.
|
||||
if (assetType != typeof(GameObject))
|
||||
return;
|
||||
|
||||
NetworkObject nob = AssetDatabase.LoadAssetAtPath<NetworkObject>(imported);
|
||||
//If is a networked object.
|
||||
if (nob != null)
|
||||
{
|
||||
//Already added!
|
||||
if (prefabCollection.Prefabs.Contains(nob))
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (imported != null)
|
||||
{
|
||||
_lastSingleImportedAsset = imported;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool fullRebuild = settings.FullRebuild;
|
||||
/* If updating FN. This needs to be done a better way.
|
||||
* Parsing the actual version file would be better.
|
||||
* I'll get to it next release. */
|
||||
if (!_ranOnce)
|
||||
{
|
||||
_ranOnce = true;
|
||||
fullRebuild = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckForVersionFile(importedAssets);
|
||||
CheckForVersionFile(deletedAssets);
|
||||
CheckForVersionFile(movedAssets);
|
||||
CheckForVersionFile(movedFromAssetPaths);
|
||||
}
|
||||
|
||||
/* See if any of the changed files are the version file.
|
||||
* A new version file suggests an update. Granted, this could occur if
|
||||
* other assets imported a new version file as well but better
|
||||
* safe than sorry. */
|
||||
void CheckForVersionFile(string[] arr)
|
||||
{
|
||||
string targetText = "VERSION.txt".ToLower();
|
||||
int targetLength = targetText.Length;
|
||||
|
||||
for (int i = 0; i < arr.Length; i++)
|
||||
{
|
||||
string item = arr[i];
|
||||
int itemLength = item.Length;
|
||||
if (itemLength < targetLength)
|
||||
continue;
|
||||
|
||||
item = item.ToLower();
|
||||
int startIndex = (itemLength - targetLength);
|
||||
if (item.Substring(startIndex, targetLength) == targetText)
|
||||
{
|
||||
fullRebuild = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fullRebuild)
|
||||
GenerateFull(settings);
|
||||
else
|
||||
GenerateChanged(importedAssets, deletedAssets, movedAssets, movedFromAssetPaths, settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 68e990388e202d54aa0fe9e7aa8cc716
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,103 @@
|
||||
#if UNITY_EDITOR
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FishNet.Editing.PrefabCollectionGenerator
|
||||
{
|
||||
internal sealed class PrefabCollectionGeneratorConfigurationsz
|
||||
{
|
||||
#region Types.
|
||||
public enum SearchScopeType : byte
|
||||
{
|
||||
EntireProject = 0,
|
||||
SpecificFolders = 1
|
||||
}
|
||||
#endregion
|
||||
|
||||
//#region Public.
|
||||
///// <summary>
|
||||
///// True if prefab generation is enabled.
|
||||
///// </summary>
|
||||
//public bool Enabled;
|
||||
///// <summary>
|
||||
///// True to rebuild all prefabs during any change. False to only check changed prefabs.
|
||||
///// </summary>
|
||||
//public bool FullRebuild;
|
||||
///// <summary>
|
||||
///// True to log results to console.
|
||||
///// </summary>
|
||||
//public bool LogToConsole;
|
||||
///// <summary>
|
||||
///// True to automatically save assets when default prefabs change.
|
||||
///// </summary>
|
||||
//public bool SaveChanges;
|
||||
///// <summary>
|
||||
///// Path where prefabs file is created.
|
||||
///// </summary>
|
||||
//public string AssetPath;
|
||||
///// <summary>
|
||||
///// How to search for files.
|
||||
///// </summary>
|
||||
//public SearchScopeType SearchScope = SearchScopeType.EntireProject;
|
||||
///// <summary>
|
||||
///// Folders to exclude when using SearchScopeType.SpecificFolders.
|
||||
///// </summary>
|
||||
//public List<string> ExcludedFolders = new List<string>();
|
||||
///// <summary>
|
||||
///// Folders to include when using SearchScopeType.SpecificFolders.
|
||||
///// </summary>
|
||||
//public List<string> IncludedFolders = new List<string>();
|
||||
//#endregion
|
||||
|
||||
//#region Private.
|
||||
///// <summary>
|
||||
///// Library folder for project. Presumably where files are saved, but this is changing. This is going away in favor of FN config. //fnconfig.
|
||||
///// </summary>
|
||||
//private static string DirectoryPath => Path.Combine(Path.GetDirectoryName(Application.dataPath), "Library");
|
||||
///// <summary>
|
||||
///// Full path of settings file. This is going away in favor of FN config. //fnconfig.
|
||||
///// </summary>
|
||||
//private static string FilePath => Path.Combine(DirectoryPath, $"FishNet.Runtime.Editor.PrefabObjects.Generation.{nameof(Settings)}.json");
|
||||
// #endregion
|
||||
|
||||
// public Settings()
|
||||
//{
|
||||
// Enabled = true;
|
||||
// LogToConsole = true;
|
||||
// FullRebuild = false;
|
||||
// SaveChanges = true;
|
||||
// SearchScope = SearchScopeType.EntireProject;
|
||||
|
||||
// AssetPath = $"Assets{Path.DirectorySeparatorChar}FishNet{Path.DirectorySeparatorChar}Runtime{Path.DirectorySeparatorChar}DefaultPrefabObjects.asset";
|
||||
//}
|
||||
|
||||
//public void Save()
|
||||
//{
|
||||
// //Create save folder if it doesn't exist. This is going away in favor of FN config. //fnconfig.
|
||||
// if (!Directory.Exists(DirectoryPath))
|
||||
// Directory.CreateDirectory(DirectoryPath);
|
||||
|
||||
// File.WriteAllText(FilePath, JsonUtility.ToJson(this));
|
||||
//}
|
||||
|
||||
//public static Settings Load()
|
||||
//{
|
||||
// try
|
||||
// {
|
||||
// if (File.Exists(FilePath))
|
||||
// return JsonUtility.FromJson<Settings>(File.ReadAllText(FilePath));
|
||||
// }
|
||||
// catch (Exception ex)
|
||||
// {
|
||||
// Debug.LogError($"An error has occurred when loading the prefab collection generator settings: {ex}");
|
||||
// }
|
||||
|
||||
// return new Settings();
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0fa5ae5e1c43e004c87577ab53180f70
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,238 @@
|
||||
#if UNITY_EDITOR
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
using UnitySettingsProviderAttribute = UnityEditor.SettingsProviderAttribute;
|
||||
using UnitySettingsProvider = UnityEditor.SettingsProvider;
|
||||
using FishNet.Configuring;
|
||||
using System.Linq;
|
||||
|
||||
namespace FishNet.Editing.PrefabCollectionGenerator
|
||||
{
|
||||
internal static class SettingsProvider
|
||||
{
|
||||
private static readonly Regex SlashRegex = new Regex(@"[\\//]");
|
||||
|
||||
private static PrefabGeneratorConfigurations _settings;
|
||||
|
||||
private static GUIContent _folderIcon;
|
||||
private static GUIContent _deleteIcon;
|
||||
|
||||
private static Vector2 _scrollVector;
|
||||
|
||||
private static bool _showFolders;
|
||||
|
||||
[UnitySettingsProvider]
|
||||
private static UnitySettingsProvider Create()
|
||||
{
|
||||
return new UnitySettingsProvider("Project/Fish-Networking/Prefab Objects Generator", SettingsScope.Project)
|
||||
{
|
||||
label = "Prefab Objects Generator",
|
||||
|
||||
guiHandler = OnGUI,
|
||||
|
||||
keywords = new string[]
|
||||
{
|
||||
"Fish",
|
||||
"Networking",
|
||||
"Prefab",
|
||||
"Objects",
|
||||
"Generator",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private static void OnGUI(string searchContext)
|
||||
{
|
||||
if (_settings == null)
|
||||
_settings = Configuration.Configurations.PrefabGenerator;
|
||||
if (_folderIcon == null)
|
||||
_folderIcon = EditorGUIUtility.IconContent("d_FolderOpened Icon");
|
||||
if (_deleteIcon == null)
|
||||
_deleteIcon = EditorGUIUtility.IconContent("P4_DeletedLocal");
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
GUIStyle scrollViewStyle = new GUIStyle()
|
||||
{
|
||||
padding = new RectOffset(10, 10, 10, 10),
|
||||
};
|
||||
|
||||
_scrollVector = EditorGUILayout.BeginScrollView(_scrollVector, scrollViewStyle);
|
||||
|
||||
_settings.Enabled = EditorGUILayout.Toggle(ObjectNames.NicifyVariableName(nameof(_settings.Enabled)), _settings.Enabled);
|
||||
_settings.LogToConsole = EditorGUILayout.Toggle(ObjectNames.NicifyVariableName(nameof(_settings.LogToConsole)), _settings.LogToConsole);
|
||||
_settings.FullRebuild = EditorGUILayout.Toggle(ObjectNames.NicifyVariableName(nameof(_settings.FullRebuild)), _settings.FullRebuild);
|
||||
_settings.SaveChanges = EditorGUILayout.Toggle(ObjectNames.NicifyVariableName(nameof(_settings.SaveChanges)), _settings.SaveChanges);
|
||||
|
||||
GUILayoutOption iconWidthConstraint = GUILayout.MaxWidth(32.0f);
|
||||
GUILayoutOption iconHeightConstraint = GUILayout.MaxHeight(EditorGUIUtility.singleLineHeight);
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
string oldAssetPath = _settings.DefaultPrefabObjectsPath;
|
||||
string newAssetPath = EditorGUILayout.DelayedTextField(ObjectNames.NicifyVariableName(nameof(_settings.DefaultPrefabObjectsPath)), oldAssetPath);
|
||||
|
||||
if (GUILayout.Button(_folderIcon, iconWidthConstraint, iconHeightConstraint))
|
||||
{
|
||||
if (TrySaveFilePathInsideAssetsFolder(null, Application.dataPath, "DefaultPrefabObjects", "asset", out string result))
|
||||
newAssetPath = result;
|
||||
else
|
||||
EditorWindow.focusedWindow.ShowNotification(new GUIContent($"{ObjectNames.NicifyVariableName(nameof(_settings.DefaultPrefabObjectsPath))} must be inside the Assets folder."));
|
||||
}
|
||||
|
||||
if (!newAssetPath.Equals(oldAssetPath, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (newAssetPath.StartsWith($"Assets{Path.DirectorySeparatorChar}", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (File.Exists(newAssetPath))
|
||||
{
|
||||
EditorWindow.focusedWindow.ShowNotification(new GUIContent("Another asset already exists at the new path."));
|
||||
}
|
||||
else
|
||||
{
|
||||
Generator.IgnorePostProcess = true;
|
||||
|
||||
if (File.Exists(oldAssetPath))
|
||||
AssetDatabase.MoveAsset(oldAssetPath, newAssetPath);
|
||||
_settings.DefaultPrefabObjectsPath = newAssetPath;
|
||||
|
||||
Generator.IgnorePostProcess = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorWindow.focusedWindow.ShowNotification(new GUIContent($"{ObjectNames.NicifyVariableName(nameof(_settings.DefaultPrefabObjectsPath))} must be inside the Assets folder."));
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
int currentSearchScope = _settings.SearchScope;
|
||||
SearchScopeType searchScopeType = (SearchScopeType)EditorGUILayout.EnumPopup(ValueToSearchScope(_settings.SearchScope));
|
||||
_settings.SearchScope = (int)searchScopeType;
|
||||
SearchScopeType ValueToSearchScope(int value) => (SearchScopeType)value;
|
||||
if (_settings.SearchScope == (int)SearchScopeType.EntireProject)
|
||||
{
|
||||
EditorGUILayout.HelpBox("Searching the entire project for prefabs can become very slow. Consider switching the search scope to specific folders instead.", MessageType.Warning);
|
||||
|
||||
if (GUILayout.Button("Switch"))
|
||||
_settings.SearchScope = (int)SearchScopeType.SpecificFolders;
|
||||
}
|
||||
//If search scope changed then update prefabs.
|
||||
if (currentSearchScope != _settings.SearchScope && (SearchScopeType)_settings.SearchScope == SearchScopeType.EntireProject)
|
||||
Generator.GenerateFull();
|
||||
|
||||
List<string> folders = null;
|
||||
string foldersName = null;
|
||||
|
||||
if (_settings.SearchScope == (int)SearchScopeType.EntireProject)
|
||||
{
|
||||
folders = _settings.ExcludedFolders;
|
||||
foldersName = ObjectNames.NicifyVariableName(nameof(_settings.ExcludedFolders));
|
||||
}
|
||||
else if (_settings.SearchScope == (int)SearchScopeType.SpecificFolders)
|
||||
{
|
||||
folders = _settings.IncludedFolders;
|
||||
foldersName = ObjectNames.NicifyVariableName(nameof(_settings.IncludedFolders));
|
||||
}
|
||||
|
||||
string folderName = foldersName.Substring(0, foldersName.Length - 1);
|
||||
|
||||
if ((_showFolders = EditorGUILayout.Foldout(_showFolders, $"{foldersName} ({folders.Count})")) && folders != null)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
|
||||
for (int i = 0; i < folders.Count; i++)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
string oldFolder = folders[i];
|
||||
string newFolder = SlashRegex.Replace(EditorGUILayout.DelayedTextField(oldFolder), Path.DirectorySeparatorChar.ToString());
|
||||
if (!newFolder.Equals(oldFolder, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (newFolder.StartsWith($"Assets{Path.DirectorySeparatorChar}", StringComparison.OrdinalIgnoreCase))
|
||||
folders[i] = newFolder;
|
||||
else
|
||||
EditorWindow.focusedWindow.ShowNotification(new GUIContent($"{folderName} must be inside the Assets folder."));
|
||||
}
|
||||
|
||||
if (GUILayout.Button(_folderIcon, iconWidthConstraint, iconHeightConstraint))
|
||||
{
|
||||
if (TryOpenFolderPathInsideAssetsFolder(null, Application.dataPath, null, out string result))
|
||||
folders[i] = result;
|
||||
else
|
||||
EditorWindow.focusedWindow.ShowNotification(new GUIContent($"{folderName} must be inside the Assets folder."));
|
||||
}
|
||||
|
||||
if (GUILayout.Button(_deleteIcon, iconWidthConstraint, iconHeightConstraint)) folders.RemoveAt(i);
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
EditorGUI.indentLevel--;
|
||||
|
||||
if (_settings.SearchScope == (int)SearchScopeType.SpecificFolders) EditorGUILayout.HelpBox("You can include subfolders by appending an asterisk (*) to a path.", MessageType.None);
|
||||
|
||||
if (GUILayout.Button("Browse"))
|
||||
{
|
||||
if (TryOpenFolderPathInsideAssetsFolder(null, Application.dataPath, null, out string result))
|
||||
{
|
||||
folders.Add(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorWindow.focusedWindow.ShowNotification(new GUIContent($"{folderName} must be inside the Assets folder."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
Configuration.Configurations.Write(true);
|
||||
if (GUILayout.Button("Generate"))
|
||||
Generator.GenerateFull();
|
||||
|
||||
EditorGUILayout.HelpBox("Consider pressing 'Generate' after changing the settings.", MessageType.Info);
|
||||
|
||||
EditorGUILayout.EndScrollView();
|
||||
}
|
||||
|
||||
private static bool TrySaveFilePathInsideAssetsFolder(string title, string directory, string name, string extension, out string result)
|
||||
{
|
||||
result = null;
|
||||
|
||||
string selectedPath = EditorUtility.SaveFilePanel(title, directory, name, extension);
|
||||
|
||||
if (selectedPath.StartsWith(Application.dataPath, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
result = SlashRegex.Replace(selectedPath.Remove(0, Path.GetDirectoryName(Application.dataPath).Length + 1), Path.DirectorySeparatorChar.ToString());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool TryOpenFolderPathInsideAssetsFolder(string title, string folder, string name, out string result)
|
||||
{
|
||||
result = null;
|
||||
|
||||
string selectedPath = EditorUtility.OpenFolderPanel(title, folder, name);
|
||||
|
||||
if (selectedPath.StartsWith(Application.dataPath, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
result = SlashRegex.Replace(selectedPath.Remove(0, Path.GetDirectoryName(Application.dataPath).Length + 1), Path.DirectorySeparatorChar.ToString());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7451fcc5eeb5b89468ab2ce22f678b26
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
85
Assets/FishNet/Runtime/Editor/PrefabProcessor.cs
Normal file
85
Assets/FishNet/Runtime/Editor/PrefabProcessor.cs
Normal file
@ -0,0 +1,85 @@
|
||||
//#if UNITY_EDITOR
|
||||
//using FishNet.Managing.Object;
|
||||
//using FishNet.Object;
|
||||
//using UnityEditor;
|
||||
//using UnityEngine;
|
||||
|
||||
//namespace FishNet.Editing
|
||||
//{
|
||||
// internal class PrefabProcessor : AssetPostprocessor
|
||||
// {
|
||||
// #region Private.
|
||||
// /// <summary>
|
||||
// /// ScriptableObject to store default prefabs.
|
||||
// /// </summary>
|
||||
// private static DefaultPrefabObjects _defaultPrefabs;
|
||||
// #endregion
|
||||
|
||||
// /// <summary>
|
||||
// /// Called after assets are created or imported.
|
||||
// /// </summary>
|
||||
// /// <param name="importedAssets"></param>
|
||||
// /// <param name="deletedAssets"></param>
|
||||
// /// <param name="movedAssets"></param>
|
||||
// /// <param name="movedFromAssetPaths"></param>
|
||||
//#if UNITY_2021_3_OR_NEWER
|
||||
// private static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths, bool didDomainReload)
|
||||
//#else
|
||||
// private static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
|
||||
//#endif
|
||||
// {
|
||||
|
||||
//#if UNITY_2021_3_OR_NEWER
|
||||
// if (didDomainReload)
|
||||
// return;
|
||||
//#endif
|
||||
// bool justPopulated;
|
||||
// if (_defaultPrefabs == null)
|
||||
// _defaultPrefabs = DefaultPrefabsFinder.GetDefaultPrefabsFile(out justPopulated);
|
||||
// else
|
||||
// justPopulated = DefaultPrefabsFinder.PopulateDefaultPrefabs();
|
||||
// //Not found.
|
||||
// if (_defaultPrefabs == null)
|
||||
// return;
|
||||
|
||||
// //True if null must be removed as well.
|
||||
// bool removeNull = (deletedAssets.Length > 0 || movedAssets.Length > 0 || movedFromAssetPaths.Length > 0);
|
||||
// if (removeNull)
|
||||
// _defaultPrefabs.RemoveNull();
|
||||
|
||||
// /* Only need to add new prefabs if not justPopulated.
|
||||
// * justPopulated would have already picked up the new prefabs. */
|
||||
// if (justPopulated)
|
||||
// return;
|
||||
|
||||
// System.Type goType = typeof(UnityEngine.GameObject);
|
||||
// foreach (string item in importedAssets)
|
||||
// {
|
||||
// System.Type assetType = AssetDatabase.GetMainAssetTypeAtPath(item);
|
||||
// if (assetType != goType)
|
||||
// continue;
|
||||
|
||||
// GameObject go = (GameObject)AssetDatabase.LoadAssetAtPath(item, typeof(GameObject));
|
||||
// //If is a gameobject.
|
||||
// if (go != null)
|
||||
// {
|
||||
|
||||
// NetworkObject nob;
|
||||
// //Not a network object.
|
||||
// if (!go.TryGetComponent<NetworkObject>(out nob))
|
||||
// continue;
|
||||
|
||||
// /* Check for duplicates because adding a component to a prefab will also call this function
|
||||
// * which will result in this function calling multiple times for the same object. */
|
||||
// _defaultPrefabs.AddObject(nob, true);
|
||||
// }
|
||||
// }
|
||||
|
||||
// EditorUtility.SetDirty(_defaultPrefabs);
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
//}
|
||||
|
||||
//#endif
|
11
Assets/FishNet/Runtime/Editor/PrefabProcessor.cs.meta
Normal file
11
Assets/FishNet/Runtime/Editor/PrefabProcessor.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f78656ace4bbad94288ff6238a2b518c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
74
Assets/FishNet/Runtime/Editor/ScriptingDefines.cs
Normal file
74
Assets/FishNet/Runtime/Editor/ScriptingDefines.cs
Normal file
@ -0,0 +1,74 @@
|
||||
#if UNITY_EDITOR
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FishNet
|
||||
{
|
||||
internal static class ScriptingDefines
|
||||
{
|
||||
[InitializeOnLoadMethod]
|
||||
public static void AddDefineSymbols()
|
||||
{
|
||||
string currentDefines = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup);
|
||||
/* Convert current defines into a hashset. This is so we can
|
||||
* determine if any of our defines were added. Only save playersettings
|
||||
* when a define is added. */
|
||||
HashSet<string> definesHs = new HashSet<string>();
|
||||
string[] currentArr = currentDefines.Split(';');
|
||||
//Add current defines into hs.
|
||||
foreach (string item in currentArr)
|
||||
definesHs.Add(item);
|
||||
|
||||
string proDefine = "FISHNET_PRO";
|
||||
string versionPrefix = "FISHNET_V";
|
||||
string thisVersion = $"{versionPrefix}3";
|
||||
string[] fishNetDefines = new string[]
|
||||
{
|
||||
"FISHNET",
|
||||
thisVersion,
|
||||
|
||||
};
|
||||
bool modified = false;
|
||||
//Now add FN defines.
|
||||
foreach (string item in fishNetDefines)
|
||||
modified |= definesHs.Add(item);
|
||||
|
||||
/* Remove pro define if not on pro. This might look a little
|
||||
* funny because the code below varies depending on if pro or not. */
|
||||
|
||||
#pragma warning disable CS0162 // Unreachable code detected
|
||||
modified |= definesHs.Remove(proDefine);
|
||||
#pragma warning restore CS0162 // Unreachable code detected
|
||||
|
||||
List<string> definesToRemove = new List<string>();
|
||||
int versionPrefixLength = versionPrefix.Length;
|
||||
//Remove old versions.
|
||||
foreach (string item in definesHs)
|
||||
{
|
||||
//Do not remove this version.
|
||||
if (item == thisVersion)
|
||||
continue;
|
||||
|
||||
//If length is possible to be a version prefix and is so then remove it.
|
||||
if (item.Length >= versionPrefixLength && item.Substring(0, versionPrefixLength) == versionPrefix)
|
||||
definesToRemove.Add(item);
|
||||
}
|
||||
|
||||
modified |= (definesToRemove.Count > 0);
|
||||
foreach (string item in definesToRemove)
|
||||
{
|
||||
definesHs.Remove(item);
|
||||
Debug.Log($"Removed unused Fish-Networking define {item}.");
|
||||
}
|
||||
|
||||
if (modified)
|
||||
{
|
||||
Debug.Log("Added or removed Fish-Networking defines within player settings.");
|
||||
string changedDefines = string.Join(";", definesHs);
|
||||
PlayerSettings.SetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup, changedDefines);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
11
Assets/FishNet/Runtime/Editor/ScriptingDefines.cs.meta
Normal file
11
Assets/FishNet/Runtime/Editor/ScriptingDefines.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 893e5074d486a0e4aaf7803436fef791
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/FishNet/Runtime/Editor/Textures.meta
Normal file
8
Assets/FishNet/Runtime/Editor/Textures.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0c9efa228205fac47af86971242e97f9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/FishNet/Runtime/Editor/Textures/Icon.meta
Normal file
8
Assets/FishNet/Runtime/Editor/Textures/Icon.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cc19ac8f58640dd4bb062b1024d23ecc
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
BIN
Assets/FishNet/Runtime/Editor/Textures/Icon/fishnet_light.png
Normal file
BIN
Assets/FishNet/Runtime/Editor/Textures/Icon/fishnet_light.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 40 KiB |
@ -0,0 +1,92 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bf9191e2e07d29749bca3a1ae44e4bc8
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 11
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
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: 0
|
||||
wrapU: 0
|
||||
wrapV: 0
|
||||
wrapW: 0
|
||||
nPOTScale: 1
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
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: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 0
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
applyGammaDecoding: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/FishNet/Runtime/Editor/Textures/UI.meta
Normal file
8
Assets/FishNet/Runtime/Editor/Textures/UI.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dff09a4ee67e87a4083af1583c025766
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Binary file not shown.
After Width: | Height: | Size: 6.9 KiB |
@ -0,0 +1,116 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2d50394614f8feb4eb0567fb7618d84d
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 11
|
||||
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: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 0
|
||||
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: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
applyGammaDecoding: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: iPhone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 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: 2.8 KiB |
@ -0,0 +1,116 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2b3dca501a9d8c8479dc71dd068aa8b8
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 11
|
||||
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: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 0
|
||||
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: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
applyGammaDecoding: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: iPhone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 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: 9.1 KiB |
@ -0,0 +1,116 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1b187e63031bf7849b249c8212440c3b
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 11
|
||||
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: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 0
|
||||
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: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
applyGammaDecoding: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: iPhone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 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:
|
BIN
Assets/FishNet/Runtime/Editor/Textures/UI/Logo_With_Text.png
Normal file
BIN
Assets/FishNet/Runtime/Editor/Textures/UI/Logo_With_Text.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 37 KiB |
@ -0,0 +1,96 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5ea1cf1e0e57aff4e9ad3cd4246b0e80
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 11
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
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
|
||||
vTOnly: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 0
|
||||
wrapV: 0
|
||||
wrapW: 0
|
||||
nPOTScale: 1
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
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: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 0
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user