nnnotes 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nnnotes/__init__.py +7 -0
- nnnotes/__main__.py +4 -0
- nnnotes/acb.py +190 -0
- nnnotes/addressables.py +413 -0
- nnnotes/adv.py +243 -0
- nnnotes/advcommand.py +29 -0
- nnnotes/advmedia.py +178 -0
- nnnotes/advscene.py +113 -0
- nnnotes/advui.py +1154 -0
- nnnotes/advvideo.py +684 -0
- nnnotes/atoms/__init__.py +151 -0
- nnnotes/atoms/astc.py +52 -0
- nnnotes/atoms/gltf.py +290 -0
- nnnotes/atoms/mesh.py +289 -0
- nnnotes/atoms/png.py +28 -0
- nnnotes/atoms/reader.py +269 -0
- nnnotes/atoms/sniff.py +198 -0
- nnnotes/atoms/sprite.py +236 -0
- nnnotes/atoms/texture.py +80 -0
- nnnotes/cache.py +289 -0
- nnnotes/catalog.py +373 -0
- nnnotes/catalogdb.py +457 -0
- nnnotes/census.py +276 -0
- nnnotes/cli.py +744 -0
- nnnotes/cli_assets.py +1539 -0
- nnnotes/config.py +238 -0
- nnnotes/contract.py +497 -0
- nnnotes/cri.py +371 -0
- nnnotes/crikey.py +71 -0
- nnnotes/crilips.py +265 -0
- nnnotes/cristages.py +558 -0
- nnnotes/deckdata.py +462 -0
- nnnotes/export.py +1462 -0
- nnnotes/gameapi.py +318 -0
- nnnotes/jsonio.py +98 -0
- nnnotes/languages.py +44 -0
- nnnotes/layout.py +596 -0
- nnnotes/link.py +418 -0
- nnnotes/live.py +115 -0
- nnnotes/live2d.py +235 -0
- nnnotes/liveaudio.py +331 -0
- nnnotes/livenotes.py +291 -0
- nnnotes/liveoptions.py +250 -0
- nnnotes/livescene.py +450 -0
- nnnotes/liveui.py +328 -0
- nnnotes/master.py +251 -0
- nnnotes/modelstages.py +424 -0
- nnnotes/motion.py +131 -0
- nnnotes/objexport.py +1564 -0
- nnnotes/orchestrate.py +630 -0
- nnnotes/plan.py +218 -0
- nnnotes/player.py +392 -0
- nnnotes/room.py +391 -0
- nnnotes/score.py +1139 -0
- nnnotes/shader.py +217 -0
- nnnotes/spot.py +201 -0
- nnnotes/stages.py +285 -0
- nnnotes/store.py +518 -0
- nnnotes/story.py +142 -0
- nnnotes/storyfonts.py +1258 -0
- nnnotes/storyhost.py +1190 -0
- nnnotes/storysite.py +662 -0
- nnnotes/storyvoices.py +102 -0
- nnnotes/textstyle.py +355 -0
- nnnotes/tmpfont.py +636 -0
- nnnotes/typetrees/6000.3.12f1.json +19 -0
- nnnotes/unity.py +368 -0
- nnnotes/viewrules.json +441 -0
- nnnotes/views.py +966 -0
- nnnotes/voices.py +1363 -0
- nnnotes/web.py +1624 -0
- nnnotes/webaudio.py +14 -0
- nnnotes/webmodel.py +397 -0
- nnnotes-0.1.0.dist-info/METADATA +200 -0
- nnnotes-0.1.0.dist-info/RECORD +79 -0
- nnnotes-0.1.0.dist-info/WHEEL +5 -0
- nnnotes-0.1.0.dist-info/entry_points.txt +2 -0
- nnnotes-0.1.0.dist-info/licenses/LICENSE +21 -0
- nnnotes-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{"format":1,"gameVersion":"1.0.1","unityVersion":"6000.3.12f1","classes":{
|
|
2
|
+
"Adv|AdvSystem.Rendering|AdvFieldRendererFeature":{"nodes":[[0,"MonoBehaviour","Base",0],[1,"PPtr<GameObject>","m_GameObject",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"UInt8","m_Enabled",16384],[1,"PPtr<MonoScript>","m_Script",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"string","m_Name",0],[2,"Array","Array",16384],[3,"int","size",0],[3,"char","data",0],[1,"UInt8","m_Active",16384],[1,"PPtr<$Shader>","_alphaBlendShader",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"PPtr<$Shader>","_characterAlphaBlendShader",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"PPtr<$Shader>","_blurShader",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"PPtr<$Shader>","_curvedLensShader",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"int","_maxFieldRendererEntryCount",0],[1,"float","_characterBlurIntensityRate",0],[1,"float","_characterBlurScale",0],[1,"float","_backgroundBlurIntensityRate",0],[1,"float","_backgroundBlurScale",0]],"typeHash":"b366a9b62e0f9de433e9ca044d26c9d1"},
|
|
3
|
+
"App.Runtime|App.Config|AppConfigDefaultData":{"nodes":[[0,"MonoBehaviour","Base",0],[1,"PPtr<GameObject>","m_GameObject",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"UInt8","m_Enabled",16384],[1,"PPtr<MonoScript>","m_Script",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"string","m_Name",0],[2,"Array","Array",16384],[3,"int","size",0],[3,"char","data",0],[1,"AppConfigDataModel","_defaultData",0],[2,"float","<LiveBgmSoundVolume>k__BackingField",0],[2,"float","<LiveSeSoundVolume>k__BackingField",0],[2,"float","<LiveVoiceSoundVolume>k__BackingField",0],[2,"float","<LiveNotesSeSoundVolume>k__BackingField",0],[2,"float","<BluetoothLiveBgmSoundVolume>k__BackingField",0],[2,"float","<BluetoothLiveSeSoundVolume>k__BackingField",0],[2,"float","<BluetoothLiveVoiceSoundVolume>k__BackingField",0],[2,"float","<BluetoothLiveNotesSeSoundVolume>k__BackingField",0]],"typeHash":"2b53ff748caf6baa04ce8616a3f29be9"},
|
|
4
|
+
"DOTween.dll|DG.Tweening.Core|DOTweenSettings":{"nodes":[[0,"MonoBehaviour","Base",0],[1,"PPtr<GameObject>","m_GameObject",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"UInt8","m_Enabled",16384],[1,"PPtr<MonoScript>","m_Script",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"string","m_Name",0],[2,"Array","Array",16384],[3,"int","size",0],[3,"char","data",0],[1,"UInt8","useSafeMode",16384],[1,"SafeModeOptions","safeModeOptions",0],[2,"int","logBehaviour",0],[2,"int","nestedTweenFailureBehaviour",0],[1,"float","timeScale",0],[1,"float","unscaledTimeScale",0],[1,"UInt8","useSmoothDeltaTime",16384],[1,"float","maxSmoothUnscaledTime",0],[1,"int","rewindCallbackMode",0],[1,"UInt8","showUnityEditorReport",16384],[1,"int","logBehaviour",0],[1,"UInt8","drawGizmos",16384],[1,"UInt8","defaultRecyclable",16384],[1,"int","defaultAutoPlay",0],[1,"int","defaultUpdateType",0],[1,"UInt8","defaultTimeScaleIndependent",16384],[1,"int","defaultEaseType",0],[1,"float","defaultEaseOvershootOrAmplitude",0],[1,"float","defaultEasePeriod",0],[1,"UInt8","defaultAutoKill",16384],[1,"int","defaultLoopType",0],[1,"UInt8","debugMode",16384],[1,"UInt8","debugStoreTargetId",16384],[1,"UInt8","showPreviewPanel",16384],[1,"int","storeSettingsLocation",0],[1,"ModulesSetup","modules",0],[2,"UInt8","showPanel",16384],[2,"UInt8","audioEnabled",16384],[2,"UInt8","physicsEnabled",16384],[2,"UInt8","physics2DEnabled",16384],[2,"UInt8","spriteEnabled",16384],[2,"UInt8","uiEnabled",16384],[2,"UInt8","textMeshProEnabled",16384],[2,"UInt8","tk2DEnabled",16384],[2,"UInt8","deAudioEnabled",16384],[2,"UInt8","deUnityExtendedEnabled",16384],[2,"UInt8","epoOutlineEnabled",16384],[1,"UInt8","createASMDEF",16384],[1,"UInt8","showPlayingTweens",16384],[1,"UInt8","showPausedTweens",16384]],"typeHash":"4f1dec93fa2a0b0e7b8b47518da31b1c"},
|
|
5
|
+
"Fwk|Fwk.Rendering|ScreenCaptureRendererFeature":{"nodes":[[0,"MonoBehaviour","Base",0],[1,"PPtr<GameObject>","m_GameObject",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"UInt8","m_Enabled",16384],[1,"PPtr<MonoScript>","m_Script",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"string","m_Name",0],[2,"Array","Array",16384],[3,"int","size",0],[3,"char","data",0],[1,"UInt8","m_Active",16384]],"typeHash":"ce87445dd61732c847969290a1daa3b1"},
|
|
6
|
+
"Fwk|Fwk.Sound|SoundVolumeSettings":{"nodes":[[0,"MonoBehaviour","Base",0],[1,"PPtr<GameObject>","m_GameObject",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"UInt8","m_Enabled",16384],[1,"PPtr<MonoScript>","m_Script",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"string","m_Name",0],[2,"Array","Array",16384],[3,"int","size",0],[3,"char","data",0],[1,"SoundVolumeData","_collection",0],[2,"Array","Array",0],[3,"int","size",0],[3,"SoundVolumeData","data",0],[4,"string","CategoryName",0],[5,"Array","Array",16384],[6,"int","size",0],[6,"char","data",0],[4,"float","DefaultVolume",0]],"typeHash":"6fb3a84e8c1ec611fde964d8d6005276"},
|
|
7
|
+
"Fwk|Fwk.UI.Rendering|UIRendererFeature":{"nodes":[[0,"MonoBehaviour","Base",0],[1,"PPtr<GameObject>","m_GameObject",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"UInt8","m_Enabled",16384],[1,"PPtr<MonoScript>","m_Script",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"string","m_Name",0],[2,"Array","Array",16384],[3,"int","size",0],[3,"char","data",0],[1,"UInt8","m_Active",16384],[1,"BitField","_layerMask",0],[2,"unsigned int","m_Bits",0],[1,"int","_blurIterations",0],[1,"float","_blurOffset",0],[1,"int","_blurDownsample",0],[1,"float","_blurBlendRateMax",0],[1,"PPtr<$Shader>","_dualKawaseBlurShader",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0]],"typeHash":"12463b61d2af82f284b2248ea336f5f6"},
|
|
8
|
+
"SiriusAsset|App.GachaAnimation.Blur.DualKawase|DualKawaseBlurFeature":{"nodes":[[0,"MonoBehaviour","Base",0],[1,"PPtr<GameObject>","m_GameObject",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"UInt8","m_Enabled",16384],[1,"PPtr<MonoScript>","m_Script",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"string","m_Name",0],[2,"Array","Array",16384],[3,"int","size",0],[3,"char","data",0],[1,"UInt8","m_Active",16384],[1,"PPtr<$Shader>","_blurShader",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0]],"typeHash":"d3a7f8d74210f879c214433da8371fb1"},
|
|
9
|
+
"SiriusAsset|App.GachaAnimation.ChromaticAberration|ChromaticAberrationFeature":{"nodes":[[0,"MonoBehaviour","Base",0],[1,"PPtr<GameObject>","m_GameObject",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"UInt8","m_Enabled",16384],[1,"PPtr<MonoScript>","m_Script",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"string","m_Name",0],[2,"Array","Array",16384],[3,"int","size",0],[3,"char","data",0],[1,"UInt8","m_Active",16384],[1,"PPtr<$Shader>","_shader",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"int","_injectionPoint",0]],"typeHash":"7cfc6fee683d3cc7ee7724ba19dca473"},
|
|
10
|
+
"SiriusAsset|App.GachaAnimation.Paraffin|ParaffinFeature":{"nodes":[[0,"MonoBehaviour","Base",0],[1,"PPtr<GameObject>","m_GameObject",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"UInt8","m_Enabled",16384],[1,"PPtr<MonoScript>","m_Script",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"string","m_Name",0],[2,"Array","Array",16384],[3,"int","size",0],[3,"char","data",0],[1,"UInt8","m_Active",16384],[1,"PPtr<$Shader>","_shader",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"int","_injectionPoint",0]],"typeHash":"514dcc098efe1dc5fdbb68299a5ee29c"},
|
|
11
|
+
"SiriusAsset|App.GachaAnimation.PostProcessing|CameraBlendFeature":{"nodes":[[0,"MonoBehaviour","Base",0],[1,"PPtr<GameObject>","m_GameObject",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"UInt8","m_Enabled",16384],[1,"PPtr<MonoScript>","m_Script",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"string","m_Name",0],[2,"Array","Array",16384],[3,"int","size",0],[3,"char","data",0],[1,"UInt8","m_Active",16384],[1,"PPtr<$Shader>","_blendShader",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"int","_injectionPoint",0]],"typeHash":"6538c8022bb4b2f5105b707ccd06ae4d"},
|
|
12
|
+
"SiriusAsset|App.GachaAnimation.PostProcessing|RadialBlurFeature":{"nodes":[[0,"MonoBehaviour","Base",0],[1,"PPtr<GameObject>","m_GameObject",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"UInt8","m_Enabled",16384],[1,"PPtr<MonoScript>","m_Script",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"string","m_Name",0],[2,"Array","Array",16384],[3,"int","size",0],[3,"char","data",0],[1,"UInt8","m_Active",16384],[1,"PPtr<$Shader>","_blurShader",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"int","_injectionPoint",0]],"typeHash":"10c8c66cb44cf8c825fee29edfbfcf5c"},
|
|
13
|
+
"SiriusAsset|App.UI.Text.DropShadow|TextDropShadowFeature":{"nodes":[[0,"MonoBehaviour","Base",0],[1,"PPtr<GameObject>","m_GameObject",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"UInt8","m_Enabled",16384],[1,"PPtr<MonoScript>","m_Script",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"string","m_Name",0],[2,"Array","Array",16384],[3,"int","size",0],[3,"char","data",0],[1,"UInt8","m_Active",16384],[1,"PPtr<$Shader>","_silhouetteShader",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"PPtr<$Shader>","_blurShader",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"PPtr<$Shader>","_compositeShader",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0]],"typeHash":"85721efe8a16a08cd5d8f51013555270"},
|
|
14
|
+
"Unity.RenderPipelines.Universal.Runtime|UnityEngine.Rendering.Universal|PostProcessData":{"nodes":[[0,"MonoBehaviour","Base",0],[1,"PPtr<GameObject>","m_GameObject",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"UInt8","m_Enabled",16384],[1,"PPtr<MonoScript>","m_Script",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"string","m_Name",0],[2,"Array","Array",16384],[3,"int","size",0],[3,"char","data",0],[1,"ShaderResources","shaders",0],[2,"PPtr<$Shader>","stopNanPS",0],[3,"int","m_FileID",0],[3,"SInt64","m_PathID",0],[2,"PPtr<$Shader>","subpixelMorphologicalAntialiasingPS",0],[3,"int","m_FileID",0],[3,"SInt64","m_PathID",0],[2,"PPtr<$Shader>","gaussianDepthOfFieldPS",0],[3,"int","m_FileID",0],[3,"SInt64","m_PathID",0],[2,"PPtr<$Shader>","bokehDepthOfFieldPS",0],[3,"int","m_FileID",0],[3,"SInt64","m_PathID",0],[2,"PPtr<$Shader>","cameraMotionBlurPS",0],[3,"int","m_FileID",0],[3,"SInt64","m_PathID",0],[2,"PPtr<$Shader>","paniniProjectionPS",0],[3,"int","m_FileID",0],[3,"SInt64","m_PathID",0],[2,"PPtr<$Shader>","lutBuilderLdrPS",0],[3,"int","m_FileID",0],[3,"SInt64","m_PathID",0],[2,"PPtr<$Shader>","lutBuilderHdrPS",0],[3,"int","m_FileID",0],[3,"SInt64","m_PathID",0],[2,"PPtr<$Shader>","bloomPS",0],[3,"int","m_FileID",0],[3,"SInt64","m_PathID",0],[2,"PPtr<$Shader>","temporalAntialiasingPS",0],[3,"int","m_FileID",0],[3,"SInt64","m_PathID",0],[2,"PPtr<$Shader>","LensFlareDataDrivenPS",0],[3,"int","m_FileID",0],[3,"SInt64","m_PathID",0],[2,"PPtr<$Shader>","LensFlareScreenSpacePS",0],[3,"int","m_FileID",0],[3,"SInt64","m_PathID",0],[2,"PPtr<$Shader>","scalingSetupPS",0],[3,"int","m_FileID",0],[3,"SInt64","m_PathID",0],[2,"PPtr<$Shader>","easuPS",0],[3,"int","m_FileID",0],[3,"SInt64","m_PathID",0],[2,"PPtr<$Shader>","uberPostPS",0],[3,"int","m_FileID",0],[3,"SInt64","m_PathID",0],[2,"PPtr<$Shader>","finalPostPassPS",0],[3,"int","m_FileID",0],[3,"SInt64","m_PathID",0],[2,"int","m_ShaderResourcesVersion",0],[1,"TextureResources","textures",0],[2,"vector","blueNoise16LTex",0],[3,"Array","Array",0],[4,"int","size",0],[4,"PPtr<$Texture2D>","data",0],[5,"int","m_FileID",0],[5,"SInt64","m_PathID",0],[2,"vector","filmGrainTex",0],[3,"Array","Array",0],[4,"int","size",0],[4,"PPtr<$Texture2D>","data",0],[5,"int","m_FileID",0],[5,"SInt64","m_PathID",0],[2,"PPtr<$Texture2D>","smaaAreaTex",0],[3,"int","m_FileID",0],[3,"SInt64","m_PathID",0],[2,"PPtr<$Texture2D>","smaaSearchTex",0],[3,"int","m_FileID",0],[3,"SInt64","m_PathID",0],[2,"int","m_TexturesResourcesVersion",0]],"typeHash":"3fd3a74e10cdfd45658891dfffc27a90"},
|
|
15
|
+
"Unity.RenderPipelines.Universal.Runtime|UnityEngine.Rendering.Universal|UniversalRenderPipelineAsset":{"nodes":[[0,"MonoBehaviour","Base",0],[1,"PPtr<GameObject>","m_GameObject",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"UInt8","m_Enabled",16384],[1,"PPtr<MonoScript>","m_Script",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"string","m_Name",0],[2,"Array","Array",16384],[3,"int","size",0],[3,"char","data",0],[1,"int","k_AssetVersion",0],[1,"int","k_AssetPreviousVersion",0],[1,"int","m_RendererType",0],[1,"PPtr<$ScriptableRendererData>","m_RendererData",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"vector","m_RendererDataList",0],[2,"Array","Array",0],[3,"int","size",0],[3,"PPtr<$ScriptableRendererData>","data",0],[4,"int","m_FileID",0],[4,"SInt64","m_PathID",0],[1,"int","m_DefaultRendererIndex",0],[1,"UInt8","m_RequireDepthTexture",16384],[1,"UInt8","m_RequireOpaqueTexture",16384],[1,"int","m_OpaqueDownsampling",0],[1,"UInt8","m_SupportsTerrainHoles",16384],[1,"UInt8","m_SupportsHDR",16384],[1,"int","m_HDRColorBufferPrecision",0],[1,"int","m_MSAA",0],[1,"float","m_RenderScale",0],[1,"int","m_UpscalingFilter",0],[1,"UInt8","m_FsrOverrideSharpness",16384],[1,"float","m_FsrSharpness",0],[1,"UInt8","m_EnableLODCrossFade",16384],[1,"int","m_LODCrossFadeDitheringType",0],[1,"int","m_ShEvalMode",0],[1,"int","m_LightProbeSystem",0],[1,"int","m_ProbeVolumeMemoryBudget",0],[1,"int","m_ProbeVolumeBlendingMemoryBudget",0],[1,"UInt8","m_SupportProbeVolumeGPUStreaming",16384],[1,"UInt8","m_SupportProbeVolumeDiskStreaming",16384],[1,"UInt8","m_SupportProbeVolumeScenarios",16384],[1,"UInt8","m_SupportProbeVolumeScenarioBlending",16384],[1,"int","m_ProbeVolumeSHBands",0],[1,"int","m_MainLightRenderingMode",0],[1,"UInt8","m_MainLightShadowsSupported",16384],[1,"int","m_MainLightShadowmapResolution",0],[1,"int","m_AdditionalLightsRenderingMode",0],[1,"int","m_AdditionalLightsPerObjectLimit",0],[1,"UInt8","m_AdditionalLightShadowsSupported",16384],[1,"int","m_AdditionalLightsShadowmapResolution",0],[1,"int","m_AdditionalLightsShadowResolutionTierLow",0],[1,"int","m_AdditionalLightsShadowResolutionTierMedium",0],[1,"int","m_AdditionalLightsShadowResolutionTierHigh",0],[1,"UInt8","m_ReflectionProbeBlending",16384],[1,"UInt8","m_ReflectionProbeBoxProjection",16384],[1,"UInt8","m_ReflectionProbeAtlas",16384],[1,"float","m_ShadowDistance",0],[1,"int","m_ShadowCascadeCount",0],[1,"float","m_Cascade2Split",0],[1,"Vector2f","m_Cascade3Split",0],[2,"float","x",0],[2,"float","y",0],[1,"Vector3f","m_Cascade4Split",0],[2,"float","x",0],[2,"float","y",0],[2,"float","z",0],[1,"float","m_CascadeBorder",0],[1,"float","m_ShadowDepthBias",0],[1,"float","m_ShadowNormalBias",0],[1,"UInt8","m_SoftShadowsSupported",16384],[1,"UInt8","m_ConservativeEnclosingSphere",16384],[1,"int","m_NumIterationsEnclosingSphere",0],[1,"int","m_SoftShadowQuality",0],[1,"int","m_AdditionalLightsCookieResolution",0],[1,"int","m_AdditionalLightsCookieFormat",0],[1,"UInt8","m_UseSRPBatcher",16384],[1,"UInt8","m_SupportsDynamicBatching",16384],[1,"UInt8","m_MixedLightingSupported",16384],[1,"UInt8","m_SupportsLightCookies",16384],[1,"UInt8","m_SupportsLightLayers",16384],[1,"int","m_DebugLevel",0],[1,"int","m_StoreActionsOptimization",0],[1,"UInt8","m_UseAdaptivePerformance",16384],[1,"int","m_ColorGradingMode",0],[1,"int","m_ColorGradingLutSize",0],[1,"UInt8","m_AllowPostProcessAlphaOutput",16384],[1,"UInt8","m_UseFastSRGBLinearConversion",16384],[1,"UInt8","m_SupportDataDrivenLensFlare",16384],[1,"UInt8","m_SupportScreenSpaceLensFlare",16384],[1,"UInt8","m_GPUResidentDrawerMode",16384],[1,"float","m_SmallMeshScreenPercentage",0],[1,"UInt8","m_GPUResidentDrawerEnableOcclusionCullingInCameras",16384],[1,"int","m_ShadowType",0],[1,"UInt8","m_LocalShadowsSupported",16384],[1,"int","m_LocalShadowsAtlasResolution",0],[1,"int","m_MaxPixelLights",0],[1,"int","m_ShadowAtlasResolution",0],[1,"int","m_VolumeFrameworkUpdateMode",0],[1,"PPtr<$VolumeProfile>","m_VolumeProfile",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"ProbeVolumeSceneData","apvScenesData",0],[2,"SerializedDictionary`2","obsoleteSceneBounds",0],[3,"vector","m_Keys",0],[4,"Array","Array",16384],[5,"int","size",0],[5,"string","data",0],[6,"Array","Array",16384],[7,"int","size",0],[7,"char","data",0],[3,"vector","m_Values",0],[4,"Array","Array",16384],[5,"int","size",0],[5,"AABB","data",0],[6,"Vector3f","m_Center",0],[7,"float","x",0],[7,"float","y",0],[7,"float","z",0],[6,"Vector3f","m_Extent",0],[7,"float","x",0],[7,"float","y",0],[7,"float","z",0],[2,"SerializedDictionary`2","obsoleteHasProbeVolumes",0],[3,"vector","m_Keys",0],[4,"Array","Array",16384],[5,"int","size",0],[5,"string","data",0],[6,"Array","Array",16384],[7,"int","size",0],[7,"char","data",0],[3,"vector","m_Values",16384],[4,"Array","Array",16384],[5,"int","size",0],[5,"UInt8","data",0],[1,"int","m_ShaderVariantLogLevel",0],[1,"int","m_ShadowCascades",0],[1,"TextureResources","m_Textures",0],[2,"PPtr<$Texture2D>","blueNoise64LTex",0],[3,"int","m_FileID",0],[3,"SInt64","m_PathID",0],[2,"PPtr<$Texture2D>","bayerMatrixTex",0],[3,"int","m_FileID",0],[3,"SInt64","m_PathID",0]],"typeHash":"ea78afb1b30663b7c04c956e9f2acdec"},
|
|
16
|
+
"Unity.RenderPipelines.Universal.Runtime|UnityEngine.Rendering.Universal|UniversalRendererData":{"nodes":[[0,"MonoBehaviour","Base",0],[1,"PPtr<GameObject>","m_GameObject",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"UInt8","m_Enabled",16384],[1,"PPtr<MonoScript>","m_Script",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"string","m_Name",0],[2,"Array","Array",16384],[3,"int","size",0],[3,"char","data",0],[1,"DebugShaderResources","debugShaders",0],[2,"PPtr<$Shader>","debugReplacementPS",0],[3,"int","m_FileID",0],[3,"SInt64","m_PathID",0],[2,"PPtr<$Shader>","hdrDebugViewPS",0],[3,"int","m_FileID",0],[3,"SInt64","m_PathID",0],[1,"ProbeVolumeResources","probeVolumeResources",0],[2,"PPtr<$Shader>","probeVolumeDebugShader",0],[3,"int","m_FileID",0],[3,"SInt64","m_PathID",0],[2,"PPtr<$Shader>","probeVolumeFragmentationDebugShader",0],[3,"int","m_FileID",0],[3,"SInt64","m_PathID",0],[2,"PPtr<$Shader>","probeVolumeOffsetDebugShader",0],[3,"int","m_FileID",0],[3,"SInt64","m_PathID",0],[2,"PPtr<$Shader>","probeVolumeSamplingDebugShader",0],[3,"int","m_FileID",0],[3,"SInt64","m_PathID",0],[2,"PPtr<$Mesh>","probeSamplingDebugMesh",0],[3,"int","m_FileID",0],[3,"SInt64","m_PathID",0],[2,"PPtr<$Texture2D>","probeSamplingDebugTexture",0],[3,"int","m_FileID",0],[3,"SInt64","m_PathID",0],[2,"PPtr<$ComputeShader>","probeVolumeBlendStatesCS",0],[3,"int","m_FileID",0],[3,"SInt64","m_PathID",0],[1,"vector","m_RendererFeatures",0],[2,"Array","Array",0],[3,"int","size",0],[3,"PPtr<$ScriptableRendererFeature>","data",0],[4,"int","m_FileID",0],[4,"SInt64","m_PathID",0],[1,"vector","m_RendererFeatureMap",0],[2,"Array","Array",16384],[3,"int","size",0],[3,"SInt64","data",0],[1,"UInt8","m_UseNativeRenderPass",16384],[1,"PPtr<$XRSystemData>","xrSystemData",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"PPtr<$PostProcessData>","postProcessData",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"int","m_AssetVersion",0],[1,"BitField","m_PrepassLayerMask",0],[2,"unsigned int","m_Bits",0],[1,"BitField","m_OpaqueLayerMask",0],[2,"unsigned int","m_Bits",0],[1,"BitField","m_TransparentLayerMask",0],[2,"unsigned int","m_Bits",0],[1,"StencilStateData","m_DefaultStencilState",0],[2,"UInt8","overrideStencilState",16384],[2,"int","stencilReference",0],[2,"int","stencilCompareFunction",0],[2,"int","passOperation",0],[2,"int","failOperation",0],[2,"int","zFailOperation",0],[1,"UInt8","m_ShadowTransparentReceive",16384],[1,"int","m_RenderingMode",0],[1,"int","m_DepthPrimingMode",0],[1,"int","m_CopyDepthMode",0],[1,"int","m_DepthAttachmentFormat",0],[1,"int","m_DepthTextureFormat",0],[1,"UInt8","m_AccurateGbufferNormals",16384],[1,"int","m_IntermediateTextureMode",0]],"typeHash":"c5a78730dc24e0c4472a14856758a6b5"},
|
|
17
|
+
"Unity.TextMeshPro|TMPro|TMP_Settings":{"nodes":[[0,"MonoBehaviour","Base",0],[1,"PPtr<GameObject>","m_GameObject",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"UInt8","m_Enabled",16384],[1,"PPtr<MonoScript>","m_Script",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"string","m_Name",0],[2,"Array","Array",16384],[3,"int","size",0],[3,"char","data",0],[1,"string","assetVersion",0],[2,"Array","Array",16384],[3,"int","size",0],[3,"char","data",0],[1,"int","m_TextWrappingMode",0],[1,"UInt8","m_enableKerning",16384],[1,"vector","m_ActiveFontFeatures",0],[2,"Array","Array",16384],[3,"int","size",0],[3,"unsigned int","data",0],[1,"UInt8","m_enableExtraPadding",16384],[1,"UInt8","m_enableTintAllSprites",16384],[1,"UInt8","m_enableParseEscapeCharacters",16384],[1,"UInt8","m_EnableRaycastTarget",16384],[1,"UInt8","m_GetFontFeaturesAtRuntime",16384],[1,"int","m_missingGlyphCharacter",0],[1,"UInt8","m_ClearDynamicDataOnBuild",16384],[1,"UInt8","m_warningsDisabled",16384],[1,"PPtr<$TMP_FontAsset>","m_defaultFontAsset",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"string","m_defaultFontAssetPath",0],[2,"Array","Array",16384],[3,"int","size",0],[3,"char","data",0],[1,"float","m_defaultFontSize",0],[1,"float","m_defaultAutoSizeMinRatio",0],[1,"float","m_defaultAutoSizeMaxRatio",0],[1,"Vector2f","m_defaultTextMeshProTextContainerSize",0],[2,"float","x",0],[2,"float","y",0],[1,"Vector2f","m_defaultTextMeshProUITextContainerSize",0],[2,"float","x",0],[2,"float","y",0],[1,"UInt8","m_autoSizeTextContainer",16384],[1,"UInt8","m_IsTextObjectScaleStatic",16384],[1,"vector","m_fallbackFontAssets",0],[2,"Array","Array",0],[3,"int","size",0],[3,"PPtr<$TMP_FontAsset>","data",0],[4,"int","m_FileID",0],[4,"SInt64","m_PathID",0],[1,"UInt8","m_matchMaterialPreset",16384],[1,"UInt8","m_HideSubTextObjects",16384],[1,"PPtr<$TMP_SpriteAsset>","m_defaultSpriteAsset",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"string","m_defaultSpriteAssetPath",0],[2,"Array","Array",16384],[3,"int","size",0],[3,"char","data",0],[1,"UInt8","m_enableEmojiSupport",16384],[1,"unsigned int","m_MissingCharacterSpriteUnicode",0],[1,"vector","m_EmojiFallbackTextAssets",0],[2,"Array","Array",0],[3,"int","size",0],[3,"PPtr<$TMP_Asset>","data",0],[4,"int","m_FileID",0],[4,"SInt64","m_PathID",0],[1,"string","m_defaultColorGradientPresetsPath",0],[2,"Array","Array",16384],[3,"int","size",0],[3,"char","data",0],[1,"PPtr<$TMP_StyleSheet>","m_defaultStyleSheet",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"string","m_StyleSheetsResourcePath",0],[2,"Array","Array",16384],[3,"int","size",0],[3,"char","data",0],[1,"PPtr<$TextAsset>","m_leadingCharacters",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"PPtr<$TextAsset>","m_followingCharacters",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"UInt8","m_UseModernHangulLineBreakingRules",16384]],"typeHash":"bfa9d6dfbc3c74a843a3b197bdcc6639"},
|
|
18
|
+
"Unity.TextMeshPro|TMPro|TMP_StyleSheet":{"nodes":[[0,"MonoBehaviour","Base",0],[1,"PPtr<GameObject>","m_GameObject",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"UInt8","m_Enabled",16384],[1,"PPtr<MonoScript>","m_Script",0],[2,"int","m_FileID",0],[2,"SInt64","m_PathID",0],[1,"string","m_Name",0],[2,"Array","Array",16384],[3,"int","size",0],[3,"char","data",0],[1,"TMP_Style","m_StyleList",0],[2,"Array","Array",0],[3,"int","size",0],[3,"TMP_Style","data",0],[4,"string","m_Name",0],[5,"Array","Array",16384],[6,"int","size",0],[6,"char","data",0],[4,"int","m_HashCode",0],[4,"string","m_OpeningDefinition",0],[5,"Array","Array",16384],[6,"int","size",0],[6,"char","data",0],[4,"string","m_ClosingDefinition",0],[5,"Array","Array",16384],[6,"int","size",0],[6,"char","data",0],[4,"vector","m_OpeningTagArray",0],[5,"Array","Array",16384],[6,"int","size",0],[6,"unsigned int","data",0],[4,"vector","m_ClosingTagArray",0],[5,"Array","Array",16384],[6,"int","size",0],[6,"unsigned int","data",0]],"typeHash":"8d5318ed8488b1fe17c08044ce1b8309"}
|
|
19
|
+
}}
|
nnnotes/unity.py
ADDED
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
"""UnityPy helpers for the game's bundles: typetree reads, TextAssets, shard JSON, meshes, the
|
|
2
|
+
GameObject/Transform scene graph and PPtr references."""
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import hashlib
|
|
6
|
+
import io
|
|
7
|
+
import json
|
|
8
|
+
import threading
|
|
9
|
+
from collections import OrderedDict
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
import numpy as np
|
|
13
|
+
import UnityPy
|
|
14
|
+
from UnityPy.classes import PPtr
|
|
15
|
+
from UnityPy.enums import TextureFormat
|
|
16
|
+
from UnityPy.helpers import MeshHelper
|
|
17
|
+
from UnityPy.helpers.TypeTreeNode import TypeTreeNode
|
|
18
|
+
|
|
19
|
+
from . import cache
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# ---- typetree blobs ---------------------------------------------------------
|
|
23
|
+
# A serialized file lists the typetree of each of its classes as a blob, and UnityPy parses every blob in Python
|
|
24
|
+
# (TypeTreeNode.parse_blob) each time a file is loaded; the same class trees recur in almost every bundle. The parse
|
|
25
|
+
# is memoized per process by the blob itself: the parse arguments, the blob's length and its BLAKE2b-128 digest. A
|
|
26
|
+
# hit returns the tree parsed before, shared: UnityPy and nnnotes only read typetree nodes (nnnotes builds new nodes
|
|
27
|
+
# where it needs a cut tree, see _head_node), and one file's objects already share their class's tree.
|
|
28
|
+
BLOB_MEMO_MAX = 8192 # distinct class trees kept per process (least recent go)
|
|
29
|
+
_blobs: OrderedDict = OrderedDict()
|
|
30
|
+
_blobs_lock = threading.Lock()
|
|
31
|
+
_blob_stats = {"hits": 0, "misses": 0, "installed": False}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def blob_memo_stats() -> dict:
|
|
35
|
+
"""{installed, hits, misses, trees}: the typetree blob memo of this process."""
|
|
36
|
+
with _blobs_lock:
|
|
37
|
+
return {**_blob_stats, "trees": len(_blobs)}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def clear_blob_memo() -> None:
|
|
41
|
+
with _blobs_lock:
|
|
42
|
+
_blobs.clear()
|
|
43
|
+
_blob_stats.update(hits=0, misses=0)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _install_blob_memo() -> bool:
|
|
47
|
+
"""Wrap TypeTreeNode.parse_blob (once) with the memo; False (nothing changed) when this UnityPy has not the
|
|
48
|
+
blob layout the wrapper reads: node count, string buffer size, the node records, the string buffer."""
|
|
49
|
+
from UnityPy.helpers import TypeTreeNode as ttn
|
|
50
|
+
node_struct = getattr(ttn, "_get_blob_node_struct", None)
|
|
51
|
+
original = ttn.TypeTreeNode.__dict__.get("parse_blob")
|
|
52
|
+
if node_struct is None or not isinstance(original, classmethod):
|
|
53
|
+
return False
|
|
54
|
+
if getattr(original.__func__, "_nnnotes_memo", False):
|
|
55
|
+
return True
|
|
56
|
+
parse = original.__func__
|
|
57
|
+
|
|
58
|
+
def parse_blob(cls, reader, version):
|
|
59
|
+
if not cache.enabled():
|
|
60
|
+
return parse(cls, reader, version)
|
|
61
|
+
start = reader.Position
|
|
62
|
+
count, strings = reader.read_int(), reader.read_int()
|
|
63
|
+
body = reader.read(node_struct(reader.endian, version)[0].size * count + strings)
|
|
64
|
+
end = reader.Position
|
|
65
|
+
key = (cls, reader.endian, version, count, strings, len(body), hashlib.blake2b(body, digest_size=16).digest())
|
|
66
|
+
with _blobs_lock:
|
|
67
|
+
node = _blobs.get(key)
|
|
68
|
+
if node is not None:
|
|
69
|
+
_blobs.move_to_end(key)
|
|
70
|
+
_blob_stats["hits"] += 1
|
|
71
|
+
return node
|
|
72
|
+
reader.Position = start
|
|
73
|
+
node = parse(cls, reader, version)
|
|
74
|
+
if reader.Position != end: # another layout: this parse is not memoized
|
|
75
|
+
return node
|
|
76
|
+
with _blobs_lock:
|
|
77
|
+
_blob_stats["misses"] += 1
|
|
78
|
+
_blobs[key] = node
|
|
79
|
+
while len(_blobs) > BLOB_MEMO_MAX:
|
|
80
|
+
_blobs.popitem(last=False)
|
|
81
|
+
return node
|
|
82
|
+
|
|
83
|
+
parse_blob._nnnotes_memo = True
|
|
84
|
+
parse_blob._original = parse
|
|
85
|
+
ttn.TypeTreeNode.parse_blob = classmethod(parse_blob)
|
|
86
|
+
_blob_stats["installed"] = True
|
|
87
|
+
return True
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
_install_blob_memo()
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def load(path: str | Path) -> "UnityPy.environment.Environment":
|
|
94
|
+
return UnityPy.load(str(path))
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def load_bytes(data: bytes) -> "UnityPy.environment.Environment":
|
|
98
|
+
return UnityPy.load(io.BytesIO(data))
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
_closures = threading.local()
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def load_closure(paths) -> "UnityPy.environment.Environment":
|
|
105
|
+
"""UnityPy environment of the bundle files `paths` (a key's closure, in this order), shared by the loads of the
|
|
106
|
+
same files in this thread: the last few closures stay loaded (cache.configure `closures` / `closure_mb`), keyed
|
|
107
|
+
by each file's path, size and modification time. Reading an object gives fresh values every time, so a shared
|
|
108
|
+
environment reads as a new one; per thread because UnityPy's readers are not thread-safe."""
|
|
109
|
+
paths = [str(p) for p in paths]
|
|
110
|
+
limit, budget = cache.settings()["closures"], cache.settings()["closure_bytes"]
|
|
111
|
+
if not cache.enabled() or limit <= 0:
|
|
112
|
+
return UnityPy.load(*paths)
|
|
113
|
+
ids = tuple(cache.file_id(p) for p in paths)
|
|
114
|
+
lru = getattr(_closures, "lru", None)
|
|
115
|
+
if lru is None:
|
|
116
|
+
lru = _closures.lru = OrderedDict()
|
|
117
|
+
hit = lru.get(ids)
|
|
118
|
+
if hit is not None:
|
|
119
|
+
lru.move_to_end(ids)
|
|
120
|
+
return hit[0]
|
|
121
|
+
env = UnityPy.load(*paths)
|
|
122
|
+
size = sum(i[1] for i in ids)
|
|
123
|
+
if size <= budget:
|
|
124
|
+
lru[ids] = (env, size)
|
|
125
|
+
while len(lru) > limit or sum(v[1] for v in lru.values()) > budget:
|
|
126
|
+
lru.popitem(last=False)
|
|
127
|
+
return env
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def clear_closures() -> None:
|
|
131
|
+
"""Drop this thread's loaded closures."""
|
|
132
|
+
lru = getattr(_closures, "lru", None)
|
|
133
|
+
if lru is not None:
|
|
134
|
+
lru.clear()
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def mono_typetrees(env) -> list[dict]:
|
|
138
|
+
"""Every MonoBehaviour in the environment, read via TypeTree."""
|
|
139
|
+
out = []
|
|
140
|
+
for o in env.objects:
|
|
141
|
+
if o.type.name == "MonoBehaviour":
|
|
142
|
+
try:
|
|
143
|
+
out.append(o.read_typetree())
|
|
144
|
+
except Exception:
|
|
145
|
+
continue
|
|
146
|
+
return out
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def first_mono(env, must_have: str | None = None) -> dict | None:
|
|
150
|
+
for tt in mono_typetrees(env):
|
|
151
|
+
if must_have is None or must_have in tt:
|
|
152
|
+
return tt
|
|
153
|
+
return None
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def textassets(env) -> dict[str, str]:
|
|
157
|
+
out = {}
|
|
158
|
+
for o in env.objects:
|
|
159
|
+
if o.type.name == "TextAsset":
|
|
160
|
+
d = o.read()
|
|
161
|
+
s = d.m_Script
|
|
162
|
+
out[d.m_Name] = s if isinstance(s, str) else bytes(s).decode("utf-8", "replace")
|
|
163
|
+
return out
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def parse_shard(text: str) -> dict:
|
|
167
|
+
"""A `-Text/-Sound/...` shard: {_header:[{_name,_type}], _allData:[rows]}.
|
|
168
|
+
|
|
169
|
+
Returns {"header": [...], "rows": [...]}. Row keys keep their leading
|
|
170
|
+
underscore + lowercased-first-letter form as serialized (e.g. `_cueName`).
|
|
171
|
+
"""
|
|
172
|
+
d = json.loads(text)
|
|
173
|
+
return {"header": d.get("_header", []), "rows": d.get("_allData", [])}
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def shard_index(rows: list[dict], id_key: str = "_id") -> dict:
|
|
177
|
+
return {r[id_key]: r for r in rows if id_key in r}
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
# ---- meshes -------------------------------------------------------------
|
|
181
|
+
def _channel(values, count: int, keep: int, what: str) -> np.ndarray:
|
|
182
|
+
"""A vertex channel as a (count, keep) float64 array: each vertex's first `keep` components, whatever the
|
|
183
|
+
channel's own dimension (UnityPy gives a flat list or one tuple per vertex; e.g. normals stored with 4
|
|
184
|
+
components give xyz, the w is dropped)."""
|
|
185
|
+
a = np.asarray(values, np.float64)
|
|
186
|
+
if a.ndim == 1:
|
|
187
|
+
if not count or a.size % count:
|
|
188
|
+
raise ValueError(f"mesh {what}: {a.size} values for {count} vertices")
|
|
189
|
+
a = a.reshape(count, a.size // count)
|
|
190
|
+
if a.ndim != 2 or a.shape[0] != count or a.shape[1] < keep:
|
|
191
|
+
raise ValueError(f"mesh {what}: shape {a.shape} for {count} vertices of {keep} components")
|
|
192
|
+
return a if a.shape[1] == keep else np.ascontiguousarray(a[:, :keep])
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def mesh_arrays(mesh):
|
|
196
|
+
"""(positions, normals, uv0, [triangles per submesh]) straight from the vertex/index buffers: positions and
|
|
197
|
+
normals xyz, uv0 uv (a channel stored with more components gives these first ones), no normals as an empty
|
|
198
|
+
array, no uv0 as zeros, a mesh without an index buffer as no triangles (an empty array per submesh)."""
|
|
199
|
+
h = MeshHelper.MeshHandler(mesh)
|
|
200
|
+
h.process()
|
|
201
|
+
if not h.m_VertexCount:
|
|
202
|
+
return None
|
|
203
|
+
count = h.m_VertexCount
|
|
204
|
+
v = _channel(h.m_Vertices, count, 3, "positions")
|
|
205
|
+
n = _channel(h.m_Normals, count, 3, "normals") if h.m_Normals else np.empty((0, 3))
|
|
206
|
+
uv = _channel(h.m_UV0, count, 2, "uv0") if h.m_UV0 else np.zeros((len(v), 2))
|
|
207
|
+
if h.m_IndexBuffer is None or len(h.m_IndexBuffer) == 0:
|
|
208
|
+
tris = [np.empty((0, 3), np.int64) for _ in (getattr(mesh, "m_SubMeshes", None) or [])]
|
|
209
|
+
else:
|
|
210
|
+
tris = [np.asarray(t, np.int64).reshape(-1, 3) for t in h.get_triangles()]
|
|
211
|
+
return v, n, uv, tris
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
class UnsupportedTexture(RuntimeError):
|
|
215
|
+
"""A texture whose format the decoder cannot decode correctly."""
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
HDR_ASTC = frozenset(range(66, 72)) # TextureFormat ASTC_HDR_4x4 .. ASTC_HDR_12x12
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def check_texture(tex) -> None:
|
|
222
|
+
"""UnsupportedTexture, naming the texture, when UnityPy cannot decode its format correctly: HDR ASTC, whose
|
|
223
|
+
blocks its decoder turns into the error colour (so no wrong pixels are written)."""
|
|
224
|
+
fmt = int(tex.m_TextureFormat)
|
|
225
|
+
if fmt in HDR_ASTC:
|
|
226
|
+
name = TextureFormat(fmt).name
|
|
227
|
+
raise UnsupportedTexture(f"texture {tex.m_Name!r}: {name} (HDR ASTC) is not decoded: UnityPy's decoder "
|
|
228
|
+
f"returns its error colour for these blocks")
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def texture_image(tex):
|
|
232
|
+
"""The decoded image of a Texture2D (UnityPy's `tex.image`), after check_texture."""
|
|
233
|
+
check_texture(tex)
|
|
234
|
+
return tex.image
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
# ---- scene graph ----------------------------------------------------------
|
|
238
|
+
def quat_matrix(q: dict) -> np.ndarray:
|
|
239
|
+
x, y, z, w = q["x"], q["y"], q["z"], q["w"]
|
|
240
|
+
return np.array([
|
|
241
|
+
[1 - 2 * (y * y + z * z), 2 * (x * y - z * w), 2 * (x * z + y * w), 0],
|
|
242
|
+
[2 * (x * y + z * w), 1 - 2 * (x * x + z * z), 2 * (y * z - x * w), 0],
|
|
243
|
+
[2 * (x * z - y * w), 2 * (y * z + x * w), 1 - 2 * (x * x + y * y), 0],
|
|
244
|
+
[0, 0, 0, 1],
|
|
245
|
+
], dtype=np.float64)
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def trs(pos: dict, rot: dict, scale: dict) -> np.ndarray:
|
|
249
|
+
t = np.eye(4)
|
|
250
|
+
t[:3, 3] = [pos["x"], pos["y"], pos["z"]]
|
|
251
|
+
return t @ quat_matrix(rot) @ np.diag([scale["x"], scale["y"], scale["z"], 1.0])
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
class SceneGraph:
|
|
255
|
+
"""GameObject/Transform hierarchy of an environment, with world matrices."""
|
|
256
|
+
|
|
257
|
+
def __init__(self, env):
|
|
258
|
+
self.go = {} # GameObject path_id -> typetree
|
|
259
|
+
self.tf = {} # Transform path_id -> typetree
|
|
260
|
+
for o in env.objects:
|
|
261
|
+
if o.type.name == "GameObject":
|
|
262
|
+
table = self.go
|
|
263
|
+
elif o.type.name in ("Transform", "RectTransform"):
|
|
264
|
+
table = self.tf
|
|
265
|
+
else:
|
|
266
|
+
continue
|
|
267
|
+
if o.path_id in table:
|
|
268
|
+
raise RuntimeError(f"{o.type.name} path_id {o.path_id} appears in two files")
|
|
269
|
+
table[o.path_id] = o.read_typetree()
|
|
270
|
+
self.tf_of_go = {t["m_GameObject"]["m_PathID"]: p for p, t in self.tf.items()}
|
|
271
|
+
self._world: dict[int, np.ndarray] = {}
|
|
272
|
+
self._paths: dict[int, str] = {}
|
|
273
|
+
self._gos_by_path: dict[str, list[int]] | None = None
|
|
274
|
+
|
|
275
|
+
def world(self, tf_pid: int) -> np.ndarray:
|
|
276
|
+
if tf_pid not in self._world:
|
|
277
|
+
t = self.tf[tf_pid]
|
|
278
|
+
m = trs(t["m_LocalPosition"], t["m_LocalRotation"], t["m_LocalScale"])
|
|
279
|
+
f = t["m_Father"]["m_PathID"]
|
|
280
|
+
self._world[tf_pid] = (self.world(f) @ m) if f in self.tf else m
|
|
281
|
+
return self._world[tf_pid]
|
|
282
|
+
|
|
283
|
+
def world_of_go(self, go_pid: int) -> np.ndarray:
|
|
284
|
+
return self.world(self.tf_of_go[go_pid])
|
|
285
|
+
|
|
286
|
+
def active(self, tf_pid: int) -> bool:
|
|
287
|
+
while tf_pid in self.tf:
|
|
288
|
+
if not self.go.get(self.tf[tf_pid]["m_GameObject"]["m_PathID"], {}).get("m_IsActive", 1):
|
|
289
|
+
return False
|
|
290
|
+
tf_pid = self.tf[tf_pid]["m_Father"]["m_PathID"]
|
|
291
|
+
return True
|
|
292
|
+
|
|
293
|
+
def path(self, tf_pid: int) -> str:
|
|
294
|
+
p = self._paths.get(tf_pid)
|
|
295
|
+
if p is None:
|
|
296
|
+
parts, t = [], tf_pid
|
|
297
|
+
while t in self.tf:
|
|
298
|
+
parts.append(self.go.get(self.tf[t]["m_GameObject"]["m_PathID"], {}).get("m_Name", "?"))
|
|
299
|
+
t = self.tf[t]["m_Father"]["m_PathID"]
|
|
300
|
+
p = self._paths[tf_pid] = "/".join(reversed(parts))
|
|
301
|
+
return p
|
|
302
|
+
|
|
303
|
+
def gos_at_path(self, path: str) -> list[int]:
|
|
304
|
+
"""GameObjects whose transform path is `path`, in tf_of_go order."""
|
|
305
|
+
if self._gos_by_path is None:
|
|
306
|
+
index: dict[str, list[int]] = {}
|
|
307
|
+
for go_pid, tf in self.tf_of_go.items():
|
|
308
|
+
index.setdefault(self.path(tf), []).append(go_pid)
|
|
309
|
+
self._gos_by_path = index
|
|
310
|
+
return self._gos_by_path.get(path, [])
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
_heads: dict[int, tuple] = {}
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
def _head_node(node: TypeTreeNode) -> TypeTreeNode | None:
|
|
317
|
+
"""The object typetree `node` cut after m_Script (the MonoBehaviour header), or None without an m_Script."""
|
|
318
|
+
hit = _heads.get(id(node))
|
|
319
|
+
if hit is not None and hit[0] is node:
|
|
320
|
+
return hit[1]
|
|
321
|
+
names = [c.m_Name for c in node.m_Children]
|
|
322
|
+
head = None
|
|
323
|
+
if "m_Script" in names:
|
|
324
|
+
head = TypeTreeNode(node.m_Level, node.m_Type, node.m_Name, node.m_ByteSize, node.m_Version,
|
|
325
|
+
m_MetaFlag=node.m_MetaFlag, m_Children=node.m_Children[:names.index("m_Script") + 1])
|
|
326
|
+
_heads[id(node)] = (node, head) # the node is kept alive, so its id is not reused
|
|
327
|
+
return head
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
def script_class(obj) -> str:
|
|
331
|
+
"""Class name of a MonoBehaviour (needs the monoscript bundle loaded). Reads the header up to m_Script with the
|
|
332
|
+
object's own typetree (not its fields); the whole object when that is not possible."""
|
|
333
|
+
try:
|
|
334
|
+
head = _head_node(obj._get_typetree_node())
|
|
335
|
+
if head is not None:
|
|
336
|
+
ms = deref(obj, obj.read_typetree(head, check_read=False)["m_Script"])
|
|
337
|
+
if ms is not None:
|
|
338
|
+
return ms.read().m_ClassName
|
|
339
|
+
except Exception:
|
|
340
|
+
pass
|
|
341
|
+
return obj.read().m_Script.read().m_ClassName
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
def strip_pptrs(tt: dict) -> dict:
|
|
345
|
+
"""Typetree without the Unity header fields (GameObject/Script/Enabled/Name)."""
|
|
346
|
+
return {k: v for k, v in tt.items() if k not in ("m_GameObject", "m_Script", "m_Enabled", "m_Name")}
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
# ---- references ---------------------------------------------------------
|
|
350
|
+
DEFAULT_RESOURCES = "Library/unity default resources"
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
def is_pptr(v) -> bool:
|
|
354
|
+
return isinstance(v, dict) and v.keys() == {"m_FileID", "m_PathID"}
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
def external_path(owner, pptr: dict) -> str | None:
|
|
358
|
+
"""Path of the serialized file a PPtr points into (None: the owner's own file)."""
|
|
359
|
+
fid = pptr["m_FileID"]
|
|
360
|
+
return None if fid == 0 else owner.assets_file.externals[fid - 1].path
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
def deref(owner, pptr: dict):
|
|
364
|
+
"""ObjectReader that a PPtr read from `owner`'s typetree points at; None if null."""
|
|
365
|
+
if not pptr["m_PathID"]:
|
|
366
|
+
return None
|
|
367
|
+
return PPtr(m_FileID=pptr["m_FileID"], m_PathID=pptr["m_PathID"],
|
|
368
|
+
assetsfile=owner.assets_file).deref()
|