release(camera-ai): publish 0.4.11 worker bundle

This commit is contained in:
KINDNICK
2026-08-10 08:51:37 +09:00
parent b78c6319b6
commit 8e5e2e8ad0
27 changed files with 98034 additions and 230 deletions
File diff suppressed because it is too large Load Diff
@@ -21,6 +21,10 @@ namespace Streamingle.Editor
private const string MotionDirectorName = "Motion";
private const string SchemaVersion = "1.3";
private const string GenerationInputKind = "generation_input";
internal const string SourceFingerprintSchema =
"cw-ai-camera-source-v2-dependency-hash";
internal const string LegacySourceFingerprintSchema =
"cw-ai-camera-source-v1-semantic";
private const string GenerationInputDirectoryPrefix =
"GenerationInput_60fps_";
@@ -490,6 +494,7 @@ namespace Streamingle.Editor
cameraSamplingPolicy =
"Per authored Cinemachine track; muted variants included by batch; " +
"procedural CameraState sampled deterministically; overlaps blended.",
sourceFingerprintSchema = SourceFingerprintSchema,
sourceFingerprint = sourceFingerprint,
discoveredCameraTrackCount =
songs.Count + skippedCameraTracks.Count,
@@ -1882,6 +1887,34 @@ namespace Streamingle.Editor
}
internal static string ComputeSceneCameraSourceFingerprint(Scene scene)
{
return ComputeSceneCameraSourceFingerprint(
scene,
out _);
}
internal static string ComputeSceneCameraSourceFingerprint(
Scene scene,
out string legacyFingerprint)
{
legacyFingerprint =
ComputeLegacySceneCameraSourceFingerprint(scene);
var dependencyRecords = AssetDatabase
.GetDependencies(scene.path, true)
.Where(IsCameraSourceDependency)
.Select(assetPath =>
assetPath.Replace('\\', '/') + "|" +
AssetDatabase
.GetAssetDependencyHash(assetPath)
.ToString())
.ToArray();
return ComposeSceneCameraSourceFingerprint(
legacyFingerprint,
dependencyRecords);
}
internal static string ComputeLegacySceneCameraSourceFingerprint(
Scene scene)
{
var lines = new List<string>();
var directors = Resources.FindObjectsOfTypeAll<PlayableDirector>()
@@ -1935,6 +1968,139 @@ namespace Streamingle.Editor
return string.Concat(bytes.Select(item => item.ToString("x2")));
}
internal static string ComposeSceneCameraSourceFingerprint(
string semanticFingerprint,
IEnumerable<string> dependencyRecords)
{
if (string.IsNullOrWhiteSpace(semanticFingerprint))
{
throw new ArgumentException(
"A semantic source fingerprint is required.",
nameof(semanticFingerprint));
}
var records = (dependencyRecords ?? Array.Empty<string>())
.Where(record => !string.IsNullOrWhiteSpace(record))
.Select(record => record.Trim().Replace('\\', '/'))
.Distinct(StringComparer.Ordinal)
.OrderBy(record => record, StringComparer.Ordinal);
var payload = string.Join(
"\n",
new[]
{
"schema|" + SourceFingerprintSchema,
"semantic|" + semanticFingerprint.Trim()
}.Concat(records.Select(record => "dependency|" + record)));
using var sha256 = SHA256.Create();
var bytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(payload));
return string.Concat(bytes.Select(item => item.ToString("x2")));
}
internal static bool TryMatchSceneCameraSourceFingerprint(
string storedSchema,
string storedFingerprint,
string currentStrongFingerprint,
string currentLegacyFingerprint,
out bool legacyFingerprintAccepted,
out string error)
{
legacyFingerprintAccepted = false;
if (string.IsNullOrWhiteSpace(storedFingerprint))
{
error = "The manifest source fingerprint is missing.";
return false;
}
if (string.IsNullOrWhiteSpace(storedSchema) ||
string.Equals(
storedSchema,
LegacySourceFingerprintSchema,
StringComparison.Ordinal))
{
if (!string.Equals(
storedFingerprint,
currentLegacyFingerprint,
StringComparison.Ordinal))
{
error =
"The loaded scene legacy semantic fingerprint does " +
"not match the manifest.";
return false;
}
legacyFingerprintAccepted = true;
error = string.Empty;
return true;
}
if (!string.Equals(
storedSchema,
SourceFingerprintSchema,
StringComparison.Ordinal))
{
error =
$"Unsupported source fingerprint schema '{storedSchema}'.";
return false;
}
if (!string.Equals(
storedFingerprint,
currentStrongFingerprint,
StringComparison.Ordinal))
{
error =
"The loaded scene strong dependency fingerprint does " +
"not match the manifest.";
return false;
}
error = string.Empty;
return true;
}
private static bool IsCameraSourceDependency(string assetPath)
{
if (string.IsNullOrWhiteSpace(assetPath))
{
return false;
}
switch (Path.GetExtension(assetPath).ToLowerInvariant())
{
case ".unity":
case ".playable":
case ".anim":
case ".prefab":
case ".controller":
case ".overridecontroller":
case ".mask":
case ".fbx":
case ".dae":
case ".obj":
case ".blend":
case ".wav":
case ".mp3":
case ".flac":
case ".ogg":
return true;
case ".asset":
var assetType =
AssetDatabase.GetMainAssetTypeAtPath(assetPath);
var fullName = assetType?.FullName ?? string.Empty;
return assetType != null &&
(typeof(TimelineAsset).IsAssignableFrom(assetType) ||
typeof(AnimationClip).IsAssignableFrom(assetType) ||
typeof(RuntimeAnimatorController)
.IsAssignableFrom(assetType) ||
typeof(AvatarMask).IsAssignableFrom(assetType) ||
fullName.StartsWith(
"Unity.Cinemachine.",
StringComparison.Ordinal));
default:
return false;
}
}
internal static bool TryComputeGenerationInputSourceFingerprint(
PlayableDirector sourceDirector,
out string fingerprint,
@@ -3392,6 +3558,7 @@ namespace Streamingle.Editor
public string rootLayout;
public string audioFeatureLayout;
public string cameraSamplingPolicy;
public string sourceFingerprintSchema;
public string sourceFingerprint;
public int discoveredCameraTrackCount;
public int exportedCameraTrackCount;
+3 -3
View File
@@ -3,6 +3,6 @@ guid: 8c8c76ce67b4489299ad2b2afb1cdf3d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
userData:
assetBundleName:
assetBundleVariant:
@@ -4,9 +4,9 @@ ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0
unsupportedSelectorAction: 0
@@ -4,7 +4,7 @@ ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}