You've already forked ParticleEffectForUGUI
mirror of
https://github.com/mob-sakai/ParticleEffectForUGUI.git
synced 2026-05-14 20:20:06 +00:00
3.0.0-preview.18
# [3.0.0-preview.18](https://github.com/mob-sakai/ParticleEffectForUGUI/compare/v3.0.0-preview.17...v3.0.0-preview.18) (2020-08-19) ### Bug Fixes * AsmdefEx is no longer required ([50e749c](50e749c183)) * fix camera for baking mesh ([6395a4f](6395a4fa74)) * support .Net Framework 3.5 (again) ([23fcb06](23fcb06bf9)) ### Features * 3.0.0 updater ([f99292b](f99292b9a1)) * add menu to create UIParticle ([14f1c78](14f1c782ff)) * Combine baked meshes to improve performance ([633d058](633d058756)) * improve performance ([77c056a](77c056ad5f)) * optimization for vertices transforms and adding node for trails ([e070e8d](e070e8d5ee)), closes [#75](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/75) * option to ignoring canvas scaling ([fe85fed](fe85fed3c0)) * support 3d scaling ([42a84bc](42a84bc5e1)) * support custom simulation space ([a83e647](a83e64761c)), closes [#78](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/78) * support for particle systems including trail only ([f389d39](f389d39953)), closes [#61](https://github.com/mob-sakai/ParticleEffectForUGUI/issues/61) ### BREAKING CHANGES * The bake-task has changed significantly. It may look different from previous versions.
This commit is contained in:
114
Scripts/Editor/AnimatedPropertiesEditor.cs
Normal file
114
Scripts/Editor/AnimatedPropertiesEditor.cs
Normal file
@@ -0,0 +1,114 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ShaderPropertyType = Coffee.UIExtensions.AnimatableProperty.ShaderPropertyType;
|
||||
|
||||
namespace Coffee.UIExtensions
|
||||
{
|
||||
internal class AnimatedPropertiesEditor
|
||||
{
|
||||
static readonly List<string> s_ActiveNames = new List<string>();
|
||||
static readonly System.Text.StringBuilder s_Sb = new System.Text.StringBuilder();
|
||||
|
||||
private string _name;
|
||||
private ShaderPropertyType _type;
|
||||
|
||||
static string CollectActiveNames(SerializedProperty sp, List<string> result)
|
||||
{
|
||||
result.Clear();
|
||||
for (var i = 0; i < sp.arraySize; i++)
|
||||
{
|
||||
var spName = sp.GetArrayElementAtIndex(i).FindPropertyRelative("m_Name");
|
||||
if (spName == null) continue;
|
||||
|
||||
result.Add(spName.stringValue);
|
||||
}
|
||||
|
||||
s_Sb.Length = 0;
|
||||
if (result.Count == 0)
|
||||
{
|
||||
s_Sb.Append("Nothing");
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Aggregate(s_Sb, (a, b) => s_Sb.AppendFormat("{0}, ", b));
|
||||
s_Sb.Length -= 2;
|
||||
}
|
||||
|
||||
return s_Sb.ToString();
|
||||
}
|
||||
|
||||
public static void DrawAnimatableProperties(SerializedProperty sp, Material mat)
|
||||
{
|
||||
if (!mat || !mat.shader) return;
|
||||
|
||||
bool isClicked;
|
||||
using (new EditorGUILayout.HorizontalScope(GUILayout.ExpandWidth(false)))
|
||||
{
|
||||
var r = EditorGUI.PrefixLabel(EditorGUILayout.GetControlRect(true), new GUIContent(sp.displayName, sp.tooltip));
|
||||
var text = sp.hasMultipleDifferentValues ? "-" : CollectActiveNames(sp, s_ActiveNames);
|
||||
isClicked = GUI.Button(r, text, EditorStyles.popup);
|
||||
}
|
||||
|
||||
if (!isClicked) return;
|
||||
|
||||
var gm = new GenericMenu();
|
||||
gm.AddItem(new GUIContent("Nothing"), s_ActiveNames.Count == 0, () =>
|
||||
{
|
||||
sp.ClearArray();
|
||||
sp.serializedObject.ApplyModifiedProperties();
|
||||
});
|
||||
|
||||
|
||||
if (!sp.hasMultipleDifferentValues)
|
||||
{
|
||||
for (var i = 0; i < sp.arraySize; i++)
|
||||
{
|
||||
var p = sp.GetArrayElementAtIndex(i);
|
||||
var name = p.FindPropertyRelative("m_Name").stringValue;
|
||||
var type = (ShaderPropertyType) p.FindPropertyRelative("m_Type").intValue;
|
||||
AddMenu(gm, sp, new AnimatedPropertiesEditor {_name = name, _type = type}, false);
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < ShaderUtil.GetPropertyCount(mat.shader); i++)
|
||||
{
|
||||
var pName = ShaderUtil.GetPropertyName(mat.shader, i);
|
||||
var type = (ShaderPropertyType) ShaderUtil.GetPropertyType(mat.shader, i);
|
||||
AddMenu(gm, sp, new AnimatedPropertiesEditor {_name = pName, _type = type}, true);
|
||||
|
||||
if (type != ShaderPropertyType.Texture) continue;
|
||||
|
||||
AddMenu(gm, sp, new AnimatedPropertiesEditor {_name = pName + "_ST", _type = ShaderPropertyType.Vector}, true);
|
||||
AddMenu(gm, sp, new AnimatedPropertiesEditor {_name = pName + "_HDR", _type = ShaderPropertyType.Vector}, true);
|
||||
AddMenu(gm, sp, new AnimatedPropertiesEditor {_name = pName + "_TexelSize", _type = ShaderPropertyType.Vector}, true);
|
||||
}
|
||||
|
||||
gm.ShowAsContext();
|
||||
}
|
||||
|
||||
private static void AddMenu(GenericMenu menu, SerializedProperty sp, AnimatedPropertiesEditor property, bool add)
|
||||
{
|
||||
if (add && s_ActiveNames.Contains(property._name)) return;
|
||||
|
||||
menu.AddItem(new GUIContent(string.Format("{0} ({1})", property._name, property._type)), s_ActiveNames.Contains(property._name), () =>
|
||||
{
|
||||
var index = s_ActiveNames.IndexOf(property._name);
|
||||
if (0 <= index)
|
||||
{
|
||||
sp.DeleteArrayElementAtIndex(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
sp.InsertArrayElementAtIndex(sp.arraySize);
|
||||
var p = sp.GetArrayElementAtIndex(sp.arraySize - 1);
|
||||
p.FindPropertyRelative("m_Name").stringValue = property._name;
|
||||
p.FindPropertyRelative("m_Type").intValue = (int) property._type;
|
||||
}
|
||||
|
||||
sp.serializedObject.ApplyModifiedProperties();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0defeb6d13f61475eacce2b101cb2248
|
||||
guid: 60feb9aeb134e4ec789c0e63b017997f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -1,510 +0,0 @@
|
||||
#if UNITY_EDITOR
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEditor.Compilation;
|
||||
|
||||
namespace __GENARATED_ASMDEF__.Coffee.UIParticle.Editor
|
||||
{
|
||||
internal static class PackageSettings
|
||||
{
|
||||
public const string PackageId = "OpenSesame.Net.Compilers.3.4.0-beta.1";
|
||||
}
|
||||
|
||||
internal static class ReflectionExtensions
|
||||
{
|
||||
const BindingFlags FLAGS = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
|
||||
|
||||
static object Inst(this object self)
|
||||
{
|
||||
return (self is Type) ? null : self;
|
||||
}
|
||||
|
||||
static Type Type(this object self)
|
||||
{
|
||||
return (self as Type) ?? self.GetType();
|
||||
}
|
||||
|
||||
public static object New(this Type self, params object[] args)
|
||||
{
|
||||
var types = args.Select(x => x.GetType()).ToArray();
|
||||
return self.Type().GetConstructor(types)
|
||||
.Invoke(args);
|
||||
}
|
||||
|
||||
public static object Call(this object self, string methodName, params object[] args)
|
||||
{
|
||||
var types = args.Select(x => x.GetType()).ToArray();
|
||||
return self.Type().GetMethod(methodName, types)
|
||||
.Invoke(self.Inst(), args);
|
||||
}
|
||||
|
||||
public static object Call(this object self, Type[] genericTypes, string methodName, params object[] args)
|
||||
{
|
||||
return self.Type().GetMethod(methodName, FLAGS)
|
||||
.MakeGenericMethod(genericTypes)
|
||||
.Invoke(self.Inst(), args);
|
||||
}
|
||||
|
||||
public static object Get(this object self, string memberName, MemberInfo mi = null)
|
||||
{
|
||||
mi = mi ?? self.Type().GetMember(memberName, FLAGS)[0];
|
||||
return mi is PropertyInfo
|
||||
? (mi as PropertyInfo).GetValue(self.Inst(), new object[0])
|
||||
: (mi as FieldInfo).GetValue(self.Inst());
|
||||
}
|
||||
|
||||
public static void Set(this object self, string memberName, object value, MemberInfo mi = null)
|
||||
{
|
||||
mi = mi ?? self.Type().GetMember(memberName, FLAGS)[0];
|
||||
if (mi is PropertyInfo)
|
||||
(mi as PropertyInfo).SetValue(self.Inst(), value, new object[0]);
|
||||
else
|
||||
(mi as FieldInfo).SetValue(self.Inst(), value);
|
||||
}
|
||||
}
|
||||
|
||||
internal class Settings
|
||||
{
|
||||
public bool IgnoreAccessChecks;
|
||||
public string ModifySymbols = "";
|
||||
public string CustomCompiler = "";
|
||||
|
||||
public bool SholdChangeCompilerProcess
|
||||
{
|
||||
get { return IgnoreAccessChecks || !string.IsNullOrEmpty(ModifySymbols) || !string.IsNullOrEmpty(CustomCompiler); }
|
||||
}
|
||||
|
||||
public bool UseCustomCompiler
|
||||
{
|
||||
get { return IgnoreAccessChecks || !string.IsNullOrEmpty(CustomCompiler); }
|
||||
}
|
||||
|
||||
public static Settings GetAtPath(string path)
|
||||
{
|
||||
var setting = new Settings();
|
||||
if (string.IsNullOrEmpty(path))
|
||||
return setting;
|
||||
|
||||
// If input path is directory, find asmdef file.
|
||||
if (Directory.Exists(path))
|
||||
path = Directory.GetFiles(path, "*.asmdef")
|
||||
.Select(x => x.Replace(Environment.CurrentDirectory + Path.DirectorySeparatorChar, ""))
|
||||
.FirstOrDefault();
|
||||
|
||||
// Not find asmdef file.
|
||||
if (string.IsNullOrEmpty(path) || !File.Exists(path) || !File.Exists(path + ".meta"))
|
||||
return setting;
|
||||
|
||||
try
|
||||
{
|
||||
var json = AssetImporter.GetAtPath(path).userData;
|
||||
GetSettingssFromJson(json, out setting.IgnoreAccessChecks, out setting.ModifySymbols, out setting.CustomCompiler);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
return setting;
|
||||
}
|
||||
|
||||
public string ToJson()
|
||||
{
|
||||
return string.Format("{{" +
|
||||
"\"IgnoreAccessChecks\":{0}," +
|
||||
"\"ModifySymbols\":\"{1}\"," +
|
||||
"\"CustomCompiler\":\"{2}\"" +
|
||||
"}}",
|
||||
IgnoreAccessChecks ? "true" : "false",
|
||||
ModifySymbols ?? "",
|
||||
CustomCompiler ?? ""
|
||||
);
|
||||
}
|
||||
|
||||
public static Settings CreateFromJson(string json = "")
|
||||
{
|
||||
var setting = new Settings();
|
||||
GetSettingssFromJson(json, out setting.IgnoreAccessChecks, out setting.ModifySymbols, out setting.CustomCompiler);
|
||||
return setting;
|
||||
}
|
||||
|
||||
static void GetSettingssFromJson(string json, out bool ignoreAccessChecks, out string modifySymbols, out string customCompiler)
|
||||
{
|
||||
ignoreAccessChecks = false;
|
||||
modifySymbols = "";
|
||||
customCompiler = "";
|
||||
if (string.IsNullOrEmpty(json))
|
||||
return;
|
||||
|
||||
ignoreAccessChecks = Regex.Match(json, "\"IgnoreAccessChecks\":\\s*(true|false)").Groups[1].Value == "true";
|
||||
modifySymbols = Regex.Match(json, "\"ModifySymbols\":\\s*\"([^\"]*)\"").Groups[1].Value;
|
||||
customCompiler = Regex.Match(json, "\"CustomCompiler\":\\s*\"([^\"]*)\"").Groups[1].Value;
|
||||
}
|
||||
}
|
||||
|
||||
internal static class CustomCompiler
|
||||
{
|
||||
static string s_InstallPath;
|
||||
const string k_LogHeader = "<color=#c34062><b>[CustomCompiler]</b></color> ";
|
||||
|
||||
static void Log(string format, params object[] args)
|
||||
{
|
||||
if (Core.LogEnabled)
|
||||
UnityEngine.Debug.LogFormat(k_LogHeader + format, args);
|
||||
}
|
||||
|
||||
public static string GetInstalledPath(string packageId = "")
|
||||
{
|
||||
if (!string.IsNullOrEmpty(s_InstallPath) && File.Exists(s_InstallPath))
|
||||
return s_InstallPath;
|
||||
|
||||
try
|
||||
{
|
||||
packageId = string.IsNullOrEmpty(packageId) ? PackageSettings.PackageId : packageId;
|
||||
s_InstallPath = Install(packageId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UnityEngine.Debug.LogException(new Exception(k_LogHeader + ex.Message, ex.InnerException));
|
||||
}
|
||||
finally
|
||||
{
|
||||
EditorUtility.ClearProgressBar();
|
||||
}
|
||||
|
||||
return s_InstallPath;
|
||||
}
|
||||
|
||||
static string Install(string packageId)
|
||||
{
|
||||
char sep = Path.DirectorySeparatorChar;
|
||||
string url = "https://globalcdn.nuget.org/packages/" + packageId.ToLower() + ".nupkg";
|
||||
string downloadPath = ("Temp/" + Path.GetFileName(Path.GetTempFileName())).Replace('/', sep);
|
||||
string installPath = ("Library/" + packageId).Replace('/', sep);
|
||||
string cscToolExe = (installPath + "/tools/csc.exe").Replace('/', sep);
|
||||
|
||||
// Custom compiler is already installed.
|
||||
if (File.Exists(cscToolExe))
|
||||
{
|
||||
Log("Custom compiler '{0}' is already installed at {1}", packageId, cscToolExe);
|
||||
return cscToolExe;
|
||||
}
|
||||
|
||||
if (Directory.Exists(installPath))
|
||||
Directory.Delete(installPath, true);
|
||||
|
||||
try
|
||||
{
|
||||
UnityEngine.Debug.LogFormat(k_LogHeader + "Install custom compiler '{0}'", packageId);
|
||||
|
||||
// Download custom compiler package from nuget.
|
||||
{
|
||||
UnityEngine.Debug.LogFormat(k_LogHeader + "Download {0} from nuget: {1}", packageId, url);
|
||||
EditorUtility.DisplayProgressBar("Custom Compiler Installer", string.Format("Download {0} from nuget", packageId), 0.2f);
|
||||
|
||||
switch (Application.platform)
|
||||
{
|
||||
case RuntimePlatform.WindowsEditor:
|
||||
ExecuteCommand("PowerShell.exe", string.Format("curl -O {0} {1}", downloadPath, url));
|
||||
break;
|
||||
case RuntimePlatform.OSXEditor:
|
||||
ExecuteCommand("curl", string.Format("-o {0} -L {1}", downloadPath, url));
|
||||
break;
|
||||
case RuntimePlatform.LinuxEditor:
|
||||
ExecuteCommand("wget", string.Format("-O {0} {1}", downloadPath, url));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Extract nuget package (unzip).
|
||||
{
|
||||
UnityEngine.Debug.LogFormat(k_LogHeader + "Extract {0} to {1} with 7z", downloadPath, installPath);
|
||||
EditorUtility.DisplayProgressBar("Custom Compiler Installer", string.Format("Extract {0}", downloadPath), 0.4f);
|
||||
|
||||
string appPath = EditorApplication.applicationContentsPath.Replace('/', sep);
|
||||
string args = string.Format("x {0} -o{1}", downloadPath, installPath);
|
||||
|
||||
switch (Application.platform)
|
||||
{
|
||||
case RuntimePlatform.WindowsEditor:
|
||||
ExecuteCommand(appPath + "\\Tools\\7z.exe", args);
|
||||
break;
|
||||
case RuntimePlatform.OSXEditor:
|
||||
case RuntimePlatform.LinuxEditor:
|
||||
ExecuteCommand(appPath + "/Tools/7za", args);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
UnityEngine.Debug.LogFormat(k_LogHeader + "Custom compiler '{0}' has been installed in {1}.", packageId, installPath);
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new Exception(string.Format("Custom compiler '{0}' installation failed.", packageId));
|
||||
}
|
||||
finally
|
||||
{
|
||||
EditorUtility.ClearProgressBar();
|
||||
}
|
||||
|
||||
if (File.Exists(cscToolExe))
|
||||
return cscToolExe;
|
||||
|
||||
throw new FileNotFoundException(string.Format("Custom compiler '{0}' is not found at {1}", packageId, cscToolExe));
|
||||
}
|
||||
|
||||
static void ExecuteCommand(string exe, string args)
|
||||
{
|
||||
UnityEngine.Debug.LogFormat(k_LogHeader + "Execute command: {0} {1}", exe, args);
|
||||
|
||||
Process p = Process.Start(new ProcessStartInfo()
|
||||
{
|
||||
FileName = exe,
|
||||
Arguments = args,
|
||||
CreateNoWindow = true,
|
||||
UseShellExecute = false,
|
||||
RedirectStandardError = true,
|
||||
});
|
||||
p.WaitForExit();
|
||||
|
||||
if (p.ExitCode != 0)
|
||||
{
|
||||
UnityEngine.Debug.LogErrorFormat(k_LogHeader + p.StandardError.ReadToEnd());
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[InitializeOnLoad]
|
||||
internal static class Core
|
||||
{
|
||||
public static bool LogEnabled { get; private set; }
|
||||
public static string k_LogHeader = "<b><color=#9a4089>[AsmdefEx]</color></b> ";
|
||||
|
||||
static void Log(string format, params object[] args)
|
||||
{
|
||||
if (LogEnabled)
|
||||
LogEx(format, args);
|
||||
}
|
||||
|
||||
public static void LogEx(string format, params object[] args)
|
||||
{
|
||||
UnityEngine.Debug.LogFormat(k_LogHeader + format, args);
|
||||
}
|
||||
|
||||
public static void Error(Exception e)
|
||||
{
|
||||
UnityEngine.Debug.LogException(new Exception(k_LogHeader + e.Message, e.InnerException));
|
||||
}
|
||||
|
||||
public static object GetScriptAssembly(string assemblyName)
|
||||
{
|
||||
Type tEditorCompilationInterface = Type.GetType("UnityEditor.Scripting.ScriptCompilation.EditorCompilationInterface, UnityEditor");
|
||||
Type tCSharpLanguage = Type.GetType("UnityEditor.Scripting.Compilers.CSharpLanguage, UnityEditor");
|
||||
return tEditorCompilationInterface.Call(new[] {tCSharpLanguage}, "GetScriptAssemblyForLanguage", assemblyName);
|
||||
}
|
||||
|
||||
public static string[] ModifyDefines(IEnumerable<string> defines, bool ignoreAccessChecks, string modifySymbols)
|
||||
{
|
||||
var symbols = modifySymbols.Split(';', ',');
|
||||
var add = symbols.Where(x => 0 < x.Length && !x.StartsWith("!"));
|
||||
var remove = symbols.Where(x => 1 < x.Length && x.StartsWith("!")).Select(x => x.Substring(1));
|
||||
return defines
|
||||
.Union(add ?? Enumerable.Empty<string>())
|
||||
.Except(remove ?? Enumerable.Empty<string>())
|
||||
.Union(ignoreAccessChecks ? new[] {"IGNORE_ACCESS_CHECKS"} : Enumerable.Empty<string>())
|
||||
.Union(new[] {"ASMDEF_EX"})
|
||||
.Distinct()
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
public static void ModifyFiles(IEnumerable<string> files, bool ignoreAccessChecks)
|
||||
{
|
||||
const string s_If = "#if IGNORE_ACCESS_CHECKS // [ASMDEFEX] DO NOT REMOVE THIS LINE MANUALLY.";
|
||||
const string s_EndIf = "#endif // [ASMDEFEX] DO NOT REMOVE THIS LINE MANUALLY.";
|
||||
|
||||
// Add #if and #endif to all source files.
|
||||
foreach (var file in files)
|
||||
{
|
||||
var text = File.ReadAllText(file);
|
||||
Log("ModifyFiles: {0} {1} {2}", file, ignoreAccessChecks, text.Contains(s_If));
|
||||
if (text.Contains(s_If) == ignoreAccessChecks)
|
||||
continue;
|
||||
|
||||
var m = Regex.Match(text, "[\r\n]+");
|
||||
if (!m.Success)
|
||||
continue;
|
||||
|
||||
var nl = m.Value;
|
||||
if (ignoreAccessChecks)
|
||||
{
|
||||
text = s_If + nl + text + nl + s_EndIf;
|
||||
}
|
||||
else
|
||||
{
|
||||
text = text.Replace(s_If + nl, "");
|
||||
text = text.Replace(nl + s_EndIf, "");
|
||||
}
|
||||
|
||||
Log("ModifyFiles: Write {0} {1} {2}", file, ignoreAccessChecks, text.Contains(s_If));
|
||||
File.WriteAllText(file, text);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ChangeCompilerProcess(object compiler, Settings setting)
|
||||
{
|
||||
Type tProgram = Type.GetType("UnityEditor.Utils.Program, UnityEditor");
|
||||
Type tScriptCompilerBase = Type.GetType("UnityEditor.Scripting.Compilers.ScriptCompilerBase, UnityEditor");
|
||||
FieldInfo fiProcess = tScriptCompilerBase.GetField("process", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
Log("Kill previous compiler process");
|
||||
var psi = compiler.Get("process", fiProcess).Call("GetProcessStartInfo") as ProcessStartInfo;
|
||||
compiler.Call("Dispose");
|
||||
|
||||
// Convert response file for Mono to .Net.
|
||||
// - Add preferreduilang option (en-US)
|
||||
// - Change language version to 'latest'
|
||||
// - Change 'debug' to 'debug:portable'
|
||||
// - Change compiler switch prefix '-' to '/'
|
||||
string responseFile = Regex.Replace(psi.Arguments, "^.*@(.+)$", "$1");
|
||||
bool isMono = compiler.GetType().Name == "MonoCSharpCompiler";
|
||||
var text = File.ReadAllText(responseFile);
|
||||
text = Regex.Replace(text, "[\r\n]+", "\n");
|
||||
text = Regex.Replace(text, "^-", "/", RegexOptions.Multiline);
|
||||
|
||||
// Modify scripting define symbols.
|
||||
{
|
||||
Log("Modify scripting define symbols: {0}", responseFile);
|
||||
var defines = Regex.Matches(text, "^/define:(.*)$", RegexOptions.Multiline)
|
||||
.Cast<Match>()
|
||||
.Select(x => x.Groups[1].Value);
|
||||
|
||||
text = Regex.Replace(text, "[\r\n]+/define:[^\r\n]+", "");
|
||||
foreach (var d in ModifyDefines(defines, setting.IgnoreAccessChecks, setting.ModifySymbols))
|
||||
{
|
||||
text += "\n/define:" + d;
|
||||
}
|
||||
}
|
||||
|
||||
// Add/remove '#if IGNORE_ACCESS_CHECKS' and '#endif' preprocessor.
|
||||
var files = Regex.Matches(text, "^\"(.*)\"$", RegexOptions.Multiline)
|
||||
.Cast<Match>()
|
||||
.Select(x => x.Groups[1].Value)
|
||||
.Where(x => Path.GetExtension(x) == ".cs")
|
||||
.Where(x => Path.GetFileName(x) != "AsmdefEx.cs");
|
||||
ModifyFiles(files, setting.IgnoreAccessChecks);
|
||||
|
||||
// To access to non-publics in other assemblies, use custom compiler instead of default csc.
|
||||
if (setting.UseCustomCompiler)
|
||||
{
|
||||
text = Regex.Replace(text, "^/langversion:\\d+$", "/langversion:latest", RegexOptions.Multiline);
|
||||
text = Regex.Replace(text, "^/debug$", "/debug:portable", RegexOptions.Multiline);
|
||||
text += "\n/preferreduilang:en-US";
|
||||
|
||||
// Change exe file path.
|
||||
var cscToolExe = CustomCompiler.GetInstalledPath(setting.CustomCompiler);
|
||||
Log("Change csc tool exe to {0}", cscToolExe);
|
||||
if (Application.platform == RuntimePlatform.WindowsEditor)
|
||||
{
|
||||
psi.FileName = Path.GetFullPath(cscToolExe);
|
||||
psi.Arguments = "/shared /noconfig @" + responseFile;
|
||||
}
|
||||
else
|
||||
{
|
||||
psi.FileName = Path.Combine(EditorApplication.applicationContentsPath, "MonoBleedingEdge/bin/mono");
|
||||
psi.Arguments = cscToolExe + " /noconfig @" + responseFile;
|
||||
}
|
||||
}
|
||||
// Revert prefix symbols for mono compiler
|
||||
else if (isMono)
|
||||
{
|
||||
text = Regex.Replace(text, "^/", "-", RegexOptions.Multiline);
|
||||
}
|
||||
|
||||
text = Regex.Replace(text, "\n", System.Environment.NewLine);
|
||||
File.WriteAllText(responseFile, text);
|
||||
|
||||
Log("Restart compiler process: {0} {1}", psi.FileName, psi.Arguments);
|
||||
var program = tProgram.New(psi);
|
||||
program.Call("Start");
|
||||
compiler.Set("process", program, fiProcess);
|
||||
}
|
||||
|
||||
static void OnAssemblyCompilationStarted(string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
string assemblyName = Path.GetFileNameWithoutExtension(name);
|
||||
string assemblyFilename = assemblyName + ".dll";
|
||||
|
||||
if (assemblyName != typeof(Core).Assembly.GetName().Name)
|
||||
return;
|
||||
|
||||
Type tEditorCompilationInterface = Type.GetType("UnityEditor.Scripting.ScriptCompilation.EditorCompilationInterface, UnityEditor");
|
||||
var compilerTasks = tEditorCompilationInterface.Get("Instance").Get("compilationTask").Get("compilerTasks") as IDictionary;
|
||||
var scriptAssembly = compilerTasks.Keys.Cast<object>().FirstOrDefault(x => (x.Get("Filename") as string) == assemblyFilename);
|
||||
|
||||
// Should change compiler process for the assembly?
|
||||
var asmdefPath = CompilationPipeline.GetAssemblyDefinitionFilePathFromAssemblyName(assemblyName);
|
||||
var setting = Settings.GetAtPath(asmdefPath);
|
||||
if (!setting.SholdChangeCompilerProcess)
|
||||
return;
|
||||
|
||||
// Create new compiler to recompile.
|
||||
Log("Assembly compilation started: <b>{0} should be recompiled.</b>", assemblyName);
|
||||
Core.ChangeCompilerProcess(compilerTasks[scriptAssembly], setting);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
UnityEngine.Debug.LogException(new Exception(k_LogHeader + e.Message, e.InnerException));
|
||||
}
|
||||
}
|
||||
|
||||
static Core()
|
||||
{
|
||||
var assemblyName = typeof(Core).Assembly.GetName().Name;
|
||||
if (assemblyName == "Coffee.AsmdefEx")
|
||||
return;
|
||||
|
||||
k_LogHeader = string.Format("<b><color=#9a4089>[AsmdefEx ({0})]</color></b> ", assemblyName);
|
||||
LogEnabled = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup)
|
||||
.Split(';', ',')
|
||||
.Any(x => x == "ASMDEF_EX_LOG");
|
||||
|
||||
Log("Start watching assembly '{0}' compilation.", typeof(Core).Assembly.GetName().Name);
|
||||
CompilationPipeline.assemblyCompilationStarted += OnAssemblyCompilationStarted;
|
||||
}
|
||||
}
|
||||
|
||||
#if !ASMDEF_EX
|
||||
[InitializeOnLoad]
|
||||
internal class RecompileRequest
|
||||
{
|
||||
static RecompileRequest()
|
||||
{
|
||||
var assemblyName = typeof(RecompileRequest).Assembly.GetName().Name;
|
||||
if (assemblyName == "Coffee.AsmdefEx")
|
||||
return;
|
||||
|
||||
// Should change compiler process for the assembly?
|
||||
var asmdefPath = CompilationPipeline.GetAssemblyDefinitionFilePathFromAssemblyName(assemblyName);
|
||||
var setting = Settings.GetAtPath(asmdefPath);
|
||||
if (!setting.SholdChangeCompilerProcess)
|
||||
return;
|
||||
|
||||
if (Core.LogEnabled)
|
||||
UnityEngine.Debug.LogFormat("<b>Request to recompile: {0} ({1})</b>", assemblyName, asmdefPath);
|
||||
|
||||
AssetDatabase.ImportAsset(asmdefPath);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -2,6 +2,6 @@ fileFormatVersion: 2
|
||||
guid: 69deabfe8eed7495886c9daa69c9826a
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData: '{"IgnoreAccessChecks":true,"ModifySymbols":""}'
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
||||
@@ -1,129 +1,32 @@
|
||||
#if IGNORE_ACCESS_CHECKS // [ASMDEFEX] DO NOT REMOVE THIS LINE MANUALLY.
|
||||
using UnityEditor;
|
||||
using UnityEditor.UI;
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System;
|
||||
using ShaderPropertyType = Coffee.UIExtensions.UIParticle.AnimatableProperty.ShaderPropertyType;
|
||||
|
||||
namespace Coffee.UIExtensions
|
||||
{
|
||||
[CustomEditor(typeof(UIParticle))]
|
||||
[CanEditMultipleObjects]
|
||||
public class UIParticleEditor : GraphicEditor
|
||||
internal class UIParticleEditor : GraphicEditor
|
||||
{
|
||||
class AnimatedPropertiesEditor
|
||||
{
|
||||
static readonly List<string> s_ActiveNames = new List<string>();
|
||||
static readonly System.Text.StringBuilder s_Sb = new System.Text.StringBuilder();
|
||||
|
||||
public string name;
|
||||
public ShaderPropertyType type;
|
||||
|
||||
static string CollectActiveNames(SerializedProperty sp, List<string> result)
|
||||
{
|
||||
result.Clear();
|
||||
for (int i = 0; i < sp.arraySize; i++)
|
||||
{
|
||||
result.Add(sp.GetArrayElementAtIndex(i).FindPropertyRelative("m_Name").stringValue);
|
||||
}
|
||||
|
||||
s_Sb.Length = 0;
|
||||
if (result.Count == 0)
|
||||
{
|
||||
s_Sb.Append("Nothing");
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Aggregate(s_Sb, (a, b) => s_Sb.AppendFormat("{0}, ", b));
|
||||
s_Sb.Length -= 2;
|
||||
}
|
||||
|
||||
return s_Sb.ToString();
|
||||
}
|
||||
|
||||
public static void DrawAnimatableProperties(SerializedProperty sp, Material mat)
|
||||
{
|
||||
if (!mat || !mat.shader)
|
||||
return;
|
||||
bool isClicked = false;
|
||||
using (new EditorGUILayout.HorizontalScope(GUILayout.ExpandWidth(false)))
|
||||
{
|
||||
var r = EditorGUI.PrefixLabel(EditorGUILayout.GetControlRect(true), new GUIContent(sp.displayName, sp.tooltip));
|
||||
isClicked = GUI.Button(r, CollectActiveNames(sp, s_ActiveNames), EditorStyles.popup);
|
||||
}
|
||||
|
||||
if (isClicked)
|
||||
{
|
||||
GenericMenu gm = new GenericMenu();
|
||||
gm.AddItem(new GUIContent("Nothing"), s_ActiveNames.Count == 0, () =>
|
||||
{
|
||||
sp.ClearArray();
|
||||
sp.serializedObject.ApplyModifiedProperties();
|
||||
});
|
||||
|
||||
|
||||
for (int i = 0; i < sp.arraySize; i++)
|
||||
{
|
||||
var p = sp.GetArrayElementAtIndex(i);
|
||||
var name = p.FindPropertyRelative("m_Name").stringValue;
|
||||
var type = (ShaderPropertyType) p.FindPropertyRelative("m_Type").intValue;
|
||||
AddMenu(gm, sp, new AnimatedPropertiesEditor() {name = name, type = type}, false);
|
||||
}
|
||||
|
||||
for (int i = 0; i < ShaderUtil.GetPropertyCount(mat.shader); i++)
|
||||
{
|
||||
var pName = ShaderUtil.GetPropertyName(mat.shader, i);
|
||||
var type = (ShaderPropertyType) ShaderUtil.GetPropertyType(mat.shader, i);
|
||||
AddMenu(gm, sp, new AnimatedPropertiesEditor() {name = pName, type = type}, true);
|
||||
|
||||
if (type == ShaderPropertyType.Texture)
|
||||
{
|
||||
AddMenu(gm, sp, new AnimatedPropertiesEditor() {name = pName + "_ST", type = ShaderPropertyType.Vector}, true);
|
||||
AddMenu(gm, sp, new AnimatedPropertiesEditor() {name = pName + "_HDR", type = ShaderPropertyType.Vector}, true);
|
||||
AddMenu(gm, sp, new AnimatedPropertiesEditor() {name = pName + "_TexelSize", type = ShaderPropertyType.Vector}, true);
|
||||
}
|
||||
}
|
||||
|
||||
gm.ShowAsContext();
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddMenu(GenericMenu menu, SerializedProperty sp, AnimatedPropertiesEditor property, bool add)
|
||||
{
|
||||
if (add && s_ActiveNames.Contains(property.name))
|
||||
return;
|
||||
|
||||
menu.AddItem(new GUIContent(string.Format("{0} ({1})", property.name, property.type)), s_ActiveNames.Contains(property.name), () =>
|
||||
{
|
||||
var index = s_ActiveNames.IndexOf(property.name);
|
||||
if (0 <= index)
|
||||
{
|
||||
sp.DeleteArrayElementAtIndex(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
sp.InsertArrayElementAtIndex(sp.arraySize);
|
||||
var p = sp.GetArrayElementAtIndex(sp.arraySize - 1);
|
||||
p.FindPropertyRelative("m_Name").stringValue = property.name;
|
||||
p.FindPropertyRelative("m_Type").intValue = (int) property.type;
|
||||
}
|
||||
|
||||
sp.serializedObject.ApplyModifiedProperties();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//################################
|
||||
// Constant or Static Members.
|
||||
//################################
|
||||
static readonly GUIContent s_ContentParticleMaterial = new GUIContent("Particle Material", "The material for rendering particles");
|
||||
static readonly GUIContent s_ContentTrailMaterial = new GUIContent("Trail Material", "The material for rendering particle trails");
|
||||
static readonly List<ParticleSystem> s_ParticleSystems = new List<ParticleSystem>();
|
||||
static readonly Color s_GizmoColor = new Color(1f, 0.7f, 0.7f, 0.9f);
|
||||
private static readonly GUIContent s_ContentParticleMaterial = new GUIContent("Particle Material", "The material for rendering particles");
|
||||
private static readonly GUIContent s_ContentTrailMaterial = new GUIContent("Trail Material", "The material for rendering particle trails");
|
||||
private static readonly GUIContent s_ContentAdvancedOptions = new GUIContent("Advanced Options");
|
||||
private static readonly GUIContent s_Content3D = new GUIContent("3D");
|
||||
private static readonly GUIContent s_ContentScale = new GUIContent("Scale");
|
||||
private static readonly List<ParticleSystem> s_ParticleSystems = new List<ParticleSystem>();
|
||||
|
||||
static readonly List<string> s_MaskablePropertyNames = new List<string>()
|
||||
private SerializedProperty _spParticleSystem;
|
||||
private SerializedProperty _spScale3D;
|
||||
private SerializedProperty _spIgnoreCanvasScaler;
|
||||
private SerializedProperty _spAnimatableProperties;
|
||||
private bool _xyzMode;
|
||||
|
||||
private static readonly List<string> s_MaskablePropertyNames = new List<string>
|
||||
{
|
||||
"_Stencil",
|
||||
"_StencilComp",
|
||||
@@ -133,6 +36,7 @@ namespace Coffee.UIExtensions
|
||||
"_ColorMask",
|
||||
};
|
||||
|
||||
|
||||
//################################
|
||||
// Public/Protected Members.
|
||||
//################################
|
||||
@@ -143,16 +47,9 @@ namespace Coffee.UIExtensions
|
||||
{
|
||||
base.OnEnable();
|
||||
_spParticleSystem = serializedObject.FindProperty("m_ParticleSystem");
|
||||
_spTrailParticle = serializedObject.FindProperty("m_TrailParticle");
|
||||
_spScale = serializedObject.FindProperty("m_Scale");
|
||||
_spIgnoreParent = serializedObject.FindProperty("m_IgnoreParent");
|
||||
_spScale3D = serializedObject.FindProperty("m_Scale3D");
|
||||
_spIgnoreCanvasScaler = serializedObject.FindProperty("m_IgnoreCanvasScaler");
|
||||
_spAnimatableProperties = serializedObject.FindProperty("m_AnimatableProperties");
|
||||
_particles = targets.Cast<UIParticle>().ToArray();
|
||||
_shapeModuleUIs = null;
|
||||
|
||||
var targetsGos = targets.Cast<UIParticle>().Select(x => x.gameObject).ToArray();
|
||||
_inspector = Resources.FindObjectsOfTypeAll<ParticleSystemInspector>()
|
||||
.FirstOrDefault(x => x.targets.Cast<ParticleSystem>().Select(x => x.gameObject).SequenceEqual(targetsGos));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -160,15 +57,19 @@ namespace Coffee.UIExtensions
|
||||
/// </summary>
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
var current = target as UIParticle;
|
||||
if (current == null) return;
|
||||
|
||||
serializedObject.Update();
|
||||
|
||||
EditorGUI.BeginDisabledGroup(true);
|
||||
EditorGUILayout.PropertyField(_spParticleSystem);
|
||||
EditorGUI.EndDisabledGroup();
|
||||
|
||||
// Draw materials.
|
||||
EditorGUI.indentLevel++;
|
||||
var ps = _spParticleSystem.objectReferenceValue as ParticleSystem;
|
||||
if (ps)
|
||||
if (ps != null)
|
||||
{
|
||||
var pr = ps.GetComponent<ParticleSystemRenderer>();
|
||||
var sp = new SerializedObject(pr).FindProperty("m_Materials");
|
||||
@@ -194,22 +95,19 @@ namespace Coffee.UIExtensions
|
||||
|
||||
EditorGUI.indentLevel--;
|
||||
|
||||
EditorGUI.BeginDisabledGroup(true);
|
||||
EditorGUILayout.PropertyField(_spTrailParticle);
|
||||
EditorGUI.EndDisabledGroup();
|
||||
// Advanced Options
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.LabelField(s_ContentAdvancedOptions, EditorStyles.boldLabel);
|
||||
|
||||
var current = target as UIParticle;
|
||||
_xyzMode = DrawFloatOrVector3Field(_spScale3D, _xyzMode);
|
||||
|
||||
EditorGUILayout.PropertyField(_spIgnoreParent);
|
||||
|
||||
EditorGUI.BeginDisabledGroup(!current.isRoot);
|
||||
EditorGUILayout.PropertyField(_spScale);
|
||||
EditorGUI.EndDisabledGroup();
|
||||
EditorGUILayout.PropertyField(_spIgnoreCanvasScaler);
|
||||
|
||||
// AnimatableProperties
|
||||
AnimatedPropertiesEditor.DrawAnimatableProperties(_spAnimatableProperties, current.material);
|
||||
|
||||
current.GetComponentsInChildren<ParticleSystem>(true, s_ParticleSystems);
|
||||
// Fix
|
||||
current.GetComponentsInChildren(true, s_ParticleSystems);
|
||||
if (s_ParticleSystems.Any(x => x.GetComponent<UIParticle>() == null))
|
||||
{
|
||||
GUILayout.BeginHorizontal();
|
||||
@@ -229,75 +127,54 @@ namespace Coffee.UIExtensions
|
||||
|
||||
s_ParticleSystems.Clear();
|
||||
|
||||
// Does the shader support UI masks?
|
||||
if (current.maskable && current.material && current.material.shader)
|
||||
{
|
||||
var mat = current.material;
|
||||
var shader = mat.shader;
|
||||
foreach (var propName in s_MaskablePropertyNames)
|
||||
{
|
||||
if (!mat.HasProperty(propName))
|
||||
{
|
||||
EditorGUILayout.HelpBox(string.Format("Shader {0} doesn't have '{1}' property. This graphic is not maskable.", shader.name, propName), MessageType.Warning);
|
||||
break;
|
||||
}
|
||||
if (mat.HasProperty(propName)) continue;
|
||||
|
||||
EditorGUILayout.HelpBox(string.Format("Shader '{0}' doesn't have '{1}' property. This graphic cannot be masked.", shader.name, propName), MessageType.Warning);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
|
||||
//################################
|
||||
// Private Members.
|
||||
//################################
|
||||
SerializedProperty _spParticleSystem;
|
||||
SerializedProperty _spTrailParticle;
|
||||
SerializedProperty _spScale;
|
||||
SerializedProperty _spIgnoreParent;
|
||||
SerializedProperty _spAnimatableProperties;
|
||||
UIParticle[] _particles;
|
||||
ShapeModuleUI[] _shapeModuleUIs;
|
||||
ParticleSystemInspector _inspector;
|
||||
|
||||
void OnSceneGUI()
|
||||
private static bool DrawFloatOrVector3Field(SerializedProperty sp, bool showXyz)
|
||||
{
|
||||
_shapeModuleUIs = _shapeModuleUIs ?? _inspector?.m_ParticleEffectUI?.m_Emitters?.SelectMany(x => x.m_Modules).OfType<ShapeModuleUI>()?.ToArray();
|
||||
if (_shapeModuleUIs == null || _shapeModuleUIs.Length == 0 || _shapeModuleUIs[0].GetParticleSystem() != (target as UIParticle).cachedParticleSystem)
|
||||
return;
|
||||
var x = sp.FindPropertyRelative("x");
|
||||
var y = sp.FindPropertyRelative("y");
|
||||
var z = sp.FindPropertyRelative("z");
|
||||
|
||||
Action postAction = () => { };
|
||||
Color origin = ShapeModuleUI.s_GizmoColor.m_Color;
|
||||
Color originDark = ShapeModuleUI.s_GizmoColor.m_Color;
|
||||
ShapeModuleUI.s_GizmoColor.m_Color = s_GizmoColor;
|
||||
ShapeModuleUI.s_GizmoColor.m_OptionalDarkColor = s_GizmoColor;
|
||||
showXyz |= !Mathf.Approximately(x.floatValue, y.floatValue) ||
|
||||
!Mathf.Approximately(y.floatValue, z.floatValue) ||
|
||||
y.hasMultipleDifferentValues ||
|
||||
z.hasMultipleDifferentValues;
|
||||
|
||||
_particles
|
||||
.Distinct()
|
||||
.Select(x => new {canvas = x.canvas, ps = x.cachedParticleSystem, scale = x.scale})
|
||||
.Where(x => x.ps && x.canvas)
|
||||
.ToList()
|
||||
.ForEach(x =>
|
||||
{
|
||||
var trans = x.ps.transform;
|
||||
var hasChanged = trans.hasChanged;
|
||||
var localScale = trans.localScale;
|
||||
postAction += () => trans.localScale = localScale;
|
||||
trans.localScale = Vector3.Scale(localScale, x.canvas.rootCanvas.transform.localScale * x.scale);
|
||||
});
|
||||
|
||||
try
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
if (showXyz)
|
||||
{
|
||||
foreach (var ui in _shapeModuleUIs)
|
||||
ui.OnSceneViewGUI();
|
||||
EditorGUILayout.PropertyField(sp);
|
||||
}
|
||||
catch
|
||||
else
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(x, s_ContentScale);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
z.floatValue = y.floatValue = x.floatValue;
|
||||
}
|
||||
|
||||
postAction();
|
||||
ShapeModuleUI.s_GizmoColor.m_Color = origin;
|
||||
ShapeModuleUI.s_GizmoColor.m_OptionalDarkColor = originDark;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
showXyz = GUILayout.Toggle(showXyz, s_Content3D, EditorStyles.miniButton, GUILayout.Width(30));
|
||||
if (EditorGUI.EndChangeCheck() && !showXyz)
|
||||
z.floatValue = y.floatValue = x.floatValue;
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
return showXyz;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // [ASMDEFEX] DO NOT REMOVE THIS LINE MANUALLY.
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
#if IGNORE_ACCESS_CHECKS // [ASMDEFEX] DO NOT REMOVE THIS LINE MANUALLY.
|
||||
#if !UNITY_2019_1_OR_NEWER
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Coffee.UIExtensions
|
||||
{
|
||||
public class UIParticleMenu
|
||||
{
|
||||
#if !UNITY_2019_1_OR_NEWER
|
||||
static string GetPreviousSamplePath(string displayName, string sampleName)
|
||||
{
|
||||
string sampleRoot = $"Assets/Samples/{displayName}";
|
||||
string sampleRoot = string.Format("Assets/Samples/{0}", displayName);
|
||||
var sampleRootInfo = new DirectoryInfo(sampleRoot);
|
||||
if (!sampleRootInfo.Exists) return null;
|
||||
|
||||
@@ -27,12 +27,12 @@ namespace Coffee.UIExtensions
|
||||
|
||||
static void ImportSample(string packageName, string sampleName)
|
||||
{
|
||||
string jsonPath = $"Packages/{packageName}/package.json";
|
||||
string jsonPath = string.Format("Packages/{0}/package.json", packageName);
|
||||
string json = File.ReadAllText(jsonPath);
|
||||
string version = Regex.Match(json, "\"version\"\\s*:\\s*\"([^\"]+)\"").Groups[1].Value;
|
||||
string displayName = Regex.Match(json, "\"displayName\"\\s*:\\s*\"([^\"]+)\"").Groups[1].Value;
|
||||
string src = $"{Path.GetDirectoryName(jsonPath)}/Samples~/{sampleName}";
|
||||
string dst = $"Assets/Samples/{displayName}/{version}/{sampleName}";
|
||||
string src = string.Format("{0}/Samples~/{1}", Path.GetDirectoryName(jsonPath), sampleName);
|
||||
string dst = string.Format("Assets/Samples/{0}/{1}/{2}", displayName, version, sampleName);
|
||||
string previous = GetPreviousSamplePath(displayName, sampleName);
|
||||
|
||||
if (!string.IsNullOrEmpty(previous))
|
||||
@@ -43,11 +43,19 @@ namespace Coffee.UIExtensions
|
||||
if (!EditorUtility.DisplayDialog("Sample Importer", msg, "OK", "Cancel"))
|
||||
return;
|
||||
|
||||
FileUtil.DeleteFileOrDirectory(previous);
|
||||
FileUtil.DeleteFileOrDirectory(previous + ".meta");
|
||||
FileUtil.DeleteFileOrDirectory(previous);
|
||||
|
||||
string versionDir = Path.GetDirectoryName(previous);
|
||||
if (Directory.GetFiles(versionDir, "*.meta", SearchOption.TopDirectoryOnly).Length == 0)
|
||||
{
|
||||
FileUtil.DeleteFileOrDirectory(versionDir + ".meta");
|
||||
FileUtil.DeleteFileOrDirectory(versionDir);
|
||||
}
|
||||
}
|
||||
|
||||
FileUtil.CopyDirectoryRecursive(src, dst);
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(dst));
|
||||
FileUtil.CopyFileOrDirectory(src, dst);
|
||||
AssetDatabase.ImportAsset(dst, ImportAssetOptions.ImportRecursive);
|
||||
}
|
||||
|
||||
@@ -56,7 +64,45 @@ namespace Coffee.UIExtensions
|
||||
{
|
||||
ImportSample("com.coffee.ui-particle", "Demo");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
[MenuItem("GameObject/UI/Particle System", false, 2019)]
|
||||
public static void AddParticle(MenuCommand menuCommand)
|
||||
{
|
||||
// Create UI element.
|
||||
EditorApplication.ExecuteMenuItem("GameObject/UI/Image");
|
||||
var ui = Selection.activeGameObject;
|
||||
|
||||
// Create ParticleSystem.
|
||||
EditorApplication.ExecuteMenuItem("GameObject/Effects/Particle System");
|
||||
var ps = Selection.activeGameObject;
|
||||
var transform = ps.transform;
|
||||
var localRotation = transform.localRotation;
|
||||
|
||||
transform.SetParent(ui.transform.parent, true);
|
||||
var pos = transform.localPosition;
|
||||
pos.z = 0;
|
||||
ps.transform.localPosition = pos;
|
||||
ps.transform.localRotation = localRotation;
|
||||
|
||||
// Destroy UI elemant
|
||||
Object.DestroyImmediate(ui);
|
||||
|
||||
// Assign default material.
|
||||
var renderer = ps.GetComponent<ParticleSystemRenderer>();
|
||||
var defaultMat = AssetDatabase.GetBuiltinExtraResource<Material>("Default-Particle.mat");
|
||||
renderer.material = defaultMat ? defaultMat : renderer.material;
|
||||
|
||||
// Set to hierarchy mode
|
||||
var particleSystem = ps.GetComponent<ParticleSystem>();
|
||||
var main = particleSystem.main;
|
||||
main.scalingMode = ParticleSystemScalingMode.Hierarchy;
|
||||
|
||||
// Add UIParticle.
|
||||
var uiParticle = ps.AddComponent<UIParticle>();
|
||||
uiParticle.ignoreCanvasScaler = true;
|
||||
uiParticle.scale = 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif // [ASMDEFEX] DO NOT REMOVE THIS LINE MANUALLY.
|
||||
|
||||
Reference in New Issue
Block a user