chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:49:17 +08:00
commit 7243d5823b
2201 changed files with 257291 additions and 0 deletions
+106
View File
@@ -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
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8105016687592461f977c054a80ce2f2
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 0
userData:
assetBundleName:
assetBundleVariant:
@@ -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 packages 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:
@@ -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 PackagesDataResponse : AssetStoreResponse
{
public List<Package> Packages { get; set; }
public PackagesDataResponse() : base() { }
public PackagesDataResponse(Exception e) : base(e) { }
public PackagesDataResponse(string json)
{
try
{
ValidateAssetStoreResponse(json);
ParseMainData(json);
Success = true;
}
catch (Exception e)
{
Success = false;
Exception = e;
}
}
private void ParseMainData(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<Package>();
var serializer = new JsonSerializer()
{
ContractResolver = Package.AssetStorePackageResolver.Instance
};
foreach (var packageToken in packageDict["packages"])
{
var property = (JProperty)packageToken;
var packageData = property.Value.ToObject<Package>(serializer);
// Package Id is the key of the package object
packageData.PackageId = property.Name;
// Package Icon Url is returned without the https: prefix
if (!string.IsNullOrEmpty(packageData.IconUrl))
packageData.IconUrl = $"https:{packageData.IconUrl}";
Packages.Add(packageData);
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 705ec748e689148479f54666993cd79d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,12 @@
using AssetStoreTools.Api.Models;
using System;
namespace AssetStoreTools.Api.Responses
{
internal class RefreshedPackageDataResponse : AssetStoreResponse
{
public Package Package { get; set; }
public RefreshedPackageDataResponse() { }
public RefreshedPackageDataResponse(Exception e) : base(e) { }
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 20f710024d5ed514db02672f12ac361c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,28 @@
using System;
namespace AssetStoreTools.Api.Responses
{
internal class PackageUploadResponse : AssetStoreResponse
{
public UploadStatus Status { get; set; }
public PackageUploadResponse() : base() { }
public PackageUploadResponse(Exception e) : base(e) { }
public PackageUploadResponse(string json)
{
try
{
ValidateAssetStoreResponse(json);
Status = UploadStatus.Success;
Success = true;
}
catch (Exception e)
{
Success = false;
Status = UploadStatus.Fail;
Exception = e;
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8f1758cfa8119cf49a61b010a04352e4
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 SessionAuthentication : AuthenticationBase
{
public SessionAuthentication(string sessionId)
{
AuthenticationContent = GetAuthenticationContent(
new KeyValuePair<string, string>("reuse_session", sessionId)
);
}
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: 02e970f660088cc4b89003608d59cd06
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,99 @@
using AssetStoreTools.Api.Responses;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
namespace AssetStoreTools.Api
{
internal class UnityPackageUploadSettings
{
public string VersionId { get; set; }
public string UnityPackagePath { get; set; }
public string RootGuid { get; set; }
public string RootPath { get; set; }
public string ProjectPath { get; set; }
}
internal class UnityPackageUploader : PackageUploaderBase
{
private UnityPackageUploadSettings _settings;
private Uri _uploadUri;
public UnityPackageUploader(UnityPackageUploadSettings settings)
{
_settings = settings;
}
protected override void ValidateSettings()
{
if (string.IsNullOrEmpty(_settings.VersionId))
throw new Exception("Version Id is unset");
if (string.IsNullOrEmpty(_settings.UnityPackagePath)
|| !File.Exists(_settings.UnityPackagePath))
throw new Exception("Package file could not be found");
if (!_settings.UnityPackagePath.EndsWith(".unitypackage"))
throw new Exception("Provided package file is not .unitypackage");
}
public override async Task<PackageUploadResponse> Upload(IAssetStoreClient client, IProgress<float> progress = null, CancellationToken cancellationToken = default)
{
try
{
ValidateSettings();
var endpoint = Constants.Api.UploadUnityPackageUrl(_settings.VersionId);
var query = new Dictionary<string, string>()
{
{ "root_guid", _settings.RootGuid },
{ "root_path", _settings.RootPath },
{ "project_path", _settings.ProjectPath }
};
_uploadUri = ApiUtility.CreateUri(endpoint, query, true);
}
catch (Exception e)
{
return new PackageUploadResponse() { Success = false, Status = UploadStatus.Fail, Exception = e };
}
return await Task.Run(() => UploadTask(client, progress, cancellationToken));
}
private PackageUploadResponse UploadTask(IAssetStoreClient client, IProgress<float> progress, CancellationToken cancellationToken)
{
try
{
using (FileStream requestFileStream = new FileStream(_settings.UnityPackagePath, FileMode.Open, FileAccess.Read))
{
var content = new StreamContent(requestFileStream, UploadChunkSizeBytes);
var response = client.Put(_uploadUri, content, cancellationToken);
WaitForUploadCompletion(response, requestFileStream, progress, cancellationToken);
cancellationToken.ThrowIfCancellationRequested();
EnsureSuccessResponse(response.Result);
var responseStr = response.Result.Content.ReadAsStringAsync().Result;
return new PackageUploadResponse(responseStr);
}
}
catch (OperationCanceledException e)
{
return new PackageUploadResponse() { Success = false, Cancelled = true, Status = UploadStatus.Cancelled, Exception = e };
}
catch (TimeoutException e)
{
return new PackageUploadResponse() { Success = true, Status = UploadStatus.ResponseTimeout, Exception = e };
}
catch (Exception e)
{
return new PackageUploadResponse() { Success = false, Exception = e, Status = UploadStatus.Fail };
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 95bd0284375397f41a2065e07d4ba526
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,11 @@
namespace AssetStoreTools.Api
{
internal enum UploadStatus
{
Default = 0,
Success = 1,
Fail = 2,
Cancelled = 3,
ResponseTimeout = 4
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0a121831a941cb64a8a9d21ca6fda9c3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,5 @@
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("AssetStoreTools.Tests")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
[assembly: InternalsVisibleTo("ab-builder")]
[assembly: InternalsVisibleTo("Inspector-Editor")]
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ccfd7faf75ab3c74a98015e772288d86
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,82 @@
using AssetStoreTools.Previews.Data;
using AssetStoreTools.Previews.UI;
using AssetStoreTools.Uploader;
using AssetStoreTools.Utility;
using AssetStoreTools.Validator.Data;
using AssetStoreTools.Validator.UI;
using System;
using UnityEditor;
using UnityEngine;
namespace AssetStoreTools
{
internal static class AssetStoreTools
{
[MenuItem("Tools/Asset Store/Uploader", false, 0)]
public static void ShowAssetStoreToolsUploader()
{
Type inspectorType = Type.GetType("UnityEditor.InspectorWindow,UnityEditor.dll");
var wnd = EditorWindow.GetWindow<UploaderWindow>(inspectorType);
wnd.Show();
}
[MenuItem("Tools/Asset Store/Validator", false, 1)]
public static void ShowAssetStoreToolsValidator()
{
Type inspectorType = Type.GetType("UnityEditor.InspectorWindow,UnityEditor.dll");
var wnd = EditorWindow.GetWindow<ValidatorWindow>(typeof(UploaderWindow), inspectorType);
wnd.Show();
}
public static void ShowAssetStoreToolsValidator(ValidationSettings settings, ValidationResult result)
{
ShowAssetStoreToolsValidator();
EditorWindow.GetWindow<ValidatorWindow>().Load(settings, result);
}
[MenuItem("Tools/Asset Store/Preview Generator", false, 2)]
public static void ShowAssetStoreToolsPreviewGenerator()
{
Type inspectorType = Type.GetType("UnityEditor.InspectorWindow,UnityEditor.dll");
var wnd = EditorWindow.GetWindow<PreviewGeneratorWindow>(inspectorType);
wnd.Show();
}
public static void ShowAssetStoreToolsPreviewGenerator(PreviewGenerationSettings settings)
{
ShowAssetStoreToolsPreviewGenerator();
EditorWindow.GetWindow<PreviewGeneratorWindow>().Load(settings);
}
[MenuItem("Tools/Asset Store/Publisher Portal", false, 20)]
public static void OpenPublisherPortal()
{
Application.OpenURL("https://publisher.unity.com/");
}
[MenuItem("Tools/Asset Store/Submission Guidelines", false, 21)]
public static void OpenSubmissionGuidelines()
{
Application.OpenURL("https://assetstore.unity.com/publishing/submission-guidelines/");
}
[MenuItem("Tools/Asset Store/Provide Feedback", false, 22)]
public static void OpenFeedback()
{
Application.OpenURL("https://forum.unity.com/threads/new-asset-store-tools-version-coming-july-20th-2022.1310939/");
}
[MenuItem("Tools/Asset Store/Check for Updates", false, 45)]
public static void OpenUpdateChecker()
{
var wnd = EditorWindow.GetWindowWithRect<ASToolsUpdater>(new Rect(Screen.width / 2, Screen.height / 2, 400, 150), true);
wnd.Show();
}
[MenuItem("Tools/Asset Store/Settings", false, 50)]
public static void OpenSettings()
{
ASToolsPreferencesProvider.OpenSettings();
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6060eef206afc844caaa1732538e8890
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,23 @@
using UnityEditor;
using UnityEngine;
namespace AssetStoreTools
{
internal abstract class AssetStoreToolsWindow : EditorWindow
{
protected abstract string WindowTitle { get; }
private void DefaultInit()
{
titleContent = new GUIContent(WindowTitle);
Init();
}
protected abstract void Init();
private void OnEnable()
{
DefaultInit();
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c1057a05baaa45942808573065c02a03
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,178 @@
using AssetStoreTools.Previews.Data;
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using PackageInfo = UnityEditor.PackageManager.PackageInfo;
namespace AssetStoreTools
{
internal class Constants
{
#if UNITY_EDITOR_OSX
public static readonly string UnityPath = System.IO.Path.Combine(EditorApplication.applicationPath, "Contents", "MacOS", "Unity");
#else
public static readonly string UnityPath = EditorApplication.applicationPath;
#endif
public static readonly string RootProjectPath = Application.dataPath.Substring(0, Application.dataPath.Length - "Assets".Length);
private static bool GetArgument(string argumentName, out string argumentValue)
{
argumentValue = string.Empty;
var args = Environment.GetCommandLineArgs();
for (int i = 0; i < args.Length; i++)
{
if (!args[i].Equals(argumentName, StringComparison.OrdinalIgnoreCase))
continue;
if (i + 1 >= args.Length)
return false;
argumentValue = args[i + 1];
break;
}
return !string.IsNullOrEmpty(argumentValue);
}
public class Api
{
public static readonly string ApiVersion = $"V{PackageInfo.FindForAssetPath("Packages/com.unity.asset-store-tools").version}";
public const string AssetStoreToolsLatestVersionUrl = "https://api.assetstore.unity3d.com/package/latest-version/115";
private const string AssetStoreBaseUrlDefault = "https://kharma.unity3d.com";
private const string AssetStoreBaseUrlOverrideArgument = "-assetStoreUrl";
public static readonly string AssetStoreBaseUrl = !GetArgument(AssetStoreBaseUrlOverrideArgument, out var overriddenUrl)
? AssetStoreBaseUrlDefault
: overriddenUrl;
public static readonly string AuthenticateUrl = $"{AssetStoreBaseUrl}/login";
public static readonly string GetPackagesUrl = $"{AssetStoreBaseUrl}/api/asset-store-tools/metadata/0.json";
public static readonly string GetPackagesAdditionalDataUrl = $"{AssetStoreBaseUrl}/api/management/packages.json";
public static readonly string GetCategoriesUrl = $"{AssetStoreBaseUrl}/api/management/categories.json";
public static string GetPackageUploadedVersionsUrl(string packageId, string versionId) =>
$"{AssetStoreBaseUrl}/api/content/preview/{packageId}/{versionId}.json";
public static string UploadUnityPackageUrl(string versionId) =>
$"{AssetStoreBaseUrl}/api/asset-store-tools/package/{versionId}/unitypackage.json";
public static IDictionary<string, string> DefaultAssetStoreQuery()
{
var dict = new Dictionary<string, string>()
{
{ "unityversion", Application.unityVersion },
{ "toolversion", ApiVersion }
};
return dict;
}
}
public class Updater
{
public const string AssetStoreToolsUrl = "https://assetstore.unity.com/packages/tools/utilities/asset-store-publishing-tools-115";
}
public class Cache
{
public const string SessionTokenKey = "kharma.sessionid";
public const string TempCachePath = "Temp/AssetStoreToolsCache";
public const string PersistentCachePath = "Library/AssetStoreToolsCache";
public const string PackageDataFileName = "PackageMetadata.json";
public const string CategoryDataFile = "Categories.json";
public const string ValidationResultFile = "ValidationStateData.asset";
public static string PackageThumbnailFileName(string packageId) => $"{packageId}.png";
public static string WorkflowStateDataFileName(string packageId) => $"{packageId}-workflowStateData.asset";
}
public class Uploader
{
public const string MinRequiredUnitySupportVersion = "2021.3";
public const long MaxPackageSizeBytes = 6576668672; // 6 GB + 128MB of headroom
public const string AccountRegistrationUrl = "https://publisher.unity.com/access";
public const string AccountForgottenPasswordUrl = "https://id.unity.com/password/new";
public class Analytics
{
public const string VendorKey = "unity.assetStoreTools";
public const int MaxEventsPerHour = 20;
public const int MaxNumberOfElements = 1000;
public class AuthenticationAnalytics
{
public const string EventName = "assetStoreToolsLogin";
public const int EventVersion = 1;
}
public class PackageUploadAnalytics
{
public const string EventName = "assetStoreTools";
public const int EventVersion = 3;
}
}
}
public class Validator
{
public const string SubmissionGuidelinesUrl = "https://assetstore.unity.com/publishing/submission-guidelines#Overview";
public const string SupportTicketUrl = "https://support.unity.com/hc/en-us/requests/new?ticket_form_id=65905";
public class Tests
{
public const string TestDefinitionsPath = "Packages/com.unity.asset-store-tools/Editor/Validator/Tests";
public const string TestMethodsPath = "Packages/com.unity.asset-store-tools/Editor/Validator/Scripts/Test Methods";
public static readonly string GenericTestMethodsPath = $"{TestMethodsPath}/Generic";
public static readonly string UnityPackageTestMethodsPath = $"{TestMethodsPath}/UnityPackage";
}
}
public class Previews
{
public const string PreviewDatabaseFile = "PreviewDatabase.json";
public static readonly string DefaultOutputPath = $"{Cache.TempCachePath}/AssetPreviews";
public const FileNameFormat DefaultFileNameFormat = FileNameFormat.Guid;
public class Native
{
public static readonly string DefaultOutputPath = $"{Previews.DefaultOutputPath}/Native";
public const PreviewFormat DefaultFormat = PreviewFormat.PNG;
public const bool DefaultWaitForPreviews = true;
public const bool DefaultChunkedPreviewLoading = true;
public const int DefaultChunkSize = 100;
}
public class Custom
{
public static readonly string DefaultOutputPath = $"{Previews.DefaultOutputPath}/Custom";
public const PreviewFormat DefaultFormat = PreviewFormat.JPG;
public const int DefaultWidth = 300;
public const int DefaultHeight = 300;
public const int DefaultDepth = 32;
public const int DefaultNativeWidth = 900;
public const int DefaultNativeHeight = 900;
public static readonly Color DefaultAudioSampleColor = new Color(1f, 0.55f, 0);
public static readonly Color DefaultAudioBackgroundColor = new Color(0.32f, 0.32f, 0.32f);
}
}
public class WindowStyles
{
public const string UploaderStylesPath = "Packages/com.unity.asset-store-tools/Editor/Uploader/Styles";
public const string ValidatorStylesPath = "Packages/com.unity.asset-store-tools/Editor/Validator/Styles";
public const string ValidatorIconsPath = "Packages/com.unity.asset-store-tools/Editor/Validator/Icons";
public const string PreviewGeneratorStylesPath = "Packages/com.unity.asset-store-tools/Editor/Previews/Styles";
public const string UpdaterStylesPath = "Packages/com.unity.asset-store-tools/Editor/Utility/Styles/Updater";
}
public class Debug
{
public const string DebugModeKey = "ASTDebugMode";
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a4ee1f78505bda748ae24b3dfd2606ca
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5f5ca981958937a43997a9f365759edf
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2072d354c04b19c48b22593536b3ebcf
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,11 @@
using System.Threading.Tasks;
namespace AssetStoreTools.Exporter
{
internal interface IPackageExporter
{
PackageExporterSettings Settings { get; }
Task<PackageExporterResult> Export();
}
}

Some files were not shown because too many files have changed in this diff Show More