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.
Files changed (79) hide show
  1. nnnotes/__init__.py +7 -0
  2. nnnotes/__main__.py +4 -0
  3. nnnotes/acb.py +190 -0
  4. nnnotes/addressables.py +413 -0
  5. nnnotes/adv.py +243 -0
  6. nnnotes/advcommand.py +29 -0
  7. nnnotes/advmedia.py +178 -0
  8. nnnotes/advscene.py +113 -0
  9. nnnotes/advui.py +1154 -0
  10. nnnotes/advvideo.py +684 -0
  11. nnnotes/atoms/__init__.py +151 -0
  12. nnnotes/atoms/astc.py +52 -0
  13. nnnotes/atoms/gltf.py +290 -0
  14. nnnotes/atoms/mesh.py +289 -0
  15. nnnotes/atoms/png.py +28 -0
  16. nnnotes/atoms/reader.py +269 -0
  17. nnnotes/atoms/sniff.py +198 -0
  18. nnnotes/atoms/sprite.py +236 -0
  19. nnnotes/atoms/texture.py +80 -0
  20. nnnotes/cache.py +289 -0
  21. nnnotes/catalog.py +373 -0
  22. nnnotes/catalogdb.py +457 -0
  23. nnnotes/census.py +276 -0
  24. nnnotes/cli.py +744 -0
  25. nnnotes/cli_assets.py +1539 -0
  26. nnnotes/config.py +238 -0
  27. nnnotes/contract.py +497 -0
  28. nnnotes/cri.py +371 -0
  29. nnnotes/crikey.py +71 -0
  30. nnnotes/crilips.py +265 -0
  31. nnnotes/cristages.py +558 -0
  32. nnnotes/deckdata.py +462 -0
  33. nnnotes/export.py +1462 -0
  34. nnnotes/gameapi.py +318 -0
  35. nnnotes/jsonio.py +98 -0
  36. nnnotes/languages.py +44 -0
  37. nnnotes/layout.py +596 -0
  38. nnnotes/link.py +418 -0
  39. nnnotes/live.py +115 -0
  40. nnnotes/live2d.py +235 -0
  41. nnnotes/liveaudio.py +331 -0
  42. nnnotes/livenotes.py +291 -0
  43. nnnotes/liveoptions.py +250 -0
  44. nnnotes/livescene.py +450 -0
  45. nnnotes/liveui.py +328 -0
  46. nnnotes/master.py +251 -0
  47. nnnotes/modelstages.py +424 -0
  48. nnnotes/motion.py +131 -0
  49. nnnotes/objexport.py +1564 -0
  50. nnnotes/orchestrate.py +630 -0
  51. nnnotes/plan.py +218 -0
  52. nnnotes/player.py +392 -0
  53. nnnotes/room.py +391 -0
  54. nnnotes/score.py +1139 -0
  55. nnnotes/shader.py +217 -0
  56. nnnotes/spot.py +201 -0
  57. nnnotes/stages.py +285 -0
  58. nnnotes/store.py +518 -0
  59. nnnotes/story.py +142 -0
  60. nnnotes/storyfonts.py +1258 -0
  61. nnnotes/storyhost.py +1190 -0
  62. nnnotes/storysite.py +662 -0
  63. nnnotes/storyvoices.py +102 -0
  64. nnnotes/textstyle.py +355 -0
  65. nnnotes/tmpfont.py +636 -0
  66. nnnotes/typetrees/6000.3.12f1.json +19 -0
  67. nnnotes/unity.py +368 -0
  68. nnnotes/viewrules.json +441 -0
  69. nnnotes/views.py +966 -0
  70. nnnotes/voices.py +1363 -0
  71. nnnotes/web.py +1624 -0
  72. nnnotes/webaudio.py +14 -0
  73. nnnotes/webmodel.py +397 -0
  74. nnnotes-0.1.0.dist-info/METADATA +200 -0
  75. nnnotes-0.1.0.dist-info/RECORD +79 -0
  76. nnnotes-0.1.0.dist-info/WHEEL +5 -0
  77. nnnotes-0.1.0.dist-info/entry_points.txt +2 -0
  78. nnnotes-0.1.0.dist-info/licenses/LICENSE +21 -0
  79. 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()