Asset store helper script + updated README (#521)
* Remove stray .meta file * Add a new project that will do asset uploads * Add asset store uploader * refactor: Replace Debug.Log calls with McpLog helper across codebase Standardize logging by replacing direct Debug.Log/LogWarning/LogError calls with McpLog.Info/Warn/Error throughout helper classes and client registry. Affected files: - McpClientRegistry.cs - GameObjectLookup.cs - GameObjectSerializer.cs - MaterialOps.cs - McpConfigurationHelper.cs - ObjectResolver.cs - PropertyConversion.cs - UnityJsonSerializer.cs - UnityTypeResolver.cs * feat: Add Asset Store release preparation script Add prepare_unity_asset_store_release.py tool to automate Asset Store packaging: - Stages temporary copy of MCPForUnity with Asset Store-specific edits - Removes auto-popup setup window ([InitializeOnLoad] attribute) - Renames menu entry to "Local Setup Window" for clarity - Sets default HTTP base URL to hosted endpoint - Defaults transport to HTTPRemote instead of HTTPLocal - Supports dry-run mode and optional backup of existing Assets/MCPForUnity * Show gif of MCP for Unity in Action * Add shield with asset store link * Update README to have asset store page unders installation sectionmain
parent
5511a2b8ad
commit
22e52664cd
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using MCPForUnity.Editor.Helpers;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
|
|
@ -47,7 +48,7 @@ namespace MCPForUnity.Editor.Clients
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"UnityMCP: Failed to instantiate configurator {type.Name}: {ex.Message}");
|
McpLog.Warn($"UnityMCP: Failed to instantiate configurator {type.Name}: {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
// Consider using by_name search with includeInactive if you need to find inactive objects.
|
// Consider using by_name search with includeInactive if you need to find inactive objects.
|
||||||
if (includeInactive)
|
if (includeInactive)
|
||||||
{
|
{
|
||||||
Debug.LogWarning("[GameObjectLookup] SearchByPath with includeInactive=true: " +
|
McpLog.Warn("[GameObjectLookup] SearchByPath with includeInactive=true: " +
|
||||||
"GameObject.Find() cannot find inactive objects. Use by_name search instead.");
|
"GameObject.Find() cannot find inactive objects. Use by_name search instead.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -224,7 +224,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
Type componentType = FindComponentType(componentTypeName);
|
Type componentType = FindComponentType(componentTypeName);
|
||||||
if (componentType == null)
|
if (componentType == null)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[GameObjectLookup] Component type '{componentTypeName}' not found.");
|
McpLog.Warn($"[GameObjectLookup] Component type '{componentTypeName}' not found.");
|
||||||
yield break;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -122,7 +122,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
public static object GetComponentData(Component c, bool includeNonPublicSerializedFields = true)
|
public static object GetComponentData(Component c, bool includeNonPublicSerializedFields = true)
|
||||||
{
|
{
|
||||||
// --- Add Early Logging ---
|
// --- Add Early Logging ---
|
||||||
// Debug.Log($"[GetComponentData] Starting for component: {c?.GetType()?.FullName ?? "null"} (ID: {c?.GetInstanceID() ?? 0})");
|
// McpLog.Info($"[GetComponentData] Starting for component: {c?.GetType()?.FullName ?? "null"} (ID: {c?.GetInstanceID() ?? 0})");
|
||||||
// --- End Early Logging ---
|
// --- End Early Logging ---
|
||||||
|
|
||||||
if (c == null) return null;
|
if (c == null) return null;
|
||||||
|
|
@ -132,7 +132,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
if (componentType == typeof(Transform))
|
if (componentType == typeof(Transform))
|
||||||
{
|
{
|
||||||
Transform tr = c as Transform;
|
Transform tr = c as Transform;
|
||||||
// Debug.Log($"[GetComponentData] Manually serializing Transform (ID: {tr.GetInstanceID()})");
|
// McpLog.Info($"[GetComponentData] Manually serializing Transform (ID: {tr.GetInstanceID()})");
|
||||||
return new Dictionary<string, object>
|
return new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ "typeName", componentType.FullName },
|
{ "typeName", componentType.FullName },
|
||||||
|
|
@ -295,7 +295,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
var serializablePropertiesOutput = new Dictionary<string, object>();
|
var serializablePropertiesOutput = new Dictionary<string, object>();
|
||||||
|
|
||||||
// --- Add Logging Before Property Loop ---
|
// --- Add Logging Before Property Loop ---
|
||||||
// Debug.Log($"[GetComponentData] Starting property loop for {componentType.Name}...");
|
// McpLog.Info($"[GetComponentData] Starting property loop for {componentType.Name}...");
|
||||||
// --- End Logging Before Property Loop ---
|
// --- End Logging Before Property Loop ---
|
||||||
|
|
||||||
// Use cached properties
|
// Use cached properties
|
||||||
|
|
@ -313,7 +313,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
// Also skip potentially problematic Matrix properties prone to cycles/errors
|
// Also skip potentially problematic Matrix properties prone to cycles/errors
|
||||||
propName == "worldToLocalMatrix" || propName == "localToWorldMatrix")
|
propName == "worldToLocalMatrix" || propName == "localToWorldMatrix")
|
||||||
{
|
{
|
||||||
// Debug.Log($"[GetComponentData] Explicitly skipping generic property: {propName}"); // Optional log
|
// McpLog.Info($"[GetComponentData] Explicitly skipping generic property: {propName}"); // Optional log
|
||||||
skipProperty = true;
|
skipProperty = true;
|
||||||
}
|
}
|
||||||
// --- End Skip Generic Properties ---
|
// --- End Skip Generic Properties ---
|
||||||
|
|
@ -330,7 +330,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
propName == "previousViewProjectionMatrix" ||
|
propName == "previousViewProjectionMatrix" ||
|
||||||
propName == "cameraToWorldMatrix"))
|
propName == "cameraToWorldMatrix"))
|
||||||
{
|
{
|
||||||
// Debug.Log($"[GetComponentData] Explicitly skipping Camera property: {propName}");
|
// McpLog.Info($"[GetComponentData] Explicitly skipping Camera property: {propName}");
|
||||||
skipProperty = true;
|
skipProperty = true;
|
||||||
}
|
}
|
||||||
// --- End Skip Camera Properties ---
|
// --- End Skip Camera Properties ---
|
||||||
|
|
@ -342,7 +342,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
propName == "worldToLocalMatrix" ||
|
propName == "worldToLocalMatrix" ||
|
||||||
propName == "localToWorldMatrix"))
|
propName == "localToWorldMatrix"))
|
||||||
{
|
{
|
||||||
// Debug.Log($"[GetComponentData] Explicitly skipping Transform property: {propName}");
|
// McpLog.Info($"[GetComponentData] Explicitly skipping Transform property: {propName}");
|
||||||
skipProperty = true;
|
skipProperty = true;
|
||||||
}
|
}
|
||||||
// --- End Skip Transform Properties ---
|
// --- End Skip Transform Properties ---
|
||||||
|
|
@ -356,7 +356,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// --- Add detailed logging ---
|
// --- Add detailed logging ---
|
||||||
// Debug.Log($"[GetComponentData] Accessing: {componentType.Name}.{propName}");
|
// McpLog.Info($"[GetComponentData] Accessing: {componentType.Name}.{propName}");
|
||||||
// --- End detailed logging ---
|
// --- End detailed logging ---
|
||||||
|
|
||||||
// --- Special handling for material/mesh properties in edit mode ---
|
// --- Special handling for material/mesh properties in edit mode ---
|
||||||
|
|
@ -392,12 +392,12 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
// Debug.LogWarning($"Could not read property {propName} on {componentType.Name}");
|
// McpLog.Warn($"Could not read property {propName} on {componentType.Name}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Add Logging Before Field Loop ---
|
// --- Add Logging Before Field Loop ---
|
||||||
// Debug.Log($"[GetComponentData] Starting field loop for {componentType.Name}...");
|
// McpLog.Info($"[GetComponentData] Starting field loop for {componentType.Name}...");
|
||||||
// --- End Logging Before Field Loop ---
|
// --- End Logging Before Field Loop ---
|
||||||
|
|
||||||
// Use cached fields
|
// Use cached fields
|
||||||
|
|
@ -406,7 +406,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// --- Add detailed logging for fields ---
|
// --- Add detailed logging for fields ---
|
||||||
// Debug.Log($"[GetComponentData] Accessing Field: {componentType.Name}.{fieldInfo.Name}");
|
// McpLog.Info($"[GetComponentData] Accessing Field: {componentType.Name}.{fieldInfo.Name}");
|
||||||
// --- End detailed logging for fields ---
|
// --- End detailed logging for fields ---
|
||||||
object value = fieldInfo.GetValue(c);
|
object value = fieldInfo.GetValue(c);
|
||||||
string fieldName = fieldInfo.Name;
|
string fieldName = fieldInfo.Name;
|
||||||
|
|
@ -415,7 +415,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
// Debug.LogWarning($"Could not read field {fieldInfo.Name} on {componentType.Name}");
|
// McpLog.Warn($"Could not read field {fieldInfo.Name} on {componentType.Name}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// --- End Use cached metadata ---
|
// --- End Use cached metadata ---
|
||||||
|
|
@ -452,7 +452,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
// Catch potential errors during JToken conversion or addition to dictionary
|
// Catch potential errors during JToken conversion or addition to dictionary
|
||||||
Debug.LogWarning($"[AddSerializableValue] Error processing value for '{name}' (Type: {type.FullName}): {e.Message}. Skipping.");
|
McpLog.Warn($"[AddSerializableValue] Error processing value for '{name}' (Type: {type.FullName}): {e.Message}. Skipping.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -508,7 +508,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
{
|
{
|
||||||
return jValue.Value;
|
return jValue.Value;
|
||||||
}
|
}
|
||||||
// Debug.LogWarning($"Unsupported JTokenType encountered: {token.Type}. Returning null.");
|
// McpLog.Warn($"Unsupported JTokenType encountered: {token.Type}. Returning null.");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -545,12 +545,12 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
}
|
}
|
||||||
catch (JsonSerializationException e)
|
catch (JsonSerializationException e)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[GameObjectSerializer] Newtonsoft.Json Error serializing value of type {type.FullName}: {e.Message}. Skipping property/field.");
|
McpLog.Warn($"[GameObjectSerializer] Newtonsoft.Json Error serializing value of type {type.FullName}: {e.Message}. Skipping property/field.");
|
||||||
return null; // Indicate serialization failure
|
return null; // Indicate serialization failure
|
||||||
}
|
}
|
||||||
catch (Exception e) // Catch other unexpected errors
|
catch (Exception e) // Catch other unexpected errors
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[GameObjectSerializer] Unexpected error serializing value of type {type.FullName}: {e}. Skipping property/field.");
|
McpLog.Warn($"[GameObjectSerializer] Unexpected error serializing value of type {type.FullName}: {e}. Skipping property/field.");
|
||||||
return null; // Indicate serialization failure
|
return null; // Indicate serialization failure
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using MCPForUnity.Editor.Tools;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using UnityEngine;
|
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using MCPForUnity.Editor.Tools;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace MCPForUnity.Editor.Helpers
|
namespace MCPForUnity.Editor.Helpers
|
||||||
{
|
{
|
||||||
|
|
@ -63,7 +63,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[MaterialOps] Failed to parse color for property '{propName}': {ex.Message}");
|
McpLog.Warn($"[MaterialOps] Failed to parse color for property '{propName}': {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -81,7 +81,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[MaterialOps] Failed to parse color array: {ex.Message}");
|
McpLog.Warn($"[MaterialOps] Failed to parse color array: {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -104,7 +104,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[MaterialOps] Failed to set float property '{propName}': {ex.Message}");
|
McpLog.Warn($"[MaterialOps] Failed to set float property '{propName}': {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -235,13 +235,13 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
// Log at Debug level since we'll try other conversions
|
// Log at Debug level since we'll try other conversions
|
||||||
Debug.Log($"[MaterialOps] SetColor attempt for '{propertyName}' failed: {ex.Message}");
|
McpLog.Info($"[MaterialOps] SetColor attempt for '{propertyName}' failed: {ex.Message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
try { Vector4 vec = value.ToObject<Vector4>(serializer); material.SetVector(propertyName, vec); return true; }
|
try { Vector4 vec = value.ToObject<Vector4>(serializer); material.SetVector(propertyName, vec); return true; }
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.Log($"[MaterialOps] SetVector (Vec4) attempt for '{propertyName}' failed: {ex.Message}");
|
McpLog.Info($"[MaterialOps] SetVector (Vec4) attempt for '{propertyName}' failed: {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -252,7 +252,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
try { material.SetColor(propertyName, ParseColor(value, serializer)); return true; }
|
try { material.SetColor(propertyName, ParseColor(value, serializer)); return true; }
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.Log($"[MaterialOps] SetColor (Vec3) attempt for '{propertyName}' failed: {ex.Message}");
|
McpLog.Info($"[MaterialOps] SetColor (Vec3) attempt for '{propertyName}' failed: {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -263,7 +263,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
try { Vector2 vec = value.ToObject<Vector2>(serializer); material.SetVector(propertyName, vec); return true; }
|
try { Vector2 vec = value.ToObject<Vector2>(serializer); material.SetVector(propertyName, vec); return true; }
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.Log($"[MaterialOps] SetVector (Vec2) attempt for '{propertyName}' failed: {ex.Message}");
|
McpLog.Info($"[MaterialOps] SetVector (Vec2) attempt for '{propertyName}' failed: {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -276,7 +276,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
try { material.SetFloat(propertyName, value.ToObject<float>(serializer)); return true; }
|
try { material.SetFloat(propertyName, value.ToObject<float>(serializer)); return true; }
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.Log($"[MaterialOps] SetFloat attempt for '{propertyName}' failed: {ex.Message}");
|
McpLog.Info($"[MaterialOps] SetFloat attempt for '{propertyName}' failed: {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (value.Type == JTokenType.Boolean)
|
else if (value.Type == JTokenType.Boolean)
|
||||||
|
|
@ -287,7 +287,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
try { material.SetFloat(propertyName, value.ToObject<bool>(serializer) ? 1f : 0f); return true; }
|
try { material.SetFloat(propertyName, value.ToObject<bool>(serializer) ? 1f : 0f); return true; }
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.Log($"[MaterialOps] SetFloat (bool) attempt for '{propertyName}' failed: {ex.Message}");
|
McpLog.Info($"[MaterialOps] SetFloat (bool) attempt for '{propertyName}' failed: {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (value.Type == JTokenType.String)
|
else if (value.Type == JTokenType.String)
|
||||||
|
|
@ -298,16 +298,16 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
string path = value.ToString();
|
string path = value.ToString();
|
||||||
if (!string.IsNullOrEmpty(path) && path.Contains("/")) // Heuristic: paths usually have slashes
|
if (!string.IsNullOrEmpty(path) && path.Contains("/")) // Heuristic: paths usually have slashes
|
||||||
{
|
{
|
||||||
// We need to handle texture assignment here.
|
// We need to handle texture assignment here.
|
||||||
// Since we don't have easy access to AssetDatabase here directly without using UnityEditor namespace (which is imported),
|
// Since we don't have easy access to AssetDatabase here directly without using UnityEditor namespace (which is imported),
|
||||||
// we can try to load it.
|
// we can try to load it.
|
||||||
var sanitizedPath = AssetPathUtility.SanitizeAssetPath(path);
|
var sanitizedPath = AssetPathUtility.SanitizeAssetPath(path);
|
||||||
Texture tex = AssetDatabase.LoadAssetAtPath<Texture>(sanitizedPath);
|
Texture tex = AssetDatabase.LoadAssetAtPath<Texture>(sanitizedPath);
|
||||||
if (tex != null && material.HasProperty(propertyName))
|
if (tex != null && material.HasProperty(propertyName))
|
||||||
{
|
{
|
||||||
material.SetTexture(propertyName, tex);
|
material.SetTexture(propertyName, tex);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
@ -318,7 +318,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
|
|
||||||
if (value.Type == JTokenType.Object)
|
if (value.Type == JTokenType.Object)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Texture texture = value.ToObject<Texture>(serializer);
|
Texture texture = value.ToObject<Texture>(serializer);
|
||||||
if (texture != null && material.HasProperty(propertyName))
|
if (texture != null && material.HasProperty(propertyName))
|
||||||
|
|
@ -333,7 +333,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.LogWarning(
|
McpLog.Warn(
|
||||||
$"[MaterialOps] Unsupported or failed conversion for material property '{propertyName}' from value: {value.ToString(Formatting.None)}"
|
$"[MaterialOps] Unsupported or failed conversion for material property '{propertyName}' from value: {value.ToString(Formatting.None)}"
|
||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -389,7 +389,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[MaterialOps] Failed to parse color from token: {ex.Message}");
|
McpLog.Warn($"[MaterialOps] Failed to parse color from token: {ex.Message}");
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"Error reading existing config: {e.Message}.");
|
McpLog.Warn($"Error reading existing config: {e.Message}.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -71,7 +71,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
// If user has partial/invalid JSON (e.g., mid-edit), start from a fresh object
|
// If user has partial/invalid JSON (e.g., mid-edit), start from a fresh object
|
||||||
if (!string.IsNullOrWhiteSpace(existingJson))
|
if (!string.IsNullOrWhiteSpace(existingJson))
|
||||||
{
|
{
|
||||||
Debug.LogWarning("UnityMCP: Configuration file could not be parsed; rewriting server block.");
|
McpLog.Warn("UnityMCP: Configuration file could not be parsed; rewriting server block.");
|
||||||
}
|
}
|
||||||
existingConfig = new JObject();
|
existingConfig = new JObject();
|
||||||
}
|
}
|
||||||
|
|
@ -137,7 +137,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"UnityMCP: Failed to read Codex config '{configPath}': {e.Message}");
|
McpLog.Warn($"UnityMCP: Failed to read Codex config '{configPath}': {e.Message}");
|
||||||
existingToml = string.Empty;
|
existingToml = string.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using MCPForUnity.Editor.Helpers;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
@ -39,7 +40,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(findTerm))
|
if (string.IsNullOrEmpty(findTerm))
|
||||||
{
|
{
|
||||||
Debug.LogWarning("[ObjectResolver] Find instruction missing 'find' term.");
|
McpLog.Warn("[ObjectResolver] Find instruction missing 'find' term.");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -85,20 +86,20 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[ObjectResolver] Could not find component type '{componentName}'. Falling back to target type '{targetType.Name}'.");
|
McpLog.Warn($"[ObjectResolver] Could not find component type '{componentName}'. Falling back to target type '{targetType.Name}'.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Component foundComp = foundGo.GetComponent(componentToGetType);
|
Component foundComp = foundGo.GetComponent(componentToGetType);
|
||||||
if (foundComp == null)
|
if (foundComp == null)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[ObjectResolver] Found GameObject '{foundGo.name}' but could not find component of type '{componentToGetType.Name}'.");
|
McpLog.Warn($"[ObjectResolver] Found GameObject '{foundGo.name}' but could not find component of type '{componentToGetType.Name}'.");
|
||||||
}
|
}
|
||||||
return foundComp;
|
return foundComp;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[ObjectResolver] Find instruction handling not implemented for target type: {targetType.Name}");
|
McpLog.Warn($"[ObjectResolver] Find instruction handling not implemented for target type: {targetType.Name}");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -190,7 +191,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
}
|
}
|
||||||
else if (guids.Length > 1)
|
else if (guids.Length > 1)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[ObjectResolver] Ambiguous asset find: Found {guids.Length} assets matching filter '{searchFilter}'. Provide a full path or unique name.");
|
McpLog.Warn($"[ObjectResolver] Ambiguous asset find: Found {guids.Length} assets matching filter '{searchFilter}'. Provide a full path or unique name.");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
using MCPForUnity.Editor.Helpers;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
|
|
@ -24,7 +25,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
{
|
{
|
||||||
if (targetType.IsValueType && Nullable.GetUnderlyingType(targetType) == null)
|
if (targetType.IsValueType && Nullable.GetUnderlyingType(targetType) == null)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[PropertyConversion] Cannot assign null to non-nullable value type {targetType.Name}. Returning default value.");
|
McpLog.Warn($"[PropertyConversion] Cannot assign null to non-nullable value type {targetType.Name}. Returning default value.");
|
||||||
return Activator.CreateInstance(targetType);
|
return Activator.CreateInstance(targetType);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -37,7 +38,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogError($"Error converting token to {targetType.FullName}: {ex.Message}\nToken: {token.ToString(Formatting.None)}");
|
McpLog.Error($"Error converting token to {targetType.FullName}: {ex.Message}\nToken: {token.ToString(Formatting.None)}");
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -82,7 +83,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
|
|
||||||
if (loadedAsset == null)
|
if (loadedAsset == null)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[PropertyConversion] Could not load asset of type {targetType.Name} from path: {assetPath}");
|
McpLog.Warn($"[PropertyConversion] Could not load asset of type {targetType.Name} from path: {assetPath}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return loadedAsset;
|
return loadedAsset;
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[VectorParsing] Failed to parse Vector3 from '{token}': {ex.Message}");
|
McpLog.Warn($"[VectorParsing] Failed to parse Vector3 from '{token}': {ex.Message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -90,7 +90,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[VectorParsing] Failed to parse Vector2 from '{token}': {ex.Message}");
|
McpLog.Warn($"[VectorParsing] Failed to parse Vector2 from '{token}': {ex.Message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -162,7 +162,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[VectorParsing] Failed to parse Quaternion from '{token}': {ex.Message}");
|
McpLog.Warn($"[VectorParsing] Failed to parse Quaternion from '{token}': {ex.Message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -218,7 +218,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[VectorParsing] Failed to parse Color from '{token}': {ex.Message}");
|
McpLog.Warn($"[VectorParsing] Failed to parse Color from '{token}': {ex.Message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -260,7 +260,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[VectorParsing] Failed to parse Rect from '{token}': {ex.Message}");
|
McpLog.Warn($"[VectorParsing] Failed to parse Rect from '{token}': {ex.Message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -286,7 +286,7 @@ namespace MCPForUnity.Editor.Helpers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[VectorParsing] Failed to parse Bounds from '{token}': {ex.Message}");
|
McpLog.Warn($"[VectorParsing] Failed to parse Bounds from '{token}': {ex.Message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ namespace MCPForUnity.Editor.Resources.Editor
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"Could not get info for window {window.GetType().Name}: {ex.Message}");
|
McpLog.Warn($"Could not get info for window {window.GetType().Name}: {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ namespace MCPForUnity.Editor.Resources.Scene
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogError($"[GameObjectResource] Error getting GameObject: {e}");
|
McpLog.Error($"[GameObjectResource] Error getting GameObject: {e}");
|
||||||
return new ErrorResponse($"Error getting GameObject: {e.Message}");
|
return new ErrorResponse($"Error getting GameObject: {e.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -199,7 +199,7 @@ namespace MCPForUnity.Editor.Resources.Scene
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogError($"[GameObjectComponentsResource] Error getting components: {e}");
|
McpLog.Error($"[GameObjectComponentsResource] Error getting components: {e}");
|
||||||
return new ErrorResponse($"Error getting components: {e.Message}");
|
return new ErrorResponse($"Error getting components: {e.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -276,7 +276,7 @@ namespace MCPForUnity.Editor.Resources.Scene
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogError($"[GameObjectComponentResource] Error getting component: {e}");
|
McpLog.Error($"[GameObjectComponentResource] Error getting component: {e}");
|
||||||
return new ErrorResponse($"Error getting component: {e.Message}");
|
return new ErrorResponse($"Error getting component: {e.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
catch (System.Exception ex)
|
catch (System.Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogError($"[FindGameObjects] Error searching GameObjects: {ex.Message}");
|
McpLog.Error($"[FindGameObjects] Error searching GameObjects: {ex.Message}");
|
||||||
return new ErrorResponse($"Error searching GameObjects: {ex.Message}");
|
return new ErrorResponse($"Error searching GameObjects: {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
using MCPForUnity.Editor.Helpers;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
|
|
@ -22,7 +23,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
catch (Newtonsoft.Json.JsonReaderException e)
|
catch (Newtonsoft.Json.JsonReaderException e)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[MCP] Could not parse '{paramName}' JSON string: {e.Message}");
|
McpLog.Warn($"[MCP] Could not parse '{paramName}' JSON string: {e.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[ManageAsset] Could not parse 'properties' JSON string: {e.Message}");
|
McpLog.Warn($"[ManageAsset] Could not parse 'properties' JSON string: {e.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -119,7 +119,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogError($"[ManageAsset] Action '{action}' failed for path '{path}': {e}");
|
McpLog.Error($"[ManageAsset] Action '{action}' failed for path '{path}': {e}");
|
||||||
return new ErrorResponse(
|
return new ErrorResponse(
|
||||||
$"Internal error processing action '{action}' on '{path}': {e.Message}"
|
$"Internal error processing action '{action}' on '{path}': {e.Message}"
|
||||||
);
|
);
|
||||||
|
|
@ -143,7 +143,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
// applying properties via reflection or specific methods, saving, then reimporting.
|
// applying properties via reflection or specific methods, saving, then reimporting.
|
||||||
if (properties != null && properties.HasValues)
|
if (properties != null && properties.HasValues)
|
||||||
{
|
{
|
||||||
Debug.LogWarning(
|
McpLog.Warn(
|
||||||
"[ManageAsset.Reimport] Modifying importer properties before reimport is not fully implemented yet."
|
"[ManageAsset.Reimport] Modifying importer properties before reimport is not fully implemented yet."
|
||||||
);
|
);
|
||||||
// AssetImporter importer = AssetImporter.GetAtPath(fullPath);
|
// AssetImporter importer = AssetImporter.GetAtPath(fullPath);
|
||||||
|
|
@ -376,7 +376,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
// Only warn about resolution failure if component also not found
|
// Only warn about resolution failure if component also not found
|
||||||
if (targetComponent == null && !resolved)
|
if (targetComponent == null && !resolved)
|
||||||
{
|
{
|
||||||
Debug.LogWarning(
|
McpLog.Warn(
|
||||||
$"[ManageAsset.ModifyAsset] Failed to resolve component '{componentName}' on '{gameObject.name}': {compError}"
|
$"[ManageAsset.ModifyAsset] Failed to resolve component '{componentName}' on '{gameObject.name}': {compError}"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -393,7 +393,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Log a warning if a specified component couldn't be found
|
// Log a warning if a specified component couldn't be found
|
||||||
Debug.LogWarning(
|
McpLog.Warn(
|
||||||
$"[ManageAsset.ModifyAsset] Component '{componentName}' not found on GameObject '{gameObject.name}' in asset '{fullPath}'. Skipping modification for this component."
|
$"[ManageAsset.ModifyAsset] Component '{componentName}' not found on GameObject '{gameObject.name}' in asset '{fullPath}'. Skipping modification for this component."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -403,7 +403,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
// Log a warning if the structure isn't {"ComponentName": {"prop": value}}
|
// Log a warning if the structure isn't {"ComponentName": {"prop": value}}
|
||||||
// We could potentially try to apply this property directly to the GameObject here if needed,
|
// We could potentially try to apply this property directly to the GameObject here if needed,
|
||||||
// but the primary goal is component modification.
|
// but the primary goal is component modification.
|
||||||
Debug.LogWarning(
|
McpLog.Warn(
|
||||||
$"[ManageAsset.ModifyAsset] Property '{prop.Name}' for GameObject modification should have a JSON object value containing component properties. Value was: {prop.Value.Type}. Skipping."
|
$"[ManageAsset.ModifyAsset] Property '{prop.Name}' for GameObject modification should have a JSON object value containing component properties. Value was: {prop.Value.Type}. Skipping."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -444,7 +444,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"Could not get TextureImporter for {fullPath}.");
|
McpLog.Warn($"Could not get TextureImporter for {fullPath}.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: Add modification logic for other common asset types (Models, AudioClips importers, etc.)
|
// TODO: Add modification logic for other common asset types (Models, AudioClips importers, etc.)
|
||||||
|
|
@ -452,7 +452,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
{
|
{
|
||||||
// This block handles non-GameObject/Material/ScriptableObject/Texture assets.
|
// This block handles non-GameObject/Material/ScriptableObject/Texture assets.
|
||||||
// Attempts to apply properties directly to the asset itself.
|
// Attempts to apply properties directly to the asset itself.
|
||||||
Debug.LogWarning(
|
McpLog.Warn(
|
||||||
$"[ManageAsset.ModifyAsset] Asset type '{asset.GetType().Name}' at '{fullPath}' is not explicitly handled for component modification. Attempting generic property setting on the asset itself."
|
$"[ManageAsset.ModifyAsset] Asset type '{asset.GetType().Name}' at '{fullPath}' is not explicitly handled for component modification. Attempting generic property setting on the asset itself."
|
||||||
);
|
);
|
||||||
modified |= ApplyObjectProperties(asset, properties);
|
modified |= ApplyObjectProperties(asset, properties);
|
||||||
|
|
@ -486,7 +486,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
// Log the detailed error internally
|
// Log the detailed error internally
|
||||||
Debug.LogError($"[ManageAsset] Action 'modify' failed for path '{path}': {e}");
|
McpLog.Error($"[ManageAsset] Action 'modify' failed for path '{path}': {e}");
|
||||||
// Return a user-friendly error message
|
// Return a user-friendly error message
|
||||||
return new ErrorResponse($"Failed to modify asset '{fullPath}': {e.Message}");
|
return new ErrorResponse($"Failed to modify asset '{fullPath}': {e.Message}");
|
||||||
}
|
}
|
||||||
|
|
@ -648,7 +648,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
{
|
{
|
||||||
// Maybe the user provided a file path instead of a folder?
|
// Maybe the user provided a file path instead of a folder?
|
||||||
// We could search in the containing folder, or return an error.
|
// We could search in the containing folder, or return an error.
|
||||||
Debug.LogWarning(
|
McpLog.Warn(
|
||||||
$"Search path '{folderScope[0]}' is not a valid folder. Searching entire project."
|
$"Search path '{folderScope[0]}' is not a valid folder. Searching entire project."
|
||||||
);
|
);
|
||||||
folderScope = null; // Search everywhere if path isn't a folder
|
folderScope = null; // Search everywhere if path isn't a folder
|
||||||
|
|
@ -671,7 +671,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning(
|
McpLog.Warn(
|
||||||
$"Could not parse filterDateAfter: '{filterDateAfterStr}'. Expected ISO 8601 format."
|
$"Could not parse filterDateAfter: '{filterDateAfterStr}'. Expected ISO 8601 format."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -816,7 +816,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogError(
|
McpLog.Error(
|
||||||
$"[ManageAsset.GetComponentsFromAsset] Error getting components for '{fullPath}': {e}"
|
$"[ManageAsset.GetComponentsFromAsset] Error getting components for '{fullPath}': {e}"
|
||||||
);
|
);
|
||||||
return new ErrorResponse(
|
return new ErrorResponse(
|
||||||
|
|
@ -1018,7 +1018,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogWarning(
|
McpLog.Warn(
|
||||||
$"[SetPropertyOrField] Failed to set '{memberName}' on {type.Name}: {ex.Message}"
|
$"[SetPropertyOrField] Failed to set '{memberName}' on {type.Name}: {ex.Message}"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -1081,7 +1081,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogWarning(
|
McpLog.Warn(
|
||||||
$"Failed to generate readable preview for '{path}': {ex.Message}. Preview might not be readable."
|
$"Failed to generate readable preview for '{path}': {ex.Message}. Preview might not be readable."
|
||||||
);
|
);
|
||||||
// Fallback: Try getting static preview if available?
|
// Fallback: Try getting static preview if available?
|
||||||
|
|
@ -1090,7 +1090,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning(
|
McpLog.Warn(
|
||||||
$"Could not get asset preview for {path} (Type: {assetType?.Name}). Is it supported?"
|
$"Could not get asset preview for {path} (Type: {assetType?.Name}). Is it supported?"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogError($"[ManageComponents] Action '{action}' failed: {e}");
|
McpLog.Error($"[ManageComponents] Action '{action}' failed: {e}");
|
||||||
return new ErrorResponse($"Internal error processing action '{action}': {e.Message}");
|
return new ErrorResponse($"Internal error processing action '{action}': {e.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -303,7 +303,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
|
|
||||||
if (errors.Count > 0)
|
if (errors.Count > 0)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[ManageComponents] Some properties failed to set on {component.GetType().Name}: {string.Join(", ", errors)}");
|
McpLog.Warn($"[ManageComponents] Some properties failed to set on {component.GetType().Name}: {string.Join(", ", errors)}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -321,7 +321,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
return null; // Success
|
return null; // Success
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.LogWarning($"[ManageComponents] {error}");
|
McpLog.Warn($"[ManageComponents] {error}");
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[ManageGameObject] Could not parse 'componentProperties' JSON string: {e.Message}");
|
McpLog.Warn($"[ManageGameObject] Could not parse 'componentProperties' JSON string: {e.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -116,7 +116,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogError($"[ManageGameObject] Action '{action}' failed: {e}");
|
McpLog.Error($"[ManageGameObject] Action '{action}' failed: {e}");
|
||||||
return new ErrorResponse($"Internal error processing action '{action}': {e.Message}");
|
return new ErrorResponse($"Internal error processing action '{action}': {e.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -149,7 +149,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
string prefabNameOnly = prefabPath;
|
string prefabNameOnly = prefabPath;
|
||||||
Debug.Log(
|
McpLog.Info(
|
||||||
$"[ManageGameObject.Create] Searching for prefab named: '{prefabNameOnly}'"
|
$"[ManageGameObject.Create] Searching for prefab named: '{prefabNameOnly}'"
|
||||||
);
|
);
|
||||||
string[] guids = AssetDatabase.FindAssets($"t:Prefab {prefabNameOnly}");
|
string[] guids = AssetDatabase.FindAssets($"t:Prefab {prefabNameOnly}");
|
||||||
|
|
@ -172,7 +172,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
else // Exactly one found
|
else // Exactly one found
|
||||||
{
|
{
|
||||||
prefabPath = AssetDatabase.GUIDToAssetPath(guids[0]); // Update prefabPath with the full path
|
prefabPath = AssetDatabase.GUIDToAssetPath(guids[0]); // Update prefabPath with the full path
|
||||||
Debug.Log(
|
McpLog.Info(
|
||||||
$"[ManageGameObject.Create] Found unique prefab at path: '{prefabPath}'"
|
$"[ManageGameObject.Create] Found unique prefab at path: '{prefabPath}'"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -180,7 +180,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
else if (!prefabPath.EndsWith(".prefab", StringComparison.OrdinalIgnoreCase))
|
else if (!prefabPath.EndsWith(".prefab", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
// If it looks like a path but doesn't end with .prefab, assume user forgot it and append it.
|
// If it looks like a path but doesn't end with .prefab, assume user forgot it and append it.
|
||||||
Debug.LogWarning(
|
McpLog.Warn(
|
||||||
$"[ManageGameObject.Create] Provided prefabPath '{prefabPath}' does not end with .prefab. Assuming it's missing and appending."
|
$"[ManageGameObject.Create] Provided prefabPath '{prefabPath}' does not end with .prefab. Assuming it's missing and appending."
|
||||||
);
|
);
|
||||||
prefabPath += ".prefab";
|
prefabPath += ".prefab";
|
||||||
|
|
@ -200,7 +200,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
if (newGo == null)
|
if (newGo == null)
|
||||||
{
|
{
|
||||||
// This might happen if the asset exists but isn't a valid GameObject prefab somehow
|
// This might happen if the asset exists but isn't a valid GameObject prefab somehow
|
||||||
Debug.LogError(
|
McpLog.Error(
|
||||||
$"[ManageGameObject.Create] Failed to instantiate prefab at '{prefabPath}', asset might be corrupted or not a GameObject."
|
$"[ManageGameObject.Create] Failed to instantiate prefab at '{prefabPath}', asset might be corrupted or not a GameObject."
|
||||||
);
|
);
|
||||||
return new ErrorResponse(
|
return new ErrorResponse(
|
||||||
|
|
@ -217,7 +217,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
newGo,
|
newGo,
|
||||||
$"Instantiate Prefab '{prefabAsset.name}' as '{newGo.name}'"
|
$"Instantiate Prefab '{prefabAsset.name}' as '{newGo.name}'"
|
||||||
);
|
);
|
||||||
Debug.Log(
|
McpLog.Info(
|
||||||
$"[ManageGameObject.Create] Instantiated prefab '{prefabAsset.name}' from path '{prefabPath}' as '{newGo.name}'."
|
$"[ManageGameObject.Create] Instantiated prefab '{prefabAsset.name}' from path '{prefabPath}' as '{newGo.name}'."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -232,7 +232,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
{
|
{
|
||||||
// Only return error if prefabPath was specified but not found.
|
// Only return error if prefabPath was specified but not found.
|
||||||
// If prefabPath was empty/null, we proceed to create primitive/empty.
|
// If prefabPath was empty/null, we proceed to create primitive/empty.
|
||||||
Debug.LogWarning(
|
McpLog.Warn(
|
||||||
$"[ManageGameObject.Create] Prefab asset not found at path: '{prefabPath}'. Will proceed to create new object if specified."
|
$"[ManageGameObject.Create] Prefab asset not found at path: '{prefabPath}'. Will proceed to create new object if specified."
|
||||||
);
|
);
|
||||||
// Do not return error here, allow fallback to primitive/empty creation
|
// Do not return error here, allow fallback to primitive/empty creation
|
||||||
|
|
@ -337,7 +337,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
// Check if tag exists first (Unity doesn't throw exceptions for undefined tags, just logs a warning)
|
// Check if tag exists first (Unity doesn't throw exceptions for undefined tags, just logs a warning)
|
||||||
if (tag != "Untagged" && !System.Linq.Enumerable.Contains(InternalEditorUtility.tags, tag))
|
if (tag != "Untagged" && !System.Linq.Enumerable.Contains(InternalEditorUtility.tags, tag))
|
||||||
{
|
{
|
||||||
Debug.Log($"[ManageGameObject.Create] Tag '{tag}' not found. Creating it.");
|
McpLog.Info($"[ManageGameObject.Create] Tag '{tag}' not found. Creating it.");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
InternalEditorUtility.AddTag(tag);
|
InternalEditorUtility.AddTag(tag);
|
||||||
|
|
@ -371,7 +371,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning(
|
McpLog.Warn(
|
||||||
$"[ManageGameObject.Create] Layer '{layerName}' not found. Using default layer."
|
$"[ManageGameObject.Create] Layer '{layerName}' not found. Using default layer."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -406,7 +406,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning(
|
McpLog.Warn(
|
||||||
$"[ManageGameObject] Invalid component format in componentsToAdd: {compToken}"
|
$"[ManageGameObject] Invalid component format in componentsToAdd: {compToken}"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -430,7 +430,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
// Ensure the *saving* path ends with .prefab
|
// Ensure the *saving* path ends with .prefab
|
||||||
if (!finalPrefabPath.EndsWith(".prefab", StringComparison.OrdinalIgnoreCase))
|
if (!finalPrefabPath.EndsWith(".prefab", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
Debug.Log(
|
McpLog.Info(
|
||||||
$"[ManageGameObject.Create] Appending .prefab extension to save path: '{finalPrefabPath}' -> '{finalPrefabPath}.prefab'"
|
$"[ManageGameObject.Create] Appending .prefab extension to save path: '{finalPrefabPath}' -> '{finalPrefabPath}.prefab'"
|
||||||
);
|
);
|
||||||
finalPrefabPath += ".prefab";
|
finalPrefabPath += ".prefab";
|
||||||
|
|
@ -447,7 +447,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
{
|
{
|
||||||
System.IO.Directory.CreateDirectory(directoryPath);
|
System.IO.Directory.CreateDirectory(directoryPath);
|
||||||
AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport); // Refresh asset database to recognize the new folder
|
AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport); // Refresh asset database to recognize the new folder
|
||||||
Debug.Log(
|
McpLog.Info(
|
||||||
$"[ManageGameObject.Create] Created directory for prefab: {directoryPath}"
|
$"[ManageGameObject.Create] Created directory for prefab: {directoryPath}"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -466,7 +466,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
$"Failed to save GameObject '{name}' as prefab at '{finalPrefabPath}'. Check path and permissions."
|
$"Failed to save GameObject '{name}' as prefab at '{finalPrefabPath}'. Check path and permissions."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Debug.Log(
|
McpLog.Info(
|
||||||
$"[ManageGameObject.Create] GameObject '{name}' saved as prefab to '{finalPrefabPath}' and instance connected."
|
$"[ManageGameObject.Create] GameObject '{name}' saved as prefab to '{finalPrefabPath}' and instance connected."
|
||||||
);
|
);
|
||||||
// Mark the new prefab asset as dirty? Not usually necessary, SaveAsPrefabAsset handles it.
|
// Mark the new prefab asset as dirty? Not usually necessary, SaveAsPrefabAsset handles it.
|
||||||
|
|
@ -593,7 +593,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
// Check if tag exists first (Unity doesn't throw exceptions for undefined tags, just logs a warning)
|
// Check if tag exists first (Unity doesn't throw exceptions for undefined tags, just logs a warning)
|
||||||
if (tagToSet != "Untagged" && !System.Linq.Enumerable.Contains(InternalEditorUtility.tags, tagToSet))
|
if (tagToSet != "Untagged" && !System.Linq.Enumerable.Contains(InternalEditorUtility.tags, tagToSet))
|
||||||
{
|
{
|
||||||
Debug.Log($"[ManageGameObject] Tag '{tagToSet}' not found. Creating it.");
|
McpLog.Info($"[ManageGameObject] Tag '{tagToSet}' not found. Creating it.");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
InternalEditorUtility.AddTag(tagToSet);
|
InternalEditorUtility.AddTag(tagToSet);
|
||||||
|
|
@ -850,7 +850,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[ManageGameObject.Duplicate] Parent '{parentToken}' not found. Keeping original parent.");
|
McpLog.Warn($"[ManageGameObject.Duplicate] Parent '{parentToken}' not found. Keeping original parent.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -976,7 +976,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
case "forward": case "front": return Vector3.forward;
|
case "forward": case "front": return Vector3.forward;
|
||||||
case "back": case "backward": case "behind": return Vector3.back;
|
case "back": case "backward": case "behind": return Vector3.back;
|
||||||
default:
|
default:
|
||||||
Debug.LogWarning($"[ManageGameObject.MoveRelative] Unknown direction '{direction}', defaulting to forward.");
|
McpLog.Warn($"[ManageGameObject.MoveRelative] Unknown direction '{direction}', defaulting to forward.");
|
||||||
return Vector3.forward;
|
return Vector3.forward;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -992,7 +992,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
case "forward": case "front": return referenceTransform.forward;
|
case "forward": case "front": return referenceTransform.forward;
|
||||||
case "back": case "backward": case "behind": return -referenceTransform.forward;
|
case "back": case "backward": case "behind": return -referenceTransform.forward;
|
||||||
default:
|
default:
|
||||||
Debug.LogWarning($"[ManageGameObject.MoveRelative] Unknown direction '{direction}', defaulting to forward.");
|
McpLog.Warn($"[ManageGameObject.MoveRelative] Unknown direction '{direction}', defaulting to forward.");
|
||||||
return referenceTransform.forward;
|
return referenceTransform.forward;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1057,7 +1057,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"Failed to parse JArray as Vector3: {array}. Error: {ex.Message}");
|
McpLog.Warn($"Failed to parse JArray as Vector3: {array}. Error: {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -1124,7 +1124,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
rootSearchObject = FindObjectInternal(targetToken, "by_id_or_name_or_path"); // Find the root for child search
|
rootSearchObject = FindObjectInternal(targetToken, "by_id_or_name_or_path"); // Find the root for child search
|
||||||
if (rootSearchObject == null)
|
if (rootSearchObject == null)
|
||||||
{
|
{
|
||||||
Debug.LogWarning(
|
McpLog.Warn(
|
||||||
$"[ManageGameObject.Find] Root object '{targetToken}' for child search not found."
|
$"[ManageGameObject.Find] Root object '{targetToken}' for child search not found."
|
||||||
);
|
);
|
||||||
return results; // Return empty if root not found
|
return results; // Return empty if root not found
|
||||||
|
|
@ -1209,7 +1209,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning(
|
McpLog.Warn(
|
||||||
$"[ManageGameObject.Find] Component type not found: {searchTerm}"
|
$"[ManageGameObject.Find] Component type not found: {searchTerm}"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -1238,7 +1238,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
results.AddRange(allObjectsName.Where(go => go.name == searchTerm));
|
results.AddRange(allObjectsName.Where(go => go.name == searchTerm));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Debug.LogWarning(
|
McpLog.Warn(
|
||||||
$"[ManageGameObject.Find] Unknown search method: {searchMethod}"
|
$"[ManageGameObject.Find] Unknown search method: {searchMethod}"
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
@ -1465,13 +1465,13 @@ namespace MCPForUnity.Editor.Tools
|
||||||
var msg = suggestions.Any()
|
var msg = suggestions.Any()
|
||||||
? $"Property '{propName}' not found. Did you mean: {string.Join(", ", suggestions)}? Available: [{string.Join(", ", availableProperties)}]"
|
? $"Property '{propName}' not found. Did you mean: {string.Join(", ", suggestions)}? Available: [{string.Join(", ", availableProperties)}]"
|
||||||
: $"Property '{propName}' not found. Available: [{string.Join(", ", availableProperties)}]";
|
: $"Property '{propName}' not found. Available: [{string.Join(", ", availableProperties)}]";
|
||||||
Debug.LogWarning($"[ManageGameObject] {msg}");
|
McpLog.Warn($"[ManageGameObject] {msg}");
|
||||||
failures.Add(msg);
|
failures.Add(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogError(
|
McpLog.Error(
|
||||||
$"[ManageGameObject] Error setting property '{propName}' on '{compName}': {e.Message}"
|
$"[ManageGameObject] Error setting property '{propName}' on '{compName}': {e.Message}"
|
||||||
);
|
);
|
||||||
failures.Add($"Error setting '{propName}': {e.Message}");
|
failures.Add($"Error setting '{propName}': {e.Message}");
|
||||||
|
|
@ -1522,7 +1522,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[SetProperty] Conversion failed for property '{memberName}' (Type: {propInfo.PropertyType.Name}) from token: {value.ToString(Formatting.None)}");
|
McpLog.Warn($"[SetProperty] Conversion failed for property '{memberName}' (Type: {propInfo.PropertyType.Name}) from token: {value.ToString(Formatting.None)}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1541,7 +1541,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[SetProperty] Conversion failed for field '{memberName}' (Type: {fieldInfo.FieldType.Name}) from token: {value.ToString(Formatting.None)}");
|
McpLog.Warn($"[SetProperty] Conversion failed for field '{memberName}' (Type: {fieldInfo.FieldType.Name}) from token: {value.ToString(Formatting.None)}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1563,7 +1563,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogError(
|
McpLog.Error(
|
||||||
$"[SetProperty] Failed to set '{memberName}' on {type.Name}: {ex.Message}\nToken: {value.ToString(Formatting.None)}"
|
$"[SetProperty] Failed to set '{memberName}' on {type.Name}: {ex.Message}\nToken: {value.ToString(Formatting.None)}"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -1622,7 +1622,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
fieldInfo = currentType.GetField(part, flags);
|
fieldInfo = currentType.GetField(part, flags);
|
||||||
if (fieldInfo == null)
|
if (fieldInfo == null)
|
||||||
{
|
{
|
||||||
Debug.LogWarning(
|
McpLog.Warn(
|
||||||
$"[SetNestedProperty] Could not find property or field '{part}' on type '{currentType.Name}'"
|
$"[SetNestedProperty] Could not find property or field '{part}' on type '{currentType.Name}'"
|
||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1637,7 +1637,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
//Need to stop if current property is null
|
//Need to stop if current property is null
|
||||||
if (currentObject == null)
|
if (currentObject == null)
|
||||||
{
|
{
|
||||||
Debug.LogWarning(
|
McpLog.Warn(
|
||||||
$"[SetNestedProperty] Property '{part}' is null, cannot access nested properties."
|
$"[SetNestedProperty] Property '{part}' is null, cannot access nested properties."
|
||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1650,7 +1650,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
var materials = currentObject as Material[];
|
var materials = currentObject as Material[];
|
||||||
if (arrayIndex < 0 || arrayIndex >= materials.Length)
|
if (arrayIndex < 0 || arrayIndex >= materials.Length)
|
||||||
{
|
{
|
||||||
Debug.LogWarning(
|
McpLog.Warn(
|
||||||
$"[SetNestedProperty] Material index {arrayIndex} out of range (0-{materials.Length - 1})"
|
$"[SetNestedProperty] Material index {arrayIndex} out of range (0-{materials.Length - 1})"
|
||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1662,7 +1662,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
var list = currentObject as System.Collections.IList;
|
var list = currentObject as System.Collections.IList;
|
||||||
if (arrayIndex < 0 || arrayIndex >= list.Count)
|
if (arrayIndex < 0 || arrayIndex >= list.Count)
|
||||||
{
|
{
|
||||||
Debug.LogWarning(
|
McpLog.Warn(
|
||||||
$"[SetNestedProperty] Index {arrayIndex} out of range (0-{list.Count - 1})"
|
$"[SetNestedProperty] Index {arrayIndex} out of range (0-{list.Count - 1})"
|
||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1671,7 +1671,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning(
|
McpLog.Warn(
|
||||||
$"[SetNestedProperty] Property '{part}' is not an array or list, cannot access by index."
|
$"[SetNestedProperty] Property '{part}' is not an array or list, cannot access by index."
|
||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1702,7 +1702,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[SetNestedProperty] Final conversion failed for property '{finalPart}' (Type: {finalPropInfo.PropertyType.Name}) from token: {value.ToString(Formatting.None)}");
|
McpLog.Warn($"[SetNestedProperty] Final conversion failed for property '{finalPart}' (Type: {finalPropInfo.PropertyType.Name}) from token: {value.ToString(Formatting.None)}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1719,12 +1719,12 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[SetNestedProperty] Final conversion failed for field '{finalPart}' (Type: {finalFieldInfo.FieldType.Name}) from token: {value.ToString(Formatting.None)}");
|
McpLog.Warn($"[SetNestedProperty] Final conversion failed for field '{finalPart}' (Type: {finalFieldInfo.FieldType.Name}) from token: {value.ToString(Formatting.None)}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogWarning(
|
McpLog.Warn(
|
||||||
$"[SetNestedProperty] Could not find final writable property or field '{finalPart}' on type '{currentType.Name}'"
|
$"[SetNestedProperty] Could not find final writable property or field '{finalPart}' on type '{currentType.Name}'"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -1732,7 +1732,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogError(
|
McpLog.Error(
|
||||||
$"[SetNestedProperty] Error setting nested property '{path}': {ex.Message}\nToken: {value.ToString(Formatting.None)}"
|
$"[SetNestedProperty] Error setting nested property '{path}': {ex.Message}\nToken: {value.ToString(Formatting.None)}"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -1805,7 +1805,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
{
|
{
|
||||||
return new Vector3(arr[0].ToObject<float>(), arr[1].ToObject<float>(), arr[2].ToObject<float>());
|
return new Vector3(arr[0].ToObject<float>(), arr[1].ToObject<float>(), arr[2].ToObject<float>());
|
||||||
}
|
}
|
||||||
Debug.LogWarning($"Could not parse JToken '{token}' as Vector3 using fallback. Returning Vector3.zero.");
|
McpLog.Warn($"Could not parse JToken '{token}' as Vector3 using fallback. Returning Vector3.zero.");
|
||||||
return Vector3.zero;
|
return Vector3.zero;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1820,7 +1820,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
{
|
{
|
||||||
return new Vector2(arr[0].ToObject<float>(), arr[1].ToObject<float>());
|
return new Vector2(arr[0].ToObject<float>(), arr[1].ToObject<float>());
|
||||||
}
|
}
|
||||||
Debug.LogWarning($"Could not parse JToken '{token}' as Vector2 using fallback. Returning Vector2.zero.");
|
McpLog.Warn($"Could not parse JToken '{token}' as Vector2 using fallback. Returning Vector2.zero.");
|
||||||
return Vector2.zero;
|
return Vector2.zero;
|
||||||
}
|
}
|
||||||
private static Quaternion ParseJTokenToQuaternion(JToken token)
|
private static Quaternion ParseJTokenToQuaternion(JToken token)
|
||||||
|
|
@ -1834,7 +1834,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
{
|
{
|
||||||
return new Quaternion(arr[0].ToObject<float>(), arr[1].ToObject<float>(), arr[2].ToObject<float>(), arr[3].ToObject<float>());
|
return new Quaternion(arr[0].ToObject<float>(), arr[1].ToObject<float>(), arr[2].ToObject<float>(), arr[3].ToObject<float>());
|
||||||
}
|
}
|
||||||
Debug.LogWarning($"Could not parse JToken '{token}' as Quaternion using fallback. Returning Quaternion.identity.");
|
McpLog.Warn($"Could not parse JToken '{token}' as Quaternion using fallback. Returning Quaternion.identity.");
|
||||||
return Quaternion.identity;
|
return Quaternion.identity;
|
||||||
}
|
}
|
||||||
private static Color ParseJTokenToColor(JToken token)
|
private static Color ParseJTokenToColor(JToken token)
|
||||||
|
|
@ -1848,7 +1848,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
{
|
{
|
||||||
return new Color(arr[0].ToObject<float>(), arr[1].ToObject<float>(), arr[2].ToObject<float>(), arr[3].ToObject<float>());
|
return new Color(arr[0].ToObject<float>(), arr[1].ToObject<float>(), arr[2].ToObject<float>(), arr[3].ToObject<float>());
|
||||||
}
|
}
|
||||||
Debug.LogWarning($"Could not parse JToken '{token}' as Color using fallback. Returning Color.white.");
|
McpLog.Warn($"Could not parse JToken '{token}' as Color using fallback. Returning Color.white.");
|
||||||
return Color.white;
|
return Color.white;
|
||||||
}
|
}
|
||||||
private static Rect ParseJTokenToRect(JToken token)
|
private static Rect ParseJTokenToRect(JToken token)
|
||||||
|
|
@ -1862,7 +1862,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
{
|
{
|
||||||
return new Rect(arr[0].ToObject<float>(), arr[1].ToObject<float>(), arr[2].ToObject<float>(), arr[3].ToObject<float>());
|
return new Rect(arr[0].ToObject<float>(), arr[1].ToObject<float>(), arr[2].ToObject<float>(), arr[3].ToObject<float>());
|
||||||
}
|
}
|
||||||
Debug.LogWarning($"Could not parse JToken '{token}' as Rect using fallback. Returning Rect.zero.");
|
McpLog.Warn($"Could not parse JToken '{token}' as Rect using fallback. Returning Rect.zero.");
|
||||||
return Rect.zero;
|
return Rect.zero;
|
||||||
}
|
}
|
||||||
private static Bounds ParseJTokenToBounds(JToken token)
|
private static Bounds ParseJTokenToBounds(JToken token)
|
||||||
|
|
@ -1880,7 +1880,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
// {
|
// {
|
||||||
// return new Bounds(new Vector3(arr[0].ToObject<float>(), arr[1].ToObject<float>(), arr[2].ToObject<float>()), new Vector3(arr[3].ToObject<float>(), arr[4].ToObject<float>(), arr[5].ToObject<float>()));
|
// return new Bounds(new Vector3(arr[0].ToObject<float>(), arr[1].ToObject<float>(), arr[2].ToObject<float>()), new Vector3(arr[3].ToObject<float>(), arr[4].ToObject<float>(), arr[5].ToObject<float>()));
|
||||||
// }
|
// }
|
||||||
Debug.LogWarning($"Could not parse JToken '{token}' as Bounds using fallback. Returning new Bounds(Vector3.zero, Vector3.zero).");
|
McpLog.Warn($"Could not parse JToken '{token}' as Bounds using fallback. Returning new Bounds(Vector3.zero, Vector3.zero).");
|
||||||
return new Bounds(Vector3.zero, Vector3.zero);
|
return new Bounds(Vector3.zero, Vector3.zero);
|
||||||
}
|
}
|
||||||
// --- End Redundant Parse Helpers ---
|
// --- End Redundant Parse Helpers ---
|
||||||
|
|
@ -1913,7 +1913,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
// Log the resolver error if type wasn't found
|
// Log the resolver error if type wasn't found
|
||||||
if (!string.IsNullOrEmpty(error))
|
if (!string.IsNullOrEmpty(error))
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[FindType] {error}");
|
McpLog.Warn($"[FindType] {error}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -1980,7 +1980,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[Property Matching] Error getting suggestions for '{userInput}': {ex.Message}");
|
McpLog.Warn($"[Property Matching] Error getting suggestions for '{userInput}': {ex.Message}");
|
||||||
return new List<string>();
|
return new List<string>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -263,7 +263,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
: new ErrorResponse("Validation failed.", result);
|
: new ErrorResponse("Validation failed.", result);
|
||||||
}
|
}
|
||||||
case "edit":
|
case "edit":
|
||||||
Debug.LogWarning("manage_script.edit is deprecated; prefer apply_text_edits. Serving structured edit for backward compatibility.");
|
McpLog.Warn("manage_script.edit is deprecated; prefer apply_text_edits. Serving structured edit for backward compatibility.");
|
||||||
var structEdits = @params["edits"] as JArray;
|
var structEdits = @params["edits"] as JArray;
|
||||||
var options = @params["options"] as JObject;
|
var options = @params["options"] as JObject;
|
||||||
return EditScript(fullPath, relativePath, name, structEdits, options);
|
return EditScript(fullPath, relativePath, name, structEdits, options);
|
||||||
|
|
@ -353,7 +353,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
else if (validationErrors != null && validationErrors.Length > 0)
|
else if (validationErrors != null && validationErrors.Length > 0)
|
||||||
{
|
{
|
||||||
// Log warnings but don't block creation
|
// Log warnings but don't block creation
|
||||||
Debug.LogWarning($"Script validation warnings for {name}:\n" + string.Join("\n", validationErrors));
|
McpLog.Warn($"Script validation warnings for {name}:\n" + string.Join("\n", validationErrors));
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
@ -451,7 +451,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
else if (validationErrors != null && validationErrors.Length > 0)
|
else if (validationErrors != null && validationErrors.Length > 0)
|
||||||
{
|
{
|
||||||
// Log warnings but don't block update
|
// Log warnings but don't block update
|
||||||
Debug.LogWarning($"Script validation warnings for {name}:\n" + string.Join("\n", validationErrors));
|
McpLog.Warn($"Script validation warnings for {name}:\n" + string.Join("\n", validationErrors));
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
@ -1405,7 +1405,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
if (!ValidateScriptSyntax(working, level, out var errors))
|
if (!ValidateScriptSyntax(working, level, out var errors))
|
||||||
return new ErrorResponse("validation_failed", new { status = "validation_failed", diagnostics = errors ?? Array.Empty<string>() });
|
return new ErrorResponse("validation_failed", new { status = "validation_failed", diagnostics = errors ?? Array.Empty<string>() });
|
||||||
else if (errors != null && errors.Length > 0)
|
else if (errors != null && errors.Length > 0)
|
||||||
Debug.LogWarning($"Script validation warnings for {name}:\n" + string.Join("\n", errors));
|
McpLog.Warn($"Script validation warnings for {name}:\n" + string.Join("\n", errors));
|
||||||
|
|
||||||
// Atomic write with backup; schedule refresh
|
// Atomic write with backup; schedule refresh
|
||||||
// Decide refresh behavior
|
// Decide refresh behavior
|
||||||
|
|
@ -2310,7 +2310,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"Could not load UnityEngine assembly: {ex.Message}");
|
McpLog.Warn($"Could not load UnityEngine assembly: {ex.Message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
|
|
@ -2320,7 +2320,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"Could not load UnityEditor assembly: {ex.Message}");
|
McpLog.Warn($"Could not load UnityEditor assembly: {ex.Message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get Unity project assemblies
|
// Get Unity project assemblies
|
||||||
|
|
@ -2337,7 +2337,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"Could not load Unity project assemblies: {ex.Message}");
|
McpLog.Warn($"Could not load Unity project assemblies: {ex.Message}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -2349,7 +2349,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Debug.LogError($"Failed to get compilation references: {ex.Message}");
|
McpLog.Error($"Failed to get compilation references: {ex.Message}");
|
||||||
return new System.Collections.Generic.List<MetadataReference>();
|
return new System.Collections.Generic.List<MetadataReference>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -597,7 +597,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"[MCP] Could not parse '{paramName}' JSON string: {e.Message}");
|
McpLog.Warn($"[MCP] Could not parse '{paramName}' JSON string: {e.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogError(
|
McpLog.Error(
|
||||||
$"[ReadConsole] Static Initialization Failed: Could not setup reflection for LogEntries/LogEntry. Console reading/clearing will likely fail. Specific Error: {e.Message}"
|
$"[ReadConsole] Static Initialization Failed: Could not setup reflection for LogEntries/LogEntry. Console reading/clearing will likely fail. Specific Error: {e.Message}"
|
||||||
);
|
);
|
||||||
// Set members to null to prevent NullReferenceExceptions later, HandleCommand should check this.
|
// Set members to null to prevent NullReferenceExceptions later, HandleCommand should check this.
|
||||||
|
|
@ -144,7 +144,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Log the error here as well for easier debugging in Unity Console
|
// Log the error here as well for easier debugging in Unity Console
|
||||||
Debug.LogError(
|
McpLog.Error(
|
||||||
"[ReadConsole] HandleCommand called but reflection members are not initialized. Static constructor might have failed silently or there's an issue."
|
"[ReadConsole] HandleCommand called but reflection members are not initialized. Static constructor might have failed silently or there's an issue."
|
||||||
);
|
);
|
||||||
return new ErrorResponse(
|
return new ErrorResponse(
|
||||||
|
|
@ -184,7 +184,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(sinceTimestampStr))
|
if (!string.IsNullOrEmpty(sinceTimestampStr))
|
||||||
{
|
{
|
||||||
Debug.LogWarning(
|
McpLog.Warn(
|
||||||
"[ReadConsole] Filtering by 'since_timestamp' is not currently implemented."
|
"[ReadConsole] Filtering by 'since_timestamp' is not currently implemented."
|
||||||
);
|
);
|
||||||
// Need a way to get timestamp per log entry.
|
// Need a way to get timestamp per log entry.
|
||||||
|
|
@ -209,7 +209,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogError($"[ReadConsole] Action '{action}' failed: {e}");
|
McpLog.Error($"[ReadConsole] Action '{action}' failed: {e}");
|
||||||
return new ErrorResponse($"Internal error processing action '{action}': {e.Message}");
|
return new ErrorResponse($"Internal error processing action '{action}': {e.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -225,7 +225,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogError($"[ReadConsole] Failed to clear console: {e}");
|
McpLog.Error($"[ReadConsole] Failed to clear console: {e}");
|
||||||
return new ErrorResponse($"Failed to clear console: {e.Message}");
|
return new ErrorResponse($"Failed to clear console: {e.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -400,7 +400,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogError($"[ReadConsole] Error while retrieving log entries: {e}");
|
McpLog.Error($"[ReadConsole] Error while retrieving log entries: {e}");
|
||||||
// EndGettingEntries will be called in the finally block
|
// EndGettingEntries will be called in the finally block
|
||||||
return new ErrorResponse($"Error retrieving log entries: {e.Message}");
|
return new ErrorResponse($"Error retrieving log entries: {e.Message}");
|
||||||
}
|
}
|
||||||
|
|
@ -413,7 +413,7 @@ namespace MCPForUnity.Editor.Tools
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.LogError($"[ReadConsole] Failed to call EndGettingEntries: {e}");
|
McpLog.Error($"[ReadConsole] Failed to call EndGettingEntries: {e}");
|
||||||
// Don't return error here as we might have valid data, but log it.
|
// Don't return error here as we might have valid data, but log it.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,14 @@ namespace MCPForUnity.Editor.Windows.Components.Connection
|
||||||
if (string.IsNullOrEmpty(scope))
|
if (string.IsNullOrEmpty(scope))
|
||||||
{
|
{
|
||||||
scope = MCPServiceLocator.Server.IsLocalUrl() ? "local" : "remote";
|
scope = MCPServiceLocator.Server.IsLocalUrl() ? "local" : "remote";
|
||||||
|
try
|
||||||
|
{
|
||||||
|
EditorPrefs.SetString(EditorPrefKeys.HttpTransportScope, scope);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
McpLog.Debug("Failed to set HttpTransportScope pref.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
transportDropdown.value = scope == "remote" ? TransportProtocol.HTTPRemote : TransportProtocol.HTTPLocal;
|
transportDropdown.value = scope == "remote" ? TransportProtocol.HTTPRemote : TransportProtocol.HTTPLocal;
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ namespace MCPForUnity.Editor.Windows
|
||||||
|
|
||||||
if (visualTree == null)
|
if (visualTree == null)
|
||||||
{
|
{
|
||||||
Debug.LogError("Failed to load EditorPrefsWindow.uxml template");
|
McpLog.Error("Failed to load EditorPrefsWindow.uxml template");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -98,7 +98,7 @@ namespace MCPForUnity.Editor.Windows
|
||||||
|
|
||||||
if (itemTemplate == null)
|
if (itemTemplate == null)
|
||||||
{
|
{
|
||||||
Debug.LogError("Failed to load EditorPrefItem.uxml template");
|
McpLog.Error("Failed to load EditorPrefItem.uxml template");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -251,7 +251,7 @@ namespace MCPForUnity.Editor.Windows
|
||||||
{
|
{
|
||||||
if (itemTemplate == null)
|
if (itemTemplate == null)
|
||||||
{
|
{
|
||||||
Debug.LogError("Item template not loaded");
|
McpLog.Error("Item template not loaded");
|
||||||
return new VisualElement();
|
return new VisualElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -341,7 +341,7 @@ namespace MCPForUnity.Runtime.Serialization
|
||||||
#else
|
#else
|
||||||
// Runtime deserialization is tricky without AssetDatabase/EditorUtility
|
// Runtime deserialization is tricky without AssetDatabase/EditorUtility
|
||||||
// Maybe log a warning and return null or existingValue?
|
// Maybe log a warning and return null or existingValue?
|
||||||
Debug.LogWarning("UnityEngineObjectConverter cannot deserialize complex objects in non-Editor mode.");
|
McpLog.Warn("UnityEngineObjectConverter cannot deserialize complex objects in non-Editor mode.");
|
||||||
// Skip the token to avoid breaking the reader
|
// Skip the token to avoid breaking the reader
|
||||||
if (reader.TokenType == JsonToken.StartObject) JObject.Load(reader);
|
if (reader.TokenType == JsonToken.StartObject) JObject.Load(reader);
|
||||||
else if (reader.TokenType == JsonToken.String) reader.ReadAsString();
|
else if (reader.TokenType == JsonToken.String) reader.ReadAsString();
|
||||||
|
|
|
||||||
49
README-zh.md
49
README-zh.md
|
|
@ -97,8 +97,9 @@ MCP for Unity 使用两个组件连接您的工具:
|
||||||
|
|
||||||
### 前置要求
|
### 前置要求
|
||||||
|
|
||||||
|
如果你**不是**通过 Unity Asset Store 安装,则还需要安装以下内容:
|
||||||
|
|
||||||
* **Python:** 版本 3.10 或更新。[下载 Python](https://www.python.org/downloads/)
|
* **Python:** 版本 3.10 或更新。[下载 Python](https://www.python.org/downloads/)
|
||||||
* **Unity Hub 和编辑器:** 版本 2021.3 LTS 或更新。[下载 Unity](https://unity.com/download)
|
|
||||||
* **uv(Python 工具链管理器):**
|
* **uv(Python 工具链管理器):**
|
||||||
```bash
|
```bash
|
||||||
# macOS / Linux
|
# macOS / Linux
|
||||||
|
|
@ -110,33 +111,43 @@ MCP for Unity 使用两个组件连接您的工具:
|
||||||
# 文档: https://docs.astral.sh/uv/getting-started/installation/
|
# 文档: https://docs.astral.sh/uv/getting-started/installation/
|
||||||
```
|
```
|
||||||
|
|
||||||
|
所有安装方式都需要以下内容:
|
||||||
|
|
||||||
|
* **Unity Hub 和编辑器:** 版本 2021.3 LTS 或更新。[下载 Unity](https://unity.com/download)
|
||||||
* **MCP 客户端:** [Claude Desktop](https://claude.ai/download) | [Claude Code](https://github.com/anthropics/claude-code) | [Cursor](https://www.cursor.com/en/downloads) | [Visual Studio Code Copilot](https://code.visualstudio.com/docs/copilot/overview) | [Windsurf](https://windsurf.com) | 其他客户端可通过手动配置使用
|
* **MCP 客户端:** [Claude Desktop](https://claude.ai/download) | [Claude Code](https://github.com/anthropics/claude-code) | [Cursor](https://www.cursor.com/en/downloads) | [Visual Studio Code Copilot](https://code.visualstudio.com/docs/copilot/overview) | [Windsurf](https://windsurf.com) | 其他客户端可通过手动配置使用
|
||||||
|
|
||||||
* <details> <summary><strong>[可选] Roslyn 用于高级脚本验证</strong></summary>
|
<details> <summary><strong>[可选] Roslyn 用于高级脚本验证</strong></summary>
|
||||||
|
|
||||||
对于捕获未定义命名空间、类型和方法的**严格**验证级别:
|
对于捕获未定义命名空间、类型和方法的**严格**验证级别:
|
||||||
|
|
||||||
**方法 1:Unity 的 NuGet(推荐)**
|
**方法 1:Unity 的 NuGet(推荐)**
|
||||||
1. 安装 [NuGetForUnity](https://github.com/GlitchEnzo/NuGetForUnity)
|
1. 安装 [NuGetForUnity](https://github.com/GlitchEnzo/NuGetForUnity)
|
||||||
2. 前往 `Window > NuGet Package Manager`
|
2. 前往 `Window > NuGet Package Manager`
|
||||||
3. 搜索 `Microsoft.CodeAnalysis`,选择版本 4.14.0 并安装包
|
3. 搜索 `Microsoft.CodeAnalysis`,选择版本 4.14.0 并安装包
|
||||||
4. 同时安装包 `SQLitePCLRaw.core` 和 `SQLitePCLRaw.bundle_e_sqlite3`。
|
4. 同时安装包 `SQLitePCLRaw.core` 和 `SQLitePCLRaw.bundle_e_sqlite3`。
|
||||||
5. 前往 `Player Settings > Scripting Define Symbols`
|
5. 前往 `Player Settings > Scripting Define Symbols`
|
||||||
6. 添加 `USE_ROSLYN`
|
6. 添加 `USE_ROSLYN`
|
||||||
7. 重启 Unity
|
7. 重启 Unity
|
||||||
|
|
||||||
**方法 2:手动 DLL 安装**
|
**方法 2:手动 DLL 安装**
|
||||||
1. 从 [NuGet](https://www.nuget.org/packages/Microsoft.CodeAnalysis.CSharp/) 下载 Microsoft.CodeAnalysis.CSharp.dll 和依赖项
|
1. 从 [NuGet](https://www.nuget.org/packages/Microsoft.CodeAnalysis.CSharp/) 下载 Microsoft.CodeAnalysis.CSharp.dll 和依赖项
|
||||||
2. 将 DLL 放置在 `Assets/Plugins/` 文件夹中
|
2. 将 DLL 放置在 `Assets/Plugins/` 文件夹中
|
||||||
3. 确保 .NET 兼容性设置正确
|
3. 确保 .NET 兼容性设置正确
|
||||||
4. 将 `USE_ROSLYN` 添加到脚本定义符号
|
4. 将 `USE_ROSLYN` 添加到脚本定义符号
|
||||||
5. 重启 Unity
|
5. 重启 Unity
|
||||||
|
|
||||||
**注意:** 没有 Roslyn 时,脚本验证会回退到基本结构检查。Roslyn 启用完整的 C# 编译器诊断和精确错误报告。</details>
|
**注意:** 没有 Roslyn 时,脚本验证会回退到基本结构检查。Roslyn 启用完整的 C# 编译器诊断和精确错误报告。</details>
|
||||||
|
|
||||||
---
|
---
|
||||||
### 🌟 步骤 1:安装 Unity 包
|
### 🌟 步骤 1:安装 Unity 包
|
||||||
|
|
||||||
|
#### 通过 Unity Asset Store 安装
|
||||||
|
|
||||||
|
1. 在浏览器中打开:https://assetstore.unity.com/packages/tools/generative-ai/mcp-for-unity-ai-driven-development-329908
|
||||||
|
2. 点击 `Add to My Assets`。
|
||||||
|
3. 在 Unity 编辑器中,前往 `Window > Package Manager`。
|
||||||
|
4. 将该资源下载并导入到你的项目中
|
||||||
|
|
||||||
#### 通过 Git URL 安装
|
#### 通过 Git URL 安装
|
||||||
|
|
||||||
1. 打开您的 Unity 项目。
|
1. 打开您的 Unity 项目。
|
||||||
|
|
@ -150,7 +161,7 @@ MCP for Unity 使用两个组件连接您的工具:
|
||||||
|
|
||||||
**需要锁定版本?** 使用带标签的 URL(更新时需卸载并重新安装):
|
**需要锁定版本?** 使用带标签的 URL(更新时需卸载并重新安装):
|
||||||
```
|
```
|
||||||
https://github.com/CoplayDev/unity-mcp.git?path=/MCPForUnity#v8.0.0
|
https://github.com/CoplayDev/unity-mcp.git?path=/MCPForUnity#v8.6.0
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 通过 OpenUPM 安装
|
#### 通过 OpenUPM 安装
|
||||||
|
|
|
||||||
51
README.md
51
README.md
|
|
@ -8,6 +8,7 @@
|
||||||
[](https://discord.gg/y4p8KfzrN4)
|
[](https://discord.gg/y4p8KfzrN4)
|
||||||
[](https://www.coplay.dev/?ref=unity-mcp)
|
[](https://www.coplay.dev/?ref=unity-mcp)
|
||||||
[](https://unity.com/releases/editor/archive)
|
[](https://unity.com/releases/editor/archive)
|
||||||
|
[](https://assetstore.unity.com/packages/tools/generative-ai/mcp-for-unity-ai-driven-development-329908)
|
||||||
[](https://www.python.org)
|
[](https://www.python.org)
|
||||||
[](https://modelcontextprotocol.io/introduction)
|
[](https://modelcontextprotocol.io/introduction)
|
||||||

|

|
||||||
|
|
@ -18,7 +19,7 @@
|
||||||
|
|
||||||
MCP for Unity acts as a bridge, allowing AI assistants (Claude, Cursor, Antigravity, VS Code, etc) to interact directly with your Unity Editor via a local **MCP (Model Context Protocol) Client**. Give your LLM tools to manage assets, control scenes, edit scripts, and automate tasks within Unity.
|
MCP for Unity acts as a bridge, allowing AI assistants (Claude, Cursor, Antigravity, VS Code, etc) to interact directly with your Unity Editor via a local **MCP (Model Context Protocol) Client**. Give your LLM tools to manage assets, control scenes, edit scripts, and automate tasks within Unity.
|
||||||
|
|
||||||
<img width="406" height="704" alt="MCP for Unity screenshot" src="docs/images/unity-mcp-ui-v8.6.png">
|
<img alt="MCP for Unity building a scene" src="docs/images/building_scene.gif">
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -110,8 +111,9 @@ MCP for Unity connects your tools using two components:
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
|
If you are **not** installing via the Unity Asset Store, you will need to install the following:
|
||||||
|
|
||||||
* **Python:** Version 3.10 or newer. [Download Python](https://www.python.org/downloads/)
|
* **Python:** Version 3.10 or newer. [Download Python](https://www.python.org/downloads/)
|
||||||
* **Unity Hub & Editor:** Version 2021.3 LTS or newer. [Download Unity](https://unity.com/download)
|
|
||||||
* **uv (Python toolchain manager):**
|
* **uv (Python toolchain manager):**
|
||||||
```bash
|
```bash
|
||||||
# macOS / Linux
|
# macOS / Linux
|
||||||
|
|
@ -123,33 +125,44 @@ MCP for Unity connects your tools using two components:
|
||||||
# Docs: https://docs.astral.sh/uv/getting-started/installation/
|
# Docs: https://docs.astral.sh/uv/getting-started/installation/
|
||||||
```
|
```
|
||||||
|
|
||||||
|
All installations require these:
|
||||||
|
|
||||||
|
* **Unity Hub & Editor:** Version 2021.3 LTS or newer. [Download Unity](https://unity.com/download)
|
||||||
* **An MCP Client:** : [Claude Desktop](https://claude.ai/download) | [Claude Code](https://github.com/anthropics/claude-code) | [Cursor](https://www.cursor.com/en/downloads) | [Visual Studio Code Copilot](https://code.visualstudio.com/docs/copilot/overview) | [Windsurf](https://windsurf.com) | Others work with manual config
|
* **An MCP Client:** : [Claude Desktop](https://claude.ai/download) | [Claude Code](https://github.com/anthropics/claude-code) | [Cursor](https://www.cursor.com/en/downloads) | [Visual Studio Code Copilot](https://code.visualstudio.com/docs/copilot/overview) | [Windsurf](https://windsurf.com) | Others work with manual config
|
||||||
|
|
||||||
* <details> <summary><strong>[Optional] Roslyn for Advanced Script Validation</strong></summary>
|
<details> <summary><strong>[Optional] Roslyn for Advanced Script Validation</strong></summary>
|
||||||
|
|
||||||
For **Strict** validation level that catches undefined namespaces, types, and methods:
|
For **Strict** validation level that catches undefined namespaces, types, and methods:
|
||||||
|
|
||||||
**Method 1: NuGet for Unity (Recommended)**
|
**Method 1: NuGet for Unity (Recommended)**
|
||||||
1. Install [NuGetForUnity](https://github.com/GlitchEnzo/NuGetForUnity)
|
1. Install [NuGetForUnity](https://github.com/GlitchEnzo/NuGetForUnity)
|
||||||
2. Go to `Window > NuGet Package Manager`
|
2. Go to `Window > NuGet Package Manager`
|
||||||
3. Search for `Microsoft.CodeAnalysis`, select version 4.14.0, and install the package
|
3. Search for `Microsoft.CodeAnalysis`, select version 4.14.0, and install the package
|
||||||
4. Also install package `SQLitePCLRaw.core` and `SQLitePCLRaw.bundle_e_sqlite3`.
|
4. Also install package `SQLitePCLRaw.core` and `SQLitePCLRaw.bundle_e_sqlite3`.
|
||||||
5. Go to `Player Settings > Scripting Define Symbols`
|
5. Go to `Player Settings > Scripting Define Symbols`
|
||||||
6. Add `USE_ROSLYN`
|
6. Add `USE_ROSLYN`
|
||||||
7. Restart Unity
|
7. Restart Unity
|
||||||
|
|
||||||
**Method 2: Manual DLL Installation**
|
**Method 2: Manual DLL Installation**
|
||||||
1. Download Microsoft.CodeAnalysis.CSharp.dll and dependencies from [NuGet](https://www.nuget.org/packages/Microsoft.CodeAnalysis.CSharp/)
|
1. Download Microsoft.CodeAnalysis.CSharp.dll and dependencies from [NuGet](https://www.nuget.org/packages/Microsoft.CodeAnalysis.CSharp/)
|
||||||
2. Place DLLs in `Assets/Plugins/` folder
|
2. Place DLLs in `Assets/Plugins/` folder
|
||||||
3. Ensure .NET compatibility settings are correct
|
3. Ensure .NET compatibility settings are correct
|
||||||
4. Add `USE_ROSLYN` to Scripting Define Symbols
|
4. Add `USE_ROSLYN` to Scripting Define Symbols
|
||||||
5. Restart Unity
|
5. Restart Unity
|
||||||
|
|
||||||
**Note:** Without Roslyn, script validation falls back to basic structural checks. Roslyn enables full C# compiler diagnostics with precise error reporting.</details>
|
**Note:** Without Roslyn, script validation falls back to basic structural checks. Roslyn enables full C# compiler diagnostics with precise error reporting.</details>
|
||||||
|
|
||||||
---
|
---
|
||||||
### 🌟 Step 1: Install the Unity Package
|
### 🌟 Step 1: Install the Unity Package
|
||||||
|
|
||||||
|
#### To install via the Unity Asset Store
|
||||||
|
|
||||||
|
1. In your browser, navigate to https://assetstore.unity.com/packages/tools/generative-ai/mcp-for-unity-ai-driven-development-329908
|
||||||
|
2. Click `Add to My Assets`.
|
||||||
|
3. In the Unity Editor, go to`Window > Package Manager`.
|
||||||
|
4. Download and import the asset to your project
|
||||||
|
|
||||||
|
|
||||||
#### To install via Git URL
|
#### To install via Git URL
|
||||||
|
|
||||||
1. Open your Unity project.
|
1. Open your Unity project.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,106 @@
|
||||||
|
# This .gitignore file should be placed at the root of your Unity project directory
|
||||||
|
#
|
||||||
|
# Get latest from https://github.com/github/gitignore/blob/main/Unity.gitignore
|
||||||
|
#
|
||||||
|
.utmp/
|
||||||
|
/[Ll]ibrary/
|
||||||
|
/[Tt]emp/
|
||||||
|
/[Oo]bj/
|
||||||
|
/[Bb]uild/
|
||||||
|
/[Bb]uilds/
|
||||||
|
/[Ll]ogs/
|
||||||
|
/[Uu]ser[Ss]ettings/
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# By default unity supports Blender asset imports, *.blend1 blender files do not need to be commited to version control.
|
||||||
|
*.blend1
|
||||||
|
*.blend1.meta
|
||||||
|
|
||||||
|
# MemoryCaptures can get excessive in size.
|
||||||
|
# They also could contain extremely sensitive data
|
||||||
|
/[Mm]emoryCaptures/
|
||||||
|
|
||||||
|
# Recordings can get excessive in size
|
||||||
|
/[Rr]ecordings/
|
||||||
|
|
||||||
|
# Uncomment this line if you wish to ignore the asset store tools plugin
|
||||||
|
# /[Aa]ssets/AssetStoreTools*
|
||||||
|
|
||||||
|
# Autogenerated Jetbrains Rider plugin
|
||||||
|
/[Aa]ssets/Plugins/Editor/JetBrains*
|
||||||
|
# Jetbrains Rider personal-layer settings
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# Visual Studio cache directory
|
||||||
|
.vs/
|
||||||
|
|
||||||
|
# Gradle cache directory
|
||||||
|
.gradle/
|
||||||
|
|
||||||
|
# Autogenerated VS/MD/Consulo solution and project files
|
||||||
|
ExportedObj/
|
||||||
|
.consulo/
|
||||||
|
*.csproj
|
||||||
|
*.unityproj
|
||||||
|
*.sln
|
||||||
|
*.suo
|
||||||
|
*.tmp
|
||||||
|
*.user
|
||||||
|
*.userprefs
|
||||||
|
*.pidb
|
||||||
|
*.booproj
|
||||||
|
*.svd
|
||||||
|
*.pdb
|
||||||
|
*.mdb
|
||||||
|
*.opendb
|
||||||
|
*.VC.db
|
||||||
|
|
||||||
|
# Unity3D generated meta files
|
||||||
|
*.pidb.meta
|
||||||
|
*.pdb.meta
|
||||||
|
*.mdb.meta
|
||||||
|
|
||||||
|
# Unity3D generated file on crash reports
|
||||||
|
sysinfo.txt
|
||||||
|
|
||||||
|
# Mono auto generated files
|
||||||
|
mono_crash.*
|
||||||
|
|
||||||
|
# Builds
|
||||||
|
*.apk
|
||||||
|
*.aab
|
||||||
|
*.unitypackage
|
||||||
|
*.unitypackage.meta
|
||||||
|
*.app
|
||||||
|
|
||||||
|
# Crashlytics generated file
|
||||||
|
crashlytics-build.properties
|
||||||
|
|
||||||
|
# TestRunner generated files
|
||||||
|
InitTestScene*.unity*
|
||||||
|
|
||||||
|
# Addressables default ignores, before user customizations
|
||||||
|
/ServerData
|
||||||
|
/[Aa]ssets/StreamingAssets/aa*
|
||||||
|
/[Aa]ssets/AddressableAssetsData/link.xml*
|
||||||
|
/[Aa]ssets/Addressables_Temp*
|
||||||
|
# By default, Addressables content builds will generate addressables_content_state.bin
|
||||||
|
# files in platform-specific subfolders, for example:
|
||||||
|
# /Assets/AddressableAssetsData/OSX/addressables_content_state.bin
|
||||||
|
/[Aa]ssets/AddressableAssetsData/*/*.bin*
|
||||||
|
|
||||||
|
# Visual Scripting auto-generated files
|
||||||
|
/[Aa]ssets/Unity.VisualScripting.Generated/VisualScripting.Flow/UnitOptions.db
|
||||||
|
/[Aa]ssets/Unity.VisualScripting.Generated/VisualScripting.Flow/UnitOptions.db.meta
|
||||||
|
/[Aa]ssets/Unity.VisualScripting.Generated/VisualScripting.Core/Property Providers
|
||||||
|
/[Aa]ssets/Unity.VisualScripting.Generated/VisualScripting.Core/Property Providers.meta
|
||||||
|
|
||||||
|
# Auto-generated scenes by play mode tests
|
||||||
|
/[Aa]ssets/[Ii]nit[Tt]est[Ss]cene*.unity*
|
||||||
|
|
||||||
|
.vscode
|
||||||
|
.cursor
|
||||||
|
.windsurf
|
||||||
|
.claude
|
||||||
|
.DS_Store
|
||||||
|
boot.config
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 93766a50487224f02b29aae42971e08b
|
guid: 8105016687592461f977c054a80ce2f2
|
||||||
NativeFormatImporter:
|
NativeFormatImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
mainObjectFileID: 0
|
mainObjectFileID: 0
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f5537d31886f841d58d487c5db45aaa0
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,407 @@
|
||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!29 &1
|
||||||
|
OcclusionCullingSettings:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
serializedVersion: 2
|
||||||
|
m_OcclusionBakeSettings:
|
||||||
|
smallestOccluder: 5
|
||||||
|
smallestHole: 0.25
|
||||||
|
backfaceThreshold: 100
|
||||||
|
m_SceneGUID: 00000000000000000000000000000000
|
||||||
|
m_OcclusionCullingData: {fileID: 0}
|
||||||
|
--- !u!104 &2
|
||||||
|
RenderSettings:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
serializedVersion: 9
|
||||||
|
m_Fog: 0
|
||||||
|
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
|
||||||
|
m_FogMode: 3
|
||||||
|
m_FogDensity: 0.01
|
||||||
|
m_LinearFogStart: 0
|
||||||
|
m_LinearFogEnd: 300
|
||||||
|
m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
|
||||||
|
m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
|
||||||
|
m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
|
||||||
|
m_AmbientIntensity: 1
|
||||||
|
m_AmbientMode: 0
|
||||||
|
m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
|
||||||
|
m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}
|
||||||
|
m_HaloStrength: 0.5
|
||||||
|
m_FlareStrength: 1
|
||||||
|
m_FlareFadeSpeed: 3
|
||||||
|
m_HaloTexture: {fileID: 0}
|
||||||
|
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
|
m_DefaultReflectionMode: 0
|
||||||
|
m_DefaultReflectionResolution: 128
|
||||||
|
m_ReflectionBounces: 1
|
||||||
|
m_ReflectionIntensity: 1
|
||||||
|
m_CustomReflection: {fileID: 0}
|
||||||
|
m_Sun: {fileID: 0}
|
||||||
|
m_IndirectSpecularColor: {r: 0.18028305, g: 0.22571313, b: 0.3069213, a: 1}
|
||||||
|
m_UseRadianceAmbientProbe: 0
|
||||||
|
--- !u!157 &3
|
||||||
|
LightmapSettings:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
serializedVersion: 12
|
||||||
|
m_GIWorkflowMode: 1
|
||||||
|
m_GISettings:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_BounceScale: 1
|
||||||
|
m_IndirectOutputScale: 1
|
||||||
|
m_AlbedoBoost: 1
|
||||||
|
m_EnvironmentLightingMode: 0
|
||||||
|
m_EnableBakedLightmaps: 1
|
||||||
|
m_EnableRealtimeLightmaps: 0
|
||||||
|
m_LightmapEditorSettings:
|
||||||
|
serializedVersion: 12
|
||||||
|
m_Resolution: 2
|
||||||
|
m_BakeResolution: 40
|
||||||
|
m_AtlasSize: 1024
|
||||||
|
m_AO: 0
|
||||||
|
m_AOMaxDistance: 1
|
||||||
|
m_CompAOExponent: 1
|
||||||
|
m_CompAOExponentDirect: 0
|
||||||
|
m_ExtractAmbientOcclusion: 0
|
||||||
|
m_Padding: 2
|
||||||
|
m_LightmapParameters: {fileID: 0}
|
||||||
|
m_LightmapsBakeMode: 1
|
||||||
|
m_TextureCompression: 1
|
||||||
|
m_FinalGather: 0
|
||||||
|
m_FinalGatherFiltering: 1
|
||||||
|
m_FinalGatherRayCount: 256
|
||||||
|
m_ReflectionCompression: 2
|
||||||
|
m_MixedBakeMode: 2
|
||||||
|
m_BakeBackend: 1
|
||||||
|
m_PVRSampling: 1
|
||||||
|
m_PVRDirectSampleCount: 32
|
||||||
|
m_PVRSampleCount: 512
|
||||||
|
m_PVRBounces: 2
|
||||||
|
m_PVREnvironmentSampleCount: 256
|
||||||
|
m_PVREnvironmentReferencePointCount: 2048
|
||||||
|
m_PVRFilteringMode: 1
|
||||||
|
m_PVRDenoiserTypeDirect: 1
|
||||||
|
m_PVRDenoiserTypeIndirect: 1
|
||||||
|
m_PVRDenoiserTypeAO: 1
|
||||||
|
m_PVRFilterTypeDirect: 0
|
||||||
|
m_PVRFilterTypeIndirect: 0
|
||||||
|
m_PVRFilterTypeAO: 0
|
||||||
|
m_PVREnvironmentMIS: 1
|
||||||
|
m_PVRCulling: 1
|
||||||
|
m_PVRFilteringGaussRadiusDirect: 1
|
||||||
|
m_PVRFilteringGaussRadiusIndirect: 5
|
||||||
|
m_PVRFilteringGaussRadiusAO: 2
|
||||||
|
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
|
||||||
|
m_PVRFilteringAtrousPositionSigmaIndirect: 2
|
||||||
|
m_PVRFilteringAtrousPositionSigmaAO: 1
|
||||||
|
m_ExportTrainingData: 0
|
||||||
|
m_TrainingDataDestination: TrainingData
|
||||||
|
m_LightProbeSampleCountMultiplier: 4
|
||||||
|
m_LightingDataAsset: {fileID: 0}
|
||||||
|
m_LightingSettings: {fileID: 0}
|
||||||
|
--- !u!196 &4
|
||||||
|
NavMeshSettings:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_BuildSettings:
|
||||||
|
serializedVersion: 2
|
||||||
|
agentTypeID: 0
|
||||||
|
agentRadius: 0.5
|
||||||
|
agentHeight: 2
|
||||||
|
agentSlope: 45
|
||||||
|
agentClimb: 0.4
|
||||||
|
ledgeDropHeight: 0
|
||||||
|
maxJumpAcrossDistance: 0
|
||||||
|
minRegionArea: 2
|
||||||
|
manualCellSize: 0
|
||||||
|
cellSize: 0.16666667
|
||||||
|
manualTileSize: 0
|
||||||
|
tileSize: 256
|
||||||
|
accuratePlacement: 0
|
||||||
|
maxJobWorkers: 0
|
||||||
|
preserveTilesOutsideBounds: 0
|
||||||
|
debug:
|
||||||
|
m_Flags: 0
|
||||||
|
m_NavMeshData: {fileID: 0}
|
||||||
|
--- !u!1 &330585543
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 330585546}
|
||||||
|
- component: {fileID: 330585545}
|
||||||
|
- component: {fileID: 330585544}
|
||||||
|
- component: {fileID: 330585547}
|
||||||
|
m_Layer: 0
|
||||||
|
m_Name: Main Camera
|
||||||
|
m_TagString: MainCamera
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!81 &330585544
|
||||||
|
AudioListener:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 330585543}
|
||||||
|
m_Enabled: 1
|
||||||
|
--- !u!20 &330585545
|
||||||
|
Camera:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 330585543}
|
||||||
|
m_Enabled: 1
|
||||||
|
serializedVersion: 2
|
||||||
|
m_ClearFlags: 1
|
||||||
|
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
|
||||||
|
m_projectionMatrixMode: 1
|
||||||
|
m_GateFitMode: 2
|
||||||
|
m_FOVAxisMode: 0
|
||||||
|
m_SensorSize: {x: 36, y: 24}
|
||||||
|
m_LensShift: {x: 0, y: 0}
|
||||||
|
m_FocalLength: 50
|
||||||
|
m_NormalizedViewPortRect:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 0
|
||||||
|
y: 0
|
||||||
|
width: 1
|
||||||
|
height: 1
|
||||||
|
near clip plane: 0.3
|
||||||
|
far clip plane: 1000
|
||||||
|
field of view: 60
|
||||||
|
orthographic: 0
|
||||||
|
orthographic size: 5
|
||||||
|
m_Depth: -1
|
||||||
|
m_CullingMask:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Bits: 4294967295
|
||||||
|
m_RenderingPath: -1
|
||||||
|
m_TargetTexture: {fileID: 0}
|
||||||
|
m_TargetDisplay: 0
|
||||||
|
m_TargetEye: 3
|
||||||
|
m_HDR: 1
|
||||||
|
m_AllowMSAA: 1
|
||||||
|
m_AllowDynamicResolution: 0
|
||||||
|
m_ForceIntoRT: 0
|
||||||
|
m_OcclusionCulling: 1
|
||||||
|
m_StereoConvergence: 10
|
||||||
|
m_StereoSeparation: 0.022
|
||||||
|
--- !u!4 &330585546
|
||||||
|
Transform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 330585543}
|
||||||
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
|
m_LocalPosition: {x: 0, y: 1, z: -10}
|
||||||
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
|
m_ConstrainProportionsScale: 0
|
||||||
|
m_Children: []
|
||||||
|
m_Father: {fileID: 0}
|
||||||
|
m_RootOrder: 0
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!114 &330585547
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 330585543}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
m_RenderShadows: 1
|
||||||
|
m_RequiresDepthTextureOption: 2
|
||||||
|
m_RequiresOpaqueTextureOption: 2
|
||||||
|
m_CameraType: 0
|
||||||
|
m_Cameras: []
|
||||||
|
m_RendererIndex: -1
|
||||||
|
m_VolumeLayerMask:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Bits: 1
|
||||||
|
m_VolumeTrigger: {fileID: 0}
|
||||||
|
m_VolumeFrameworkUpdateModeOption: 2
|
||||||
|
m_RenderPostProcessing: 1
|
||||||
|
m_Antialiasing: 0
|
||||||
|
m_AntialiasingQuality: 2
|
||||||
|
m_StopNaN: 0
|
||||||
|
m_Dithering: 0
|
||||||
|
m_ClearDepth: 1
|
||||||
|
m_AllowXRRendering: 1
|
||||||
|
m_RequiresDepthTexture: 0
|
||||||
|
m_RequiresColorTexture: 0
|
||||||
|
m_Version: 2
|
||||||
|
--- !u!1 &410087039
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 410087041}
|
||||||
|
- component: {fileID: 410087040}
|
||||||
|
- component: {fileID: 410087042}
|
||||||
|
m_Layer: 0
|
||||||
|
m_Name: Directional Light
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!108 &410087040
|
||||||
|
Light:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 410087039}
|
||||||
|
m_Enabled: 1
|
||||||
|
serializedVersion: 10
|
||||||
|
m_Type: 1
|
||||||
|
m_Shape: 0
|
||||||
|
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
m_Intensity: 2
|
||||||
|
m_Range: 10
|
||||||
|
m_SpotAngle: 30
|
||||||
|
m_InnerSpotAngle: 21.80208
|
||||||
|
m_CookieSize: 10
|
||||||
|
m_Shadows:
|
||||||
|
m_Type: 2
|
||||||
|
m_Resolution: -1
|
||||||
|
m_CustomResolution: -1
|
||||||
|
m_Strength: 1
|
||||||
|
m_Bias: 0.05
|
||||||
|
m_NormalBias: 0.4
|
||||||
|
m_NearPlane: 0.2
|
||||||
|
m_CullingMatrixOverride:
|
||||||
|
e00: 1
|
||||||
|
e01: 0
|
||||||
|
e02: 0
|
||||||
|
e03: 0
|
||||||
|
e10: 0
|
||||||
|
e11: 1
|
||||||
|
e12: 0
|
||||||
|
e13: 0
|
||||||
|
e20: 0
|
||||||
|
e21: 0
|
||||||
|
e22: 1
|
||||||
|
e23: 0
|
||||||
|
e30: 0
|
||||||
|
e31: 0
|
||||||
|
e32: 0
|
||||||
|
e33: 1
|
||||||
|
m_UseCullingMatrixOverride: 0
|
||||||
|
m_Cookie: {fileID: 0}
|
||||||
|
m_DrawHalo: 0
|
||||||
|
m_Flare: {fileID: 0}
|
||||||
|
m_RenderMode: 0
|
||||||
|
m_CullingMask:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_Bits: 4294967295
|
||||||
|
m_RenderingLayerMask: 1
|
||||||
|
m_Lightmapping: 4
|
||||||
|
m_LightShadowCasterMode: 0
|
||||||
|
m_AreaSize: {x: 1, y: 1}
|
||||||
|
m_BounceIntensity: 1
|
||||||
|
m_ColorTemperature: 5000
|
||||||
|
m_UseColorTemperature: 1
|
||||||
|
m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
m_UseBoundingSphereOverride: 0
|
||||||
|
m_UseViewFrustumForShadowCasterCull: 1
|
||||||
|
m_ShadowRadius: 0
|
||||||
|
m_ShadowAngle: 0
|
||||||
|
--- !u!4 &410087041
|
||||||
|
Transform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 410087039}
|
||||||
|
m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261}
|
||||||
|
m_LocalPosition: {x: 0, y: 3, z: 0}
|
||||||
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
|
m_ConstrainProportionsScale: 0
|
||||||
|
m_Children: []
|
||||||
|
m_Father: {fileID: 0}
|
||||||
|
m_RootOrder: 1
|
||||||
|
m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0}
|
||||||
|
--- !u!114 &410087042
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 410087039}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 474bcb49853aa07438625e644c072ee6, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
m_Version: 1
|
||||||
|
m_UsePipelineSettings: 1
|
||||||
|
m_AdditionalLightsShadowResolutionTier: 2
|
||||||
|
m_LightLayerMask: 1
|
||||||
|
m_CustomShadowLayers: 0
|
||||||
|
m_ShadowLayerMask: 1
|
||||||
|
m_LightCookieSize: {x: 1, y: 1}
|
||||||
|
m_LightCookieOffset: {x: 0, y: 0}
|
||||||
|
--- !u!1 &832575517
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 832575519}
|
||||||
|
- component: {fileID: 832575518}
|
||||||
|
m_Layer: 0
|
||||||
|
m_Name: Global Volume
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!114 &832575518
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 832575517}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 172515602e62fb746b5d573b38a5fe58, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
m_IsGlobal: 1
|
||||||
|
priority: 0
|
||||||
|
blendDistance: 0
|
||||||
|
weight: 1
|
||||||
|
sharedProfile: {fileID: 11400000, guid: a6560a915ef98420e9faacc1c7438823, type: 2}
|
||||||
|
--- !u!4 &832575519
|
||||||
|
Transform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 832575517}
|
||||||
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
|
m_ConstrainProportionsScale: 0
|
||||||
|
m_Children: []
|
||||||
|
m_Father: {fileID: 0}
|
||||||
|
m_RootOrder: 2
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 99c9720ab356a0642a771bea13969a05
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 709f11a7f3c4041caa4ef136ea32d874
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: a6560a915ef98420e9faacc1c7438823
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 0
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e634585d5c4544dd297acaee93dc2beb
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 11400000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e1260c1148f6143b28bae5ace5e9c5d1
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 0
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c40be3174f62c4acf8c1216858c64956
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 11400000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 7b7fd9122c28c4d15b667c7040e3b3fd
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 0
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 707360a9c581a4bd7aa53bfeb1429f71
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 11400000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d0e2fc18fe036412f8223b3b3d9ad574
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 0
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ba062aa6c92b140379dbc06b43dd3b9b
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8a0c9218a650547d98138cd835033977
|
||||||
|
folderAsset: yes
|
||||||
|
timeCreated: 1484670163
|
||||||
|
licenseType: Store
|
||||||
|
DefaultImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
|
|
@ -0,0 +1,134 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 727a75301c3d24613a3ebcec4a24c2c8
|
||||||
|
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
|
||||||
|
vTOnly: 0
|
||||||
|
ignoreMasterTextureLimit: 0
|
||||||
|
grayScaleToAlpha: 0
|
||||||
|
generateCubemap: 6
|
||||||
|
cubemapConvolution: 0
|
||||||
|
seamlessCubemap: 0
|
||||||
|
textureFormat: 1
|
||||||
|
maxTextureSize: 2048
|
||||||
|
textureSettings:
|
||||||
|
serializedVersion: 2
|
||||||
|
filterMode: 0
|
||||||
|
aniso: 1
|
||||||
|
mipBias: 0
|
||||||
|
wrapU: 1
|
||||||
|
wrapV: 1
|
||||||
|
wrapW: 0
|
||||||
|
nPOTScale: 0
|
||||||
|
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: 1
|
||||||
|
spriteTessellationDetail: -1
|
||||||
|
textureType: 2
|
||||||
|
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: 0
|
||||||
|
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: Android
|
||||||
|
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:
|
||||||
|
internalID: 0
|
||||||
|
vertices: []
|
||||||
|
indices:
|
||||||
|
edges: []
|
||||||
|
weights: []
|
||||||
|
secondaryTextures: []
|
||||||
|
nameFileIdTable: {}
|
||||||
|
spritePackingTag:
|
||||||
|
pSDRemoveMatte: 0
|
||||||
|
pSDShowRemoveMatteOption: 0
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,654 @@
|
||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!114 &1
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 52
|
||||||
|
m_PrefabParentObject: {fileID: 0}
|
||||||
|
m_PrefabInternal: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 1
|
||||||
|
m_Script: {fileID: 12004, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
m_PixelRect:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 0
|
||||||
|
y: 45
|
||||||
|
width: 1666
|
||||||
|
height: 958
|
||||||
|
m_ShowMode: 4
|
||||||
|
m_Title:
|
||||||
|
m_RootView: {fileID: 6}
|
||||||
|
m_MinSize: {x: 950, y: 542}
|
||||||
|
m_MaxSize: {x: 10000, y: 10000}
|
||||||
|
--- !u!114 &2
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 52
|
||||||
|
m_PrefabParentObject: {fileID: 0}
|
||||||
|
m_PrefabInternal: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 1
|
||||||
|
m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
m_Children: []
|
||||||
|
m_Position:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 0
|
||||||
|
y: 466
|
||||||
|
width: 290
|
||||||
|
height: 442
|
||||||
|
m_MinSize: {x: 234, y: 271}
|
||||||
|
m_MaxSize: {x: 10004, y: 10021}
|
||||||
|
m_ActualView: {fileID: 14}
|
||||||
|
m_Panes:
|
||||||
|
- {fileID: 14}
|
||||||
|
m_Selected: 0
|
||||||
|
m_LastSelected: 0
|
||||||
|
--- !u!114 &3
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 52
|
||||||
|
m_PrefabParentObject: {fileID: 0}
|
||||||
|
m_PrefabInternal: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 1
|
||||||
|
m_Script: {fileID: 12010, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
m_Children:
|
||||||
|
- {fileID: 4}
|
||||||
|
- {fileID: 2}
|
||||||
|
m_Position:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 973
|
||||||
|
y: 0
|
||||||
|
width: 290
|
||||||
|
height: 908
|
||||||
|
m_MinSize: {x: 234, y: 492}
|
||||||
|
m_MaxSize: {x: 10004, y: 14042}
|
||||||
|
vertical: 1
|
||||||
|
controlID: 226
|
||||||
|
--- !u!114 &4
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 52
|
||||||
|
m_PrefabParentObject: {fileID: 0}
|
||||||
|
m_PrefabInternal: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 1
|
||||||
|
m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
m_Children: []
|
||||||
|
m_Position:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 0
|
||||||
|
y: 0
|
||||||
|
width: 290
|
||||||
|
height: 466
|
||||||
|
m_MinSize: {x: 204, y: 221}
|
||||||
|
m_MaxSize: {x: 4004, y: 4021}
|
||||||
|
m_ActualView: {fileID: 17}
|
||||||
|
m_Panes:
|
||||||
|
- {fileID: 17}
|
||||||
|
m_Selected: 0
|
||||||
|
m_LastSelected: 0
|
||||||
|
--- !u!114 &5
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 52
|
||||||
|
m_PrefabParentObject: {fileID: 0}
|
||||||
|
m_PrefabInternal: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 1
|
||||||
|
m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
m_Children: []
|
||||||
|
m_Position:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 0
|
||||||
|
y: 466
|
||||||
|
width: 973
|
||||||
|
height: 442
|
||||||
|
m_MinSize: {x: 202, y: 221}
|
||||||
|
m_MaxSize: {x: 4002, y: 4021}
|
||||||
|
m_ActualView: {fileID: 15}
|
||||||
|
m_Panes:
|
||||||
|
- {fileID: 15}
|
||||||
|
m_Selected: 0
|
||||||
|
m_LastSelected: 0
|
||||||
|
--- !u!114 &6
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 52
|
||||||
|
m_PrefabParentObject: {fileID: 0}
|
||||||
|
m_PrefabInternal: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 1
|
||||||
|
m_Script: {fileID: 12008, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
m_Children:
|
||||||
|
- {fileID: 7}
|
||||||
|
- {fileID: 8}
|
||||||
|
- {fileID: 9}
|
||||||
|
m_Position:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 0
|
||||||
|
y: 0
|
||||||
|
width: 1666
|
||||||
|
height: 958
|
||||||
|
m_MinSize: {x: 950, y: 542}
|
||||||
|
m_MaxSize: {x: 10000, y: 10000}
|
||||||
|
--- !u!114 &7
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 52
|
||||||
|
m_PrefabParentObject: {fileID: 0}
|
||||||
|
m_PrefabInternal: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 1
|
||||||
|
m_Script: {fileID: 12011, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
m_Children: []
|
||||||
|
m_Position:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 0
|
||||||
|
y: 0
|
||||||
|
width: 1666
|
||||||
|
height: 30
|
||||||
|
m_MinSize: {x: 0, y: 0}
|
||||||
|
m_MaxSize: {x: 0, y: 0}
|
||||||
|
m_LastLoadedLayoutName: Tutorial
|
||||||
|
--- !u!114 &8
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 52
|
||||||
|
m_PrefabParentObject: {fileID: 0}
|
||||||
|
m_PrefabInternal: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 1
|
||||||
|
m_Script: {fileID: 12010, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
m_Children:
|
||||||
|
- {fileID: 10}
|
||||||
|
- {fileID: 3}
|
||||||
|
- {fileID: 11}
|
||||||
|
m_Position:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 0
|
||||||
|
y: 30
|
||||||
|
width: 1666
|
||||||
|
height: 908
|
||||||
|
m_MinSize: {x: 713, y: 492}
|
||||||
|
m_MaxSize: {x: 18008, y: 14042}
|
||||||
|
vertical: 0
|
||||||
|
controlID: 74
|
||||||
|
--- !u!114 &9
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 52
|
||||||
|
m_PrefabParentObject: {fileID: 0}
|
||||||
|
m_PrefabInternal: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 1
|
||||||
|
m_Script: {fileID: 12042, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
m_Children: []
|
||||||
|
m_Position:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 0
|
||||||
|
y: 938
|
||||||
|
width: 1666
|
||||||
|
height: 20
|
||||||
|
m_MinSize: {x: 0, y: 0}
|
||||||
|
m_MaxSize: {x: 0, y: 0}
|
||||||
|
--- !u!114 &10
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 52
|
||||||
|
m_PrefabParentObject: {fileID: 0}
|
||||||
|
m_PrefabInternal: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 1
|
||||||
|
m_Script: {fileID: 12010, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
m_Children:
|
||||||
|
- {fileID: 12}
|
||||||
|
- {fileID: 5}
|
||||||
|
m_Position:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 0
|
||||||
|
y: 0
|
||||||
|
width: 973
|
||||||
|
height: 908
|
||||||
|
m_MinSize: {x: 202, y: 442}
|
||||||
|
m_MaxSize: {x: 4002, y: 8042}
|
||||||
|
vertical: 1
|
||||||
|
controlID: 75
|
||||||
|
--- !u!114 &11
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 52
|
||||||
|
m_PrefabParentObject: {fileID: 0}
|
||||||
|
m_PrefabInternal: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 1
|
||||||
|
m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
m_Children: []
|
||||||
|
m_Position:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 1263
|
||||||
|
y: 0
|
||||||
|
width: 403
|
||||||
|
height: 908
|
||||||
|
m_MinSize: {x: 277, y: 71}
|
||||||
|
m_MaxSize: {x: 4002, y: 4021}
|
||||||
|
m_ActualView: {fileID: 13}
|
||||||
|
m_Panes:
|
||||||
|
- {fileID: 13}
|
||||||
|
m_Selected: 0
|
||||||
|
m_LastSelected: 0
|
||||||
|
--- !u!114 &12
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 52
|
||||||
|
m_PrefabParentObject: {fileID: 0}
|
||||||
|
m_PrefabInternal: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 1
|
||||||
|
m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
m_Children: []
|
||||||
|
m_Position:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 0
|
||||||
|
y: 0
|
||||||
|
width: 973
|
||||||
|
height: 466
|
||||||
|
m_MinSize: {x: 202, y: 221}
|
||||||
|
m_MaxSize: {x: 4002, y: 4021}
|
||||||
|
m_ActualView: {fileID: 16}
|
||||||
|
m_Panes:
|
||||||
|
- {fileID: 16}
|
||||||
|
m_Selected: 0
|
||||||
|
m_LastSelected: 0
|
||||||
|
--- !u!114 &13
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 52
|
||||||
|
m_PrefabParentObject: {fileID: 0}
|
||||||
|
m_PrefabInternal: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 1
|
||||||
|
m_Script: {fileID: 12019, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
m_AutoRepaintOnSceneChange: 0
|
||||||
|
m_MinSize: {x: 275, y: 50}
|
||||||
|
m_MaxSize: {x: 4000, y: 4000}
|
||||||
|
m_TitleContent:
|
||||||
|
m_Text: Inspector
|
||||||
|
m_Image: {fileID: -6905738622615590433, guid: 0000000000000000d000000000000000,
|
||||||
|
type: 0}
|
||||||
|
m_Tooltip:
|
||||||
|
m_DepthBufferBits: 0
|
||||||
|
m_Pos:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 2
|
||||||
|
y: 19
|
||||||
|
width: 401
|
||||||
|
height: 887
|
||||||
|
m_ScrollPosition: {x: 0, y: 0}
|
||||||
|
m_InspectorMode: 0
|
||||||
|
m_PreviewResizer:
|
||||||
|
m_CachedPref: -160
|
||||||
|
m_ControlHash: -371814159
|
||||||
|
m_PrefName: Preview_InspectorPreview
|
||||||
|
m_PreviewWindow: {fileID: 0}
|
||||||
|
--- !u!114 &14
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 52
|
||||||
|
m_PrefabParentObject: {fileID: 0}
|
||||||
|
m_PrefabInternal: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 1
|
||||||
|
m_Script: {fileID: 12014, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
m_AutoRepaintOnSceneChange: 0
|
||||||
|
m_MinSize: {x: 230, y: 250}
|
||||||
|
m_MaxSize: {x: 10000, y: 10000}
|
||||||
|
m_TitleContent:
|
||||||
|
m_Text: Project
|
||||||
|
m_Image: {fileID: -7501376956915960154, guid: 0000000000000000d000000000000000,
|
||||||
|
type: 0}
|
||||||
|
m_Tooltip:
|
||||||
|
m_DepthBufferBits: 0
|
||||||
|
m_Pos:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 2
|
||||||
|
y: 19
|
||||||
|
width: 286
|
||||||
|
height: 421
|
||||||
|
m_SearchFilter:
|
||||||
|
m_NameFilter:
|
||||||
|
m_ClassNames: []
|
||||||
|
m_AssetLabels: []
|
||||||
|
m_AssetBundleNames: []
|
||||||
|
m_VersionControlStates: []
|
||||||
|
m_ReferencingInstanceIDs:
|
||||||
|
m_ScenePaths: []
|
||||||
|
m_ShowAllHits: 0
|
||||||
|
m_SearchArea: 0
|
||||||
|
m_Folders:
|
||||||
|
- Assets
|
||||||
|
m_ViewMode: 0
|
||||||
|
m_StartGridSize: 64
|
||||||
|
m_LastFolders:
|
||||||
|
- Assets
|
||||||
|
m_LastFoldersGridSize: -1
|
||||||
|
m_LastProjectPath: /Users/danielbrauer/Unity Projects/New Unity Project 47
|
||||||
|
m_IsLocked: 0
|
||||||
|
m_FolderTreeState:
|
||||||
|
scrollPos: {x: 0, y: 0}
|
||||||
|
m_SelectedIDs: ee240000
|
||||||
|
m_LastClickedID: 9454
|
||||||
|
m_ExpandedIDs: ee24000000ca9a3bffffff7f
|
||||||
|
m_RenameOverlay:
|
||||||
|
m_UserAcceptedRename: 0
|
||||||
|
m_Name:
|
||||||
|
m_OriginalName:
|
||||||
|
m_EditFieldRect:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 0
|
||||||
|
y: 0
|
||||||
|
width: 0
|
||||||
|
height: 0
|
||||||
|
m_UserData: 0
|
||||||
|
m_IsWaitingForDelay: 0
|
||||||
|
m_IsRenaming: 0
|
||||||
|
m_OriginalEventType: 11
|
||||||
|
m_IsRenamingFilename: 1
|
||||||
|
m_ClientGUIView: {fileID: 0}
|
||||||
|
m_SearchString:
|
||||||
|
m_CreateAssetUtility:
|
||||||
|
m_EndAction: {fileID: 0}
|
||||||
|
m_InstanceID: 0
|
||||||
|
m_Path:
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_ResourceFile:
|
||||||
|
m_AssetTreeState:
|
||||||
|
scrollPos: {x: 0, y: 0}
|
||||||
|
m_SelectedIDs: 68fbffff
|
||||||
|
m_LastClickedID: 0
|
||||||
|
m_ExpandedIDs: ee240000
|
||||||
|
m_RenameOverlay:
|
||||||
|
m_UserAcceptedRename: 0
|
||||||
|
m_Name:
|
||||||
|
m_OriginalName:
|
||||||
|
m_EditFieldRect:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 0
|
||||||
|
y: 0
|
||||||
|
width: 0
|
||||||
|
height: 0
|
||||||
|
m_UserData: 0
|
||||||
|
m_IsWaitingForDelay: 0
|
||||||
|
m_IsRenaming: 0
|
||||||
|
m_OriginalEventType: 11
|
||||||
|
m_IsRenamingFilename: 1
|
||||||
|
m_ClientGUIView: {fileID: 0}
|
||||||
|
m_SearchString:
|
||||||
|
m_CreateAssetUtility:
|
||||||
|
m_EndAction: {fileID: 0}
|
||||||
|
m_InstanceID: 0
|
||||||
|
m_Path:
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_ResourceFile:
|
||||||
|
m_ListAreaState:
|
||||||
|
m_SelectedInstanceIDs: 68fbffff
|
||||||
|
m_LastClickedInstanceID: -1176
|
||||||
|
m_HadKeyboardFocusLastEvent: 0
|
||||||
|
m_ExpandedInstanceIDs: c6230000
|
||||||
|
m_RenameOverlay:
|
||||||
|
m_UserAcceptedRename: 0
|
||||||
|
m_Name:
|
||||||
|
m_OriginalName:
|
||||||
|
m_EditFieldRect:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 0
|
||||||
|
y: 0
|
||||||
|
width: 0
|
||||||
|
height: 0
|
||||||
|
m_UserData: 0
|
||||||
|
m_IsWaitingForDelay: 0
|
||||||
|
m_IsRenaming: 0
|
||||||
|
m_OriginalEventType: 11
|
||||||
|
m_IsRenamingFilename: 1
|
||||||
|
m_ClientGUIView: {fileID: 0}
|
||||||
|
m_CreateAssetUtility:
|
||||||
|
m_EndAction: {fileID: 0}
|
||||||
|
m_InstanceID: 0
|
||||||
|
m_Path:
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_ResourceFile:
|
||||||
|
m_NewAssetIndexInList: -1
|
||||||
|
m_ScrollPosition: {x: 0, y: 0}
|
||||||
|
m_GridSize: 64
|
||||||
|
m_DirectoriesAreaWidth: 110
|
||||||
|
--- !u!114 &15
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 52
|
||||||
|
m_PrefabParentObject: {fileID: 0}
|
||||||
|
m_PrefabInternal: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 1
|
||||||
|
m_Script: {fileID: 12015, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
m_AutoRepaintOnSceneChange: 1
|
||||||
|
m_MinSize: {x: 200, y: 200}
|
||||||
|
m_MaxSize: {x: 4000, y: 4000}
|
||||||
|
m_TitleContent:
|
||||||
|
m_Text: Game
|
||||||
|
m_Image: {fileID: -2087823869225018852, guid: 0000000000000000d000000000000000,
|
||||||
|
type: 0}
|
||||||
|
m_Tooltip:
|
||||||
|
m_DepthBufferBits: 32
|
||||||
|
m_Pos:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 0
|
||||||
|
y: 19
|
||||||
|
width: 971
|
||||||
|
height: 421
|
||||||
|
m_MaximizeOnPlay: 0
|
||||||
|
m_Gizmos: 0
|
||||||
|
m_Stats: 0
|
||||||
|
m_SelectedSizes: 00000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
m_TargetDisplay: 0
|
||||||
|
m_ZoomArea:
|
||||||
|
m_HRangeLocked: 0
|
||||||
|
m_VRangeLocked: 0
|
||||||
|
m_HBaseRangeMin: -242.75
|
||||||
|
m_HBaseRangeMax: 242.75
|
||||||
|
m_VBaseRangeMin: -101
|
||||||
|
m_VBaseRangeMax: 101
|
||||||
|
m_HAllowExceedBaseRangeMin: 1
|
||||||
|
m_HAllowExceedBaseRangeMax: 1
|
||||||
|
m_VAllowExceedBaseRangeMin: 1
|
||||||
|
m_VAllowExceedBaseRangeMax: 1
|
||||||
|
m_ScaleWithWindow: 0
|
||||||
|
m_HSlider: 0
|
||||||
|
m_VSlider: 0
|
||||||
|
m_IgnoreScrollWheelUntilClicked: 0
|
||||||
|
m_EnableMouseInput: 1
|
||||||
|
m_EnableSliderZoom: 0
|
||||||
|
m_UniformScale: 1
|
||||||
|
m_UpDirection: 1
|
||||||
|
m_DrawArea:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 0
|
||||||
|
y: 17
|
||||||
|
width: 971
|
||||||
|
height: 404
|
||||||
|
m_Scale: {x: 2, y: 2}
|
||||||
|
m_Translation: {x: 485.5, y: 202}
|
||||||
|
m_MarginLeft: 0
|
||||||
|
m_MarginRight: 0
|
||||||
|
m_MarginTop: 0
|
||||||
|
m_MarginBottom: 0
|
||||||
|
m_LastShownAreaInsideMargins:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: -242.75
|
||||||
|
y: -101
|
||||||
|
width: 485.5
|
||||||
|
height: 202
|
||||||
|
m_MinimalGUI: 1
|
||||||
|
m_defaultScale: 2
|
||||||
|
m_TargetTexture: {fileID: 0}
|
||||||
|
m_CurrentColorSpace: 0
|
||||||
|
m_LastWindowPixelSize: {x: 1942, y: 842}
|
||||||
|
m_ClearInEditMode: 1
|
||||||
|
m_NoCameraWarning: 1
|
||||||
|
m_LowResolutionForAspectRatios: 01000000000100000100
|
||||||
|
--- !u!114 &16
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 52
|
||||||
|
m_PrefabParentObject: {fileID: 0}
|
||||||
|
m_PrefabInternal: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 1
|
||||||
|
m_Script: {fileID: 12013, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
m_AutoRepaintOnSceneChange: 1
|
||||||
|
m_MinSize: {x: 200, y: 200}
|
||||||
|
m_MaxSize: {x: 4000, y: 4000}
|
||||||
|
m_TitleContent:
|
||||||
|
m_Text: Scene
|
||||||
|
m_Image: {fileID: 2318424515335265636, guid: 0000000000000000d000000000000000,
|
||||||
|
type: 0}
|
||||||
|
m_Tooltip:
|
||||||
|
m_DepthBufferBits: 32
|
||||||
|
m_Pos:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 0
|
||||||
|
y: 19
|
||||||
|
width: 971
|
||||||
|
height: 445
|
||||||
|
m_SceneLighting: 1
|
||||||
|
lastFramingTime: 0
|
||||||
|
m_2DMode: 0
|
||||||
|
m_isRotationLocked: 0
|
||||||
|
m_AudioPlay: 0
|
||||||
|
m_Position:
|
||||||
|
m_Target: {x: 0, y: 0, z: 0}
|
||||||
|
speed: 2
|
||||||
|
m_Value: {x: 0, y: 0, z: 0}
|
||||||
|
m_RenderMode: 0
|
||||||
|
m_ValidateTrueMetals: 0
|
||||||
|
m_SceneViewState:
|
||||||
|
showFog: 1
|
||||||
|
showMaterialUpdate: 0
|
||||||
|
showSkybox: 1
|
||||||
|
showFlares: 1
|
||||||
|
showImageEffects: 1
|
||||||
|
grid:
|
||||||
|
xGrid:
|
||||||
|
m_Target: 0
|
||||||
|
speed: 2
|
||||||
|
m_Value: 0
|
||||||
|
yGrid:
|
||||||
|
m_Target: 1
|
||||||
|
speed: 2
|
||||||
|
m_Value: 1
|
||||||
|
zGrid:
|
||||||
|
m_Target: 0
|
||||||
|
speed: 2
|
||||||
|
m_Value: 0
|
||||||
|
m_Rotation:
|
||||||
|
m_Target: {x: -0.08717229, y: 0.89959055, z: -0.21045254, w: -0.3726226}
|
||||||
|
speed: 2
|
||||||
|
m_Value: {x: -0.08717229, y: 0.89959055, z: -0.21045254, w: -0.3726226}
|
||||||
|
m_Size:
|
||||||
|
m_Target: 10
|
||||||
|
speed: 2
|
||||||
|
m_Value: 10
|
||||||
|
m_Ortho:
|
||||||
|
m_Target: 0
|
||||||
|
speed: 2
|
||||||
|
m_Value: 0
|
||||||
|
m_LastSceneViewRotation: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
m_LastSceneViewOrtho: 0
|
||||||
|
m_ReplacementShader: {fileID: 0}
|
||||||
|
m_ReplacementString:
|
||||||
|
m_LastLockedObject: {fileID: 0}
|
||||||
|
m_ViewIsLockedToObject: 0
|
||||||
|
--- !u!114 &17
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 52
|
||||||
|
m_PrefabParentObject: {fileID: 0}
|
||||||
|
m_PrefabInternal: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 1
|
||||||
|
m_Script: {fileID: 12061, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
m_AutoRepaintOnSceneChange: 0
|
||||||
|
m_MinSize: {x: 200, y: 200}
|
||||||
|
m_MaxSize: {x: 4000, y: 4000}
|
||||||
|
m_TitleContent:
|
||||||
|
m_Text: Hierarchy
|
||||||
|
m_Image: {fileID: -590624980919486359, guid: 0000000000000000d000000000000000,
|
||||||
|
type: 0}
|
||||||
|
m_Tooltip:
|
||||||
|
m_DepthBufferBits: 0
|
||||||
|
m_Pos:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 2
|
||||||
|
y: 19
|
||||||
|
width: 286
|
||||||
|
height: 445
|
||||||
|
m_TreeViewState:
|
||||||
|
scrollPos: {x: 0, y: 0}
|
||||||
|
m_SelectedIDs: 68fbffff
|
||||||
|
m_LastClickedID: -1176
|
||||||
|
m_ExpandedIDs: 7efbffff00000000
|
||||||
|
m_RenameOverlay:
|
||||||
|
m_UserAcceptedRename: 0
|
||||||
|
m_Name:
|
||||||
|
m_OriginalName:
|
||||||
|
m_EditFieldRect:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 0
|
||||||
|
y: 0
|
||||||
|
width: 0
|
||||||
|
height: 0
|
||||||
|
m_UserData: 0
|
||||||
|
m_IsWaitingForDelay: 0
|
||||||
|
m_IsRenaming: 0
|
||||||
|
m_OriginalEventType: 11
|
||||||
|
m_IsRenamingFilename: 0
|
||||||
|
m_ClientGUIView: {fileID: 0}
|
||||||
|
m_SearchString:
|
||||||
|
m_ExpandedScenes:
|
||||||
|
-
|
||||||
|
m_CurrenRootInstanceID: 0
|
||||||
|
m_Locked: 0
|
||||||
|
m_CurrentSortingName: TransformSorting
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: eabc9546105bf4accac1fd62a63e88e6
|
||||||
|
timeCreated: 1487337779
|
||||||
|
licenseType: Store
|
||||||
|
DefaultImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 5a9bcd70e6a4b4b05badaa72e827d8e0
|
||||||
|
folderAsset: yes
|
||||||
|
timeCreated: 1475835190
|
||||||
|
licenseType: Store
|
||||||
|
DefaultImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3ad9b87dffba344c89909c6d1b1c17e1
|
||||||
|
folderAsset: yes
|
||||||
|
timeCreated: 1475593892
|
||||||
|
licenseType: Store
|
||||||
|
DefaultImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,242 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEditor;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
[CustomEditor(typeof(Readme))]
|
||||||
|
[InitializeOnLoad]
|
||||||
|
public class ReadmeEditor : Editor
|
||||||
|
{
|
||||||
|
static string s_ShowedReadmeSessionStateName = "ReadmeEditor.showedReadme";
|
||||||
|
|
||||||
|
static string s_ReadmeSourceDirectory = "Assets/TutorialInfo";
|
||||||
|
|
||||||
|
const float k_Space = 16f;
|
||||||
|
|
||||||
|
static ReadmeEditor()
|
||||||
|
{
|
||||||
|
EditorApplication.delayCall += SelectReadmeAutomatically;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RemoveTutorial()
|
||||||
|
{
|
||||||
|
if (EditorUtility.DisplayDialog("Remove Readme Assets",
|
||||||
|
|
||||||
|
$"All contents under {s_ReadmeSourceDirectory} will be removed, are you sure you want to proceed?",
|
||||||
|
"Proceed",
|
||||||
|
"Cancel"))
|
||||||
|
{
|
||||||
|
if (Directory.Exists(s_ReadmeSourceDirectory))
|
||||||
|
{
|
||||||
|
FileUtil.DeleteFileOrDirectory(s_ReadmeSourceDirectory);
|
||||||
|
FileUtil.DeleteFileOrDirectory(s_ReadmeSourceDirectory + ".meta");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Log($"Could not find the Readme folder at {s_ReadmeSourceDirectory}");
|
||||||
|
}
|
||||||
|
|
||||||
|
var readmeAsset = SelectReadme();
|
||||||
|
if (readmeAsset != null)
|
||||||
|
{
|
||||||
|
var path = AssetDatabase.GetAssetPath(readmeAsset);
|
||||||
|
FileUtil.DeleteFileOrDirectory(path + ".meta");
|
||||||
|
FileUtil.DeleteFileOrDirectory(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetDatabase.Refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SelectReadmeAutomatically()
|
||||||
|
{
|
||||||
|
if (!SessionState.GetBool(s_ShowedReadmeSessionStateName, false))
|
||||||
|
{
|
||||||
|
var readme = SelectReadme();
|
||||||
|
SessionState.SetBool(s_ShowedReadmeSessionStateName, true);
|
||||||
|
|
||||||
|
if (readme && !readme.loadedLayout)
|
||||||
|
{
|
||||||
|
LoadLayout();
|
||||||
|
readme.loadedLayout = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LoadLayout()
|
||||||
|
{
|
||||||
|
var assembly = typeof(EditorApplication).Assembly;
|
||||||
|
var windowLayoutType = assembly.GetType("UnityEditor.WindowLayout", true);
|
||||||
|
var method = windowLayoutType.GetMethod("LoadWindowLayout", BindingFlags.Public | BindingFlags.Static);
|
||||||
|
method.Invoke(null, new object[] { Path.Combine(Application.dataPath, "TutorialInfo/Layout.wlt"), false });
|
||||||
|
}
|
||||||
|
|
||||||
|
static Readme SelectReadme()
|
||||||
|
{
|
||||||
|
var ids = AssetDatabase.FindAssets("Readme t:Readme");
|
||||||
|
if (ids.Length == 1)
|
||||||
|
{
|
||||||
|
var readmeObject = AssetDatabase.LoadMainAssetAtPath(AssetDatabase.GUIDToAssetPath(ids[0]));
|
||||||
|
|
||||||
|
Selection.objects = new UnityEngine.Object[] { readmeObject };
|
||||||
|
|
||||||
|
return (Readme)readmeObject;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Log("Couldn't find a readme");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnHeaderGUI()
|
||||||
|
{
|
||||||
|
var readme = (Readme)target;
|
||||||
|
Init();
|
||||||
|
|
||||||
|
var iconWidth = Mathf.Min(EditorGUIUtility.currentViewWidth / 3f - 20f, 128f);
|
||||||
|
|
||||||
|
GUILayout.BeginHorizontal("In BigTitle");
|
||||||
|
{
|
||||||
|
if (readme.icon != null)
|
||||||
|
{
|
||||||
|
GUILayout.Space(k_Space);
|
||||||
|
GUILayout.Label(readme.icon, GUILayout.Width(iconWidth), GUILayout.Height(iconWidth));
|
||||||
|
}
|
||||||
|
GUILayout.Space(k_Space);
|
||||||
|
GUILayout.BeginVertical();
|
||||||
|
{
|
||||||
|
|
||||||
|
GUILayout.FlexibleSpace();
|
||||||
|
GUILayout.Label(readme.title, TitleStyle);
|
||||||
|
GUILayout.FlexibleSpace();
|
||||||
|
}
|
||||||
|
GUILayout.EndVertical();
|
||||||
|
GUILayout.FlexibleSpace();
|
||||||
|
}
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnInspectorGUI()
|
||||||
|
{
|
||||||
|
var readme = (Readme)target;
|
||||||
|
Init();
|
||||||
|
|
||||||
|
foreach (var section in readme.sections)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(section.heading))
|
||||||
|
{
|
||||||
|
GUILayout.Label(section.heading, HeadingStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(section.text))
|
||||||
|
{
|
||||||
|
GUILayout.Label(section.text, BodyStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(section.linkText))
|
||||||
|
{
|
||||||
|
if (LinkLabel(new GUIContent(section.linkText)))
|
||||||
|
{
|
||||||
|
Application.OpenURL(section.url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayout.Space(k_Space);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GUILayout.Button("Remove Readme Assets", ButtonStyle))
|
||||||
|
{
|
||||||
|
RemoveTutorial();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool m_Initialized;
|
||||||
|
|
||||||
|
GUIStyle LinkStyle
|
||||||
|
{
|
||||||
|
get { return m_LinkStyle; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[SerializeField]
|
||||||
|
GUIStyle m_LinkStyle;
|
||||||
|
|
||||||
|
GUIStyle TitleStyle
|
||||||
|
{
|
||||||
|
get { return m_TitleStyle; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[SerializeField]
|
||||||
|
GUIStyle m_TitleStyle;
|
||||||
|
|
||||||
|
GUIStyle HeadingStyle
|
||||||
|
{
|
||||||
|
get { return m_HeadingStyle; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[SerializeField]
|
||||||
|
GUIStyle m_HeadingStyle;
|
||||||
|
|
||||||
|
GUIStyle BodyStyle
|
||||||
|
{
|
||||||
|
get { return m_BodyStyle; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[SerializeField]
|
||||||
|
GUIStyle m_BodyStyle;
|
||||||
|
|
||||||
|
GUIStyle ButtonStyle
|
||||||
|
{
|
||||||
|
get { return m_ButtonStyle; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[SerializeField]
|
||||||
|
GUIStyle m_ButtonStyle;
|
||||||
|
|
||||||
|
void Init()
|
||||||
|
{
|
||||||
|
if (m_Initialized)
|
||||||
|
return;
|
||||||
|
m_BodyStyle = new GUIStyle(EditorStyles.label);
|
||||||
|
m_BodyStyle.wordWrap = true;
|
||||||
|
m_BodyStyle.fontSize = 14;
|
||||||
|
m_BodyStyle.richText = true;
|
||||||
|
|
||||||
|
m_TitleStyle = new GUIStyle(m_BodyStyle);
|
||||||
|
m_TitleStyle.fontSize = 26;
|
||||||
|
|
||||||
|
m_HeadingStyle = new GUIStyle(m_BodyStyle);
|
||||||
|
m_HeadingStyle.fontStyle = FontStyle.Bold;
|
||||||
|
m_HeadingStyle.fontSize = 18;
|
||||||
|
|
||||||
|
m_LinkStyle = new GUIStyle(m_BodyStyle);
|
||||||
|
m_LinkStyle.wordWrap = false;
|
||||||
|
|
||||||
|
// Match selection color which works nicely for both light and dark skins
|
||||||
|
m_LinkStyle.normal.textColor = new Color(0x00 / 255f, 0x78 / 255f, 0xDA / 255f, 1f);
|
||||||
|
m_LinkStyle.stretchWidth = false;
|
||||||
|
|
||||||
|
m_ButtonStyle = new GUIStyle(EditorStyles.miniButton);
|
||||||
|
m_ButtonStyle.fontStyle = FontStyle.Bold;
|
||||||
|
|
||||||
|
m_Initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LinkLabel(GUIContent label, params GUILayoutOption[] options)
|
||||||
|
{
|
||||||
|
var position = GUILayoutUtility.GetRect(label, LinkStyle, options);
|
||||||
|
|
||||||
|
Handles.BeginGUI();
|
||||||
|
Handles.color = LinkStyle.normal.textColor;
|
||||||
|
Handles.DrawLine(new Vector3(position.xMin, position.yMax), new Vector3(position.xMax, position.yMax));
|
||||||
|
Handles.color = Color.white;
|
||||||
|
Handles.EndGUI();
|
||||||
|
|
||||||
|
EditorGUIUtility.AddCursorRect(position, MouseCursor.Link);
|
||||||
|
|
||||||
|
return GUI.Button(position, label, LinkStyle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 476cc7d7cd9874016adc216baab94a0a
|
||||||
|
timeCreated: 1484146680
|
||||||
|
licenseType: Store
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public class Readme : ScriptableObject
|
||||||
|
{
|
||||||
|
public Texture2D icon;
|
||||||
|
public string title;
|
||||||
|
public Section[] sections;
|
||||||
|
public bool loadedLayout;
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class Section
|
||||||
|
{
|
||||||
|
public string heading, text, linkText, url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: fcf7219bab7fe46a1ad266029b2fee19
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences:
|
||||||
|
- icon: {instanceID: 0}
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {fileID: 2800000, guid: a186f8a87ca4f4d3aa864638ad5dfb65, type: 3}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 18dc0cd2c080841dea60987a38ce93fa
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 11400000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,324 @@
|
||||||
|
# Changelog
|
||||||
|
All notable changes to this package will be documented in this file.
|
||||||
|
|
||||||
|
## [12.0.1] - 2025-01-16
|
||||||
|
|
||||||
|
### Preview Generator changes
|
||||||
|
- Updated generated preview collection UI to display the asset extension
|
||||||
|
- Fixed an issue with some prefab and model asset types not generating previews
|
||||||
|
- Fixed an error that could occur when changing scenes after deleting a preview source asset
|
||||||
|
|
||||||
|
## [12.0.0] - 2025-01-13
|
||||||
|
|
||||||
|
### General changes
|
||||||
|
- The code comprising the Asset Store Publishing Tools has been refactored.
|
||||||
|
- Added dependency on Newtonsoft Json
|
||||||
|
|
||||||
|
### Uploader changes
|
||||||
|
- Updated window to retain its state if closed unless a domain reload occurs
|
||||||
|
- Added option to generate higher resolution asset previews when exporting
|
||||||
|
- Fixed a rare issue where authentication would fail
|
||||||
|
- Minor UI tweaks
|
||||||
|
|
||||||
|
### Validator changes
|
||||||
|
- Added validation tests for:
|
||||||
|
- Package naming
|
||||||
|
- Project Template assets
|
||||||
|
- Updated the Type Namespace validation test to check for Unity top level namespaces
|
||||||
|
|
||||||
|
### Exporter changes
|
||||||
|
- Updated how asset previews are generated/included for the package that is being exported
|
||||||
|
|
||||||
|
### Preview Generator
|
||||||
|
- Added a Preview Generator window that can be used to pre-generate and inspect package previews before exporting
|
||||||
|
|
||||||
|
## [11.4.4] - 2024-11-29
|
||||||
|
|
||||||
|
### Validator Changes
|
||||||
|
- The validator UI window description section can now be expanded or shrunk to take up less screen space
|
||||||
|
- Updated severity of the Model Importer Logs validation test
|
||||||
|
|
||||||
|
### Exporter Changes
|
||||||
|
- Updated exporter to always exclude hidden files and folders beginning with the dot symbol (e.g.: .hiddenFolder/ or .hiddenfile.txt)
|
||||||
|
- Updated exporter to explicitly exclude extended attribute files when exporting packages on macOS systems
|
||||||
|
|
||||||
|
### Other
|
||||||
|
- Moved the Asset Store Tools toolbar items into the Tools section
|
||||||
|
- Fixed several window-related compilation warnings when using Unity 6 versions of the Editor
|
||||||
|
|
||||||
|
## [11.4.3] - 2024-08-01
|
||||||
|
|
||||||
|
### Validator Changes
|
||||||
|
- Hotfix: Remove non-ascii characters from the demo scene validation
|
||||||
|
|
||||||
|
## [11.4.2] - 2024-07-30
|
||||||
|
|
||||||
|
### Validator Changes
|
||||||
|
- Check for nested .unitypackage files in the demo scene validation
|
||||||
|
- Prevent normal map test from erroring when misc importer types are detected
|
||||||
|
- Remove Templates category from the uncompressed images requirement list
|
||||||
|
|
||||||
|
## [11.4.1] - 2024-05-10
|
||||||
|
|
||||||
|
### Exporter Changes
|
||||||
|
- Fixed an issue with bundled plugin folder contents not being exported
|
||||||
|
|
||||||
|
### Other
|
||||||
|
- Miscellaneous internal changes
|
||||||
|
|
||||||
|
## [11.4.0] - 2024-01-23
|
||||||
|
|
||||||
|
### Uploader Changes
|
||||||
|
- Added prevention of uploading packages larger than 6 GB
|
||||||
|
- Added a prompt to allow automatically generating meta files within hidden folders
|
||||||
|
- Fixed some obsolete API usage warnings in newer Unity versions
|
||||||
|
|
||||||
|
### Validator Changes
|
||||||
|
- Added validation tests for:
|
||||||
|
- Animation Clip take names
|
||||||
|
- Model import logs
|
||||||
|
- Uncompressed Package size
|
||||||
|
- Updated the fail severity of Audio Clipping validation test
|
||||||
|
- Updated the Demo Scene test to treat default scenes with custom skyboxes as valid demo scenes
|
||||||
|
- Fixed some obsolete API usage warnings in newer Unity versions
|
||||||
|
|
||||||
|
### Other
|
||||||
|
- Added an option to check for Asset Store Publishing Tools updates
|
||||||
|
|
||||||
|
## [11.3.1] - 2023-08-14
|
||||||
|
|
||||||
|
### Uploader Changes
|
||||||
|
- Added the option to select indirect package dependencies from the project (e.g. Mathematics package installed by the Burst package)
|
||||||
|
|
||||||
|
### Validator Changes
|
||||||
|
- Updated the Texture Dimensions test to ignore 'Sprite' and 'Editor GUI' texture types
|
||||||
|
|
||||||
|
### Exporter Changes
|
||||||
|
- Updated exporter to ignore the 'ProjectSettings/ProjectVersion.txt' asset when exporting 'Complete Project' category packages
|
||||||
|
|
||||||
|
## [11.3.0] - 2023-07-04
|
||||||
|
|
||||||
|
### Uploader Changes
|
||||||
|
|
||||||
|
- Added the option to validate a pre-exported package
|
||||||
|
- Added the option to export a .unitypackage file without uploading
|
||||||
|
- Updated the dependency selection UI
|
||||||
|
|
||||||
|
### Validator Changes
|
||||||
|
|
||||||
|
- Added the option to validate several asset paths at once
|
||||||
|
- Note: when validating package that is comprised of several folders (e.g. Assets/MyPackage +
|
||||||
|
Assets/StreamingAssets + Assets/WebGLTemplates), please select all applicable paths that would be included in the package
|
||||||
|
- Added several new validation tests for:
|
||||||
|
- File Menu Names
|
||||||
|
- Compressed files
|
||||||
|
- Model Types
|
||||||
|
- Texture Dimensions
|
||||||
|
- Particle Systems
|
||||||
|
- Normal Map Textures
|
||||||
|
- Audio Clipping
|
||||||
|
- Path Lengths
|
||||||
|
- Script Compilation
|
||||||
|
- Updated validation test severities based on package category
|
||||||
|
- Updated validation tests to each have their own test logic class
|
||||||
|
- Updated validation tests to be displayed in alphabetical order
|
||||||
|
- Fixed several issues with the namespace check test
|
||||||
|
- Fixed scenes in Samples~ folders not being taken into account for the sample scene check test
|
||||||
|
- Other internal changes
|
||||||
|
|
||||||
|
### Exporter Changes
|
||||||
|
|
||||||
|
- Package exporter is now a separate module (similar to Uploader and Validator)
|
||||||
|
- Fixed hidden folders being included when exporting package content
|
||||||
|
- Note: this prevents an issue with the Unity Editor, where exported hidden folders would appear in the Project window
|
||||||
|
as empty folders when imported, despite having content on disk. Content nested within hidden folders is still collected,
|
||||||
|
provided it contains unique .meta files
|
||||||
|
|
||||||
|
## [11.2.2] - 2023-02-23
|
||||||
|
|
||||||
|
### Validator Changes
|
||||||
|
|
||||||
|
- Updated the 'LOD Setup' test to address some issues
|
||||||
|
- Added additional checks for LOD renderers (inactive renderer check, LOD Group reference check, relative hierarchy position to LOD Group check)
|
||||||
|
- LOD Group Component is no longer required to be on the root of the Prefab
|
||||||
|
- Updated the test result message interface when invalid Prefabs are found
|
||||||
|
|
||||||
|
## [11.2.1] - 2023-01-17
|
||||||
|
|
||||||
|
### Uploader Changes
|
||||||
|
|
||||||
|
- Added a more informative error when exporting content with clashing guid meta files in hidden folders
|
||||||
|
- Fixed a compilation issue for Unity 2020.1 and 2020.2
|
||||||
|
- Fixed a rare error condition when queueing multiple package uploads in quick succession
|
||||||
|
- Fixed Asset Store Uploader state not being properly reset if the uploading process fails
|
||||||
|
|
||||||
|
### Validator Changes
|
||||||
|
|
||||||
|
- Updated the Asset Store Validator description
|
||||||
|
- Fixed a rare memory overflow issue when performing package validation
|
||||||
|
|
||||||
|
## [11.2.0] - 2022-11-03
|
||||||
|
|
||||||
|
### Uploader Changes
|
||||||
|
|
||||||
|
- Uploader will now use the custom package exporter by default
|
||||||
|
- An option to use the legacy (native) exporter can be found in the Asset Store Publishing Tools' settings window
|
||||||
|
- When exporting from the Assets folder, package dependencies can now be selected individually instead of being a choice between 'All' or 'None'
|
||||||
|
- This option is only available with the custom exporter
|
||||||
|
- Changed the way the Uploader reports completed uploading tasks
|
||||||
|
- Modal pop-up has been replaced by a new UI view state
|
||||||
|
- Added an option to the Asset Store Publishing Tools' Settings to display the pop-up after a completed upload
|
||||||
|
- Changed exported .unitypackage files to have distinguishable file names
|
||||||
|
- Fixed the Uploader window indefinitely stalling at 100% upload progress when a response from the Asset Store server is not received
|
||||||
|
- Fixed native package exporter producing broken packages when the export path contained hidden folders
|
||||||
|
- Fixed an issue with high CPU usage when uploading packages
|
||||||
|
- Fixed Asset Store Publishing Tools' settings not being saved between Editor sessions on macOS
|
||||||
|
- Other minor changes and tweaks
|
||||||
|
|
||||||
|
### Validator Changes
|
||||||
|
|
||||||
|
- Added two new tests:
|
||||||
|
- 'Types have namespaces': checks whether scripts and native libraries under the validated path are nested under a namespace
|
||||||
|
- 'Consistent line endings': checks whether scripts under the validated path have consistent line endings. This is similar to the warning from the Unity Editor compilation pipeline when a script contains both Windows and UNIX line endings.
|
||||||
|
- Improved 'Reset Prefabs' test to display and be more informative about prefabs with unusually low transform values
|
||||||
|
- Improved 'SpeedTree asset inclusion' test to search for '.st' files
|
||||||
|
- Improved 'Documentation inclusion' test to treat '.md' files as valid documentation files
|
||||||
|
- Improved 'Lossy audio file inclusion' test to treat '.aif' and '.aiff' files as valid non-lossy audio files
|
||||||
|
- Improved 'Lossy audio file inclusion' test to search the project for non-lossy variants of existing lossy audio files
|
||||||
|
- Removed 'Duplicate animation names' test
|
||||||
|
- Tweaked validation severities for several tests
|
||||||
|
- Other minor changes and tweaks
|
||||||
|
|
||||||
|
## [11.1.0] - 2022-09-14
|
||||||
|
|
||||||
|
### Uploader Changes
|
||||||
|
|
||||||
|
- Package Publisher Portal links can now be opened for all packages regardless of package status
|
||||||
|
- External Dependency Manager can now be selected as a 'Special Folder' if found in the root Assets folder
|
||||||
|
|
||||||
|
### Validator Changes
|
||||||
|
|
||||||
|
- Added category selection for the Validator
|
||||||
|
- Categories help determine the outcome of package validation more accurately. For example, documentation is not crucial for art packages, but is required for tooling packages.
|
||||||
|
- Added a list of prefabs with missing mesh references to 'Meshes have Prefabs' test when the test fails
|
||||||
|
- Corrected the message for a passing 'Shader compilation errors' test
|
||||||
|
- Improved the floating point precision accuracy of 'Reset Prefabs' test
|
||||||
|
- Fixed 'Missing Components in Assets' test checking all project folders instead of only the set path
|
||||||
|
- Fixed 'Prefabs for meshes' test not checking meshes in certain paths
|
||||||
|
- Fixed 'Reset Prefabs' test failing because of Prefabs with a Rect Transform Component
|
||||||
|
- Fixed 'Reset Prefabs' test ignoring Transform rotation
|
||||||
|
- Fixed test description text overlapping in some cases
|
||||||
|
- Other minor changes and tweaks
|
||||||
|
|
||||||
|
## [11.0.2] - 2022-08-09
|
||||||
|
|
||||||
|
- Corrected some namespaces which were causing issues when deriving classes from Editor class
|
||||||
|
|
||||||
|
## [11.0.1] - 2022-08-05
|
||||||
|
|
||||||
|
### Uploader Changes
|
||||||
|
|
||||||
|
- Added Settings window (Asset Store Tools > Settings)
|
||||||
|
- Added Soft/Junction Symlink support (enable through Settings)
|
||||||
|
- Added workflow and path selection serialization (workflow saved locally, paths locally and online)
|
||||||
|
- No more logs when using the `-nullable` compiler option (thanks @alfish)
|
||||||
|
- Some API refactoring in preparation for CLI support
|
||||||
|
- Other minor fixes/improvements
|
||||||
|
|
||||||
|
**Note:** when updating Asset Store Tools from the Package Manager, don't forget to remove the old version from the project (V11.0.0) before importing the new one (V11.0.1)
|
||||||
|
|
||||||
|
|
||||||
|
## [11.0.0] - 2022-07-20
|
||||||
|
|
||||||
|
### Uploader changes
|
||||||
|
|
||||||
|
- UI has been reworked using UI Toolkit
|
||||||
|
- New login window, allowing to login using Unity Cloud Services
|
||||||
|
- Improved top bar, including search and sorting
|
||||||
|
- Draft packages moved to the top
|
||||||
|
- Added category, size, and last modified date next to the package
|
||||||
|
- Added a link to the publishing portal next to the package
|
||||||
|
- New uploading flow: “Pre-exported .unitypackage”
|
||||||
|
- Previous uploading flow (folder selection) has been renamed to “From Assets Folder”
|
||||||
|
- Dependencies check has been renamed to “Include Package Manifest” for clarity
|
||||||
|
- Special Folders can now be selected and uploaded together with the package’s main folder (i.e. StreamingAssets, Plugins)
|
||||||
|
- You can now upload to multiple packages at the same time without waiting for the first one to finish
|
||||||
|
- Package can now be validated in the Uploading window by pressing the “Validate” button
|
||||||
|
- Added refresh and logout buttons to the bottom toolbar for easier access
|
||||||
|
- Packages caching - package information will no longer be redownloaded every time you open the Uploader window during the same Editor session
|
||||||
|
- (Experimental) Custom exporter - will export your package ~2 times faster, but may miss some asset previews in the final product. To enable it - click three dots on the top left side of the window and enable “Use Custom Exporting”
|
||||||
|
|
||||||
|
|
||||||
|
### Validator changes
|
||||||
|
|
||||||
|
- UI has been reworked using UI Toolkit
|
||||||
|
- New tests based on the new guidelines
|
||||||
|
- Updated tests’ titles, descriptions, and error reporting
|
||||||
|
|
||||||
|
## [5.0.5] - 2021-11-04
|
||||||
|
|
||||||
|
- Fixed namespace issues
|
||||||
|
|
||||||
|
## [5.0.4] - 2020-07-28
|
||||||
|
|
||||||
|
- Fixed issues with Unity 2020.1
|
||||||
|
|
||||||
|
## [5.0.3] - 2020-05-07
|
||||||
|
|
||||||
|
- Remove "Remove Standard Assets" check
|
||||||
|
|
||||||
|
## [5.0.2] - 2020-04-21
|
||||||
|
|
||||||
|
- Enable auto login with Unity account
|
||||||
|
- Upload package with thread
|
||||||
|
|
||||||
|
## [5.0.1] - 2020-03-23
|
||||||
|
|
||||||
|
- Fix domain resolve issue
|
||||||
|
|
||||||
|
## [5.0.0] - 2019-10-09
|
||||||
|
|
||||||
|
- Added "Package Validator" tool
|
||||||
|
- Added Help window
|
||||||
|
- Added logout confirmation popup
|
||||||
|
- Updated toolbar menu layout
|
||||||
|
- Removed "Mass Labeler" tool
|
||||||
|
- Updated layout of Login and Package Upload windows
|
||||||
|
- Error messages are now more elaborate and user-friendly
|
||||||
|
- Removed deprecated "Main Assets" step from the Package Upload window
|
||||||
|
- Package Upload window now has a step for including package manager dependencies
|
||||||
|
- Tooltips are now added to each upload process step
|
||||||
|
|
||||||
|
|
||||||
|
## [4.1.0] - 2018-05-14
|
||||||
|
|
||||||
|
- Made Tool compatible with 2017.1
|
||||||
|
|
||||||
|
## [4.0.7] - 2017-07-10
|
||||||
|
|
||||||
|
- Tweaked menu items.
|
||||||
|
|
||||||
|
## [4.0.6] - 2016-07-15
|
||||||
|
|
||||||
|
- Improved error messages.
|
||||||
|
|
||||||
|
## [4.0.5] - 2016-03-17
|
||||||
|
|
||||||
|
- Enabling upload of fbm files.
|
||||||
|
|
||||||
|
## [4.0.4] - 2015-11-16
|
||||||
|
|
||||||
|
- Login improvements
|
||||||
|
|
||||||
|
## [4.0.3] - 2015-11-16
|
||||||
|
|
||||||
|
- Prepare the Tools for Unity 5.3
|
||||||
|
|
||||||
|
## [4.0.2] - 2015-10-23
|
||||||
|
|
||||||
|
- Fixed issue where Upload button would not work for some projects.
|
||||||
|
- Fixed issues for publishers that only had one package.
|
||||||
|
|
||||||
|
## [4.0.0] - 2015-09-01
|
||||||
|
|
||||||
|
- Replaced Package Manager with Package Upload. Package management is now handled by Publisher Administration
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 06607220dbd46414e8f66bf9c5e3eb79
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 166da5c6fc70e814a8262463903b2714
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d48a2325d352e7a4cae56d3f8eeaab2d
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 25799fb31cd475347af7f5442c231797
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
using AssetStoreTools.Api.Responses;
|
||||||
|
using AssetStoreTools.Utility;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace AssetStoreTools.Api
|
||||||
|
{
|
||||||
|
internal abstract class AuthenticationBase : IAuthenticationType
|
||||||
|
{
|
||||||
|
protected Uri LoginUrl = ApiUtility.CreateUri(Constants.Api.AuthenticateUrl, true);
|
||||||
|
protected FormUrlEncodedContent AuthenticationContent;
|
||||||
|
|
||||||
|
protected FormUrlEncodedContent GetAuthenticationContent(params KeyValuePair<string, string>[] content)
|
||||||
|
{
|
||||||
|
var baseContent = Constants.Api.DefaultAssetStoreQuery();
|
||||||
|
|
||||||
|
try { baseContent.Add("license_hash", ApiUtility.GetLicenseHash()); } catch { ASDebug.LogWarning("Could not retrieve license hash"); }
|
||||||
|
try { baseContent.Add("hardware_hash", ApiUtility.GetHardwareHash()); } catch { ASDebug.LogWarning("Could not retrieve hardware hash"); }
|
||||||
|
|
||||||
|
foreach (var extraContent in content)
|
||||||
|
{
|
||||||
|
baseContent.Add(extraContent.Key, extraContent.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new FormUrlEncodedContent(baseContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AuthenticationResponse ParseResponse(HttpResponseMessage response)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
var responseString = response.Content.ReadAsStringAsync().Result;
|
||||||
|
return new AuthenticationResponse(responseString);
|
||||||
|
}
|
||||||
|
catch (HttpRequestException e)
|
||||||
|
{
|
||||||
|
return new AuthenticationResponse(response.StatusCode, e) { Success = false };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract Task<AuthenticationResponse> Authenticate(IAssetStoreClient client, CancellationToken cancellationToken = default);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f677e03f1be1048439a1fa5e7a0a37b6
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
using AssetStoreTools.Api.Models;
|
||||||
|
using AssetStoreTools.Api.Responses;
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace AssetStoreTools.Api
|
||||||
|
{
|
||||||
|
internal interface IAssetStoreApi
|
||||||
|
{
|
||||||
|
Task<AssetStoreToolsVersionResponse> GetLatestAssetStoreToolsVersion(CancellationToken cancellationToken = default);
|
||||||
|
Task<AuthenticationResponse> Authenticate(IAuthenticationType authenticationType, CancellationToken cancellationToken = default);
|
||||||
|
void Deauthenticate();
|
||||||
|
Task<PackagesDataResponse> GetPackages(CancellationToken cancellationToken = default);
|
||||||
|
Task<CategoryDataResponse> GetCategories(CancellationToken cancellationToken = default);
|
||||||
|
Task<PackageThumbnailResponse> GetPackageThumbnail(Package package, CancellationToken cancellationToken = default);
|
||||||
|
Task<RefreshedPackageDataResponse> RefreshPackageMetadata(Package package, CancellationToken cancellationToken = default);
|
||||||
|
Task<PackageUploadedUnityVersionDataResponse> GetPackageUploadedVersions(Package package, CancellationToken cancellationToken = default);
|
||||||
|
Task<PackageUploadResponse> UploadPackage(IPackageUploader uploader, IProgress<float> progress = null, CancellationToken cancellationToken = default);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e616488c25d278741bb0d08168219309
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
using System;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace AssetStoreTools.Api
|
||||||
|
{
|
||||||
|
internal interface IAssetStoreClient
|
||||||
|
{
|
||||||
|
void SetSessionId(string sessionId);
|
||||||
|
void ClearSessionId();
|
||||||
|
|
||||||
|
Task<HttpResponseMessage> Get(Uri uri, CancellationToken cancellationToken = default);
|
||||||
|
Task<HttpResponseMessage> Post(Uri uri, HttpContent content, CancellationToken cancellationToken = default);
|
||||||
|
Task<HttpResponseMessage> Put(Uri uri, HttpContent content, CancellationToken cancellationToken = default);
|
||||||
|
Task<HttpResponseMessage> Send(HttpRequestMessage request, CancellationToken cancellationToken = default);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b2bbadec62178cc4189e605367b219e7
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
using AssetStoreTools.Api.Responses;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace AssetStoreTools.Api
|
||||||
|
{
|
||||||
|
internal interface IAuthenticationType
|
||||||
|
{
|
||||||
|
Task<AuthenticationResponse> Authenticate(IAssetStoreClient client, CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0000dcd6975bc8e4abc546a19f194040
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
using AssetStoreTools.Api.Responses;
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace AssetStoreTools.Api
|
||||||
|
{
|
||||||
|
internal interface IPackageUploader
|
||||||
|
{
|
||||||
|
Task<PackageUploadResponse> Upload(IAssetStoreClient client, IProgress<float> progress, CancellationToken cancellationToken = default);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0fc6c47b1c0a65540a40efbf1491193b
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
using AssetStoreTools.Api.Responses;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace AssetStoreTools.Api
|
||||||
|
{
|
||||||
|
internal abstract class PackageUploaderBase : IPackageUploader
|
||||||
|
{
|
||||||
|
protected const int UploadChunkSizeBytes = 32768;
|
||||||
|
protected const int UploadResponseTimeoutMs = 10000;
|
||||||
|
|
||||||
|
protected abstract void ValidateSettings();
|
||||||
|
public abstract Task<PackageUploadResponse> Upload(IAssetStoreClient client, IProgress<float> progress = null, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
protected void EnsureSuccessResponse(HttpResponseMessage response)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
throw new Exception(response.Content.ReadAsStringAsync().Result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void WaitForUploadCompletion(Task<HttpResponseMessage> response, FileStream requestFileStream, IProgress<float> progress, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
// Progress tracking
|
||||||
|
int updateIntervalMs = 100;
|
||||||
|
bool allBytesSent = false;
|
||||||
|
DateTime timeOfCompletion = default;
|
||||||
|
|
||||||
|
while (!response.IsCompleted)
|
||||||
|
{
|
||||||
|
float uploadProgress = (float)requestFileStream.Position / requestFileStream.Length * 100;
|
||||||
|
progress?.Report(uploadProgress);
|
||||||
|
Thread.Sleep(updateIntervalMs);
|
||||||
|
|
||||||
|
// A timeout for rare cases, when package uploading reaches 100%, but Put task IsComplete value remains 'False'
|
||||||
|
if (requestFileStream.Position == requestFileStream.Length)
|
||||||
|
{
|
||||||
|
if (!allBytesSent)
|
||||||
|
{
|
||||||
|
allBytesSent = true;
|
||||||
|
timeOfCompletion = DateTime.UtcNow;
|
||||||
|
}
|
||||||
|
else if (DateTime.UtcNow.Subtract(timeOfCompletion).TotalMilliseconds > UploadResponseTimeoutMs)
|
||||||
|
{
|
||||||
|
throw new TimeoutException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 2718ddd16e425ba4a82ab973724bcff7
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
using AssetStoreTools.Api.Models;
|
||||||
|
using AssetStoreTools.Utility;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using UnityEditorInternal;
|
||||||
|
|
||||||
|
namespace AssetStoreTools.Api
|
||||||
|
{
|
||||||
|
internal class ApiUtility
|
||||||
|
{
|
||||||
|
public static Uri CreateUri(string url, bool includeDefaultAssetStoreQuery) => CreateUri(url, null, includeDefaultAssetStoreQuery);
|
||||||
|
public static Uri CreateUri(string url, IDictionary<string, string> queryParameters, bool includeDefaultAssetStoreQuery)
|
||||||
|
{
|
||||||
|
IDictionary<string, string> fullQueryParameters = includeDefaultAssetStoreQuery ?
|
||||||
|
Constants.Api.DefaultAssetStoreQuery() : new Dictionary<string, string>();
|
||||||
|
|
||||||
|
if (queryParameters != null && queryParameters.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (var kvp in queryParameters)
|
||||||
|
fullQueryParameters.Add(kvp);
|
||||||
|
}
|
||||||
|
|
||||||
|
var builder = new UriBuilder(url);
|
||||||
|
if (fullQueryParameters.Count == 0)
|
||||||
|
return builder.Uri;
|
||||||
|
|
||||||
|
var fullQueryParameterString = string.Empty;
|
||||||
|
foreach (var queryParam in fullQueryParameters)
|
||||||
|
{
|
||||||
|
var escapedValue = queryParam.Value != null ? Uri.EscapeDataString(queryParam.Value) : string.Empty;
|
||||||
|
fullQueryParameterString += $"{queryParam.Key}={escapedValue}&";
|
||||||
|
}
|
||||||
|
fullQueryParameterString = fullQueryParameterString.Remove(fullQueryParameterString.Length - 1);
|
||||||
|
|
||||||
|
builder.Query = fullQueryParameterString;
|
||||||
|
return builder.Uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Package> CombinePackageData(List<Package> mainPackageData, List<PackageAdditionalData> extraPackageData, List<Category> categoryData)
|
||||||
|
{
|
||||||
|
foreach (var package in mainPackageData)
|
||||||
|
{
|
||||||
|
var extraData = extraPackageData.FirstOrDefault(x => package.PackageId == x.PackageId);
|
||||||
|
|
||||||
|
if (extraData == null)
|
||||||
|
{
|
||||||
|
ASDebug.LogWarning($"Could not find extra data for Package {package.PackageId}");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var categoryId = extraData.CategoryId;
|
||||||
|
var category = categoryData.FirstOrDefault(x => x.Id.ToString() == categoryId);
|
||||||
|
if (category != null)
|
||||||
|
package.Category = category.Name;
|
||||||
|
else
|
||||||
|
package.Category = "Unknown";
|
||||||
|
|
||||||
|
package.Modified = extraData.Modified;
|
||||||
|
package.Size = extraData.Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mainPackageData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetLicenseHash()
|
||||||
|
{
|
||||||
|
return InternalEditorUtility.GetAuthToken().Substring(0, 40);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetHardwareHash()
|
||||||
|
{
|
||||||
|
return InternalEditorUtility.GetAuthToken().Substring(40, 40);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 5becec0b3c0ba274fb0b01544e63b6c4
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,268 @@
|
||||||
|
using AssetStoreTools.Api.Models;
|
||||||
|
using AssetStoreTools.Api.Responses;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace AssetStoreTools.Api
|
||||||
|
{
|
||||||
|
internal class AssetStoreApi : IAssetStoreApi
|
||||||
|
{
|
||||||
|
private IAssetStoreClient _client;
|
||||||
|
|
||||||
|
public AssetStoreApi(IAssetStoreClient client)
|
||||||
|
{
|
||||||
|
_client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<AssetStoreToolsVersionResponse> GetLatestAssetStoreToolsVersion(CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var uri = ApiUtility.CreateUri(Constants.Api.AssetStoreToolsLatestVersionUrl, false);
|
||||||
|
var response = await _client.Get(uri, cancellationToken);
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
var responseStr = response.Content.ReadAsStringAsync().Result;
|
||||||
|
return new AssetStoreToolsVersionResponse(responseStr);
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException e)
|
||||||
|
{
|
||||||
|
return new AssetStoreToolsVersionResponse() { Success = false, Cancelled = true, Exception = e };
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return new AssetStoreToolsVersionResponse() { Success = false, Exception = e };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<AuthenticationResponse> Authenticate(IAuthenticationType authenticationType, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var loginResponse = await authenticationType.Authenticate(_client, cancellationToken);
|
||||||
|
if (loginResponse.Success)
|
||||||
|
{
|
||||||
|
_client.SetSessionId(loginResponse.User.SessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return loginResponse;
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException e)
|
||||||
|
{
|
||||||
|
return new AuthenticationResponse() { Success = false, Cancelled = true, Exception = e };
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return new AuthenticationResponse() { Success = false, Exception = e };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Deauthenticate()
|
||||||
|
{
|
||||||
|
_client.ClearSessionId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<PackagesDataResponse> GetPackages(CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var mainDataResponse = await GetPackageDataMain(cancellationToken);
|
||||||
|
if (!mainDataResponse.Success)
|
||||||
|
throw mainDataResponse.Exception;
|
||||||
|
var additionalDataResponse = await GetPackageDataExtra(cancellationToken);
|
||||||
|
if (!additionalDataResponse.Success)
|
||||||
|
throw additionalDataResponse.Exception;
|
||||||
|
var categoryDataResponse = await GetCategories(cancellationToken);
|
||||||
|
if (!categoryDataResponse.Success)
|
||||||
|
throw categoryDataResponse.Exception;
|
||||||
|
|
||||||
|
var joinedData = ApiUtility.CombinePackageData(mainDataResponse.Packages, additionalDataResponse.Packages, categoryDataResponse.Categories);
|
||||||
|
return new PackagesDataResponse() { Success = true, Packages = joinedData };
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException e)
|
||||||
|
{
|
||||||
|
return new PackagesDataResponse() { Success = false, Cancelled = true, Exception = e };
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return new PackagesDataResponse() { Success = false, Exception = e };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<PackagesDataResponse> GetPackageDataMain(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var uri = ApiUtility.CreateUri(Constants.Api.GetPackagesUrl, true);
|
||||||
|
var response = await _client.Get(uri, cancellationToken);
|
||||||
|
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
var responseStr = response.Content.ReadAsStringAsync().Result;
|
||||||
|
return new PackagesDataResponse(responseStr);
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException e)
|
||||||
|
{
|
||||||
|
return new PackagesDataResponse() { Success = false, Cancelled = true, Exception = e };
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return new PackagesDataResponse() { Success = false, Exception = e };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<PackagesAdditionalDataResponse> GetPackageDataExtra(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var uri = ApiUtility.CreateUri(Constants.Api.GetPackagesAdditionalDataUrl, true);
|
||||||
|
var response = await _client.Get(uri, cancellationToken);
|
||||||
|
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
var responseStr = response.Content.ReadAsStringAsync().Result;
|
||||||
|
return new PackagesAdditionalDataResponse(responseStr);
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException e)
|
||||||
|
{
|
||||||
|
return new PackagesAdditionalDataResponse() { Success = false, Cancelled = true, Exception = e };
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return new PackagesAdditionalDataResponse() { Success = false, Exception = e };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<CategoryDataResponse> GetCategories(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var uri = ApiUtility.CreateUri(Constants.Api.GetCategoriesUrl, true);
|
||||||
|
var response = await _client.Get(uri, cancellationToken);
|
||||||
|
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
var responseStr = response.Content.ReadAsStringAsync().Result;
|
||||||
|
return new CategoryDataResponse(responseStr);
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException e)
|
||||||
|
{
|
||||||
|
return new CategoryDataResponse() { Success = false, Cancelled = true, Exception = e };
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return new CategoryDataResponse() { Success = false, Exception = e };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<PackageThumbnailResponse> GetPackageThumbnail(Package package, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(package.IconUrl))
|
||||||
|
throw new Exception($"Could not retrieve thumbnail for package {package.PackageId} - icon url is null");
|
||||||
|
|
||||||
|
var response = await _client.Get(new Uri(package.IconUrl), cancellationToken);
|
||||||
|
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
var responseBytes = response.Content.ReadAsByteArrayAsync().Result;
|
||||||
|
return new PackageThumbnailResponse(responseBytes);
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException e)
|
||||||
|
{
|
||||||
|
return new PackageThumbnailResponse() { Success = false, Cancelled = true, Exception = e };
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return new PackageThumbnailResponse() { Success = false, Exception = e };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<RefreshedPackageDataResponse> RefreshPackageMetadata(Package package, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var refreshedPackage = JObject.FromObject(package).DeepClone().ToObject<Package>();
|
||||||
|
|
||||||
|
var packagesResponse = await GetPackageDataExtra(cancellationToken);
|
||||||
|
if (!packagesResponse.Success)
|
||||||
|
throw packagesResponse.Exception;
|
||||||
|
|
||||||
|
// Find the updated package data in the latest data json
|
||||||
|
var packageRefreshSource = packagesResponse.Packages.FirstOrDefault(x => x.PackageId == refreshedPackage.PackageId);
|
||||||
|
if (packageRefreshSource == null)
|
||||||
|
return new RefreshedPackageDataResponse() { Success = false, Exception = new MissingMemberException($"Unable to find downloaded package data for package id {package.PackageId}") };
|
||||||
|
|
||||||
|
// Retrieve the category map
|
||||||
|
var categoryData = await GetCategories(cancellationToken);
|
||||||
|
if (!categoryData.Success)
|
||||||
|
return new RefreshedPackageDataResponse() { Success = false, Exception = packagesResponse.Exception };
|
||||||
|
|
||||||
|
// Update the package data
|
||||||
|
refreshedPackage.Name = packageRefreshSource.Name;
|
||||||
|
refreshedPackage.Status = packageRefreshSource.Status;
|
||||||
|
var newCategory = categoryData.Categories.FirstOrDefault(x => x.Id.ToString() == packageRefreshSource.CategoryId);
|
||||||
|
refreshedPackage.Category = newCategory != null ? newCategory.Name : "Unknown";
|
||||||
|
refreshedPackage.Modified = packageRefreshSource.Modified;
|
||||||
|
refreshedPackage.Size = packageRefreshSource.Size;
|
||||||
|
|
||||||
|
return new RefreshedPackageDataResponse() { Success = true, Package = refreshedPackage };
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
return new RefreshedPackageDataResponse() { Success = false, Cancelled = true };
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return new RefreshedPackageDataResponse() { Success = false, Exception = e };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<PackageUploadedUnityVersionDataResponse> GetPackageUploadedVersions(Package package, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var uri = ApiUtility.CreateUri(Constants.Api.GetPackageUploadedVersionsUrl(package.PackageId, package.VersionId), true);
|
||||||
|
var response = await _client.Get(uri, cancellationToken);
|
||||||
|
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
var responseStr = response.Content.ReadAsStringAsync().Result;
|
||||||
|
return new PackageUploadedUnityVersionDataResponse(responseStr);
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException e)
|
||||||
|
{
|
||||||
|
return new PackageUploadedUnityVersionDataResponse() { Success = false, Cancelled = true, Exception = e };
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return new PackageUploadedUnityVersionDataResponse() { Success = false, Exception = e };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<PackageUploadResponse> UploadPackage(IPackageUploader uploader, IProgress<float> progress = null, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await uploader.Upload(_client, progress, cancellationToken);
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException e)
|
||||||
|
{
|
||||||
|
return new PackageUploadResponse() { Success = false, Cancelled = true, Exception = e };
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return new PackageUploadResponse() { Success = false, Exception = e };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 684fca3fffd79d944a32d9b3adbfc007
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
using System;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace AssetStoreTools.Api
|
||||||
|
{
|
||||||
|
internal class AssetStoreClient : IAssetStoreClient
|
||||||
|
{
|
||||||
|
private HttpClient _httpClient;
|
||||||
|
|
||||||
|
public AssetStoreClient()
|
||||||
|
{
|
||||||
|
ServicePointManager.DefaultConnectionLimit = 500;
|
||||||
|
_httpClient = new HttpClient();
|
||||||
|
_httpClient.DefaultRequestHeaders.ConnectionClose = false;
|
||||||
|
_httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
|
||||||
|
_httpClient.Timeout = TimeSpan.FromMinutes(1320);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetSessionId(string sessionId)
|
||||||
|
{
|
||||||
|
ClearSessionId();
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(sessionId))
|
||||||
|
_httpClient.DefaultRequestHeaders.Add("X-Unity-Session", sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearSessionId()
|
||||||
|
{
|
||||||
|
_httpClient.DefaultRequestHeaders.Remove("X-Unity-Session");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<HttpResponseMessage> Get(Uri uri, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
return _httpClient.GetAsync(uri, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<HttpResponseMessage> Post(Uri uri, HttpContent content, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
return _httpClient.PostAsync(uri, content, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<HttpResponseMessage> Put(Uri uri, HttpContent content, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
return _httpClient.PutAsync(uri, content, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<HttpResponseMessage> Send(HttpRequestMessage request, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
return _httpClient.SendAsync(request, cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 80b4527c908161a4b9f06dc393b502f9
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
using AssetStoreTools.Api.Responses;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace AssetStoreTools.Api
|
||||||
|
{
|
||||||
|
internal class CloudTokenAuthentication : AuthenticationBase
|
||||||
|
{
|
||||||
|
public CloudTokenAuthentication(string cloudToken)
|
||||||
|
{
|
||||||
|
AuthenticationContent = GetAuthenticationContent(
|
||||||
|
new KeyValuePair<string, string>("user_access_token", cloudToken)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<AuthenticationResponse> Authenticate(IAssetStoreClient client, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var result = await client.Post(LoginUrl, AuthenticationContent, cancellationToken);
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
return ParseResponse(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 99f1baec74f26a34bb972b19c92d523f
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
using AssetStoreTools.Api.Responses;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace AssetStoreTools.Api
|
||||||
|
{
|
||||||
|
internal class CredentialsAuthentication : AuthenticationBase
|
||||||
|
{
|
||||||
|
public CredentialsAuthentication(string email, string password)
|
||||||
|
{
|
||||||
|
AuthenticationContent = GetAuthenticationContent(
|
||||||
|
new KeyValuePair<string, string>("user", email),
|
||||||
|
new KeyValuePair<string, string>("pass", password)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<AuthenticationResponse> Authenticate(IAssetStoreClient client, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var result = await client.Post(LoginUrl, AuthenticationContent, cancellationToken);
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
return ParseResponse(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 353e556b63fd441428f387bc85aa612c
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 1f83e4b5507886f4b873c22c146b8f6a
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace AssetStoreTools.Api.Models
|
||||||
|
{
|
||||||
|
internal class Category
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Status { get; set; }
|
||||||
|
|
||||||
|
public class AssetStoreCategoryResolver : DefaultContractResolver
|
||||||
|
{
|
||||||
|
private Dictionary<string, string> _propertyConversions;
|
||||||
|
|
||||||
|
public AssetStoreCategoryResolver()
|
||||||
|
{
|
||||||
|
_propertyConversions = new Dictionary<string, string>()
|
||||||
|
{
|
||||||
|
{ nameof(Category.Name), "assetstore_name" }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string ResolvePropertyName(string propertyName)
|
||||||
|
{
|
||||||
|
if (_propertyConversions.ContainsKey(propertyName))
|
||||||
|
return _propertyConversions[propertyName];
|
||||||
|
|
||||||
|
return base.ResolvePropertyName(propertyName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CachedCategoryResolver : DefaultContractResolver
|
||||||
|
{
|
||||||
|
private static CachedCategoryResolver _instance;
|
||||||
|
public static CachedCategoryResolver Instance => _instance ?? (_instance = new CachedCategoryResolver());
|
||||||
|
|
||||||
|
private Dictionary<string, string> _propertyConversion;
|
||||||
|
|
||||||
|
private CachedCategoryResolver()
|
||||||
|
{
|
||||||
|
this.NamingStrategy = new SnakeCaseNamingStrategy();
|
||||||
|
_propertyConversion = new Dictionary<string, string>()
|
||||||
|
{
|
||||||
|
{ nameof(Category.Name), "name" }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string ResolvePropertyName(string propertyName)
|
||||||
|
{
|
||||||
|
if (_propertyConversion.ContainsKey(propertyName))
|
||||||
|
return _propertyConversion[propertyName];
|
||||||
|
|
||||||
|
return base.ResolvePropertyName(propertyName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 5897866bc65f5834dab1f17371daada7
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace AssetStoreTools.Api.Models
|
||||||
|
{
|
||||||
|
internal class Package
|
||||||
|
{
|
||||||
|
public string PackageId { get; set; }
|
||||||
|
public string VersionId { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Status { get; set; }
|
||||||
|
public string Category { get; set; }
|
||||||
|
public bool IsCompleteProject { get; set; }
|
||||||
|
public string RootGuid { get; set; }
|
||||||
|
public string RootPath { get; set; }
|
||||||
|
public string ProjectPath { get; set; }
|
||||||
|
public string Modified { get; set; }
|
||||||
|
public string Size { get; set; }
|
||||||
|
public string IconUrl { get; set; }
|
||||||
|
|
||||||
|
public class AssetStorePackageResolver : DefaultContractResolver
|
||||||
|
{
|
||||||
|
private static AssetStorePackageResolver _instance;
|
||||||
|
public static AssetStorePackageResolver Instance => _instance ?? (_instance = new AssetStorePackageResolver());
|
||||||
|
|
||||||
|
private Dictionary<string, string> _propertyConversions;
|
||||||
|
|
||||||
|
private AssetStorePackageResolver()
|
||||||
|
{
|
||||||
|
_propertyConversions = new Dictionary<string, string>()
|
||||||
|
{
|
||||||
|
{ nameof(Package.VersionId), "id" },
|
||||||
|
{ nameof(Package.IsCompleteProject), "is_complete_project" },
|
||||||
|
{ nameof(Package.RootGuid), "root_guid" },
|
||||||
|
{ nameof(Package.RootPath), "root_path" },
|
||||||
|
{ nameof(Package.ProjectPath), "project_path" },
|
||||||
|
{ nameof(Package.IconUrl), "icon_url" }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string ResolvePropertyName(string propertyName)
|
||||||
|
{
|
||||||
|
if (_propertyConversions.ContainsKey(propertyName))
|
||||||
|
return _propertyConversions[propertyName];
|
||||||
|
|
||||||
|
return base.ResolvePropertyName(propertyName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CachedPackageResolver : DefaultContractResolver
|
||||||
|
{
|
||||||
|
private static CachedPackageResolver _instance;
|
||||||
|
public static CachedPackageResolver Instance => _instance ?? (_instance = new CachedPackageResolver());
|
||||||
|
|
||||||
|
private Dictionary<string, string> _propertyConversion;
|
||||||
|
|
||||||
|
private CachedPackageResolver()
|
||||||
|
{
|
||||||
|
this.NamingStrategy = new SnakeCaseNamingStrategy();
|
||||||
|
_propertyConversion = new Dictionary<string, string>()
|
||||||
|
{
|
||||||
|
{ nameof(Package.PackageId), "package_id" },
|
||||||
|
{ nameof(Package.VersionId), "version_id" },
|
||||||
|
{ nameof(Package.IsCompleteProject), "is_complete_project" },
|
||||||
|
{ nameof(Package.RootGuid), "root_guid" },
|
||||||
|
{ nameof(Package.RootPath), "root_path" },
|
||||||
|
{ nameof(Package.IconUrl), "icon_url" }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string ResolvePropertyName(string propertyName)
|
||||||
|
{
|
||||||
|
if (_propertyConversion.ContainsKey(propertyName))
|
||||||
|
return _propertyConversion[propertyName];
|
||||||
|
|
||||||
|
return base.ResolvePropertyName(propertyName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 7e9f0b99820061b49abf6e8cf544a727
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace AssetStoreTools.Api.Models
|
||||||
|
{
|
||||||
|
internal class PackageAdditionalData
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Status { get; set; }
|
||||||
|
public string PackageId { get; set; }
|
||||||
|
public string VersionId { get; set; }
|
||||||
|
public string CategoryId { get; set; }
|
||||||
|
public string Modified { get; set; }
|
||||||
|
public string Size { get; set; }
|
||||||
|
|
||||||
|
public class AssetStorePackageResolver : DefaultContractResolver
|
||||||
|
{
|
||||||
|
private static AssetStorePackageResolver _instance;
|
||||||
|
public static AssetStorePackageResolver Instance => _instance ?? (_instance = new AssetStorePackageResolver());
|
||||||
|
|
||||||
|
private Dictionary<string, string> _propertyConversions;
|
||||||
|
|
||||||
|
private AssetStorePackageResolver()
|
||||||
|
{
|
||||||
|
_propertyConversions = new Dictionary<string, string>()
|
||||||
|
{
|
||||||
|
{ nameof(PackageAdditionalData.PackageId), "id" },
|
||||||
|
{ nameof(PackageAdditionalData.CategoryId), "category_id" }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string ResolvePropertyName(string propertyName)
|
||||||
|
{
|
||||||
|
if (_propertyConversions.ContainsKey(propertyName))
|
||||||
|
return _propertyConversions[propertyName];
|
||||||
|
|
||||||
|
return base.ResolvePropertyName(propertyName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0663f29f3fcd0e34ab77338d1bdbb528
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace AssetStoreTools.Api.Models
|
||||||
|
{
|
||||||
|
internal class User
|
||||||
|
{
|
||||||
|
public string Id { get; set; }
|
||||||
|
public string SessionId { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Username { get; set; }
|
||||||
|
public string PublisherId { get; set; }
|
||||||
|
public bool IsPublisher => !string.IsNullOrEmpty(PublisherId);
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return
|
||||||
|
$"{nameof(Id)}: {Id}\n" +
|
||||||
|
$"{nameof(Name)}: {Name}\n" +
|
||||||
|
$"{nameof(Username)}: {Username}\n" +
|
||||||
|
$"{nameof(PublisherId)}: {PublisherId}\n" +
|
||||||
|
$"{nameof(IsPublisher)}: {IsPublisher}\n" +
|
||||||
|
$"{nameof(SessionId)}: [HIDDEN]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AssetStoreUserResolver : DefaultContractResolver
|
||||||
|
{
|
||||||
|
private static AssetStoreUserResolver _instance;
|
||||||
|
public static AssetStoreUserResolver Instance => _instance ?? (_instance = new AssetStoreUserResolver());
|
||||||
|
|
||||||
|
private Dictionary<string, string> _propertyConversions;
|
||||||
|
|
||||||
|
private AssetStoreUserResolver()
|
||||||
|
{
|
||||||
|
_propertyConversions = new Dictionary<string, string>()
|
||||||
|
{
|
||||||
|
{ nameof(User.SessionId), "xunitysession" },
|
||||||
|
{ nameof(User.PublisherId), "publisher" }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string ResolvePropertyName(string propertyName)
|
||||||
|
{
|
||||||
|
if (_propertyConversions.ContainsKey(propertyName))
|
||||||
|
return _propertyConversions[propertyName];
|
||||||
|
|
||||||
|
return base.ResolvePropertyName(propertyName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: caf38df5cd685a345a1ebec8f7651c93
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 49581213e7b6ca645955cce8ce23ac4b
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace AssetStoreTools.Api.Responses
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A structure used to return the success outcome and the result of Asset Store API calls
|
||||||
|
/// </summary>
|
||||||
|
internal class AssetStoreResponse
|
||||||
|
{
|
||||||
|
public bool Success { get; set; } = false;
|
||||||
|
public bool Cancelled { get; set; } = false;
|
||||||
|
public Exception Exception { get; set; }
|
||||||
|
|
||||||
|
public AssetStoreResponse() { }
|
||||||
|
|
||||||
|
public AssetStoreResponse(Exception e) : this()
|
||||||
|
{
|
||||||
|
Exception = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void ValidateAssetStoreResponse(string json)
|
||||||
|
{
|
||||||
|
var dict = JsonConvert.DeserializeObject<JObject>(json);
|
||||||
|
if (dict == null)
|
||||||
|
throw new Exception("Response is empty");
|
||||||
|
|
||||||
|
// Some json responses return an error field on error
|
||||||
|
if (dict.ContainsKey("error"))
|
||||||
|
{
|
||||||
|
// Server side error message
|
||||||
|
// Do not write to console since this is an error that
|
||||||
|
// is "expected" ie. can be handled by the gui.
|
||||||
|
throw new Exception(dict.GetValue("error").ToString());
|
||||||
|
}
|
||||||
|
// Some json responses return status+message fields instead of an error field. Go figure.
|
||||||
|
else if (dict.ContainsKey("status") && dict.GetValue("status").ToString() != "ok"
|
||||||
|
&& dict.ContainsKey("message"))
|
||||||
|
{
|
||||||
|
throw new Exception(dict.GetValue("message").ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ee338db031a0cfb459f7cac7f41a5d75
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace AssetStoreTools.Api.Responses
|
||||||
|
{
|
||||||
|
internal class AssetStoreToolsVersionResponse : AssetStoreResponse
|
||||||
|
{
|
||||||
|
public string Version { get; set; }
|
||||||
|
|
||||||
|
public AssetStoreToolsVersionResponse() : base() { }
|
||||||
|
public AssetStoreToolsVersionResponse(Exception e) : base(e) { }
|
||||||
|
|
||||||
|
public AssetStoreToolsVersionResponse(string json)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ValidateAssetStoreResponse(json);
|
||||||
|
ParseVersion(json);
|
||||||
|
Success = true;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Success = false;
|
||||||
|
Exception = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ParseVersion(string json)
|
||||||
|
{
|
||||||
|
var dict = JsonConvert.DeserializeObject<JObject>(json);
|
||||||
|
if (!dict.ContainsKey("version"))
|
||||||
|
throw new Exception("Version was not found");
|
||||||
|
|
||||||
|
Version = dict.GetValue("version").ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 40558675926f913478a654350149209e
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
using AssetStoreTools.Api.Models;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
|
||||||
|
namespace AssetStoreTools.Api.Responses
|
||||||
|
{
|
||||||
|
internal class AuthenticationResponse : AssetStoreResponse
|
||||||
|
{
|
||||||
|
public User User { get; set; }
|
||||||
|
|
||||||
|
public AuthenticationResponse() : base() { }
|
||||||
|
|
||||||
|
public AuthenticationResponse(Exception e) : base(e) { }
|
||||||
|
|
||||||
|
public AuthenticationResponse(HttpStatusCode statusCode, HttpRequestException fallbackException)
|
||||||
|
{
|
||||||
|
string message;
|
||||||
|
switch (statusCode)
|
||||||
|
{
|
||||||
|
case HttpStatusCode.Unauthorized:
|
||||||
|
message = "Incorrect email and/or password. Please try again.";
|
||||||
|
break;
|
||||||
|
case HttpStatusCode.InternalServerError:
|
||||||
|
message = "Authentication request failed\nIf you were logging in with your Unity Cloud account, please make sure you are still logged in.\n" +
|
||||||
|
"This might also be caused by too many invalid login attempts - if that is the case, please try again later.";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Exception = fallbackException;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Exception = new Exception(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthenticationResponse(string json)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ValidateAssetStoreResponse(json);
|
||||||
|
var serializerSettings = new JsonSerializerSettings()
|
||||||
|
{
|
||||||
|
ContractResolver = User.AssetStoreUserResolver.Instance
|
||||||
|
};
|
||||||
|
User = JsonConvert.DeserializeObject<User>(json, serializerSettings);
|
||||||
|
ValidateLoginData();
|
||||||
|
ValidatePublisher();
|
||||||
|
Success = true;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Success = false;
|
||||||
|
Exception = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ValidateLoginData()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(User.Id)
|
||||||
|
|| string.IsNullOrEmpty(User.SessionId)
|
||||||
|
|| string.IsNullOrEmpty(User.Name)
|
||||||
|
|| string.IsNullOrEmpty(User.Username))
|
||||||
|
throw new Exception("Could not parse the necessary publisher information from the response.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ValidatePublisher()
|
||||||
|
{
|
||||||
|
if (!User.IsPublisher)
|
||||||
|
throw new Exception($"Your Unity ID {User.Name} is not currently connected to a publisher account. " +
|
||||||
|
$"Please create a publisher profile.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ec3a5cb59a7e78646b07f800d317874d
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
using AssetStoreTools.Api.Models;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace AssetStoreTools.Api.Responses
|
||||||
|
{
|
||||||
|
internal class CategoryDataResponse : AssetStoreResponse
|
||||||
|
{
|
||||||
|
public List<Category> Categories { get; set; }
|
||||||
|
|
||||||
|
public CategoryDataResponse() : base() { }
|
||||||
|
public CategoryDataResponse(Exception e) : base(e) { }
|
||||||
|
|
||||||
|
public CategoryDataResponse(string json)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var categoryArray = JsonConvert.DeserializeObject<JArray>(json);
|
||||||
|
|
||||||
|
Categories = new List<Category>();
|
||||||
|
var serializer = new JsonSerializer()
|
||||||
|
{
|
||||||
|
ContractResolver = new Category.AssetStoreCategoryResolver()
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var categoryData in categoryArray)
|
||||||
|
{
|
||||||
|
var category = categoryData.ToObject<Category>(serializer);
|
||||||
|
Categories.Add(category);
|
||||||
|
}
|
||||||
|
|
||||||
|
Success = true;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Success = false;
|
||||||
|
Exception = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e3789323453f1604286b436f77bdca97
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace AssetStoreTools.Api.Responses
|
||||||
|
{
|
||||||
|
internal class PackageThumbnailResponse : AssetStoreResponse
|
||||||
|
{
|
||||||
|
public Texture2D Thumbnail { get; set; }
|
||||||
|
public PackageThumbnailResponse() : base() { }
|
||||||
|
public PackageThumbnailResponse(Exception e) : base(e) { }
|
||||||
|
|
||||||
|
public PackageThumbnailResponse(byte[] textureBytes)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var tex = new Texture2D(1, 1, TextureFormat.RGBA32, false);
|
||||||
|
var success = tex.LoadImage(textureBytes);
|
||||||
|
if (!success)
|
||||||
|
throw new Exception("Could not retrieve image from the provided texture bytes");
|
||||||
|
|
||||||
|
Thumbnail = tex;
|
||||||
|
Success = true;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Success = false;
|
||||||
|
Exception = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: dacfba636b3757e408514b850d715e18
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace AssetStoreTools.Api.Responses
|
||||||
|
{
|
||||||
|
internal class PackageUploadedUnityVersionDataResponse : AssetStoreResponse
|
||||||
|
{
|
||||||
|
public List<string> UnityVersions { get; set; }
|
||||||
|
|
||||||
|
public PackageUploadedUnityVersionDataResponse() : base() { }
|
||||||
|
public PackageUploadedUnityVersionDataResponse(Exception e) : base(e) { }
|
||||||
|
|
||||||
|
public PackageUploadedUnityVersionDataResponse(string json)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ValidateAssetStoreResponse(json);
|
||||||
|
ParseVersionData(json);
|
||||||
|
Success = true;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Success = false;
|
||||||
|
Exception = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ParseVersionData(string json)
|
||||||
|
{
|
||||||
|
var data = JsonConvert.DeserializeObject<JObject>(json);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var content = data.GetValue("content").ToObject<JObject>();
|
||||||
|
UnityVersions = content.GetValue("unity_versions").ToObject<List<string>>();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
throw new Exception("Could not parse the unity versions array");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 2552f659a600e124aa952f3ba760ddf3
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
using AssetStoreTools.Api.Models;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace AssetStoreTools.Api.Responses
|
||||||
|
{
|
||||||
|
internal class PackagesAdditionalDataResponse : AssetStoreResponse
|
||||||
|
{
|
||||||
|
public List<PackageAdditionalData> Packages { get; set; }
|
||||||
|
|
||||||
|
public PackagesAdditionalDataResponse() : base() { }
|
||||||
|
public PackagesAdditionalDataResponse(Exception e) : base(e) { }
|
||||||
|
|
||||||
|
public PackagesAdditionalDataResponse(string json)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ValidateAssetStoreResponse(json);
|
||||||
|
ParseExtraData(json);
|
||||||
|
Success = true;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Success = false;
|
||||||
|
Exception = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ParseExtraData(string json)
|
||||||
|
{
|
||||||
|
var packageDict = JsonConvert.DeserializeObject<JObject>(json);
|
||||||
|
if (!packageDict.ContainsKey("packages"))
|
||||||
|
throw new Exception("Response did not not contain the list of packages");
|
||||||
|
|
||||||
|
Packages = new List<PackageAdditionalData>();
|
||||||
|
var serializer = new JsonSerializer()
|
||||||
|
{
|
||||||
|
ContractResolver = PackageAdditionalData.AssetStorePackageResolver.Instance
|
||||||
|
};
|
||||||
|
|
||||||
|
var packageArray = packageDict.GetValue("packages").ToObject<JArray>();
|
||||||
|
foreach (var packageData in packageArray)
|
||||||
|
{
|
||||||
|
var package = packageData.ToObject<PackageAdditionalData>(serializer);
|
||||||
|
|
||||||
|
// Some fields are based on the latest version in the json
|
||||||
|
var latestVersion = packageData["versions"].ToObject<JArray>().Last;
|
||||||
|
|
||||||
|
package.VersionId = latestVersion["id"].ToString();
|
||||||
|
package.Modified = latestVersion["modified"].ToString();
|
||||||
|
package.Size = latestVersion["size"].ToString();
|
||||||
|
|
||||||
|
Packages.Add(package);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 88d58ad5e0eea6345b5c83f30ee8ebd5
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue