同步
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
Yarn Spinner is licensed to you under the terms found in the file LICENSE.md.
|
||||
*/
|
||||
|
||||
using System.Linq;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace Yarn.Unity.Editor
|
||||
{
|
||||
[System.Serializable]
|
||||
public class FunctionInfo
|
||||
{
|
||||
public string Name = "unknown";
|
||||
public string ReturnType = "unknown";
|
||||
public string[] Parameters = System.Array.Empty<string>();
|
||||
|
||||
public static FunctionInfo CreateFunctionInfoFromMethodGroup(System.Reflection.MethodInfo method)
|
||||
{
|
||||
var returnType = $"-> {method.ReturnType.Name}";
|
||||
|
||||
var parameters = method.GetParameters();
|
||||
var p = new string[parameters.Count()];
|
||||
for (int i = 0; i < parameters.Count(); i++)
|
||||
{
|
||||
var q = parameters[i].ParameterType;
|
||||
p[i] = parameters[i].Name;
|
||||
}
|
||||
|
||||
return new FunctionInfo
|
||||
{
|
||||
Name = method.Name,
|
||||
ReturnType = returnType,
|
||||
Parameters = p,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2eb55257a9b4d499fa13f7ef4148fe70
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
Yarn Spinner is licensed to you under the terms found in the file LICENSE.md.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace Yarn.Unity
|
||||
{
|
||||
public class ProjectImportData : ScriptableObject
|
||||
{
|
||||
public List<Editor.YarnProjectImporter.SerializedDeclaration> serializedDeclarations = new List<Editor.YarnProjectImporter.SerializedDeclaration>();
|
||||
|
||||
public bool HasCompileErrors => diagnostics.Count() > 0;
|
||||
|
||||
public bool containsImplicitLineIDs = false;
|
||||
|
||||
public List<TextAsset> yarnFiles = new List<TextAsset>();
|
||||
|
||||
[System.Serializable]
|
||||
public struct LocalizationEntry
|
||||
{
|
||||
public string languageID;
|
||||
public DefaultAsset? assetsFolder;
|
||||
public TextAsset? stringsFile;
|
||||
public bool isExternal;
|
||||
public Localization? externalLocalization;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public struct DiagnosticEntry
|
||||
{
|
||||
public TextAsset? yarnFile;
|
||||
public List<string> errorMessages;
|
||||
}
|
||||
|
||||
public enum ImportStatusCode
|
||||
{
|
||||
Unknown = 0,
|
||||
Succeeded = 1,
|
||||
CompilationFailed = 2,
|
||||
NeedsUpgradeFromV1 = 3,
|
||||
}
|
||||
|
||||
public ImportStatusCode ImportStatus = ImportStatusCode.Unknown;
|
||||
|
||||
public List<DiagnosticEntry> diagnostics = new List<DiagnosticEntry>();
|
||||
|
||||
public List<string> sourceFilePatterns = new List<string>();
|
||||
|
||||
public List<LocalizationEntry> localizations = new List<LocalizationEntry>();
|
||||
|
||||
public string? baseLanguageName;
|
||||
|
||||
public LocalizationEntry BaseLocalizationEntry
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return localizations.First(l => l.languageID == baseLanguageName);
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
throw new System.InvalidOperationException("Project import data has no base localisation", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryGetLocalizationEntry(string languageID, out LocalizationEntry result)
|
||||
{
|
||||
foreach (var loc in this.localizations)
|
||||
{
|
||||
if (loc.languageID == languageID)
|
||||
{
|
||||
result = loc;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
result = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a8e4ace65c1d3417f8e45daa8b368eb7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
216
Packages/dev.yarnspinner.unity/Editor/Importers/YarnImporter.cs
Normal file
216
Packages/dev.yarnspinner.unity/Editor/Importers/YarnImporter.cs
Normal file
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
Yarn Spinner is licensed to you under the terms found in the file LICENSE.md.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using UnityEditor;
|
||||
using UnityEditor.AssetImporters;
|
||||
using UnityEngine;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace Yarn.Unity.Editor
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="ScriptedImporter"/> for Yarn assets.
|
||||
/// </summary>
|
||||
[ScriptedImporter(6, new[] { "yarn", "yarnc" }, -1), HelpURL("https://docs.yarnspinner.dev/using-yarnspinner-with-unity/importing-yarn-files/yarn-projects")]
|
||||
[InitializeOnLoad]
|
||||
public class YarnImporter : ScriptedImporter
|
||||
{
|
||||
/// <summary>
|
||||
/// Get the collection of <see cref="YarnProject"/> assets that
|
||||
/// reference this Yarn script.
|
||||
/// </summary>
|
||||
public IEnumerable<YarnProject> DestinationProjects
|
||||
{
|
||||
get
|
||||
{
|
||||
return DestinationProjectImporters
|
||||
.Select(importer => AssetDatabase.LoadAssetAtPath<YarnProject>(AssetDatabase.GetAssetPath(importer)));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the collection of importers for the <see cref="YarnProject"/> assets that
|
||||
/// reference this Yarn script.
|
||||
/// </summary>
|
||||
public IEnumerable<YarnProjectImporter> DestinationProjectImporters
|
||||
{
|
||||
get
|
||||
{
|
||||
var myAssetPath = assetPath;
|
||||
var destinationProjectImporters = YarnEditorUtility.GetAllAssetsOf<YarnProjectImporter>("t:YarnProject")
|
||||
.Where(importer =>
|
||||
{
|
||||
// Does this importer depend on this asset? If so,
|
||||
// then this is our destination asset.
|
||||
string[] dependencies = AssetDatabase.GetDependencies(importer.assetPath);
|
||||
var importerDependsOnThisAsset = dependencies.Contains(myAssetPath);
|
||||
|
||||
return importerDependsOnThisAsset;
|
||||
});
|
||||
return destinationProjectImporters;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether any of the Yarn Projects in <see
|
||||
/// cref="DestinationProjects"/> reported any errors in this file.
|
||||
/// </summary>
|
||||
public bool HasErrors
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (var projectImporter in DestinationProjectImporters)
|
||||
{
|
||||
if (projectImporter.GetErrorsForScript(ImportedScript).Any())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private TextAsset ImportedScript => AssetDatabase.LoadAssetAtPath<TextAsset>(this.assetPath);
|
||||
|
||||
/// <summary>
|
||||
/// Called by Unity to import an asset.
|
||||
/// </summary>
|
||||
/// <param name="ctx">The context for the asset import
|
||||
/// operation.</param>
|
||||
public override void OnImportAsset(AssetImportContext ctx)
|
||||
{
|
||||
var stopwatch = new System.Diagnostics.Stopwatch();
|
||||
stopwatch.Start();
|
||||
|
||||
var extension = System.IO.Path.GetExtension(ctx.assetPath);
|
||||
|
||||
if (extension == ".yarn")
|
||||
{
|
||||
// Import this file as a TextAsset.
|
||||
var textAsset = new TextAsset(File.ReadAllText(ctx.assetPath));
|
||||
ctx.AddObjectToAsset("Script", textAsset, YarnEditorUtility.GetYarnDocumentIconTexture());
|
||||
ctx.SetMainObject(textAsset);
|
||||
|
||||
|
||||
// Next, if we're a brand-new script, ensure that project
|
||||
// importers that need to depend on this script have a chance to
|
||||
// re-import.
|
||||
|
||||
// Find all Yarn Project importers that _should_ be using this file.
|
||||
var projectsThatReferenceThisFile = YarnEditorUtility
|
||||
.GetAllAssetsOf<YarnProjectImporter>("t:YarnProject")
|
||||
.Where(importer => importer.GetProjectReferencesYarnFile(this));
|
||||
|
||||
var missingProjectImporters = projectsThatReferenceThisFile
|
||||
.Where(importer =>
|
||||
{
|
||||
var dependencies = AssetDatabase.GetDependencies(AssetDatabase.GetAssetPath(importer));
|
||||
var importerDependsOnThisAsset = dependencies.Contains(ctx.assetPath);
|
||||
return importerDependsOnThisAsset == false;
|
||||
});
|
||||
|
||||
// We now have a list of project importers that SHOULD be
|
||||
// depending on this script, but currently aren't (because this
|
||||
// script was created after the project was last imported.)
|
||||
// Reimport these assets, which will cause them to add a
|
||||
// dependency on us. Do this on the next frame, because we're in
|
||||
// the middle of an import now, and aren't allowed to start
|
||||
// another one.
|
||||
EditorApplication.delayCall += () =>
|
||||
{
|
||||
// Re-import each project.
|
||||
foreach (var importer in missingProjectImporters)
|
||||
{
|
||||
EditorUtility.SetDirty(importer);
|
||||
importer.SaveAndReimport();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
else if (extension == ".yarnc")
|
||||
{
|
||||
ImportCompiledYarn(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a byte array containing a SHA-256 hash of <paramref
|
||||
/// name="inputString"/>.
|
||||
/// </summary>
|
||||
/// <param name="inputString">The string to produce a hash value
|
||||
/// for.</param>
|
||||
/// <returns>The hash of <paramref name="inputString"/>.</returns>
|
||||
private static byte[] GetHash(string inputString)
|
||||
{
|
||||
using (HashAlgorithm algorithm = SHA256.Create())
|
||||
{
|
||||
return algorithm.ComputeHash(Encoding.UTF8.GetBytes(inputString));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a string containing the hexadecimal representation of a
|
||||
/// SHA-256 hash of <paramref name="inputString"/>.
|
||||
/// </summary>
|
||||
/// <param name="inputString">The string to produce a hash
|
||||
/// for.</param>
|
||||
/// <param name="limitCharacters">The length of the string to
|
||||
/// return. The returned string will be at most <paramref
|
||||
/// name="limitCharacters"/> characters long. If this is set to -1,
|
||||
/// the entire string will be returned.</param>
|
||||
/// <returns>A string version of the hash.</returns>
|
||||
public static string GetHashString(string inputString, int limitCharacters = -1)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
foreach (byte b in GetHash(inputString))
|
||||
{
|
||||
sb.Append(b.ToString("x2"));
|
||||
}
|
||||
|
||||
if (limitCharacters == -1)
|
||||
{
|
||||
// Return the entire string
|
||||
return sb.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Return a substring (or the entire string, if
|
||||
// limitCharacters is longer than the string)
|
||||
return sb.ToString(0, Mathf.Min(sb.Length, limitCharacters));
|
||||
}
|
||||
}
|
||||
|
||||
private void ImportCompiledYarn(AssetImportContext ctx)
|
||||
{
|
||||
|
||||
var bytes = File.ReadAllBytes(ctx.assetPath);
|
||||
|
||||
try
|
||||
{
|
||||
// Validate that this can be parsed as a Program protobuf
|
||||
var _ = Program.Parser.ParseFrom(bytes);
|
||||
}
|
||||
catch (Google.Protobuf.InvalidProtocolBufferException)
|
||||
{
|
||||
ctx.LogImportError("Invalid compiled yarn file. Please re-compile the source code.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a container for storing the bytes
|
||||
var programContainer = new TextAsset("<pre-compiled Yarn script>");
|
||||
|
||||
// Add this container to the imported asset; it will be what
|
||||
// the user interacts with in Unity
|
||||
ctx.AddObjectToAsset("Program", programContainer, YarnEditorUtility.GetYarnDocumentIconTexture());
|
||||
ctx.SetMainObject(programContainer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 94073015eacc34c1d8fc6786e43d60ca
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
Yarn Spinner is licensed to you under the terms found in the file LICENSE.md.
|
||||
*/
|
||||
|
||||
namespace Yarn.Unity.Editor
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// An asset post processor that forwards any asset database changes to all
|
||||
/// YarnProjectImporter for them to verify if they need to update their
|
||||
/// locale assets.
|
||||
/// </summary>
|
||||
class YarnProjectAssetReimport : AssetPostprocessor
|
||||
{
|
||||
static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths, bool didDomainReload)
|
||||
{
|
||||
if (!YarnSpinnerProjectSettings.GetOrCreateSettings().autoRefreshLocalisedAssets)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var modifiedAssets = new List<string>();
|
||||
modifiedAssets.AddRange(importedAssets);
|
||||
modifiedAssets.AddRange(deletedAssets);
|
||||
modifiedAssets.AddRange(movedAssets);
|
||||
modifiedAssets.AddRange(movedFromAssetPaths);
|
||||
|
||||
var yarnProjects = AssetDatabase.FindAssets($"t:{nameof(YarnProject)}");
|
||||
foreach (var guid in yarnProjects)
|
||||
{
|
||||
var path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
var importer = AssetImporter.GetAtPath(path) as YarnProjectImporter;
|
||||
if (importer != null)
|
||||
{
|
||||
importer.CheckUpdatedAssetsRequireReimport(modifiedAssets);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 64377162a9d0e46e08de43748d8661bb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 053561912b1654d80a424bb0696a74ae
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
Yarn Spinner is licensed to you under the terms found in the file LICENSE.md.
|
||||
*/
|
||||
|
||||
#if USE_UNITY_LOCALIZATION
|
||||
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Callbacks;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace Yarn.Unity.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// An asset post processor that updates Unity Localization string tables
|
||||
/// when a Yarn Project that uses them is imported.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Due to a bug in Unity, <see cref="ScriptedImporter"/> objects aren't
|
||||
/// able to interact with ScriptableObject instances during import, and
|
||||
/// Unity string tables are scriptable objects. To work around this, we
|
||||
/// update the string table after import is complete, using a
|
||||
/// post-processor.
|
||||
/// </remarks>
|
||||
internal class YarnProjectUnityLocalizationUpdater : AssetPostprocessor
|
||||
{
|
||||
[RunAfterPackage("com.unity.localization")]
|
||||
public static void OnPostprocessAllAssets(string[] importedAssets,
|
||||
string[] deletedAssets,
|
||||
string[] movedAssets,
|
||||
string[] movedFromAssetPaths,
|
||||
bool didDomainReload)
|
||||
{
|
||||
// Get all importers for Yarn projects that were just imported
|
||||
var importedYarnProjectAssets = importedAssets
|
||||
.Select(path => AssetImporter.GetAtPath(path))
|
||||
.OfType<YarnProjectImporter>();
|
||||
|
||||
foreach (var importer in importedYarnProjectAssets)
|
||||
{
|
||||
// If the importer uses Unity Localization, get it to update its
|
||||
// table
|
||||
if (importer.UseUnityLocalisationSystem)
|
||||
{
|
||||
importer.AddStringsToUnityLocalization();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: df51791547d164f7d92c82f972fd8305
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user