This commit is contained in:
SoulliesOfficial
2026-06-09 11:21:59 -04:00
parent 7c60c40d6b
commit 021e76efe7
493 changed files with 50500 additions and 2211 deletions

View File

@@ -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,
};
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2eb55257a9b4d499fa13f7ef4148fe70
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a8e4ace65c1d3417f8e45daa8b368eb7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 94073015eacc34c1d8fc6786e43d60ca
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}
}
}
}

View File

@@ -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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 053561912b1654d80a424bb0696a74ae
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: df51791547d164f7d92c82f972fd8305
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: