diff --git a/build.gradle b/build.gradle index b77e8a72..af27c78b 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ plugins { id 'java' - id 'org.jetbrains.kotlin.jvm' version '1.7.20' + id 'org.jetbrains.kotlin.jvm' version '1.8.21' id 'maven-publish' } @@ -9,16 +9,19 @@ version '0.0.1' repositories { mavenCentral() + maven { url 'https://jitpack.io' } } dependencies { + implementation "org.jetbrains.kotlin:kotlin-reflect" implementation "org.jetbrains.kotlin:kotlin-stdlib" implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7' - implementation 'org.json:json:20220924' + implementation 'org.json:json:20230618' implementation 'org.lz4:lz4-java:1.8.0' implementation 'com.nixxcode.jvmbrotli:jvmbrotli:0.2.0' - testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.0' - testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.0' + implementation 'com.github.Deficuet:JImageUtils:0.0.3.a' + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.2' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.2' } test { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 69a97150..db9a6b82 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/io/github/deficuet/unitykt/extension/TextureDecoder.java b/src/main/java/io/github/deficuet/unitykt/extension/TextureDecoder.java index a0484253..77fa3c6b 100644 --- a/src/main/java/io/github/deficuet/unitykt/extension/TextureDecoder.java +++ b/src/main/java/io/github/deficuet/unitykt/extension/TextureDecoder.java @@ -1,6 +1,6 @@ package io.github.deficuet.unitykt.extension; -import io.github.deficuet.unitykt.util.NativeUtils; +import io.github.deficuet.unitykt.internal.NativeUtils; public final class TextureDecoder { private TextureDecoder() { } @@ -9,7 +9,7 @@ private TextureDecoder() { } try { System.loadLibrary("TextureDecoder"); } catch (UnsatisfiedLinkError e) { - NativeUtils.Companion.loadLibraryFromJar("TextureDecoder.dll"); + NativeUtils.Companion.loadLibraryFromJar("TextureDecoder", "dll"); } } diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/AnimationClipFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/AnimationClipFields.java new file mode 100644 index 00000000..9623b288 --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/AnimationClipFields.java @@ -0,0 +1,33 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.classes.AnimationType; +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import kotlin.UInt; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +abstract class AnimationClipFields extends NamedObjectImpl { + AnimationClipFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } + + AnimationType fmAnimationType; + Boolean fmLegacy; + Boolean fmCompressed; + Boolean fmUseHighQualityCurve; + QuaternionCurveImpl[] fmRotationCurves; + CompressedAnimationCurveImpl[] fmCompressedRotationCurves; + Vector3CurveImpl[] fmEulerCurves; + Vector3CurveImpl[] fmPositionCurves; + Vector3CurveImpl[] fmScaleCurves; + FloatCurveImpl[] fmFloatCurves; + PPtrCurveImpl[] fmPPtrCurves; + Float fmSampleRate; + Integer fmWrapMode; + @Nullable AABBImpl fmBounds; + UInt fmMuscleClipSize; + @Nullable ClipMuscleConstantImpl fmMuscleClip; + @Nullable AnimationClipBindingConstantImpl fmClipBindingConstant; + AnimationEventImpl[] fmEvents; +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/AnimationFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/AnimationFields.java new file mode 100644 index 00000000..c7e5fd5a --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/AnimationFields.java @@ -0,0 +1,15 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.classes.AnimationClip; +import io.github.deficuet.unitykt.classes.PPtr; +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import org.jetbrains.annotations.NotNull; + +abstract class AnimationFields extends BehaviourImpl { + AnimationFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } + + PPtr[] fmAnimations; +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/AnimatorControllerFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/AnimatorControllerFields.java new file mode 100644 index 00000000..622b1a42 --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/AnimatorControllerFields.java @@ -0,0 +1,23 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.classes.AnimationClip; +import io.github.deficuet.unitykt.classes.ControllerConstant; +import io.github.deficuet.unitykt.classes.PPtr; +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import kotlin.UInt; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.Map; + +abstract class AnimatorControllerFields extends RuntimeAnimatorControllerImpl { + AnimatorControllerFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } + + UInt fmControllerSize; + ControllerConstant fmController; + Map> fmTOS; + PPtr[] fmAnimationClip; +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/AnimatorFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/AnimatorFields.java new file mode 100644 index 00000000..914903ec --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/AnimatorFields.java @@ -0,0 +1,18 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.classes.Avatar; +import io.github.deficuet.unitykt.classes.PPtr; +import io.github.deficuet.unitykt.classes.RuntimeAnimatorController; +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import org.jetbrains.annotations.NotNull; + +abstract class AnimatorFields extends BehaviourImpl { + AnimatorFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } + + PPtr fmAvatar; + PPtr fmController; + Boolean fmHasTransformHierarchy; +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/AnimatorOverrideControllerFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/AnimatorOverrideControllerFields.java new file mode 100644 index 00000000..715fa811 --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/AnimatorOverrideControllerFields.java @@ -0,0 +1,17 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.classes.AnimationClipOverride; +import io.github.deficuet.unitykt.classes.PPtr; +import io.github.deficuet.unitykt.classes.RuntimeAnimatorController; +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import org.jetbrains.annotations.NotNull; + +abstract class AnimatorOverrideControllerFields extends RuntimeAnimatorControllerImpl { + AnimatorOverrideControllerFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } + + PPtr fmController; + AnimationClipOverride[] fmClips; +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/AssetBundleFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/AssetBundleFields.java new file mode 100644 index 00000000..e6767b5d --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/AssetBundleFields.java @@ -0,0 +1,28 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.classes.AssetInfo; +import io.github.deficuet.unitykt.classes.PPtr; +import io.github.deficuet.unitykt.classes.UnityObject; +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import kotlin.UInt; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.Map; + +abstract class AssetBundleFields extends NamedObjectImpl { + AssetBundleFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } + + PPtr[] fmPreloadTable; + Map> fmContainer; + AssetInfo fmMainAsset; + UInt fmRuntimeCompatibility; + String fmAssetBundleName; + String[] fmDependencies; + Boolean fmIsStreamedSceneAssetBundle; + Integer fmExplicitDataLayout; + Integer fmPathFlags; +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/AudioClipFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/AudioClipFields.java new file mode 100644 index 00000000..84bc4c22 --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/AudioClipFields.java @@ -0,0 +1,34 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.classes.AudioCompressionFormat; +import io.github.deficuet.unitykt.classes.FMODSoundType; +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import io.github.deficuet.unitykt.util.ResourceReader; +import org.jetbrains.annotations.NotNull; + +abstract class AudioClipFields extends NamedObjectImpl { + AudioClipFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } + + Integer fmFormat; + FMODSoundType fmType; + Boolean fm3D; + Boolean fmUseHardware; + Integer fmLoadType; + Integer fmChannels; + Integer fmFrequency; + Integer fmBitsPerSample; + Float fmLength; + Boolean fmIsTrackerFormat; + Integer fmSubSoundIndex; + Boolean fmPreloadAudioData; + Boolean fmLoadInBackground; + Boolean fmLegacy3D; + AudioCompressionFormat fmCompressionFormat; + String fmSource; + Long fmOffset; + Long fmSize; + ResourceReader pfAudioData; +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/AvatarFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/AvatarFields.java new file mode 100644 index 00000000..c78473db --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/AvatarFields.java @@ -0,0 +1,20 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.classes.AvatarConstant; +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import kotlin.UInt; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.Map; + +abstract class AvatarFields extends NamedObjectImpl { + AvatarFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } + + UInt fmAvatarSize; + AvatarConstant fmAvatar; + Map> fmTOS; +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/BehaviourFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/BehaviourFields.java new file mode 100644 index 00000000..0ac08ff0 --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/BehaviourFields.java @@ -0,0 +1,13 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import org.jetbrains.annotations.NotNull; + +abstract class BehaviourFields extends ComponentImpl { + BehaviourFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } + + Byte fmEnabled; +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/CanvasFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/CanvasFields.java new file mode 100644 index 00000000..f5fe72af --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/CanvasFields.java @@ -0,0 +1,26 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.classes.PPtr; +import io.github.deficuet.unitykt.classes.UnityObject; +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import org.jetbrains.annotations.NotNull; + +abstract class CanvasFields extends BehaviourImpl { + CanvasFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } + + Integer fmRenderMode; + PPtr fmCamera; + Float fmPlaneDistance; + Boolean fmPixelPerfect; + Boolean fmReceivesEvent; + Boolean fmOverrideSorting; + Boolean fmOverridePixelPerfect; + Float fmSortingBucketNormalizedSize; + Integer fmAdditionalShaderChannelsFlag; + Integer fmSortingLayerID; + Short fmSortingOrder; + Byte fmTargetDisplay; +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/ComponentFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/ComponentFields.java new file mode 100644 index 00000000..12c20ee6 --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/ComponentFields.java @@ -0,0 +1,15 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.classes.GameObject; +import io.github.deficuet.unitykt.classes.PPtr; +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import org.jetbrains.annotations.NotNull; + +abstract class ComponentFields extends EditorExtensionImpl { + ComponentFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } + + PPtr fmGameObject; +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/EditorExtensionFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/EditorExtensionFields.java new file mode 100644 index 00000000..ec08aab8 --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/EditorExtensionFields.java @@ -0,0 +1,11 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import org.jetbrains.annotations.NotNull; + +abstract class EditorExtensionFields extends UnityObjectImpl { + EditorExtensionFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/GameObjectFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/GameObjectFields.java new file mode 100644 index 00000000..eeb3d954 --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/GameObjectFields.java @@ -0,0 +1,26 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.classes.*; +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import kotlin.UInt; +import kotlin.UShort; +import org.jetbrains.annotations.NotNull; + +abstract class GameObjectFields extends EditorExtensionImpl { + GameObjectFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } + + PPtr[] fmComponents; + UInt fmLayer; + String fmName; + UShort fmTag; + Boolean fmIsActive; + Transform fmTransform; + MeshRenderer fmMeshRenderer; + MeshFilter fmMeshFilter; + SkinnedMeshRenderer fmSkinnedMeshRenderer; + Animator fmAnimator; + Animation fmAnimation; +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/MaterialFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/MaterialFields.java new file mode 100644 index 00000000..a408e697 --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/MaterialFields.java @@ -0,0 +1,17 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.classes.PPtr; +import io.github.deficuet.unitykt.classes.Shader; +import io.github.deficuet.unitykt.classes.UnityPropertySheet; +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import org.jetbrains.annotations.NotNull; + +abstract class MaterialFields extends NamedObjectImpl { + MaterialFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } + + PPtr fmShader; + UnityPropertySheet fmSavedProperties; +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/MeshFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/MeshFields.java new file mode 100644 index 00000000..62fe9dcc --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/MeshFields.java @@ -0,0 +1,34 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import io.github.deficuet.unitykt.math.Matrix4x4; +import kotlin.UInt; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +abstract class MeshFields extends NamedObjectImpl { + MeshFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } + + SubMashImpl[] fmSubMeshes; + @Nullable BlendShapeDataImpl fmShapes; + UInt[] fmIndices; + Matrix4x4[] fmBindPose = new Matrix4x4[0]; + UInt[] fmBoneNameHashes = new UInt[0]; + int fmVertexCount = 0; + float[] fmVertices = new float[0]; + BoneWeights4Impl[] fmSkin = new BoneWeights4Impl[0]; + float[] fmNormals = new float[0]; + float[] fmColors = new float[0]; + float[] fmUV0 = new float[0]; + float[] fmUV1 = new float[0]; + float[] fmUV2 = new float[0]; + float[] fmUV3 = new float[0]; + float[] fmUV4 = new float[0]; + float[] fmUV5 = new float[0]; + float[] fmUV6 = new float[0]; + float[] fmUV7 = new float[0]; + float[] fmTangents = new float[0]; +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/MeshFilterFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/MeshFilterFields.java new file mode 100644 index 00000000..dad98434 --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/MeshFilterFields.java @@ -0,0 +1,15 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.classes.Mesh; +import io.github.deficuet.unitykt.classes.PPtr; +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import org.jetbrains.annotations.NotNull; + +abstract class MeshFilterFields extends ComponentImpl{ + MeshFilterFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } + + PPtr fmMesh; +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/MeshRendererFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/MeshRendererFields.java new file mode 100644 index 00000000..c371edbc --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/MeshRendererFields.java @@ -0,0 +1,11 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import org.jetbrains.annotations.NotNull; + +abstract class MeshRendererFields extends RendererImpl { + MeshRendererFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/MonoBehaviourFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/MonoBehaviourFields.java new file mode 100644 index 00000000..1a2d827c --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/MonoBehaviourFields.java @@ -0,0 +1,16 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.classes.MonoScript; +import io.github.deficuet.unitykt.classes.PPtr; +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import org.jetbrains.annotations.NotNull; + +abstract class MonoBehaviourFields extends BehaviourImpl { + MonoBehaviourFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } + + PPtr fmScript; + String fmName; +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/MonoScriptFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/MonoScriptFields.java new file mode 100644 index 00000000..765f5595 --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/MonoScriptFields.java @@ -0,0 +1,15 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import org.jetbrains.annotations.NotNull; + +abstract class MonoScriptFields extends NamedObjectImpl { + MonoScriptFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } + + String fmClassName; + String fmNameSpace; + String fmAssemblyName; +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/MovieTextureFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/MovieTextureFields.java new file mode 100644 index 00000000..ecc500c1 --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/MovieTextureFields.java @@ -0,0 +1,17 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.classes.AudioClip; +import io.github.deficuet.unitykt.classes.PPtr; +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import org.jetbrains.annotations.NotNull; + +abstract class MovieTextureFields extends TextureImpl { + MovieTextureFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } + + Boolean fmLoop; + PPtr fmAudioClip; + byte[] fmMovieData; +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/NamedObjectFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/NamedObjectFields.java new file mode 100644 index 00000000..e7c1ec08 --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/NamedObjectFields.java @@ -0,0 +1,12 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import org.jetbrains.annotations.NotNull; + +abstract class NamedObjectFields extends EditorExtensionImpl { + NamedObjectFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } + String fmName; +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/PlayerSettingsFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/PlayerSettingsFields.java new file mode 100644 index 00000000..7ba4d095 --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/PlayerSettingsFields.java @@ -0,0 +1,14 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import org.jetbrains.annotations.NotNull; + +abstract class PlayerSettingsFields extends UnityObjectImpl { + PlayerSettingsFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } + + String fCompanyName; + String fProductName; +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/RectTransformFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/RectTransformFields.java new file mode 100644 index 00000000..1f9986d1 --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/RectTransformFields.java @@ -0,0 +1,18 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import io.github.deficuet.unitykt.math.Vector2; +import org.jetbrains.annotations.NotNull; + +abstract class RectTransformFields extends TransformImpl { + RectTransformFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } + + Vector2 fmAnchorMin; + Vector2 fmAnchorMax; + Vector2 fmAnchoredPosition; + Vector2 fmSizeDelta; + Vector2 fmPivot; +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/RendererFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/RendererFields.java new file mode 100644 index 00000000..ead17064 --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/RendererFields.java @@ -0,0 +1,19 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.classes.Material; +import io.github.deficuet.unitykt.classes.PPtr; +import io.github.deficuet.unitykt.classes.StaticBatchInfo; +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import kotlin.UInt; +import org.jetbrains.annotations.NotNull; + +abstract class RendererFields extends ComponentImpl { + RendererFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } + + PPtr[] fmMaterials; + StaticBatchInfo fmStaticBatchInfo; + UInt[] fmSubsetIndices; +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/ResourceManagerFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/ResourceManagerFields.java new file mode 100644 index 00000000..233290bf --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/ResourceManagerFields.java @@ -0,0 +1,18 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.classes.PPtr; +import io.github.deficuet.unitykt.classes.UnityObject; +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.Map; + +abstract class ResourceManagerFields extends UnityObjectImpl { + ResourceManagerFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } + + Map>> fmContainer; +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/RuntimeAnimatorControllerFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/RuntimeAnimatorControllerFields.java new file mode 100644 index 00000000..c9280dc7 --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/RuntimeAnimatorControllerFields.java @@ -0,0 +1,11 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import org.jetbrains.annotations.NotNull; + +abstract class RuntimeAnimatorControllerFields extends NamedObjectImpl { + RuntimeAnimatorControllerFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/ShaderFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/ShaderFields.java new file mode 100644 index 00000000..f0e72d77 --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/ShaderFields.java @@ -0,0 +1,24 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.classes.ShaderCompilerPlatform; +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import kotlin.UInt; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +abstract class ShaderFields extends NamedObjectImpl { + ShaderFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } + + byte[] fmScript; + UInt fDecompressedSize; + byte[] fmSubProgramBlob; + @Nullable SerializedShaderImpl fmParsedForm; + ShaderCompilerPlatform[] fPlatforms; + UInt[][] fOffsets; + UInt[][] fCompressedLengths; + UInt[][] fDecompressedLengths; + byte[] fCompressedBlob; +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/SkinnedMeshRendererFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/SkinnedMeshRendererFields.java new file mode 100644 index 00000000..085aaf03 --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/SkinnedMeshRendererFields.java @@ -0,0 +1,18 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.classes.Mesh; +import io.github.deficuet.unitykt.classes.PPtr; +import io.github.deficuet.unitykt.classes.Transform; +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import org.jetbrains.annotations.NotNull; + +abstract class SkinnedMeshRendererFields extends RendererImpl { + SkinnedMeshRendererFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } + + PPtr fmMesh; + PPtr[] fmBones; + float[] fmBlendShapeWeights; +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/SpriteAtlasFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/SpriteAtlasFields.java new file mode 100644 index 00000000..229f7993 --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/SpriteAtlasFields.java @@ -0,0 +1,21 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.classes.Sprite; +import io.github.deficuet.unitykt.classes.SpriteAtlasData; +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import kotlin.Pair; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; +import java.util.UUID; + +abstract class SpriteAtlasFields extends NamedObjectImpl { + SpriteAtlasFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } + + PPtrImpl[] fmPackedSprites; + Map, SpriteAtlasData> fmRenderDataMap; + Boolean fmIsVariant; +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/SpriteFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/SpriteFields.java new file mode 100644 index 00000000..258786c7 --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/SpriteFields.java @@ -0,0 +1,35 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.classes.PPtr; +import io.github.deficuet.unitykt.classes.SpriteAtlas; +import io.github.deficuet.unitykt.classes.SpriteRenderData; +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import io.github.deficuet.unitykt.math.Rectangle; +import io.github.deficuet.unitykt.math.Vector2; +import io.github.deficuet.unitykt.math.Vector4; +import kotlin.Pair; +import kotlin.UInt; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.UUID; + +abstract class SpriteFields extends NamedObjectImpl{ + SpriteFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } + + Rectangle fmRect; + Vector2 fmOffset; + Vector4 fmBorder; + Float fmPixelsToUnits; + Vector2 fmPivot; + UInt fmExtrude; + Boolean fmIsPolygon; + Pair fmRenderDataKey; + String[] fmAtlasTags; + @Nullable PPtr fmSpriteAtlas; + SpriteRenderData fmRD; + Vector2[][] fmPhysicsShape; +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/TextAssetFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/TextAssetFields.java new file mode 100644 index 00000000..b36e9646 --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/TextAssetFields.java @@ -0,0 +1,13 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import org.jetbrains.annotations.NotNull; + +abstract class TextAssetFields extends NamedObjectImpl { + TextAssetFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } + + byte[] fmScript; +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/Texture2DFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/Texture2DFields.java new file mode 100644 index 00000000..6a0cbdca --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/Texture2DFields.java @@ -0,0 +1,25 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.classes.GLTextureSettings; +import io.github.deficuet.unitykt.classes.StreamingInfo; +import io.github.deficuet.unitykt.classes.TextureFormat; +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import io.github.deficuet.unitykt.util.ResourceReader; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +abstract class Texture2DFields extends TextureImpl { + Texture2DFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } + + Integer fmWidth; + Integer fmHeight; + TextureFormat fmTextureFormat; + Boolean fmMipMap; + Integer fmMipCount; + GLTextureSettings fmTextureSettings; + @Nullable StreamingInfo fmStreamData; + ResourceReader pfImageData; +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/TextureFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/TextureFields.java new file mode 100644 index 00000000..14f5ae98 --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/TextureFields.java @@ -0,0 +1,11 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import org.jetbrains.annotations.NotNull; + +abstract class TextureFields extends NamedObjectImpl { + TextureFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/TransformFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/TransformFields.java new file mode 100644 index 00000000..c9b3ea3a --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/TransformFields.java @@ -0,0 +1,21 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.classes.PPtr; +import io.github.deficuet.unitykt.classes.Transform; +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import io.github.deficuet.unitykt.math.Quaternion; +import io.github.deficuet.unitykt.math.Vector3; +import org.jetbrains.annotations.NotNull; + +abstract class TransformFields extends ComponentImpl { + TransformFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } + + Quaternion fmLocalRotation; + Vector3 fmLocalPosition; + Vector3 fmLocalScale; + PPtr[] fmChildren; + PPtr fmFather; +} diff --git a/src/main/java/io/github/deficuet/unitykt/internal/impl/VideoClipFields.java b/src/main/java/io/github/deficuet/unitykt/internal/impl/VideoClipFields.java new file mode 100644 index 00000000..841b4276 --- /dev/null +++ b/src/main/java/io/github/deficuet/unitykt/internal/impl/VideoClipFields.java @@ -0,0 +1,37 @@ +package io.github.deficuet.unitykt.internal.impl; + +import io.github.deficuet.unitykt.classes.PPtr; +import io.github.deficuet.unitykt.classes.Shader; +import io.github.deficuet.unitykt.classes.StreamedResource; +import io.github.deficuet.unitykt.internal.file.ObjectInfo; +import io.github.deficuet.unitykt.internal.file.SerializedFile; +import io.github.deficuet.unitykt.util.ResourceReader; +import kotlin.UInt; +import kotlin.ULong; +import kotlin.UShort; +import org.jetbrains.annotations.NotNull; + +abstract class VideoClipFields extends NamedObjectImpl { + VideoClipFields(@NotNull SerializedFile assetFile, @NotNull ObjectInfo info) { + super(assetFile, info); + } + + String fmOriginalPath; + UInt fmProxyWidth; + UInt fmProxyHeight; + UInt fmWidth; + UInt fmHeight; + UInt fmPixelAspectRatioNumerator; + UInt fmPixelAspectRatioDenominator; + Double fmFrameRate; + ULong fmFrameCount; + Integer fmFormat; + UShort[] fmAudioChannelCount; + UInt[] fmAudioSampleRate; + String[] fmAudioLanguage; + PPtr[] fmVideoShaders; + StreamedResource fmExternalResource; + Boolean fmHasSplitAlpha; + Boolean fmsRGB; + ResourceReader pfVideoData; +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/ImportContext.kt b/src/main/kotlin/io/github/deficuet/unitykt/ImportContext.kt index 30f19d2c..02b046cd 100644 --- a/src/main/kotlin/io/github/deficuet/unitykt/ImportContext.kt +++ b/src/main/kotlin/io/github/deficuet/unitykt/ImportContext.kt @@ -1,77 +1,28 @@ package io.github.deficuet.unitykt -import io.github.deficuet.unitykt.data.Object -import io.github.deficuet.unitykt.file.* -import io.github.deficuet.unitykt.util.* -import java.io.File - -class ImportContext: AssetBundleFile { - override val files: Map - override val bundleParent = this - override val root = this +import io.github.deficuet.unitykt.classes.UnityObject +interface ImportContext { /** - * The directory where the file is. + * File name */ - val directory: String + val name: String /** - * The name of the file. + * Parent directory */ - override val name: String + val parent: String /** * The [UnityAssetManager] which loads this file. */ val manager: UnityAssetManager + val readerConfig: ReaderConfig + /** - * All [Object] loaded from this file. + * All [UnityObject] loaded from this file. */ - val objectMap = mutableMapOf() - val objectList: Collection get() = objectMap.values - - internal constructor( - filePath: String, manager: UnityAssetManager, - offsetMode: OffsetMode = OffsetMode.MANUAL, - manualOffset: Long = 0 - ) { - val file = File(filePath) - directory = file.parentFile.canonicalPath - name = file.name - this.manager = manager - files = mapOf(name to init(EndianFileStreamReader( - filePath, offsetMode = offsetMode, manualOffset = manualOffset - ))) - } - - internal constructor( - data: ByteArray, name: String, manager: UnityAssetManager, - offsetMode: OffsetMode = OffsetMode.MANUAL, - manualOffset: Long = 0 - ) { - directory = "" - this.name = name - this.manager = manager - files = mapOf(this.name to init(EndianByteArrayReader( - data, offsetMode = offsetMode, manualOffset = manualOffset - ))) - } - - private fun init(reader: EndianBinaryReader): RawAssetFile { - return when (reader.fileType) { - FileType.BUNDLE -> BundleFile(reader, this, name).also { - manager.assetBundles[name] = it - } - FileType.WEB -> WebFile(reader, this, name).also { - manager.assetBundles[name] = it - } - FileType.ASSETS -> SerializedFile(reader, this, name).also { - manager.assetFiles[name] = it - } - FileType.RESOURCE -> ResourceFile(reader, this, name).also { - manager.resourceFiles[name] = it - } - } - } -} \ No newline at end of file + val objectMap: Map + val objectList: Collection +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/PPtrUtils.kt b/src/main/kotlin/io/github/deficuet/unitykt/PPtrUtils.kt deleted file mode 100644 index 9f30fdcc..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/PPtrUtils.kt +++ /dev/null @@ -1,56 +0,0 @@ -package io.github.deficuet.unitykt - -import io.github.deficuet.unitykt.data.Object -import io.github.deficuet.unitykt.data.PPtr - -inline fun PPtr.safeGetObj(): O? { - if (obj != null) return obj - getManager()?.let { manager -> - if (mPathID in manager.objects) { - val objFound = manager.objects.getValue(mPathID) - return if (objFound is O) { - obj = objFound - obj - } else { - null - } - } - } - return null -} - -inline fun PPtr.getObj(): O { - return safeGetObj()!! -} - -inline fun PPtr<*>.safeGetObjAs(): O? { - return safeGetObj() as? O -} - -inline fun PPtr<*>.getObjAs(): T { - return safeGetObj() as T -} - -inline fun Array>.allObjectsOf(): List { - return map { it.safeGetObj() }.filterIsInstance() -} - -inline fun Collection>.allObjectsOf(): List { - return map { it.safeGetObj() }.filterIsInstance() -} - -inline fun Array>.firstObjectOf(): T { - return mapNotNull { it.safeGetObj() }.firstObjectOf() -} - -inline fun Collection>.firstObjectOf(): T { - return mapNotNull { it.safeGetObj() }.firstObjectOf() -} - -inline fun Array>.firstOfOrNull(): T? { - return mapNotNull { it.safeGetObj() }.firstOfOrNull() -} - -inline fun Collection>.firstOfOrNull(): T? { - return mapNotNull { it.safeGetObj() }.firstOfOrNull() -} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/UnityAssetManager.kt b/src/main/kotlin/io/github/deficuet/unitykt/UnityAssetManager.kt index e07d597b..d7afeaca 100644 --- a/src/main/kotlin/io/github/deficuet/unitykt/UnityAssetManager.kt +++ b/src/main/kotlin/io/github/deficuet/unitykt/UnityAssetManager.kt @@ -1,165 +1,170 @@ package io.github.deficuet.unitykt -import io.github.deficuet.unitykt.file.* -import io.github.deficuet.unitykt.util.OffsetMode -import io.github.deficuet.unitykt.util.isDirectory -import io.github.deficuet.unitykt.util.isFile +import io.github.deficuet.unitykt.classes.AssetBundle +import io.github.deficuet.unitykt.classes.PPtr +import io.github.deficuet.unitykt.classes.UnityObject +import io.github.deficuet.unitykt.internal.UnityAssetManagerImpl import java.io.Closeable -import java.nio.file.Files -import java.util.stream.Collectors -import kotlin.io.path.Path -import kotlin.io.path.isRegularFile -import kotlin.io.path.pathString +import java.io.File +import java.nio.file.Path -class UnityAssetManager: Closeable { - /** - * Usually [BundleFile] and [WebFile] with their file names. - */ - val assetBundles = mutableMapOf() - - val assetFiles = mutableMapOf() - val resourceFiles = mutableMapOf() +interface UnityAssetManager: Closeable { + val assetRootFolder: File? + val defaultReaderConfig: ReaderConfig /** - * All file context loaded from disk. + * All file contexts loaded. */ - val contexts = mutableMapOf() + val contexts: Map /** - * All Objects loaded except [io.github.deficuet.unitykt.data.AssetBundle] + * All Objects loaded except [AssetBundle] */ - val objectList get() = contexts.values.flatMap { context -> - sequence { - for (obj in context.objectMap) { - if (obj.key != 1L) { - yield(obj.value) - } - } - } - } + val objectList: List /** * Multi-dictionary of objects associated with their mPathID */ - val objectMap get() = objectList.groupBy { it.mPathID } - - data class Configuration internal constructor( - /** - * @see [OffsetMode] - */ - var offsetMode: OffsetMode = OffsetMode.AUTO, - - /** - * Skip specific number of bytes before reading under [OffsetMode.MANUAL] mode. - */ - var manualOffset: Long = 0 - ) - - private val configuration = Configuration() - - internal val otherReaderList = mutableListOf() - - init { managers.add(this) } + val objectMap: Map> /** * @param data Bytes of AsserBundle file * @param name A string as the "file name" of this bytes - * @param config To set [Configuration.offsetMode] and [Configuration.manualOffset] **before** reading - */ - fun loadFromByteArray(data: ByteArray, name: String, config: Configuration.() -> Unit = {}): ImportContext { - configuration.config() - return ImportContext( - data, name, this, - configuration.offsetMode, - configuration.manualOffset - ).also { - contexts[it.name] = it - } - } + * @param config To set [offsetMode][ReaderConfig.offsetMode] + * and [manualOffset][ReaderConfig.manualOffset] **before** reading + * @return A [ImportContext] for the bytes. + */ + fun loadFromByteArray(data: ByteArray, name: String, config: ReaderConfig = defaultReaderConfig): ImportContext /** - * @param path The path string points to a **file** - * @param config To set [Configuration.offsetMode] and [Configuration.manualOffset] **before** reading + * @param file The **file** path. + * @param config To set [offsetMode][ReaderConfig.offsetMode] + * and [manualOffset][ReaderConfig.manualOffset] **before** reading * @return A [ImportContext] for this file. - * @throws IllegalStateException If [path] does not point to a **file** - */ - fun loadFile(path: String, config: Configuration.() -> Unit = {}): ImportContext { - configuration.config() - if (!path.isFile()) throw IllegalStateException("\"path\" must be a file") - return ImportContext( - path, this, - configuration.offsetMode, - configuration.manualOffset - ).also { - contexts[it.name] = it - } - } - + * @throws IllegalArgumentException If [file] does not point to a file. + */ + fun loadFile(file: String, config: ReaderConfig = defaultReaderConfig): ImportContext /** - * @param path The path strings point to **files** - * @param config To set [Configuration.offsetMode] and [Configuration.manualOffset] **before** reading - * @return A list of [ImportContext] for each file. - * @throws IllegalStateException If [path] does not point to a **file** + * @see loadFile */ - fun loadFiles(vararg path: String, config: Configuration.() -> Unit = {}): List { - configuration.config() - if (path.any { !it.isFile() }) throw IllegalStateException("\"path\" must be a file") - return mutableListOf().apply { - for (dir in path) { - add(loadFile(dir)) - } - } - } + fun loadFile(file: Path, config: ReaderConfig = defaultReaderConfig): ImportContext + /** + * @see loadFile + */ + fun loadFile(file: File, config: ReaderConfig = defaultReaderConfig): ImportContext /** - * @param folder The path strings point to a **folder** - * @param config To set [Configuration.offsetMode] and [Configuration.manualOffset] **before** reading - * @return A list of [ImportContext] for each file under this folder. - * Others folders under this directory will be ignored. - * @throws IllegalStateException If [folder] does not point to a **folder**. + * @param files Arbitrary number of **file** paths. + * @param config config To set [offsetMode][ReaderConfig.offsetMode] + * and [manualOffset][ReaderConfig.manualOffset] **before** reading for all files + * @return An [Array] of [ImportContext] for each file. + * @throws IllegalArgumentException If any of [files] does not point to a file. */ - fun loadFolder(folder: String, config: Configuration.() -> Unit = {}): List { - configuration.config() - if (!folder.isDirectory()) throw IllegalStateException("\"path\" must be a directory") - val files = Files.newDirectoryStream(Path(folder)).use { stream -> - stream.filter { it.isRegularFile() } - .map { it.pathString } - .toTypedArray() - } - return loadFiles(*files) - } + fun loadFiles(vararg files: String, config: ReaderConfig = defaultReaderConfig): Array + /** + * @see loadFiles + */ + fun loadFiles(vararg files: Path, config: ReaderConfig = defaultReaderConfig): Array + /** + * @see loadFiles + */ + fun loadFiles(vararg files: File, config: ReaderConfig = defaultReaderConfig): Array /** - * @param folder The path strings point to a **folder** - * @param config To set [Configuration.offsetMode] and [Configuration.manualOffset] **before** reading - * @return A list of [ImportContext] for all reachable files under this folder. - * @throws IllegalStateException If [folder] does not point to a **folder**. + * @param folder The **folder** path + * @param config To set [offsetMode][ReaderConfig.offsetMode] + * and [manualOffset][ReaderConfig.manualOffset] **before** reading for all files + * @return An [Array] of [ImportContext] for each file under this folder. + * Folders under this directory is excluded. + * @throws IllegalArgumentException If [folder] does not point to a folder. */ - fun loadFolderRecursively(folder: String, config: Configuration.() -> Unit = {}): List { - configuration.config() - if (!folder.isDirectory()) throw IllegalStateException("\"path\" must be a directory") - val files = Files.walk(Path(folder)).filter(Files::isRegularFile) - .map { it.pathString }.collect(Collectors.toList()).toTypedArray() - return loadFiles(*files) - } + fun loadFolder(folder: String, config: ReaderConfig = defaultReaderConfig): Array + /** + * @see loadFolder + */ + fun loadFolder(folder: File, config: ReaderConfig = defaultReaderConfig): Array + /** + * @see loadFolder + */ + fun loadFolder(folder: Path, config: ReaderConfig = defaultReaderConfig): Array - override fun close() { - assetFiles.values.forEach { it.reader.close() } - resourceFiles.values.forEach { it.reader.close() } - otherReaderList.forEach { it.close() } - assetBundles.clear() - assetFiles.clear() - resourceFiles.clear() - otherReaderList.clear() - contexts.clear() - } + /** + * @param folder The **folder** path + * @param config To set [offsetMode][ReaderConfig.offsetMode] + * and [manualOffset][ReaderConfig.manualOffset] **before** reading for all files + * @return An [Array] of [ImportContext] for **all** reachable files under this folder. + * @throws IllegalArgumentException If [folder] does not point to a folder. + */ + fun loadFolderRecursively(folder: String, config: ReaderConfig = defaultReaderConfig): Array + /** + * @see loadFolderRecursively + */ + fun loadFolderRecursively(folder: File, config: ReaderConfig = defaultReaderConfig): Array + /** + * @see loadFolderRecursively + */ + fun loadFolderRecursively(folder: Path, config: ReaderConfig = defaultReaderConfig): Array companion object { - private val managers = mutableListOf() + /** + * @param assetRootFolder The root folder of a Unity asset bundles system. + * This will be used by [PPtr] to find dependency objects. + */ + fun new(assetRootFolder: String, readerConfig: ReaderConfig = ReaderConfig.default): UnityAssetManager { + return new(File(assetRootFolder), readerConfig) + } + /** + * @see new + */ + fun new(assetRootFolder: Path, readerConfig: ReaderConfig = ReaderConfig.default): UnityAssetManager { + return new(assetRootFolder.toFile(), readerConfig) + } + /** + * @see new + */ + fun new(assetRootFolder: File, readerConfig: ReaderConfig = ReaderConfig.default): UnityAssetManager { + if (!assetRootFolder.isDirectory) { + throw IllegalArgumentException("${assetRootFolder.path} is not a valid folder") + } + return UnityAssetManagerImpl(assetRootFolder, readerConfig) + } + + fun new(readerConfig: ReaderConfig = ReaderConfig.default): UnityAssetManager { + return UnityAssetManagerImpl(null, readerConfig) + } + + internal val managers = mutableListOf() fun closeAll() { managers.forEach { it.close() } managers.clear() } } +} + +data class ReaderConfig internal constructor( + /** + * @see [OffsetMode] + */ + val offsetMode: OffsetMode = OffsetMode.MANUAL, + + /** + * Skip specific number of bytes before reading. + * + * Works under [OffsetMode.MANUAL] mode. + */ + val manualOffset: Long = 0 +) { + companion object { + val default = ReaderConfig() + } +} + +enum class OffsetMode { + MANUAL, + + /** + * Stream will seek automatically to the first non-zero byte. + */ + AUTO } \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/Animation.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/Animation.kt new file mode 100644 index 00000000..cdcb48a9 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/Animation.kt @@ -0,0 +1,5 @@ +package io.github.deficuet.unitykt.classes + +interface Animation: Behaviour { + val mAnimations: Array> +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/AnimationClip.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/AnimationClip.kt new file mode 100644 index 00000000..782ebb52 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/AnimationClip.kt @@ -0,0 +1,280 @@ +package io.github.deficuet.unitykt.classes + +import io.github.deficuet.unitykt.enums.ClassIDType +import io.github.deficuet.unitykt.enums.NumericalEnum +import io.github.deficuet.unitykt.enums.NumericalEnumCompanion +import io.github.deficuet.unitykt.math.Quaternion +import io.github.deficuet.unitykt.math.Vector3 +import io.github.deficuet.unitykt.math.Vector4 + +interface AnimationClip: NamedObject { + val mAnimationType: AnimationType + val mLegacy: Boolean + val mCompressed: Boolean + val mUseHighQualityCurve: Boolean + val mRotationCurves: Array + val mCompressedRotationCurves: Array + val mEulerCurves: Array + val mPositionCurves: Array + val mScaleCurves: Array + val mFloatCurves: Array + val mPPtrCurves: Array + val mSampleRate: Float + val mWrapMode: Int + val mBounds: AABB? + val mMuscleClipSize: UInt + val mMuscleClip: ClipMuscleConstant? + val mClipBindingConstant: AnimationClipBindingConstant? + val mEvents: Array +} + +interface KeyFrame { + val time: Float + val value: T + val inSlope: T + val outSlope: T + val weightedMode: Int + val inWeight: T? + val outWeight: T? +} + +interface AnimationCurve { + val mCurve: Array> + val mPreInfinity: Int + val mPostInfinity: Int + val mRotationOrder: Int +} + +interface QuaternionCurve { + val curve: AnimationCurve + val path: String +} + +interface PackedFloatVector { + val mNumItems: UInt + val mRange: Float + val mStart: Float + val mData: ByteArray + val mBitSize: UByte + + fun unpackFloats( + itemCountInChunk: Int, + chunkStride: Int, + start: Int = 0, + chunkCount: Int = -1 + ): FloatArray +} + +interface PackedIntVector { + val mNumItems: UInt + val mData: ByteArray + val mBitSize: UByte + + fun unpackInts(): IntArray +} + +interface PackedQuatVector { + val mNumItems: UInt + val mData: ByteArray + + fun unpackQuats(): Array +} + +interface CompressedAnimationCurve { + val mPath: String + val mTimes: PackedIntVector + val mValues: PackedQuatVector + val mSlopes: PackedFloatVector + val mPreInfinity: Int + val mPostInfinity: Int +} + +interface Vector3Curve { + val curve: AnimationCurve + val path: String +} + +interface FloatCurve { + val curve: AnimationCurve + val attribute: String + val path: String + val classID: ClassIDType + val script: PPtr +} + +interface PPtrKeyFrame { + val time: Float + val value: PPtr +} + +interface PPtrCurve { + val curve: Array + val attribute: String + val path: String + val classID: Int + val script: PPtr +} + +interface AABB { + val mCenter: Vector3 + val mExtent: Vector3 +} + +interface XForm { + val t: Vector3 + val q: Quaternion + val s: Vector3 +} + +interface HandPose { + val mGrabX: XForm + val mDoFArray: FloatArray + val mOverride: Float + val mCloseOpen: Float + val mInOut: Float + val mGrab: Float +} + +interface HumanGoal { + val mX: XForm + val mWeightT: Float + val mWeightR: Float + val mHintT: Vector3 + val mHintWeightT: Float +} + +interface HumanPose { + val mRootX: XForm + val mLookAt: Vector3 + val mLookAtWeight: Vector4 + val mGoalArray: Array + val mLeftHandPose: HandPose + val mRightHandPose: HandPose + val mDoFArray: FloatArray + val mTDoFArray: Array +} + +interface StreamedCurveKey { + val index: Int + val coeff: FloatArray + val outSlope: Float + val value: Float + val inSlope: Float + + fun nextInSlope(deltaX: Float, rhs: StreamedCurveKey): Float +} + +interface StreamedFrame { + val time: Float + val keyList: Array +} + +interface StreamedClip { + val data: Array + val curveCount: UInt + + fun readData(): List +} + +interface DenseClip { + val mFrameCount: Int + val mCurveCount: UInt + val mSampleRate: Float + val mBeginTime: Float + val mSampleArray: FloatArray +} + +interface ConstantClip { + val data: FloatArray +} + +interface ValueConstant { + val mID: UInt + val mTypeID: UInt + val mType: UInt + val mIndex: UInt +} + +interface ValueArrayConstant { + val mValueArray: Array +} + +interface GenericBinding { + val path: UInt + val attribute: UInt + val script: PPtr? + val typeID: ClassIDType + val customType: UByte + val isPPtrCurve: UByte + val isIntCurve: UByte +} + +interface AnimationClipBindingConstant { + val genericBindings: Array + val pptrCurveMapping: Array> + + fun findBinding(index: Int): GenericBinding? +} + +interface Clip { + val mStreamedClip: StreamedClip + val mDenseClip: DenseClip + val mConstantClip: ConstantClip? + val mBinding: ValueArrayConstant? + + fun buildGenericBindings(): AnimationClipBindingConstant +} + +interface ValueDelta { + val mStart: Float + val mStop: Float +} + + +interface ClipMuscleConstant { + val mDeltaPose: HumanPose + val mStartX: XForm + val mStopX: XForm? + val mLeftFootStartX: XForm + val mRightFootStartX: XForm + val mMotionStartX: XForm? + val mMotionStopX: XForm? + val mAverageSpeed: Vector3 + val mClip: Clip + val mStartTime: Float + val mStopTime: Float + val mOrientationOffsetY: Float + val mLevel: Float + val mCycleOffset: Float + val mAverageAngularSpeed: Float + val mIndexArray: IntArray + val mValueArrayDelta: Array + val mValueArrayReferencePose: FloatArray + val mMirror: Boolean + val mLoopTime: Boolean + val mLoopBlend: Boolean + val mLoopBlendOrientation: Boolean + val mLoopBlendPositionY: Boolean + val mLoopBlendPositionXZ: Boolean + val mStartAtOrigin: Boolean + val mKeepOriginalOrientation: Boolean + val mKeepOriginalPositionY: Boolean + val mKeepOriginalPositionXZ: Boolean + val mHeightFromFeet: Boolean +} + +interface AnimationEvent { + val time: Float + val functionName: String + val data: String + val objectReferenceParameter: PPtr + val floatParameter: Float + val intParameter: Int + val messageOptions: Int +} + +enum class AnimationType(override val id: Int): NumericalEnum { + Default(0), Legacy(1), Generic(2), Humanoid(3); + + companion object: NumericalEnumCompanion(values(), Default) +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/Animator.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/Animator.kt new file mode 100644 index 00000000..5c65f54e --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/Animator.kt @@ -0,0 +1,7 @@ +package io.github.deficuet.unitykt.classes + +interface Animator: Behaviour { + val mAvatar: PPtr + val mController: PPtr + val mHasTransformHierarchy: Boolean +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/AnimatorController.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/AnimatorController.kt new file mode 100644 index 00000000..ad6e696f --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/AnimatorController.kt @@ -0,0 +1,167 @@ +package io.github.deficuet.unitykt.classes + +import io.github.deficuet.unitykt.math.Vector2 +import io.github.deficuet.unitykt.math.Vector3 +import io.github.deficuet.unitykt.math.Vector4 + +interface AnimatorController: RuntimeAnimatorController { + val mControllerSize: UInt + val mController: ControllerConstant + val mTOS: Map> + val mAnimationClip: Array> +} + +interface HumanPoseMask { + val word0: UInt + val word1: UInt + val word2: UInt +} + +interface SkeletonMaskElement { + val mPathHash: UInt + val mWeight: Float +} + +interface SkeletonMask { + val mData: Array +} + +interface LayerConstant { + val mStateMachineIndex: UInt + val mStateMachineMotionSetIndex: UInt + val mBodyMask: HumanPoseMask + val mSkeletonMask: SkeletonMask + val mBinding: UInt + val mLayerBlendingMode: Int + val mDefaultWeight: Float + val mIKPass: Boolean + val mSyncedLayerAffectsTiming: Boolean +} + +interface ConditionConstant { + val mConditionMode: UInt + val mEventID: UInt + val mEventThreshold: Float + val mExitTime: Float +} + +interface TransitionConstant { + val mConditionConstantArray: Array + val mDestinationState: UInt + val mFullPathID: UInt + val mID: UInt + val mUserID: UInt + val mTransitionDuration: Float + val mTransitionOffset: Float + val mExitTime: Float + val mHasExitTime: Boolean + val mHasFixedDuration: Boolean + val mInterruptionSource: Int + val mOrderedInterruption: Boolean + val mAtomic: Boolean + val mCanTransitionToSelf: Boolean +} + +interface LeafInfoConstant { + val mIDArray: Array + val mIndexOffset: UInt +} + +interface MotionNeighborList { + val mNeighborArray: Array +} + +interface Blend2dDataConstant { + val mChildPositionArray: Array + val mChildMagnitudeArray: FloatArray + val mChildPairVectorArray: Array + val mChildPairAvgMagInvArray: FloatArray + val mChildNeighborListArray: Array +} + +interface Blend1dDataConstant { + val mChildThresholdArray: FloatArray +} + +interface BlendDirectDataConstant { + val mChildBlendEventIDArray: Array + val mNormalizedBlendValues: Boolean +} + +interface BlendTreeNodeConstant { + val mBlendType: UInt + val mBlendEventID: UInt + val mBlendEventYID: UInt + val mChildIndices: Array + val mChildThresholdArray: FloatArray + val mBlend1dData: Blend1dDataConstant? + val mBlend2dData: Blend2dDataConstant? + val mBlendDirectData: BlendDirectDataConstant? + val mClipID: UInt + val mClipIndex: UInt + val mDuration: Float + val mCycleOffset: Float + val mMirror: Boolean +} + +interface BlendTreeConstant { + val mNodeArray: Array + val mBlendEventArrayConstant: ValueArrayConstant? +} + +interface StateConstant { + val mTransitionConstantArray: Array + val mBlendTreeConstantIndexArray: IntArray + val mLeafInfoArray: Array + val mBlendTreeConstantArray: Array + val mNameID: UInt + val mPathID: UInt + val mFullPathID: UInt + val mTagID: UInt + val mSpeedParamID: UInt + val mMirrorParamID: UInt + val mCycleOffsetParamID: UInt + val mTimeParamID: UInt + val mSpeed: Float + val mCycleOffset: Float + val mIKOnFeet: Boolean + val mWriteDefaultValues: Boolean + val mLoop: Boolean + val mMirror: Boolean +} + +interface SelectorTransitionConstant { + val mDestination: UInt + val mConditionConstantArray: Array +} + +interface SelectorStateConstant { + val mTransitionConstantArray: Array + val mFullPathID: UInt + val mIsEntry: Boolean +} + +interface StateMachineConstant { + val mStateConstantArray: Array + val mAnyStateTransitionConstantArray: Array + val mSelectorStateConstantArray: Array + val mDefaultState: UInt + val mMotionSetCount: UInt +} + +interface ValueArray { + val mBoolValues: BooleanArray + val mIntValues: IntArray + val mFloatValues: FloatArray + val mVectorValues: Array + val mPositionValues: Array + val mQuaternionValues: Array + val mScaleValues: Array +} + +interface ControllerConstant { + val mLayerArray: Array + val mStateMachineArray: Array + val mValues: ValueArrayConstant + val mDefaultValues: ValueArray +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/AnimatorOverrideController.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/AnimatorOverrideController.kt new file mode 100644 index 00000000..cc56ffab --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/AnimatorOverrideController.kt @@ -0,0 +1,11 @@ +package io.github.deficuet.unitykt.classes + +interface AnimatorOverrideController: RuntimeAnimatorController { + val mController: PPtr + val mClips: Array +} + +interface AnimationClipOverride { + val mOriginalClip: PPtr + val mOverrideClip: PPtr +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/AssetBundle.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/AssetBundle.kt new file mode 100644 index 00000000..f0c1974b --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/AssetBundle.kt @@ -0,0 +1,19 @@ +package io.github.deficuet.unitykt.classes + +interface AssetBundle: NamedObject { + val mPreloadTable: Array> + val mContainer: Map> + val mMainAsset: AssetInfo + val mRuntimeCompatibility: UInt + val mAssetBundleName: String + val mDependencies: Array + val mIsStreamedSceneAssetBundle: Boolean + val mExplicitDataLayout: Int + val mPathFlags: Int +} + +interface AssetInfo { + val preloadIndex: Int + val preloadSize: Int + val asset: PPtr +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/AudioClip.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/AudioClip.kt new file mode 100644 index 00000000..53ba5a1f --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/AudioClip.kt @@ -0,0 +1,81 @@ +package io.github.deficuet.unitykt.classes + +import io.github.deficuet.unitykt.enums.NumericalEnum +import io.github.deficuet.unitykt.enums.NumericalEnumCompanion + +interface AudioClip: NamedObject { + val mFormat: Int + val mType: FMODSoundType + val m3D: Boolean + val mUseHardware: Boolean + + val mLoadType: Int + val mChannels: Int + val mFrequency: Int + val mBitsPerSample: Int + val mLength: Float + val mIsTrackerFormat: Boolean + val mSubSoundIndex: Int + val mPreloadAudioData: Boolean + val mLoadInBackground: Boolean + val mLegacy3D: Boolean + val mCompressionFormat: AudioCompressionFormat + + val mSource: String + val mOffset: Long + val mSize: Long + + fun getRawData(): ByteArray +} + +enum class FMODSoundType(override val id: Int, val ext: String): NumericalEnum { + UNKNOWN(1, ""), + ACC(2, ".m4a"), + AIFF(3, ".aif"), + ASF(3, ""), + AT3(4, ""), + CDDA(5, ""), + DLS(6, ""), + FLAC(7, ""), + FSB(8, ""), + GCADPCM(9, ""), + IT(10, ".it"), + MIDI(11, ""), + MOD(12, ".mod"), + MPEG(13, ".mp3"), + OGGVORBIS(14, ".ogg"), + PLAYLIST(15, ""), + RAW(16, ""), + S3M(17, ".s3m"), + SF2(18, ""), + USER(19, ""), + WAV(20, ".wav"), + XM(21, ".xm"), + XMA(22, ".wav"), + VAG(23, ".vag"), + AUDIOQUEUE(24, ".fsb"), + XWMA(25, ""), + BCWAV(26, ""), + AT9(27, ""), + VORBIS(28, ""), + MEDIA_FOUNDATION(29, ""); + + companion object: NumericalEnumCompanion(values(), UNKNOWN) +} + + +enum class AudioCompressionFormat(override val id: Int, val ext: String): NumericalEnum { + PCM(0, ".fsb"), + Vorbis(1, ".fsb"), + ADPCM(2, ".fsb"), + MP3(3, ".fsb"), + PSVAG(4, ".fsb"), + HEVAG(5, ".fsb"), + XMA(6, ".fsb"), + AAC(7, ".m4a"), + GCADPCM(8, ".fsb"), + ATRAC9(9, ".fsb"), + UNKNOWN(9999, "."); + + companion object: NumericalEnumCompanion(values(), UNKNOWN) +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/Avatar.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/Avatar.kt new file mode 100644 index 00000000..10af0ed0 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/Avatar.kt @@ -0,0 +1,100 @@ +package io.github.deficuet.unitykt.classes + +import io.github.deficuet.unitykt.math.Vector +import io.github.deficuet.unitykt.math.Vector4 + +interface Avatar: NamedObject { + val mAvatarSize: UInt + val mAvatar: AvatarConstant + val mTOS: Map> +} + +interface Node { + val mParentId: Int + val mAxesId: Int +} + +interface Limit { + val mMin: Vector<*> + val mMax: Vector<*> +} + +interface Axes { + val mPreQ: Vector4 + val mPostQ: Vector4 + val mSgn: Vector<*> + val mLimit: Limit + val mLength: Float + val mType: UInt +} + +interface Skeleton { + val mNode: Array + val mID: Array + val mAxesArray: Array +} + +interface SkeletonPose { + val mX: Array +} + +interface Hand { + val mHandBoneIndex: IntArray +} + +interface Handle { + val mX: XForm + val mParentHumanIndex: UInt + val mID: UInt +} + +interface Collider { + val mX: XForm + val mType: UInt + val mXMotionType: UInt + val mYMotionType: UInt + val mZMotionType: UInt + val mMinLimitX: Float + val mMaxLimitX: Float + val mMaxLimitY: Float + val mMaxLimitZ: Float +} + +interface Human { + val mRootX: XForm + val mSkeleton: Skeleton + val mSkeletonPose: SkeletonPose + val mLeftHand: Hand + val mRightHand: Hand + val mHandles: Array + val mColliderArray: Array + val mHumanBoneIndex: IntArray + val mHumanBoneMass: FloatArray + val mColliderIndex: IntArray + val mScale: Float + val mAriTwist: Float + val mForeArmTwist: Float + val mUpperLegTwist: Float + val mLegTwist: Float + val mArmStretch: Float + val mLegStretch: Float + val mFeetSpacing: Float + val mHasLeftHand: Boolean + val mHasRightHand: Boolean + val mHasTDoF: Boolean +} + +interface AvatarConstant { + val mAvatarSkeleton: Skeleton + val mAvatarSkeletonPose: SkeletonPose + val mDefaultPose: SkeletonPose? + val mSkeletonNameIDArray: Array + val mHuman: Human + val mHumanSkeletonIndexArray: IntArray + val mHumanSkeletonReverseIndexArray: IntArray + val mRootMotionBoneIndex: Int + val mRootMotionBoneX: XForm + val mRootMotionSkeleton: Skeleton? + val mRootMotionSkeletonPose: SkeletonPose? + val mRootMotionSkeletonIndexArray: IntArray +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/Behaviour.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/Behaviour.kt new file mode 100644 index 00000000..0c5d7e88 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/Behaviour.kt @@ -0,0 +1,5 @@ +package io.github.deficuet.unitykt.classes + +interface Behaviour: Component { + val mEnabled: Byte +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/Canvas.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/Canvas.kt new file mode 100644 index 00000000..d256abc9 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/Canvas.kt @@ -0,0 +1,19 @@ +package io.github.deficuet.unitykt.classes + +/** + * Only tested under version `2018.4.34f1` + */ +interface Canvas: Behaviour { + val mRenderMode: Int + val mCamera: PPtr //PPtr + val mPlaneDistance: Float + val mPixelPerfect: Boolean + val mReceivesEvent: Boolean + val mOverrideSorting: Boolean + val mOverridePixelPerfect: Boolean + val mSortingBucketNormalizedSize: Float + val mAdditionalShaderChannelsFlag: Int + val mSortingLayerID: Int + val mSortingOrder: Short + val mTargetDisplay: Byte +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/Component.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/Component.kt new file mode 100644 index 00000000..eae8fbe7 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/Component.kt @@ -0,0 +1,5 @@ +package io.github.deficuet.unitykt.classes + +interface Component: EditorExtension { + val mGameObject: PPtr +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/EditorExtension.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/EditorExtension.kt new file mode 100644 index 00000000..c476eccd --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/EditorExtension.kt @@ -0,0 +1,3 @@ +package io.github.deficuet.unitykt.classes + +interface EditorExtension: UnityObject \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/GameObject.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/GameObject.kt new file mode 100644 index 00000000..fa03fff0 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/GameObject.kt @@ -0,0 +1,15 @@ +package io.github.deficuet.unitykt.classes + +interface GameObject: EditorExtension { + val mComponents: Array> + val mLayer: UInt + val mName: String + val mTag: UShort + val mIsActive: Boolean + val mTransform: Transform + val mMeshRenderer: MeshRenderer + val mMeshFilter: MeshFilter + val mSkinnedMeshRenderer: SkinnedMeshRenderer + val mAnimator: Animator + val mAnimation: Animation +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/Material.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/Material.kt new file mode 100644 index 00000000..fc38c511 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/Material.kt @@ -0,0 +1,22 @@ +package io.github.deficuet.unitykt.classes + +import io.github.deficuet.unitykt.math.Color +import io.github.deficuet.unitykt.math.Vector2 + +interface Material: NamedObject { + val mShader: PPtr + val mSavedProperties: UnityPropertySheet +} + +interface UnityTexEnv { + val mTexture: PPtr + val mScale: Vector2 + val mOffset: Vector2 +} + +interface UnityPropertySheet { + val mTexEnvs: Map> + val mInts: Map> + val mFloats: Map> + val mColors: Map> +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/Mesh.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/Mesh.kt new file mode 100644 index 00000000..e9aaecaa --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/Mesh.kt @@ -0,0 +1,138 @@ +package io.github.deficuet.unitykt.classes + +import io.github.deficuet.unitykt.math.Matrix4x4 +import io.github.deficuet.unitykt.math.Vector2 +import io.github.deficuet.unitykt.math.Vector3 + +interface Mesh: NamedObject { + val mSubMeshes: Array + val mShapes: BlendShapeData? + val mIndices: Array + val mBindPose: Array + val mBoneNameHashes: Array + val mVertexCount: Int + val mVertices: FloatArray + val mSkin: Array + val mNormals: FloatArray + val mColors: FloatArray + val mUV0: FloatArray + val mUV1: FloatArray + val mUV2: FloatArray + val mUV3: FloatArray + val mUV4: FloatArray + val mUV5: FloatArray + val mUV6: FloatArray + val mUV7: FloatArray + val mTangents: FloatArray + + fun exportString(): String + + /** + * The data for lines starting with "v" + */ + fun exportVertices(): Array + + /** + * The data for lines starting with "vt" + */ + fun exportUV(): Array + + /** + * The data for lines starting with "vn" + */ + fun exportNormals(): Array + + /** + * The data for lines starting with "f" + */ + fun exportFaces(): Array> +} + +interface MinMaxAABB { + val mMin: Vector3 + val mMax: Vector3 +} + +interface CompressedMesh { + val mVertices: PackedFloatVector + val mUV: PackedFloatVector + val mBindPoses: PackedFloatVector? + val mNormals: PackedFloatVector + val mTangents: PackedFloatVector + val mWeights: PackedIntVector + val mNormalSigns: PackedIntVector + val mTangentSigns: PackedIntVector + val mFloatColors: PackedFloatVector? + val mBoneIndices: PackedIntVector + val mTriangles: PackedIntVector + val mColors: PackedIntVector? + val mUVInfo: UInt +} + +interface StreamInfo { + val channelMask: UInt + val offset: UInt + val stride: UInt + val align: UInt + val dividerOp: UByte + val frequency: UShort +} + +interface ChannelInfo { + val stream: UByte + val offset: UByte + val format: UByte + val dimension: UByte +} + +interface VertexData { + val mCurrentChannels: UInt + val mVertexCount: UInt + val mChannels: Array + val mStreams: Array + val mDataSize: ByteArray +} + +interface BoneWeights4 { + val weight: FloatArray + val boneIndex: IntArray +} + +interface BlendShapeVertex { + val vertex: Vector3 + val normal: Vector3 + val tangent: Vector3 + val index: UInt +} + +interface MeshBlendShape { + val firstVertex: UInt + val vertexCount: UInt + val hasNormals: Boolean + val hasTangents: Boolean +} + +interface MeshBlendShapeChannel { + val name: String + val nameHash: UInt + val frameIndex: Int + val frameCount: Int +} + +interface BlendShapeData { + val vertices: Array + val shapes: Array + val channels: Array + val fullWeights: FloatArray +} + +interface SubMash { + val firstByte: UInt + val indexCount: UInt + val topology: Int + val triangleCount: UInt + val baseVertex: UInt + val firstVertex: UInt + val vertexCount: UInt + val localAABB: AABB? +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/MeshFilter.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/MeshFilter.kt new file mode 100644 index 00000000..eb760dd8 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/MeshFilter.kt @@ -0,0 +1,5 @@ +package io.github.deficuet.unitykt.classes + +interface MeshFilter: Component { + val mMesh: PPtr +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/MeshRenderer.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/MeshRenderer.kt new file mode 100644 index 00000000..4bd22d9e --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/MeshRenderer.kt @@ -0,0 +1,3 @@ +package io.github.deficuet.unitykt.classes + +interface MeshRenderer: Renderer \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/MonoBehaviour.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/MonoBehaviour.kt new file mode 100644 index 00000000..89904103 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/MonoBehaviour.kt @@ -0,0 +1,6 @@ +package io.github.deficuet.unitykt.classes + +interface MonoBehaviour: Behaviour { + val mScript: PPtr + val mName: String +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/MonoScript.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/MonoScript.kt new file mode 100644 index 00000000..559bad96 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/MonoScript.kt @@ -0,0 +1,7 @@ +package io.github.deficuet.unitykt.classes + +interface MonoScript: NamedObject { + val mClassName: String + val mNameSpace: String + val mAssemblyName: String +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/MovieTexture.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/MovieTexture.kt new file mode 100644 index 00000000..57986d00 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/MovieTexture.kt @@ -0,0 +1,7 @@ +package io.github.deficuet.unitykt.classes + +interface MovieTexture: Texture { + val mLoop: Boolean + val mAudioClip: PPtr + val mMovieData: ByteArray +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/NamedObject.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/NamedObject.kt new file mode 100644 index 00000000..dd1c4d7e --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/NamedObject.kt @@ -0,0 +1,5 @@ +package io.github.deficuet.unitykt.classes + +interface NamedObject: EditorExtension { + val mName: String +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/PPtr.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/PPtr.kt new file mode 100644 index 00000000..a784266d --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/PPtr.kt @@ -0,0 +1,53 @@ +package io.github.deficuet.unitykt.classes + +import io.github.deficuet.unitykt.cast +import io.github.deficuet.unitykt.firstObjectOf +import io.github.deficuet.unitykt.firstOfOrNull +import io.github.deficuet.unitykt.internal.impl.PPtrImpl +import io.github.deficuet.unitykt.internal.impl.getObj +import io.github.deficuet.unitykt.internal.impl.safeGetObj +import io.github.deficuet.unitykt.safeCast + +interface PPtr { + val mFileID: Int + val mPathID: Long + val isNull: Boolean +} + +inline fun PPtr.safeGetObj() = (this as PPtrImpl).safeGetObj() + +inline fun PPtr.getObj(): T = (this as PPtrImpl).getObj() + +inline fun PPtr<*>.safeGetAs(): T? = (this as PPtrImpl).safeGetObj() as? T + +inline fun PPtr<*>.getAs(): T = (this as PPtrImpl).getObj() as T + +inline fun Iterable>.firstObjectOf() = + mapNotNull { it.safeGetObj() }.firstObjectOf() + +inline fun Array>.firstObjectOf() = + mapNotNull { it.safeGetObj() }.firstObjectOf() + +inline fun Iterable>.firstOfOrNull(): O? { + return mapNotNull { it.safeGetObj() }.firstOfOrNull() +} + +inline fun Array>.firstOfOrNull(): O? { + return mapNotNull { it.safeGetObj() }.firstOfOrNull() +} + +inline fun Iterable>.safeFindWithPathID(pathId: Long): T? { + return find { it.mPathID == pathId }?.safeGetObj().safeCast() +} + +inline fun Array>.safeFindWithPathID(pathId: Long): T? { + return find { it.mPathID == pathId }?.safeGetObj().safeCast() +} + +inline fun Iterable>.findWithPathID(pathId: Long): T { + return first { it.mPathID == pathId }.getObj().cast() +} + +inline fun Array>.findWithPathID(pathId: Long): T { + return first { it.mPathID == pathId }.getObj().cast() +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/PlayerSettings.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/PlayerSettings.kt new file mode 100644 index 00000000..72c2de46 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/PlayerSettings.kt @@ -0,0 +1,6 @@ +package io.github.deficuet.unitykt.classes + +interface PlayerSettings { + val companyName: String + val productName: String +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/RectTransform.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/RectTransform.kt new file mode 100644 index 00000000..9d6ae2d9 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/RectTransform.kt @@ -0,0 +1,11 @@ +package io.github.deficuet.unitykt.classes + +import io.github.deficuet.unitykt.math.Vector2 + +interface RectTransform: Transform { + val mAnchorMin: Vector2 + val mAnchorMax: Vector2 + val mAnchoredPosition: Vector2 + val mSizeDelta: Vector2 + val mPivot: Vector2 +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/Renderer.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/Renderer.kt new file mode 100644 index 00000000..cf174faa --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/Renderer.kt @@ -0,0 +1,12 @@ +package io.github.deficuet.unitykt.classes + +interface Renderer: Component { + val mMaterials: Array> + val mStaticBatchInfo: StaticBatchInfo? + val mSubsetIndices: Array +} + +interface StaticBatchInfo { + val firstSubMesh: UShort + val subMeshCount: UShort +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/ResourceManager.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/ResourceManager.kt new file mode 100644 index 00000000..47175144 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/ResourceManager.kt @@ -0,0 +1,5 @@ +package io.github.deficuet.unitykt.classes + +interface ResourceManager: UnityObject { + val mContainer: Map>> +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/RuntimeAnimatorController.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/RuntimeAnimatorController.kt new file mode 100644 index 00000000..1af3de58 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/RuntimeAnimatorController.kt @@ -0,0 +1,3 @@ +package io.github.deficuet.unitykt.classes + +interface RuntimeAnimatorController: NamedObject \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/Shader.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/Shader.kt new file mode 100644 index 00000000..fd9735da --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/Shader.kt @@ -0,0 +1,459 @@ +package io.github.deficuet.unitykt.classes + +import io.github.deficuet.unitykt.enums.NumericalEnum +import io.github.deficuet.unitykt.enums.NumericalEnumCompanion +import io.github.deficuet.unitykt.util.EndianBinaryReader + +interface Shader: NamedObject { + val mScript: ByteArray + val decompressedSize: UInt + val mSubProgramBlob: ByteArray + val mParsedForm: SerializedShader? + val platforms: Array + val offsets: Array> + val compressedLengths: Array> + val decompressedLengths: Array> + val compressedBlob: ByteArray + + fun exportToString(): String +} + +interface ShaderSubProgramEntry { + val offset: Int + val length: Int + val segment: Int +} + +interface ShaderProgram { + val entries: Array + val mSubPrograms: Array + + fun read(reader: EndianBinaryReader, segment: Int) + fun export(shader: String): String +} + +interface ShaderSubProgram { + val mProgramType: ShaderGpuProgramType + val mKeywords: Array + val mLocalKeywords: Array + val mProgramCode: ByteArray + + fun export(): String +} + +interface Hash128 { + val bytes: ByteArray +} + +interface MatrixParameter { + val mNameIndex: Int + val mIndex: Int + val mArraySize: Int + val mType: Byte + val mRowCount: Byte +} + +interface VectorParameter { + val mNameIndex: Int + val mIndex: Int + val mArraySize: Int + val mType: Byte + val mDim: Byte +} + +interface StructParameter { + val mMatrixParams: Array + val mVectorParams: Array +} + +interface SamplerParameter { + val sampler: UInt + val bindPoint: Int +} + +enum class TextureDimension(override val id: Int): NumericalEnum { + Unknown(-1), + None(0), + Any(1), + Tex2D(2), + Tex3D(3), + Cube(4), + Tex2DArray(5), + CubeArray(6); + + companion object: NumericalEnumCompanion(values(), Unknown) +} + +interface SerializedTextureProperty { + val mDefaultName: String + val mTexDim: TextureDimension +} + +enum class SerializedPropertyType(override val id: Int): NumericalEnum { + Color(0), + Vector(1), + Float(2), + Range(3), + Texture(4), + Integer(5); + + companion object: NumericalEnumCompanion(values(), Color) +} + +interface SerializedProperty { + val mName: String + val mDescription: String + val mAttributes: Array + val mType: SerializedPropertyType + val mFlags: UInt + val mDefValue: FloatArray + val mDefTexture: SerializedTextureProperty +} + +interface SerializedProperties { + val mProps: Array +} + +interface SerializedShaderFloatValue { + val value: Float + val name: String +} + +interface SerializedShaderRTBlendState { + val srcBlend: SerializedShaderFloatValue + val destBlend: SerializedShaderFloatValue + val srcBlendAlpha: SerializedShaderFloatValue + val destBlendAlpha: SerializedShaderFloatValue + val blendOp: SerializedShaderFloatValue + val blendOpAlpha: SerializedShaderFloatValue + val colMask: SerializedShaderFloatValue +} + +interface SerializedStencilOp { + val pass: SerializedShaderFloatValue + val fail: SerializedShaderFloatValue + val zFail: SerializedShaderFloatValue + val comp: SerializedShaderFloatValue +} + +interface SerializedShaderVectorValue { + val x: SerializedShaderFloatValue + val y: SerializedShaderFloatValue + val z: SerializedShaderFloatValue + val w: SerializedShaderFloatValue + val name: String +} + +enum class FogMode(override val id: Int): NumericalEnum { + Unknown(-1), + Disabled(0), + Linear(1), + Exp(2), + Exp2(3); + + companion object: NumericalEnumCompanion(values(), Disabled) +} + +interface SerializedTagMap { + val tags: Array> +} + +interface SerializedShaderState { + val mName: String + val rtBlend: Array + val rtSeparateBlend: Boolean + val zClip: SerializedShaderFloatValue? + val zTest: SerializedShaderFloatValue + val zWrite: SerializedShaderFloatValue + val culling: SerializedShaderFloatValue + val conservative: SerializedShaderFloatValue? + val offsetFactor: SerializedShaderFloatValue + val offsetUnits: SerializedShaderFloatValue + val alphaToMask: SerializedShaderFloatValue + val stencilOp: SerializedStencilOp + val stencilOpFront: SerializedStencilOp + val stencilOpBack: SerializedStencilOp + val stencilReadMask: SerializedShaderFloatValue + val stencilWriteMask: SerializedShaderFloatValue + val stencilRef: SerializedShaderFloatValue + val fogStart: SerializedShaderFloatValue + val fogEnd: SerializedShaderFloatValue + val fogDensity: SerializedShaderFloatValue + val fogColor: SerializedShaderVectorValue + val fogMode: FogMode + val gpuProgramID: Int + val mTags: SerializedTagMap + val mLOD: Int + val lighting: Boolean +} + +interface ShaderBindChannel { + val source: Byte + val target: Byte +} + +interface ParserBindChannels { + val mChannels: Array + val mSourceMap: UInt +} + +interface TextureParameter { + val mNameIndex: Int + val mIndex: Int + val mSamplerIndex: Int + val mDim: Byte +} + +interface BufferBinding { + val mNameIndex: Int + val mIndex: Int + val mArraySize: Int +} + +interface ConstantBuffer { + val mNameIndex: Int + val mMatrixParams: Array + val mVectorParams: Array + val mStructParams: Array + val mSize: Int + val mIsPartialCB: Boolean +} + +interface UAVParameter { + val mNameIndex: Int + val mIndex: Int + val mOriginalIndex: Int +} + +enum class ShaderGpuProgramType(override val id: Int): NumericalEnum { + Unknown(0), + GLLegacy(1), + GLES31AEP(2), + GLES31(3), + GLES3(4), + GLES(5), + GLCore32(6), + GLCore41(7), + GLCore43(8), + DX9VertexSM20(9), + DX9VertexSM30(10), + DX9PixelSM20(11), + DX9PixelSM30(12), + DX10Level9Vertex(13), + DX10Level9Pixel(14), + DX11VertexSM40(15), + DX11VertexSM50(16), + DX11PixelSM40(17), + DX11PixelSM50(18), + DX11GeometrySM40(19), + DX11GeometrySM50(20), + DX11HullSM50(21), + DX11DomainSM50(22), + MetalVS(23), + MetalFS(24), + SPIRV(25), + ConsoleVS(26), + ConsoleFS(27), + ConsoleHS(28), + ConsoleDS(29), + ConsoleGS(30), + RayTracing(31), + PS5NGGC(32); + + companion object: NumericalEnumCompanion(values(), Unknown) +} + +interface SerializedProgramParameters { + val mVectorParams: Array + val mMatrixParams: Array + val mTextureParams: Array + val mBufferParams: Array + val mConstantBuffers: Array + val mConstantBufferBindings: Array + val mUAVParams: Array + val mSamplers: Array +} + +interface SerializedSubProgram { + val mBlobIndex: UInt + val mChannels: ParserBindChannels + val mKeywordIndices: Array + val mShaderHardwareTier: Byte + val mGpuProgramType: ShaderGpuProgramType + val mParameters: SerializedProgramParameters? + val mVectorParams: Array + val mMatrixParams: Array + val mTextureParams: Array + val mBufferParams: Array + val mConstantBuffers: Array + val mConstantBufferBindings: Array + val mUAVParams: Array + val mSamplers: Array +} + +interface SerializedProgram { + val mSubPrograms: Array + val mCommonParameters: SerializedProgramParameters? + val mSerializedKeywordStateMask: Array +} + +enum class PassType(override val id: Int): NumericalEnum { + Normal(0), + Use(1), + Grab(2); + + companion object: NumericalEnumCompanion(values(), Normal) +} + +interface SerializedPass { + val mEditorDataHash: Array + val mPlatforms: ByteArray + val mLocalKeywordMask: Array + val mGlobalKeywordMask: Array + val mNameIndices: Map> + val mType: PassType + val mState: SerializedShaderState + val mProgramMask: UInt + val progVertex: SerializedProgram + val progFragment: SerializedProgram + val progGeometry: SerializedProgram + val progHull: SerializedProgram + val progDomain: SerializedProgram + val progRayTracing: SerializedProgram? + val mHasInstancingVariant: Boolean + val mUseName: String + val mName: String + val mTextureName: String + val mTags: SerializedTagMap + val mSerializedKeywordStateMask: Array +} + +interface SerializedSubShader { + val mPasses: Array + val mTags: SerializedTagMap + val mLOD: Int +} + +interface SerializedShaderDependency { + val from: String + val to: String +} + +interface SerializedCustomEditorForRenderPipeline { + val customEditorName: String + val renderPipelineType: String +} + +interface SerializedShader { + val mPropInfo: SerializedProperties + val mSubShaders: Array + val mKeywordNames: Array + val mKeywordFlags: ByteArray + val mName: String + val mCustomEditorName: String + val mFallbackName: String + val mDependencies: Array + val mCustomEditorForRenderPipelines: Array + val mDisableNoSubShadersMessage: Boolean +} + +@Suppress("EnumEntryName") +enum class ShaderCompilerPlatform(override val id: Int, val str: String = "unknown"): NumericalEnum { + None(-1), + GL(0, "openGL"), + D3D9(1, "d3d9"), + Xbox360(2, "xbox360"), + PS3(3, "ps3"), + D3D11(4, "d3d11"), + GLES20(5, "gles"), + NaCl(6, "glesdesktop"), + Flash(7, "flash"), + D3D11_9x(8, "d3d11_9x"), + GLES3Plus(9, "gles3"), + PSP2(10, "psp2"), + PS4(11, "ps4"), + XboxOne(12, "xboxone"), + PSM(13, "psm"), + Metal(14, "metal"), + OpenGLCore(15, "glcore"), + N3DS(16, "n3ds"), + WiiU(17, "wiiu"), + Vulkan(18, "vulkan"), + Switch(19, "switch"), + XboxOneD3D12(20, "xboxone_d3d12"), + GameCoreXboxOne(21, "xboxone"), + GameCoreScarlett(22, "xbox_scarlett"), + PS5(23, "ps5"), + PS5NGGC(24, "ps5_nggc"); + + internal fun checkProgramUsability(programType: ShaderGpuProgramType): Boolean { + return when (this) { + GL -> programType == ShaderGpuProgramType.GLLegacy + D3D9 -> programType in setD3D9 + + Xbox360, PS3, + PSP2, PS4, + XboxOne, N3DS, + WiiU, Switch, + XboxOneD3D12, GameCoreXboxOne, + GameCoreScarlett, PS5 -> programType in setXbox360ToPS5 + + PS5NGGC -> programType == ShaderGpuProgramType.PS5NGGC + D3D11 -> programType in setD3D11 + GLES20 -> programType == ShaderGpuProgramType.GLES + NaCl -> false + Flash -> false + D3D11_9x -> programType in setD3D11_9x + GLES3Plus -> programType in setGLES3Plus + PSM -> false + Metal -> programType in setMetal + OpenGLCore -> programType in setOpenGLCore + Vulkan -> programType == ShaderGpuProgramType.SPIRV + else -> false + } + } + + companion object: NumericalEnumCompanion(values(), None) { + private val setD3D9 = setOf( + ShaderGpuProgramType.DX9VertexSM20, + ShaderGpuProgramType.DX9VertexSM30, + ShaderGpuProgramType.DX9PixelSM20, + ShaderGpuProgramType.DX9PixelSM30 + ) + private val setXbox360ToPS5 = setOf( + ShaderGpuProgramType.ConsoleVS, + ShaderGpuProgramType.ConsoleFS, + ShaderGpuProgramType.ConsoleHS, + ShaderGpuProgramType.ConsoleDS, + ShaderGpuProgramType.ConsoleGS + ) + private val setD3D11 = setOf( + ShaderGpuProgramType.DX11VertexSM40, + ShaderGpuProgramType.DX11VertexSM50, + ShaderGpuProgramType.DX11PixelSM40, + ShaderGpuProgramType.DX11PixelSM50, + ShaderGpuProgramType.DX11GeometrySM40, + ShaderGpuProgramType.DX11GeometrySM50, + ShaderGpuProgramType.DX11HullSM50, + ShaderGpuProgramType.DX11DomainSM50 + ) + private val setD3D11_9x = setOf( + ShaderGpuProgramType.DX10Level9Vertex, + ShaderGpuProgramType.DX10Level9Pixel + ) + private val setGLES3Plus = setOf( + ShaderGpuProgramType.GLES31AEP, + ShaderGpuProgramType.GLES31, + ShaderGpuProgramType.GLES3 + ) + private val setMetal = setOf( + ShaderGpuProgramType.MetalVS, + ShaderGpuProgramType.MetalFS + ) + private val setOpenGLCore = setOf( + ShaderGpuProgramType.GLCore32, + ShaderGpuProgramType.GLCore41, + ShaderGpuProgramType.GLCore43 + ) + } +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/SkinnedMeshRenderer.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/SkinnedMeshRenderer.kt new file mode 100644 index 00000000..24612765 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/SkinnedMeshRenderer.kt @@ -0,0 +1,7 @@ +package io.github.deficuet.unitykt.classes + +interface SkinnedMeshRenderer: Renderer { + val mMesh: PPtr + val mBones: Array> + val mBlendShapeWeights: FloatArray +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/Sprite.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/Sprite.kt new file mode 100644 index 00000000..d97009fa --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/Sprite.kt @@ -0,0 +1,85 @@ +package io.github.deficuet.unitykt.classes + +import io.github.deficuet.unitykt.enums.NumericalEnum +import io.github.deficuet.unitykt.enums.NumericalEnumCompanion +import io.github.deficuet.unitykt.math.* +import java.awt.image.BufferedImage +import java.util.* + +interface Sprite: NamedObject { + val mRect: Rectangle + val mOffset: Vector2 + val mBorder: Vector4 + val mPixelsToUnits: Float + val mPivot: Vector2 + val mExtrude: UInt + val mIsPolygon: Boolean + val mRenderDataKey: Pair + val mAtlasTags: Array + val mSpriteAtlas: PPtr? + val mRD: SpriteRenderData + val mPhysicsShape: Array> + + fun getImage(): BufferedImage? +} + +interface SecondarySpriteTexture { + val texture: PPtr + val name: String +} + +enum class SpritePackingRotation(override val id: UInt): NumericalEnum { + None(0u), + FlipHorizontal(1u), + FlipVertical(2u), + Rotate180(3u), + Rotate90(4u); + + companion object: NumericalEnumCompanion(values(), None) +} + +enum class SpritePackingMode(override val id: UInt): NumericalEnum { + Tight(0u), + Rectangle(1u); + + companion object: NumericalEnumCompanion(values(), Tight) +} + +enum class SpriteMeshType(override val id: UInt): NumericalEnum { + FullRect(0u), + Tight(1u); + + companion object: NumericalEnumCompanion(values(), FullRect) +} + +interface SpriteSettings { + val settingsRaw: UInt + val packed: UInt + val packingMode: SpritePackingMode + val packingRotation: SpritePackingRotation + val meshType: SpriteMeshType +} + +interface SpriteVertex { + val pos: Vector3 + val uv: Vector2 +} + +interface SpriteRenderData { + val texture: PPtr + val alphaTexture: PPtr? + val secondaryTexturesSize: Array + val mSubMeshes: Array + val mIndexBuffer: ByteArray + val mVertexData: VertexData? + val vertices: Array + val indices: Array + val mBindPose: Array + val mSourceSkin: Array + val textureRect: Rectangle + val textureRectOffset: Vector2 + val atlasRectOffset: Vector2 + val settingsRaw: SpriteSettings + val uvTransform: Vector4 + val downScaleMultiplier: Float +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/SpriteAtlas.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/SpriteAtlas.kt new file mode 100644 index 00000000..6b1cef8e --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/SpriteAtlas.kt @@ -0,0 +1,24 @@ +package io.github.deficuet.unitykt.classes + +import io.github.deficuet.unitykt.math.Rectangle +import io.github.deficuet.unitykt.math.Vector2 +import io.github.deficuet.unitykt.math.Vector4 +import java.util.* + +interface SpriteAtlas: NamedObject { + val mPackedSprites: Array> + val mRenderDataMap: Map, SpriteAtlasData> + val mIsVariant: Boolean +} + +interface SpriteAtlasData { + val texture: PPtr + val alphaText: PPtr + val textureRect: Rectangle + val textureRectOffset: Vector2 + val atlasRectOffset: Vector2 + val uvTransform: Vector4 + val downScaleMultiplier: Float + val settingsRaw: SpriteSettings + val secondaryTextures: Array +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/TextAsset.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/TextAsset.kt new file mode 100644 index 00000000..97141b05 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/TextAsset.kt @@ -0,0 +1,9 @@ +package io.github.deficuet.unitykt.classes + +import java.nio.charset.Charset + +interface TextAsset: NamedObject { + val mScript: ByteArray + + fun getText(charset: Charset = Charsets.UTF_8): String +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/Texture.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/Texture.kt new file mode 100644 index 00000000..f0c60a62 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/Texture.kt @@ -0,0 +1,3 @@ +package io.github.deficuet.unitykt.classes + +interface Texture: NamedObject \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/Texture2D.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/Texture2D.kt new file mode 100644 index 00000000..680085a6 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/Texture2D.kt @@ -0,0 +1,111 @@ +package io.github.deficuet.unitykt.classes + +import io.github.deficuet.unitykt.enums.NumericalEnum +import io.github.deficuet.unitykt.enums.NumericalEnumCompanion +import java.awt.image.BufferedImage + +interface Texture2D: Texture { + val mWidth: Int + val mHeight: Int + val mTextureFormat: TextureFormat + val mMipMap: Boolean + val mMipCount: Int + val mTextureSettings: GLTextureSettings + val mStreamData: StreamingInfo? + + fun getDecompressedData(): ByteArray? + + /** + * Usually up-side-down + */ + fun getImage(): BufferedImage? +} + +interface StreamingInfo { + val offset: Long + val size: UInt + val path: String +} + +interface GLTextureSettings { + val mFilterMode: Int + val mAniso: Int + val mMipBias: Float + val mWrapMode: Int +} + +@Suppress("EnumEntryName") +enum class TextureFormat(override val id: Int): NumericalEnum { + Unknown(0), + Alpha8(1), + ARGB4444(2), + RGB24(3), + RGBA32(4), + ARGB32(5), + RGB565(7), + BGR24(8), + R16(9), + DXT1(10), + DXT3(11), + DXT5(12), + RGBA4444(13), + BGRA32(14), + RHalf(15), + RGHalf(16), + RGBAHalf(17), + RFloat(18), + RGFloat(19), + RGBAFloat(20), + YUY2(21), + RGB9e5Float(22), + RGBFloat(23), + BC6H(24), + BC7(25), + BC4(26), + BC5(27), + DXT1Crunched(28), + DXT5Crunched(29), + PVRTC_RGB2(30), + PVRTC_RGBA2(31), + PVRTC_RGB4(32), + PVRTC_RGBA4(33), + ETC_RGB4(34), + ATC_RGB4(35), + ATC_RGBA8(36), + EAC_R(41), + EAC_R_SIGNED(42), + EAC_RG(43), + EAC_RG_SIGNED(44), + ETC2_RGB(45), + ETC2_RGBA1(46), + ETC2_RGBA8(47), + ASTC_RGB_4x4(48), + ASTC_RGB_5x5(49), + ASTC_RGB_6x6(50), + ASTC_RGB_8x8(51), + ASTC_RGB_10x10(52), + ASTC_RGB_12x12(53), + ASTC_RGBA_4x4(54), + ASTC_RGBA_5x5(55), + ASTC_RGBA_6x6(56), + ASTC_RGBA_8x8(57), + ASTC_RGBA_10x10(58), + ASTC_RGBA_12x12(59), + ETC_RGB4_3DS(60), + ETC_RGBA8_3DS(61), + RG16(62), + R8(63), + ETC_RGB4Crunched(64), + ETC2_RGBA8Crunched(65), + ASTC_HDR_4x4(66), + ASTC_HDR_5x5(67), + ASTC_HDR_6x6(68), + ASTC_HDR_8x8(69), + ASTC_HDR_10x10(70), + ASTC_HDR_12x12(71), + RG32(72), + RGB48(73), + RGBA64(74); + + companion object: NumericalEnumCompanion(values(), Unknown) +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/Transform.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/Transform.kt new file mode 100644 index 00000000..ec70569b --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/Transform.kt @@ -0,0 +1,12 @@ +package io.github.deficuet.unitykt.classes + +import io.github.deficuet.unitykt.math.Quaternion +import io.github.deficuet.unitykt.math.Vector3 + +interface Transform: Component { + val mLocalRotation: Quaternion + val mLocalPosition: Vector3 + val mLocalScale: Vector3 + val mChildren: Array> + val mFather: PPtr +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/UnityObject.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/UnityObject.kt new file mode 100644 index 00000000..c6387f0b --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/UnityObject.kt @@ -0,0 +1,32 @@ +package io.github.deficuet.unitykt.classes + +import io.github.deficuet.unitykt.ImportContext +import io.github.deficuet.unitykt.enums.BuildTarget +import io.github.deficuet.unitykt.enums.ClassIDType +import io.github.deficuet.unitykt.internal.file.SerializedType +import org.json.JSONObject + +interface UnityObject { + //region metadata + val context: ImportContext + val type: ClassIDType + val mPathID: Long + val unityVersion: IntArray + val platform: BuildTarget + val serializedType: SerializedType? + //endregion + + val bytes: ByteArray + + /** + * @see [SerializedType.Tree.readTypeString] + */ + fun dump(): String? + + /** + * @see [SerializedType.Tree.readType] + */ + fun toTypeTree(): Map? + fun toTypeTreeJson(): JSONObject? + fun toTypeTreeJsonString(indent: Int = 4): String +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/classes/VideoClip.kt b/src/main/kotlin/io/github/deficuet/unitykt/classes/VideoClip.kt new file mode 100644 index 00000000..297d16f0 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/classes/VideoClip.kt @@ -0,0 +1,29 @@ +package io.github.deficuet.unitykt.classes + +interface VideoClip: NamedObject { + val mOriginalPath: String + val mProxyWidth: UInt + val mProxyHeight: UInt + val mWidth: UInt + val mHeight: UInt + val mPixelAspectRatioNumerator: UInt + val mPixelAspectRatioDenominator: UInt + val mFrameRate: Double + val mFrameCount: ULong + val mFormat: Int + val mAudioChannelCount: Array + val mAudioSampleRate: Array + val mAudioLanguage: Array + val mVideoShaders: Array> + val mExternalResource: StreamedResource + val mHasSplitAlpha: Boolean + val msRGB: Boolean + + fun getRawData(): ByteArray +} + +interface StreamedResource { + val mSource: String + val mOffset: Long + val mSize: Long +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/Animation.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/Animation.kt deleted file mode 100644 index 3be3447f..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/Animation.kt +++ /dev/null @@ -1,15 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.AnimationImpl -import io.github.deficuet.unitykt.file.ObjectInfo -import io.github.deficuet.unitykt.file.SerializedFile -import io.github.deficuet.unitykt.util.ObjectReader - -class Animation private constructor( - private val container: ImplementationContainer -): Behaviour(container) { - internal constructor(assetFile: SerializedFile, info: ObjectInfo): - this(ImplementationContainer(assetFile, info) { AnimationImpl(ObjectReader(assetFile, info)) }) - - val mAnimations: Array> get() = container.impl.mAnimations -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/AnimationClip.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/AnimationClip.kt deleted file mode 100644 index 5486077d..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/AnimationClip.kt +++ /dev/null @@ -1,32 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.* -import io.github.deficuet.unitykt.file.ObjectInfo -import io.github.deficuet.unitykt.file.SerializedFile -import io.github.deficuet.unitykt.util.ObjectReader - -class AnimationClip private constructor( - private val container: ImplementationContainer -): NamedObject(container) { - internal constructor(assetFile: SerializedFile, info: ObjectInfo): - this(ImplementationContainer(assetFile, info) { AnimationClipImpl(ObjectReader(assetFile, info)) }) - - val mAnimationType: AnimationType get() = container.impl.mAnimationType - val mLegacy: Boolean get() = container.impl.mLegacy - val mCompressed: Boolean get() = container.impl.mCompressed - val mUseHighQualityCurve: Boolean get() = container.impl.mUseHighQualityCurve - val mRotationCurves: Array get() = container.impl.mRotationCurves - val mCompressedRotationCurves: Array get() = container.impl.mCompressedRotationCurves - val mEulerCurves: Array get() = container.impl.mEulerCurves - val mPositionCurves: Array get() = container.impl.mPositionCurves - val mScaleCurves: Array get() = container.impl.mScaleCurves - val mFloatCurves: Array get() = container.impl.mFloatCurves - val mPPtrCurves: Array get() = container.impl.mPPtrCurves - val mSampleRate: Float get() = container.impl.mSampleRate - val mWrapMode: Int get() = container.impl.mWrapMode - val mBounds: AABB? get() = container.impl.mBounds - val mMuscleClipSize: UInt get() = container.impl.mMuscleClipSize - val mMuscleClip: ClipMuscleConstant? get() = container.impl.mMuscleClip - val mClipBindingConstant: AnimationClipBindingConstant? get() = container.impl.mClipBindingConstant - val mEvents: Array get() = container.impl.mEvents -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/Animator.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/Animator.kt deleted file mode 100644 index a0eb3492..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/Animator.kt +++ /dev/null @@ -1,17 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.AnimatorImpl -import io.github.deficuet.unitykt.file.ObjectInfo -import io.github.deficuet.unitykt.file.SerializedFile -import io.github.deficuet.unitykt.util.ObjectReader - -class Animator private constructor( - private val container: ImplementationContainer -): Behaviour(container) { - internal constructor(assetFile: SerializedFile, info: ObjectInfo): - this(ImplementationContainer(assetFile, info) { AnimatorImpl(ObjectReader(assetFile, info)) }) - - val mAvatar: PPtr get() = container.impl.mAvatar - val mController: PPtr get() = container.impl.mController - val mHasTransformHierarchy: Boolean get() = container.impl.mHasTransformHierarchy -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/AnimatorController.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/AnimatorController.kt deleted file mode 100644 index eda077c7..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/AnimatorController.kt +++ /dev/null @@ -1,15 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.AnimatorControllerImpl -import io.github.deficuet.unitykt.file.ObjectInfo -import io.github.deficuet.unitykt.file.SerializedFile -import io.github.deficuet.unitykt.util.ObjectReader - -class AnimatorController private constructor( - private val container: ImplementationContainer -): RuntimeAnimatorController(container) { - internal constructor(assetFile: SerializedFile, info: ObjectInfo): - this(ImplementationContainer(assetFile, info) { AnimatorControllerImpl(ObjectReader(assetFile, info)) }) - - val mAnimationClips: Array> get() = container.impl.mAnimationClips -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/AnimatorOverrideController.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/AnimatorOverrideController.kt deleted file mode 100644 index 00ea8523..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/AnimatorOverrideController.kt +++ /dev/null @@ -1,17 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.AnimationClipOverride -import io.github.deficuet.unitykt.dataImpl.AnimatorOverrideControllerImpl -import io.github.deficuet.unitykt.file.ObjectInfo -import io.github.deficuet.unitykt.file.SerializedFile -import io.github.deficuet.unitykt.util.ObjectReader - -class AnimatorOverrideController private constructor( - private val container: ImplementationContainer -): RuntimeAnimatorController(container) { - internal constructor(assetFile: SerializedFile, info: ObjectInfo): - this(ImplementationContainer(assetFile, info) { AnimatorOverrideControllerImpl(ObjectReader(assetFile, info)) }) - - val mController: PPtr get() = container.impl.mController - val mClips: Array get() = container.impl.mClips -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/AssetBundle.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/AssetBundle.kt deleted file mode 100644 index ae217389..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/AssetBundle.kt +++ /dev/null @@ -1,24 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.AssetBundleImpl -import io.github.deficuet.unitykt.dataImpl.AssetInfo -import io.github.deficuet.unitykt.file.ObjectInfo -import io.github.deficuet.unitykt.file.SerializedFile -import io.github.deficuet.unitykt.util.ObjectReader - -class AssetBundle private constructor( - private val container: ImplementationContainer -): NamedObject(container) { - internal constructor(assetFile: SerializedFile, info: ObjectInfo): - this(ImplementationContainer(assetFile, info) { AssetBundleImpl(ObjectReader(assetFile, info)) }) - - val mPreloadTable: Array> get() = container.impl.mPreloadTable - val mContainer: Array> get() = container.impl.mContainer - val mMainAsset: AssetInfo get() = container.impl.mMainAsset - val mRuntimeCompatibility: UInt get() = container.impl.mRuntimeCompatibility - val mAssetBundleName: String get() = container.impl.mAssetBundleName - val mDependencies: Array get() = container.impl.mDependencies - val mIsStreamedSceneAssetBundle: Boolean get() = container.impl.mIsStreamedSceneAssetBundle - val mExplicitDataLayout: Int get() = container.impl.mExplicitDataLayout - val mPathFlags: Int get() = container.impl.mPathFlags -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/AudioClip.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/AudioClip.kt deleted file mode 100644 index 321adf88..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/AudioClip.kt +++ /dev/null @@ -1,38 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.AudioClipImpl -import io.github.deficuet.unitykt.dataImpl.AudioCompressionFormat -import io.github.deficuet.unitykt.dataImpl.FMODSoundType -import io.github.deficuet.unitykt.file.ObjectInfo -import io.github.deficuet.unitykt.file.SerializedFile -import io.github.deficuet.unitykt.util.ObjectReader -import io.github.deficuet.unitykt.util.ResourceReader - -class AudioClip private constructor( - private val container: ImplementationContainer -): NamedObject(container) { - internal constructor(assetFile: SerializedFile, info: ObjectInfo): - this(ImplementationContainer(assetFile, info) { AudioClipImpl(ObjectReader(assetFile, info)) }) - - val mFormat: Int get() = container.impl.mFormat - val mType: FMODSoundType get() = container.impl.mType - val m3D: Boolean get() = container.impl.m3D - val mUseHardware: Boolean get() = container.impl.mUseHardware - - val mLoadType: Int get() = container.impl.mLoadType - val mChannels: Int get() = container.impl.mChannels - val mFrequency: Int get() = container.impl.mFrequency - val mBitsPerSample: Int get() = container.impl.mBitsPerSample - val mLength: Float get() = container.impl.mLength - val mIsTrackerFormat: Boolean get() = container.impl.mIsTrackerFormat - val mSubSoundIndex: Int get() = container.impl.mSubSoundIndex - val mPreloadAudioData: Boolean get() = container.impl.mPreloadAudioData - val mLoadInBackground: Boolean get() = container.impl.mLoadInBackground - val mLegacy3D: Boolean get() = container.impl.mLegacy3D - val mCompressionFormat: AudioCompressionFormat get() = container.impl.mCompressionFormat - - val mSource: String get() = container.impl.mSource - val mOffset: Long get() = container.impl.mOffset - val mSize: Long get() = container.impl.mSize - val mAudioData: ResourceReader get() = container.impl.mAudioData -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/Avatar.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/Avatar.kt deleted file mode 100644 index 4b21a2ed..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/Avatar.kt +++ /dev/null @@ -1,18 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.AvatarConstant -import io.github.deficuet.unitykt.dataImpl.AvatarImpl -import io.github.deficuet.unitykt.file.ObjectInfo -import io.github.deficuet.unitykt.file.SerializedFile -import io.github.deficuet.unitykt.util.ObjectReader - -class Avatar private constructor( - private val container: ImplementationContainer -): NamedObject(container) { - internal constructor(assetFile: SerializedFile, info: ObjectInfo): - this(ImplementationContainer(assetFile, info) { AvatarImpl(ObjectReader(assetFile, info)) }) - - val mAvatarSize: UInt get() = container.impl.mAvatarSize - val mAvatar: AvatarConstant get() = container.impl.mAvatar - val mTOS: Array> get() = container.impl.mTOS -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/Behaviour.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/Behaviour.kt deleted file mode 100644 index c2742a9c..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/Behaviour.kt +++ /dev/null @@ -1,9 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.BehaviourImpl - -abstract class Behaviour internal constructor( - private val container: ImplementationContainer -): Component(container) { - val mEnabled: UByte get() = container.impl.mEnabled -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/BuildSettings.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/BuildSettings.kt deleted file mode 100644 index 6cdd595f..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/BuildSettings.kt +++ /dev/null @@ -1,15 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.BuildSettingsImpl -import io.github.deficuet.unitykt.file.ObjectInfo -import io.github.deficuet.unitykt.file.SerializedFile -import io.github.deficuet.unitykt.util.ObjectReader - -class BuildSettings private constructor( - private val container: ImplementationContainer -): Object(container) { - internal constructor(assetFile: SerializedFile, info: ObjectInfo): - this(ImplementationContainer(assetFile, info) { BuildSettingsImpl(ObjectReader(assetFile, info)) }) - - val mVersion: String get() = container.impl.mVersion -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/Canvas.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/Canvas.kt deleted file mode 100644 index 61773de5..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/Canvas.kt +++ /dev/null @@ -1,29 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.CanvasImpl -import io.github.deficuet.unitykt.file.ObjectInfo -import io.github.deficuet.unitykt.file.SerializedFile -import io.github.deficuet.unitykt.util.ObjectReader - -/** - * Errors may occur for bundles with version before `2018.4.34f1` - */ -class Canvas private constructor( - private val container: ImplementationContainer -): Behaviour(container) { - internal constructor(assetFile: SerializedFile, info: ObjectInfo): - this(ImplementationContainer(assetFile, info) { CanvasImpl(ObjectReader(assetFile, info)) }) - - val mRenderMode: Int get() = container.impl.mRenderMode - val mCamera: PPtr get() = container.impl.mCamera - val mPlaneDistance: Float get() = container.impl.mPlaneDistance - val mPixelPerfect: Boolean get() = container.impl.mPixelPerfect - val mReceivesEvent: Boolean get() = container.impl.mReceivesEvent - val mOverrideSorting: Boolean get() = container.impl.mOverrideSorting - val mOverridePixelPerfect: Boolean get() = container.impl.mOverridePixelPerfect - val mSortingBucketNormalizedSize: Float get() = container.impl.mSortingBucketNormalizedSize - val mAdditionalShaderChannelsFlag: Int get() = container.impl.mAdditionalShaderChannelsFlag - val mSortingLayerID: Int get() = container.impl.mSortingLayerID - val mSortingOrder: Short get() = container.impl.mSortingOrder - val mTargetDisplay: Byte get() = container.impl.mTargetDisplay -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/Component.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/Component.kt deleted file mode 100644 index ec179ced..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/Component.kt +++ /dev/null @@ -1,9 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.ComponentImpl - -abstract class Component internal constructor( - private val container: ImplementationContainer -): EditorExtension(container) { - val mGameObject: PPtr get() = container.impl.mGameObject -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/EditorExtension.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/EditorExtension.kt deleted file mode 100644 index c49a8baa..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/EditorExtension.kt +++ /dev/null @@ -1,7 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.EditorExtensionImpl - -abstract class EditorExtension internal constructor( - container: ImplementationContainer -): Object(container) \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/Font.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/Font.kt deleted file mode 100644 index 869aaeeb..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/Font.kt +++ /dev/null @@ -1,15 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.FontImpl -import io.github.deficuet.unitykt.file.ObjectInfo -import io.github.deficuet.unitykt.file.SerializedFile -import io.github.deficuet.unitykt.util.ObjectReader - -class Font private constructor( - private val container: ImplementationContainer -): NamedObject(container) { - internal constructor(assetFile: SerializedFile, info: ObjectInfo): - this(ImplementationContainer(assetFile, info) { FontImpl(ObjectReader(assetFile, info)) }) - - val mFontData: ByteArray get() = container.impl.mFontData -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/GameObject.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/GameObject.kt deleted file mode 100644 index 2affe067..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/GameObject.kt +++ /dev/null @@ -1,22 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.GameObjectImpl -import io.github.deficuet.unitykt.file.ObjectInfo -import io.github.deficuet.unitykt.file.SerializedFile -import io.github.deficuet.unitykt.util.ObjectReader - -class GameObject private constructor( - private val container: ImplementationContainer -): EditorExtension(container) { - internal constructor(assetFile: SerializedFile, info: ObjectInfo): - this(ImplementationContainer(assetFile, info) { GameObjectImpl(ObjectReader(assetFile, info)) }) - - val mComponents: Array> get() = container.impl.mComponents - val mName: String get() = container.impl.mName - val mTransform: Array get() = container.impl.mTransform - val mMeshRenderer: Array get() = container.impl.mMeshRenderer - val mMeshFilter: Array get() = container.impl.mMeshFilter - val mSkinnedMeshRenderer: Array get() = container.impl.mSkinnedMeshRenderer - val mAnimator: Array get() = container.impl.mAnimator - val mAnimation: Array get() = container.impl.mAnimation -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/ImplementationContainer.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/ImplementationContainer.kt deleted file mode 100644 index 2edbd23d..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/ImplementationContainer.kt +++ /dev/null @@ -1,13 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.ObjectImpl -import io.github.deficuet.unitykt.file.ObjectInfo -import io.github.deficuet.unitykt.file.SerializedFile - -class ImplementationContainer internal constructor( - internal val assetFile: SerializedFile, - internal val info: ObjectInfo, - implConstructor: () -> T -) { - val impl: T by lazy(implConstructor) -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/Material.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/Material.kt deleted file mode 100644 index 5f3bbd9e..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/Material.kt +++ /dev/null @@ -1,17 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.MaterialImpl -import io.github.deficuet.unitykt.dataImpl.UnityPropertySheet -import io.github.deficuet.unitykt.file.ObjectInfo -import io.github.deficuet.unitykt.file.SerializedFile -import io.github.deficuet.unitykt.util.ObjectReader - -class Material private constructor( - private val container: ImplementationContainer -): NamedObject(container) { - internal constructor(assetFile: SerializedFile, info: ObjectInfo): - this(ImplementationContainer(assetFile, info) { MaterialImpl(ObjectReader(assetFile, info)) }) - - val mShader: PPtr get() = container.impl.mShader - val mSavedProperties: UnityPropertySheet get() = container.impl.mSavedProperties -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/Mesh.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/Mesh.kt deleted file mode 100644 index 9d21e2c3..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/Mesh.kt +++ /dev/null @@ -1,64 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.BlendShapeData -import io.github.deficuet.unitykt.dataImpl.BoneWeights4 -import io.github.deficuet.unitykt.dataImpl.MeshImpl -import io.github.deficuet.unitykt.dataImpl.SubMash -import io.github.deficuet.unitykt.file.ObjectInfo -import io.github.deficuet.unitykt.file.SerializedFile -import io.github.deficuet.unitykt.math.Matrix4x4 -import io.github.deficuet.unitykt.math.Vector2 -import io.github.deficuet.unitykt.math.Vector3 -import io.github.deficuet.unitykt.util.ObjectReader - -class Mesh private constructor( - private val container: ImplementationContainer -): NamedObject(container) { - internal constructor(assetFile: SerializedFile, info: ObjectInfo): - this(ImplementationContainer(assetFile, info) { MeshImpl(ObjectReader(assetFile, info)) }) - - val mSubMeshes: Array get() = container.impl.mSubMeshes - val mShapes: BlendShapeData? get() = container.impl.mShapes - val mIndices: Array get() = container.impl.mIndices - val mBindPose: Array get() = container.impl.mBindPose - val mBoneNameHashes: Array get() = container.impl.mBoneNameHashes - val mVertexCount: Int get() = container.impl.mVertexCount - val mVertices: FloatArray get() = container.impl.mVertices - val mSkin: Array get() = container.impl.mSkin - val mNormals: FloatArray get() = container.impl.mNormals - val mColors: FloatArray get() = container.impl.mColors - val mUV0: FloatArray get() = container.impl.mUV0 - val mUV1: FloatArray get() = container.impl.mUV1 - val mUV2: FloatArray get() = container.impl.mUV2 - val mUV3: FloatArray get() = container.impl.mUV3 - val mUV4: FloatArray get() = container.impl.mUV4 - val mUV5: FloatArray get() = container.impl.mUV5 - val mUV6: FloatArray get() = container.impl.mUV6 - val mUV7: FloatArray get() = container.impl.mUV7 - val mTangents: FloatArray get() = container.impl.mTangents - - /** - * Same content to the export .obj file. - */ - val exportString: String get() = container.impl.exportString - - /** - * The data of lines start with "v" - */ - val exportVertices: Array get() = container.impl.exportVertices - - /** - * The data of lines start with "vt" - */ - val exportUV: Array get() = container.impl.exportUV - - /** - * The data of lines start with "vn" - */ - val exportNormals: Array get() = container.impl.exportNormals - - /** - * The data of lines start with "f" - */ - val exportFaces: Array> get() = container.impl.exportFaces -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/MeshFilter.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/MeshFilter.kt deleted file mode 100644 index 4f41e752..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/MeshFilter.kt +++ /dev/null @@ -1,15 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.MeshFilterImpl -import io.github.deficuet.unitykt.file.ObjectInfo -import io.github.deficuet.unitykt.file.SerializedFile -import io.github.deficuet.unitykt.util.ObjectReader - -class MeshFilter private constructor( - private val container: ImplementationContainer -): Component(container) { - internal constructor(assetFile: SerializedFile, info: ObjectInfo): - this(ImplementationContainer(assetFile, info) { MeshFilterImpl(ObjectReader(assetFile, info)) }) - - val mMesh: PPtr get() = container.impl.mMesh -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/MeshRenderer.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/MeshRenderer.kt deleted file mode 100644 index 5dfc6e04..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/MeshRenderer.kt +++ /dev/null @@ -1,13 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.MeshRendererImpl -import io.github.deficuet.unitykt.file.ObjectInfo -import io.github.deficuet.unitykt.file.SerializedFile -import io.github.deficuet.unitykt.util.ObjectReader - -class MeshRenderer private constructor( - container: ImplementationContainer -): Renderer(container) { - internal constructor(assetFile: SerializedFile, info: ObjectInfo): - this(ImplementationContainer(assetFile, info) { MeshRendererImpl(ObjectReader(assetFile, info)) }) -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/MonoBehaviour.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/MonoBehaviour.kt deleted file mode 100644 index 48e29191..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/MonoBehaviour.kt +++ /dev/null @@ -1,17 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.MonoBehaviourImpl -import io.github.deficuet.unitykt.file.ObjectInfo -import io.github.deficuet.unitykt.file.SerializedFile -import io.github.deficuet.unitykt.util.ObjectReader -import org.json.JSONObject - -class MonoBehaviour private constructor( - private val container: ImplementationContainer -): Behaviour(container) { - internal constructor(assetFile: SerializedFile, info: ObjectInfo): - this(ImplementationContainer(assetFile, info) { MonoBehaviourImpl(ObjectReader(assetFile, info)) }) - - val mScript: PPtr get() = container.impl.mScript - val mName: String get() = container.impl.mName -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/MonoScript.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/MonoScript.kt deleted file mode 100644 index 7ae7367c..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/MonoScript.kt +++ /dev/null @@ -1,17 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.MonoScriptImpl -import io.github.deficuet.unitykt.file.ObjectInfo -import io.github.deficuet.unitykt.file.SerializedFile -import io.github.deficuet.unitykt.util.ObjectReader - -class MonoScript private constructor( - private val container: ImplementationContainer -): NamedObject(container) { - internal constructor(assetFile: SerializedFile, info: ObjectInfo): - this(ImplementationContainer(assetFile, info) { MonoScriptImpl(ObjectReader(assetFile, info)) }) - - val mClassName: String get() = container.impl.mClassName - val mNameSpace: String get() = container.impl.mNameSpace - val mAssemblyName: String get() = container.impl.mAssemblyName -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/MovieTexture.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/MovieTexture.kt deleted file mode 100644 index a1e6b4b0..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/MovieTexture.kt +++ /dev/null @@ -1,16 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.MovieTextureImpl -import io.github.deficuet.unitykt.file.ObjectInfo -import io.github.deficuet.unitykt.file.SerializedFile -import io.github.deficuet.unitykt.util.ObjectReader - -class MovieTexture private constructor( - private val container: ImplementationContainer -): Texture(container) { - internal constructor(assetFile: SerializedFile, info: ObjectInfo): - this(ImplementationContainer(assetFile, info) { MovieTextureImpl(ObjectReader(assetFile, info)) }) - - val mMovieData: ByteArray get() = container.impl.mMovieData - val mAudioClip: PPtr get() = container.impl.mAudioClip -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/NamedObject.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/NamedObject.kt deleted file mode 100644 index 8fd523b8..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/NamedObject.kt +++ /dev/null @@ -1,9 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.NamedObjectImpl - -abstract class NamedObject internal constructor( - private val container: ImplementationContainer -): EditorExtension(container) { - val mName: String get() = container.impl.mName -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/Object.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/Object.kt deleted file mode 100644 index 5b4fab4d..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/Object.kt +++ /dev/null @@ -1,34 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.ObjectImpl -import io.github.deficuet.unitykt.file.* -import io.github.deficuet.unitykt.util.ObjectReader -import org.json.JSONObject - -open class Object internal constructor(private val container: ImplementationContainer) { - internal constructor(assetFile: SerializedFile, info: ObjectInfo): - this(ImplementationContainer(assetFile, info) { ObjectImpl(ObjectReader(assetFile, info)) }) - - val assetFile: SerializedFile = container.assetFile - val type: ClassIDType = container.info.type - val mPathID: Long = container.info.mPathID - val unityVersion: IntArray = container.assetFile.version - val byteSize: UInt = container.info.byteSize - val platform: BuildTarget = assetFile.targetPlatform - val serializedType: SerializedType? = container.info.serializedType - - val bytes: ByteArray get() = container.impl.bytes - - /** - * @see [SerializedType.Tree.readTypeString] - */ - fun dump() = container.impl.dump() - - /** - * @see [SerializedType.Tree.readType] - */ - fun toType() = container.impl.toType() - - val typeTreeJson: JSONObject? get() = container.impl.typeTreeJson - val typeTreeJsonString: String get() = container.impl.typeTreeJsonString -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/PPtr.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/PPtr.kt deleted file mode 100644 index a7972605..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/PPtr.kt +++ /dev/null @@ -1,85 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.ImportContext -import io.github.deficuet.unitykt.dataImpl.ObjectImpl -import io.github.deficuet.unitykt.file.FormatVersion -import io.github.deficuet.unitykt.file.SerializedFile -import io.github.deficuet.unitykt.util.ObjectReader -import io.github.deficuet.unitykt.util.containsIgnoreCase -import io.github.deficuet.unitykt.util.listFiles -import io.github.deficuet.unitykt.util.tryGet -import java.io.File - -class PPtr internal constructor(reader: ObjectReader) { - var mFileID = reader.readInt() - internal set - var mPathID = with(reader) { if (formatVersion < FormatVersion.Unknown_14) readInt().toLong() else readLong() } - internal set - val isNull = mPathID == 0L || mFileID < 0 - val assetFile = reader.assetFile - - /** - * @see io.github.deficuet.unitykt.safeGetObj - */ - @PublishedApi internal var obj: @UnsafeVariance T? = null - - @PublishedApi internal fun getManager(): SerializedFile? { - return if (mFileID == 0) { - assetFile - } else if (mFileID > 0 && mFileID - 1 < assetFile.externals.size) { - val parent = assetFile.bundleParent - val manager = assetFile.root.manager - val name = assetFile.externals[mFileID - 1].name - if (parent !is ImportContext) { - (parent.files.tryGet(name) as? SerializedFile).let { - if (it == null) { - val path = parent.bundleParent.root.directory - if (path.isNotEmpty()) { - val actualName = path.listFiles().containsIgnoreCase(name) - if (actualName != null) { - val new = ImportContext("$path/${actualName}", manager) - new.files.getValue(actualName) as SerializedFile - } else null - } else null - } else it - } - } else { - manager.assetFiles.tryGet(name).let { - if (it == null) { - val new = if (File("${parent.directory}/$name").exists()) { - ImportContext("${parent.directory}/$name", manager) - } else if (File("${parent.directory}/${name.uppercase()}").exists()) { - ImportContext("${parent.directory}/${name.uppercase()}", manager) - } else null - new?.files?.tryGet(name)!!.let { externalFile -> - if (externalFile is SerializedFile) { - externalFile - } else null - } - } else it - } - } - } else { null } - } - - internal fun setObjInfo(impl: ObjectImpl) { - val name = impl.assetFile.name - if (name.contentEquals(assetFile.name)) { - mFileID = 0 - } else { - mFileID = assetFile.externals.indexOfFirst { it.name.contentEquals(name) } - if (mFileID == -1) { - (assetFile.externals as MutableList).add( - SerializedFile.FileIdentifier( - kotlin.byteArrayOf(), 0, impl.assetFile.name - ) - ) - mFileID = assetFile.externals.size - } else { - mFileID += 1 - } - } - mPathID = impl.mPathID - obj = null - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/PlayerSetting.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/PlayerSetting.kt deleted file mode 100644 index 6a65dea8..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/PlayerSetting.kt +++ /dev/null @@ -1,16 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.PlayerSettingImpl -import io.github.deficuet.unitykt.file.ObjectInfo -import io.github.deficuet.unitykt.file.SerializedFile -import io.github.deficuet.unitykt.util.ObjectReader - -class PlayerSetting private constructor( - private val container: ImplementationContainer -): Object(container) { - internal constructor(assetFile: SerializedFile, info: ObjectInfo): - this(ImplementationContainer(assetFile, info) { PlayerSettingImpl(ObjectReader(assetFile, info)) }) - - val companyName: String get() = container.impl.companyName - val productName: String get() = container.impl.productName -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/RectTransform.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/RectTransform.kt deleted file mode 100644 index d13866b0..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/RectTransform.kt +++ /dev/null @@ -1,20 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.RectTransformImpl -import io.github.deficuet.unitykt.file.ObjectInfo -import io.github.deficuet.unitykt.file.SerializedFile -import io.github.deficuet.unitykt.math.Vector2 -import io.github.deficuet.unitykt.util.ObjectReader - -class RectTransform private constructor( - private val container: ImplementationContainer -): Transform(container) { - internal constructor(assetFile: SerializedFile, info: ObjectInfo): - this(ImplementationContainer(assetFile, info) { RectTransformImpl(ObjectReader(assetFile, info)) }) - - val mAnchorMin: Vector2 get() = container.impl.mAnchorMin - val mAnchorMax: Vector2 get() = container.impl.mAnchorMax - val mAnchoredPosition: Vector2 get() = container.impl.mAnchoredPosition - val mSizeDelta: Vector2 get() = container.impl.mSizeDelta - val mPivot: Vector2 get() = container.impl.mPivot -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/Renderer.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/Renderer.kt deleted file mode 100644 index 25addd13..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/Renderer.kt +++ /dev/null @@ -1,12 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.RendererImpl -import io.github.deficuet.unitykt.dataImpl.StaticBatchInfo - -abstract class Renderer internal constructor( - private val container: ImplementationContainer -): Component(container) { - val mMaterials: Array> get() = container.impl.mMaterials - val mStaticBatchInfo: StaticBatchInfo? get() = container.impl.mStaticBatchInfo - val mSubsetIndices: Array get() = container.impl.mSubsetIndices -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/ResourceManager.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/ResourceManager.kt deleted file mode 100644 index ff0c24b9..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/ResourceManager.kt +++ /dev/null @@ -1,15 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.ResourceManagerImpl -import io.github.deficuet.unitykt.file.ObjectInfo -import io.github.deficuet.unitykt.file.SerializedFile -import io.github.deficuet.unitykt.util.ObjectReader - -class ResourceManager private constructor( - private val container: ImplementationContainer -): Object(container) { - internal constructor(assetFile: SerializedFile, info: ObjectInfo): - this(ImplementationContainer(assetFile, info) { ResourceManagerImpl(ObjectReader(assetFile, info)) }) - - val mContainer: Array>> get() = container.impl.mContainer -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/RuntimeAnimatorController.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/RuntimeAnimatorController.kt deleted file mode 100644 index 930fd052..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/RuntimeAnimatorController.kt +++ /dev/null @@ -1,7 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.RuntimeAnimatorControllerImpl - -abstract class RuntimeAnimatorController internal constructor( - container: ImplementationContainer -): NamedObject(container) \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/Shader.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/Shader.kt deleted file mode 100644 index 96fb38db..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/Shader.kt +++ /dev/null @@ -1,27 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.SerializedShader -import io.github.deficuet.unitykt.dataImpl.ShaderCompilerPlatform -import io.github.deficuet.unitykt.dataImpl.ShaderImpl -import io.github.deficuet.unitykt.file.ObjectInfo -import io.github.deficuet.unitykt.file.SerializedFile -import io.github.deficuet.unitykt.util.ObjectReader - -class Shader private constructor( - private val container: ImplementationContainer -): NamedObject(container) { - internal constructor(assetFile: SerializedFile, info: ObjectInfo): - this(ImplementationContainer(assetFile, info) { ShaderImpl(ObjectReader(assetFile, info)) }) - - val mScript: ByteArray get() = container.impl.mScript - val decompressedSize: UInt get() = container.impl.decompressedSize - val mSubProgramBlob: ByteArray get() = container.impl.mSubProgramBlob - val mParsedForm: SerializedShader? get() = container.impl.mParsedForm - val platforms: Array get() = container.impl.platforms - val offsets: Array> get() = container.impl.offsets - val compressedLengths: Array> get() = container.impl.compressedLengths - val decompressedLengths: Array> get() = container.impl.decompressedLengths - val compressedBlob: ByteArray get() = container.impl.compressedBlob - - val exportString: String get() = container.impl.exportString -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/SkinnedMeshRenderer.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/SkinnedMeshRenderer.kt deleted file mode 100644 index 016c3398..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/SkinnedMeshRenderer.kt +++ /dev/null @@ -1,17 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.SkinnedMeshRendererImpl -import io.github.deficuet.unitykt.file.ObjectInfo -import io.github.deficuet.unitykt.file.SerializedFile -import io.github.deficuet.unitykt.util.ObjectReader - -class SkinnedMeshRenderer private constructor( - private val container: ImplementationContainer -): Renderer(container) { - internal constructor(assetFile: SerializedFile, info: ObjectInfo): - this(ImplementationContainer(assetFile, info) { SkinnedMeshRendererImpl(ObjectReader(assetFile, info)) }) - - val mMesh: PPtr get() = container.impl.mMesh - val mBones: Array> get() = container.impl.mBones - val mBlendShapeWeights: FloatArray get() = container.impl.mBlendShapeWeights -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/Sprite.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/Sprite.kt deleted file mode 100644 index d128715a..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/Sprite.kt +++ /dev/null @@ -1,30 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.SpriteImpl -import io.github.deficuet.unitykt.dataImpl.SpriteRenderData -import io.github.deficuet.unitykt.file.ObjectInfo -import io.github.deficuet.unitykt.file.SerializedFile -import io.github.deficuet.unitykt.math.Rectangle -import io.github.deficuet.unitykt.math.Vector2 -import io.github.deficuet.unitykt.math.Vector4 -import io.github.deficuet.unitykt.util.ObjectReader - -class Sprite private constructor( - private val container: ImplementationContainer -): NamedObject(container) { - internal constructor(assetFile: SerializedFile, info: ObjectInfo): - this(ImplementationContainer(assetFile, info) { SpriteImpl(ObjectReader(assetFile, info)) }) - - val mRect: Rectangle get() = container.impl.mRect - val mOffset: Vector2 get() = container.impl.mOffset - val mBorder: Vector4 get() = container.impl.mBorder - val mPixelsToUnits: Float get() = container.impl.mPixelsToUnits - val mPivot: Vector2 get() = container.impl.mPivot - val mExtrude: UInt get() = container.impl.mExtrude - val mIsPolygon: Boolean get() = container.impl.mIsPolygon - val mRenderDataKey: Map get() = container.impl.mRenderDataKey - val mAtlasTags: Array get() = container.impl.mAtlasTags - val mSpriteAtlas: PPtr? get() = container.impl.mSpriteAtlas - val mRD: SpriteRenderData get() = container.impl.mRD - val mPhysicsShape: Array> get() = container.impl.mPhysicsShape -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/SpriteAtlas.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/SpriteAtlas.kt deleted file mode 100644 index 2c9dd573..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/SpriteAtlas.kt +++ /dev/null @@ -1,18 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.SpriteAtlasData -import io.github.deficuet.unitykt.dataImpl.SpriteAtlasImpl -import io.github.deficuet.unitykt.file.ObjectInfo -import io.github.deficuet.unitykt.file.SerializedFile -import io.github.deficuet.unitykt.util.ObjectReader - -class SpriteAtlas private constructor( - private val container: ImplementationContainer -): NamedObject(container) { - internal constructor(assetFile: SerializedFile, info: ObjectInfo): - this(ImplementationContainer(assetFile, info) { SpriteAtlasImpl(ObjectReader(assetFile, info)) }) - - val mPackedSprites: Array> get() = container.impl.mPackedSprites - val mRenderDataMap: Map, SpriteAtlasData> get() = container.impl.mRenderDataMap - val mIsVariant: Boolean get() = container.impl.mIsVariant -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/TextAsset.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/TextAsset.kt deleted file mode 100644 index 895e0ba7..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/TextAsset.kt +++ /dev/null @@ -1,19 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.TextAssetImpl -import io.github.deficuet.unitykt.file.ObjectInfo -import io.github.deficuet.unitykt.file.SerializedFile -import io.github.deficuet.unitykt.util.ObjectReader -import io.github.deficuet.unitykt.util.decodeToString -import java.nio.charset.Charset - -class TextAsset private constructor( - private val container: ImplementationContainer -): NamedObject(container) { - internal constructor(assetFile: SerializedFile, info: ObjectInfo): - this(ImplementationContainer(assetFile, info) { TextAssetImpl(ObjectReader(assetFile, info)) }) - - val mScript: ByteArray get() = container.impl.mScript - - fun text(charset: Charset = Charsets.UTF_8) = mScript.decodeToString(charset) -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/Texture.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/Texture.kt deleted file mode 100644 index c8d7c55c..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/Texture.kt +++ /dev/null @@ -1,7 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.TextureImpl - -abstract class Texture internal constructor( - container: ImplementationContainer -): NamedObject(container) \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/Texture2D.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/Texture2D.kt deleted file mode 100644 index bf39724f..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/Texture2D.kt +++ /dev/null @@ -1,34 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.GLTextureSettings -import io.github.deficuet.unitykt.dataImpl.StreamingInfo -import io.github.deficuet.unitykt.dataImpl.Texture2DImpl -import io.github.deficuet.unitykt.dataImpl.TextureFormat -import io.github.deficuet.unitykt.file.ObjectInfo -import io.github.deficuet.unitykt.file.SerializedFile -import io.github.deficuet.unitykt.util.ObjectReader -import io.github.deficuet.unitykt.util.ResourceReader -import java.awt.image.BufferedImage - -class Texture2D private constructor( - private val container: ImplementationContainer -): Texture(container) { - internal constructor(assetFile: SerializedFile, info: ObjectInfo): - this(ImplementationContainer(assetFile, info) { Texture2DImpl(ObjectReader(assetFile, info)) }) - - val mWidth: Int get() = container.impl.mWidth - val mHeight: Int get() = container.impl.mHeight - val mTextureFormat: TextureFormat get() = container.impl.mTextureFormat - val mMipMap: Boolean get() = container.impl.mMipMap - val mMipCount: Int get() = container.impl.mMipCount - val mTextureSettings: GLTextureSettings get() = container.impl.mTextureSettings - val imageData: ResourceReader get() = container.impl.imageData - val mStreamData: StreamingInfo? get() = container.impl.mStreamData - - val decompressedImageData: ByteArray get() = container.impl.decompressedImageData - - /** - * Usually up-side-down - */ - val image: BufferedImage get() = container.impl.image -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/Transform.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/Transform.kt deleted file mode 100644 index a99cfdc2..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/Transform.kt +++ /dev/null @@ -1,21 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.TransformImpl -import io.github.deficuet.unitykt.file.ObjectInfo -import io.github.deficuet.unitykt.file.SerializedFile -import io.github.deficuet.unitykt.math.Quaternion -import io.github.deficuet.unitykt.math.Vector3 -import io.github.deficuet.unitykt.util.ObjectReader - -open class Transform internal constructor( - private val container: ImplementationContainer -): Component(container) { - internal constructor(assetFile: SerializedFile, info: ObjectInfo): - this(ImplementationContainer(assetFile, info) { TransformImpl(ObjectReader(assetFile, info)) }) - - val mLocalRotation: Quaternion get() = container.impl.mLocalRotation - val mLocalPosition: Vector3 get() = container.impl.mLocalPosition - val mLocalScale: Vector3 get() = container.impl.mLocalScale - val mChildren: Array> get() = container.impl.mChildren - val mFather: PPtr get() = container.impl.mFather -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/data/VideoClip.kt b/src/main/kotlin/io/github/deficuet/unitykt/data/VideoClip.kt deleted file mode 100644 index 5167f302..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/data/VideoClip.kt +++ /dev/null @@ -1,19 +0,0 @@ -package io.github.deficuet.unitykt.data - -import io.github.deficuet.unitykt.dataImpl.StreamedResource -import io.github.deficuet.unitykt.dataImpl.VideoClipImpl -import io.github.deficuet.unitykt.file.ObjectInfo -import io.github.deficuet.unitykt.file.SerializedFile -import io.github.deficuet.unitykt.util.ObjectReader -import io.github.deficuet.unitykt.util.ResourceReader - -class VideoClip private constructor( - private val container: ImplementationContainer -): NamedObject(container) { - internal constructor(assetFile: SerializedFile, info: ObjectInfo): - this(ImplementationContainer(assetFile, info) { VideoClipImpl(ObjectReader(assetFile, info)) }) - - val mOriginalPath: String get() = container.impl.mOriginalPath - val mVideoData: ResourceReader get() = container.impl.mVideoData - val mExternamResource: StreamedResource get() = container.impl.mExternamResource -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/AnimationClipImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/AnimationClipImpl.kt deleted file mode 100644 index 56ba51ae..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/AnimationClipImpl.kt +++ /dev/null @@ -1,590 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.data.MonoScript -import io.github.deficuet.unitykt.data.Object -import io.github.deficuet.unitykt.data.PPtr -import io.github.deficuet.unitykt.file.ClassIDType -import io.github.deficuet.unitykt.math.Quaternion -import io.github.deficuet.unitykt.math.Vector3 -import io.github.deficuet.unitykt.util.* -import kotlin.math.sqrt - -class AnimationClipImpl internal constructor(reader: ObjectReader): NamedObjectImpl(reader) { - val mAnimationType: AnimationType - val mLegacy: Boolean - val mCompressed: Boolean - val mUseHighQualityCurve: Boolean - val mRotationCurves: Array - val mCompressedRotationCurves: Array - val mEulerCurves: Array - val mPositionCurves: Array - val mScaleCurves: Array - val mFloatCurves: Array - val mPPtrCurves: Array - val mSampleRate: Float - val mWrapMode: Int - val mBounds: AABB? - val mMuscleClipSize: UInt - val mMuscleClip: ClipMuscleConstant? - val mClipBindingConstant: AnimationClipBindingConstant? - val mEvents: Array - - init { - val v43 = intArrayOf(4, 3) - mLegacy = if (unityVersion[0] >= 5) { - mAnimationType = AnimationType.default - reader.readBool() - } else if (unityVersion[0] >= 4) { - mAnimationType = AnimationType.of(reader.readInt()) - mAnimationType == AnimationType.Legacy - } else { - mAnimationType = AnimationType.default - true - } - mCompressed = reader.readBool() - mUseHighQualityCurve = if (unityVersion >= v43) reader.readBool() else false - reader.alignStream() - mRotationCurves = reader.readArrayOf { QuaternionCurve(reader) } - mCompressedRotationCurves = reader.readArrayOf { CompressedAnimationCurve(reader) } - mEulerCurves = if (unityVersion >= intArrayOf(5, 3)) { - reader.readArrayOf { Vector3Curve(reader) } - } else emptyArray() - mPositionCurves = reader.readArrayOf { Vector3Curve(reader) } - mScaleCurves = reader.readArrayOf { Vector3Curve(reader) } - mFloatCurves = reader.readArrayOf { FloatCurve(reader) } - mPPtrCurves = if (unityVersion >= v43) { - reader.readArrayOf { PPtrCurve(reader) } - } else emptyArray() - mSampleRate = reader.readFloat() - mWrapMode = reader.readInt() - mBounds = if (unityVersion >= intArrayOf(3, 4)) AABB(reader) else null - if (unityVersion[0] >= 4) { - mMuscleClipSize = reader.readUInt() - mMuscleClip = ClipMuscleConstant(reader) - } else { - mMuscleClipSize = 0u; mMuscleClip = null - } - mClipBindingConstant = if (unityVersion >= v43) AnimationClipBindingConstant(reader) else null - if (unityVersion >= intArrayOf(2018, 3)) { - reader += 2 //m_HasGenericRootTransform, m_HasMotionFloatCurves: Boolean - reader.alignStream() - } - mEvents = reader.readArrayOf { AnimationEvent(reader) } - if (unityVersion[0] >= 2017) reader.alignStream() - } -} - -class KeyFrame internal constructor(reader: ObjectReader, readerFunc: () -> T) { - val time = reader.readFloat() - val value = readerFunc() - val inSlope = readerFunc() - val outSlope = readerFunc() - val weightedMode: Int - val inWeight: T? - val outWeight: T? - - init { - if (reader.unityVersion[0] >= 2018) { - weightedMode = reader.readInt() - inWeight = readerFunc() - outWeight = readerFunc() - } else { - weightedMode = 0; inWeight = null; outWeight = null - } - } -} - -class AnimationCurve internal constructor(reader: ObjectReader, readerFunc: () -> T) { - val mCurve = reader.readArrayOf { KeyFrame(reader, readerFunc) } - val mPreInfinity = reader.readInt() - val mPostInfinity = reader.readInt() - val mRotationOrder = if (reader.unityVersion >= intArrayOf(5, 3)) reader.readInt() else 0 -} - -class QuaternionCurve internal constructor(reader: ObjectReader) { - val curve = AnimationCurve(reader, reader::readQuaternion) - val path = reader.readAlignedString() -} - -class PackedFloatVector internal constructor(reader: ObjectReader) { - val mNumItems = reader.readUInt() - val mRange = reader.readFloat() - val mStart = reader.readFloat() - val mData: ByteArray - val mBitSize: UByte - - init { - mData = reader.read(reader.readInt()) - reader.alignStream() - mBitSize = reader.readByte() - reader.alignStream() - } - - fun unpackFloats( - itemCountInChunk: Int, - chunkStride: Int, - start: Int = 0, - chunkCount: Int = -1 - ): FloatArray { - val bitSize = mBitSize.toInt() - var bitPos = start * bitSize - var indexPos = (bitPos / 8).toUInt() - bitPos %= 8 - val scale = 1.0f / mRange - val numChunks = if (chunkCount == -1) { - mNumItems.toInt() / itemCountInChunk - } else chunkCount - val end = chunkStride * numChunks / 4 - val data = mutableListOf() - var idx = 0 - while (idx != end) { - for (i in 0 until itemCountInChunk) { - var x = 0u - var bits = 0 - while (bits < bitSize) { - x = x.or(mData[indexPos].shr(bitPos).shl(bits).toUInt()) - val num = minOf(bitSize - bits, 8 - bitPos) - bitPos += num; bits += num - if (bitPos == 8) { - indexPos++; bitPos = 0 - } - } - x = x.and(1.shl(bitSize).toUInt() - 1u) - data.add(x.toFloat() / (scale * (1.shl(bitSize) - 1)) + mStart) - } - idx += chunkStride / 4 - } - return data.toFloatArray() - } -} - -class PackedIntVector internal constructor(reader: ObjectReader) { - var mNumItems = reader.readUInt() - internal set - val mData: ByteArray - var mBitSize: UByte - internal set - - init { - mData = reader.read(reader.readInt()) - reader.alignStream() - mBitSize = reader.readByte() - reader.alignStream() - } - - fun unpackInts(): IntArray { - val data = IntArray(mNumItems.toInt()) - var indexPos = 0u; var bitPos = 0 - val bitSize = mBitSize.toInt() - for (i in 0 until mNumItems.toInt()) { - var bits = 0; var value = 0 - while (bits < bitSize) { - value = value.or(mData[indexPos].shr(bitPos).shl(bits)) - val num = minOf(bitSize - bits, 8 - bitPos) - bitPos += num; bits += num - if (bitPos == 8) { - indexPos++; bitPos = 0 - } - } - data[i] = value.and(1.shl(bitSize) - 1) - } - return data - } -} - -class PackedQuatVector internal constructor(reader: ObjectReader) { - val mNumItems = reader.readUInt() - val mData: ByteArray - - init { - mData = reader.read(reader.readInt()) - reader.alignStream() - } - - fun unpackQuats(): Array { - val data = arrayOf() - var indexPos = 0; var bitPos = 0 - for (i in 0 until mNumItems.toInt()) { - var flags = 0u; var bits = 0 - while (bits < 3) { - flags = flags or ((mData[indexPos].toInt() shr bitPos) shl bits).toUInt() - val num = minOf(3 - bits, 8 - bitPos) - bitPos += num; bits += num - if (bitPos == 8) { - indexPos++; bitPos = 0 - } - } - flags = flags and 7u - val qFloats = FloatArray(4) - var sum = 0f - for (j in 0u..3u) { - if ((flags and 3u) != j) { - val bitSize = if (((flags and 3u) + 1u) % 4u == j) 9 else 10 - var x = 0u; bits = 0 - while (bits < bitSize) { - x = x or ((mData[indexPos].toInt() shr bitPos) shl bits).toUInt() - val num = minOf(bitSize - bits, 8 - bitPos) - bitPos += num; bits += num - if (bitPos == 8) { - indexPos++; bitPos = 0 - } - } - x = x and ((1 shl bitSize) - 1).toUInt() - val f = x.toFloat() / (0.5f * ((1 shl bitSize) - 1)) - 1 - sum += f * f - qFloats[j.toInt()] = f - } - } - val qLast = (flags and 3u).toInt() - qFloats[qLast] = sqrt(1 - sum) - if ((flags and 4u) != 0u) qFloats[qLast] = -qFloats[qLast] - data[i] = Quaternion(*qFloats) - } - return data - } -} - -class CompressedAnimationCurve internal constructor(reader: ObjectReader) { - val mPath = reader.readAlignedString() - val mTimes = PackedIntVector(reader) - val mValues = PackedQuatVector(reader) - val mSlopes = PackedFloatVector(reader) - val mPreInfinity = reader.readInt() - val mPostInfinity = reader.readInt() -} - -class Vector3Curve internal constructor(reader: ObjectReader) { - val curve = AnimationCurve(reader, reader::readVector3) - val path = reader.readAlignedString() -} - -class FloatCurve internal constructor(reader: ObjectReader) { - val curve = AnimationCurve(reader, reader::readFloat) - val attribute = reader.readAlignedString() - val path = reader.readAlignedString() - val classID: ClassIDType - val script: PPtr - - init { - val id = reader.readInt() - classID = ClassIDType.of(id) - script = PPtr(reader) - } -} - -class PPtrKeyFrame internal constructor(reader: ObjectReader) { - val time = reader.readFloat() - val value = PPtr(reader) -} - -class PPtrCurve internal constructor(reader: ObjectReader) { - val curve = reader.readArrayOf { PPtrKeyFrame(reader) } - val attribute = reader.readAlignedString() - val path = reader.readAlignedString() - val classID = reader.readInt() - val script = PPtr(reader) -} - -class AABB internal constructor(reader: ObjectReader) { - val mCenter = reader.readVector3() - val mExtent = reader.readVector3() -} - -class XForm internal constructor(reader: ObjectReader) { - val t: Vector3 - val q: Quaternion - val s: Vector3 - - init { - val version = reader.unityVersion - val v = intArrayOf(5, 4) - t = if (version >= v) reader.readVector3() else reader.readVector4().vector3 - q = reader.readQuaternion() - s = if (version >= v) reader.readVector3() else reader.readVector4().vector3 - } -} - -class HandPose internal constructor(reader: ObjectReader) { - val mGrabX = XForm(reader) - val mDoFArray = reader.readNextFloatArray() - val mOverride = reader.readFloat() - val mCloseOpen = reader.readFloat() - val mInOut = reader.readFloat() - val mGrab = reader.readFloat() -} - -class HumanGoal internal constructor(reader: ObjectReader) { - val mX = XForm(reader) - val mWeightT = reader.readFloat() - val mWeightR = reader.readFloat() - val mHintT: Vector3 - val mHintWeightT: Float - - init { - val version = reader.unityVersion - if (version[0] > 5) { - mHintT = if (version >= intArrayOf(5, 4)) reader.readVector3() else reader.readVector4().vector3 - mHintWeightT = reader.readFloat() - } else { - mHintT = Vector3.Zero - mHintWeightT = 0f - } - } -} - -class HumanPose internal constructor(reader: ObjectReader) { - val mRootX = XForm(reader) - val mLookAt = if (reader.unityVersion >= intArrayOf(5, 4)) reader.readVector3() else reader.readVector4().vector3 - val mLookAtWeight = reader.readVector4() - val mGoalArray = reader.readArrayOf { HumanGoal(reader) } - val mLeftHandPose = HandPose(reader) - val mRightHandPose = HandPose(reader) - val mDoFArray = reader.readNextFloatArray() - val mTDoFArray = if (reader.unityVersion > intArrayOf(5, 2)) { - reader.readArrayOf { - if (reader.unityVersion >= intArrayOf(5, 4)) reader.readVector3() else reader.readVector4().vector3 - } - } else emptyArray() -} - -class StreamedCurveKey internal constructor(reader: EndianBinaryReader) { - val index = reader.readInt() - val coeff = reader.readNextFloatArray(4) - val outSlope = coeff[2] - val value = coeff[3] - var inSlope = 0f - - fun nextInSlope(deltaX: Float, rhs: StreamedCurveKey): Float { - if (coeff.sliceArray(0..2).all { it == 0f }) return Float.POSITIVE_INFINITY - val dx = maxOf(deltaX, 0.0001f) - val dy = rhs.value - value - val length = 1f / dx / dx - val d1 = outSlope * dx - val d2 = dy * 3 - d1 * 2 - coeff[1] / length - return d2 / dx - } -} - -class StreamedFrame internal constructor(reader: EndianBinaryReader) { - val time = reader.readFloat() - val keyList = reader.readArrayOf { StreamedCurveKey(reader) } -} - -class StreamedClip internal constructor(reader: ObjectReader) { - val data = reader.readNextUIntArray() - val curveCount = reader.readUInt() - - fun readData(): List { - val frameList = mutableListOf() - val buffer = ByteArray(data.size * 4) { - data[it / 4].shr(24 - (it % 4) * 8).toByte() - } - EndianByteArrayReader(buffer).use { - while (it.position < it.length) { - frameList.add(StreamedFrame(it)) - } - } - for (frameIdx in 2 until frameList.size) { - val frame = frameList[frameIdx] - for (curveKey in frame.keyList) { - for (i in frameIdx - 1 downTo 0) { - val preFrame = frameList[i] - val preCurveKey = preFrame.keyList.firstOrNull { it.index == curveKey.index } - if (preCurveKey != null) { - curveKey.inSlope = preCurveKey.nextInSlope(frame.time - preFrame.time, curveKey) - break - } - } - } - } - return frameList - } -} - -class DenseClip internal constructor(reader: ObjectReader) { - val mFrameCount = reader.readInt() - val mCurveCount = reader.readUInt() - val mSampleRate = reader.readFloat() - val mBeginTime = reader.readFloat() - val mSampleArray = reader.readNextFloatArray() -} - -class ConstantClip internal constructor(reader: ObjectReader) { - val data = reader.readNextFloatArray() -} - -class ValueConstant internal constructor(reader: ObjectReader) { - val mID = reader.readUInt() - val mTypeID: UInt - val mType: UInt - val mIndex: UInt - - init { - val version = reader.unityVersion - mTypeID = if (version < intArrayOf(5, 5)) { - reader.readUInt() - } else 0u - mType = reader.readUInt() - mIndex = reader.readUInt() - } -} - -class ValueArrayConstant internal constructor(reader: ObjectReader) { - val mValueArray = reader.readArrayOf { ValueConstant(reader) } -} - -class GenericBinding internal constructor(reader: ObjectReader) { - val path = reader.readUInt() - val attribute = reader.readUInt() - val script = PPtr(reader) - val typeID: ClassIDType - val customType: UByte - val isPPtrCurve: UByte - val isIntCurve: UByte - - init { - val version = reader.unityVersion - typeID = ClassIDType.of( - if (version >= intArrayOf(5, 6)) reader.readInt() else reader.readUShort().toInt() - ) - customType = reader.readByte() - isPPtrCurve = reader.readByte() - isIntCurve = if (version >= intArrayOf(2022, 1)) reader.readByte() else 0u - reader.alignStream() - } -} - -class AnimationClipBindingConstant internal constructor(reader: ObjectReader) { - val genericBindings = reader.readArrayOf { GenericBinding(reader) } - val pptrCurveMapping = reader.readArrayOf { PPtr(reader) } - - fun findBinding(index: Int): GenericBinding? { - var curves = 0 - for (b in genericBindings) { - curves += if (b.typeID == ClassIDType.Transform) { - when (b.attribute) { - 1u, 3u, 4u -> 3 - 2u -> 4 - else -> 1 - } - } else 1 - if (curves > index) return b - } - return null - } -} - -class Clip internal constructor(reader: ObjectReader) { - val mStreamedClip = StreamedClip(reader) - val mDenseClip = DenseClip(reader) - val mConstantClip: ConstantClip? - val mBinding: ValueArrayConstant? - - init { - val version = reader.unityVersion - mConstantClip = if (version >= intArrayOf(4, 3)) { - ConstantClip(reader) - } else null - mBinding = if (version < intArrayOf(2018, 3)) { - ValueArrayConstant(reader) - } else null - } -} - -class ValueDelta internal constructor(reader: ObjectReader) { - val mStart = reader.readFloat() - val mStop = reader.readFloat() -} - -class ClipMuscleConstant internal constructor(reader: ObjectReader) { - val mDeltaPose: HumanPose - val mStartX: XForm - val mStopX: XForm? - val mLeftFootStartX: XForm - val mRightFootStartX: XForm - val mMotionStartX: XForm? - val mMotionStopX: XForm? - val mAverageSpeed: Vector3 - val mClip: Clip - val mStartTime: Float - val mStopTime: Float - val mOrientationOffsetY: Float - val mLevel: Float - val mCycleOffset: Float - val mAverageAngularSpeed: Float - val mIndexArray: IntArray - val mValueArrayDelta: Array - val mValueArrayReferencePose: FloatArray - val mMirror: Boolean - val mLoopTime: Boolean - val mLoopBlend: Boolean - val mLoopBlendOrientation: Boolean - val mLoopBlendPositionY: Boolean - val mLoopBlendPositionXZ: Boolean - val mStartAtOrigin: Boolean - val mKeepOriginalOrientation: Boolean - val mKeepOriginalPositionY: Boolean - val mKeepOriginalPositionXZ: Boolean - val mHeightFromFeet: Boolean - - init { - mDeltaPose = HumanPose(reader) - mStartX = XForm(reader) - val version = reader.unityVersion - val v55 = intArrayOf(5, 5) - mStopX = if (version > v55) XForm(reader) else null - mLeftFootStartX = XForm(reader) - mRightFootStartX = XForm(reader) - if (version[0] < 5) { - mMotionStartX = XForm(reader) - mMotionStopX = XForm(reader) - } else { - mMotionStartX = null - mMotionStopX = null - } - mAverageSpeed = if (version >= intArrayOf(5, 4)) reader.readVector3() else reader.readVector4().vector3 - mClip = Clip(reader) - mStartTime = reader.readFloat() - mStopTime = reader.readFloat() - mOrientationOffsetY = reader.readFloat() - mLevel = reader.readFloat() - mCycleOffset = reader.readFloat() - mAverageAngularSpeed = reader.readFloat() - mIndexArray = reader.readNextIntArray() - if (version < intArrayOf(4, 3)) reader.readNextIntArray() //m_AdditionalCurveIndexArray: List - mValueArrayDelta = reader.readArrayOf { ValueDelta(reader) } - mValueArrayReferencePose = if (version >= intArrayOf(5, 3)) reader.readNextFloatArray() else floatArrayOf() - mMirror = reader.readBool() - mLoopTime = if (version >= intArrayOf(4, 3)) reader.readBool() else false - mLoopBlend = reader.readBool() - mLoopBlendOrientation = reader.readBool() - mLoopBlendPositionY = reader.readBool() - mLoopBlendPositionXZ = reader.readBool() - mStartAtOrigin = if (version > v55) reader.readBool() else false - mKeepOriginalOrientation = reader.readBool() - mKeepOriginalPositionY = reader.readBool() - mKeepOriginalPositionXZ = reader.readBool() - mHeightFromFeet = reader.readBool() - reader.alignStream() - } -} - -class AnimationEvent internal constructor(reader: ObjectReader) { - val time = reader.readFloat() - val functionName = reader.readAlignedString() - val data = reader.readAlignedString() - val objectReferenceParameter = PPtr(reader) - val floatParameter = reader.readFloat() - val intParameter = if (reader.unityVersion[0] >= 3) reader.readInt() else 0 - val messageOptions = reader.readInt() -} - -enum class AnimationType(val id: Int) { - default(0), Legacy(1), Generic(2), Humanoid(3); - - companion object { - fun of(value: Int): AnimationType { - return values().firstOrNull { it.id == value } ?: default - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/AnimationImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/AnimationImpl.kt deleted file mode 100644 index 6d3a8e58..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/AnimationImpl.kt +++ /dev/null @@ -1,14 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.data.AnimationClip -import io.github.deficuet.unitykt.data.PPtr -import io.github.deficuet.unitykt.util.ObjectReader - -class AnimationImpl(reader: ObjectReader): BehaviourImpl(reader) { - val mAnimations: Array> - - init { - PPtr(reader) //m_Animation - mAnimations = reader.readArrayOf { PPtr(reader) } - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/AnimatorControllerImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/AnimatorControllerImpl.kt deleted file mode 100644 index 3d20506e..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/AnimatorControllerImpl.kt +++ /dev/null @@ -1,295 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.data.AnimationClip -import io.github.deficuet.unitykt.data.PPtr -import io.github.deficuet.unitykt.math.Vector3 -import io.github.deficuet.unitykt.math.Vector4 -import io.github.deficuet.unitykt.util.ObjectReader -import io.github.deficuet.unitykt.util.compareTo - -class AnimatorControllerImpl internal constructor(reader: ObjectReader): RuntimeAnimatorControllerImpl(reader) { - val mAnimationClips: Array> - - init { - reader += 4 //m_ControllerSize: UInt - ControllerConstant(reader) //m_Controller - reader.readArrayOf { with(reader) { readUInt() to readAlignedString() } } //m_TOS: Map<> - mAnimationClips = reader.readArrayOf { PPtr(reader) } - } -} - -class HumanPoseMask internal constructor(reader: ObjectReader) { - val word0 = reader.readUInt() - val word1 = reader.readUInt() - val word2 = if (reader.unityVersion >= intArrayOf(5, 2)) reader.readUInt() else 0u -} - -class SkeletonMaskElement internal constructor(reader: ObjectReader) { - val mPathHash = reader.readUInt() - val mWeight = reader.readUInt() -} - -class SkeletonMask internal constructor(reader: ObjectReader) { - val mData = reader.readArrayOf { SkeletonMaskElement(reader) } -} - -class LayerConstant internal constructor(reader: ObjectReader) { - val mStateMachineIndex = reader.readUInt() - val mStateMachineMotionSetIndex = reader.readUInt() - val mBodyMask = HumanPoseMask(reader) - val mSkeletonMask = SkeletonMask(reader) - val mBinding = reader.readUInt() - val mLayerBlendingMode = reader.readInt() - val mDefaultWeight = if (reader.unityVersion >= intArrayOf(4, 2)) reader.readFloat() else 0f - val mIKPass = reader.readBool() - val mSyncedLayerAffectsTiming = if (reader.unityVersion >= intArrayOf(4, 2)) reader.readBool() else false - - init { reader.alignStream() } -} - -class ConditionConstant internal constructor(reader: ObjectReader) { - val mConditionMode = reader.readUInt() - val mEventID = reader.readUInt() - val mEventThreshold = reader.readFloat() - val mExitTime = reader.readFloat() -} - -class TransitionConstant internal constructor(reader: ObjectReader) { - val mConditionConstantArray = reader.readArrayOf { ConditionConstant(reader) } - val mDestinationState = reader.readUInt() - val mFullPathID = if (reader.unityVersion[0] >= 5) reader.readUInt() else 0u - val mID = reader.readUInt() - val mUserID = reader.readUInt() - val mTransitionDuration = reader.readFloat() - val mTransitionOffset = reader.readFloat() - val mExitTime: Float - val mHasExitTime: Boolean - val mHasFixedDuration: Boolean - val mInterruptionSource: Int - val mOrderedInterruption: Boolean - val mAtomic: Boolean - val mCanTransitionToSelf: Boolean - - init { - val version = reader.unityVersion - if (version[0] >= 5) { - mExitTime = reader.readFloat() - mHasExitTime = reader.readBool() - mHasFixedDuration = reader.readBool() - reader.alignStream() - mInterruptionSource = reader.readInt() - mOrderedInterruption = reader.readBool() - mAtomic = false - } else { - mExitTime = 0f - mHasExitTime = false - mHasFixedDuration = false - mInterruptionSource = 0 - mOrderedInterruption = false - mAtomic = reader.readBool() - } - mCanTransitionToSelf = if (version >= intArrayOf(4, 5)) reader.readBool() else false - reader.alignStream() - } -} - -class LeafInfoConstant internal constructor(reader: ObjectReader) { - val mIDArray = reader.readNextUIntArray() - val mIndexOffset = reader.readUInt() -} - -class MotionNeighborList internal constructor(reader: ObjectReader) { - val mNeighborArray = reader.readNextUIntArray() -} - -class Blend2dDataConstant internal constructor(reader: ObjectReader) { - val mChildPositionArray = reader.readNextVector2Array() - val mChildMagnitudeArray = reader.readNextFloatArray() - val mChildPairVectorArray = reader.readNextVector2Array() - val mChildPairAvgMagInvArray = reader.readNextFloatArray() - val mChildNeighborListArray = reader.readArrayOf { MotionNeighborList(reader) } -} - -class Blend1dDataConstant internal constructor(reader: ObjectReader) { - val mChildThresholdArray = reader.readNextFloatArray() -} - -class BlendDirectDataConstant internal constructor(reader: ObjectReader) { - val mChildBlendEventIDArray = reader.readNextUIntArray() - val mNormalizedBlendValues = reader.readBool() - - init { reader.alignStream() } -} - -class BlendTreeNodeConstant internal constructor(reader: ObjectReader) { - val mBlendType: UInt - val mBlendEventID: UInt - val mBlendEventYID: UInt - val mChildIndices: Array - val mChildThresholdArray: FloatArray - val mBlend1dData: Blend1dDataConstant? - val mBlend2dData: Blend2dDataConstant? - val mBlendDirectData: BlendDirectDataConstant? - val mClipID: UInt - val mClipIndex: UInt - val mDuration: Float - val mCycleOffset: Float - val mMirror: Boolean - - init { - val version = reader.unityVersion - val v41 = intArrayOf(4, 1) - mBlendType = if (version >= v41) reader.readUInt() else 0u - mBlendEventID = reader.readUInt() - mBlendEventYID = if (version >= v41) reader.readUInt() else 0u - mChildIndices = reader.readNextUIntArray() - mChildThresholdArray = if (version < v41) reader.readNextFloatArray() else floatArrayOf() - if (version >= v41) { - mBlend1dData = Blend1dDataConstant(reader) - mBlend2dData = Blend2dDataConstant(reader) - } else { - mBlend1dData = null; mBlend2dData = null - } - mBlendDirectData = if (version[0] >= 5) BlendDirectDataConstant(reader) else null - mClipID = reader.readUInt() - mClipIndex = if (intArrayOf(4, 5) <= version && version[0] < 5) reader.readUInt() else 0u - mDuration = reader.readFloat() - if (version >= intArrayOf(4, 1, 3)) { - mCycleOffset = reader.readFloat() - mMirror = reader.readBool() - reader.alignStream() - } else { - mCycleOffset = 0f; mMirror = false - } - } -} - -class BlendTreeConstant internal constructor(reader: ObjectReader) { - val mNodeArray = reader.readArrayOf { BlendTreeNodeConstant(reader) } - val mBlendEventArrayConstant = if (reader.unityVersion < intArrayOf(4, 5)) { - ValueArrayConstant(reader) - } else null -} - -class StateConstant internal constructor(reader: ObjectReader) { - val mTransitionConstantArray = reader.readArrayOf { TransitionConstant(reader) } - val mBlendTreeConstantIndexArray = reader.readNextIntArray() - val mLeafInfoArray = if (reader.unityVersion < intArrayOf(5, 2)) { - reader.readArrayOf { LeafInfoConstant(reader) } - } else emptyArray() - val mBlendTreeConstantArray = reader.readArrayOf { BlendTreeConstant(reader) } - val mNameID = reader.readUInt() - val mPathID = if (reader.unityVersion >= intArrayOf(4, 3)) reader.readUInt() else 0u - val mFullPathID = if (reader.unityVersion[0] >= 5) reader.readUInt() else 0u - val mTagID = reader.readUInt() - val mSpeedParamID: UInt - val mMirrorParamID: UInt - val mCycleOffsetParamID: UInt - val mSpeed: Float - val mCycleOffset: Float - val mIKOnFeet: Boolean - val mWriteDefaultValues: Boolean - val mLoop: Boolean - val mMirror: Boolean - - init { - val version = reader.unityVersion - if (version >= intArrayOf(5, 1)) { - mSpeedParamID = reader.readUInt() - mMirrorParamID = reader.readUInt() - mCycleOffsetParamID = reader.readUInt() - } else { - mSpeedParamID = 0u - mMirrorParamID = 0u - mCycleOffsetParamID = 0u - } - if (version >= intArrayOf(2017, 2)) reader += 4 //m_TimeParamID: UInt - mSpeed = reader.readFloat() - mCycleOffset = if (version >= intArrayOf(4, 1)) reader.readFloat() else 0f - mIKOnFeet = reader.readBool() - mWriteDefaultValues = if (version[0] >= 5) reader.readBool() else false - mLoop = reader.readBool() - mMirror = if (version >= intArrayOf(4, 1)) reader.readBool() else false - reader.alignStream() - } -} - -class SelectorTransitionConstant internal constructor(reader: ObjectReader) { - val mDestination = reader.readUInt() - val mConditionConstantArray = reader.readArrayOf { ConditionConstant(reader) } -} - -class SelectorStateConstant internal constructor(reader: ObjectReader) { - val mTransitionConstantArray = reader.readArrayOf { SelectorTransitionConstant(reader) } - val mFullPathID = reader.readUInt() - val mIsEntry = reader.readBool() - - init { reader.alignStream() } -} - -class StateMachineConstant internal constructor(reader: ObjectReader) { - val mStateConstantArray = reader.readArrayOf { StateConstant(reader) } - val mAnyStateTransitionConstantArray = reader.readArrayOf { TransitionConstant(reader) } - val mSelectorStateConstantArray = if (reader.unityVersion[0] >= 5) { - reader.readArrayOf { SelectorStateConstant(reader) } - } else emptyArray() - val mDefaultState = reader.readUInt() - val mMotionSetCount = reader.readUInt() -} - -class ValueArray internal constructor(reader: ObjectReader) { - val mBoolValues: BooleanArray - val mIntValues: IntArray - val mFloatValues: FloatArray - val mVectorValues: Array - val mPositionValues: Array - val mQuaternionValues: Array - val mScaleValues: Array - - init { - val version = reader.unityVersion - val v55 = intArrayOf(5, 5); val v54 = intArrayOf(5, 4) - var bool: BooleanArray = booleanArrayOf() - var ints: IntArray = intArrayOf() - var floats: FloatArray = floatArrayOf() - if (version < v55) { - bool = reader.readNextBoolArray() - reader.alignStream() - ints = reader.readNextIntArray() - floats = reader.readNextFloatArray() - } - if (version < intArrayOf(4, 3)) { - mVectorValues = reader.readNextVector4Array() - mPositionValues = emptyArray() - mQuaternionValues = emptyArray() - mScaleValues = emptyArray() - } else { - mVectorValues = emptyArray() - mPositionValues = reader.readArrayOf { - if (version >= v54) reader.readVector3() - else reader.readVector4().vector3 - } - mQuaternionValues = reader.readNextVector4Array() - mScaleValues = reader.readArrayOf { - if (version >= v54) reader.readVector3() - else reader.readVector4().vector3 - } - if (version >= v55) { - floats = reader.readNextFloatArray() - ints = reader.readNextIntArray() - bool = reader.readNextBoolArray() - reader.alignStream() - } - } - mBoolValues = bool - mIntValues = ints - mFloatValues = floats - } -} - -class ControllerConstant internal constructor(reader: ObjectReader) { - val mLayerArray = reader.readArrayOf { LayerConstant(reader) } - val mStateMachineArray = reader.readArrayOf { StateMachineConstant(reader) } - val mValues = ValueArrayConstant(reader) - val mDefaultValues = ValueArray(reader) -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/AnimatorImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/AnimatorImpl.kt deleted file mode 100644 index 20047012..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/AnimatorImpl.kt +++ /dev/null @@ -1,34 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.data.Avatar -import io.github.deficuet.unitykt.data.PPtr -import io.github.deficuet.unitykt.data.RuntimeAnimatorController -import io.github.deficuet.unitykt.util.ObjectReader -import io.github.deficuet.unitykt.util.compareTo - -class AnimatorImpl internal constructor(reader: ObjectReader): BehaviourImpl(reader) { - val mAvatar = PPtr(reader) - val mController = PPtr(reader) - val mHasTransformHierarchy: Boolean - - init { - reader += 4 //m_CullingMode: Int - val v45 = intArrayOf(4, 5) - if (unityVersion >= v45) reader += 4 //m_UpdateMode: Int - reader += 1 //m_ApplyRootMotion: Boolean - if (v45 <= unityVersion && unityVersion[0] < 5) reader.alignStream() - if (unityVersion[0] >= 5) { - reader += 1 //m_LinearVelocityBlending: Boolean - if (unityVersion >= intArrayOf(2021, 2)) reader += 1 //m_StabilizeFeet: Boolean - reader.alignStream() - } - if (unityVersion < v45) reader += 1 //m_AnimatePhysics: Boolean - mHasTransformHierarchy = if (unityVersion >= intArrayOf(4, 3)) reader.readBool() else true - if (unityVersion >= v45) reader += 1 //m_AllowConstantClipSamplingOptimization: Boolean - if (unityVersion[0] in 5..2017) reader.alignStream() - if (unityVersion[0] >= 2018) { - reader += 1 //m_KeepAnimatorControllerStateOnDisable: Boolean - reader.alignStream() - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/AnimatorOverrideControllerImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/AnimatorOverrideControllerImpl.kt deleted file mode 100644 index 76ac2e01..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/AnimatorOverrideControllerImpl.kt +++ /dev/null @@ -1,16 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.data.AnimationClip -import io.github.deficuet.unitykt.data.PPtr -import io.github.deficuet.unitykt.data.RuntimeAnimatorController -import io.github.deficuet.unitykt.util.ObjectReader - -class AnimatorOverrideControllerImpl internal constructor(reader: ObjectReader): RuntimeAnimatorControllerImpl(reader) { - val mController = PPtr(reader) - val mClips = reader.readArrayOf { AnimationClipOverride(reader) } -} - -class AnimationClipOverride internal constructor(reader: ObjectReader) { - val mOriginalClip = PPtr(reader) - val mOverrideClip = PPtr(reader) -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/AssetBundleImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/AssetBundleImpl.kt deleted file mode 100644 index becb4b34..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/AssetBundleImpl.kt +++ /dev/null @@ -1,31 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.data.Object -import io.github.deficuet.unitykt.data.PPtr -import io.github.deficuet.unitykt.util.ObjectReader -import io.github.deficuet.unitykt.util.compareTo - -class AssetBundleImpl internal constructor(reader: ObjectReader): NamedObjectImpl(reader) { - val mPreloadTable = reader.readArrayOf { PPtr(reader) } - val mContainer = reader.readArrayOf { reader.readAlignedString() to AssetInfo(reader) } - val mMainAsset = AssetInfo(reader) - val mRuntimeCompatibility = reader.readUInt() - val mAssetBundleName = reader.readAlignedString() - val mDependencies = reader.readNextStringArray() - val mIsStreamedSceneAssetBundle: Boolean - val mExplicitDataLayout: Int - val mPathFlags: Int - - init { - mIsStreamedSceneAssetBundle = reader.readBool() - reader.alignStream() - mExplicitDataLayout = if (unityVersion >= intArrayOf(2017, 3)) reader.readInt() else 0 - mPathFlags = if (unityVersion >= intArrayOf(2017, 1, 0)) reader.readInt() else 0 - } -} - -class AssetInfo internal constructor(reader: ObjectReader) { - val preloadIndex = reader.readInt() - val preloadSize = reader.readInt() - val asset = PPtr(reader) -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/AudioClipImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/AudioClipImpl.kt deleted file mode 100644 index 7cb7f007..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/AudioClipImpl.kt +++ /dev/null @@ -1,151 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.util.ObjectReader -import io.github.deficuet.unitykt.util.ResourceReader -import io.github.deficuet.unitykt.util.compareTo - -class AudioClipImpl internal constructor(reader: ObjectReader): NamedObjectImpl(reader) { - val mFormat: Int - val mType: FMODSoundType - val m3D: Boolean - val mUseHardware: Boolean - - val mLoadType: Int - val mChannels: Int - val mFrequency: Int - val mBitsPerSample: Int - val mLength: Float - val mIsTrackerFormat: Boolean - val mSubSoundIndex: Int - val mPreloadAudioData: Boolean - val mLoadInBackground: Boolean - val mLegacy3D: Boolean - val mCompressionFormat: AudioCompressionFormat - - val mSource: String - val mOffset: Long - val mSize: Long - val mAudioData: ResourceReader - - init { - if (unityVersion[0] < 5) { - mFormat = reader.readInt() - mType = FMODSoundType.of(reader.readInt()) - m3D = reader.readBool() - mUseHardware = reader.readBool() - reader.alignStream() - if (unityVersion >= intArrayOf(3, 2)) { - reader += 4 //m_Stream: Int - mSize = reader.readInt().toLong() - val tSize = if (mSize % 4 != 0L) mSize + 4 - mSize % 4 else mSize - if (reader.byteSize.toLong() + reader.byteStart - reader.absolutePosition != tSize) { - mOffset = reader.readUInt().toLong() - mSource = "${assetFile.name}.resS" - } else { - mOffset = 0 - mSource = "" - } - } else { - mSize = reader.readInt().toLong() - mOffset = 0 - mSource = "" - } - mLoadType = 0 - mChannels = 0 - mFrequency = 0 - mBitsPerSample = 0 - mLength = 0f - mIsTrackerFormat = false - mSubSoundIndex = 0 - mPreloadAudioData = false - mLoadInBackground = false - mLegacy3D = false - mCompressionFormat = AudioCompressionFormat.UNKNOWN - } else { - mLoadType = reader.readInt() - mChannels = reader.readInt() - mFrequency = reader.readInt() - mBitsPerSample = reader.readInt() - mLength = reader.readFloat() - mIsTrackerFormat = reader.readBool() - reader.alignStream() - mSubSoundIndex = reader.readInt() - mPreloadAudioData = reader.readBool() - mLoadInBackground = reader.readBool() - mLegacy3D = reader.readBool() - reader.alignStream() - mSource = reader.readAlignedString() - mOffset = reader.readLong() - mSize = reader.readLong() - mCompressionFormat = AudioCompressionFormat.of(reader.readInt()) - mFormat = 0 - mType = FMODSoundType.UNKNOWN - m3D = false - mUseHardware = false - } - mAudioData = if (mSource.isNotEmpty()) { - ResourceReader(mSource, assetFile, mOffset, mSize) - } else { - ResourceReader(reader, reader.absolutePosition, mSize) - }.registerToManager(assetFile.root.manager) - } -} -enum class FMODSoundType(val id: Int, val ext: String) { - UNKNOWN(1, ""), - ACC(2, ".m4a"), - AIFF(3, ".aif"), - ASF(3, ""), - AT3(4, ""), - CDDA(5, ""), - DLS(6, ""), - FLAC(7, ""), - FSB(8, ""), - GCADPCM(9, ""), - IT(10, ".it"), - MIDI(11, ""), - MOD(12, ".mod"), - MPEG(13, ".mp3"), - OGGVORBIS(14, ".ogg"), - PLAYLIST(15, ""), - RAW(16, ""), - S3M(17, ".s3m"), - SF2(18, ""), - USER(19, ""), - WAV(20, ".wav"), - XM(21, ".xm"), - XMA(22, ".wav"), - VAG(23, ".vag"), - AUDIOQUEUE(24, ".fsb"), - XWMA(25, ""), - BCWAV(26, ""), - AT9(27, ""), - VORBIS(28, ""), - MEDIA_FOUNDATION(29, ""); - - companion object { - fun of(value: Int): FMODSoundType { - return values().firstOrNull { it.id == value } ?: UNKNOWN - } - } -} - - -enum class AudioCompressionFormat(val id: Int, val ext: String) { - PCM(0, ".fsb"), - Vorbis(1, ".fsb"), - ADPCM(2, ".fsb"), - MP3(3, ".fsb"), - PSVAG(4, ".vag"), - HEVAG(5, ".vag"), - XMA(6, ".wav"), - AAC(7, ".m4a"), - GCADPCM(8, ".fsb"), - ATRAC9(9, ".at9"), - UNKNOWN(10, "."); - - companion object { - fun of(value: Int): AudioCompressionFormat { - return values().firstOrNull { it.id == value } ?: UNKNOWN - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/AvatarImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/AvatarImpl.kt deleted file mode 100644 index 1d1438f4..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/AvatarImpl.kt +++ /dev/null @@ -1,173 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.math.Vector -import io.github.deficuet.unitykt.util.ObjectReader -import io.github.deficuet.unitykt.util.compareTo - -class AvatarImpl internal constructor(reader: ObjectReader): NamedObjectImpl(reader) { - val mAvatarSize = reader.readUInt() - val mAvatar = AvatarConstant(reader) - val mTOS = reader.readArrayOf { with(reader) { readUInt() to readAlignedString() } } -} - -class Node internal constructor(reader: ObjectReader) { - val mParentId = reader.readInt() - val mAxesId = reader.readInt() -} - -class Limit internal constructor(reader: ObjectReader) { - val mMin: Vector - val mMax: Vector - - init { - if (reader.unityVersion >= intArrayOf(5, 4)) { - mMin = reader.readVector3() - mMax = reader.readVector3() - } else { - mMin = reader.readVector4() - mMax = reader.readVector4() - } - } -} - -class Axes internal constructor(reader: ObjectReader) { - val mPreQ = reader.readVector4() - val mPostQ = reader.readVector4() - val mSgn: Vector - val mLimit: Limit - val mLength: Float - val mType: UInt - - init { - mSgn = if (reader.unityVersion >= intArrayOf(5, 4)) { - reader.readVector3() - } else reader.readVector4() - mLimit = Limit(reader) - mLength = reader.readFloat() - mType = reader.readUInt() - } -} - -class Skeleton internal constructor(reader: ObjectReader) { - val mNode = reader.readArrayOf { Node(reader) } - val mID = reader.readNextUIntArray() - val mAxesArray = reader.readArrayOf { Axes(reader) } -} - -class SkeletonPose internal constructor(reader: ObjectReader) { - val mX = reader.readArrayOf { XForm(reader) } -} - -class Hand internal constructor(reader: ObjectReader) { - val mHandBoneIndex = reader.readNextIntArray() -} - -class Handle internal constructor(reader: ObjectReader) { - val mX = XForm(reader) - val mParentHumanIndex = reader.readUInt() - val mID = reader.readUInt() -} - -class Collider internal constructor(reader: ObjectReader) { - val mX = XForm(reader) - val mType = reader.readUInt() - val mXMotionType = reader.readUInt() - val mYMotionType = reader.readUInt() - val mZMotionType = reader.readUInt() - val mMinLimitX = reader.readFloat() - val mMaxLimitX = reader.readFloat() - val mMaxLimitY = reader.readFloat() - val mMaxLimitZ = reader.readFloat() -} - -class Human internal constructor(reader: ObjectReader) { - val mRootX = XForm(reader) - val mSkeleton = Skeleton(reader) - val mSkeletonPose = SkeletonPose(reader) - val mLeftHand = Hand(reader) - val mRightHand = Hand(reader) - val mHandles: Array - val mColliderArray: Array - val mHumanBoneIndex: IntArray - val mHumanBoneMass: FloatArray - val mColliderIndex: IntArray - val mScale: Float - val mAriTwist: Float - val mForeArmTwist: Float - val mUpperLegTwist: Float - val mLegTwist: Float - val mArmStretch: Float - val mLegStretch: Float - val mFeetSpacing: Float - val mHasLeftHand: Boolean - val mHasRightHand: Boolean - val mHasTDoF: Boolean - - init { - val version = reader.unityVersion - val v182 = intArrayOf(2018, 2) - if (version < v182) { - mHandles = reader.readArrayOf { Handle(reader) } - mColliderArray = reader.readArrayOf { Collider(reader) } - } else { - mHandles = emptyArray(); mColliderArray = emptyArray() - } - mHumanBoneIndex = reader.readNextIntArray() - mHumanBoneMass = reader.readNextFloatArray() - mColliderIndex = if (version < v182) reader.readNextIntArray() else intArrayOf() - mScale = reader.readFloat() - mAriTwist = reader.readFloat() - mForeArmTwist = reader.readFloat() - mUpperLegTwist = reader.readFloat() - mLegTwist = reader.readFloat() - mArmStretch = reader.readFloat() - mLegStretch = reader.readFloat() - mFeetSpacing = reader.readFloat() - mHasLeftHand = reader.readBool() - mHasRightHand = reader.readBool() - mHasTDoF = if (version >= intArrayOf(5, 2)) reader.readBool() else false - reader.alignStream() - } -} - -class AvatarConstant internal constructor(reader: ObjectReader) { - val mAvatarSkeleton = Skeleton(reader) - val mAvatarSkeletonPose = SkeletonPose(reader) - val mDefaultPose: SkeletonPose? - val mSkeletonNameIDArray: Array - val mHuman: Human - val mHumanSkeletonIndexArray: IntArray - val mHumanSkeletonReverseIndexArray: IntArray - val mRootMotionBoneIndex: Int - val mRootMotionBoneX: XForm - val mRootMotionSkeleton: Skeleton? - val mRootMotionSkeletonPose: SkeletonPose? - val mRootMotionSkeletonIndexArray: IntArray - - init { - val version = reader.unityVersion - val v43 = intArrayOf(4, 3) - if (version >= v43) { - mDefaultPose = SkeletonPose(reader) - mSkeletonNameIDArray = reader.readNextUIntArray() - } else { - mDefaultPose = null; mSkeletonNameIDArray = emptyArray() - } - mHuman = Human(reader) - mHumanSkeletonIndexArray = reader.readNextIntArray() - mHumanSkeletonReverseIndexArray = if (version >= v43) { - reader.readNextIntArray() - } else intArrayOf() - mRootMotionBoneIndex = reader.readInt() - mRootMotionBoneX = XForm(reader) - if (version >= v43) { - mRootMotionSkeleton = Skeleton(reader) - mRootMotionSkeletonPose = SkeletonPose(reader) - mRootMotionSkeletonIndexArray = reader.readNextIntArray() - } else { - mRootMotionSkeleton = null - mRootMotionSkeletonPose = null - mRootMotionSkeletonIndexArray = intArrayOf() - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/BehaviourImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/BehaviourImpl.kt deleted file mode 100644 index ff2cfe2c..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/BehaviourImpl.kt +++ /dev/null @@ -1,8 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.util.ObjectReader - -abstract class BehaviourImpl internal constructor(reader: ObjectReader): ComponentImpl(reader) { - val mEnabled = reader.readByte() - init { reader.alignStream() } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/BuildSettingsImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/BuildSettingsImpl.kt deleted file mode 100644 index 4bf45519..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/BuildSettingsImpl.kt +++ /dev/null @@ -1,13 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.util.ObjectReader - -class BuildSettingsImpl internal constructor(reader: ObjectReader): ObjectImpl(reader) { - val mVersion: String - - init { - reader.readNextStringArray() - reader += 4 //hasRenderTexture, hasPROVersion, hasPublishingRights, hasShadows: Boolean - mVersion = reader.readAlignedString() - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/CanvasImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/CanvasImpl.kt deleted file mode 100644 index 0cb8e430..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/CanvasImpl.kt +++ /dev/null @@ -1,29 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.data.* -import io.github.deficuet.unitykt.util.ObjectReader - -/** - * Errors may occur for bundles with version before `2018.4.34f1` - */ -class CanvasImpl internal constructor(reader: ObjectReader): BehaviourImpl(reader) { - val mRenderMode = reader.readInt() - val mCamera = PPtr(reader) //PPtr - val mPlaneDistance = reader.readFloat() - val mPixelPerfect = reader.readBool() - val mReceivesEvent = reader.readBool() - val mOverrideSorting = reader.readBool() - val mOverridePixelPerfect = reader.readBool() - val mSortingBucketNormalizedSize = reader.readFloat() - val mAdditionalShaderChannelsFlag = reader.readInt() - val mSortingLayerID: Int - val mSortingOrder: Short - val mTargetDisplay: Byte - - init { - reader.alignStream() - mSortingLayerID = reader.readInt() - mSortingOrder = reader.readShort() - mTargetDisplay = reader.readSByte() - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/ComponentImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/ComponentImpl.kt deleted file mode 100644 index 11689b34..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/ComponentImpl.kt +++ /dev/null @@ -1,9 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.data.GameObject -import io.github.deficuet.unitykt.data.PPtr -import io.github.deficuet.unitykt.util.ObjectReader - -abstract class ComponentImpl internal constructor(reader: ObjectReader): EditorExtensionImpl(reader) { - val mGameObject = PPtr(reader) -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/EditorExtensionImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/EditorExtensionImpl.kt deleted file mode 100644 index 012eb671..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/EditorExtensionImpl.kt +++ /dev/null @@ -1,16 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.data.EditorExtension -import io.github.deficuet.unitykt.data.Object -import io.github.deficuet.unitykt.data.PPtr -import io.github.deficuet.unitykt.file.BuildTarget -import io.github.deficuet.unitykt.util.ObjectReader - -abstract class EditorExtensionImpl internal constructor(reader: ObjectReader): ObjectImpl(reader) { - init { - if (platform == BuildTarget.NoTarget) { - PPtr(reader) //m_PrefabParentObject - PPtr(reader) //m_PrefabInternal - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/FontImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/FontImpl.kt deleted file mode 100644 index de6b9e9e..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/FontImpl.kt +++ /dev/null @@ -1,72 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.data.Material -import io.github.deficuet.unitykt.data.PPtr -import io.github.deficuet.unitykt.data.Texture -import io.github.deficuet.unitykt.util.ObjectReader -import io.github.deficuet.unitykt.util.compareTo - -class FontImpl internal constructor(reader: ObjectReader): NamedObjectImpl(reader) { - val mFontData: ByteArray - - init { - if (unityVersion >= intArrayOf(5, 5)) { - reader += 4 //m_LineSpacing: Float - PPtr(reader) //m_DefaultMaterial - reader += 4 //m_FontSize: Float - PPtr(reader) //m_Texture - //m_AsciiStartOffset: Int, m_Tracking: Float m_CharacterSpacing: Int, - //m_CharacterPadding: Int, m_ConvertCase: Int - reader += 20 - val characterRectSize = reader.readInt() - for (i in 1..characterRectSize) { - reader += 44 - } - val kerningValuesSize = reader.readInt() - for (j in 1..kerningValuesSize) { - reader += 8 - } - reader += 4 //m_PixelScale: Float - val fontDataSize = reader.readInt() - mFontData = if (fontDataSize > 0) { - reader.read(fontDataSize) - } else byteArrayOf() - } else { - reader += 4 //m_AsciiStartOffset: Int - if (unityVersion[0] <= 3) { - reader += 8 //m_FontCountX, m_FontCountY: Int - } - reader += 8 //m_Kerning, m_LineSpacing: Float - if (unityVersion[0] <= 3) { - reader.readArrayOf { - reader += 8 //first: Int, second: Float - } - } else { - reader += 8 //m_CharacterSpacing, m_CharacterPadding: Int - } - reader += 4 //m_ConvertCase: Int - PPtr(reader) - val charRectSize = reader.readInt() - for (i in 1..charRectSize) { - reader += 40 - if (unityVersion[0] >= 4) { - reader += 1 //flipped: Boolean - reader.alignStream() - } - } - PPtr(reader) - val kerningValueSize = reader.readInt() - for (j in 1..kerningValueSize) { - reader += 8 - } - if (unityVersion[0] <= 3) { - reader += 1 //m_GridFont - reader.alignStream() - } else { - reader += 4 //m_PixelScale - } - val fontDataSize = reader.readInt() - mFontData = if (fontDataSize > 0) reader.read(fontDataSize) else byteArrayOf() - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/GameObjectImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/GameObjectImpl.kt deleted file mode 100644 index d9bc6617..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/GameObjectImpl.kt +++ /dev/null @@ -1,54 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.data.* -import io.github.deficuet.unitykt.safeGetObj -import io.github.deficuet.unitykt.util.ObjectReader -import io.github.deficuet.unitykt.util.compareTo - -class GameObjectImpl internal constructor(reader: ObjectReader): EditorExtensionImpl(reader) { - val mComponents: Array> - val mName: String - val mTransform: Array - val mMeshRenderer: Array - val mMeshFilter: Array - val mSkinnedMeshRenderer: Array - val mAnimator: Array - val mAnimation: Array - - init { - val components = reader.readArrayOf { - if (unityVersion < intArrayOf(5, 5)) { - reader += 4 //first: Int - } - PPtr(reader) - } - reader += 4 //m_Layer: Int - mName = reader.readAlignedString() - mComponents = components - val transforms = mutableListOf() - val meshRenderers = mutableListOf() - val meshFilters = mutableListOf() - val skinnedMeshRenderers = mutableListOf() - val animators = mutableListOf() - val animations = mutableListOf() - for (pptr in mComponents) { - val obj = pptr.safeGetObj() - if (obj != null) { - when (obj) { - is Transform -> transforms.add(obj) - is MeshRenderer -> meshRenderers.add(obj) - is MeshFilter -> meshFilters.add(obj) - is SkinnedMeshRenderer -> skinnedMeshRenderers.add(obj) - is Animator -> animators.add(obj) - is Animation -> animations.add(obj) - } - } - } - mTransform = transforms.toTypedArray() - mMeshRenderer = meshRenderers.toTypedArray() - mMeshFilter = meshFilters.toTypedArray() - mSkinnedMeshRenderer = skinnedMeshRenderers.toTypedArray() - mAnimator = animators.toTypedArray() - mAnimation = animations.toTypedArray() - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/MaterialImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/MaterialImpl.kt deleted file mode 100644 index b2debc4f..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/MaterialImpl.kt +++ /dev/null @@ -1,59 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.data.PPtr -import io.github.deficuet.unitykt.data.Shader -import io.github.deficuet.unitykt.data.Texture -import io.github.deficuet.unitykt.util.ObjectReader -import io.github.deficuet.unitykt.util.compareTo - -class MaterialImpl internal constructor(reader: ObjectReader): NamedObjectImpl(reader) { - val mShader = PPtr(reader) - val mSavedProperties: UnityPropertySheet - - init { - if (unityVersion[0] == 4 && unityVersion[1] >= 1) { - reader.readNextStringArray() //m_ShaderKeywords - } - if (unityVersion >= intArrayOf(2021, 3)) { - reader.readNextStringArray() - reader.readNextStringArray() - } else if (unityVersion[0] >= 5) { - reader.readAlignedString() //m_ShaderKeywords - } - if (unityVersion[0] >= 5) { - reader += 4 //m_LightmapFlags: UInt - } - if (unityVersion >= intArrayOf(5, 6)) { - reader += 1 //m_EnableInstancingVariants: Boolean - reader.alignStream() - } - if (unityVersion >= intArrayOf(4, 3)) { - reader += 4 //m_CustomRenderQueue: Int - } - if (unityVersion >= intArrayOf(5, 1)) { - reader.readArrayOf { - reader.readAlignedString() //first - reader.readAlignedString() //second - } - } - if (unityVersion >= intArrayOf(5, 6)) { - reader.readNextStringArray() - } - mSavedProperties = UnityPropertySheet(reader) - } -} - -class UnityTexEnv internal constructor(reader: ObjectReader) { - val mTexture = PPtr(reader) - val mScale = reader.readVector2() - val mOffset = reader.readVector2() -} - -class UnityPropertySheet internal constructor(reader: ObjectReader) { - val mTexEnvs = reader.readArrayOf { reader.readAlignedString() to UnityTexEnv(reader) } - val mInts = if (reader.unityVersion[0] >= 2021) { - reader.readArrayOf { with(reader) { readAlignedString() to readInt() } } - } else emptyArray() - val mFloats = reader.readArrayOf { with(reader) { readAlignedString() to readFloat() } } - val mColors = reader.readArrayOf { with(reader) { readAlignedString() to readColor4() } } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/MeshFilterImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/MeshFilterImpl.kt deleted file mode 100644 index f0e15223..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/MeshFilterImpl.kt +++ /dev/null @@ -1,9 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.data.Mesh -import io.github.deficuet.unitykt.data.PPtr -import io.github.deficuet.unitykt.util.ObjectReader - -class MeshFilterImpl internal constructor(reader: ObjectReader): ComponentImpl(reader) { - val mMesh = PPtr(reader) -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/MeshImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/MeshImpl.kt deleted file mode 100644 index 2c8abf6f..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/MeshImpl.kt +++ /dev/null @@ -1,1025 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.dataImpl.MeshHelper.Companion.toVertexFormat -import io.github.deficuet.unitykt.math.Matrix4x4 -import io.github.deficuet.unitykt.math.Vector2 -import io.github.deficuet.unitykt.math.Vector3 -import io.github.deficuet.unitykt.util.* -import java.nio.ByteBuffer -import java.nio.ByteOrder -import java.util.* -import kotlin.math.sqrt - -class MeshImpl internal constructor(reader: ObjectReader): NamedObjectImpl(reader) { - val mSubMeshes: Array - val mShapes: BlendShapeData? - val mIndices: Array - var mBindPose: Array = emptyArray() - private set - var mBoneNameHashes: Array = emptyArray() - private set - var mVertexCount: Int = 0 - private set - var mVertices: FloatArray = floatArrayOf() - private set - var mSkin: Array = emptyArray() - private set - var mNormals: FloatArray = floatArrayOf() - private set - var mColors: FloatArray = floatArrayOf() - private set - var mUV0: FloatArray = floatArrayOf() - private set - var mUV1: FloatArray = floatArrayOf() - private set - var mUV2: FloatArray = floatArrayOf() - private set - var mUV3: FloatArray = floatArrayOf() - private set - var mUV4: FloatArray = floatArrayOf() - private set - var mUV5: FloatArray = floatArrayOf() - private set - var mUV6: FloatArray = floatArrayOf() - private set - var mUV7: FloatArray = floatArrayOf() - private set - var mTangents: FloatArray = floatArrayOf() - private set - private var mUse16BitIndices: Boolean - private var mIndexBuffer: Array = emptyArray() - private lateinit var mVertexData: VertexData - private val mCompressedMesh: CompressedMesh? - private val mStreamData: StreamingInfo? - - init { - val indices = mutableListOf() - mUse16BitIndices = if (unityVersion < intArrayOf(3, 5)) reader.readInt() > 0 else true - if (unityVersion <= intArrayOf(2, 5)) { - val indexBufferSize = reader.readInt() - if (mUse16BitIndices) { - mIndexBuffer = reader.readArrayOf(indexBufferSize / 2) { reader.readUShort().toUInt() } - reader.alignStream() - } else { - mIndexBuffer = reader.readNextUIntArray(indexBufferSize / 4) - } - } - mSubMeshes = reader.readArrayOf { SubMash(reader) } - mShapes = if (unityVersion >= intArrayOf(4, 1)) BlendShapeData(reader) else null - if (unityVersion >= intArrayOf(4, 3)) { - mBindPose = reader.readNextMatrixArray() - mBoneNameHashes = reader.readNextUIntArray() - reader += 4 //m_RootBoneNameHash: UInt - } - if (unityVersion >= intArrayOf(2, 6)) { - if (unityVersion[0] >= 2019) { - reader.readArrayOf { MinMaxAABB(reader) } //m_BonesAABB - reader.readNextUIntArray() //m_VariableBoneCountWeights - } - val meshCompression = reader.readByte() - if (unityVersion[0] >= 4) { - if (unityVersion[0] < 5) { - reader += 1 //m_StreamCompression: UByte - } - reader += 3 //m_IsReadable, m_KeepVertices, m_KeepIndices: Boolean - } - reader.alignStream() - if ( - unityVersion >= intArrayOf(2017, 4) || - ((unityVersion[0] == 2017 && unityVersion[1] == 3 && unityVersion[2] == 1) && buildType.isPatch) || - ((unityVersion[0] == 2017 && unityVersion[1] == 3) && meshCompression == 0u.toUByte()) - ) { - mUse16BitIndices = reader.readInt() == 0 - } - val indexBufferSize = reader.readInt() - if (mUse16BitIndices) { - mIndexBuffer = reader.readArrayOf(indexBufferSize / 2) { reader.readUShort().toUInt() } - reader.alignStream() - } else { - mIndexBuffer = reader.readNextUIntArray(indexBufferSize / 4) - } - } - if (unityVersion < intArrayOf(3, 5)) { - mVertexCount = reader.readInt() - mVertices = reader.readNextFloatArray(mVertexCount * 3) - mSkin = reader.readArrayOf { BoneWeights4(reader) } - mBindPose = reader.readNextMatrixArray() - mUV0 = reader.readNextFloatArray(reader.readInt() * 2) - mUV1 = reader.readNextFloatArray(reader.readInt() * 2) - if (unityVersion[0] == 2 && unityVersion[1] <= 5) { - val tangentSpaceSize = reader.readInt() - val normals = FloatArray(tangentSpaceSize * 3) - val tangents = FloatArray(tangentSpaceSize * 4) - for (v in 0 until tangentSpaceSize) { - normals[v * 3] = reader.readFloat() - normals[v * 3 + 1] = reader.readFloat() - normals[v * 3 + 2] = reader.readFloat() - tangents[v * 3] = reader.readFloat() - tangents[v * 3 + 1] = reader.readFloat() - tangents[v * 3 + 2] = reader.readFloat() - tangents[v * 3 + 3] = reader.readFloat() - } - mNormals = normals - mTangents = tangents - } else { - mNormals = reader.readNextFloatArray(reader.readInt() * 3) - mTangents = reader.readNextFloatArray(reader.readInt() * 4) - } - } else { - if (unityVersion < intArrayOf(2018, 2)) { - mSkin = reader.readArrayOf { BoneWeights4(reader) } - } - if (unityVersion[0] == 3 || (unityVersion[0] == 4 && unityVersion[1] <= 2)) { - mBindPose = reader.readNextMatrixArray() - } - mVertexData = VertexData(reader) - } - mCompressedMesh = if (unityVersion >= intArrayOf(2, 6)) { - CompressedMesh(reader) - } else null - reader += 24 - if (unityVersion <= intArrayOf(3, 4)) { - mColors = reader.readArrayOf(reader.readInt() * 4) { - (reader.readByte() / 0xFFu).toFloat() - }.toFloatArray() - reader += reader.readInt() * 4 + 4 //m_CollisionVertexCount - } - reader += 4 //m_MeshUsageFlags: Int - if (unityVersion >= intArrayOf(2022, 1)) { - reader += 4 //m_CookingOptions - } - if (unityVersion[0] >= 5) { - reader.readNextByteArray() //m_BakedConvexCollisionMesh - reader.alignStream() - reader.readNextByteArray() //m_BakedTriangleCollisionMesh - reader.alignStream() - } - if (unityVersion >= intArrayOf(2018, 2)) { - reader += 8 //m_MeshMetrics: float[2] - } - mStreamData = if (unityVersion >= intArrayOf(2018, 3)) { - reader.alignStream() - StreamingInfo(reader) - } else null - //region processData - if (mStreamData?.path?.isNotEmpty() == true) { - if (mVertexData.mVertexCount > 0u) { - ResourceReader( - mStreamData.path, assetFile, mStreamData.offset, mStreamData.size.toLong() - ).use { - mVertexData.mDataSize = it.read() - } - } - } - if (unityVersion >= intArrayOf(3, 5)) { - //region readVertexData - mVertexCount = mVertexData.mVertexCount.toInt() - for (chn in mVertexData.mChannels.indices) { - val channel = mVertexData.mChannels[chn] - if (channel.dimension > 0u) { - val stream = mVertexData.mStreams[channel.stream.toInt()] - val mask = BitSet.valueOf(longArrayOf(stream.channelMask.toLong())) - if (mask[chn]) { - if (unityVersion[0] < 2018 && chn == 2 && channel.format == 2u.toUByte()) { - channel.dimension = 4u - } - val vertexFormat = channel.format.toVertexFormat(unityVersion) - val componentByteSize = vertexFormat.size.toInt() - val componentBytes = ByteArray( - mVertexCount * channel.dimension.toInt() * componentByteSize - ) - for (v in 0 until mVertexCount) { - val vertexOffset = stream.offset.toInt() + - channel.offset.toInt() + - stream.stride.toInt() * v - for (d in 0 until channel.dimension.toInt()) { - val componentOffset = vertexOffset + componentByteSize * d - val buff = mVertexData.mDataSize[componentOffset, componentByteSize] - if (reader.endian == ByteOrder.LITTLE_ENDIAN && componentByteSize > 1) { - buff.reverse() - } - System.arraycopy( - buff, 0, componentBytes, - componentByteSize * (channel.dimension.toInt() * v + d), - componentByteSize - ) - } - } - val fa: FloatArray? - val ia: IntArray? - if (vertexFormat.isIntFormat) { - ia = componentBytes.toIntArray(vertexFormat) - fa = null - } else { - fa = componentBytes.toFloatArray(vertexFormat) - ia = null - } - if (unityVersion[0] >= 2018) { - when (chn) { - 0 -> mVertices = fa!! - 1 -> mNormals = fa!! - 2 -> mTangents = fa!! - 3 -> mColors = fa!! - 4 -> mUV0 = fa!! - 5 -> mUV1 = fa!! - 6 -> mUV2 = fa!! - 7 -> mUV3 = fa!! - 8 -> mUV4 = fa!! - 9 -> mUV5 = fa!! - 10 -> mUV6 = fa!! - 11 -> mUV7 = fa!! - 12 -> { - if (mSkin.isEmpty()) { - mSkin = reader.readArrayOf(mVertexCount) { BoneWeights4() } - } - for (i in 0 until mVertexCount) { - for (j in 0 until channel.dimension.toInt()) { - mSkin[i].weight[j] = fa!![i * channel.dimension.toInt() + j] - } - } - } - 13 -> { - if (mSkin.isEmpty()) { - mSkin = reader.readArrayOf(mVertexCount) { BoneWeights4() } - } - for (i in 0 until mVertexCount) { - for (j in 0 until channel.dimension.toInt()) { - mSkin[i].boneIndex[j] = ia!![i * channel.dimension.toInt() + j] - } - } - } - } - } else { - when (chn) { - 0 -> mVertices = fa!! - 1 -> mNormals = fa!! - 2 -> mColors = fa!! - 3 -> mUV0 = fa!! - 4 -> mUV1 = fa!! - 5 -> { - if (unityVersion[0] >= 5) { - mUV2 = fa!! - } else { - mTangents = fa!! - } - } - 6 -> mUV3 = fa!! - 7 -> mTangents = fa!! - } - } - } - } - } - //endregion - } - if (unityVersion >= intArrayOf(2, 6)) { - //region DecompressCompressedMesh - if (mCompressedMesh!!.mVertices.mNumItems > 0u) { - mVertexCount = (mCompressedMesh.mVertices.mNumItems / 3u).toInt() - mVertices = mCompressedMesh.mVertices.unpackFloats(3, 12) - } - if (mCompressedMesh.mUV.mNumItems > 0u) { - val uvInfo = mCompressedMesh.mUVInfo - if (uvInfo != 0u) { - var uvSrcOffset = 0 - for (uv in 0 until kMaxTexCoordShaderChannels) { - var texCoordBits = uvInfo.shr(uv * kInfoBitsPerUV) - texCoordBits = texCoordBits.and(1u.shl(kInfoBitsPerUV) - 1u) - if (texCoordBits.and(kUVChannelExists) != 0u) { - val uvDim = 1 + texCoordBits.and(kUVDimensionMask).toInt() - val mUV = mCompressedMesh.mUV.unpackFloats( - uvDim, uvDim * 4, uvSrcOffset, mVertexCount - ) - //region setUV - when (uv) { - 0 -> mUV0 = mUV - 1 -> mUV1 = mUV - 2 -> mUV2 = mUV - 3 -> mUV3 = mUV - 4 -> mUV4 = mUV - 5 -> mUV5 = mUV - 6 -> mUV6 = mUV - 7 -> mUV7 = mUV - else -> throw IndexOutOfBoundsException() - } - //endregion - uvSrcOffset += uvDim * mVertexCount - } - } - } else { - mUV0 = mCompressedMesh.mUV.unpackFloats( - 2, 8, 0, mVertexCount - ) - if (mCompressedMesh.mUV.mNumItems >= (mVertexCount * 4).toUInt()) { - mUV1 = mCompressedMesh.mUV.unpackFloats( - 2, 8, mVertexCount * 2, mVertexCount - ) - } - } - } - if (unityVersion[0] < 5) { - val unpackedBindPose = mCompressedMesh.mBindPoses!!.unpackFloats(16, 64) - val buffer = FloatArray(16) - mBindPose = reader.readArrayIndexedOf( - (mCompressedMesh.mBindPoses.mNumItems / 16u).toInt() - ) { - System.arraycopy( - unpackedBindPose, it * 16, - buffer, 0, 16 - ) - Matrix4x4(*buffer) - } - } - if (mCompressedMesh.mNormals.mNumItems > 0u) { - val normalData = mCompressedMesh.mNormals.unpackFloats(2, 8) - val signs = mCompressedMesh.mNormalSigns.unpackInts() - val normals = FloatArray((mCompressedMesh.mNormals.mNumItems / 2u * 3u).toInt()) - for (i in 0 until (mCompressedMesh.mNormals.mNumItems / 2u).toInt()) { - var x = normalData[i * 2] - var y = normalData[i * 2 + 1] - val zsqr = 1 - x * x - y * y - var z: Float - if (zsqr >= 0f) { - z = sqrt(zsqr) - } else { - z = 0f - with(Vector3(x, y, z).unit) { - x = this.x.toFloat() - y = this.y.toFloat() - z = this.z.toFloat() - } - } - if (signs[i] == 0) z = -z - normals[i * 3] = x - normals[i * 3 + 1] = y - normals[i * 3 + 2] = z - } - mNormals = normals - } - if (mCompressedMesh.mTangents.mNumItems > 0u) { - val tangentData = mCompressedMesh.mTangents.unpackFloats(2, 8) - val signs = mCompressedMesh.mTangentSigns.unpackInts() - val tangents = FloatArray((mCompressedMesh.mTangents.mNumItems / 2u * 4u).toInt()) - for (i in 0 until mCompressedMesh.mTangents.mNumItems.toInt() / 2) { - var x = tangentData[i * 2] - var y = tangentData[i * 2 + 1] - val zsqr = 1 - x * x - y * y - var z: Float - if (zsqr >= 0f) { - z = sqrt(zsqr) - } else { - z = 0f - with(Vector3(x, y, z).unit) { - x = this.x.toFloat() - y = this.y.toFloat() - z = this.z.toFloat() - } - } - if (signs[i * 2] == 0) z = -z - val w = if (signs[i * 2 + 1] > 0) 1f else -1f - tangents[i * 4] = x - tangents[i * 4 + 1] = y - tangents[i * 4 + 2] = z - tangents[i * 4 + 3] = w - } - mTangents = tangents - } - if (unityVersion[0] >= 5) { - if (mCompressedMesh.mFloatColors!!.mNumItems > 0u) { - mColors = mCompressedMesh.mFloatColors.unpackFloats(1, 4) - } - } - if (mCompressedMesh.mWeights.mNumItems > 0u) { - val weights = mCompressedMesh.mWeights.unpackInts() - val boneIndices = mCompressedMesh.mBoneIndices.unpackInts() - mSkin = reader.readArrayOf(mVertexCount) { BoneWeights4() } - var bonePos = 0; var boneIndexPos = 0; var j = 0; var sum = 0 - for (i in 0 until mCompressedMesh.mWeights.mNumItems.toInt()) { - with(mSkin[bonePos]) { - weight[j] = weights[i] / 31f - boneIndex[j] = boneIndices[boneIndexPos++] - } - j++; sum += weights[i] - if (sum >= 31) { - while (j < 4) { - with(mSkin[bonePos]) { - weight[j] = 0f - boneIndex[j] = 0 - } - j++ - } - bonePos++ - j = 0; sum = 0 - } else if (j == 3) { - with(mSkin[bonePos]) { - weight[j] = (31 - sum) / 31f - boneIndex[j] = boneIndices[boneIndexPos++] - } - bonePos++ - j = 0; sum = 0 - } - } - } - if (mCompressedMesh.mTriangles.mNumItems > 0u) { - mIndexBuffer = with(mCompressedMesh.mTriangles.unpackInts()) { Array(size) { this[it].toUInt() } } - } - if (with(mCompressedMesh.mColors) { this != null && mNumItems > 0u }) { - mCompressedMesh.mColors!!.mNumItems *= 4u - mCompressedMesh.mColors!!.mBitSize = (mCompressedMesh.mColors.mBitSize / 4u).toUByte() - val num = mCompressedMesh.mColors.mNumItems.toInt() - val tempColors = mCompressedMesh.mColors.unpackInts() - val colors = FloatArray(num) - for (v in 0 until num) { - colors[v] = tempColors[v] / 255f - } - } - //endregion - } - //region getTriangle - for (subMesh in mSubMeshes) { - var firstIdx = (subMesh.firstByte / 2u).toInt() - if (!mUse16BitIndices) { - firstIdx /= 2 - } - val indexCount = subMesh.indexCount.toInt() - if (subMesh.topology == GfxPrimitiveType.Triangles) { - for (i in 0 until indexCount step 3) { - with(indices) { - add(mIndexBuffer[firstIdx + i]) - add(mIndexBuffer[firstIdx + i + 1]) - add(mIndexBuffer[firstIdx + i + 2]) - } - } - } else if (unityVersion[0] < 4 && subMesh.topology == GfxPrimitiveType.TriangleStrip) { - var triIndex = 0u - for (i in 0 until indexCount - 2) { - val a = mIndexBuffer[firstIdx + i] - val b = mIndexBuffer[firstIdx + i + 1] - val c = mIndexBuffer[firstIdx + i + 2] - if (a == b || a == c || b == c) continue - if (i.and(1) == 1) { - indices.add(b) - indices.add(a) - } else { - indices.add(a) - indices.add(b) - } - indices.add(c) - triIndex += 3u - } - subMesh.indexCount = triIndex - } else if (subMesh.topology == GfxPrimitiveType.Quads) { - for (q in 0 until indexCount step 4) { - for (x in intArrayOf(0, 1, 2, 0, 2, 3)) { - indices.add(mIndexBuffer[firstIdx + q + x]) - } - } - } else { - throw UnsupportedFormatException("Failed getting triangles. Submesh topology is lines or points.") - } - } - //endregion - //endregion - mIndices = indices.toTypedArray() - } - - val exportString: String - get() { - if (mVertexCount < 0) return "" - val builder = StringBuilder() - builder.append("g $mName\r\n") - if (mVertices.isEmpty()) return "" - var c = if (mVertices.size == mVertexCount * 4) 4 else 3 - for (v in 0 until mVertexCount) { - builder.append("v ${"%.7G"(-mVertices[v * c])} " + - "${"%.7G"(mVertices[v * c + 1])} " + - "${"%.7G"(mVertices[v * c + 2])}\r\n") - } - if (mUV0.isNotEmpty()) { - c = when (mUV0.size) { - mVertexCount * 2 -> 2 - mVertexCount * 3 -> 3 - else -> 4 - } - for (vt in 0 until mVertexCount) { - builder.append("vt ${"%.7G"(mUV0[vt * c]).trimEnd('0')} " + - "${"%.7G"(mUV0[vt * c + 1]).trimEnd('0')}\r\n") - } - } - if (mNormals.isNotEmpty()) { - when(mNormals.size) { - mVertexCount * 3 -> c = 3 - mVertexCount * 4 -> c = 4 - } - for (vn in 0 until mVertexCount) { - builder.append("vn ${"%.7G"(-mNormals[vn * c])} " + - "${"%.7G"(mNormals[vn * c + 1])} " + - "${"%.7G"(mNormals[vn * c + 2])}\r\n") - } - } - var sum = 0 - for (i in mSubMeshes.indices) { - builder.append("g ${mName}_$i\r\n") - val end = sum + mSubMeshes[i].indexCount.toInt() / 3 - for (f in sum until end) { - val v0 = mIndices[f * 3 + 2] + 1u - val v1 = mIndices[f * 3 + 1] + 1u - val v2 = mIndices[f * 3] + 1u - builder.append("f $v0/$v0/$v0 $v1/$v1/$v1 $v2/$v2/$v2\r\n") - } - sum = end - } - return builder.toString().replace("NaN", "0") - } - - val exportVertices: Array - get() { - val c = if (mVertices.size == mVertexCount * 4) 4 else 3 - return Array(mVertexCount) { Vector3(mVertices[it * c], mVertices[it * c + 1], mVertices[it * c + 2]) } - } - - val exportUV: Array - get() { - return if (mUV0.isEmpty()) arrayOf() - else { - val c = when (mUV0.size) { - mVertexCount * 2 -> 2 - mVertexCount * 3 -> 3 - else -> 4 - } - Array(mVertexCount) { Vector2(mUV0[it * c], mUV0[it * c + 1]) } - } - } - - val exportNormals: Array - get() { - return if (mNormals.isEmpty()) arrayOf() - else { - var c = when (mUV0.size) { - mVertexCount * 2 -> 2 - mVertexCount * 3 -> 3 - else -> 4 - } - when(mNormals.size) { - mVertexCount * 3 -> c = 3 - mVertexCount * 4 -> c = 4 - } - Array(mVertexCount) { Vector3(mNormals[it * c], mNormals[it * c + 1], mNormals[it * c + 2]) } - } - } - - val exportFaces: Array> - get() { - var sum = 0 - return Array(mSubMeshes.size) { - val end = sum + mSubMeshes[it].indexCount.toInt() / 3 - val v = mutableListOf() - for (f in sum until end) { - v.add(Vector3( - (mIndices[f * 3 + 2] + 1u).toDouble(), - (mIndices[f * 3 + 1] + 1u).toDouble(), - (mIndices[f * 3] + 1u).toDouble() - )) - } - sum = end - v.toTypedArray() - } - } - - private fun ByteArray.toIntArray(vertexFormat: VertexFormat): IntArray { - val len = size / vertexFormat.size.toInt() - val result = IntArray(len) - for (i in 0 until len) { - when (vertexFormat) { - VertexFormat.UInt8, - VertexFormat.SInt8 -> result[i] = this[i].toIntBits() - VertexFormat.UInt16, - VertexFormat.SInt16 -> { - result[i] = ByteBuffer.wrap(this[i * 2, 2]).short.toInt() - } - VertexFormat.UInt32, - VertexFormat.SInt32 -> { - result[i] = ByteBuffer.wrap(this[i * 4, 4]).int - } - else -> { } - } - } - return result - } - - private fun ByteArray.toFloatArray(vertexFormat: VertexFormat): FloatArray { - val len = size / vertexFormat.size.toInt() - val result = FloatArray(len) - for (i in 0 until len) { - when (vertexFormat) { - VertexFormat.Float -> { - result[i] = ByteBuffer.wrap(this[i * 4, 4]).float - } - VertexFormat.Float16 -> { - result[i] = this[i * 2, 2].toHalf() - } - VertexFormat.UNorm8 -> { - result[i] = maxOf(get(i) / 127f, -1f) - } - VertexFormat.SNorm8 -> { - result[i] = ByteBuffer.wrap(this[i * 2, 2]).short / 65536f - } - VertexFormat.SNorm16 -> { - result[i] = maxOf( - ByteBuffer.wrap(this[i * 2, 2]).short / 32767f, - -1f - ) - } - else -> { } - } - } - return result - } - - companion object { - private const val kInfoBitsPerUV = 4 - private const val kUVDimensionMask = 3u - private const val kUVChannelExists = 4u - private const val kMaxTexCoordShaderChannels = 8 - } -} - -internal class MeshHelper private constructor() { - companion object { - private val vertexFormatMap = mapOf( - VertexChannelFormat.Float to VertexFormat.Float, - VertexChannelFormat.Float16 to VertexFormat.Float16, - VertexChannelFormat.Color to VertexFormat.UNorm8, - VertexChannelFormat.Byte to VertexFormat.UInt8, - VertexChannelFormat.UInt32 to VertexFormat.UInt32 - ) - private val vertexFormat2017Map = mapOf( - *(VertexFormat.values().map { vf -> - VertexFormat2017.valueOf(vf.name) to vf - } + listOf(VertexFormat2017.Color to VertexFormat.UNorm8)) - .toTypedArray() - ) - internal fun UByte.toVertexFormat(version: IntArray): VertexFormat { - return if (version[0] < 2017) { - val vcf = VertexChannelFormat.of(toInt()) - vertexFormatMap[vcf] ?: throw NoSuchElementException(vcf.name) - } else if (version[0] < 2019) { - val vf2017 = VertexFormat2017.of(toInt()) - vertexFormat2017Map[vf2017] ?: throw NoSuchElementException(vf2017.name) - } else { - VertexFormat.of(toInt()) - } - } - } -} - -internal enum class VertexChannelFormat { - Float, - Float16, - Color, - Byte, - UInt32; - - companion object { - fun of(value: Int): VertexChannelFormat { - return values()[value] - } - } -} - -internal enum class VertexFormat2017 { - Float, - Float16, - Color, - UNorm8, - SNorm8, - UNorm16, - SNorm16, - UInt8, - SInt8, - UInt16, - SInt16, - UInt32, - SInt32; - - companion object { - fun of(value: Int): VertexFormat2017 { - return values()[value] - } - } -} - -internal enum class VertexFormat(val size: UInt) { - Float(4u), - Float16(2u), - UNorm8(1u), - SNorm8(1u), - UNorm16(2u), - SNorm16(2u), - UInt8(1u), - SInt8(1u), - UInt16(2u), - SInt16(2u), - UInt32(4u), - SInt32(4u); - - val isIntFormat get() = this >= UInt8 - - companion object { - fun of(value: Int): VertexFormat { - return values()[value] - } - } -} - -class MinMaxAABB internal constructor(reader: EndianBinaryReader) { - val mMin = reader.readVector3() - val mMax = reader.readVector3() -} - -class CompressedMesh internal constructor(reader: ObjectReader) { - val mVertices = PackedFloatVector(reader) - val mUV = PackedFloatVector(reader) - val mBindPoses = if (reader.unityVersion[0] < 5) PackedFloatVector(reader) else null - val mNormals = PackedFloatVector(reader) - val mTangents = PackedFloatVector(reader) - val mWeights = PackedIntVector(reader) - val mNormalSigns = PackedIntVector(reader) - val mTangentSigns = PackedIntVector(reader) - val mFloatColors = if (reader.unityVersion[0] >= 5) PackedFloatVector(reader) else null - val mBoneIndices = PackedIntVector(reader) - val mTriangles = PackedIntVector(reader) - val mColors: PackedIntVector? - val mUVInfo: UInt - - init { - if (reader.unityVersion >= intArrayOf(3, 5)) { - if (reader.unityVersion[0] < 5) { - mColors = PackedIntVector(reader) - mUVInfo = 0u - } else { - mUVInfo = reader.readUInt() - mColors = null - } - } else { - mUVInfo = 0u - mColors = null - } - } -} - -class StreamInfo { - val channelMask: UInt - val offset: UInt - val stride: UInt - val align: UInt - val dividerOp: UByte - val frequency: UShort - - internal constructor(reader: ObjectReader) { - channelMask = reader.readUInt() - offset = reader.readUInt() - if (reader.unityVersion[0] < 4) { - stride = reader.readUInt() - align = reader.readUInt() - dividerOp = 0u - frequency = 0u - } else { - stride = reader.readByte().toUInt() - dividerOp = reader.readByte() - frequency = reader.readUShort() - align = 0u - } - } - - internal constructor(c: UInt, o: UInt, s: UInt, d: UByte, f: UShort) { - channelMask = c - offset = o - stride = s - align = 0u - dividerOp = d - frequency = f - } -} - -class ChannelInfo { - val stream: UByte - val offset: UByte - val format: UByte - var dimension: UByte - internal set - - internal constructor(reader: ObjectReader) { - stream = reader.readByte() - offset = reader.readByte() - format = reader.readByte() - dimension = reader.readByte() and 0xfu - } - - internal constructor(data: ChannelInfoInternal) { - stream = data.stream - offset = data.offset - format = data.format - dimension = data.dimension - } -} - -internal data class ChannelInfoInternal( - var stream: UByte = 0u, - var offset: UByte = 0u, - var format: UByte = 0u, - var dimension: UByte = 0u -) - -class VertexData internal constructor(reader: ObjectReader) { - val mCurrentChannels = if (reader.unityVersion[0] < 2018) reader.readUInt() else 0u - val mVertexCount = reader.readUInt() - val mChannels: Array - val mStreams: Array - var mDataSize: ByteArray - internal set - - init { - val version = reader.unityVersion - var channels = emptyArray() - if (version[0] >= 4) { - channels = reader.readArrayOf { ChannelInfo(reader) } - } - if (version[0] < 5) { - val streamSize = if (version[0] < 4) 4 else reader.readInt() - mStreams = reader.readArrayOf(streamSize) { StreamInfo(reader) } - if (version[0] < 4) { - //region getChannels - val internalChannels = mutableListOf() - for (i in 1..6) internalChannels.add(ChannelInfoInternal()) - for (s in mStreams.indices) { - val stream = mStreams[s] - val channelMask = BitSet.valueOf(longArrayOf(stream.channelMask.toLong())) - var offset: UByte = 0u - for (j in 0..5) { - if (channelMask[j]) { - val channel = internalChannels[j] - channel.stream = s.toUByte() - channel.offset = offset - when (j) { - 0, 1 -> { - channel.format = 0u - channel.dimension = 3u - } - 2 -> { - channel.format = 2u - channel.dimension = 4u - } - 3, 4 -> { - channel.format = 0u - channel.dimension = 2u - } - 5 -> { - channel.format = 0u - channel.dimension = 4u - } - } - val inc = channel.dimension * channel.format.toVertexFormat(version).size - offset = (offset + inc).toUByte() - } - } - } - channels = with(internalChannels) { Array(size) { ChannelInfo(this[it]) } } - //endregion - } - } else { - //region getStream - val streams = mutableListOf() - val streamCount = channels.maxOf { it.stream }.toInt() + 1 - var offset = 0u - for (k in 0 until streamCount) { - var chnMask = 0u - var stride = 0u - for (chn in channels.indices) { - val channel = channels[chn] - if (channel.stream.toInt() == k && channel.dimension > 0u) { - chnMask = chnMask.or(1u.shl(chn)) - stride += channel.dimension * channel.format.toVertexFormat(version).size - } - } - streams.add(StreamInfo( - chnMask, offset, stride, 0u, 0u - )) - offset += mVertexCount * stride - offset = (offset + 15u).and(15u.inv()) - } - mStreams = streams.toTypedArray() - //endregion - } - mDataSize = reader.readNextByteArray() - mChannels = channels - } -} - -class BoneWeights4 { - val weight: FloatArray - val boneIndex: IntArray - - internal constructor(reader: ObjectReader) { - weight = reader.readNextFloatArray(4) - boneIndex = reader.readNextIntArray(4) - } - - internal constructor() { - weight = FloatArray(4) - boneIndex = IntArray(4) - } -} - -class BlendShapeVertex internal constructor(reader: ObjectReader) { - val vertex = reader.readVector3() - val normal = reader.readVector3() - val tangent = reader.readVector3() - val index = reader.readUInt() -} - -class MeshBlendShape internal constructor(reader: ObjectReader) { - val firstVertex: UInt - val vertexCount: UInt - val hasNormals: Boolean - val hasTangents: Boolean - - init { - val version = reader.unityVersion - val v43 = intArrayOf(4, 3) - if (version < v43) { - reader.readAlignedString() //name - } - firstVertex = reader.readUInt() - vertexCount = reader.readUInt() - if (version < v43) { - reader += 24 //aabbMinDelta, aabbMaxDelta: Vector3 - } - hasNormals = reader.readBool() - hasTangents = reader.readBool() - if (version >= v43) reader.alignStream() - } -} - -class MeshBlendShapeChannel internal constructor(reader: ObjectReader) { - val name = reader.readAlignedString() - val nameHash = reader.readUInt() - val frameIndex = reader.readInt() - val frameCount = reader.readInt() -} - -class BlendShapeData internal constructor(reader: ObjectReader) { - val vertices: Array - val shapes: Array - val channels: Array - val fullWeights: FloatArray - - init { - if (reader.unityVersion >= intArrayOf(4, 3)) { - vertices = reader.readArrayOf { BlendShapeVertex(reader) } - shapes = reader.readArrayOf { MeshBlendShape(reader) } - channels = reader.readArrayOf { MeshBlendShapeChannel(reader) } - fullWeights = reader.readNextFloatArray() - } else { - reader.readArrayOf { MeshBlendShape(reader) } //m_Shapes - reader.alignStream() - reader.readArrayOf { BlendShapeVertex(reader) } //m_ShapeVertices - vertices = emptyArray() - shapes = emptyArray() - channels = emptyArray() - fullWeights = floatArrayOf() - } - } -} - -class GfxPrimitiveType private constructor() { - companion object { - const val Triangles = 0 - const val TriangleStrip = 1 - const val Quads = 2 - } -} - -class SubMash internal constructor(reader: ObjectReader) { - val firstByte = reader.readUInt() - var indexCount = reader.readUInt() - internal set - val topology = reader.readInt() - val triangleCount = if (reader.unityVersion[0] < 4) reader.readUInt() else 0u - val baseVertex = if (reader.unityVersion >= intArrayOf(2017, 3)) reader.readInt() else 0 - val firstVertex: UInt - val vertexCount: UInt - val localAABB: AABB? - - init { - if (reader.unityVersion[0] >= 3) { - firstVertex = reader.readUInt() - vertexCount = reader.readUInt() - localAABB = AABB(reader) - } else { - firstVertex = 0u - vertexCount = 0u - localAABB = null - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/MeshRendererImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/MeshRendererImpl.kt deleted file mode 100644 index 9ea4ae23..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/MeshRendererImpl.kt +++ /dev/null @@ -1,5 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.util.ObjectReader - -class MeshRendererImpl internal constructor(reader: ObjectReader): RendererImpl(reader) \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/MonoBehaviourImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/MonoBehaviourImpl.kt deleted file mode 100644 index 902a1d1b..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/MonoBehaviourImpl.kt +++ /dev/null @@ -1,11 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.data.MonoScript -import io.github.deficuet.unitykt.data.PPtr -import io.github.deficuet.unitykt.util.ObjectReader -import io.github.deficuet.unitykt.util.toJSONObject - -class MonoBehaviourImpl internal constructor(reader: ObjectReader): BehaviourImpl(reader) { - val mScript = PPtr(reader) - val mName = reader.readAlignedString() -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/MonoScriptImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/MonoScriptImpl.kt deleted file mode 100644 index d93e02be..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/MonoScriptImpl.kt +++ /dev/null @@ -1,20 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.util.ObjectReader -import io.github.deficuet.unitykt.util.compareTo - -class MonoScriptImpl internal constructor(reader: ObjectReader): NamedObjectImpl(reader) { - val mClassName: String - val mNameSpace: String - val mAssemblyName: String - - init { - if (unityVersion >= intArrayOf(3, 4)) reader += 4 //m_ExecutionOrder: Int - reader += if (unityVersion < intArrayOf(5)) 4 else 16 //m_PropertiesHash: UInt/Bytes(16) - if (unityVersion < intArrayOf(3)) reader.readAlignedString() - mClassName = reader.readAlignedString() - mNameSpace = if (unityVersion >= intArrayOf(3)) reader.readAlignedString() else "" - mAssemblyName = reader.readAlignedString() - if (unityVersion < intArrayOf(2018, 2)) reader += 1 //m_IsEditorScript: Boolean - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/MovieTextureImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/MovieTextureImpl.kt deleted file mode 100644 index 371be99c..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/MovieTextureImpl.kt +++ /dev/null @@ -1,17 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.data.AudioClip -import io.github.deficuet.unitykt.data.PPtr -import io.github.deficuet.unitykt.util.ObjectReader - -class MovieTextureImpl internal constructor(reader: ObjectReader): TextureImpl(reader) { - val mMovieData: ByteArray - val mAudioClip: PPtr - - init { - reader += 1 //m_Loop: Boolean - reader.alignStream() - mAudioClip = PPtr(reader) - mMovieData = reader.readNextByteArray() - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/NamedObjectImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/NamedObjectImpl.kt deleted file mode 100644 index d07f985a..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/NamedObjectImpl.kt +++ /dev/null @@ -1,7 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.util.ObjectReader - -abstract class NamedObjectImpl internal constructor(reader: ObjectReader): EditorExtensionImpl(reader) { - val mName = reader.readAlignedString() -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/ObjectImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/ObjectImpl.kt deleted file mode 100644 index 042bbf2d..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/ObjectImpl.kt +++ /dev/null @@ -1,28 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.file.BuildTarget -import io.github.deficuet.unitykt.util.ObjectReader -import io.github.deficuet.unitykt.util.toJSONObject -import org.json.JSONObject - -open class ObjectImpl internal constructor(private val reader: ObjectReader) { - val assetFile = reader.assetFile - val mPathID = reader.mPathID - val unityVersion = reader.unityVersion - protected val buildType = reader.buildType - val platform = reader.platform - private val serializedType = reader.serializedType - val bytes: ByteArray get() { return reader.bytes } - - init { - println("Object(${reader.type}) path id $mPathID initialized") - reader.position = 0 - if (platform == BuildTarget.NoTarget) reader += 4 //m_ObjectHideFlags: UInt - } - - fun dump() = serializedType?.typeTree?.readTypeString(reader) - fun toType() = serializedType?.typeTree?.readType(reader) - - val typeTreeJson: JSONObject? get() = toType()?.toJSONObject() - val typeTreeJsonString: String get() = typeTreeJson?.toString(4) ?: "null" -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/PlayerSettingImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/PlayerSettingImpl.kt deleted file mode 100644 index 6167df76..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/PlayerSettingImpl.kt +++ /dev/null @@ -1,35 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.util.ObjectReader -import io.github.deficuet.unitykt.util.compareTo - -class PlayerSettingImpl internal constructor(reader: ObjectReader): ObjectImpl(reader) { - val companyName: String - val productName: String - - init { - if (unityVersion >= intArrayOf(5, 4)) { - reader += 16 //productGUID: ByteArrat(16) - } - reader += 1 //AndroidProfiler: Boolean - reader.alignStream() - reader += 8 //defaultScreenOrientation, targetDevice: Int - if (unityVersion < intArrayOf(5, 3)) { - if (unityVersion[0] < 5) { - reader += 4 //targetPlatform: Int - if (unityVersion >= intArrayOf(4, 6)) { - reader += 4 //targetIOSGraphics: Int - } - } - reader += 4 //targetResolution: Int - } else { - reader += 1 //useOnDemandResources: Boolean - reader.alignStream() - } - if (unityVersion >= intArrayOf(3, 5)) { - reader += 4 //accelerometerFrequency: Int - } - companyName = reader.readAlignedString() - productName = reader.readAlignedString() - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/RectTransformImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/RectTransformImpl.kt deleted file mode 100644 index cc0c610d..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/RectTransformImpl.kt +++ /dev/null @@ -1,11 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.util.ObjectReader - -class RectTransformImpl internal constructor(reader: ObjectReader): TransformImpl(reader) { - val mAnchorMin = reader.readVector2() - val mAnchorMax = reader.readVector2() - val mAnchoredPosition = reader.readVector2() - val mSizeDelta = reader.readVector2() - val mPivot = reader.readVector2() -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/RendererImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/RendererImpl.kt deleted file mode 100644 index 65569ffb..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/RendererImpl.kt +++ /dev/null @@ -1,95 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.data.GameObject -import io.github.deficuet.unitykt.data.Material -import io.github.deficuet.unitykt.data.PPtr -import io.github.deficuet.unitykt.data.Transform -import io.github.deficuet.unitykt.util.ObjectReader -import io.github.deficuet.unitykt.util.compareTo - -abstract class RendererImpl internal constructor(reader: ObjectReader): ComponentImpl(reader) { - val mMaterials: Array> - val mStaticBatchInfo: StaticBatchInfo? - val mSubsetIndices: Array - - init { - val v43 = intArrayOf(4, 3) - if (unityVersion[0] < 5) { - //m_Enabled, m_CastShadows, m_ReceiveShadows: Boolean, m_LightmapIndex: UByte - reader += 4 - } else { - if (unityVersion >= intArrayOf(5, 4)) { - reader += 3 //m_Enabled: Boolean, m_CastShadows, m_ReceiveShadows: UByte - if (unityVersion >= intArrayOf(2017, 2)) { - reader += 1 //m_DynamicOccludee: UByte - } - if (unityVersion[0] >= 2021) { - reader += 1 //m_StaticShadowCaster: UByte - } - reader += 3 //m_MotionVectors, m_LightProbeUsage, m_ReflectionProbeUsage: UByte - if (unityVersion >= intArrayOf(2019, 3)) { - reader += 1 //m_RayTracingMode: UByte - } - if (unityVersion[0] >= 2020) { - reader += 1 //m_RayTraceProcedural: UByte - } - reader.alignStream() - } else { - reader += 1 //m_Enabled: Boolean - reader.alignStream() - reader += 2 //m_CastShadows: UByte, m_ReceiveShadows: Boolean - reader.alignStream() - } - if (unityVersion[0] >= 2018) { - reader += 4 //m_RenderingLayerMask: UInt - } - if (unityVersion >= intArrayOf(2018, 3)) { - reader += 4 //m_RendererPriority - } - reader += 4 //m_LightmapIndex, m_LightmapIndexDynamic: UShort - } - if (unityVersion[0] >= 3) { - reader += 16 //m_LightmapTilingOffset: Vector4 - } - if (unityVersion[0] >= 5) { - reader += 16 //m_LightmapTilingOffsetDynamic: Vector4 - } - mMaterials = reader.readArrayOf { PPtr(reader) } - if (unityVersion[0] < 3) { - reader += 16 //m_LightmapTilingOffset: Vector4 - mStaticBatchInfo = null - mSubsetIndices = emptyArray() - } else { - if (unityVersion >= intArrayOf(5, 5)) { - mStaticBatchInfo = StaticBatchInfo(reader) - mSubsetIndices = emptyArray() - } else { - mSubsetIndices = reader.readNextUIntArray() - mStaticBatchInfo = null - } - PPtr(reader) //m_StaticBatchRoot - } - if (unityVersion >= intArrayOf(5, 4)) { - PPtr(reader) //m_ProbeAnchor - PPtr(reader) //m_LightProbeVolumeOverride - } else if (unityVersion >= intArrayOf(3, 5)) { - reader += 1 //m_UseLightProbes: Boolean - reader.alignStream() - if (unityVersion[0] >= 5) { - reader += 4 //m_ReflectionProbeUsage: Int - } - PPtr(reader) //m_LightProbeAnchor - } - if (unityVersion >= v43) { - //m_SortingLayer: Short / m_SortingLayerID: UInt - reader += if (unityVersion.contentEquals(v43)) 2 else 4 - reader += 2 //m_SortingOrder: Short - reader.alignStream() - } - } -} - -class StaticBatchInfo internal constructor(reader: ObjectReader) { - val firstSubMesh = reader.readUShort() - val subMeshCount = reader.readUShort() -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/ResourceManagerImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/ResourceManagerImpl.kt deleted file mode 100644 index 06a71638..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/ResourceManagerImpl.kt +++ /dev/null @@ -1,11 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.data.Object -import io.github.deficuet.unitykt.data.PPtr -import io.github.deficuet.unitykt.util.ObjectReader - -class ResourceManagerImpl internal constructor(reader: ObjectReader): ObjectImpl(reader) { - val mContainer = reader.readArrayOf { - with(reader) { readAlignedString() to PPtr(reader) } - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/RuntimeAnimatorControllerImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/RuntimeAnimatorControllerImpl.kt deleted file mode 100644 index 297b2710..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/RuntimeAnimatorControllerImpl.kt +++ /dev/null @@ -1,5 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.util.ObjectReader - -abstract class RuntimeAnimatorControllerImpl internal constructor(reader: ObjectReader): NamedObjectImpl(reader) \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/ShaderImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/ShaderImpl.kt deleted file mode 100644 index bede9107..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/ShaderImpl.kt +++ /dev/null @@ -1,1344 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.data.PPtr -import io.github.deficuet.unitykt.data.Shader -import io.github.deficuet.unitykt.data.Texture -import io.github.deficuet.unitykt.export.EndianByteArrayWriter -import io.github.deficuet.unitykt.export.smolv.SmolvDecoder -import io.github.deficuet.unitykt.export.spirv.Disassembler -import io.github.deficuet.unitykt.export.spirv.Module -import io.github.deficuet.unitykt.util.* -import java.nio.ByteOrder - -class ShaderImpl internal constructor(reader: ObjectReader): NamedObjectImpl(reader) { - val mScript: ByteArray - val decompressedSize: UInt - val mSubProgramBlob: ByteArray - val mParsedForm: SerializedShader? - val platforms: Array - val offsets: Array> - val compressedLengths: Array> - val decompressedLengths: Array> - val compressedBlob: ByteArray - - init { - if (unityVersion >= intArrayOf(5, 5)) { - mParsedForm = SerializedShader(reader) - platforms = with(reader.readNextUIntArray()) { - Array(size) { ShaderCompilerPlatform.of(this[it].toInt()) } - } - if (unityVersion >= intArrayOf(2019, 3)) { - offsets = reader.readNestedUIntArray() - compressedLengths = reader.readNestedUIntArray() - decompressedLengths = reader.readNestedUIntArray() - } else { - offsets = arrayOf(reader.readNextUIntArray()) - compressedLengths = arrayOf(reader.readNextUIntArray()) - decompressedLengths = arrayOf(reader.readNextUIntArray()) - } - compressedBlob = reader.readNextByteArray() - reader.alignStream() - reader.readArrayOf { PPtr(reader) } //m_Dependencies - if (unityVersion[0] >= 2018) { - reader.readArrayOf { - reader.readAlignedString() - PPtr(reader) // m_NonModifiableTextures - } - } - reader += 1 //m_ShaderIsBaked - reader.alignStream() - mScript = byteArrayOf() - decompressedSize = 0u - mSubProgramBlob = byteArrayOf() - } else { - mScript = reader.readNextByteArray() - reader.alignStream() - reader.readAlignedString() //m_PathName - if (unityVersion >= intArrayOf(5, 3)) { - decompressedSize = reader.readUInt() - mSubProgramBlob = reader.readNextByteArray() - } else { - decompressedSize = 0u - mSubProgramBlob = byteArrayOf() - } - mParsedForm = null - platforms = emptyArray() - offsets = emptyArray() - compressedLengths = emptyArray() - decompressedLengths = emptyArray() - compressedBlob = byteArrayOf() - } - } - - val exportString: String - get() { - if (mSubProgramBlob.isNotEmpty()) { - val decompressed = CompressUtils.lz4Decompress(mSubProgramBlob, decompressedSize.toInt()) - EndianByteArrayReader(decompressed).use { blobReader -> - val program = ShaderProgram(blobReader, unityVersion) - return exportHeader + program.export(mScript.decodeToString()) - } - } - if (compressedBlob.isNotEmpty()) { - return exportHeader + convertSerializedShader() - } - return exportHeader + mScript.decodeToString() - } - - private fun convertSerializedShader(): String { - val programsList = mutableListOf() - for (i in platforms.indices) { - for (j in offsets[i].indices) { - val length = compressedLengths[i][j].toInt() - val compressedByte = ByteArray(length) - System.arraycopy( - compressedBlob, offsets[i][j].toInt(), - compressedByte, 0, length - ) - val decompressedByte = CompressUtils.lz4Decompress( - compressedByte, decompressedLengths[i][j].toInt() - ) - EndianByteArrayReader(decompressedByte, endian = ByteOrder.LITTLE_ENDIAN).use { blobReader -> - if (j == 0) { - programsList.add(ShaderProgram(blobReader, unityVersion)) - } - programsList[i].read(blobReader, j) - } - } - } - val programs = programsList.toTypedArray() - return StringBuilder().apply { - append("Shader \"${mParsedForm!!.mName}\" {\n") - //region convertSerializedProperties - append("Properties {\n") - for (prop in mParsedForm.mPropInfo.mProps) { - prop.toString(this) - } - append("}\n") - //endregion - for (subShader in mParsedForm.mSubShaders) { - //region convertSerializedSubShader - append("SubShader {\n") - if (subShader.mLOD != 0) { - append(" LOD ${subShader.mLOD}\n") - } - subShader.mTags.toString(this, 1) - for (passe in subShader.mPasses) { - passe.toString(this, platforms, programs) - } - append("}\n") - //endregion - } - if (mParsedForm.mFallbackName.isNotBlank()) { - append("Fallback \"${mParsedForm.mFallbackName}\"\n") - } - if (mParsedForm.mCustomEditorName.isNotBlank()) { - append("CustomEditor \"${mParsedForm.mCustomEditorName}\"\n") - } - append("}") - }.toString() - } - - companion object { - internal const val exportHeader = "" + - "//////////////////////////////////////////\n" + - "//\n" + - "// NOTE: This is *not* a valid shader file\n" + - "//\n" + - "//////////////////////////////////////////\n" - } -} - -internal class ShaderSubProgramEntry(reader: EndianBinaryReader, version: IntArray) { - val offset = reader.readInt() - val length = reader.readInt() - val segment = if (version >= intArrayOf(2019, 3)) reader.readInt() else 0 -} - -internal class ShaderProgram(reader: EndianBinaryReader, version: IntArray) { - val entries = reader.readArrayOf { - ShaderSubProgramEntry(reader, version) - } - val mSubPrograms = Array(entries.size) { null } - - fun read(reader: EndianBinaryReader, segment: Int) { - for ((i, e) in entries.withIndex()) { - if (e.segment == segment) { - reader.position = e.offset.toLong() - mSubPrograms[i] = ShaderSubProgram(reader) - } - } - } - - fun export(shader: String): String { - return exportRegex.replace(shader) { - mSubPrograms[it.groups[1]!!.value.toInt()]?.export() ?: "" - } - } - - companion object { - private val exportRegex = Regex("GpuProgramIndex (.+)") - } -} - -internal class ShaderSubProgram(private val reader: EndianBinaryReader) { - private val mVersion = reader.readInt() - private val mProgramType = ShaderGpuProgramType.of(reader.readInt()) - private val mKeywords: Array - private val mLocalKeywords: Array - private val mProgramCode: ByteArray - - init { - reader += if (mVersion >= 201608170) 16 else 12 - mKeywords = reader.readNextStringArray() - mLocalKeywords = if (mVersion in 201806140 until 202012090) { - reader.readNextStringArray() - } else emptyArray() - mProgramCode = reader.readNextByteArray() - reader.alignStream() - } - - fun export(): String { - val builder = StringBuilder() - if (mKeywords.isNotEmpty()) { - builder.append("Keywords { ") - mKeywords.forEach { builder.append("\"$it\" ") } - builder.append("}\n") - } - if (mLocalKeywords.isNotEmpty()) { - builder.append("Local Keywords { ") - mLocalKeywords.forEach { builder.append("\"$it\" ") } - builder.append("}\n") - } - builder.append("\"") - if (mProgramCode.isNotEmpty()) { - when (mProgramType) { - ShaderGpuProgramType.GLLegacy, - ShaderGpuProgramType.GLES31AEP, - ShaderGpuProgramType.GLES31, - ShaderGpuProgramType.GLES3, - ShaderGpuProgramType.GLES, - ShaderGpuProgramType.GLCore32, - ShaderGpuProgramType.GLCore41, - ShaderGpuProgramType.GLCore43 -> { - builder.append(mProgramCode.decodeToString(Charsets.UTF_8)) - } - ShaderGpuProgramType.DX9VertexSM20, - ShaderGpuProgramType.DX9VertexSM30, - ShaderGpuProgramType.DX9PixelSM20, - ShaderGpuProgramType.DX9PixelSM30 -> { - builder.append("// shader disassembly not supported on DXBC") - } - ShaderGpuProgramType.DX10Level9Vertex, - ShaderGpuProgramType.DX10Level9Pixel, - ShaderGpuProgramType.DX11VertexSM40, - ShaderGpuProgramType.DX11VertexSM50, - ShaderGpuProgramType.DX11PixelSM40, - ShaderGpuProgramType.DX11PixelSM50, - ShaderGpuProgramType.DX11GeometrySM40, - ShaderGpuProgramType.DX11GeometrySM50, - ShaderGpuProgramType.DX11HullSM50, - ShaderGpuProgramType.DX11DomainSM50 -> { - builder.append("// shader disassembly not supported on DXBC") - } - ShaderGpuProgramType.MetalVS, - ShaderGpuProgramType.MetalFS -> { - val fourCC = reader.readUInt() - if (fourCC == 0xF00DCAFEu) { - val offset = reader.readInt() - reader.position = offset.toLong() - } - reader.readStringUntilNull() - val buff = reader.read(with(reader) { length - position }.toInt()) - builder.append(buff.decodeToString(Charsets.UTF_8)) - } - ShaderGpuProgramType.SPIRV -> { - builder.append( - try { - mProgramCode.covertToSpirV() - } catch (e: Exception) { - "// disassembly error ${e.message}\n" - } - ) - } - ShaderGpuProgramType.ConsoleVS, - ShaderGpuProgramType.ConsoleFS, - ShaderGpuProgramType.ConsoleHS, - ShaderGpuProgramType.ConsoleDS, - ShaderGpuProgramType.ConsoleGS -> { - builder.append(mProgramCode.decodeToString(Charsets.UTF_8)) - } - else -> { builder.append("//shader disassembly not supported on $mProgramType") } - } - } - builder.append("\"") - return builder.toString() - } - - companion object { - private fun ByteArray.covertToSpirV(): String { - val builder = StringBuilder() - EndianByteArrayReader(this, endian = ByteOrder.LITTLE_ENDIAN).use { reader -> - reader += 4 - var minOffset = reader.length - for (i in 0..4) { - if (reader.position >= minOffset) break - val offset = reader.readInt() - val size = reader.readInt() - if (size > 0) { - if (offset < minOffset) minOffset = offset.toLong() - reader.withMark { - position = offset.toLong() - val decodedSize = SmolvDecoder.getDecodedBufferSize(reader) - if (decodedSize == 0) return "// disassembly error: Invalid SMOL-V shader header" - EndianByteArrayWriter(decodedSize, endianType = ByteOrder.LITTLE_ENDIAN).use { writer -> - if (SmolvDecoder.decode(this, size, writer)) { - val module = Module.readFrom(writer.array) - builder.append(Disassembler().disassemble(module)) - } - } - } - } - } - } - return builder.toString() - } - } -} - -class Hash128 internal constructor(reader: EndianBinaryReader) { - val bytes = reader.read(16) -} - -class MatrixParameter internal constructor(reader: EndianBinaryReader) { - val mNameIndex = reader.readInt() - val mIndex = reader.readInt() - val mArraySize = reader.readInt() - val mType = reader.readSByte() - val mRowCount = reader.readSByte() - - init { reader.alignStream() } -} - -class VectorParameter internal constructor(reader: EndianBinaryReader) { - val mNameIndex = reader.readInt() - val mIndex = reader.readInt() - val mArraySize = reader.readInt() - val mType = reader.readSByte() - val mDim = reader.readSByte() - - init { reader.alignStream() } -} - -class StructParameter internal constructor(reader: EndianBinaryReader) { - val mMatrixParams: Array - val mVectorParams: Array - - init { - reader += 16 //m_NameIndex, m_Index, m_ArraySize, m_StructSize: Int - mVectorParams = reader.readArrayOf { VectorParameter(reader) } - mMatrixParams = reader.readArrayOf { MatrixParameter(reader) } - } -} - -class SamplerParameter internal constructor(reader: EndianBinaryReader) { - val sampler = reader.readUInt() - val bindPoint = reader.readInt() -} - -enum class TextureDimension(val id: Int) { - Unknown(-1), - None(0), - Any(1), - Tex2D(2), - Tex3D(3), - Cube(4), - Tex2DArray(5), - CubeArray(6); - - companion object { - fun of(value: Int): TextureDimension { - return values().firstOrNull { it.id == value } ?: Unknown - } - } -} - -class SerializedTextureProperty internal constructor(reader: EndianBinaryReader) { - val mDefaultName = reader.readAlignedString() - val mTexDim = TextureDimension.of(reader.readInt()) -} - -enum class SerializedPropertyType(val id: Int) { - Color(0), - Vector(1), - Float(2), - Range(3), - Texture(4); -// Integer(5); - - companion object { - fun of(value: Int): SerializedPropertyType { - return values().firstOrNull { it.id == value } ?: Color - } - } -} - -class SerializedProperty internal constructor(reader: EndianBinaryReader) { - val mName = reader.readAlignedString() - val mDescription = reader.readAlignedString() - val mAttributes = reader.readNextStringArray() - val mType = SerializedPropertyType.of(reader.readInt()) - val mFlags = reader.readUInt() - val mDefValue = reader.readNextFloatArray(4) - val mDefTexture = SerializedTextureProperty(reader) - - internal fun toString(builder: StringBuilder): StringBuilder { - for (attribute in mAttributes) { - builder.append("[$attribute] ") - } - builder.append("$mName (\"$mDescription\", ") - builder.append( - when (mType) { - SerializedPropertyType.Color -> "Color" - SerializedPropertyType.Vector -> "Vector" - SerializedPropertyType.Float -> "Float" - SerializedPropertyType.Range -> "Range(${mDefValue[1]}, ${mDefValue[2]})" - SerializedPropertyType.Texture -> { - when (mDefTexture.mTexDim) { - TextureDimension.Any -> "any" - TextureDimension.Tex2D -> "2D" - TextureDimension.Tex3D -> "3D" - TextureDimension.Cube -> "Cube" - TextureDimension.Tex2DArray -> "2DArray" - TextureDimension.CubeArray -> "CubeArray" - else -> "" - } - } - } - ) - builder.append(") = ") - builder.append( - when (mType) { - SerializedPropertyType.Color, - SerializedPropertyType.Vector -> { - "(${mDefValue[0]},${mDefValue[1]},${mDefValue[2]},${mDefValue[3]})" - } - SerializedPropertyType.Float, - SerializedPropertyType.Range -> { - mDefValue[0] - } - SerializedPropertyType.Texture -> { - "\"${mDefTexture.mDefaultName}\" { }" - } - } - ) - builder.append("\n") - return builder - } -} - -class SerializedProperties internal constructor(reader: EndianBinaryReader) { - val mProps = reader.readArrayOf { SerializedProperty(reader) } -} - -class SerializedShaderFloatValue internal constructor(reader: EndianBinaryReader) { - val value = reader.readFloat() - val name = reader.readAlignedString() - - internal fun convertBlendFactor(): String { - return when (value) { - 0f -> "Zero" - 2f -> "DstColor" - 3f -> "SrcColor" - 4f -> "OneMinusDstColor" - 5f -> "SrcAlpha" - 6f -> "OneMinusSrcColor" - 7f -> "DstAlpha" - 8f -> "OneMinusDstAlpha" - 9f -> "SrcAlphaSaturate" - 10f -> "OneMinusSrcAlpha" - else -> "One" - } - } - - internal fun convertBlendOp(): String { - return when (value) { - 1f -> "Sub" - 2f -> "RevSub" - 3f -> "Min" - 4f -> "Max" - 5f -> "LogicalClear" - 6f -> "LogicalSet" - 7f -> "LogicalCopy" - 8f -> "LogicalCopyInverted" - 9f -> "LogicalNoop" - 10f -> "LogicalInvert" - 11f -> "LogicalAnd" - 12f -> "LogicalNand" - 13f -> "LogicalOr" - 14f -> "LogicalNor" - 15f -> "LogicalXor" - 16f -> "LogicalEquiv" - 17f -> "LogicalAndReverse" - 18f -> "LogicalAndInverted" - 19f -> "LogicalOrReverse" - 20f -> "LogicalOrInverted" - else -> "Add" - } - } - - internal fun convertStencilOp(): String { - return when (value) { - 1f -> "Zero" - 2f -> "Replace" - 3f -> "IncrSat" - 4f -> "DecrSat" - 5f -> "Invert" - 6f -> "IncrWrap" - 7f -> "DecrWrap" - else -> "Keep" - } - } - - internal fun convertStencilComp(): String { - return when (value) { - 0f -> "Disabled" - 1f -> "Never" - 2f -> "Less" - 3f -> "Equal" - 4f -> "LEqual" - 5f -> "Greater" - 6f -> "NotEqual" - 7f -> "GEqual" - else -> "Always" - } - } -} - -class SerializedShaderRTBlendState internal constructor(reader: EndianBinaryReader) { - val srcBlend = SerializedShaderFloatValue(reader) - val destBlend = SerializedShaderFloatValue(reader) - val srcBlendAlpha = SerializedShaderFloatValue(reader) - val destBlendAlpha = SerializedShaderFloatValue(reader) - val blendOp = SerializedShaderFloatValue(reader) - val blendOpAlpha = SerializedShaderFloatValue(reader) - val colMask = SerializedShaderFloatValue(reader) -} - -class SerializedStencilOp internal constructor(reader: EndianBinaryReader) { - val pass = SerializedShaderFloatValue(reader) - val fail = SerializedShaderFloatValue(reader) - val zFail = SerializedShaderFloatValue(reader) - val comp = SerializedShaderFloatValue(reader) - - internal fun toString(builder: StringBuilder, suffix: String): StringBuilder { - return builder.apply { - append(" Comp$suffix ${comp.convertStencilComp()}") - append(" Pass$suffix ${pass.convertStencilOp()}") - append(" Fail$suffix ${fail.convertStencilOp()}") - append(" ZFail$suffix ${zFail.convertStencilOp()}") - } - } -} - -class SerializedShaderVectorValue internal constructor(reader: EndianBinaryReader) { - val x = SerializedShaderFloatValue(reader) - val y = SerializedShaderFloatValue(reader) - val z = SerializedShaderFloatValue(reader) - val w = SerializedShaderFloatValue(reader) - val name = reader.readAlignedString() -} - -enum class FogMode(val id: Int) { - Unknown(-1), - Disabled(0), - Linear(1), - Exp(2), - Exp2(3); - - companion object { - fun of(value: Int): FogMode { - return values().firstOrNull { it.id == value } ?: Disabled - } - } -} - -class SerializedTagMap internal constructor(reader: EndianBinaryReader) { - val tags = reader.readArrayOf { with(reader) { readAlignedString() to readAlignedString() } } - - internal fun toString(builder: StringBuilder, indent: Int): StringBuilder { - if (tags.isNotEmpty()) { - builder.append(" ".repeat(indent)) - builder.append("Tags { ") - for (pair in tags) { - builder.append("\"${pair.first}\" = \"${pair.second}\"") - } - builder.append("}\n") - } - return builder - } -} - -class SerializedShaderState internal constructor(reader: ObjectReader) { - val mName = reader.readAlignedString() - val rtBlend = reader.readArrayOf(8) { SerializedShaderRTBlendState(reader) } - val rtSeparateBlend = reader.readBool() - val zClip: SerializedShaderFloatValue? - val zTest: SerializedShaderFloatValue - val zWrite: SerializedShaderFloatValue - val culling: SerializedShaderFloatValue - val conservative: SerializedShaderFloatValue? - val offsetFactor: SerializedShaderFloatValue - val offsetUnits: SerializedShaderFloatValue - val alphaToMask: SerializedShaderFloatValue - val stencilOp: SerializedStencilOp - val stencilOpFront: SerializedStencilOp - val stencilOpBack: SerializedStencilOp - val stencilReadMask: SerializedShaderFloatValue - val stencilWriteMask: SerializedShaderFloatValue - val stencilRef: SerializedShaderFloatValue - val fogStart: SerializedShaderFloatValue - val fogEnd: SerializedShaderFloatValue - val fogDensity: SerializedShaderFloatValue - val fogColor: SerializedShaderVectorValue - val fogMode: FogMode - val gpuProgramID: Int - val mTags: SerializedTagMap - val mLOD: Int - val lighting: Boolean - - init { - val version = reader.unityVersion - reader.alignStream() - zClip = if (version >= intArrayOf(2017, 2)) { - SerializedShaderFloatValue(reader) - } else null - zTest = SerializedShaderFloatValue(reader) - zWrite = SerializedShaderFloatValue(reader) - culling = SerializedShaderFloatValue(reader) - conservative = if (version[0] >= 2020) SerializedShaderFloatValue(reader) else null - offsetFactor = SerializedShaderFloatValue(reader) - offsetUnits = SerializedShaderFloatValue(reader) - alphaToMask = SerializedShaderFloatValue(reader) - stencilOp = SerializedStencilOp(reader) - stencilOpFront = SerializedStencilOp(reader) - stencilOpBack = SerializedStencilOp(reader) - stencilReadMask = SerializedShaderFloatValue(reader) - stencilWriteMask = SerializedShaderFloatValue(reader) - stencilRef = SerializedShaderFloatValue(reader) - fogStart = SerializedShaderFloatValue(reader) - fogEnd = SerializedShaderFloatValue(reader) - fogDensity = SerializedShaderFloatValue(reader) - fogColor = SerializedShaderVectorValue(reader) - fogMode = FogMode.of(reader.readInt()) - gpuProgramID = reader.readInt() - mTags = SerializedTagMap(reader) - mLOD = reader.readInt() - lighting = reader.readBool() - reader.alignStream() - } - - internal fun toString(builder: StringBuilder): StringBuilder { - if (mName.isNotEmpty()) builder.append(" Name \"$mName\"\n") - if (mLOD != 0) builder.append(" LOD ${mLOD}\n") - mTags.toString(builder, 2) - rtBlend.toString(builder) - if (alphaToMask.value > 0f) builder.append(" AlphaToMask On\n") - if (zClip?.value != 1f) builder.append(" ZClip Off\n") - if (zTest.value != 4f) { - builder.append(" ZTest ") - when (zTest.value) { - 0f -> builder.append("Off") - 1f -> builder.append("Never") - 2f -> builder.append("Less") - 3f -> builder.append("Equal") - 5f -> builder.append("Greater") - 6f -> builder.append("NotEqual") - 7f -> builder.append("GEqual") - 8f -> builder.append("Always") - } - builder.append("\n") - } - if (zWrite.value != 1f) builder.append(" ZWrite Off\n") - if (culling.value != 2f) { - builder.append(" Cull ") - when (culling.value) { - 0f -> builder.append("Off") - 1f -> builder.append("Front") - } - builder.append("\n") - } - if (offsetFactor.value != 0f || offsetUnits.value != 0f) { - builder.append(" Offset ${offsetFactor.value}, ${offsetUnits.value}\n") - } - if ( - stencilRef.value != 0f || - stencilReadMask.value != 255f || - stencilWriteMask.value != 255f || - stencilOp.pass.value != 0f || - stencilOp.fail.value != 0f || - stencilOp.zFail.value != 0f || - stencilOp.comp.value != 8f || - stencilOpFront.pass.value != 0f || - stencilOpFront.fail.value != 0f || - stencilOpFront.zFail.value != 0f || - stencilOpFront.comp.value != 8f || - stencilOpBack.pass.value != 0f || - stencilOpBack.fail.value != 0f || - stencilOpBack.zFail.value != 0f || - stencilOpBack.comp.value != 8f - ) { - builder.append(" Stencil {\n") - if (stencilRef.value != 0f) builder.append(" Ref ${stencilRef.value}\n") - if (stencilReadMask.value != 255f) builder.append(" ReadMask ${stencilReadMask.value}\n") - if (stencilWriteMask.value != 255f) builder.append(" WriteMask ${stencilWriteMask.value}\n") - if ( - stencilOp.pass.value != 0f || - stencilOp.fail.value != 0f || - stencilOp.zFail.value != 0f || - stencilOp.comp.value != 8f - ) { - stencilOp.toString(builder, "") - } - if ( - stencilOpFront.pass.value != 0f || - stencilOpFront.fail.value != 0f || - stencilOpFront.zFail.value != 0f || - stencilOpFront.comp.value != 8f) - { - stencilOpFront.toString(builder, "Front") - } - if ( - stencilOpBack.pass.value != 0f || - stencilOpBack.fail.value != 0f || - stencilOpBack.zFail.value != 0f || - stencilOpBack.comp.value != 8f) - { - stencilOpBack.toString(builder, "Back") - } - builder.append(" }\n") - } - if ( - fogMode != FogMode.Unknown || - fogColor.x.value != 0f || - fogColor.y.value != 0f || - fogColor.z.value != 0f || - fogColor.w.value != 0f || - fogDensity.value != 0f || - fogStart.value != 0f || - fogEnd.value != 0f - ) { - builder.append(" Fog {\n") - if (fogMode != FogMode.Unknown) { - builder.append(" Mode ") - when (fogMode) { - FogMode.Disabled -> builder.append("Off") - FogMode.Linear -> builder.append("Linear") - FogMode.Exp -> builder.append("Exp") - FogMode.Exp2 -> builder.append("Exp2") - else -> { } - } - builder.append("\n") - } - if ( - fogColor.x.value != 0f || - fogColor.y.value != 0f || - fogColor.z.value != 0f || - fogColor.w.value != 0f - ) { - builder.append( - " Color (${fogColor.x.value},${fogColor.y.value},${fogColor.z.value},${fogColor.w.value})\n" - ) - } - if (fogDensity.value != 0f) { - builder.append(" Density ${fogDensity.value}\n") - } - if (fogStart.value != 0f || fogEnd.value != 0f) { - builder.append(" Range ${fogStart.value}, ${fogEnd.value}\n") - } - builder.append("\n") - } - return builder.apply { - append(" Lighting ${if (lighting) "On" else "Off"}\n") - append(" GpuProgramID $gpuProgramID") - } - } - - private fun Array.toString(builder: StringBuilder): StringBuilder { - for (i in indices) { - val blend = get(i) - if ( - blend.srcBlend.value != 1f || - blend.destBlend.value != 0f || - blend.srcBlendAlpha.value != 1f || - blend.destBlendAlpha.value != 0f - ) { - builder.append(" Blend ") - if (i != 0 || rtSeparateBlend) { - builder.append("$i ") - } - builder.append("${blend.srcBlend.convertBlendFactor()} ${blend.destBlend.convertBlendFactor()}") - if (blend.srcBlendAlpha.value != 1f || blend.destBlendAlpha.value != 0f) { - builder.append( - ", ${blend.srcBlendAlpha.convertBlendFactor()} ${blend.destBlendAlpha.convertBlendFactor()}" - ) - } - builder.append("\n") - } - if (blend.blendOp.value != 0f || blend.blendOpAlpha.value != 0f) { - builder.append(" BlendOp ") - if (i != 0 || rtSeparateBlend) { - builder.append("$i ") - } - builder.append(blend.blendOp.convertBlendOp()) - if (blend.blendOpAlpha.value != 0f) { - builder.append(", ${blend.blendOpAlpha.convertBlendOp()}") - } - builder.append("\n") - } - val value = blend.colMask.value.toInt() - if (value != 0xF) { - builder.append(" ColorMask ") - if (value == 0) builder.append(0) - else { - when { - value.and(0x2) != 0 -> builder.append("R") - value.and(0x4) != 0 -> builder.append("G") - value.and(0x8) != 0 -> builder.append("B") - value.and(0x1) != 0 -> builder.append("A") - } - } - builder.append(" $i\n") - } - } - return builder - } -} - -class ShaderBindChannel internal constructor(reader: EndianBinaryReader) { - val source = reader.readSByte() - val target = reader.readSByte() -} - -class ParserBindChannels internal constructor(reader: EndianBinaryReader) { - val mChannels = reader.readArrayOf { ShaderBindChannel(reader) } - val mSourceMap: UInt - - init { - reader.alignStream() - mSourceMap = reader.readUInt() - } -} - -class TextureParameter internal constructor(reader: ObjectReader) { - val mNameIndex = reader.readInt() - val mIndex = reader.readInt() - val mSamplerIndex = reader.readInt() - val mDim: Byte - - init { - if (reader.unityVersion >= intArrayOf(2017, 3)) reader += 1 //m_MultiSampled: Boolean - mDim = reader.readSByte() - reader.alignStream() - } -} - -class BufferBinding internal constructor(reader: ObjectReader) { - val mNameIndex = reader.readInt() - val mIndex = reader.readInt() - val mArraySize = if (reader.unityVersion[0] >= 2020) reader.readInt() else 0 -} - -class ConstantBuffer internal constructor(reader: ObjectReader) { - val mNameIndex = reader.readInt() - val mMatrixParams = reader.readArrayOf { MatrixParameter(reader) } - val mVectorParams = reader.readArrayOf { VectorParameter(reader) } - val mStructParams = if (reader.unityVersion >= intArrayOf(2017, 3)) { - reader.readArrayOf { StructParameter(reader) } - } else emptyArray() - val mSize = reader.readInt() - val mIsPartialCB = if (with(reader.unityVersion) { - (this[0] == 2020 && this >= intArrayOf(2020, 3, 2)) || - (this >= intArrayOf(2021, 1, 4)) - }) { - reader.readBool() - } else false - - init { reader.alignStream() } -} - -class UAVParameter internal constructor(reader: EndianBinaryReader) { - val mNameIndex = reader.readInt() - val mIndex = reader.readInt() - val mOriginalIndex = reader.readInt() -} - -enum class ShaderGpuProgramType(val id: Int) { - Unknown(0), - GLLegacy(1), - GLES31AEP(2), - GLES31(3), - GLES3(4), - GLES(5), - GLCore32(6), - GLCore41(7), - GLCore43(8), - DX9VertexSM20(9), - DX9VertexSM30(10), - DX9PixelSM20(11), - DX9PixelSM30(12), - DX10Level9Vertex(13), - DX10Level9Pixel(14), - DX11VertexSM40(15), - DX11VertexSM50(16), - DX11PixelSM40(17), - DX11PixelSM50(18), - DX11GeometrySM40(19), - DX11GeometrySM50(20), - DX11HullSM50(21), - DX11DomainSM50(22), - MetalVS(23), - MetalFS(24), - SPIRV(25), - ConsoleVS(26), - ConsoleFS(27), - ConsoleHS(28), - ConsoleDS(29), - ConsoleGS(30), - RayTracing(31), - PS5NGGC(32); - - companion object { - fun of(value: Int): ShaderGpuProgramType { - return values().firstOrNull { it.id == value } ?: Unknown - } - } -} - -class SerializedProgramParameters internal constructor(reader: ObjectReader) { - val mVectorParams = reader.readArrayOf { VectorParameter(reader) } - val mMatrixParams = reader.readArrayOf { MatrixParameter(reader) } - val mTextureParams = reader.readArrayOf { TextureParameter(reader) } - val mBufferParams = reader.readArrayOf { BufferBinding(reader) } - val mConstantBuffers = reader.readArrayOf { ConstantBuffer(reader) } - val mConstantBufferBindings = reader.readArrayOf { BufferBinding(reader) } - val mUAVParams = reader.readArrayOf { UAVParameter(reader) } - val mSamplers = reader.readArrayOf { SamplerParameter(reader) } -} - -class SerializedSubProgram internal constructor(reader: ObjectReader) { - val mBlobIndex = reader.readUInt() - val mChannels = ParserBindChannels(reader) - val mKeywordIndices: Array - val mShaderHardwareTier: Byte - val mGpuProgramType: ShaderGpuProgramType - val mParameters: SerializedProgramParameters? - val mVectorParams: Array - val mMatrixParams: Array - val mTextureParams: Array - val mBufferParams: Array - val mConstantBuffers: Array - val mConstantBufferBindings: Array - val mUAVParams: Array - val mSamplers: Array - - init { - val version = reader.unityVersion - if (version[0] >= 2019 && version < intArrayOf(2021, 2)) { - reader.readNextIntArray() //m_GlobalKeywordIndices - reader.alignStream() - reader.readNextIntArray() //m_LocalKeywordIndices - reader.alignStream() - mKeywordIndices = emptyArray() - } else { - mKeywordIndices = reader.readNextUShortArray() - if (version[0] >= 2017) reader.alignStream() - } - mShaderHardwareTier = reader.readSByte() - mGpuProgramType = ShaderGpuProgramType.of(reader.readSByte().toInt()) - reader.alignStream() - if ( - (version[0] == 2020 && version >= intArrayOf(2020, 3, 2)) || - (version >= intArrayOf(2021, 2, 4)) - ) { - mParameters = SerializedProgramParameters(reader) - mVectorParams = emptyArray() - mMatrixParams = emptyArray() - mTextureParams = emptyArray() - mBufferParams = emptyArray() - mConstantBuffers = emptyArray() - mConstantBufferBindings = emptyArray() - mUAVParams = emptyArray() - mSamplers = emptyArray() - } else { - mVectorParams = reader.readArrayOf { VectorParameter(reader) } - mMatrixParams = reader.readArrayOf { MatrixParameter(reader) } - mTextureParams = reader.readArrayOf { TextureParameter(reader) } - mBufferParams = reader.readArrayOf { BufferBinding(reader) } - mConstantBuffers = reader.readArrayOf { ConstantBuffer(reader) } - mConstantBufferBindings = reader.readArrayOf { BufferBinding(reader) } - mUAVParams = reader.readArrayOf { UAVParameter(reader) } - mSamplers = if (version[0] >= 2017) reader.readArrayOf { SamplerParameter(reader) } else emptyArray() - mParameters = null - } - if (version >= intArrayOf(2017, 2)) { - reader += if (version[0] >= 2021) 8 else 4 //m_ShaderRequirements: Long/Int - } - } -} - -class SerializedProgram internal constructor(reader: ObjectReader) { - val mSubPrograms = reader.readArrayOf { SerializedSubProgram(reader) } - val mCommonParameters = if (with(reader.unityVersion) { - (this[0] == 2020 && this >= intArrayOf(2020, 3, 2)) || - (this >= intArrayOf(2021, 1, 4)) - }) SerializedProgramParameters(reader) else null - val mSerializedKeywordStateMask: Array - - init { - if (reader.unityVersion >= intArrayOf(2022, 1)) { - mSerializedKeywordStateMask = reader.readNextUShortArray() - reader.alignStream() - } else { - mSerializedKeywordStateMask = emptyArray() - } - } -} - -enum class PassType(val id: Int) { - Normal(0), - Use(1), - Grab(2); - - companion object { - fun of(value: Int): PassType { - return values().firstOrNull { it.id == value } ?: Normal - } - } -} - -class SerializedPass internal constructor(reader: ObjectReader) { - val mEditorDataHash: Array - val mPlatforms: ByteArray - val mLocalKeywordMask: Array - val mGlobalKeywordMask: Array - val mNameIndices: Array> - val mType: PassType - val mState: SerializedShaderState - val mProgramMask: UInt - val progVertex: SerializedProgram - val progFragment: SerializedProgram - val progGeometry: SerializedProgram - val progHull: SerializedProgram - val progDomain: SerializedProgram - val progRayTracing: SerializedProgram? - val mHasInstancingVariant: Boolean - val mUseName: String - val mName: String - val mTextureName: String - val mTags: SerializedTagMap - val mSerializedKeywordStateMask: Array - - init { - val version = reader.unityVersion - if (version >= intArrayOf(2020, 2)) { - mEditorDataHash = reader.readArrayOf { Hash128(reader) } - reader.alignStream() - mPlatforms = reader.readNextByteArray() - reader.alignStream() - if (version < intArrayOf(2021, 2)) { - mLocalKeywordMask = reader.readNextUShortArray() - reader.alignStream() - mGlobalKeywordMask = reader.readNextUShortArray() - reader.alignStream() - } else { - mLocalKeywordMask = emptyArray() - mGlobalKeywordMask = emptyArray() - } - } else { - mEditorDataHash = emptyArray() - mPlatforms = byteArrayOf() - mLocalKeywordMask = emptyArray() - mGlobalKeywordMask = emptyArray() - } - mNameIndices = reader.readArrayOf { with(reader) { readAlignedString() to readInt() } } - mType = PassType.of(reader.readInt()) - mState = SerializedShaderState(reader) - mProgramMask = reader.readUInt() - progVertex = SerializedProgram(reader) - progFragment = SerializedProgram(reader) - progGeometry = SerializedProgram(reader) - progHull = SerializedProgram(reader) - progDomain = SerializedProgram(reader) - progRayTracing = if (version >= intArrayOf(2019, 3)) SerializedProgram(reader) else null - mHasInstancingVariant = reader.readBool() - if (version[0] >= 2018) reader += 1 //m_HasProceduralInstancingVariant: Boolean - reader.alignStream() - mUseName = reader.readAlignedString() - mName = reader.readAlignedString() - mTextureName = reader.readAlignedString() - mTags = SerializedTagMap(reader) - if (version[0] == 2021 && version[1] >= 2) { - mSerializedKeywordStateMask = reader.readNextUShortArray() - reader.alignStream() - } else { - mSerializedKeywordStateMask = emptyArray() - } - } - - internal fun toString( - builder: StringBuilder, - platforms: Array, - shaderPrograms: Array - ): StringBuilder { - builder.append( - when (mType) { - PassType.Normal -> " Pass " - PassType.Use -> " UsePass " - PassType.Grab -> " GrabPass " - } - ) - if (mType == PassType.Use) { - builder.append("\"$mUseName\"\n") - } else { - builder.append("{\n") - if (mType == PassType.Grab) { - if (mTextureName.isNotEmpty()) { - builder.append(" \"${mTextureName}\"\n") - } - } else { - mState.toString(builder) - if (progVertex.mSubPrograms.isNotEmpty()) { - builder.apply { - append("Program \"vp\" {\n") - progVertex.mSubPrograms.toString(this, platforms, shaderPrograms) - append("}\n") - } - } - if (progFragment.mSubPrograms.isNotEmpty()) { - builder.apply { - append("Program \"fp\" {\n") - progFragment.mSubPrograms.toString(this, platforms, shaderPrograms) - append("}\n") - } - } - if (progGeometry.mSubPrograms.isNotEmpty()) { - builder.apply { - append("Program \"gp\" {\n") - progGeometry.mSubPrograms.toString(this, platforms, shaderPrograms) - append("}\n") - } - } - if (progHull.mSubPrograms.isNotEmpty()) { - builder.apply { - append("Program \"hp\" {\n") - progHull.mSubPrograms.toString(this, platforms, shaderPrograms) - append("}\n") - } - } - if (progDomain.mSubPrograms.isNotEmpty()) { - builder.apply { - append("Program \"dp\" {\n") - progDomain.mSubPrograms.toString(this, platforms, shaderPrograms) - append("}\n") - } - } - if (progRayTracing?.mSubPrograms?.isNotEmpty() == true) { - builder.apply { - append("Program \"rtp\" {\n") - progRayTracing.mSubPrograms.toString(this, platforms, shaderPrograms) - append("}\n") - } - } - } - builder.append("}\n") - } - return builder - } - - private fun Array.toString( - builder: StringBuilder, - platforms: Array, - shaderPrograms: Array - ): StringBuilder { - for (group in groupBy { it.mBlobIndex }) { - for (program in group.value.groupBy { it.mGpuProgramType }) { - for ((i, platform) in platforms.withIndex()) { - if (platform.checkProgramUsability(program.key)) { - for (subProgram in program.value) { - builder.append("SubProgram \"${platform.str} ") - if (program.value.size > 1) { - builder.append("hw_tier${"%02d"(subProgram.mShaderHardwareTier)} ") - } - builder.append( - "\" {\n" + - shaderPrograms[i].mSubPrograms[subProgram.mBlobIndex.toInt()]?.export() + - "\n}\n" - ) - } - break - } - } - } - } - return builder - } -} - -class SerializedSubShader internal constructor(reader: ObjectReader) { - val mPasses = reader.readArrayOf { SerializedPass(reader) } - val mTags = SerializedTagMap(reader) - val mLOD = reader.readInt() -} - -class SerializedShaderDependency internal constructor(reader: EndianBinaryReader) { - val from = reader.readAlignedString() - val to = reader.readAlignedString() -} - -class SerializedCustomEditorForRenderPipeline internal constructor(reader: EndianBinaryReader) { - val customEditorName = reader.readAlignedString() - val renderPipelineType = reader.readAlignedString() -} - -class SerializedShader internal constructor(reader: ObjectReader) { - val mPropInfo = SerializedProperties(reader) - val mSubShaders = reader.readArrayOf { SerializedSubShader(reader) } - val mKeywordNames: Array - val mKeywordFlags: ByteArray - val mName: String - val mCustomEditorName: String - val mFallbackName: String - val mDependencies: Array - val mCustomEditorForRenderPipelines: Array - val mDisableNoSubShadersMessage: Boolean - - init { - val version = reader.unityVersion - if (version >= intArrayOf(2021, 2)) { - mKeywordNames = reader.readNextStringArray() - mKeywordFlags = reader.readNextByteArray() - reader.alignStream() - } else { - mKeywordNames = emptyArray() - mKeywordFlags = byteArrayOf() - } - mName = reader.readAlignedString() - mCustomEditorName = reader.readAlignedString() - mFallbackName = reader.readAlignedString() - mDependencies = reader.readArrayOf { SerializedShaderDependency(reader) } - mCustomEditorForRenderPipelines = if (version[0] >= 2021) { - reader.readArrayOf { SerializedCustomEditorForRenderPipeline(reader) } - } else emptyArray() - mDisableNoSubShadersMessage = reader.readBool() - reader.alignStream() - } -} - -enum class ShaderCompilerPlatform(val id: Int, val str: String = "unknown") { - None(-1), - GL(0, "openGL"), - D3D9(1, "d3d9"), - Xbox360(2, "xbox360"), - PS3(3, "ps3"), - D3D11(4, "d3d11"), - GLES20(5, "gles"), - NaCl(6, "glesdesktop"), - Flash(7, "flash"), - D3D11_9x(8, "d3d11_9x"), - GLES3Plus(9, "gles3"), - PSP2(10, "psp2"), - PS4(11, "ps4"), - XboxOne(12, "xboxone"), - PSM(13, "psm"), - Metal(14, "metal"), - OpenGLCore(15, "glcore"), - N3DS(16, "n3ds"), - WiiU(17, "wiiu"), - Vulkan(18, "vulkan"), - Switch(19, "switch"), - XboxOneD3D12(20, "xboxone_d3d12"), - GameCoreXboxOne(21, "xboxone"), - GameCoreScarlett(22, "xbox_scarlett"), - PS5(23, "ps5"), - PS5NGGC(24, "ps5_nggc"); - - internal fun checkProgramUsability(programType: ShaderGpuProgramType): Boolean { - return when (this) { - GL -> programType == ShaderGpuProgramType.GLLegacy - D3D9 -> { - programType.equalsAnyOf( - ShaderGpuProgramType.DX9VertexSM20, - ShaderGpuProgramType.DX9VertexSM30, - ShaderGpuProgramType.DX9PixelSM20, - ShaderGpuProgramType.DX9PixelSM30 - ) - } - Xbox360, PS3, - PSP2, PS4, - XboxOne, N3DS, - WiiU, Switch, - XboxOneD3D12, GameCoreXboxOne, - GameCoreScarlett, PS5 -> { - programType.equalsAnyOf( - ShaderGpuProgramType.ConsoleVS, - ShaderGpuProgramType.ConsoleFS, - ShaderGpuProgramType.ConsoleHS, - ShaderGpuProgramType.ConsoleDS, - ShaderGpuProgramType.ConsoleGS - ) - } - PS5NGGC -> programType == ShaderGpuProgramType.PS5NGGC - D3D11 -> { - programType.equalsAnyOf( - ShaderGpuProgramType.DX11VertexSM40, - ShaderGpuProgramType.DX11VertexSM50, - ShaderGpuProgramType.DX11PixelSM40, - ShaderGpuProgramType.DX11PixelSM50, - ShaderGpuProgramType.DX11GeometrySM40, - ShaderGpuProgramType.DX11GeometrySM50, - ShaderGpuProgramType.DX11HullSM50, - ShaderGpuProgramType.DX11DomainSM50 - ) - } - GLES20 -> programType == ShaderGpuProgramType.GLES - NaCl -> throw UnsupportedFormatException("Unsupported platform") - Flash -> throw UnsupportedFormatException("Unsupported platform") - D3D11_9x -> { - programType.equalsAnyOf( - ShaderGpuProgramType.DX10Level9Vertex, - ShaderGpuProgramType.DX10Level9Pixel - ) - } - GLES3Plus -> { - programType.equalsAnyOf( - ShaderGpuProgramType.GLES31AEP, - ShaderGpuProgramType.GLES31, - ShaderGpuProgramType.GLES3 - ) - } - PSM -> throw UnsupportedFormatException("Unknown") - Metal -> { - programType.equalsAnyOf( - ShaderGpuProgramType.MetalVS, - ShaderGpuProgramType.MetalFS - ) - } - OpenGLCore -> { - programType.equalsAnyOf( - ShaderGpuProgramType.GLCore32, - ShaderGpuProgramType.GLCore41, - ShaderGpuProgramType.GLCore43 - ) - } - Vulkan -> programType == ShaderGpuProgramType.SPIRV - else -> throw UnsupportedFormatException("Unsupported platform") - } - } - - companion object { - fun of(value: Int): ShaderCompilerPlatform { - return values().firstOrNull { it.id == value } ?: None - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/SkinnedMeshRendererImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/SkinnedMeshRendererImpl.kt deleted file mode 100644 index 6b3fe9bb..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/SkinnedMeshRendererImpl.kt +++ /dev/null @@ -1,27 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.data.Animation -import io.github.deficuet.unitykt.data.Mesh -import io.github.deficuet.unitykt.data.PPtr -import io.github.deficuet.unitykt.data.Transform -import io.github.deficuet.unitykt.util.ObjectReader -import io.github.deficuet.unitykt.util.compareTo - -class SkinnedMeshRendererImpl internal constructor(reader: ObjectReader): RendererImpl(reader) { - val mMesh: PPtr - val mBones: Array> - val mBlendShapeWeights: FloatArray - - init { - reader += 6 //m_Quality: Int, m_UpdateWhenOffscreen, m_SkinNormals: Boolean - reader.alignStream() - if (unityVersion[0] == 2 && unityVersion[1] < 6) { - PPtr(reader) //m_DisableAnimationWhenOffscreen - } - mMesh = PPtr(reader) - mBones = reader.readArrayOf { PPtr(reader) } - mBlendShapeWeights = if (unityVersion >= intArrayOf(4, 3)) { - reader.readNextFloatArray() - } else floatArrayOf() - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/SpriteAtlasImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/SpriteAtlasImpl.kt deleted file mode 100644 index 5a46afd6..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/SpriteAtlasImpl.kt +++ /dev/null @@ -1,58 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.data.PPtr -import io.github.deficuet.unitykt.data.Sprite -import io.github.deficuet.unitykt.data.Texture2D -import io.github.deficuet.unitykt.math.Vector2 -import io.github.deficuet.unitykt.util.ObjectReader -import io.github.deficuet.unitykt.util.compareTo - -class SpriteAtlasImpl internal constructor(reader: ObjectReader): NamedObjectImpl(reader) { - val mPackedSprites = reader.readArrayOf { PPtr(reader) } - val mRenderDataMap: Map, SpriteAtlasData> - val mIsVariant: Boolean - - init { - reader.readNextStringArray() //m_PackedSpriteNamesToIndex - mRenderDataMap = reader.readArrayOf { - val first = reader.read(16) - val second = reader.readLong() - val value = SpriteAtlasData(reader) - (first to second) to value - }.toMap() - reader.readAlignedString() //m_Tag - mIsVariant = reader.readBool() - reader.alignStream() - if (!mIsVariant) { - for (pack in mPackedSprites) { - val sprite = pack.obj - if (sprite != null) { - if (sprite.mSpriteAtlas != null && sprite.mSpriteAtlas!!.isNull) { - sprite.mSpriteAtlas!!.setObjInfo(this) - } - } - } - } - } -} - -class SpriteAtlasData internal constructor(reader: ObjectReader) { - val texture = PPtr(reader) - val alphaText = PPtr(reader) - val textureRect = reader.readRectangle() - val textureRectOffset = reader.readVector2() - val atlasRectOffset = if (reader.unityVersion >= intArrayOf(2017, 2)) { - reader.readVector2() - } else Vector2.Zero - val uvTransform = reader.readVector4() - val downScaleMultiplier = reader.readFloat() - val settingsRaw = SpriteSettings(reader) - val secondaryTextures: Array - - init { - if (reader.unityVersion >= intArrayOf(2020, 2)) { - secondaryTextures = reader.readArrayOf { SecondarySpriteTexture(reader) } - reader.alignStream() - } else secondaryTextures = emptyArray() - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/SpriteImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/SpriteImpl.kt deleted file mode 100644 index 46cb5284..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/SpriteImpl.kt +++ /dev/null @@ -1,166 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.data.PPtr -import io.github.deficuet.unitykt.data.SpriteAtlas -import io.github.deficuet.unitykt.data.Texture2D -import io.github.deficuet.unitykt.math.Matrix4x4 -import io.github.deficuet.unitykt.math.Rectangle -import io.github.deficuet.unitykt.math.Vector2 -import io.github.deficuet.unitykt.math.Vector4 -import io.github.deficuet.unitykt.util.ObjectReader -import io.github.deficuet.unitykt.util.compareTo - -class SpriteImpl internal constructor(reader: ObjectReader): NamedObjectImpl(reader) { - val mRect = reader.readRectangle() - val mOffset = reader.readVector2() - val mBorder = if (reader.unityVersion >= intArrayOf(4, 5)) reader.readVector4() else Vector4.Zero - val mPixelsToUnits = reader.readFloat() - val mPivot = if (reader.unityVersion >= intArrayOf(5, 4, 1, 3)) { - reader.readVector2() - } else Vector2(0.5, 0.5) - val mExtrude = reader.readUInt() - val mIsPolygon: Boolean - val mRenderDataKey: Map - val mAtlasTags: Array - val mSpriteAtlas: PPtr? - val mRD: SpriteRenderData - val mPhysicsShape: Array> - - init { - val version = reader.unityVersion - if (version >= intArrayOf(5, 3)) { - mIsPolygon = reader.readBool() - reader.alignStream() - } else { - mIsPolygon = false - } - if (version[0] >= 2017) { - mRenderDataKey = mapOf(reader.read(16) to reader.readLong()) - mAtlasTags = reader.readNextStringArray() - mSpriteAtlas = PPtr(reader) - } else { - mRenderDataKey = emptyMap() - mAtlasTags = emptyArray() - mSpriteAtlas = null - } - mRD = SpriteRenderData(reader) - mPhysicsShape = if (version[0] >= 2017) { - reader.readArrayOf { reader.readNextVector2Array() } - } else emptyArray() - } -} - -class SecondarySpriteTexture internal constructor(reader: ObjectReader) { - val texture = PPtr(reader) - val name = reader.readStringUntilNull() -} - -enum class SpritePackingRotation(val id: UInt) { - None(0u), - FlipHorizontal(1u), - FlipVertical(2u), - Rotate180(3u), - Rotate90(4u); - - companion object { - fun of(value: UInt): SpritePackingRotation { - return values().firstOrNull { it.id == value } ?: None - } - } -} - -enum class SpritePackingMode(val id: UInt) { - Tight(0u), - Rectangle(1u); - - companion object { - fun of(value: UInt): SpritePackingMode { - return values().firstOrNull { it.id == value } ?: Tight - } - } -} - -enum class SpriteMeshType(val id: UInt) { - FullRect(0u), - Tight(1u); - - companion object { - fun of(value: UInt): SpriteMeshType { - return values().firstOrNull { it.id == value } ?: FullRect - } - } -} - -class SpriteSettings internal constructor(reader: ObjectReader) { - val settingsRaw = reader.readUInt() - val packed = settingsRaw.and(1u) - val packingMode = SpritePackingMode.of(settingsRaw.shr(1).and(1u)) - val packingRotation = SpritePackingRotation.of(settingsRaw.shr(2).and(0xFu)) - val meshType = SpriteMeshType.of(settingsRaw.shr(6).and(1u)) -} - -class SpriteVertex internal constructor(reader: ObjectReader) { - val pos = reader.readVector3() - val uv = if (reader.unityVersion <= intArrayOf(4, 3)) reader.readVector2() else Vector2.Zero -} - -class SpriteRenderData internal constructor(reader: ObjectReader) { - val texture = PPtr(reader) - val alphaTexture = if (reader.unityVersion >= intArrayOf(5, 2)) PPtr(reader) else null - val secondaryTexturesSize = if (reader.unityVersion[0] >= 2019) { - reader.readArrayOf { SecondarySpriteTexture(reader) } - } else emptyArray() - val mSubMeshes: Array - val mIndexBuffer: ByteArray - val mVertexData: VertexData? - val vertices: Array - val indices: Array - val mBindPose: Array - val mSourceSkin: Array - val textureRect: Rectangle - val textureRectOffset: Vector2 - val atlasRectOffset: Vector2 - val settingsRaw: SpriteSettings - val uvTransform: Vector4 - val downScaleMultiplier: Float - - init { - val version = reader.unityVersion - if (version >= intArrayOf(5, 6)) { - mSubMeshes = reader.readArrayOf { SubMash(reader) } - mIndexBuffer = reader.readNextByteArray() - reader.alignStream() - mVertexData = VertexData(reader) - vertices = emptyArray() - indices = emptyArray() - } else { - vertices = reader.readArrayOf { SpriteVertex(reader) } - indices = reader.readNextUShortArray() - reader.alignStream() - mSubMeshes = emptyArray() - mIndexBuffer = byteArrayOf() - mVertexData = null - } - if (version[0] >= 2018) { - mBindPose = reader.readNextMatrixArray() - mSourceSkin = if (version[0] == 2018 && version[1] < 2) { - reader.readArrayOf { BoneWeights4(reader) } - } else emptyArray() - } else { - mBindPose = emptyArray() - mSourceSkin = emptyArray() - } - textureRect = reader.readRectangle() - textureRectOffset = reader.readVector2() - atlasRectOffset = if (version >= intArrayOf(5, 6)) { - reader.readVector2() - } else Vector2.Zero - settingsRaw = SpriteSettings(reader) - uvTransform = if (version >= intArrayOf(4, 5)) { - reader.readVector4() - } else Vector4.Zero - downScaleMultiplier = if (version[0] >= 2017) { - reader.readFloat() - } else 0f - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/TextAssetImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/TextAssetImpl.kt deleted file mode 100644 index 91db3cee..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/TextAssetImpl.kt +++ /dev/null @@ -1,7 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.util.ObjectReader - -class TextAssetImpl internal constructor(reader: ObjectReader): NamedObjectImpl(reader) { - val mScript = reader.readNextByteArray() -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/Texture2DImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/Texture2DImpl.kt deleted file mode 100644 index 053aba78..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/Texture2DImpl.kt +++ /dev/null @@ -1,472 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.extension.TextureDecoder -import io.github.deficuet.unitykt.file.BuildTarget -import io.github.deficuet.unitykt.util.* -import java.awt.image.* -import java.nio.ByteBuffer -import kotlin.math.pow -import kotlin.math.roundToInt - -class StreamingInfo internal constructor(reader: ObjectReader) { - val offset = if (reader.unityVersion[0] >= 2020) reader.readLong() else reader.readUInt().toLong() - val size = reader.readUInt() - val path = reader.readAlignedString() -} - -class GLTextureSettings internal constructor(reader: ObjectReader) { - val mFilterMode = reader.readInt() - val mAniso = reader.readInt() - val mMipBias = reader.readFloat() - val mWrapMode: Int - - init { - if (reader.unityVersion[0] >= 2017) { - mWrapMode = reader.readInt() - reader += 8 //m_WrapV, m_WrapW: Int - } else mWrapMode = reader.readInt() - } -} - -class Texture2DImpl internal constructor(reader: ObjectReader): TextureImpl(reader) { - val mWidth = reader.readInt() - val mHeight = reader.readInt() - val mTextureFormat: TextureFormat - val mMipMap: Boolean - val mMipCount: Int - val mTextureSettings: GLTextureSettings - val imageData: ResourceReader - val mStreamData: StreamingInfo? - - init { - val version = reader.unityVersion - reader += 4 //m_CompleteImageSize: Int - if (version[0] >= 2020) reader += 4 //m_MipsStripped: Int - mTextureFormat = TextureFormat.of(reader.readInt()) - if (version < intArrayOf(5, 2)) { - mMipMap = reader.readBool() - mMipCount = 0 - } else { - mMipCount = reader.readInt() - mMipMap = false - } - if (version >= intArrayOf(2, 6)) reader += 1 //m_IsReadable: Boolean - if (version[0] >= 2020) reader += 1 //m_IsPreProcessed: Boolean - if (version >= intArrayOf(2019, 3)) reader += 1 //m_IgnoreMasterTextureLimit: Boolean - if (version[0] >= 3 && version <= intArrayOf(5, 4)) reader += 1 //m_ReadAllowed: Boolean - if (version >= intArrayOf(2018, 2)) reader += 1 //m_StreamingMipmaps: Boolean - reader.alignStream() - if (version >= intArrayOf(2018, 2)) reader += 4 //m_StreamingMipmapsPriority: Int - reader += 8 //m_ImageCount, m_TextureDimension: Int - mTextureSettings = GLTextureSettings(reader) - if (version[0] >= 3) reader += 4 //m_LightmapFormat: Int - if (version >= intArrayOf(3, 5)) reader += 4 //m_ColorSpace: Int - if (version >= intArrayOf(2020, 2)) { - reader.readNextByteArray() //m_PlatformBlob - reader.alignStream() - } - val imageDataSize = reader.readInt() - mStreamData = if (imageDataSize == 0 && version >= intArrayOf(5, 3)) { - StreamingInfo(reader) - } else null - imageData = if (mStreamData?.path?.isNotEmpty() == true) { - ResourceReader(mStreamData.path, assetFile, mStreamData.offset, mStreamData.size.toLong()) - } else { - ResourceReader(reader, reader.absolutePosition, imageDataSize.toLong()) - }.registerToManager(assetFile.root.manager) - } - - val decompressedImageData get() = imageData.read().decompressTexture() - val image: BufferedImage - get() = BufferedImage(mWidth, mHeight, BufferedImage.TYPE_4BYTE_ABGR).apply { - data = Raster.createRaster( - ComponentSampleModel( - DataBuffer.TYPE_BYTE, mWidth, mHeight, 4, - mWidth * 4, intArrayOf(2, 1, 0, 3) - ), - DataBufferByte(decompressedImageData, decompressedImageData.size), - null - ) - } - - private val areaIndices by lazy { 0 until mWidth * mHeight } - private val dataSizeIndices by lazy { 0 until mWidth * mHeight * 4 step 4 } - - private fun ByteArray.swapForXbox() { - if (platform == BuildTarget.XBOX360) reverse() - } - - private fun ByteArray.decompressTexture(): ByteArray { - val out = ByteArray(mWidth * mHeight * 4) - - when (mTextureFormat) { - TextureFormat.Alpha8 -> { - out.fill(-1) - for (i in areaIndices) { - out[i * 4 + 3] = this[i] - } - } - TextureFormat.ARGB4444 -> { - swapForXbox() - for (i in areaIndices) { - val p = ByteBuffer.wrap(this[i * 2, 2]).short.toIntBits() - val a = p.and(0x000f).let { it.shl(4).or(it) } - val b = p.and(0x00f0).shr(4).let { it.shl(4).or(it) } - val c = p.and(0x0f00).shr(8).let { it.shl(4).or(it) } - val d = p.and(0xf000).shr(12).let { it.shl(4).or(it) } - out[i * 4] = a.toByte() - out[i * 4 + 1] = b.toByte() - out[i * 4 + 2] = c.toByte() - out[i * 4 + 3] = d.toByte() - } - } - TextureFormat.RGBA4444 -> { - for (i in areaIndices) { - val p = ByteBuffer.wrap(this[i * 2, 2]).short.toIntBits() - val a = p.and(0x00f0).shr(4).let { it.shl(4).or(it) } - val b = p.and(0x0f00).shr(8).let { it.shl(4).or(it) } - val c = p.and(0xf000).shr(12).let { it.shl(4).or(it) } - val d = p.and(0x000f).let { it.shl(4).or(it) } - out[i * 4] = a.toByte() - out[i * 4 + 1] = b.toByte() - out[i * 4 + 2] = c.toByte() - out[i * 4 + 3] = d.toByte() - } - } - TextureFormat.RGBA32 -> { - for (i in dataSizeIndices) { - out[i] = this[i + 2] - out[i + 1] = this[i + 1] - out[i + 2] = this[i] - out[i + 3] = this[i + 3] - } - } - TextureFormat.BGRA32 -> { - return this - } - TextureFormat.ARGB32 -> { - for (i in dataSizeIndices) { - out[i] = this[i + 3] - out[i + 1] = this[i + 2] - out[i + 2] = this[i + 1] - out[i + 3] = this[i + 0] - } - } - TextureFormat.RGB24 -> { - for (i in areaIndices) { - out[i * 4] = this[i * 3 + 2] - out[i * 4 + 1] = this[i * 3 + 1] - out[i * 4 + 2] = this[i * 3] - out[i * 4 + 3] = -1 - } - } - TextureFormat.RGB565 -> { - swapForXbox() - for (i in areaIndices) { - val p = ByteBuffer.wrap(this[i * 2, 2]).short.toIntBits() - out[i * 4] = p.shl(3).or(p.shr(2).and(7)).toByte() - out[i * 4 + 1] = p.shr(3).and(0xFC).or(p.shr(9).and(3)).toByte() - out[i * 4 + 2] = p.shr(8).and(0xF8).or(p.shr(13)).toByte() - out[i * 4 + 3] = -1 - } - } - TextureFormat.R8 -> { - for (i in areaIndices) { - out[i * 4] = 0 - out[i * 4 + 1] = 0 - out[i * 4 + 2] = this[i] - out[i * 4 + 3] = -1 - } - } - TextureFormat.R16 -> { - for (i in areaIndices) { - out[i * 4] = 0 - out[i * 4 + 1] = 0 - out[i * 4 + 2] = this[i * 2 + 1] - out[i * 4 + 3] = -1 - } - } - TextureFormat.RG16 -> { - for (i in 0 until mWidth * mHeight step 2) { - out[i * 2] = 0 - out[i * 2 + 1] = this[i + 1] - out[i * 2 + 2] = this[i] - out[i * 2 + 3] = -1 - } - } - TextureFormat.RHalf -> { - for (i in dataSizeIndices) { - out[i] = 0 - out[i + 1] = 0 - out[i + 2] = (this[i / 2, 2].toHalf() * 255f).roundToInt().toByte() - out[i + 3] = -1 - } - } - TextureFormat.RGHalf -> { - for (i in dataSizeIndices) { - out[i] = 0 - out[i + 1] = (this[i + 2, 2].toHalf() * 255f).roundToInt().toByte() - out[i + 2] = (this[i, 2].toHalf() * 255f).roundToInt().toByte() - out[i + 3] = -1 - } - } - TextureFormat.RGBAHalf -> { - for (i in dataSizeIndices) { - out[i] = (this[i * 2 + 4, 2].toHalf() * 255f).roundToInt().toByte() - out[i + 1] = (this[i * 2 + 2, 2].toHalf() * 255f).roundToInt().toByte() - out[i + 2] = (this[i * 2, 2].toHalf() * 255f).roundToInt().toByte() - out[i + 3] = (this[i * 2 + 6, 2].toHalf() * 255f).roundToInt().toByte() - } - } - TextureFormat.RFloat -> { - for (i in dataSizeIndices) { - out[i] = 0 - out[i + 1] = 0 - out[i + 2] = (ByteBuffer.wrap(this[i, 4]).float * 255f).roundToInt().toByte() - out[i + 3] = -1 - } - } - TextureFormat.RGFloat -> { - for (i in dataSizeIndices) { - out[i] = 0 - out[i + 2] = (ByteBuffer.wrap(this[i * 2 + 4, 4]).float * 255f).roundToInt().toByte() - out[i + 1] = (ByteBuffer.wrap(this[i * 2, 4]).float * 255f).roundToInt().toByte() - out[i + 3] = -1 - } - } - TextureFormat.RGBAFloat -> { - for (i in dataSizeIndices) { - out[i] = (ByteBuffer.wrap(this[i * 4 + 8, 4]).float * 255f).roundToInt().toByte() - out[i + 1] = (ByteBuffer.wrap(this[i * 4 + 4, 4]).float * 255f).roundToInt().toByte() - out[i + 2] = (ByteBuffer.wrap(this[i * 4, 4]).float * 255f).roundToInt().toByte() - out[i + 3] = (ByteBuffer.wrap(this[i * 4 + 12, 4]).float * 255f).roundToInt().toByte() - } - } - TextureFormat.YUY2 -> { - var p = 0u; var o = 0 - for (y in 0 until mHeight) { - for (x in 0 until mWidth / 2) { - val y0 = this[p++] - val u0 = this[p++] - val y1 = this[p++] - val v0 = this[p++] - var c = y0 - 16 - val d = u0 - 128 - val e = v0 - 128 - out[o++] = (298 * c + 516 * d + 128).shr(8).clampByte() - out[o++] = (298 * c - 100 * d - 208 * e + 128).shr(8).clampByte() - out[o++] = (298 * c + 409 * e + 128).shr(8).clampByte() - out[o++] = -1 - c = y1 - 16 - out[o++] = (298 * c + 516 * d + 128).shr(8).clampByte() - out[o++] = (298 * c - 100 * d - 208 * e + 128).shr(8).clampByte() - out[o++] = (298 * c + 409 * e + 128).shr(8).clampByte() - out[o++] = -1 - } - } - } - TextureFormat.RGB9e5Float -> { - for (i in dataSizeIndices) { - val n = ByteBuffer.wrap(this[i, 4]).int - val scale = n.shr(27).and(0x1F) - val scalef = 2.0.pow(scale - 24) - val b = n.shr(18).and(0x1FF) - val g = n.shr(9).and(0x1FF) - val r = n.and(0x1FF) - out[i] = (b * scalef * 255).roundToInt().toByte() - out[i + 1] = (g * scalef * 255).roundToInt().toByte() - out[i + 2] = (r * scalef * 255).roundToInt().toByte() - out[i + 3] = -1 - } - } - TextureFormat.DXT1 -> { - swapForXbox() - TextureDecoder.decodeDXT1(this, mWidth, mHeight, out) - } - TextureFormat.DXT1Crunched -> { - unpackCrunch()?.let { - TextureDecoder.decodeDXT1(it, mWidth, mHeight, out) - } - } - TextureFormat.DXT5 -> { - swapForXbox() - TextureDecoder.decodeDXT5(this, mWidth, mHeight, out) - } - TextureFormat.DXT5Crunched -> { - unpackCrunch()?.let { - TextureDecoder.decodeDXT5(it, mWidth, mHeight, out) - } - } - TextureFormat.BC4 -> { - TextureDecoder.decodeBC4(this, mWidth, mHeight, out) - } - TextureFormat.BC5 -> { - TextureDecoder.decodeBC5(this, mWidth, mHeight, out) - } - TextureFormat.BC6H -> { - TextureDecoder.decodeBC6(this, mWidth, mHeight, out) - } - TextureFormat.BC7 -> { - TextureDecoder.decodeBC7(this, mWidth, mHeight, out) - } - TextureFormat.PVRTC_RGB2, TextureFormat.PVRTC_RGBA2 -> { - TextureDecoder.decodePVRTC(this, mWidth, mHeight, out, true) - } - TextureFormat.PVRTC_RGB4, TextureFormat.PVRTC_RGBA4 -> { - TextureDecoder.decodePVRTC(this, mWidth, mHeight, out, false) - } - TextureFormat.ETC_RGB4, TextureFormat.ETC_RGB4_3DS -> { - TextureDecoder.decodeETC1(this, mWidth, mHeight, out) - } - TextureFormat.ETC2_RGB -> { - TextureDecoder.decodeETC2(this, mWidth, mHeight, out) - } - TextureFormat.ETC2_RGBA1 -> { - TextureDecoder.decodeETC2A1(this, mWidth, mHeight, out) - } - TextureFormat.ETC2_RGBA8, TextureFormat.ETC_RGBA8_3DS -> { - TextureDecoder.decodeETC2A8(this, mWidth, mHeight, out) - } - TextureFormat.ETC_RGB4Crunched -> { - unpackCrunch()?.let { - TextureDecoder.decodeETC1(it, mWidth, mHeight, out) - } - } - TextureFormat.ETC2_RGBA8Crunched -> { - unpackCrunch()?.let { - TextureDecoder.decodeETC2A8(it, mWidth, mHeight, out) - } - } - TextureFormat.ATC_RGB4 -> { - TextureDecoder.decodeATCRGB4(this, mWidth, mHeight, out) - } - TextureFormat.ATC_RGBA8 -> { - TextureDecoder.decodeATCRGBA8(this, mWidth, mHeight, out) - } - TextureFormat.ASTC_RGB_4x4, TextureFormat.ASTC_RGBA_4x4, TextureFormat.ASTC_HDR_4x4 -> { - TextureDecoder.decodeASTC(this, mWidth, mHeight, out, 4) - } - TextureFormat.ASTC_RGB_5x5, TextureFormat.ASTC_RGBA_5x5, TextureFormat.ASTC_HDR_5x5 -> { - TextureDecoder.decodeASTC(this, mWidth, mHeight, out, 5) - } - TextureFormat.ASTC_RGB_6x6, TextureFormat.ASTC_RGBA_6x6, TextureFormat.ASTC_HDR_6x6 -> { - TextureDecoder.decodeASTC(this, mWidth, mHeight, out, 6) - } - TextureFormat.ASTC_RGB_8x8, TextureFormat.ASTC_RGBA_8x8, TextureFormat.ASTC_HDR_8x8 -> { - TextureDecoder.decodeASTC(this, mWidth, mHeight, out, 8) - } - TextureFormat.ASTC_RGB_10x10, TextureFormat.ASTC_RGBA_10x10, TextureFormat.ASTC_HDR_10x10 -> { - TextureDecoder.decodeASTC(this, mWidth, mHeight, out, 10) - } - TextureFormat.ASTC_RGB_12x12, TextureFormat.ASTC_RGBA_12x12, TextureFormat.ASTC_HDR_12x12 -> { - TextureDecoder.decodeASTC(this, mWidth, mHeight, out, 12) - } - TextureFormat.EAC_R -> { - TextureDecoder.decodeEACR(this, mWidth, mHeight, out) - } - TextureFormat.EAC_R_SIGNED -> { - TextureDecoder.decodeEACRSigned(this, mWidth, mHeight, out) - } - TextureFormat.EAC_RG -> { - TextureDecoder.decodeEACRG(this, mWidth, mHeight, out) - } - TextureFormat.EAC_RG_SIGNED -> { - TextureDecoder.decodeEACRGSigned(this, mWidth, mHeight, out) - } - else -> { } - } - return out - } - - private fun unpackCrunch(): ByteArray? { - return if ( - unityVersion >= intArrayOf(2017, 3) || - mTextureFormat == TextureFormat.ETC_RGB4Crunched || - mTextureFormat == TextureFormat.ETC2_RGBA8Crunched - ) { - TextureDecoder.unpackUnityCrunch(imageData.read()) - } else { - TextureDecoder.unpackCrunch(imageData.read()) - } - } -} - -@Suppress("EnumEntryName") -enum class TextureFormat(val id: Int) { - Unknown(0), - Alpha8(1), - ARGB4444(2), - RGB24(3), - RGBA32(4), - ARGB32(5), - RGB565(7), - BGR24(8), - R16(9), - DXT1(10), - DXT3(11), - DXT5(12), - RGBA4444(13), - BGRA32(14), - RHalf(15), - RGHalf(16), - RGBAHalf(17), - RFloat(18), - RGFloat(19), - RGBAFloat(20), - YUY2(21), - RGB9e5Float(22), - RGBFloat(23), - BC6H(24), - BC7(25), - BC4(26), - BC5(27), - DXT1Crunched(28), - DXT5Crunched(29), - PVRTC_RGB2(30), - PVRTC_RGBA2(31), - PVRTC_RGB4(32), - PVRTC_RGBA4(33), - ETC_RGB4(34), - ATC_RGB4(35), - ATC_RGBA8(36), - EAC_R(41), - EAC_R_SIGNED(42), - EAC_RG(43), - EAC_RG_SIGNED(44), - ETC2_RGB(45), - ETC2_RGBA1(46), - ETC2_RGBA8(47), - ASTC_RGB_4x4(48), - ASTC_RGB_5x5(49), - ASTC_RGB_6x6(50), - ASTC_RGB_8x8(51), - ASTC_RGB_10x10(52), - ASTC_RGB_12x12(53), - ASTC_RGBA_4x4(54), - ASTC_RGBA_5x5(55), - ASTC_RGBA_6x6(56), - ASTC_RGBA_8x8(57), - ASTC_RGBA_10x10(58), - ASTC_RGBA_12x12(59), - ETC_RGB4_3DS(60), - ETC_RGBA8_3DS(61), - RG16(62), - R8(63), - ETC_RGB4Crunched(64), - ETC2_RGBA8Crunched(65), - ASTC_HDR_4x4(66), - ASTC_HDR_5x5(67), - ASTC_HDR_6x6(68), - ASTC_HDR_8x8(69), - ASTC_HDR_10x10(70), - ASTC_HDR_12x12(71), - RG32(72), - RGB48(73), - RGBA64(74); - - companion object { - fun of(value: Int): TextureFormat { - return values().firstOrNull { it.id == value } ?: Unknown - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/TextureImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/TextureImpl.kt deleted file mode 100644 index d92f043d..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/TextureImpl.kt +++ /dev/null @@ -1,13 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.util.ObjectReader -import io.github.deficuet.unitykt.util.compareTo - -abstract class TextureImpl internal constructor(reader: ObjectReader): NamedObjectImpl(reader) { - init { - // m_ForcedFallbackFormat: Int, m_DownscaleFallback: Boolean - // when >= 2020.2: m_IsAlphaChannelOptional: Boolean - reader += if (unityVersion >= intArrayOf(2020, 2)) 6 else 5 - reader.alignStream() - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/TransformImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/TransformImpl.kt deleted file mode 100644 index 9eb58968..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/TransformImpl.kt +++ /dev/null @@ -1,13 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.data.PPtr -import io.github.deficuet.unitykt.data.Transform -import io.github.deficuet.unitykt.util.ObjectReader - -open class TransformImpl internal constructor(reader: ObjectReader): ComponentImpl(reader) { - val mLocalRotation = reader.readQuaternion() - val mLocalPosition = reader.readVector3() - val mLocalScale = reader.readVector3() - val mChildren = reader.readArrayOf { PPtr(reader) } - val mFather = PPtr(reader) -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/VideoClipImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/VideoClipImpl.kt deleted file mode 100644 index 6c309413..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/dataImpl/VideoClipImpl.kt +++ /dev/null @@ -1,44 +0,0 @@ -package io.github.deficuet.unitykt.dataImpl - -import io.github.deficuet.unitykt.data.PPtr -import io.github.deficuet.unitykt.data.Shader -import io.github.deficuet.unitykt.util.ObjectReader -import io.github.deficuet.unitykt.util.ResourceReader -import io.github.deficuet.unitykt.util.compareTo - -class VideoClipImpl internal constructor(reader: ObjectReader): NamedObjectImpl(reader) { - val mOriginalPath = reader.readAlignedString() - val mVideoData: ResourceReader - val mExternamResource: StreamedResource - - init { - reader += 32 //m_ProxyWidth, m_ProxyHeight, Width, Height: UInt - if (unityVersion >= intArrayOf(2017, 2)) { - reader += 8 //m_PixelAspecRatioNum, m_PixelAspecRatioDen: UInt - } - reader += 20 //m_FrameRate: Double, m_FrameCount: ULong, m_Format: Int - reader.readNextUShortArray() //m_AudioChannelCount - reader.alignStream() - reader.readNextUIntArray() //m_AudioSampleRate - reader.readNextStringArray() //m_AudioLanguage - if (unityVersion[0] >= 2020) { - reader.readArrayOf { PPtr(reader) } //m_VideoShaders - } - mExternamResource = StreamedResource(reader) - reader += 1 //m_HasSplitAlpha: Boolean - if (unityVersion[0] >= 2020) reader += 1 //m_sRGB - mVideoData = if (mExternamResource.mSource.isNotEmpty()) { - with(mExternamResource) { - ResourceReader(mSource, assetFile, mOffset, mSize) - } - } else { - ResourceReader(reader, reader.absolutePosition, mExternamResource.mSize) - }.registerToManager(assetFile.root.manager) - } -} - -class StreamedResource internal constructor(reader: ObjectReader) { - val mSource = reader.readAlignedString() - val mOffset = reader.readLong() - val mSize = reader.readLong() -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/enums/BuildTarget.kt b/src/main/kotlin/io/github/deficuet/unitykt/enums/BuildTarget.kt new file mode 100644 index 00000000..ef836ebe --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/enums/BuildTarget.kt @@ -0,0 +1,57 @@ +package io.github.deficuet.unitykt.enums + +@Suppress("EnumEntryName") +enum class BuildTarget(override val id: Int): NumericalEnum { + NoTarget(-2), + AnyPlayer(-1), + ValidPlayer(1), + StandaloneOSX(2), + StandaloneOSXPPC(3), + StandaloneOSXIntel(4), + StandaloneWindows(5), + WebPlayer(6), + WebPlayerStreamed(7), + Wii(8), + iOS(9), + PS3(10), + XBOX360(11), + Broadcom(12), + Android(13), + StandaloneGLESEmu(14), + StandaloneGLES20Emu(15), + NaCl(16), + StandaloneLinux(17), + FlashPlayer(18), + StandaloneWindows64(19), + WebGL(20), + WSAPlayer(21), + StandaloneLinux64(24), + StandaloneLinuxUniversal(25), + WP8Player(26), + StandaloneOSXIntel64(27), + BlackBerry(28), + Tizen(29), + PSP2(30), + PS4(31), + PSM(32), + XboxOne(33), + SamsungTV(34), + N3DS(35), + WiiU(36), + tvOS(37), + Switch(38), + Lumin(39), + Stadia(40), + CloudRendering(41), + GameCoreXboxSeries(42), + GameCoreXboxOne(43), + PS5(44), + EmbeddedLinux(45), + QNX(46), + + UnknownPlatform(9999); + + companion object: NumericalEnumCompanion(BuildTarget.values(), NoTarget) { + fun isDefined(v: Int): Boolean = cacheTable[v] != null + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/file/ClassIDType.kt b/src/main/kotlin/io/github/deficuet/unitykt/enums/ClassIDType.kt similarity index 94% rename from src/main/kotlin/io/github/deficuet/unitykt/file/ClassIDType.kt rename to src/main/kotlin/io/github/deficuet/unitykt/enums/ClassIDType.kt index 26736d44..f6bef5f1 100644 --- a/src/main/kotlin/io/github/deficuet/unitykt/file/ClassIDType.kt +++ b/src/main/kotlin/io/github/deficuet/unitykt/enums/ClassIDType.kt @@ -1,379 +1,375 @@ -package io.github.deficuet.unitykt.file - -@Suppress("EnumEntryName") -enum class ClassIDType(val id: Int) { - UnknownType(-1), - Object(0), - GameObject(1), - Component(2), - LevelGameManager(3), - Transform(4), - TimeManager(5), - GlobalGameManager(6), - Behaviour(8), - GameManager(9), - AudioManager(11), - ParticleAnimator(12), - InputManager(13), - EllipsoidParticleEmitter(15), - Pipeline(17), - EditorExtension(18), - Physics2DSettings(19), - Camera(20), - Material(21), - MeshRenderer(23), - Renderer(25), - ParticleRenderer(26), - Texture(27), - Texture2D(28), - OcclusionCullingSettings(29), - GraphicsSettings(30), - MeshFilter(33), - OcclusionPortal(41), - Mesh(43), - Skybox(45), - QualitySettings(47), - Shader(48), - TextAsset(49), - Rigidbody2D(50), - Physics2DManager(51), - Collider2D(53), - Rigidbody(54), - PhysicsManager(55), - Collider(56), - Joint(57), - CircleCollider2D(58), - HingeJoint(59), - PolygonCollider2D(60), - BoxCollider2D(61), - PhysicsMaterial2D(62), - MeshCollider(64), - BoxCollider(65), - CompositeCollider2D(66), - EdgeCollider2D(68), - CapsuleCollider2D(70), - ComputeShader(72), - AnimationClip(74), - ConstantForce(75), - WorldParticleCollider(76), - TagManager(78), - AudioListener(81), - AudioSource(82), - AudioClip(83), - RenderTexture(84), - CustomRenderTexture(86), - MeshParticleEmitter(87), - ParticleEmitter(88), - Cubemap(89), - Avatar(90), - AnimatorController(91), - GUILayer(92), - RuntimeAnimatorController(93), - ScriptMapper(94), - Animator(95), - TrailRenderer(96), - DelayedCallManager(98), - TextMesh(102), - RenderSettings(104), - Light(108), - CGProgram(109), - BaseAnimationTrack(110), - Animation(111), - MonoBehaviour(114), - MonoScript(115), - MonoManager(116), - Texture3D(117), - NewAnimationTrack(118), - Projector(119), - LineRenderer(120), - Flare(121), - Halo(122), - LensFlare(123), - FlareLayer(124), - HaloLayer(125), - NavMeshProjectSettings(126), - HaloManager(127), - Font(128), - PlayerSettings(129), - NamedObject(130), - GUITexture(131), - GUIText(132), - GUIElement(133), - PhysicMaterial(134), - SphereCollider(135), - CapsuleCollider(136), - SkinnedMeshRenderer(137), - FixedJoint(138), - RaycastCollider(140), - BuildSettings(141), - AssetBundle(142), - CharacterController(143), - CharacterJoint(144), - SpringJoint(145), - WheelCollider(146), - ResourceManager(147), - NetworkView(148), - NetworkManager(149), - PreloadData(150), - MovieTexture(152), - ConfigurableJoint(153), - TerrainCollider(154), - MasterServerInterface(155), - TerrainData(156), - LightmapSettings(157), - WebCamTexture(158), - EditorSettings(159), - InteractiveCloth(160), - ClothRenderer(161), - EditorUserSettings(162), - SkinnedCloth(163), - AudioReverbFilter(164), - AudioHighPassFilter(165), - AudioChorusFilter(166), - AudioReverbZone(167), - AudioEchoFilter(168), - AudioLowPassFilter(169), - AudioDistortionFilter(170), - SparseTexture(171), - AudioBehaviour(180), - AudioFilter(181), - WindZone(182), - Cloth(183), - SubstanceArchive(184), - ProceduralMaterial(185), - ProceduralTexture(186), - Texture2DArray(187), - CubemapArray(188), - OffMeshLink(191), - OcclusionArea(192), - Tree(193), - NavMeshObsolete(194), - NavMeshAgent(195), - NavMeshSettings(196), - LightProbesLegacy(197), - ParticleSystem(198), - ParticleSystemRenderer(199), - ShaderVariantCollection(200), - LODGroup(205), - BlendTree(206), - Motion(207), - NavMeshObstacle(208), - SortingGroup(210), - SpriteRenderer(212), - Sprite(213), - CachedSpriteAtlas(214), - ReflectionProbe(215), - ReflectionProbes(216), - Terrain(218), - LightProbeGroup(220), - AnimatorOverrideController(221), - CanvasRenderer(222), - Canvas(223), - RectTransform(224), - CanvasGroup(225), - BillboardAsset(226), - BillboardRenderer(227), - SpeedTreeWindAsset(228), - AnchoredJoint2D(229), - Joint2D(230), - SpringJoint2D(231), - DistanceJoint2D(232), - HingeJoint2D(233), - SliderJoint2D(234), - WheelJoint2D(235), - ClusterInputManager(236), - BaseVideoTexture(237), - NavMeshData(238), - AudioMixer(240), - AudioMixerController(241), - AudioMixerGroupController(243), - AudioMixerEffectController(244), - AudioMixerSnapshotController(245), - PhysicsUpdateBehaviour2D(246), - ConstantForce2D(247), - Effector2D(248), - AreaEffector2D(249), - PointEffector2D(250), - PlatformEffector2D(251), - SurfaceEffector2D(252), - BuoyancyEffector2D(253), - RelativeJoint2D(254), - FixedJoint2D(255), - FrictionJoint2D(256), - TargetJoint2D(257), - LightProbes(258), - LightProbeProxyVolume(259), - SampleClip(271), - AudioMixerSnapshot(272), - AudioMixerGroup(273), - NScreenBridge(280), - AssetBundleManifest(290), - UnityAdsManager(292), - RuntimeInitializeOnLoadManager(300), - CloudWebServicesManager(301), - UnityAnalyticsManager(303), - CrashReportManager(304), - PerformanceReportingManager(305), - UnityConnectSettings(310), - AvatarMask(319), - PlayableDirector(320), - VideoPlayer(328), - VideoClip(329), - ParticleSystemForceField(330), - SpriteMask(331), - WorldAnchor(362), - OcclusionCullingData(363), - SmallestEditorClassID(1000), - PrefabInstance(1001), - EditorExtensionImpl(1002), - AssetImporter(1003), - AssetDatabaseV1(1004), - Mesh3DSImporter(1005), - TextureImporter(1006), - ShaderImporter(1007), - ComputeShaderImporter(1008), - AudioImporter(1020), - HierarchyState(1026), - GUIDSerializer(1027), - AssetMetaData(1028), - DefaultAsset(1029), - DefaultImporter(1030), - TextScriptImporter(1031), - SceneAsset(1032), - NativeFormatImporter(1034), - MonoImporter(1035), - AssetServerCache(1037), - LibraryAssetImporter(1038), - ModelImporter(1040), - FBXImporter(1041), - TrueTypeFontImporter(1042), - MovieImporter(1044), - EditorBuildSettings(1045), - DDSImporter(1046), - InspectorExpandedState(1048), - AnnotationManager(1049), - PluginImporter(1050), - EditorUserBuildSettings(1051), - PVRImporter(1052), - ASTCImporter(1053), - KTXImporter(1054), - IHVImageFormatImporter(1055), - AnimatorStateTransition(1101), - AnimatorState(1102), - HumanTemplate(1105), - AnimatorStateMachine(1107), - PreviewAnimationClip(1108), - AnimatorTransition(1109), - SpeedTreeImporter(1110), - AnimatorTransitionBase(1111), - SubstanceImporter(1112), - LightmapParameters(1113), - LightingDataAsset(1120), - GISRaster(1121), - GISRasterImporter(1122), - CadImporter(1123), - SketchUpImporter(1124), - BuildReport(1125), - PackedAssets(1126), - VideoClipImporter(1127), - ActivationLogComponent(2000), - int(100000), - bool(100001), - float(100002), - MonoObject(100003), - Collision(100004), - Vector3f(100005), - RootMotionData(100006), - Collision2D(100007), - AudioMixerLiveUpdateFloat(100008), - AudioMixerLiveUpdateBool(100009), - Polygon2D(100010), - void(100011), - TilemapCollider2D(19719996), - AssetImporterLog(41386430), - VFXRenderer(73398921), - SerializableManagedRefTestClass(76251197), - Grid(156049354), - ScenesUsingAssets(156483287), - ArticulationBody(171741748), - Preset(181963792), - EmptyObject(277625683), - IConstraint(285090594), - TestObjectWithSpecialLayoutOne(293259124), - AssemblyDefinitionReferenceImporter(294290339), - SiblingDerived(334799969), - TestObjectWithSerializedMapStringNonAlignedStruct(342846651), - SubDerived(367388927), - AssetImportInProgressProxy(369655926), - PluginBuildInfo(382020655), - EditorProjectAccess(426301858), - PrefabImporter(468431735), - TestObjectWithSerializedArray(478637458), - TestObjectWithSerializedAnimationCurve(478637459), - TilemapRenderer(483693784), - ScriptableCamera(488575907), - SpriteAtlasAsset(612988286), - SpriteAtlasDatabase(638013454), - AudioBuildInfo(641289076), - CachedSpriteAtlasRuntimeData(644342135), - RendererFake(646504946), - AssemblyDefinitionReferenceAsset(662584278), - BuiltAssetBundleInfoSet(668709126), - SpriteAtlas(687078895), - RayTracingShaderImporter(747330370), - RayTracingShader(825902497), - LightingSettings(850595691), - PlatformModuleSetup(877146078), - VersionControlSettings(890905787), - AimConstraint(895512359), - VFXManager(937362698), - VisualEffectSubgraph(994735392), - VisualEffectSubgraphOperator(994735403), - VisualEffectSubgraphBlock(994735404), - LocalizationImporter(1027052791), - Derived(1091556383), - PropertyModificationsTargetTestObject(1111377672), - ReferencesArtifactGenerator(1114811875), - AssemblyDefinitionAsset(1152215463), - SceneVisibilityState(1154873562), - LookAtConstraint(1183024399), - SpriteAtlasImporter(1210832254), - MultiArtifactTestImporter(1223240404), - GameObjectRecorder(1268269756), - LightingDataAssetParent(1325145578), - PresetManager(1386491679), - TestObjectWithSpecialLayoutTwo(1392443030), - StreamingManager(1403656975), - LowerResBlitTexture(1480428607), - StreamingController(1542919678), - RenderPassAttachment(1571458007), - TestObjectVectorPairStringBool(1628831178), - GridLayout(1742807556), - AssemblyDefinitionImporter(1766753193), - ParentConstraint(1773428102), - FakeComponent(1803986026), - PositionConstraint(1818360608), - RotationConstraint(1818360609), - ScaleConstraint(1818360610), - Tilemap(1839735485), - PackageManifest(1896753125), - PackageManifestImporter(1896753126), - TerrainLayer(1953259897), - SpriteShapeRenderer(1971053207), - NativeObjectType(1977754360), - TestObjectWithSerializedMapStringBool(1981279845), - SerializableManagedHost(1995898324), - VisualEffectAsset(2058629509), - VisualEffectImporter(2058629510), - VisualEffectResource(2058629511), - VisualEffectObject(2059678085), - VisualEffect(2083052967), - LocalizationAsset(2083778819), - ScriptedImporter(2089858483); - - companion object { - fun of(value: Int): ClassIDType { - return values().firstOrNull { it.id == value } ?: Object - } - } -} \ No newline at end of file +package io.github.deficuet.unitykt.enums + +@Suppress("EnumEntryName") +enum class ClassIDType(override val id: Int): NumericalEnum { + UnknownType(-1), + Object(0), + GameObject(1), + Component(2), + LevelGameManager(3), + Transform(4), + TimeManager(5), + GlobalGameManager(6), + Behaviour(8), + GameManager(9), + AudioManager(11), + ParticleAnimator(12), + InputManager(13), + EllipsoidParticleEmitter(15), + Pipeline(17), + EditorExtension(18), + Physics2DSettings(19), + Camera(20), + Material(21), + MeshRenderer(23), + Renderer(25), + ParticleRenderer(26), + Texture(27), + Texture2D(28), + OcclusionCullingSettings(29), + GraphicsSettings(30), + MeshFilter(33), + OcclusionPortal(41), + Mesh(43), + Skybox(45), + QualitySettings(47), + Shader(48), + TextAsset(49), + Rigidbody2D(50), + Physics2DManager(51), + Collider2D(53), + Rigidbody(54), + PhysicsManager(55), + Collider(56), + Joint(57), + CircleCollider2D(58), + HingeJoint(59), + PolygonCollider2D(60), + BoxCollider2D(61), + PhysicsMaterial2D(62), + MeshCollider(64), + BoxCollider(65), + CompositeCollider2D(66), + EdgeCollider2D(68), + CapsuleCollider2D(70), + ComputeShader(72), + AnimationClip(74), + ConstantForce(75), + WorldParticleCollider(76), + TagManager(78), + AudioListener(81), + AudioSource(82), + AudioClip(83), + RenderTexture(84), + CustomRenderTexture(86), + MeshParticleEmitter(87), + ParticleEmitter(88), + Cubemap(89), + Avatar(90), + AnimatorController(91), + GUILayer(92), + RuntimeAnimatorController(93), + ScriptMapper(94), + Animator(95), + TrailRenderer(96), + DelayedCallManager(98), + TextMesh(102), + RenderSettings(104), + Light(108), + CGProgram(109), + BaseAnimationTrack(110), + Animation(111), + MonoBehaviour(114), + MonoScript(115), + MonoManager(116), + Texture3D(117), + NewAnimationTrack(118), + Projector(119), + LineRenderer(120), + Flare(121), + Halo(122), + LensFlare(123), + FlareLayer(124), + HaloLayer(125), + NavMeshProjectSettings(126), + HaloManager(127), + Font(128), + PlayerSettings(129), + NamedObject(130), + GUITexture(131), + GUIText(132), + GUIElement(133), + PhysicMaterial(134), + SphereCollider(135), + CapsuleCollider(136), + SkinnedMeshRenderer(137), + FixedJoint(138), + RaycastCollider(140), + BuildSettings(141), + AssetBundle(142), + CharacterController(143), + CharacterJoint(144), + SpringJoint(145), + WheelCollider(146), + ResourceManager(147), + NetworkView(148), + NetworkManager(149), + PreloadData(150), + MovieTexture(152), + ConfigurableJoint(153), + TerrainCollider(154), + MasterServerInterface(155), + TerrainData(156), + LightmapSettings(157), + WebCamTexture(158), + EditorSettings(159), + InteractiveCloth(160), + ClothRenderer(161), + EditorUserSettings(162), + SkinnedCloth(163), + AudioReverbFilter(164), + AudioHighPassFilter(165), + AudioChorusFilter(166), + AudioReverbZone(167), + AudioEchoFilter(168), + AudioLowPassFilter(169), + AudioDistortionFilter(170), + SparseTexture(171), + AudioBehaviour(180), + AudioFilter(181), + WindZone(182), + Cloth(183), + SubstanceArchive(184), + ProceduralMaterial(185), + ProceduralTexture(186), + Texture2DArray(187), + CubemapArray(188), + OffMeshLink(191), + OcclusionArea(192), + Tree(193), + NavMeshObsolete(194), + NavMeshAgent(195), + NavMeshSettings(196), + LightProbesLegacy(197), + ParticleSystem(198), + ParticleSystemRenderer(199), + ShaderVariantCollection(200), + LODGroup(205), + BlendTree(206), + Motion(207), + NavMeshObstacle(208), + SortingGroup(210), + SpriteRenderer(212), + Sprite(213), + CachedSpriteAtlas(214), + ReflectionProbe(215), + ReflectionProbes(216), + Terrain(218), + LightProbeGroup(220), + AnimatorOverrideController(221), + CanvasRenderer(222), + Canvas(223), + RectTransform(224), + CanvasGroup(225), + BillboardAsset(226), + BillboardRenderer(227), + SpeedTreeWindAsset(228), + AnchoredJoint2D(229), + Joint2D(230), + SpringJoint2D(231), + DistanceJoint2D(232), + HingeJoint2D(233), + SliderJoint2D(234), + WheelJoint2D(235), + ClusterInputManager(236), + BaseVideoTexture(237), + NavMeshData(238), + AudioMixer(240), + AudioMixerController(241), + AudioMixerGroupController(243), + AudioMixerEffectController(244), + AudioMixerSnapshotController(245), + PhysicsUpdateBehaviour2D(246), + ConstantForce2D(247), + Effector2D(248), + AreaEffector2D(249), + PointEffector2D(250), + PlatformEffector2D(251), + SurfaceEffector2D(252), + BuoyancyEffector2D(253), + RelativeJoint2D(254), + FixedJoint2D(255), + FrictionJoint2D(256), + TargetJoint2D(257), + LightProbes(258), + LightProbeProxyVolume(259), + SampleClip(271), + AudioMixerSnapshot(272), + AudioMixerGroup(273), + NScreenBridge(280), + AssetBundleManifest(290), + UnityAdsManager(292), + RuntimeInitializeOnLoadManager(300), + CloudWebServicesManager(301), + UnityAnalyticsManager(303), + CrashReportManager(304), + PerformanceReportingManager(305), + UnityConnectSettings(310), + AvatarMask(319), + PlayableDirector(320), + VideoPlayer(328), + VideoClip(329), + ParticleSystemForceField(330), + SpriteMask(331), + WorldAnchor(362), + OcclusionCullingData(363), + SmallestEditorClassID(1000), + PrefabInstance(1001), + EditorExtensionImpl(1002), + AssetImporter(1003), + AssetDatabaseV1(1004), + Mesh3DSImporter(1005), + TextureImporter(1006), + ShaderImporter(1007), + ComputeShaderImporter(1008), + AudioImporter(1020), + HierarchyState(1026), + GUIDSerializer(1027), + AssetMetaData(1028), + DefaultAsset(1029), + DefaultImporter(1030), + TextScriptImporter(1031), + SceneAsset(1032), + NativeFormatImporter(1034), + MonoImporter(1035), + AssetServerCache(1037), + LibraryAssetImporter(1038), + ModelImporter(1040), + FBXImporter(1041), + TrueTypeFontImporter(1042), + MovieImporter(1044), + EditorBuildSettings(1045), + DDSImporter(1046), + InspectorExpandedState(1048), + AnnotationManager(1049), + PluginImporter(1050), + EditorUserBuildSettings(1051), + PVRImporter(1052), + ASTCImporter(1053), + KTXImporter(1054), + IHVImageFormatImporter(1055), + AnimatorStateTransition(1101), + AnimatorState(1102), + HumanTemplate(1105), + AnimatorStateMachine(1107), + PreviewAnimationClip(1108), + AnimatorTransition(1109), + SpeedTreeImporter(1110), + AnimatorTransitionBase(1111), + SubstanceImporter(1112), + LightmapParameters(1113), + LightingDataAsset(1120), + GISRaster(1121), + GISRasterImporter(1122), + CadImporter(1123), + SketchUpImporter(1124), + BuildReport(1125), + PackedAssets(1126), + VideoClipImporter(1127), + ActivationLogComponent(2000), + int(100000), + bool(100001), + float(100002), + MonoObject(100003), + Collision(100004), + Vector3f(100005), + RootMotionData(100006), + Collision2D(100007), + AudioMixerLiveUpdateFloat(100008), + AudioMixerLiveUpdateBool(100009), + Polygon2D(100010), + void(100011), + TilemapCollider2D(19719996), + AssetImporterLog(41386430), + VFXRenderer(73398921), + SerializableManagedRefTestClass(76251197), + Grid(156049354), + ScenesUsingAssets(156483287), + ArticulationBody(171741748), + Preset(181963792), + EmptyObject(277625683), + IConstraint(285090594), + TestObjectWithSpecialLayoutOne(293259124), + AssemblyDefinitionReferenceImporter(294290339), + SiblingDerived(334799969), + TestObjectWithSerializedMapStringNonAlignedStruct(342846651), + SubDerived(367388927), + AssetImportInProgressProxy(369655926), + PluginBuildInfo(382020655), + EditorProjectAccess(426301858), + PrefabImporter(468431735), + TestObjectWithSerializedArray(478637458), + TestObjectWithSerializedAnimationCurve(478637459), + TilemapRenderer(483693784), + ScriptableCamera(488575907), + SpriteAtlasAsset(612988286), + SpriteAtlasDatabase(638013454), + AudioBuildInfo(641289076), + CachedSpriteAtlasRuntimeData(644342135), + RendererFake(646504946), + AssemblyDefinitionReferenceAsset(662584278), + BuiltAssetBundleInfoSet(668709126), + SpriteAtlas(687078895), + RayTracingShaderImporter(747330370), + RayTracingShader(825902497), + LightingSettings(850595691), + PlatformModuleSetup(877146078), + VersionControlSettings(890905787), + AimConstraint(895512359), + VFXManager(937362698), + VisualEffectSubgraph(994735392), + VisualEffectSubgraphOperator(994735403), + VisualEffectSubgraphBlock(994735404), + LocalizationImporter(1027052791), + Derived(1091556383), + PropertyModificationsTargetTestObject(1111377672), + ReferencesArtifactGenerator(1114811875), + AssemblyDefinitionAsset(1152215463), + SceneVisibilityState(1154873562), + LookAtConstraint(1183024399), + SpriteAtlasImporter(1210832254), + MultiArtifactTestImporter(1223240404), + GameObjectRecorder(1268269756), + LightingDataAssetParent(1325145578), + PresetManager(1386491679), + TestObjectWithSpecialLayoutTwo(1392443030), + StreamingManager(1403656975), + LowerResBlitTexture(1480428607), + StreamingController(1542919678), + RenderPassAttachment(1571458007), + TestObjectVectorPairStringBool(1628831178), + GridLayout(1742807556), + AssemblyDefinitionImporter(1766753193), + ParentConstraint(1773428102), + FakeComponent(1803986026), + PositionConstraint(1818360608), + RotationConstraint(1818360609), + ScaleConstraint(1818360610), + Tilemap(1839735485), + PackageManifest(1896753125), + PackageManifestImporter(1896753126), + TerrainLayer(1953259897), + SpriteShapeRenderer(1971053207), + NativeObjectType(1977754360), + TestObjectWithSerializedMapStringBool(1981279845), + SerializableManagedHost(1995898324), + VisualEffectAsset(2058629509), + VisualEffectImporter(2058629510), + VisualEffectResource(2058629511), + VisualEffectObject(2059678085), + VisualEffect(2083052967), + LocalizationAsset(2083778819), + ScriptedImporter(2089858483); + + companion object: NumericalEnumCompanion(values(), Object) +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/enums/FlagsAttributeEnum.kt b/src/main/kotlin/io/github/deficuet/unitykt/enums/FlagsAttributeEnum.kt new file mode 100644 index 00000000..8a8cb97b --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/enums/FlagsAttributeEnum.kt @@ -0,0 +1,35 @@ +package io.github.deficuet.unitykt.enums + +import java.util.* + +/** + * C# [`Flags`] attribute applied on enum class + */ +interface FlagsAttributeEnum { + val bitPos: Int + val value get() = if (bitPos == -1) 0u else 1u.shl(bitPos) + + companion object { + internal val flagsAttributeEnumClass = FlagsAttributeEnum::class.java + } +} + +abstract class FlagsAttributeEnumCompanion( + private val enumClass: Class, + enumValues: Array, + private val mainZero: E +) where E: FlagsAttributeEnum, E: Enum { + private val nonZeroTable = enumValues.associateBy { it.bitPos } + private val zeros = enumValues.filter { it.bitPos == -1 && it != mainZero } + + fun of(value: UInt): EnumSet { + if (value == 0u) return EnumSet.of(mainZero) + val set = EnumSet.copyOf(zeros) + for (i in 0..31) { + if (value.and(1u.shl(i)) != 0u) { + nonZeroTable[i]?.let { set.add(it) } ?: return EnumSet.noneOf(enumClass) + } + } + return set + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/enums/NumericalEnum.kt b/src/main/kotlin/io/github/deficuet/unitykt/enums/NumericalEnum.kt new file mode 100644 index 00000000..ee49cc49 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/enums/NumericalEnum.kt @@ -0,0 +1,18 @@ +package io.github.deficuet.unitykt.enums + +interface NumericalEnum> { + val id: N +} + +interface NumericalEnumMap, E: Enum> { + fun of(value: N): E +} + +abstract class NumericalEnumCompanion, E>( + enumValues: Array, + private val default: E +): NumericalEnumMap where E: Enum, E: NumericalEnum { + val cacheTable: Map = enumValues.associateBy { it.id } + + override fun of(value: N): E = cacheTable[value] ?: default +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/enums/OrdinalEnumCompanion.kt b/src/main/kotlin/io/github/deficuet/unitykt/enums/OrdinalEnumCompanion.kt new file mode 100644 index 00000000..36c0f73b --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/enums/OrdinalEnumCompanion.kt @@ -0,0 +1,7 @@ +package io.github.deficuet.unitykt.enums + +abstract class OrdinalEnumCompanion>( + val array: Array +) { + fun of(num: Int) = array[num] +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/export/EndianByteArrayWriter.kt b/src/main/kotlin/io/github/deficuet/unitykt/export/EndianByteArrayWriter.kt deleted file mode 100644 index c711b0b1..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/export/EndianByteArrayWriter.kt +++ /dev/null @@ -1,26 +0,0 @@ -package io.github.deficuet.unitykt.export - -import java.nio.ByteBuffer -import java.nio.ByteOrder - -internal class EndianByteArrayWriter( - size: Int, - var endianType: ByteOrder = ByteOrder.BIG_ENDIAN -): AutoCloseable { - val array = ByteArray(size) - val length = size - var position = 0 - - @Suppress("SameParameterValue") - private fun newByteBuffer(capacity: Int) = ByteBuffer.allocate(capacity).order(endianType) - - private fun write(bytes: ByteArray) { - System.arraycopy(bytes, 0, array, position, bytes.size) - position += bytes.size - } - - fun writeInt(value: Int) = write(newByteBuffer(4).putInt(value).array()) - fun writeUInt(value: UInt) = writeInt(value.toInt()) - - override fun close() { } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/export/spirv/EnumType.kt b/src/main/kotlin/io/github/deficuet/unitykt/export/spirv/EnumType.kt deleted file mode 100644 index 99d03d8f..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/export/spirv/EnumType.kt +++ /dev/null @@ -1,56 +0,0 @@ -package io.github.deficuet.unitykt.export.spirv - -import io.github.deficuet.unitykt.util.Reference - -internal class EnumType, P: ParameterFactory> private constructor( - private val enumClass: Class, - private val factory: P -): OperandType() { - override fun readValue(words: Array, index: Int, value: Reference): Int { - var wordsUsedForParameters = 0 - val enumValues = enumClass.enumConstants - if (FlagsAttributeEnum.flagsClass.isAssignableFrom(enumClass)) { - val result = mutableMapOf>() - for (enum in enumValues) { - val bit = (enum as FlagsAttributeEnum<*>).numeric.toUInt() - if (words[index].and(bit) != 0u || (bit == 0u && words[index] == 0u)) { - result[bit] = factory.createParameter(bit)?.let { param -> - Array(param.operandTypes.size) { - val pValueRef = Reference() - val pWordsUsed = param.operandTypes[it].readValue( - words, 1 + wordsUsedForParameters, pValueRef - ) - wordsUsedForParameters += pWordsUsed - pValueRef.value - } - } ?: emptyArray() - } - } - value.value = BitEnumOperandValue(result, enumClass) - } else { - val result: Array = factory.createParameter(words[index])?.let { param -> - Array(param.operandTypes.size) { - val pValueRef = Reference() - val pWordsUsed = param.operandTypes[it].readValue( - words, 1 + wordsUsedForParameters, pValueRef - ) - wordsUsedForParameters += pWordsUsed - pValueRef.value - } - } ?: emptyArray() - value.value = ValueEnumOperandValue( - enumValues.firstOrNull { (it as NumericalEnum<*>).id == words[index] } ?: enumValues.first(), - result, enumClass - ) - } - return wordsUsedForParameters + 1 - } - - companion object { - internal inline operator fun , reified U: ParameterFactory> invoke(): EnumType { - return EnumType(T::class.java, U::class.java.constructors[0].newInstance() as U) - } - - internal inline fun > create() = EnumType() - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/export/spirv/FlagsAttributeEnum.kt b/src/main/kotlin/io/github/deficuet/unitykt/export/spirv/FlagsAttributeEnum.kt deleted file mode 100644 index 617c5c35..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/export/spirv/FlagsAttributeEnum.kt +++ /dev/null @@ -1,36 +0,0 @@ -package io.github.deficuet.unitykt.export.spirv - -import java.util.* - -internal interface FlagsAttributeEnum> { - val exp: Int - - val numeric: Int get() = if (exp == -1) 0 else 1.shl(exp) - - companion object { - val flagsClass = FlagsAttributeEnum::class.java - } -} - -internal abstract class FlagsAttributeEnumCompanion> - -internal inline fun > FlagsAttributeEnumCompanion.of(value: Long): EnumSet { - val enums = enumValues() - val enumClass = E::class.java - val zeros = enums.filter { (it as FlagsAttributeEnum<*>).exp == -1 }.toMutableList() - if (value == 0L) { - return if (zeros.isEmpty()) EnumSet.noneOf(enumClass) else EnumSet.of(zeros[0]) - } else { - with(zeros) { if (isNotEmpty()) removeFirst() } - val bits = BitSet.valueOf(longArrayOf(value)) - val exps = enums.map { (it as FlagsAttributeEnum<*>).exp } - val result = if (zeros.isEmpty()) EnumSet.noneOf(enumClass) else EnumSet.copyOf(zeros) - for (i in 0..31) { - if (bits[i]) { - if (i !in exps) return EnumSet.noneOf(enumClass) - result += enums.last { (it as FlagsAttributeEnum<*>).exp == i } - } - } - return result - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/export/spirv/Instruction.kt b/src/main/kotlin/io/github/deficuet/unitykt/export/spirv/Instruction.kt deleted file mode 100644 index 140af56b..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/export/spirv/Instruction.kt +++ /dev/null @@ -1,347 +0,0 @@ -package io.github.deficuet.unitykt.export.spirv - -internal enum class OperandQuantifier { - Default, Optional, Varying -} - -internal class Operand(val type: OperandType, val name: String, val quantifier: OperandQuantifier) - -internal class Instruction(val name: String, val operands: List) { - constructor(name: String): this(name, emptyList()) - - companion object { - //Auto generated - val fromOpcode = mapOf( - 0 to Instruction("OpNop"), - 1 to Instruction("OpUndef", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default))), - 2 to Instruction("OpSourceContinued", listOf(Operand(LiteralString(), "Continued Source", OperandQuantifier.Default))), - 3 to Instruction("OpSource", listOf(Operand(EnumType(), "", OperandQuantifier.Default), Operand(LiteralInteger(), "Version", OperandQuantifier.Default), Operand(IdRef(), "File", OperandQuantifier.Optional), Operand(LiteralString(), "Source", OperandQuantifier.Optional))), - 4 to Instruction("OpSourceExtension", listOf(Operand(LiteralString(), "Extension", OperandQuantifier.Default))), - 5 to Instruction("OpName", listOf(Operand(IdRef(), "Target", OperandQuantifier.Default), Operand(LiteralString(), "Name", OperandQuantifier.Default))), - 6 to Instruction("OpMemberName", listOf(Operand(IdRef(), "Type", OperandQuantifier.Default), Operand(LiteralInteger(), "Member", OperandQuantifier.Default), Operand(LiteralString(), "Name", OperandQuantifier.Default))), - 7 to Instruction("OpString", listOf(Operand(IdResult(), "", OperandQuantifier.Default), Operand(LiteralString(), "String", OperandQuantifier.Default))), - 8 to Instruction("OpLine", listOf(Operand(IdRef(), "File", OperandQuantifier.Default), Operand(LiteralInteger(), "Line", OperandQuantifier.Default), Operand(LiteralInteger(), "Column", OperandQuantifier.Default))), - 10 to Instruction("OpExtension", listOf(Operand(LiteralString(), "Name", OperandQuantifier.Default))), - 11 to Instruction("OpExtInstImport", listOf(Operand(IdResult(), "", OperandQuantifier.Default), Operand(LiteralString(), "Name", OperandQuantifier.Default))), - 12 to Instruction("OpExtInst", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Set", OperandQuantifier.Default), Operand(LiteralExtInstInteger(), "Instruction", OperandQuantifier.Default), Operand(IdRef(), "Operand 1, +Operand 2, +...", OperandQuantifier.Varying))), - 14 to Instruction("OpMemoryModel", listOf(Operand(EnumType(), "", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Default))), - 15 to Instruction("OpEntryPoint", listOf(Operand(EnumType(), "", OperandQuantifier.Default), Operand(IdRef(), "Entry Point", OperandQuantifier.Default), Operand(LiteralString(), "Name", OperandQuantifier.Default), Operand(IdRef(), "Interface", OperandQuantifier.Varying))), - 16 to Instruction("OpExecutionMode", listOf(Operand(IdRef(), "Entry Point", OperandQuantifier.Default), Operand(EnumType(), "Mode", OperandQuantifier.Default))), - 17 to Instruction("OpCapability", listOf(Operand(EnumType(), "Capability", OperandQuantifier.Default))), - 19 to Instruction("OpTypeVoid", listOf(Operand(IdResult(), "", OperandQuantifier.Default))), - 20 to Instruction("OpTypeBool", listOf(Operand(IdResult(), "", OperandQuantifier.Default))), - 21 to Instruction("OpTypeInt", listOf(Operand(IdResult(), "", OperandQuantifier.Default), Operand(LiteralInteger(), "Width", OperandQuantifier.Default), Operand(LiteralInteger(), "Signedness", OperandQuantifier.Default))), - 22 to Instruction("OpTypeFloat", listOf(Operand(IdResult(), "", OperandQuantifier.Default), Operand(LiteralInteger(), "Width", OperandQuantifier.Default))), - 23 to Instruction("OpTypeVector", listOf(Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Component Type", OperandQuantifier.Default), Operand(LiteralInteger(), "Component Count", OperandQuantifier.Default))), - 24 to Instruction("OpTypeMatrix", listOf(Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Column Type", OperandQuantifier.Default), Operand(LiteralInteger(), "Column Count", OperandQuantifier.Default))), - 25 to Instruction("OpTypeImage", listOf(Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Type", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Default), Operand(LiteralInteger(), "Depth", OperandQuantifier.Default), Operand(LiteralInteger(), "Arrayed", OperandQuantifier.Default), Operand(LiteralInteger(), "MS", OperandQuantifier.Default), Operand(LiteralInteger(), "Sampled", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Optional))), - 26 to Instruction("OpTypeSampler", listOf(Operand(IdResult(), "", OperandQuantifier.Default))), - 27 to Instruction("OpTypeSampledImage", listOf(Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Image Type", OperandQuantifier.Default))), - 28 to Instruction("OpTypeArray", listOf(Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Element Type", OperandQuantifier.Default), Operand(IdRef(), "Length", OperandQuantifier.Default))), - 29 to Instruction("OpTypeRuntimeArray", listOf(Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Element Type", OperandQuantifier.Default))), - 30 to Instruction("OpTypeStruct", listOf(Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Member 0 type, +member 1 type, +...", OperandQuantifier.Varying))), - 31 to Instruction("OpTypeOpaque", listOf(Operand(IdResult(), "", OperandQuantifier.Default), Operand(LiteralString(), "The name of the opaque type.", OperandQuantifier.Default))), - 32 to Instruction("OpTypePointer", listOf(Operand(IdResult(), "", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Default), Operand(IdRef(), "Type", OperandQuantifier.Default))), - 33 to Instruction("OpTypeFunction", listOf(Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Return Type", OperandQuantifier.Default), Operand(IdRef(), "Parameter 0 Type, +Parameter 1 Type, +...", OperandQuantifier.Varying))), - 34 to Instruction("OpTypeEvent", listOf(Operand(IdResult(), "", OperandQuantifier.Default))), - 35 to Instruction("OpTypeDeviceEvent", listOf(Operand(IdResult(), "", OperandQuantifier.Default))), - 36 to Instruction("OpTypeReserveId", listOf(Operand(IdResult(), "", OperandQuantifier.Default))), - 37 to Instruction("OpTypeQueue", listOf(Operand(IdResult(), "", OperandQuantifier.Default))), - 38 to Instruction("OpTypePipe", listOf(Operand(IdResult(), "", OperandQuantifier.Default), Operand(EnumType(), "Qualifier", OperandQuantifier.Default))), - 39 to Instruction("OpTypeForwardPointer", listOf(Operand(IdRef(), "Pointer Type", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Default))), - 41 to Instruction("OpConstantTrue", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default))), - 42 to Instruction("OpConstantFalse", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default))), - 43 to Instruction("OpConstant", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(LiteralContextDependentNumber(), "Value", OperandQuantifier.Default))), - 44 to Instruction("OpConstantComposite", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Constituents", OperandQuantifier.Varying))), - 45 to Instruction("OpConstantSampler", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Default), Operand(LiteralInteger(), "Param", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Default))), - 46 to Instruction("OpConstantNull", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default))), - 48 to Instruction("OpSpecConstantTrue", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default))), - 49 to Instruction("OpSpecConstantFalse", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default))), - 50 to Instruction("OpSpecConstant", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(LiteralContextDependentNumber(), "Value", OperandQuantifier.Default))), - 51 to Instruction("OpSpecConstantComposite", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Constituents", OperandQuantifier.Varying))), - 52 to Instruction("OpSpecConstantOp", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(LiteralSpecConstantOpInteger(), "Opcode", OperandQuantifier.Default))), - 54 to Instruction("OpFunction", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Default), Operand(IdRef(), "Function Type", OperandQuantifier.Default))), - 55 to Instruction("OpFunctionParameter", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default))), - 56 to Instruction("OpFunctionEnd"), - 57 to Instruction("OpFunctionCall", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Function", OperandQuantifier.Default), Operand(IdRef(), "Argument 0, +Argument 1, +...", OperandQuantifier.Varying))), - 59 to Instruction("OpVariable", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Default), Operand(IdRef(), "Initializer", OperandQuantifier.Optional))), - 60 to Instruction("OpImageTexelPointer", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(IdRef(), "Sample", OperandQuantifier.Default))), - 61 to Instruction("OpLoad", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Optional))), - 62 to Instruction("OpStore", listOf(Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdRef(), "Object", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Optional))), - 63 to Instruction("OpCopyMemory", listOf(Operand(IdRef(), "Target", OperandQuantifier.Default), Operand(IdRef(), "Source", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Optional))), - 64 to Instruction("OpCopyMemorySized", listOf(Operand(IdRef(), "Target", OperandQuantifier.Default), Operand(IdRef(), "Source", OperandQuantifier.Default), Operand(IdRef(), "Size", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Optional))), - 65 to Instruction("OpAccessChain", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Base", OperandQuantifier.Default), Operand(IdRef(), "Indexes", OperandQuantifier.Varying))), - 66 to Instruction("OpInBoundsAccessChain", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Base", OperandQuantifier.Default), Operand(IdRef(), "Indexes", OperandQuantifier.Varying))), - 67 to Instruction("OpPtrAccessChain", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Base", OperandQuantifier.Default), Operand(IdRef(), "Element", OperandQuantifier.Default), Operand(IdRef(), "Indexes", OperandQuantifier.Varying))), - 68 to Instruction("OpArrayLength", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Structure", OperandQuantifier.Default), Operand(LiteralInteger(), "Array member", OperandQuantifier.Default))), - 69 to Instruction("OpGenericPtrMemSemantics", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default))), - 70 to Instruction("OpInBoundsPtrAccessChain", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Base", OperandQuantifier.Default), Operand(IdRef(), "Element", OperandQuantifier.Default), Operand(IdRef(), "Indexes", OperandQuantifier.Varying))), - 71 to Instruction("OpDecorate", listOf(Operand(IdRef(), "Target", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Default))), - 72 to Instruction("OpMemberDecorate", listOf(Operand(IdRef(), "Structure Type", OperandQuantifier.Default), Operand(LiteralInteger(), "Member", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Default))), - 73 to Instruction("OpDecorationGroup", listOf(Operand(IdResult(), "", OperandQuantifier.Default))), - 74 to Instruction("OpGroupDecorate", listOf(Operand(IdRef(), "Decoration Group", OperandQuantifier.Default), Operand(IdRef(), "Targets", OperandQuantifier.Varying))), - 75 to Instruction("OpGroupMemberDecorate", listOf(Operand(IdRef(), "Decoration Group", OperandQuantifier.Default), Operand(PairIdRefLiteralInteger(), "Targets", OperandQuantifier.Varying))), - 77 to Instruction("OpVectorExtractDynamic", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Vector", OperandQuantifier.Default), Operand(IdRef(), "Index", OperandQuantifier.Default))), - 78 to Instruction("OpVectorInsertDynamic", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Vector", OperandQuantifier.Default), Operand(IdRef(), "Component", OperandQuantifier.Default), Operand(IdRef(), "Index", OperandQuantifier.Default))), - 79 to Instruction("OpVectorShuffle", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Vector 1", OperandQuantifier.Default), Operand(IdRef(), "Vector 2", OperandQuantifier.Default), Operand(LiteralInteger(), "Components", OperandQuantifier.Varying))), - 80 to Instruction("OpCompositeConstruct", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Constituents", OperandQuantifier.Varying))), - 81 to Instruction("OpCompositeExtract", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Composite", OperandQuantifier.Default), Operand(LiteralInteger(), "Indexes", OperandQuantifier.Varying))), - 82 to Instruction("OpCompositeInsert", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Object", OperandQuantifier.Default), Operand(IdRef(), "Composite", OperandQuantifier.Default), Operand(LiteralInteger(), "Indexes", OperandQuantifier.Varying))), - 83 to Instruction("OpCopyObject", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand", OperandQuantifier.Default))), - 84 to Instruction("OpTranspose", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Matrix", OperandQuantifier.Default))), - 86 to Instruction("OpSampledImage", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Image", OperandQuantifier.Default), Operand(IdRef(), "Sampler", OperandQuantifier.Default))), - 87 to Instruction("OpImageSampleImplicitLod", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Optional))), - 88 to Instruction("OpImageSampleExplicitLod", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Default))), - 89 to Instruction("OpImageSampleDrefImplicitLod", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(IdRef(), "D~ref~", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Optional))), - 90 to Instruction("OpImageSampleDrefExplicitLod", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(IdRef(), "D~ref~", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Default))), - 91 to Instruction("OpImageSampleProjImplicitLod", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Optional))), - 92 to Instruction("OpImageSampleProjExplicitLod", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Default))), - 93 to Instruction("OpImageSampleProjDrefImplicitLod", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(IdRef(), "D~ref~", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Optional))), - 94 to Instruction("OpImageSampleProjDrefExplicitLod", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(IdRef(), "D~ref~", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Default))), - 95 to Instruction("OpImageFetch", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Optional))), - 96 to Instruction("OpImageGather", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(IdRef(), "Component", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Optional))), - 97 to Instruction("OpImageDrefGather", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(IdRef(), "D~ref~", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Optional))), - 98 to Instruction("OpImageRead", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Optional))), - 99 to Instruction("OpImageWrite", listOf(Operand(IdRef(), "Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(IdRef(), "Texel", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Optional))), - 100 to Instruction("OpImage", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default))), - 101 to Instruction("OpImageQueryFormat", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Image", OperandQuantifier.Default))), - 102 to Instruction("OpImageQueryOrder", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Image", OperandQuantifier.Default))), - 103 to Instruction("OpImageQuerySizeLod", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Image", OperandQuantifier.Default), Operand(IdRef(), "Level of Detail", OperandQuantifier.Default))), - 104 to Instruction("OpImageQuerySize", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Image", OperandQuantifier.Default))), - 105 to Instruction("OpImageQueryLod", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default))), - 106 to Instruction("OpImageQueryLevels", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Image", OperandQuantifier.Default))), - 107 to Instruction("OpImageQuerySamples", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Image", OperandQuantifier.Default))), - 109 to Instruction("OpConvertFToU", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Float Value", OperandQuantifier.Default))), - 110 to Instruction("OpConvertFToS", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Float Value", OperandQuantifier.Default))), - 111 to Instruction("OpConvertSToF", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Signed Value", OperandQuantifier.Default))), - 112 to Instruction("OpConvertUToF", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Unsigned Value", OperandQuantifier.Default))), - 113 to Instruction("OpUConvert", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Unsigned Value", OperandQuantifier.Default))), - 114 to Instruction("OpSConvert", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Signed Value", OperandQuantifier.Default))), - 115 to Instruction("OpFConvert", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Float Value", OperandQuantifier.Default))), - 116 to Instruction("OpQuantizeToF16", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default))), - 117 to Instruction("OpConvertPtrToU", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default))), - 118 to Instruction("OpSatConvertSToU", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Signed Value", OperandQuantifier.Default))), - 119 to Instruction("OpSatConvertUToS", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Unsigned Value", OperandQuantifier.Default))), - 120 to Instruction("OpConvertUToPtr", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Integer Value", OperandQuantifier.Default))), - 121 to Instruction("OpPtrCastToGeneric", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default))), - 122 to Instruction("OpGenericCastToPtr", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default))), - 123 to Instruction("OpGenericCastToPtrExplicit", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(EnumType(), "Storage", OperandQuantifier.Default))), - 124 to Instruction("OpBitcast", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand", OperandQuantifier.Default))), - 126 to Instruction("OpSNegate", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand", OperandQuantifier.Default))), - 127 to Instruction("OpFNegate", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand", OperandQuantifier.Default))), - 128 to Instruction("OpIAdd", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 129 to Instruction("OpFAdd", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 130 to Instruction("OpISub", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 131 to Instruction("OpFSub", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 132 to Instruction("OpIMul", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 133 to Instruction("OpFMul", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 134 to Instruction("OpUDiv", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 135 to Instruction("OpSDiv", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 136 to Instruction("OpFDiv", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 137 to Instruction("OpUMod", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 138 to Instruction("OpSRem", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 139 to Instruction("OpSMod", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 140 to Instruction("OpFRem", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 141 to Instruction("OpFMod", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 142 to Instruction("OpVectorTimesScalar", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Vector", OperandQuantifier.Default), Operand(IdRef(), "Scalar", OperandQuantifier.Default))), - 143 to Instruction("OpMatrixTimesScalar", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Matrix", OperandQuantifier.Default), Operand(IdRef(), "Scalar", OperandQuantifier.Default))), - 144 to Instruction("OpVectorTimesMatrix", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Vector", OperandQuantifier.Default), Operand(IdRef(), "Matrix", OperandQuantifier.Default))), - 145 to Instruction("OpMatrixTimesVector", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Matrix", OperandQuantifier.Default), Operand(IdRef(), "Vector", OperandQuantifier.Default))), - 146 to Instruction("OpMatrixTimesMatrix", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "LeftMatrix", OperandQuantifier.Default), Operand(IdRef(), "RightMatrix", OperandQuantifier.Default))), - 147 to Instruction("OpOuterProduct", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Vector 1", OperandQuantifier.Default), Operand(IdRef(), "Vector 2", OperandQuantifier.Default))), - 148 to Instruction("OpDot", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Vector 1", OperandQuantifier.Default), Operand(IdRef(), "Vector 2", OperandQuantifier.Default))), - 149 to Instruction("OpIAddCarry", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 150 to Instruction("OpISubBorrow", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 151 to Instruction("OpUMulExtended", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 152 to Instruction("OpSMulExtended", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 154 to Instruction("OpAny", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Vector", OperandQuantifier.Default))), - 155 to Instruction("OpAll", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Vector", OperandQuantifier.Default))), - 156 to Instruction("OpIsNan", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "x", OperandQuantifier.Default))), - 157 to Instruction("OpIsInf", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "x", OperandQuantifier.Default))), - 158 to Instruction("OpIsFinite", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "x", OperandQuantifier.Default))), - 159 to Instruction("OpIsNormal", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "x", OperandQuantifier.Default))), - 160 to Instruction("OpSignBitSet", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "x", OperandQuantifier.Default))), - 161 to Instruction("OpLessOrGreater", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "x", OperandQuantifier.Default), Operand(IdRef(), "y", OperandQuantifier.Default))), - 162 to Instruction("OpOrdered", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "x", OperandQuantifier.Default), Operand(IdRef(), "y", OperandQuantifier.Default))), - 163 to Instruction("OpUnordered", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "x", OperandQuantifier.Default), Operand(IdRef(), "y", OperandQuantifier.Default))), - 164 to Instruction("OpLogicalEqual", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 165 to Instruction("OpLogicalNotEqual", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 166 to Instruction("OpLogicalOr", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 167 to Instruction("OpLogicalAnd", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 168 to Instruction("OpLogicalNot", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand", OperandQuantifier.Default))), - 169 to Instruction("OpSelect", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Condition", OperandQuantifier.Default), Operand(IdRef(), "Object 1", OperandQuantifier.Default), Operand(IdRef(), "Object 2", OperandQuantifier.Default))), - 170 to Instruction("OpIEqual", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 171 to Instruction("OpINotEqual", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 172 to Instruction("OpUGreaterThan", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 173 to Instruction("OpSGreaterThan", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 174 to Instruction("OpUGreaterThanEqual", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 175 to Instruction("OpSGreaterThanEqual", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 176 to Instruction("OpULessThan", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 177 to Instruction("OpSLessThan", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 178 to Instruction("OpULessThanEqual", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 179 to Instruction("OpSLessThanEqual", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 180 to Instruction("OpFOrdEqual", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 181 to Instruction("OpFUnordEqual", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 182 to Instruction("OpFOrdNotEqual", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 183 to Instruction("OpFUnordNotEqual", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 184 to Instruction("OpFOrdLessThan", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 185 to Instruction("OpFUnordLessThan", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 186 to Instruction("OpFOrdGreaterThan", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 187 to Instruction("OpFUnordGreaterThan", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 188 to Instruction("OpFOrdLessThanEqual", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 189 to Instruction("OpFUnordLessThanEqual", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 190 to Instruction("OpFOrdGreaterThanEqual", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 191 to Instruction("OpFUnordGreaterThanEqual", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 194 to Instruction("OpShiftRightLogical", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Base", OperandQuantifier.Default), Operand(IdRef(), "Shift", OperandQuantifier.Default))), - 195 to Instruction("OpShiftRightArithmetic", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Base", OperandQuantifier.Default), Operand(IdRef(), "Shift", OperandQuantifier.Default))), - 196 to Instruction("OpShiftLeftLogical", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Base", OperandQuantifier.Default), Operand(IdRef(), "Shift", OperandQuantifier.Default))), - 197 to Instruction("OpBitwiseOr", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 198 to Instruction("OpBitwiseXor", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 199 to Instruction("OpBitwiseAnd", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), - 200 to Instruction("OpNot", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand", OperandQuantifier.Default))), - 201 to Instruction("OpBitFieldInsert", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Base", OperandQuantifier.Default), Operand(IdRef(), "Insert", OperandQuantifier.Default), Operand(IdRef(), "Offset", OperandQuantifier.Default), Operand(IdRef(), "Count", OperandQuantifier.Default))), - 202 to Instruction("OpBitFieldSExtract", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Base", OperandQuantifier.Default), Operand(IdRef(), "Offset", OperandQuantifier.Default), Operand(IdRef(), "Count", OperandQuantifier.Default))), - 203 to Instruction("OpBitFieldUExtract", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Base", OperandQuantifier.Default), Operand(IdRef(), "Offset", OperandQuantifier.Default), Operand(IdRef(), "Count", OperandQuantifier.Default))), - 204 to Instruction("OpBitReverse", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Base", OperandQuantifier.Default))), - 205 to Instruction("OpBitCount", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Base", OperandQuantifier.Default))), - 207 to Instruction("OpDPdx", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "P", OperandQuantifier.Default))), - 208 to Instruction("OpDPdy", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "P", OperandQuantifier.Default))), - 209 to Instruction("OpFwidth", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "P", OperandQuantifier.Default))), - 210 to Instruction("OpDPdxFine", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "P", OperandQuantifier.Default))), - 211 to Instruction("OpDPdyFine", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "P", OperandQuantifier.Default))), - 212 to Instruction("OpFwidthFine", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "P", OperandQuantifier.Default))), - 213 to Instruction("OpDPdxCoarse", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "P", OperandQuantifier.Default))), - 214 to Instruction("OpDPdyCoarse", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "P", OperandQuantifier.Default))), - 215 to Instruction("OpFwidthCoarse", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "P", OperandQuantifier.Default))), - 218 to Instruction("OpEmitVertex"), - 219 to Instruction("OpEndPrimitive"), - 220 to Instruction("OpEmitStreamVertex", listOf(Operand(IdRef(), "Stream", OperandQuantifier.Default))), - 221 to Instruction("OpEndStreamPrimitive", listOf(Operand(IdRef(), "Stream", OperandQuantifier.Default))), - 224 to Instruction("OpControlBarrier", listOf(Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(IdScope(), "Memory", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default))), - 225 to Instruction("OpMemoryBarrier", listOf(Operand(IdScope(), "Memory", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default))), - 227 to Instruction("OpAtomicLoad", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default))), - 228 to Instruction("OpAtomicStore", listOf(Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default))), - 229 to Instruction("OpAtomicExchange", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default))), - 230 to Instruction("OpAtomicCompareExchange", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Equal", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Unequal", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default), Operand(IdRef(), "Comparator", OperandQuantifier.Default))), - 231 to Instruction("OpAtomicCompareExchangeWeak", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Equal", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Unequal", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default), Operand(IdRef(), "Comparator", OperandQuantifier.Default))), - 232 to Instruction("OpAtomicIIncrement", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default))), - 233 to Instruction("OpAtomicIDecrement", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default))), - 234 to Instruction("OpAtomicIAdd", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default))), - 235 to Instruction("OpAtomicISub", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default))), - 236 to Instruction("OpAtomicSMin", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default))), - 237 to Instruction("OpAtomicUMin", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default))), - 238 to Instruction("OpAtomicSMax", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default))), - 239 to Instruction("OpAtomicUMax", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default))), - 240 to Instruction("OpAtomicAnd", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default))), - 241 to Instruction("OpAtomicOr", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default))), - 242 to Instruction("OpAtomicXor", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default))), - 245 to Instruction("OpPhi", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(PairIdRefIdRef(), "Variable, Parent, ...", OperandQuantifier.Varying))), - 246 to Instruction("OpLoopMerge", listOf(Operand(IdRef(), "Merge Block", OperandQuantifier.Default), Operand(IdRef(), "Continue Target", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Default))), - 247 to Instruction("OpSelectionMerge", listOf(Operand(IdRef(), "Merge Block", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Default))), - 248 to Instruction("OpLabel", listOf(Operand(IdResult(), "", OperandQuantifier.Default))), - 249 to Instruction("OpBranch", listOf(Operand(IdRef(), "Target Label", OperandQuantifier.Default))), - 250 to Instruction("OpBranchConditional", listOf(Operand(IdRef(), "Condition", OperandQuantifier.Default), Operand(IdRef(), "True Label", OperandQuantifier.Default), Operand(IdRef(), "False Label", OperandQuantifier.Default), Operand(LiteralInteger(), "Branch weights", OperandQuantifier.Varying))), - 251 to Instruction("OpSwitch", listOf(Operand(IdRef(), "Selector", OperandQuantifier.Default), Operand(IdRef(), "Default", OperandQuantifier.Default), Operand(PairLiteralIntegerIdRef(), "Target", OperandQuantifier.Varying))), - 252 to Instruction("OpKill"), - 253 to Instruction("OpReturn"), - 254 to Instruction("OpReturnValue", listOf(Operand(IdRef(), "Value", OperandQuantifier.Default))), - 255 to Instruction("OpUnreachable"), - 256 to Instruction("OpLifetimeStart", listOf(Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(LiteralInteger(), "Size", OperandQuantifier.Default))), - 257 to Instruction("OpLifetimeStop", listOf(Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(LiteralInteger(), "Size", OperandQuantifier.Default))), - 259 to Instruction("OpGroupAsyncCopy", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(IdRef(), "Destination", OperandQuantifier.Default), Operand(IdRef(), "Source", OperandQuantifier.Default), Operand(IdRef(), "Num Elements", OperandQuantifier.Default), Operand(IdRef(), "Stride", OperandQuantifier.Default), Operand(IdRef(), "Event", OperandQuantifier.Default))), - 260 to Instruction("OpGroupWaitEvents", listOf(Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(IdRef(), "Num Events", OperandQuantifier.Default), Operand(IdRef(), "Events List", OperandQuantifier.Default))), - 261 to Instruction("OpGroupAll", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(IdRef(), "Predicate", OperandQuantifier.Default))), - 262 to Instruction("OpGroupAny", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(IdRef(), "Predicate", OperandQuantifier.Default))), - 263 to Instruction("OpGroupBroadcast", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default), Operand(IdRef(), "LocalId", OperandQuantifier.Default))), - 264 to Instruction("OpGroupIAdd", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(EnumType(), "Operation", OperandQuantifier.Default), Operand(IdRef(), "X", OperandQuantifier.Default))), - 265 to Instruction("OpGroupFAdd", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(EnumType(), "Operation", OperandQuantifier.Default), Operand(IdRef(), "X", OperandQuantifier.Default))), - 266 to Instruction("OpGroupFMin", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(EnumType(), "Operation", OperandQuantifier.Default), Operand(IdRef(), "X", OperandQuantifier.Default))), - 267 to Instruction("OpGroupUMin", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(EnumType(), "Operation", OperandQuantifier.Default), Operand(IdRef(), "X", OperandQuantifier.Default))), - 268 to Instruction("OpGroupSMin", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(EnumType(), "Operation", OperandQuantifier.Default), Operand(IdRef(), "X", OperandQuantifier.Default))), - 269 to Instruction("OpGroupFMax", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(EnumType(), "Operation", OperandQuantifier.Default), Operand(IdRef(), "X", OperandQuantifier.Default))), - 270 to Instruction("OpGroupUMax", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(EnumType(), "Operation", OperandQuantifier.Default), Operand(IdRef(), "X", OperandQuantifier.Default))), - 271 to Instruction("OpGroupSMax", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(EnumType(), "Operation", OperandQuantifier.Default), Operand(IdRef(), "X", OperandQuantifier.Default))), - 274 to Instruction("OpReadPipe", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pipe", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdRef(), "Packet Size", OperandQuantifier.Default), Operand(IdRef(), "Packet Alignment", OperandQuantifier.Default))), - 275 to Instruction("OpWritePipe", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pipe", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdRef(), "Packet Size", OperandQuantifier.Default), Operand(IdRef(), "Packet Alignment", OperandQuantifier.Default))), - 276 to Instruction("OpReservedReadPipe", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pipe", OperandQuantifier.Default), Operand(IdRef(), "Reserve Id", OperandQuantifier.Default), Operand(IdRef(), "Index", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdRef(), "Packet Size", OperandQuantifier.Default), Operand(IdRef(), "Packet Alignment", OperandQuantifier.Default))), - 277 to Instruction("OpReservedWritePipe", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pipe", OperandQuantifier.Default), Operand(IdRef(), "Reserve Id", OperandQuantifier.Default), Operand(IdRef(), "Index", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdRef(), "Packet Size", OperandQuantifier.Default), Operand(IdRef(), "Packet Alignment", OperandQuantifier.Default))), - 278 to Instruction("OpReserveReadPipePackets", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pipe", OperandQuantifier.Default), Operand(IdRef(), "Num Packets", OperandQuantifier.Default), Operand(IdRef(), "Packet Size", OperandQuantifier.Default), Operand(IdRef(), "Packet Alignment", OperandQuantifier.Default))), - 279 to Instruction("OpReserveWritePipePackets", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pipe", OperandQuantifier.Default), Operand(IdRef(), "Num Packets", OperandQuantifier.Default), Operand(IdRef(), "Packet Size", OperandQuantifier.Default), Operand(IdRef(), "Packet Alignment", OperandQuantifier.Default))), - 280 to Instruction("OpCommitReadPipe", listOf(Operand(IdRef(), "Pipe", OperandQuantifier.Default), Operand(IdRef(), "Reserve Id", OperandQuantifier.Default), Operand(IdRef(), "Packet Size", OperandQuantifier.Default), Operand(IdRef(), "Packet Alignment", OperandQuantifier.Default))), - 281 to Instruction("OpCommitWritePipe", listOf(Operand(IdRef(), "Pipe", OperandQuantifier.Default), Operand(IdRef(), "Reserve Id", OperandQuantifier.Default), Operand(IdRef(), "Packet Size", OperandQuantifier.Default), Operand(IdRef(), "Packet Alignment", OperandQuantifier.Default))), - 282 to Instruction("OpIsValidReserveId", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Reserve Id", OperandQuantifier.Default))), - 283 to Instruction("OpGetNumPipePackets", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pipe", OperandQuantifier.Default), Operand(IdRef(), "Packet Size", OperandQuantifier.Default), Operand(IdRef(), "Packet Alignment", OperandQuantifier.Default))), - 284 to Instruction("OpGetMaxPipePackets", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pipe", OperandQuantifier.Default), Operand(IdRef(), "Packet Size", OperandQuantifier.Default), Operand(IdRef(), "Packet Alignment", OperandQuantifier.Default))), - 285 to Instruction("OpGroupReserveReadPipePackets", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(IdRef(), "Pipe", OperandQuantifier.Default), Operand(IdRef(), "Num Packets", OperandQuantifier.Default), Operand(IdRef(), "Packet Size", OperandQuantifier.Default), Operand(IdRef(), "Packet Alignment", OperandQuantifier.Default))), - 286 to Instruction("OpGroupReserveWritePipePackets", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(IdRef(), "Pipe", OperandQuantifier.Default), Operand(IdRef(), "Num Packets", OperandQuantifier.Default), Operand(IdRef(), "Packet Size", OperandQuantifier.Default), Operand(IdRef(), "Packet Alignment", OperandQuantifier.Default))), - 287 to Instruction("OpGroupCommitReadPipe", listOf(Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(IdRef(), "Pipe", OperandQuantifier.Default), Operand(IdRef(), "Reserve Id", OperandQuantifier.Default), Operand(IdRef(), "Packet Size", OperandQuantifier.Default), Operand(IdRef(), "Packet Alignment", OperandQuantifier.Default))), - 288 to Instruction("OpGroupCommitWritePipe", listOf(Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(IdRef(), "Pipe", OperandQuantifier.Default), Operand(IdRef(), "Reserve Id", OperandQuantifier.Default), Operand(IdRef(), "Packet Size", OperandQuantifier.Default), Operand(IdRef(), "Packet Alignment", OperandQuantifier.Default))), - 291 to Instruction("OpEnqueueMarker", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Queue", OperandQuantifier.Default), Operand(IdRef(), "Num Events", OperandQuantifier.Default), Operand(IdRef(), "Wait Events", OperandQuantifier.Default), Operand(IdRef(), "Ret Event", OperandQuantifier.Default))), - 292 to Instruction("OpEnqueueKernel", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Queue", OperandQuantifier.Default), Operand(IdRef(), "Flags", OperandQuantifier.Default), Operand(IdRef(), "ND Range", OperandQuantifier.Default), Operand(IdRef(), "Num Events", OperandQuantifier.Default), Operand(IdRef(), "Wait Events", OperandQuantifier.Default), Operand(IdRef(), "Ret Event", OperandQuantifier.Default), Operand(IdRef(), "Invoke", OperandQuantifier.Default), Operand(IdRef(), "Param", OperandQuantifier.Default), Operand(IdRef(), "Param Size", OperandQuantifier.Default), Operand(IdRef(), "Param Align", OperandQuantifier.Default), Operand(IdRef(), "Local Size", OperandQuantifier.Varying))), - 293 to Instruction("OpGetKernelNDrangeSubGroupCount", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "ND Range", OperandQuantifier.Default), Operand(IdRef(), "Invoke", OperandQuantifier.Default), Operand(IdRef(), "Param", OperandQuantifier.Default), Operand(IdRef(), "Param Size", OperandQuantifier.Default), Operand(IdRef(), "Param Align", OperandQuantifier.Default))), - 294 to Instruction("OpGetKernelNDrangeMaxSubGroupSize", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "ND Range", OperandQuantifier.Default), Operand(IdRef(), "Invoke", OperandQuantifier.Default), Operand(IdRef(), "Param", OperandQuantifier.Default), Operand(IdRef(), "Param Size", OperandQuantifier.Default), Operand(IdRef(), "Param Align", OperandQuantifier.Default))), - 295 to Instruction("OpGetKernelWorkGroupSize", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Invoke", OperandQuantifier.Default), Operand(IdRef(), "Param", OperandQuantifier.Default), Operand(IdRef(), "Param Size", OperandQuantifier.Default), Operand(IdRef(), "Param Align", OperandQuantifier.Default))), - 296 to Instruction("OpGetKernelPreferredWorkGroupSizeMultiple", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Invoke", OperandQuantifier.Default), Operand(IdRef(), "Param", OperandQuantifier.Default), Operand(IdRef(), "Param Size", OperandQuantifier.Default), Operand(IdRef(), "Param Align", OperandQuantifier.Default))), - 297 to Instruction("OpRetainEvent", listOf(Operand(IdRef(), "Event", OperandQuantifier.Default))), - 298 to Instruction("OpReleaseEvent", listOf(Operand(IdRef(), "Event", OperandQuantifier.Default))), - 299 to Instruction("OpCreateUserEvent", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default))), - 300 to Instruction("OpIsValidEvent", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Event", OperandQuantifier.Default))), - 301 to Instruction("OpSetUserEventStatus", listOf(Operand(IdRef(), "Event", OperandQuantifier.Default), Operand(IdRef(), "Status", OperandQuantifier.Default))), - 302 to Instruction("OpCaptureEventProfilingInfo", listOf(Operand(IdRef(), "Event", OperandQuantifier.Default), Operand(IdRef(), "Profiling Info", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default))), - 303 to Instruction("OpGetDefaultQueue", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default))), - 304 to Instruction("OpBuildNDRange", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "GlobalWorkSize", OperandQuantifier.Default), Operand(IdRef(), "LocalWorkSize", OperandQuantifier.Default), Operand(IdRef(), "GlobalWorkOffset", OperandQuantifier.Default))), - 305 to Instruction("OpImageSparseSampleImplicitLod", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Optional))), - 306 to Instruction("OpImageSparseSampleExplicitLod", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Default))), - 307 to Instruction("OpImageSparseSampleDrefImplicitLod", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(IdRef(), "D~ref~", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Optional))), - 308 to Instruction("OpImageSparseSampleDrefExplicitLod", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(IdRef(), "D~ref~", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Default))), - 309 to Instruction("OpImageSparseSampleProjImplicitLod", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Optional))), - 310 to Instruction("OpImageSparseSampleProjExplicitLod", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Default))), - 311 to Instruction("OpImageSparseSampleProjDrefImplicitLod", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(IdRef(), "D~ref~", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Optional))), - 312 to Instruction("OpImageSparseSampleProjDrefExplicitLod", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(IdRef(), "D~ref~", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Default))), - 313 to Instruction("OpImageSparseFetch", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Optional))), - 314 to Instruction("OpImageSparseGather", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(IdRef(), "Component", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Optional))), - 315 to Instruction("OpImageSparseDrefGather", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(IdRef(), "D~ref~", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Optional))), - 316 to Instruction("OpImageSparseTexelsResident", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Resident Code", OperandQuantifier.Default))), - 317 to Instruction("OpNoLine"), - 318 to Instruction("OpAtomicFlagTestAndSet", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default))), - 319 to Instruction("OpAtomicFlagClear", listOf(Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default))), - 320 to Instruction("OpImageSparseRead", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Optional))), - 321 to Instruction("OpSizeOf", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default))), - 322 to Instruction("OpTypePipeStorage", listOf(Operand(IdResult(), "", OperandQuantifier.Default))), - 323 to Instruction("OpConstantPipeStorage", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(LiteralInteger(), "Packet Size", OperandQuantifier.Default), Operand(LiteralInteger(), "Packet Alignment", OperandQuantifier.Default), Operand(LiteralInteger(), "Capacity", OperandQuantifier.Default))), - 324 to Instruction("OpCreatePipeFromPipeStorage", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pipe Storage", OperandQuantifier.Default))), - 325 to Instruction("OpGetKernelLocalSizeForSubgroupCount", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Subgroup Count", OperandQuantifier.Default), Operand(IdRef(), "Invoke", OperandQuantifier.Default), Operand(IdRef(), "Param", OperandQuantifier.Default), Operand(IdRef(), "Param Size", OperandQuantifier.Default), Operand(IdRef(), "Param Align", OperandQuantifier.Default))), - 326 to Instruction("OpGetKernelMaxNumSubgroups", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Invoke", OperandQuantifier.Default), Operand(IdRef(), "Param", OperandQuantifier.Default), Operand(IdRef(), "Param Size", OperandQuantifier.Default), Operand(IdRef(), "Param Align", OperandQuantifier.Default))), - 327 to Instruction("OpTypeNamedBarrier", listOf(Operand(IdResult(), "", OperandQuantifier.Default))), - 328 to Instruction("OpNamedBarrierInitialize", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Subgroup Count", OperandQuantifier.Default))), - 329 to Instruction("OpMemoryNamedBarrier", listOf(Operand(IdRef(), "Named Barrier", OperandQuantifier.Default), Operand(IdScope(), "Memory", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default))), - 330 to Instruction("OpModuleProcessed", listOf(Operand(LiteralString(), "Process", OperandQuantifier.Default))), - 331 to Instruction("OpExecutionModeId", listOf(Operand(IdRef(), "Entry Point", OperandQuantifier.Default), Operand(EnumType(), "Mode", OperandQuantifier.Default))), - 332 to Instruction("OpDecorateId", listOf(Operand(IdRef(), "Target", OperandQuantifier.Default), Operand(EnumType(), "", OperandQuantifier.Default))), - 4421 to Instruction("OpSubgroupBallotKHR", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Predicate", OperandQuantifier.Default))), - 4422 to Instruction("OpSubgroupFirstInvocationKHR", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default))), - 4428 to Instruction("OpSubgroupAllKHR", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Predicate", OperandQuantifier.Default))), - 4429 to Instruction("OpSubgroupAnyKHR", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Predicate", OperandQuantifier.Default))), - 4430 to Instruction("OpSubgroupAllEqualKHR", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Predicate", OperandQuantifier.Default))), - 4432 to Instruction("OpSubgroupReadInvocationKHR", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default), Operand(IdRef(), "Index", OperandQuantifier.Default))), - 5000 to Instruction("OpGroupIAddNonUniformAMD", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(EnumType(), "Operation", OperandQuantifier.Default), Operand(IdRef(), "X", OperandQuantifier.Default))), - 5001 to Instruction("OpGroupFAddNonUniformAMD", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(EnumType(), "Operation", OperandQuantifier.Default), Operand(IdRef(), "X", OperandQuantifier.Default))), - 5002 to Instruction("OpGroupFMinNonUniformAMD", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(EnumType(), "Operation", OperandQuantifier.Default), Operand(IdRef(), "X", OperandQuantifier.Default))), - 5003 to Instruction("OpGroupUMinNonUniformAMD", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(EnumType(), "Operation", OperandQuantifier.Default), Operand(IdRef(), "X", OperandQuantifier.Default))), - 5004 to Instruction("OpGroupSMinNonUniformAMD", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(EnumType(), "Operation", OperandQuantifier.Default), Operand(IdRef(), "X", OperandQuantifier.Default))), - 5005 to Instruction("OpGroupFMaxNonUniformAMD", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(EnumType(), "Operation", OperandQuantifier.Default), Operand(IdRef(), "X", OperandQuantifier.Default))), - 5006 to Instruction("OpGroupUMaxNonUniformAMD", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(EnumType(), "Operation", OperandQuantifier.Default), Operand(IdRef(), "X", OperandQuantifier.Default))), - 5007 to Instruction("OpGroupSMaxNonUniformAMD", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(EnumType(), "Operation", OperandQuantifier.Default), Operand(IdRef(), "X", OperandQuantifier.Default))), - 5011 to Instruction("OpFragmentMaskFetchAMD", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default))), - 5012 to Instruction("OpFragmentFetchAMD", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(IdRef(), "Fragment Index", OperandQuantifier.Default))), - 5571 to Instruction("OpSubgroupShuffleINTEL", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Data", OperandQuantifier.Default), Operand(IdRef(), "InvocationId", OperandQuantifier.Default))), - 5572 to Instruction("OpSubgroupShuffleDownINTEL", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Current", OperandQuantifier.Default), Operand(IdRef(), "Next", OperandQuantifier.Default), Operand(IdRef(), "Delta", OperandQuantifier.Default))), - 5573 to Instruction("OpSubgroupShuffleUpINTEL", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Previous", OperandQuantifier.Default), Operand(IdRef(), "Current", OperandQuantifier.Default), Operand(IdRef(), "Delta", OperandQuantifier.Default))), - 5574 to Instruction("OpSubgroupShuffleXorINTEL", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Data", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default))), - 5575 to Instruction("OpSubgroupBlockReadINTEL", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Ptr", OperandQuantifier.Default))), - 5576 to Instruction("OpSubgroupBlockWriteINTEL", listOf(Operand(IdRef(), "Ptr", OperandQuantifier.Default), Operand(IdRef(), "Data", OperandQuantifier.Default))), - 5577 to Instruction("OpSubgroupImageBlockReadINTEL", listOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default))), - 5578 to Instruction("OpSubgroupImageBlockWriteINTEL", listOf(Operand(IdRef(), "Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(IdRef(), "Data", OperandQuantifier.Default))), - ) - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/export/spirv/Meta.kt b/src/main/kotlin/io/github/deficuet/unitykt/export/spirv/Meta.kt deleted file mode 100644 index 9665d57b..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/export/spirv/Meta.kt +++ /dev/null @@ -1,30 +0,0 @@ -package io.github.deficuet.unitykt.export.spirv - -internal class Meta private constructor() { - enum class Tools(val id: Int, val vendor: String, val toolName: String = "") { - Khronos0(0, "Khronos"), - LunarG(1, "LunarG"), - Valve(2, "Valve"), - Codeplay(3, "Codeplay"), - NVIDIA(4, "NVIDIA"), - ARM(5, "ARM"), - Khronos1(6, "Khronos", "LLVM/SPIR-V Translator"), - Khronos2(7, "Khronos", "SPIR-V Tools Assembler"), - Khronos3(8, "Khronos", "Glslang Reference Front End"), - Qualcomm(9, "Qualcomm"), - AMD(10, "AMD"), - Intel(11, "Intel"), - Imagination(12, "Imagination"), - Google0(13, "Google", "Shaderc over Glslang"), - Google1(14, "Google", "spiregg"), - Google2(15, "Google", "rspirv"), - X_LEGEND(16, "X_LEGEND", "Mesa-IR/SPIR-V Translator"), - Khronos(17, "Khronos", "SPIR-V Tools Linker"); - - companion object { - fun of(value: Int): Tools? { - return values().firstOrNull { it.id == value } - } - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/export/spirv/NumericalEnum.kt b/src/main/kotlin/io/github/deficuet/unitykt/export/spirv/NumericalEnum.kt deleted file mode 100644 index 8471e007..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/export/spirv/NumericalEnum.kt +++ /dev/null @@ -1,12 +0,0 @@ -package io.github.deficuet.unitykt.export.spirv - -internal interface NumericalEnum> { - val id: T -} - -internal abstract class NumericalEnumCompanion, C: Comparable> - -internal inline fun , N: Comparable> NumericalEnumCompanion.of(value: N): E { - val values = enumValues() - return values.firstOrNull { (it as NumericalEnum<*>).id == value } ?: values.first() -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/export/spirv/OperandType.kt b/src/main/kotlin/io/github/deficuet/unitykt/export/spirv/OperandType.kt deleted file mode 100644 index 28821c35..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/export/spirv/OperandType.kt +++ /dev/null @@ -1,138 +0,0 @@ -package io.github.deficuet.unitykt.export.spirv - -import io.github.deficuet.unitykt.util.Reference - -internal open class OperandType { - open fun readValue(words: Array, index: Int, value: Reference): Int { - value.value = this::class - return 1 - } -} - -internal open class Literal: OperandType() - -internal open class LiteralNumber: Literal() - -internal class LiteralInteger: LiteralNumber() { - override fun readValue(words: Array, index: Int, value: Reference): Int { - value.value = words[index] - return 1 - } -} - -internal class LiteralString: Literal() { - override fun readValue(words: Array, index: Int, value: Reference): Int { - var wordsUsed = 1; var bytesUsed = 0 - val bytes = ByteArray((words.size - index) * 4) - readWord@ - for (i in index until words.size) { - val word = words[i] - for (j in 0..3) { - val b = word.shr(j * 8).and(0xFFu).toByte() - if (b == 0.toByte()) break@readWord - else bytes[bytesUsed++] = b - } - wordsUsed++ - } - value.value = bytes.decodeToString(0, bytesUsed) - return wordsUsed - } -} - -internal class LiteralContextDependentNumber: Literal() - -internal class LiteralExtInstInteger: Literal() { - override fun readValue(words: Array, index: Int, value: Reference): Int { - value.value = words[index] - return 1 - } -} - -internal class LiteralSpecConstantOpInteger: Literal() { - override fun readValue(words: Array, index: Int, value: Reference): Int { - val result = mutableListOf() - for (i in index until words.size) { - result.add(ObjectReference(words[i])) - } - value.value = result - return words.size - index - } -} - -internal class IdScope: OperandType() { - override fun readValue(words: Array, index: Int, value: Reference): Int { - value.value = Scope.of(words[index]) - return 1 - } -} - -internal class IdMemorySemantics: OperandType() { - override fun readValue(words: Array, index: Int, value: Reference): Int { - value.value = MemorySemantics.of(words[index].toLong()) - return 1 - } -} - -internal open class IdType: OperandType() { - override fun readValue(words: Array, index: Int, value: Reference): Int { - value.value = words[index] - return 1 - } -} - -internal class IdResult: IdType() { - override fun readValue(words: Array, index: Int, value: Reference): Int { - value.value = ObjectReference(words[index]) - return 1 - } -} - -internal class IdRef: IdType() { - override fun readValue(words: Array, index: Int, value: Reference): Int { - value.value = ObjectReference(words[index]) - return 1 - } -} - -internal class IdResultType: IdType() - -//internal abstract class Parameter { -// abstract val operandTypes: List -// -// companion object { -// operator fun invoke(types: List): Parameter { -// return object : Parameter() { override val operandTypes = types } -// } -// } -//} - -internal class PairIdRefIdRef: OperandType() { - override fun readValue(words: Array, index: Int, value: Reference): Int { - value.value = Pair(ObjectReference(words[index]), ObjectReference(words[index + 1])) - return 2 - } -} - -internal class PairIdRefLiteralInteger: OperandType() { - override fun readValue(words: Array, index: Int, value: Reference): Int { - value.value = Pair(ObjectReference(words[index]), words[index + 1]) - return 2 - } -} - -internal class PairLiteralIntegerIdRef: OperandType() { - override fun readValue(words: Array, index: Int, value: Reference): Int { - value.value = Pair(words[index], ObjectReference(words[index + 1])) - return 2 - } -} - -internal class Parameter(vararg types: OperandType) { - val operandTypes = types -} - -internal open class ParameterFactory { - open fun createParameter(value: UInt): Parameter? { - return null - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/export/spirv/Version.kt b/src/main/kotlin/io/github/deficuet/unitykt/export/spirv/Version.kt deleted file mode 100644 index 01d318ba..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/export/spirv/Version.kt +++ /dev/null @@ -1,17 +0,0 @@ -package io.github.deficuet.unitykt.export.spirv - -internal data class Version( - val major: Int = -1, - val minor: Int = -1, - val build: Int = -1, - val revision: Int = -1 -) { - override fun toString(): String { - return StringBuilder().apply { - if (major != -1) append(major) - if (minor != -1) append(".$minor") - if (build != -1) append(".$build") - if (revision != -1) append(".$revision") - }.toString() - } -} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/file/AssetBundleFile.kt b/src/main/kotlin/io/github/deficuet/unitykt/file/AssetBundleFile.kt deleted file mode 100644 index 426ac693..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/file/AssetBundleFile.kt +++ /dev/null @@ -1,70 +0,0 @@ -package io.github.deficuet.unitykt.file - -import io.github.deficuet.unitykt.ImportContext -import io.github.deficuet.unitykt.util.EndianBinaryReader -import io.github.deficuet.unitykt.util.EndianByteArrayReader -import io.github.deficuet.unitykt.util.FileType -import kotlin.collections.set - -data class DirectoryInfoNode( - val path: String, - val offset: Long, - val size: Long, - val flag: UInt = 0u -) - -abstract class RawAssetFile { - abstract val bundleParent: AssetBundleFile - abstract val name: String - open val root: ImportContext - get() = if (bundleParent is ImportContext) bundleParent as ImportContext else bundleParent.root - - companion object { - val resourceExt = arrayOf(".resS", ".resource", ".config", ".xml", ".dat") - } -} - -abstract class AssetBundleFile: RawAssetFile() { - abstract val files: Map - - protected fun readFiles( - reader: EndianBinaryReader, directoryInfo: List - ): Map { - val fileMap = mutableMapOf() - for (node in directoryInfo) { - reader.position = node.offset - val nodeReader = EndianByteArrayReader( - reader.read(node.size.toInt()), - baseOffset = reader.baseOffset + node.offset - ) - val nodeFile = when (nodeReader.fileType) { - FileType.BUNDLE -> { - BundleFile(nodeReader, this, node.path).also { - root.manager.assetBundles[node.path] = it - } - } - FileType.WEB -> { - WebFile(nodeReader, this, node.path).also { - root.manager.assetBundles[node.path] = it - } - } - FileType.ASSETS -> { - if (resourceExt.none { node.path.endsWith(it) }) { - SerializedFile(nodeReader, this, node.path).also { - root.manager.assetFiles[node.path] = it - } - } else { - ResourceFile(nodeReader, this, node.path).also { - root.manager.resourceFiles[node.path] = it - } - } - } - FileType.RESOURCE -> ResourceFile(nodeReader, this, node.path).also { - root.manager.resourceFiles[node.path] = it - } - } - fileMap[node.path] = nodeFile - } - return fileMap - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/file/BundleFile.kt b/src/main/kotlin/io/github/deficuet/unitykt/file/BundleFile.kt deleted file mode 100644 index cf3e9915..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/file/BundleFile.kt +++ /dev/null @@ -1,163 +0,0 @@ -package io.github.deficuet.unitykt.file - -import io.github.deficuet.unitykt.util.* - -internal class ArchiveFlags { - companion object { - const val CompressionTypeMask = 0x3Fu - const val BlocksAndDirectoryInfoCombined = 0x40u - const val BlocksInfoAtTheEnd = 0x80u - const val OldWebPluginCompatibility = 0x100u - const val BlockInfoNeedPaddingAtStart = 0x200u - } -} - -class BundleFile( - private val reader: EndianBinaryReader, - override val bundleParent: AssetBundleFile, - override val name: String -): AssetBundleFile() { - data class Block( - val compressedSize: UInt, - val uncompressedSize: UInt, - val flags: UShort - ) - - //Header - private val hSignature: String = reader.readStringUntilNull() - private val hVersion: UInt = reader.readUInt() - - private val blocksInfo = mutableListOf() - private val directoryInfo = mutableListOf() - - override val files: Map - - init { - reader.readStringUntilNull() //hUnityVersion - reader.readStringUntilNull() //hUnityRevision - val filesReader = when (hSignature) { - "UnityArchive" -> throw UnsupportedFormatException("Unsupported file type UnityArchive") - "UnityWeb", "UnityRaw" -> { - if (hVersion == 6u) readFS() - else readWebRaw() - } - "UnityFS" -> readFS() - else -> throw UnsupportedFormatException("Unknown Bundle Signature") - } - files = readFiles(filesReader, directoryInfo) - filesReader.close() - reader.close() - } - - private fun readWebRaw(): EndianBinaryReader { - val isCompressed = hSignature == "UnityWeb" - if (hVersion >= 4u) { - reader += 20 //hash(16), crc: UInt - } - reader += 4 //minStreamedByte: UInt - val hSize = reader.readUInt().toLong() - reader += 4 //levelsBeforeStreaming: UInt - val levelCount = reader.readInt() - reader += 4 * 2 * (levelCount - 1) - blocksInfo.add( - Block( - reader.readUInt(), reader.readUInt(), 0u - ) - ) - if (hVersion >= 2u) { - reader += 4 //completeFileSize: UInt - } - if (hVersion >= 3u) { - reader += 4 //fileInfoHeaderSize: UInt - } - reader.position = hSize - val uncompressedBytes = with(reader.read(blocksInfo[0].compressedSize.toInt())) { - if (isCompressed) { - CompressUtils.lzmaDecompress(this) - } else this - } - val blocksReader = EndianByteArrayReader( - uncompressedBytes, - baseOffset = hSize - ) - val nodesCount = blocksReader.readInt() - for (i in 0 until nodesCount) { - directoryInfo.add( - with(blocksReader) { - DirectoryInfoNode( - readStringUntilNull(), - readUInt().toLong(), - readUInt().toLong() - ) - } - ) - } - return blocksReader - } - - private fun readFS(): EndianBinaryReader { - reader += 8 //header.size: Long - val hCompressedBlockSize = reader.readUInt() - val uncompressedBlockSize = reader.readUInt() - val hFlags = reader.readUInt() - if (hSignature != "UnityFS") reader += 1 - if (hVersion >= 7u) reader.alignStream(16) - val blockOffset = reader.position - var blocksInfoBytes: ByteArray - if (hFlags.and(ArchiveFlags.BlocksInfoAtTheEnd) != 0u) { - blocksInfoBytes = reader.withMark { - position = length - hCompressedBlockSize.toLong() - read(hCompressedBlockSize.toInt()) - } - } else { - blocksInfoBytes = reader.read(hCompressedBlockSize.toInt()) - } - when (hFlags.and(ArchiveFlags.CompressionTypeMask)) { - 1u -> blocksInfoBytes = CompressUtils.lzmaDecompress(blocksInfoBytes) - 2u, 3u -> blocksInfoBytes = CompressUtils.lz4Decompress(blocksInfoBytes, uncompressedBlockSize.toInt()) - } - val blocksInfoReader = EndianByteArrayReader(blocksInfoBytes, baseOffset = blockOffset) - blocksInfoReader += 16 //uncompressedDataHash - val blocksInfoCount = blocksInfoReader.readInt() - for (i in 0 until blocksInfoCount) { - blocksInfo.add( - Block( - uncompressedSize = blocksInfoReader.readUInt(), - compressedSize = blocksInfoReader.readUInt(), - flags = blocksInfoReader.readUShort() - ) - ) - } - val nodesCount = blocksInfoReader.readInt() - with(blocksInfoReader) { - for (j in 0 until nodesCount) { - directoryInfo.add( - DirectoryInfoNode( - offset = readLong(), - size = readLong(), - flag = readUInt(), - path = readStringUntilNull() - ) - ) - } - } - if (hFlags.and(ArchiveFlags.BlockInfoNeedPaddingAtStart) != 0u) { - reader.alignStream(16) - } - return EndianByteArrayReader( - manualOffset = blocksInfoReader.realOffset - ) { - blocksInfo.map { block -> - when (block.flags.and(ArchiveFlags.CompressionTypeMask.toUShort())) { - 1.toUShort() -> CompressUtils.lzmaDecompress( - reader.read(block.compressedSize.toInt()) - ) - 2.toUShort(), 3.toUShort() -> CompressUtils.lz4Decompress( - reader.read(block.compressedSize.toInt()), block.uncompressedSize.toInt() - ) - else -> reader.read(block.uncompressedSize.toInt()) - } - }.sum() - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/file/ResourceFile.kt b/src/main/kotlin/io/github/deficuet/unitykt/file/ResourceFile.kt deleted file mode 100644 index bdcf315e..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/file/ResourceFile.kt +++ /dev/null @@ -1,13 +0,0 @@ -package io.github.deficuet.unitykt.file - -import io.github.deficuet.unitykt.util.EndianBinaryReader - -class ResourceFile( - internal val reader: EndianBinaryReader, - override val bundleParent: AssetBundleFile, - override val name: String -): RawAssetFile() { - fun read(offset: Long, size: Int): ByteArray { - return with(reader) { position = offset; read(size) } - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/file/SerializedFile.kt b/src/main/kotlin/io/github/deficuet/unitykt/file/SerializedFile.kt deleted file mode 100644 index d09146b4..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/file/SerializedFile.kt +++ /dev/null @@ -1,520 +0,0 @@ -package io.github.deficuet.unitykt.file - -import io.github.deficuet.unitykt.data.* -import io.github.deficuet.unitykt.util.EndianBinaryReader -import io.github.deficuet.unitykt.util.EndianByteArrayReader -import java.io.File -import java.nio.ByteOrder - -class FormatVersion private constructor() { - companion object { -// const val Unsupported = 1u - const val Unknown_2 = 2u - const val Unknown_3 = 3u - const val Unknown_5 = 5u - const val Unknown_6 = 6u - const val Unknown_7 = 7u - const val Unknown_8 = 8u - const val Unknown_9 = 9u - const val Unknown_10 = 10u - const val HasScriptTypeIndex = 11u - const val Unknown_12 = 12u - const val HasTypeTreeHashes = 13u - const val Unknown_14 = 14u - const val SupportsStrippedObject = 15u - const val RefactoredClassId = 16u - const val RefactorTypeData = 17u -// const val RefactorShareableTypeTreeData = 18u - const val TypeTreeNodeWithTypeFlags = 19u - const val SupportsRefObject = 20u - const val StoresTypeDependencies = 21u - const val LargeFilesSupport = 22u - } -} - -class BuildType(private val type: String) { -// val isAlpha get() = type == "a" - val isPatch get() = type == "p" -} - -@Suppress("EnumEntryName") -enum class BuildTarget(val id: Int) { - NoTarget(-2), - AnyPlayer(-1), - ValidPlayer(1), - StandaloneOSX(2), - StandaloneOSXPPC(3), - StandaloneOSXIntel(4), - StandaloneWindows(5), - WebPlayer(6), - WebPlayerStreamed(7), - Wii(8), - iOS(9), - PS3(10), - XBOX360(11), - Broadcom(12), - Android(13), - StandaloneGLESEmu(14), - StandaloneGLES20Emu(15), - NaCl(16), - StandaloneLinux(17), - FlashPlayer(18), - StandaloneWindows64(19), - WebGL(20), - WSAPlayer(21), - StandaloneLinux64(24), - StandaloneLinuxUniversal(25), - WP8Player(26), - StandaloneOSXIntel64(27), - BlackBerry(28), - Tizen(29), - PSP2(30), - PS4(31), - PSM(32), - XboxOne(33), - SamsungTV(34), - N3DS(35), - WiiU(36), - tvOS(37), - Switch(38), - Lumin(39), - Stadia(40), - CloudRendering(41), - GameCoreXboxSeries(42), - GameCoreXboxOne(43), - PS5(44), - EmbeddedLinux(45), - QNX(46), - - UnknownPlatform(9999); - - companion object { - fun isDefined(v: Int) = values().any { it.id == v } - } -} - -data class ObjectInfo( - val byteStart: Long, - val byteSize: UInt, - val typeID: Int, - val classID: Int, - val isDestroyed: UShort, - val stripped: UByte, - val mPathID: Long, - val serializedType: SerializedType? -) { - val type = ClassIDType.of(classID) -} - -class SerializedFile( - internal val reader: EndianBinaryReader, - override val bundleParent: AssetBundleFile, - override val name: String -): RawAssetFile() { - data class Header( - val metadataSize: UInt = 0u, - val fileSize: Long = 0, - val version: UInt = 0u, - val dataOffset: Long = 0, - val endian: UByte = 0u - ) - - data class FileIdentifier( - val guid: ByteArray, - val type: Int, - val path: String - ) { - val name: String by lazy { File(path).name } - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (javaClass != other?.javaClass) return false - - other as FileIdentifier - - if (!guid.contentEquals(other.guid)) return false - if (type != other.type) return false - if (path != other.path) return false - - return true - } - - override fun hashCode(): Int { - var result = guid.contentHashCode() - result = 31 * result + type - result = 31 * result + path.hashCode() - return result - } - } - - data class ObjectIdentifier( - val serializedFileIndex: Int, - val identifierInFile: Long - ) - - data class SerializedTypeTreeNodeInternal( - val byteSize: Int, - val index: Int, - val typeFlags: Int, - val version: Int, - val metaFlag: Int, - val level: Int, - val typeStrOffset: UInt, - val nameStrOffset: UInt - ) - - //Header - private var hMetadataSize = reader.readUInt() - private var hFileSize = reader.readUInt().toLong() - private val hVersion = reader.readUInt() - private var hDataOffset = reader.readUInt().toLong() - private val hEndian: UByte -// private val hReserved: ByteArray - - private var unityVersion = "2.5.0.f5" - - private val enableTypeTree: Boolean - private var bigIDEnabled = 0 - private val objectInfoList: List - private val scriptTypes = mutableListOf() - private val refTypes = mutableListOf() - private val userInformation: String - private val types: List - - val header: Header get() = Header(hMetadataSize, hFileSize, hVersion, hDataOffset, hEndian) - var version: IntArray = intArrayOf(0, 0, 0, 0) - private set - var targetPlatform = BuildTarget.UnknownPlatform - private set - var buildType = BuildType("") - private set - val externals: List - val objects: Map - val objectList: Collection get() = objects.values - - init { - if (hVersion >= FormatVersion.Unknown_9) { - hEndian = reader.readByte() - reader += 3 //hReserved = reader.read(3) - } else { - reader.position = hFileSize - hMetadataSize.toLong() - hEndian = reader.readByte() - } - if (hVersion >= FormatVersion.LargeFilesSupport) { - hMetadataSize = reader.readUInt() - hFileSize = reader.readLong() - hDataOffset = reader.readLong() - reader += 8 //unknown - } - if (hEndian == 0u.toUByte()) reader.resetEndian(ByteOrder.LITTLE_ENDIAN) - if (hVersion >= FormatVersion.Unknown_7) { - unityVersion = reader.readStringUntilNull() - buildType = buildTypeRegex.findAll(unityVersion).iterator().let { - BuildType( - if (it.hasNext()) it.next().value - else "" - ) - } - version = versionSplitRegex.split(unityVersion).map { it.toInt() }.toIntArray() - } - if (hVersion >= FormatVersion.Unknown_8) { - val targetPlatformID = reader.readInt() - if (BuildTarget.isDefined(targetPlatformID)) { - targetPlatform = BuildTarget.values().first { it.id == targetPlatformID } - } - } - enableTypeTree = if (hVersion >= FormatVersion.HasTypeTreeHashes) reader.readBool() else true - val typeCount = reader.readInt() - val typesList = mutableListOf() - for (i in 0 until typeCount) { - typesList.add(readSerializedType(false)) - } - types = typesList - if (hVersion in with(FormatVersion) { Unknown_7 until Unknown_14 }) { - bigIDEnabled = reader.readInt() - } - val objectCount = reader.readInt() - val objectInfoList = mutableListOf() - for (j in 0 until objectCount) { - val mPathID = if (bigIDEnabled != 0) { - reader.readLong() - } else if (hVersion < FormatVersion.Unknown_14) { - reader.readInt().toLong() - } else { - reader.alignStream() - reader.readLong() - } - var byteStart = if (hVersion >= FormatVersion.LargeFilesSupport) { - reader.readLong() - } else reader.readUInt().toLong() - byteStart += hDataOffset - val byteSize = reader.readUInt() - val typeID = reader.readInt() - val classID: Int; val serialisedType: SerializedType? - if (hVersion < FormatVersion.RefactoredClassId) { - classID = reader.readUShort().toInt() - serialisedType = types.find { it.classID == typeID } - } else { - with(types[typeID]) { - serialisedType = this - classID = this.classID - } - } - var isDestoryed: UShort = 0u - if (hVersion < FormatVersion.HasScriptTypeIndex) { - isDestoryed = reader.readUShort() - } - if (hVersion in with(FormatVersion) { HasScriptTypeIndex until RefactorTypeData } ) { - serialisedType?.scriptTypeIndex = reader.readShort() - } - var stripped: UByte = 0u - if (hVersion == FormatVersion.SupportsStrippedObject || - hVersion == FormatVersion.RefactoredClassId) { - stripped = reader.readByte() - } - objectInfoList.add( - ObjectInfo( - byteStart, byteSize, typeID, classID, isDestoryed, - stripped, mPathID, serialisedType - ) - ) - } - this.objectInfoList = objectInfoList - if (hVersion >= FormatVersion.HasScriptTypeIndex) { - val scriptCount = reader.readInt() - for (k in 0 until scriptCount) { - scriptTypes.add( - ObjectIdentifier( - serializedFileIndex = reader.readInt(), - identifierInFile = if (hVersion < FormatVersion.Unknown_14) { - reader.readInt().toLong() - } else { - reader.alignStream() - reader.readLong() - } - ) - ) - } - } - val externalsCount = reader.readInt() - val externals = mutableListOf() - for (l in 0 until externalsCount) { - if (hVersion >= FormatVersion.Unknown_6) reader.readStringUntilNull() - var guid = ByteArray(16); var type = 0 - if (hVersion >= FormatVersion.Unknown_5) { - guid = reader.read(16) - type = reader.readInt() - } - externals.add( - FileIdentifier( - guid, type, - reader.readStringUntilNull() - ) - ) - } - this.externals = externals - if (hVersion >= FormatVersion.SupportsRefObject) { - val refTypesCount = reader.readInt() - for (m in 0 until refTypesCount) { - refTypes.add(readSerializedType(true)) - } - } - userInformation = if (hVersion >= FormatVersion.Unknown_5) { - reader.readStringUntilNull() - } else "" - //region readObjects - val objectMap = mutableMapOf() - for (info in objectInfoList) { - val obj = when (info.type) { - ClassIDType.Animation -> Animation(this, info) - ClassIDType.AnimationClip -> AnimationClip(this, info) - ClassIDType.Animator -> Animator(this, info) - ClassIDType.AnimatorController -> AnimatorController(this, info) - ClassIDType.AnimatorOverrideController -> AnimatorOverrideController(this, info) - ClassIDType.AssetBundle -> AssetBundle(this, info) - ClassIDType.AudioClip -> AudioClip(this, info) - ClassIDType.Avatar -> Avatar(this, info) - ClassIDType.Canvas -> Canvas(this, info) - ClassIDType.Font -> Font(this, info) - ClassIDType.GameObject -> GameObject(this, info) - ClassIDType.Material -> Material(this, info) - ClassIDType.Mesh -> Mesh(this, info) - ClassIDType.MeshFilter -> MeshFilter(this, info) - ClassIDType.MeshRenderer -> MeshRenderer(this, info) - ClassIDType.MonoBehaviour -> MonoBehaviour(this, info) - ClassIDType.MonoScript -> MonoScript(this, info) - ClassIDType.MovieTexture -> MovieTexture(this, info) - ClassIDType.PlayerSettings -> PlayerSetting(this, info) - ClassIDType.RectTransform -> RectTransform(this, info) - ClassIDType.Shader -> Shader(this, info) - ClassIDType.SkinnedMeshRenderer -> SkinnedMeshRenderer(this, info) - ClassIDType.Sprite -> Sprite(this, info) - ClassIDType.SpriteAtlas -> SpriteAtlas(this, info) - ClassIDType.TextAsset -> TextAsset(this, info) - ClassIDType.Texture2D -> Texture2D(this, info) - ClassIDType.Transform -> Transform(this, info) - ClassIDType.VideoClip -> VideoClip(this, info) - ClassIDType.ResourceManager -> ResourceManager(this, info) - else -> Object(this, info) - } - objectMap[obj.mPathID] = obj - } - objects = objectMap - root.objectMap.putAll(objects) - objectInfoList.clear() - //endregion - } - - private fun readSerializedType(isRefType: Boolean): SerializedType { - val classID = reader.readInt() - var isStrippedType = false - var scriptTypeIndex: Short = -1 - var scriptID: ByteArray = byteArrayOf() - var oldTypeHash: ByteArray = byteArrayOf() - var typeTree = SerializedType.Tree() - var className = "" - var nameSpace = "" - var asmName = "" - var typeDependencies: IntArray = intArrayOf() - if (hVersion >= FormatVersion.RefactoredClassId) isStrippedType = reader.readBool() - if (hVersion >= FormatVersion.RefactorTypeData) scriptTypeIndex = reader.readShort() - if (hVersion >= FormatVersion.HasTypeTreeHashes) { - if (isRefType && scriptTypeIndex >= 0) scriptID = reader.read(16) - else if ((hVersion < FormatVersion.RefactoredClassId && classID < 0) || - (hVersion >= FormatVersion.RefactoredClassId && classID == 114)) { - scriptID = reader.read(16) - } - oldTypeHash = reader.read(16) - } - if (enableTypeTree) { - typeTree = if (hVersion >= FormatVersion.Unknown_12 || hVersion == FormatVersion.Unknown_10) { - typeTreeBlobRead() - } else { - readTypeTree() - } - } - if (hVersion >= FormatVersion.StoresTypeDependencies) { - if (isRefType) { - className = reader.readStringUntilNull() - nameSpace = reader.readStringUntilNull() - asmName = reader.readStringUntilNull() - } else { - typeDependencies = reader.readNextIntArray() - } - } - return SerializedType( - classID, - isStrippedType, - scriptTypeIndex, - typeTree, - scriptID, - oldTypeHash, - typeDependencies, - className, - nameSpace, - asmName - ) - } - - private fun typeTreeBlobRead(): SerializedType.Tree { - val nodeCount = reader.readInt() - val stringBufferSize = reader.readInt() - val nodeList = mutableListOf() - val nodeListInternal = mutableListOf() - for (i in 0 until nodeCount) { - nodeListInternal.add( - SerializedTypeTreeNodeInternal( - version = reader.readUShort().toInt(), - level = reader.readByte().toInt(), - typeFlags = reader.readByte().toInt(), - typeStrOffset = reader.readUInt(), - nameStrOffset = reader.readUInt(), - byteSize = reader.readInt(), - index = reader.readInt(), - metaFlag = reader.readInt() - ) - ) - if (hVersion >= FormatVersion.TypeTreeNodeWithTypeFlags) { - reader += 8 //refTypeHash: ULong - } - } - val stringBuffer = reader.read(stringBufferSize) - fun EndianBinaryReader.readNodeString(value: UInt): String { - if ((value and 0x80000000u) == 0u) { - position = value.toLong() - return readStringUntilNull() - } - val offset = value and 0x7FFFFFFFu - return commonString[offset] ?: offset.toString() - } - EndianByteArrayReader(stringBuffer).use { - for (node in nodeListInternal) { - nodeList.add( - SerializedType.TreeNode( - node, - type = it.readNodeString(node.typeStrOffset), - name = it.readNodeString(node.nameStrOffset) - ) - ) - } - } - return SerializedType.Tree(nodeList) - } - - private fun readTypeTree(): SerializedType.Tree { - val newTree = SerializedType.Tree() - val levelStack = mutableListOf(mutableListOf(0, 1)) - while (levelStack.isNotEmpty()) { - val (level, count) = levelStack.last() - if (count == 1) levelStack.removeLast() - else levelStack.last()[1] -= 1 - val type = reader.readStringUntilNull() - val name = reader.readStringUntilNull() - val byteSize = reader.readInt() - if (hVersion == FormatVersion.Unknown_2) reader += 4 //variableCount - val index = if (hVersion != FormatVersion.Unknown_3) reader.readInt() else 0 - val typeFlags = reader.readInt() - val version = reader.readInt() - val metaFlag = if (hVersion != FormatVersion.Unknown_3) reader.readInt() else 0 - newTree.nodes.add(SerializedType.TreeNode( - type, name, byteSize, index, typeFlags, version, metaFlag, level - )) - val childrenCount = reader.readInt() - if (childrenCount > 0) levelStack.add(mutableListOf(level + 1, childrenCount)) - } - return newTree - } - - companion object { - private val buildTypeRegex = Regex("""([^\d.])""") - private val versionSplitRegex = Regex("""\D""") - private val commonString = mapOf( - 0u to "AABB", 5u to "AnimationClip", 19u to "AnimationCurve", 34u to "AnimationState", - 49u to "Array", 55u to "Base", 60u to "BitField", 69u to "bitset", 76u to "bool", - 81u to "char", 86u to "ColorRGBA", 96u to "Component", 106u to "data", 111u to "deque", - 117u to "double", 124u to "dynamic_array", 138u to "FastPropertyName", 155u to "first", - 161u to "float", 167u to "Font", 172u to "GameObject", 183u to "Generic Mono", 196u to "GradientNEW", - 208u to "GUID", 213u to "GUIStyle", 222u to "int", 226u to "list", 231u to "long long", - 241u to "map", 245u to "Matrix4x4f", 256u to "MdFour", 263u to "MonoBehaviour", 277u to "MonoScript", - 288u to "m_ByteSize", 299u to "m_Curve", 307u to "m_EditorClassIdentifier", 331u to "m_EditorHideFlags", - 349u to "m_Enabled", 359u to "m_ExtensionPtr", 374u to "m_GameObject", 387u to "m_Index", - 395u to "m_IsArray", 405u to "m_IsStatic", 416u to "m_MetaFlag", 427u to "m_Name", - 434u to "m_ObjectHideFlags", 452u to "m_PrefabInternal", 469u to "m_PrefabParentObject", - 490u to "m_Script", 499u to "m_StaticEditorFlags", 519u to "m_Type", 526u to "m_Version", - 536u to "Object", 543u to "pair", 548u to "PPtr", 564u to "PPtr", - 581u to "PPtr", 596u to "PPtr", 616u to "PPtr", - 633u to "PPtr", 646u to "PPtr", 659u to "PPtr", 672u to "PPtr", - 688u to "PPtr", 702u to "PPtr", 718u to "PPtr", - 734u to "Prefab", 741u to "Quaternionf", 753u to "Rectf", 759u to "RectInt", 767u to "RectOffset", - 778u to "second", 785u to "set", 789u to "short", 795u to "size", 800u to "SInt16", 807u to "SInt32", - 814u to "SInt64", 821u to "SInt8", 827u to "staticvector", 840u to "string", 847u to "TextAsset", - 857u to "TextMesh", 866u to "Texture", 874u to "Texture2D", 884u to "Transform", 894u to "TypelessData", - 907u to "UInt16", 914u to "UInt32", 921u to "UInt64", 928u to "UInt8", 934u to "unsigned int", - 947u to "unsigned long long", 966u to "unsigned short", 981u to "vector", 988u to "Vector2f", - 997u to "Vector3f", 1006u to "Vector4f", 1015u to "m_ScriptingClassIdentifier", 1042u to "Gradient", - 1051u to "Type*", 1057u to "int2_storage", 1070u to "int3_storage", 1083u to "BoundsInt", - 1093u to "m_CorrespondingSourceObject", 1121u to "m_PrefabInstance", 1138u to "m_PrefabAsset", - 1152u to "FileSize", 1161u to "Hash128" - ) - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/file/WebFile.kt b/src/main/kotlin/io/github/deficuet/unitykt/file/WebFile.kt deleted file mode 100644 index 12cfe5f2..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/file/WebFile.kt +++ /dev/null @@ -1,53 +0,0 @@ -package io.github.deficuet.unitykt.file - -import io.github.deficuet.unitykt.util.CompressUtils -import io.github.deficuet.unitykt.util.EndianBinaryReader -import io.github.deficuet.unitykt.util.EndianByteArrayReader -import java.nio.ByteOrder - -class WebFile( - preReader: EndianBinaryReader, - override val bundleParent: AssetBundleFile, - override val name: String -): AssetBundleFile() { - override val files: Map - - private val reader: EndianBinaryReader - private val directoryInfo = mutableListOf() - - init { - var magic = preReader.runThenReset { read(2) } - reader = if (magic.contentEquals(CompressUtils.GZIP_MAGIC)) { - EndianByteArrayReader( - CompressUtils.gzipDecompress(preReader.bytes), - endian = ByteOrder.LITTLE_ENDIAN - ) - } else { - preReader.position = 0x20 - magic = preReader.runThenReset { read(6) } - if (magic.contentEquals(CompressUtils.BROTLI_MAGIC)) { - EndianByteArrayReader( - CompressUtils.brotliDecompress(preReader.bytes), - endian = ByteOrder.LITTLE_ENDIAN - ) - } else { - preReader.resetEndian(ByteOrder.LITTLE_ENDIAN) - } - } - if (reader.readStringUntilNull() == "UnityWebData1.0") { - val headLength = reader.readInt() - while (reader.position < headLength) { - directoryInfo.add( - DirectoryInfoNode( - offset = reader.readInt().toLong(), - size = reader.readInt().toLong(), - path = reader.readString(reader.readInt()) - ) - ) - } - } - files = readFiles(reader, directoryInfo) - preReader.close() - reader.close() - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/ImportContextImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/ImportContextImpl.kt new file mode 100644 index 00000000..78e3c339 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/ImportContextImpl.kt @@ -0,0 +1,74 @@ +package io.github.deficuet.unitykt.internal + +import io.github.deficuet.unitykt.ImportContext +import io.github.deficuet.unitykt.ReaderConfig +import io.github.deficuet.unitykt.classes.UnityObject +import io.github.deficuet.unitykt.internal.file.* +import io.github.deficuet.unitykt.util.CompressUtils +import io.github.deficuet.unitykt.util.EndianBinaryFileReader +import io.github.deficuet.unitykt.util.EndianBinaryReader +import io.github.deficuet.unitykt.util.EndianByteArrayReader +import java.io.File +import java.nio.ByteOrder + +internal class ImportContextImpl: ImportContext, FileNode { + override val bundleParent = this + override val root = this + + override val name: String + override val parent: String + override val manager: UnityAssetManagerImpl + override val readerConfig: ReaderConfig + override val objectMap = mutableMapOf() + override val objectList: Collection get() = objectMap.values + + internal constructor( + file: File, + manager: UnityAssetManagerImpl, + config: ReaderConfig + ) { + parent = file.parentFile.canonicalPath + name = file.name + this.manager = manager + readerConfig = config + init(EndianBinaryFileReader(file, config = config)) + } + + internal constructor( + data: ByteArray, + name: String, + manager: UnityAssetManagerImpl, + config: ReaderConfig + ) { + parent = "" + this.name = name + this.manager = manager + readerConfig = config + init(EndianByteArrayReader(data, config = config)) + } + + private fun init(reader: EndianBinaryReader): AssetFile { + return when (readerFileType(reader)) { + FileType.BUNDLE -> BundleFile(reader, this, name) + FileType.WEB -> WebFile(reader, this, name) + FileType.GZIP -> init( + EndianByteArrayReader( + CompressUtils.gzipDecompress(reader.bytes), + endian = ByteOrder.LITTLE_ENDIAN + ) + ) + FileType.BROTLI -> init( + EndianByteArrayReader( + CompressUtils.brotliDecompress(reader.bytes), + endian = ByteOrder.LITTLE_ENDIAN + ) + ) + FileType.ASSETS -> SerializedFile(reader, this, name).also { + manager.assetFiles[name.lowercase()] = it + } + FileType.RESOURCE -> ResourceFile(reader, this, name).also { + manager.resourceFiles[name] = it + } + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/util/NativeUtils.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/NativeUtils.kt similarity index 61% rename from src/main/kotlin/io/github/deficuet/unitykt/util/NativeUtils.kt rename to src/main/kotlin/io/github/deficuet/unitykt/internal/NativeUtils.kt index 4090e3c1..2fa4fa28 100644 --- a/src/main/kotlin/io/github/deficuet/unitykt/util/NativeUtils.kt +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/NativeUtils.kt @@ -1,4 +1,4 @@ -package io.github.deficuet.unitykt.util +package io.github.deficuet.unitykt.internal import java.io.File import java.io.IOException @@ -6,11 +6,11 @@ import java.nio.file.FileSystems import java.nio.file.Files import java.nio.file.StandardCopyOption -class NativeUtils private constructor() { +internal class NativeUtils private constructor() { companion object { private val nativeTempFolder by lazy { val temp = File( - "${System.getProperty("java.io.tmpdir")}UnityKt-Deficuet" + "${System.getProperty("java.io.tmpdir")}UnityKt_Deficuet" ) if (!temp.exists()) { if (!temp.mkdir()) @@ -27,22 +27,24 @@ class NativeUtils private constructor() { } } - fun loadLibraryFromJar(name: String) { - val tempFile = File(nativeTempFolder, name) - NativeUtils::class.java.getResourceAsStream("/$name")!!.use { + fun loadLibraryFromJar(name: String, ext: String) { + val f = File.createTempFile("${name}_", ".${ext}", nativeTempFolder) + NativeUtils::class.java.getResourceAsStream("/${name}.${ext}")!!.use { try { - Files.copy(it, tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING) + Files.copy(it, f.toPath(), StandardCopyOption.REPLACE_EXISTING) } catch (e: IOException) { - tempFile.delete() + f.delete() throw e } } try { - System.load(tempFile.absolutePath) + System.load(f.absolutePath) } finally { try { if (isPosix) { - tempFile.delete() + f.delete() + } else { + f.deleteOnExit() } } catch (_: Throwable) { } } diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/UnityAssetManagerImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/UnityAssetManagerImpl.kt new file mode 100644 index 00000000..6215f4cb --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/UnityAssetManagerImpl.kt @@ -0,0 +1,97 @@ +package io.github.deficuet.unitykt.internal + +import io.github.deficuet.unitykt.ImportContext +import io.github.deficuet.unitykt.ReaderConfig +import io.github.deficuet.unitykt.UnityAssetManager +import io.github.deficuet.unitykt.internal.file.ResourceFile +import io.github.deficuet.unitykt.internal.file.SerializedFile +import java.io.Closeable +import java.io.File +import java.nio.file.Files +import java.nio.file.Path +import java.util.stream.Collectors +import kotlin.io.path.Path +import kotlin.io.path.isDirectory +import kotlin.io.path.isRegularFile + +internal class UnityAssetManagerImpl( + override val assetRootFolder: File?, + override val defaultReaderConfig: ReaderConfig +): UnityAssetManager { + init { UnityAssetManager.managers.add(this) } + + val assetFiles = mutableMapOf() + val resourceFiles = mutableMapOf() + override val contexts = mutableMapOf() + override val objectList get() = contexts.values.flatMap { context -> + sequence { + for (obj in context.objectMap) { + if (obj.key != 1L) { + yield(obj.value) + } + } + } + } + override val objectMap get() = objectList.groupBy { it.mPathID } + + override fun loadFromByteArray(data: ByteArray, name: String, config: ReaderConfig): ImportContext { + return ImportContextImpl(data, name, this, config).also { + contexts[it.name] = it + } + } + override fun loadFile(file: String, config: ReaderConfig) = loadFile(File(file), config) + override fun loadFile(file: Path, config: ReaderConfig) = loadFile(file.toFile(), config) + override fun loadFile(file: File, config: ReaderConfig): ImportContext { + if (!file.isFile) throw IllegalArgumentException("parameter \"file\" must be a file") + return ImportContextImpl(file, this, config).also { + contexts[it.name] = it + } + } + override fun loadFiles(vararg files: String, config: ReaderConfig): Array { + return loadFiles(*Array(files.size) { File(files[it]) }, config = config) + } + override fun loadFiles(vararg files: Path, config: ReaderConfig): Array { + return loadFiles(*Array(files.size) { files[it].toFile() }, config = config) + } + override fun loadFiles(vararg files: File, config: ReaderConfig): Array { + if (files.any { !it.isFile }) throw IllegalArgumentException("all elements in \"files\" must be file") + return Array(files.size) { + loadFile(files[it], config) + } + } + override fun loadFolder(folder: String, config: ReaderConfig) = loadFolder(Path(folder), config) + override fun loadFolder(folder: File, config: ReaderConfig) = loadFolder(folder.toPath(), config) + override fun loadFolder(folder: Path, config: ReaderConfig): Array { + if (!folder.isDirectory()) throw IllegalArgumentException("parameter \"folder\" must be a directory") + val files = Files.newDirectoryStream(folder).use { stream -> + stream.filter { it.isRegularFile() } + .toTypedArray() + } + return loadFiles(*files, config = config) + } + override fun loadFolderRecursively(folder: String, config: ReaderConfig): Array { + return loadFolderRecursively(Path(folder), config) + } + override fun loadFolderRecursively(folder: File, config: ReaderConfig): Array { + return loadFolderRecursively(folder.toPath(), config) + } + override fun loadFolderRecursively(folder: Path, config: ReaderConfig): Array { + if (!folder.isDirectory()) throw IllegalArgumentException("parameter \"path\" must be a directory") + val files = Files.walk(folder).use { + it.filter(Files::isRegularFile).collect(Collectors.toList()).toTypedArray() + } + return loadFiles(*files, config = config) + } + + internal val otherReaderList = mutableListOf() + + override fun close() { + assetFiles.values.forEach { it.reader.close() } + resourceFiles.values.forEach { it.reader.close() } + otherReaderList.forEach { it.close() } + assetFiles.clear() + resourceFiles.clear() + otherReaderList.clear() + contexts.clear() + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/export/smolv/SmolvDecoder.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/export/smolv/SmolvDecoder.kt similarity index 53% rename from src/main/kotlin/io/github/deficuet/unitykt/export/smolv/SmolvDecoder.kt rename to src/main/kotlin/io/github/deficuet/unitykt/internal/export/smolv/SmolvDecoder.kt index 71cb34c4..a2e9d28a 100644 --- a/src/main/kotlin/io/github/deficuet/unitykt/export/smolv/SmolvDecoder.kt +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/export/smolv/SmolvDecoder.kt @@ -1,32 +1,23 @@ -package io.github.deficuet.unitykt.export.smolv +package io.github.deficuet.unitykt.internal.export.smolv -import io.github.deficuet.unitykt.export.EndianByteArrayWriter -import io.github.deficuet.unitykt.export.spirv.of import io.github.deficuet.unitykt.util.EndianBinaryReader -import io.github.deficuet.unitykt.util.Reference +import io.github.deficuet.unitykt.util.EndianByteArrayWriter +import io.github.deficuet.unitykt.util.useEndian +import io.github.deficuet.unitykt.util.withMark import java.nio.ByteOrder internal class SmolvDecoder private constructor() { companion object { private const val headerSize = 24 private const val spirVHeaderMagic = 0x07230203u - private val UInt.zigDecode: Int get() { - return if (this.and(1u) != 0u) { - this.shr(1).inv().toInt() - } else { - this.shr(1).toInt() - } - } fun getDecodedBufferSize(reader: EndianBinaryReader): Int { if (reader.position + headerSize > reader.length) return 0 return reader.withMark { - position += headerSize - 4 - val endian = reader.endian - resetEndian(ByteOrder.LITTLE_ENDIAN) - val size = readInt() - resetEndian(endian) - size + skip(headerSize - 4) + useEndian(ByteOrder.LITTLE_ENDIAN) { + readInt32() + } } } @@ -37,38 +28,36 @@ internal class SmolvDecoder private constructor() { val decodedSize: Int with(writer) { with(reader) { - writeUInt(spirVHeaderMagic) - reader += 4 - writeUInt(readUInt()) - writeUInt(readUInt()) - writeInt(readInt()) - writeUInt(readUInt()) - decodedSize = readInt() + writeUInt32(spirVHeaderMagic) + reader.skip(4) + writeUInt32(readUInt32()) + writeUInt32(readUInt32()) + writeInt32(readInt32()) + writeUInt32(readUInt32()) + decodedSize = readInt32() } } var prevResult = 0; var prevDecorate = 0 while (reader.position < inputEnd) { - val inStrLenRef = Reference() - val opRef = Reference() - readLengthOp(reader, inStrLenRef, opRef) - var op = opRef.value; val inStrLen = inStrLenRef.value + val len: UInt; var op: SpvOp + with(readLengthOp(reader)) { len = this.len; op = this.op } val wasSwizzle = op == SpvOp.VectorShuffleCompact if (wasSwizzle) op = SpvOp.VectorShuffle - writer.writeUInt(inStrLen.shl(16).or(op.id)) + writer.writeUInt32(len.shl(16).or(op.id)) var ioffs = 1u if (op.hasType) { - writer.writeUInt(readVarInt(reader)) + writer.writeUInt32(readVarInt(reader)) ioffs++ } if (op.hasResult) { - val zds = prevResult + readVarInt(reader).zigDecode - writer.writeInt(zds) + val zds = prevResult + zigDecode(readVarInt(reader)) + writer.writeInt32(zds) prevResult = zds ioffs++ } if (op == SpvOp.Decorate || op == SpvOp.MemberDecorate) { val zds = prevDecorate + readVarInt(reader).toInt() - writer.writeInt(zds) + writer.writeInt32(zds) prevDecorate = zds ioffs++ } @@ -79,27 +68,27 @@ internal class SmolvDecoder private constructor() { relativeCount = -relativeCount } var i = 0 - while (i < relativeCount && ioffs < inStrLen) { + while (i < relativeCount && ioffs < len) { val v = readVarInt(reader) - val zd = if (inverted) v.zigDecode else v.toInt() - writer.writeInt(prevResult - zd) + val zd = if (inverted) zigDecode(v) else v.toInt() + writer.writeInt32(prevResult - zd) i++; ioffs++ } - if (wasSwizzle && inStrLen <= 9u) { - val swizzle = reader.readByte().toUInt() - if (inStrLen > 5u) { writer.writeUInt(swizzle.shr(6)) } - if (inStrLen > 6u) { writer.writeUInt(swizzle.shr(4).and(3u)) } - if (inStrLen > 7u) { writer.writeUInt(swizzle.shr(2).and(3u)) } - if (inStrLen > 8u) { writer.writeUInt(swizzle.and(3u)) } + if (wasSwizzle && len <= 9u) { + val swizzle = reader.read().toUInt() + if (len > 5u) { writer.writeUInt32(swizzle.shr(6)) } + if (len > 6u) { writer.writeUInt32(swizzle.shr(4).and(3u)) } + if (len > 7u) { writer.writeUInt32(swizzle.shr(2).and(3u)) } + if (len > 8u) { writer.writeUInt32(swizzle.and(3u)) } } else if (op.varRest) { - while (ioffs < inStrLen) { - writer.writeUInt(readVarInt(reader)) + while (ioffs < len) { + writer.writeUInt32(readVarInt(reader)) ioffs++ } } else { - while (ioffs < inStrLen) { + while (ioffs < len) { if (reader.position + 4 > reader.length) return false - writer.writeUInt(reader.readUInt()) + writer.writeUInt32(reader.readUInt32()) ioffs++ } } @@ -108,10 +97,18 @@ internal class SmolvDecoder private constructor() { return true } + private fun zigDecode(u: UInt): Int { + return if (u.and(1u) != 0u) { + u.shr(1).inv().toInt() + } else { + u.shr(1).toInt() + } + } + private fun readVarInt(reader: EndianBinaryReader): UInt { var v = 0u; var shift = 0 while (reader.position < reader.length) { - val b = reader.readByte().toUInt() + val b = reader.read().toUInt() v = v.or(b.and(127u).shl(shift)) shift += 7 if (b.and(128u) == 0u) break @@ -119,17 +116,14 @@ internal class SmolvDecoder private constructor() { return v } - private fun readLengthOp( - reader: EndianBinaryReader, - len: Reference, - op: Reference - ): Boolean { - len.value = 0u; op.value = SpvOp.Nop + private data class LengthOp(val len: UInt, val op: SpvOp) + + private fun readLengthOp(reader: EndianBinaryReader): LengthOp { val value = readVarInt(reader) - len.value = value.shr(20).shl(4).or(value.shr(4).and(0xFu)) - op.value = SpvOp.of(value.shr(4).and(0xFFF0u).or(value.and(0xFu))).remap() - len.value = decodeLen(op.value, len.value) - return true + var len = value.shr(20).shl(4).or(value.shr(4).and(0xFu)) + val op = SpvOp.of(value.shr(4).and(0xFFF0u).or(value.and(0xFu))).remap() + len = decodeLen(op, len) + return LengthOp(len, op) } private fun decodeLen(op: SpvOp, len: UInt): UInt { diff --git a/src/main/kotlin/io/github/deficuet/unitykt/export/smolv/SpvOp.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/export/smolv/SpvOp.kt similarity index 96% rename from src/main/kotlin/io/github/deficuet/unitykt/export/smolv/SpvOp.kt rename to src/main/kotlin/io/github/deficuet/unitykt/internal/export/smolv/SpvOp.kt index 8af3ed98..1fa8da68 100644 --- a/src/main/kotlin/io/github/deficuet/unitykt/export/smolv/SpvOp.kt +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/export/smolv/SpvOp.kt @@ -1,10 +1,8 @@ -package io.github.deficuet.unitykt.export.smolv +package io.github.deficuet.unitykt.internal.export.smolv -import io.github.deficuet.unitykt.export.spirv.NumericalEnum -import io.github.deficuet.unitykt.export.spirv.NumericalEnumCompanion -import io.github.deficuet.unitykt.util.equalsAnyOf +import io.github.deficuet.unitykt.enums.NumericalEnum +import io.github.deficuet.unitykt.enums.NumericalEnumCompanion -@Suppress("unused") internal enum class SpvOp( override val id: UInt, private val hasResultValue: Int, @@ -349,7 +347,6 @@ internal enum class SpvOp( val hasResult get() = hasResultValue != 0 val hasType get() = hasTypeValue != 0 val varRest get() = varRestValue != 0 - val debugInfo get() = equalsAnyOf(*debugInfoArray) fun remap(): SpvOp { return when (this) { @@ -381,10 +378,5 @@ internal enum class SpvOp( } } - companion object: NumericalEnumCompanion() { - private val debugInfoArray = arrayOf( - SourceContinued, Source, SourceExtension, Name, - MemberName, String, Line, NoLine, ModuleProcessed - ) - } -} \ No newline at end of file + companion object: NumericalEnumCompanion(values(), DefaultOutOfRange) +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/export/spirv/Disassembler.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/export/spirv/Disassembler.kt similarity index 52% rename from src/main/kotlin/io/github/deficuet/unitykt/export/spirv/Disassembler.kt rename to src/main/kotlin/io/github/deficuet/unitykt/internal/export/spirv/Disassembler.kt index 3d0546d7..51a02000 100644 --- a/src/main/kotlin/io/github/deficuet/unitykt/export/spirv/Disassembler.kt +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/export/spirv/Disassembler.kt @@ -1,15 +1,17 @@ -package io.github.deficuet.unitykt.export.spirv +package io.github.deficuet.unitykt.internal.export.spirv +import io.github.deficuet.unitykt.cast +import io.github.deficuet.unitykt.enums.FlagsAttributeEnum +import io.github.deficuet.unitykt.enums.FlagsAttributeEnumCompanion import java.util.* -@Suppress("unused") -internal enum class DisassemblyOptions(override val exp: Int): FlagsAttributeEnum { +internal enum class DisassemblyOptions(override val bitPos: Int): FlagsAttributeEnum { None(-1), ShowTypes(0), ShowNames(1); - companion object: FlagsAttributeEnumCompanion() { - val Default = of(3) + companion object: FlagsAttributeEnumCompanion(DisassemblyOptions::class.java, values(), None) { + val Default = of(3u) } } @@ -22,7 +24,7 @@ internal class Disassembler { options: EnumSet = DisassemblyOptions.Default ): String { + "; SPIR-v\n" - + "; Version: ${module.header.version}\n" + + "; Version: ${module.header.versionMajor}.${module.header.versionMinor}\n" + "; Generator: ${ with(module.header) { if (generatorName.isBlank()) { @@ -38,7 +40,7 @@ internal class Disassembler { lines[0] = builder.toString() builder.clear() for (i in module.instructions.indices) { - module.instructions[i].disassemble(options) + disassembleInstruction(module.instructions[i], options) lines[i + 1] = builder.toString() builder.clear() } @@ -63,65 +65,65 @@ internal class Disassembler { return result } - private fun ParsedInstruction.disassemble(options: EnumSet) { - if (operands.isEmpty()) { - + instruction.name + private fun disassembleInstruction(p: ParsedInstruction, options: EnumSet) { + if (p.operands.isEmpty()) { + + p.instruction.name return } var currentOperand = 0 - if (instruction.operands[currentOperand].type is IdResultType) { + if (p.instruction.operands[currentOperand].type is IdResultType) { if (DisassemblyOptions.ShowTypes in options) { - resultType!!.toString(builder).append(" ") + p.resultType!!.toString(builder).append(" ") } ++currentOperand } - if (currentOperand < operands.size && instruction.operands[currentOperand].type is IdResult) { - if (DisassemblyOptions.ShowNames !in options || name.isBlank()) { - operands[currentOperand].value.disassembleOperand(options) + if (currentOperand < p.operands.size && p.instruction.operands[currentOperand].type is IdResult) { + if (DisassemblyOptions.ShowNames !in options || p.name.isBlank()) { + disassembleOperand(p.operands[currentOperand].value, options) } else { - + name + + p.name } + " = " ++currentOperand } - + "${instruction.name} " - while (currentOperand < operands.size) { - operands[currentOperand].value.disassembleOperand(options) + + "${p.instruction.name} " + while (currentOperand < p.operands.size) { + disassembleOperand(p.operands[currentOperand].value, options) + " " currentOperand++ } } - private fun Any.disassembleOperand(options: EnumSet) { - when (this) { - is Class<*> -> + simpleName - is String -> + "\"$this\"" + private fun disassembleOperand(o: Any, options: EnumSet) { + when (o) { + is Class<*> -> + o.simpleName + is String -> + "\"$o\"" is ObjectReference -> { - if (DisassemblyOptions.ShowNames in options && reference != null && reference!!.name.isNotBlank()) { - + reference!!.name + if (DisassemblyOptions.ShowNames in options && o.reference != null && o.reference!!.name.isNotBlank()) { + + o.reference!!.name } else { - toString(builder) + o.toString(builder) } } is BitEnumOperandValue<*> -> { - for (key in values.keys) { - + enumClass.enumConstants.first { (it as FlagsAttributeEnum<*>).numeric.toUInt() == key }.name - val value = values.getValue(key) + for (key in o.values.keys) { + + o.enumClass.enumConstants.first { it.cast().value == key }.name + val value = o.values.getValue(key) if (value.isNotEmpty()) { + " " - value.forEach { it.disassembleOperand(options) } + value.forEach { disassembleOperand(it, options) } } } } is ValueEnumOperandValue<*> -> { - + key.name - if (value.isNotEmpty()) { + + o.key.name + if (o.value.isNotEmpty()) { + " " - value.forEach { it.disassembleOperand(options) } + o.value.forEach { disassembleOperand(it, options) } } } - is VaryingOperandValue -> toString(builder) - else -> + toString() + is VaryingOperandValue -> o.toString(builder) + else -> + java.lang.String.valueOf(o) } } -} \ No newline at end of file +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/export/spirv/Instruction.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/export/spirv/Instruction.kt new file mode 100644 index 00000000..a33bcacd --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/export/spirv/Instruction.kt @@ -0,0 +1,348 @@ +package io.github.deficuet.unitykt.internal.export.spirv + +internal enum class OperandQuantifier { + Default, Optional, Varying +} + +internal class Operand(val type: OperandType, val name: String, val quantifier: OperandQuantifier) + +internal class Instruction(val name: String, val operands: Array) { + constructor(name: String): this(name, emptyArray()) + + companion object { + val opcodeMap by lazy { + mapOf( + 0 to Instruction("OpNop"), + 1 to Instruction("OpUndef", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default))), + 2 to Instruction("OpSourceContinued", arrayOf(Operand(LiteralString(), "Continued Source", OperandQuantifier.Default))), + 3 to Instruction("OpSource", arrayOf(Operand(EnumType(SourceLanguage::class.java, SourceLanguage.values(), SourceLanguage.Companion, SourceLanguageParameterFactory.defaultInst), "", OperandQuantifier.Default), Operand(LiteralInteger(), "Version", OperandQuantifier.Default), Operand(IdRef(), "File", OperandQuantifier.Optional), Operand(LiteralString(), "Source", OperandQuantifier.Optional))), + 4 to Instruction("OpSourceExtension", arrayOf(Operand(LiteralString(), "Extension", OperandQuantifier.Default))), + 5 to Instruction("OpName", arrayOf(Operand(IdRef(), "Target", OperandQuantifier.Default), Operand(LiteralString(), "Name", OperandQuantifier.Default))), + 6 to Instruction("OpMemberName", arrayOf(Operand(IdRef(), "Type", OperandQuantifier.Default), Operand(LiteralInteger(), "Member", OperandQuantifier.Default), Operand(LiteralString(), "Name", OperandQuantifier.Default))), + 7 to Instruction("OpString", arrayOf(Operand(IdResult(), "", OperandQuantifier.Default), Operand(LiteralString(), "String", OperandQuantifier.Default))), + 8 to Instruction("OpLine", arrayOf(Operand(IdRef(), "File", OperandQuantifier.Default), Operand(LiteralInteger(), "Line", OperandQuantifier.Default), Operand(LiteralInteger(), "Column", OperandQuantifier.Default))), + 10 to Instruction("OpExtension", arrayOf(Operand(LiteralString(), "Name", OperandQuantifier.Default))), + 11 to Instruction("OpExtInstImport", arrayOf(Operand(IdResult(), "", OperandQuantifier.Default), Operand(LiteralString(), "Name", OperandQuantifier.Default))), + 12 to Instruction("OpExtInst", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Set", OperandQuantifier.Default), Operand(LiteralExtInstInteger(), "Instruction", OperandQuantifier.Default), Operand(IdRef(), "Operand 1, +Operand 2, +...", OperandQuantifier.Varying))), + 14 to Instruction("OpMemoryModel", arrayOf(Operand(EnumType(AddressingModel::class.java, AddressingModel.values(), AddressingModel.Companion, AddressingModelParameterFactory.defaultInst), "", OperandQuantifier.Default), Operand(EnumType(MemoryModel::class.java, MemoryModel.values(), MemoryModel.Companion, MemoryModelParameterFactory.defaultInst), "", OperandQuantifier.Default))), + 15 to Instruction("OpEntryPoint", arrayOf(Operand(EnumType(ExecutionModel::class.java, ExecutionModel.values(), ExecutionModel.Companion, ExecutionModelParameterFactory.defaultInst), "", OperandQuantifier.Default), Operand(IdRef(), "Entry Point", OperandQuantifier.Default), Operand(LiteralString(), "Name", OperandQuantifier.Default), Operand(IdRef(), "Interface", OperandQuantifier.Varying))), + 16 to Instruction("OpExecutionMode", arrayOf(Operand(IdRef(), "Entry Point", OperandQuantifier.Default), Operand(EnumType(ExecutionMode::class.java, ExecutionMode.values(), ExecutionMode.Companion, ExecutionModeParameterFactory.defaultInst), "Mode", OperandQuantifier.Default))), + 17 to Instruction("OpCapability", arrayOf(Operand(EnumType(Capability::class.java, Capability.values(), Capability.Companion, CapabilityParameterFactory.defaultInst), "Capability", OperandQuantifier.Default))), + 19 to Instruction("OpTypeVoid", arrayOf(Operand(IdResult(), "", OperandQuantifier.Default))), + 20 to Instruction("OpTypeBool", arrayOf(Operand(IdResult(), "", OperandQuantifier.Default))), + 21 to Instruction("OpTypeInt", arrayOf(Operand(IdResult(), "", OperandQuantifier.Default), Operand(LiteralInteger(), "Width", OperandQuantifier.Default), Operand(LiteralInteger(), "Signedness", OperandQuantifier.Default))), + 22 to Instruction("OpTypeFloat", arrayOf(Operand(IdResult(), "", OperandQuantifier.Default), Operand(LiteralInteger(), "Width", OperandQuantifier.Default))), + 23 to Instruction("OpTypeVector", arrayOf(Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Component Type", OperandQuantifier.Default), Operand(LiteralInteger(), "Component Count", OperandQuantifier.Default))), + 24 to Instruction("OpTypeMatrix", arrayOf(Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Column Type", OperandQuantifier.Default), Operand(LiteralInteger(), "Column Count", OperandQuantifier.Default))), + 25 to Instruction("OpTypeImage", arrayOf(Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Type", OperandQuantifier.Default), Operand(EnumType(Dim::class.java, Dim.values(), Dim.Companion, DimParameterFactory.defaultInst), "", OperandQuantifier.Default), Operand(LiteralInteger(), "Depth", OperandQuantifier.Default), Operand(LiteralInteger(), "Arrayed", OperandQuantifier.Default), Operand(LiteralInteger(), "MS", OperandQuantifier.Default), Operand(LiteralInteger(), "Sampled", OperandQuantifier.Default), Operand(EnumType(ImageFormat::class.java, ImageFormat.values(), ImageFormat.Companion, ImageFormatParameterFactory.defaultInst), "", OperandQuantifier.Default), Operand(EnumType(AccessQualifier::class.java, AccessQualifier.values(), AccessQualifier.Companion, AccessQualifierParameterFactory.defaultInst), "", OperandQuantifier.Optional))), + 26 to Instruction("OpTypeSampler", arrayOf(Operand(IdResult(), "", OperandQuantifier.Default))), + 27 to Instruction("OpTypeSampledImage", arrayOf(Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Image Type", OperandQuantifier.Default))), + 28 to Instruction("OpTypeArray", arrayOf(Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Element Type", OperandQuantifier.Default), Operand(IdRef(), "Length", OperandQuantifier.Default))), + 29 to Instruction("OpTypeRuntimeArray", arrayOf(Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Element Type", OperandQuantifier.Default))), + 30 to Instruction("OpTypeStruct", arrayOf(Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Member 0 type, +member 1 type, +...", OperandQuantifier.Varying))), + 31 to Instruction("OpTypeOpaque", arrayOf(Operand(IdResult(), "", OperandQuantifier.Default), Operand(LiteralString(), "The name of the opaque type.", OperandQuantifier.Default))), + 32 to Instruction("OpTypePointer", arrayOf(Operand(IdResult(), "", OperandQuantifier.Default), Operand(EnumType(StorageClass::class.java, StorageClass.values(), StorageClass.Companion, StorageClassParameterFactory.defaultInst), "", OperandQuantifier.Default), Operand(IdRef(), "Type", OperandQuantifier.Default))), + 33 to Instruction("OpTypeFunction", arrayOf(Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Return Type", OperandQuantifier.Default), Operand(IdRef(), "Parameter 0 Type, +Parameter 1 Type, +...", OperandQuantifier.Varying))), + 34 to Instruction("OpTypeEvent", arrayOf(Operand(IdResult(), "", OperandQuantifier.Default))), + 35 to Instruction("OpTypeDeviceEvent", arrayOf(Operand(IdResult(), "", OperandQuantifier.Default))), + 36 to Instruction("OpTypeReserveId", arrayOf(Operand(IdResult(), "", OperandQuantifier.Default))), + 37 to Instruction("OpTypeQueue", arrayOf(Operand(IdResult(), "", OperandQuantifier.Default))), + 38 to Instruction("OpTypePipe", arrayOf(Operand(IdResult(), "", OperandQuantifier.Default), Operand(EnumType(AccessQualifier::class.java, AccessQualifier.values(), AccessQualifier.Companion, AccessQualifierParameterFactory.defaultInst), "Qualifier", OperandQuantifier.Default))), + 39 to Instruction("OpTypeForwardPointer", arrayOf(Operand(IdRef(), "Pointer Type", OperandQuantifier.Default), Operand(EnumType(StorageClass::class.java, StorageClass.values(), StorageClass.Companion, StorageClassParameterFactory.defaultInst), "", OperandQuantifier.Default))), + 41 to Instruction("OpConstantTrue", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default))), + 42 to Instruction("OpConstantFalse", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default))), + 43 to Instruction("OpConstant", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(LiteralContextDependentNumber(), "Value", OperandQuantifier.Default))), + 44 to Instruction("OpConstantComposite", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Constituents", OperandQuantifier.Varying))), + 45 to Instruction("OpConstantSampler", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(EnumType(SamplerAddressingMode::class.java, SamplerAddressingMode.values(), SamplerAddressingMode.Companion, SamplerAddressingModeParameterFactory.defaultInst), "", OperandQuantifier.Default), Operand(LiteralInteger(), "Param", OperandQuantifier.Default), Operand(EnumType(SamplerFilterMode::class.java, SamplerFilterMode.values(), SamplerFilterMode.Companion, SamplerFilterModeParameterFactory.defaultInst), "", OperandQuantifier.Default))), + 46 to Instruction("OpConstantNull", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default))), + 48 to Instruction("OpSpecConstantTrue", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default))), + 49 to Instruction("OpSpecConstantFalse", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default))), + 50 to Instruction("OpSpecConstant", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(LiteralContextDependentNumber(), "Value", OperandQuantifier.Default))), + 51 to Instruction("OpSpecConstantComposite", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Constituents", OperandQuantifier.Varying))), + 52 to Instruction("OpSpecConstantOp", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(LiteralSpecConstantOpInteger(), "Opcode", OperandQuantifier.Default))), + 54 to Instruction("OpFunction", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(EnumType(FunctionControl::class.java, FunctionControl.values(), FunctionControl.Companion, FunctionControlParameterFactory.defaultInst), "", OperandQuantifier.Default), Operand(IdRef(), "Function Type", OperandQuantifier.Default))), + 55 to Instruction("OpFunctionParameter", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default))), + 56 to Instruction("OpFunctionEnd"), + 57 to Instruction("OpFunctionCall", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Function", OperandQuantifier.Default), Operand(IdRef(), "Argument 0, +Argument 1, +...", OperandQuantifier.Varying))), + 59 to Instruction("OpVariable", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(EnumType(StorageClass::class.java, StorageClass.values(), StorageClass.Companion, StorageClassParameterFactory.defaultInst), "", OperandQuantifier.Default), Operand(IdRef(), "Initializer", OperandQuantifier.Optional))), + 60 to Instruction("OpImageTexelPointer", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(IdRef(), "Sample", OperandQuantifier.Default))), + 61 to Instruction("OpLoad", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(EnumType(MemoryAccess::class.java, MemoryAccess.values(), MemoryAccess.Companion, MemoryAccessParameterFactory.defaultInst), "", OperandQuantifier.Optional))), + 62 to Instruction("OpStore", arrayOf(Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdRef(), "Object", OperandQuantifier.Default), Operand(EnumType(MemoryAccess::class.java, MemoryAccess.values(), MemoryAccess.Companion, MemoryAccessParameterFactory.defaultInst), "", OperandQuantifier.Optional))), + 63 to Instruction("OpCopyMemory", arrayOf(Operand(IdRef(), "Target", OperandQuantifier.Default), Operand(IdRef(), "Source", OperandQuantifier.Default), Operand(EnumType(MemoryAccess::class.java, MemoryAccess.values(), MemoryAccess.Companion, MemoryAccessParameterFactory.defaultInst), "", OperandQuantifier.Optional))), + 64 to Instruction("OpCopyMemorySized", arrayOf(Operand(IdRef(), "Target", OperandQuantifier.Default), Operand(IdRef(), "Source", OperandQuantifier.Default), Operand(IdRef(), "Size", OperandQuantifier.Default), Operand(EnumType(MemoryAccess::class.java, MemoryAccess.values(), MemoryAccess.Companion, MemoryAccessParameterFactory.defaultInst), "", OperandQuantifier.Optional))), + 65 to Instruction("OpAccessChain", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Base", OperandQuantifier.Default), Operand(IdRef(), "Indexes", OperandQuantifier.Varying))), + 66 to Instruction("OpInBoundsAccessChain", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Base", OperandQuantifier.Default), Operand(IdRef(), "Indexes", OperandQuantifier.Varying))), + 67 to Instruction("OpPtrAccessChain", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Base", OperandQuantifier.Default), Operand(IdRef(), "Element", OperandQuantifier.Default), Operand(IdRef(), "Indexes", OperandQuantifier.Varying))), + 68 to Instruction("OpArrayLength", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Structure", OperandQuantifier.Default), Operand(LiteralInteger(), "Array member", OperandQuantifier.Default))), + 69 to Instruction("OpGenericPtrMemSemantics", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default))), + 70 to Instruction("OpInBoundsPtrAccessChain", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Base", OperandQuantifier.Default), Operand(IdRef(), "Element", OperandQuantifier.Default), Operand(IdRef(), "Indexes", OperandQuantifier.Varying))), + 71 to Instruction("OpDecorate", arrayOf(Operand(IdRef(), "Target", OperandQuantifier.Default), Operand(EnumType(Decoration::class.java, Decoration.values(), Decoration.Companion, DecorationParameterFactory.defaultInst), "", OperandQuantifier.Default))), + 72 to Instruction("OpMemberDecorate", arrayOf(Operand(IdRef(), "Structure Type", OperandQuantifier.Default), Operand(LiteralInteger(), "Member", OperandQuantifier.Default), Operand(EnumType(Decoration::class.java, Decoration.values(), Decoration.Companion, DecorationParameterFactory.defaultInst), "", OperandQuantifier.Default))), + 73 to Instruction("OpDecorationGroup", arrayOf(Operand(IdResult(), "", OperandQuantifier.Default))), + 74 to Instruction("OpGroupDecorate", arrayOf(Operand(IdRef(), "Decoration Group", OperandQuantifier.Default), Operand(IdRef(), "Targets", OperandQuantifier.Varying))), + 75 to Instruction("OpGroupMemberDecorate", arrayOf(Operand(IdRef(), "Decoration Group", OperandQuantifier.Default), Operand(PairIdRefLiteralInteger(), "Targets", OperandQuantifier.Varying))), + 77 to Instruction("OpVectorExtractDynamic", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Vector", OperandQuantifier.Default), Operand(IdRef(), "Index", OperandQuantifier.Default))), + 78 to Instruction("OpVectorInsertDynamic", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Vector", OperandQuantifier.Default), Operand(IdRef(), "Component", OperandQuantifier.Default), Operand(IdRef(), "Index", OperandQuantifier.Default))), + 79 to Instruction("OpVectorShuffle", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Vector 1", OperandQuantifier.Default), Operand(IdRef(), "Vector 2", OperandQuantifier.Default), Operand(LiteralInteger(), "Components", OperandQuantifier.Varying))), + 80 to Instruction("OpCompositeConstruct", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Constituents", OperandQuantifier.Varying))), + 81 to Instruction("OpCompositeExtract", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Composite", OperandQuantifier.Default), Operand(LiteralInteger(), "Indexes", OperandQuantifier.Varying))), + 82 to Instruction("OpCompositeInsert", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Object", OperandQuantifier.Default), Operand(IdRef(), "Composite", OperandQuantifier.Default), Operand(LiteralInteger(), "Indexes", OperandQuantifier.Varying))), + 83 to Instruction("OpCopyObject", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand", OperandQuantifier.Default))), + 84 to Instruction("OpTranspose", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Matrix", OperandQuantifier.Default))), + 86 to Instruction("OpSampledImage", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Image", OperandQuantifier.Default), Operand(IdRef(), "Sampler", OperandQuantifier.Default))), + 87 to Instruction("OpImageSampleImplicitLod", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(EnumType(ImageOperands::class.java, ImageOperands.values(), ImageOperands.Companion, ImageOperandsParameterFactory.defaultInst), "", OperandQuantifier.Optional))), + 88 to Instruction("OpImageSampleExplicitLod", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(EnumType(ImageOperands::class.java, ImageOperands.values(), ImageOperands.Companion, ImageOperandsParameterFactory.defaultInst), "", OperandQuantifier.Default))), + 89 to Instruction("OpImageSampleDrefImplicitLod", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(IdRef(), "D~ref~", OperandQuantifier.Default), Operand(EnumType(ImageOperands::class.java, ImageOperands.values(), ImageOperands.Companion, ImageOperandsParameterFactory.defaultInst), "", OperandQuantifier.Optional))), + 90 to Instruction("OpImageSampleDrefExplicitLod", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(IdRef(), "D~ref~", OperandQuantifier.Default), Operand(EnumType(ImageOperands::class.java, ImageOperands.values(), ImageOperands.Companion, ImageOperandsParameterFactory.defaultInst), "", OperandQuantifier.Default))), + 91 to Instruction("OpImageSampleProjImplicitLod", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(EnumType(ImageOperands::class.java, ImageOperands.values(), ImageOperands.Companion, ImageOperandsParameterFactory.defaultInst), "", OperandQuantifier.Optional))), + 92 to Instruction("OpImageSampleProjExplicitLod", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(EnumType(ImageOperands::class.java, ImageOperands.values(), ImageOperands.Companion, ImageOperandsParameterFactory.defaultInst), "", OperandQuantifier.Default))), + 93 to Instruction("OpImageSampleProjDrefImplicitLod", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(IdRef(), "D~ref~", OperandQuantifier.Default), Operand(EnumType(ImageOperands::class.java, ImageOperands.values(), ImageOperands.Companion, ImageOperandsParameterFactory.defaultInst), "", OperandQuantifier.Optional))), + 94 to Instruction("OpImageSampleProjDrefExplicitLod", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(IdRef(), "D~ref~", OperandQuantifier.Default), Operand(EnumType(ImageOperands::class.java, ImageOperands.values(), ImageOperands.Companion, ImageOperandsParameterFactory.defaultInst), "", OperandQuantifier.Default))), + 95 to Instruction("OpImageFetch", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(EnumType(ImageOperands::class.java, ImageOperands.values(), ImageOperands.Companion, ImageOperandsParameterFactory.defaultInst), "", OperandQuantifier.Optional))), + 96 to Instruction("OpImageGather", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(IdRef(), "Component", OperandQuantifier.Default), Operand(EnumType(ImageOperands::class.java, ImageOperands.values(), ImageOperands.Companion, ImageOperandsParameterFactory.defaultInst), "", OperandQuantifier.Optional))), + 97 to Instruction("OpImageDrefGather", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(IdRef(), "D~ref~", OperandQuantifier.Default), Operand(EnumType(ImageOperands::class.java, ImageOperands.values(), ImageOperands.Companion, ImageOperandsParameterFactory.defaultInst), "", OperandQuantifier.Optional))), + 98 to Instruction("OpImageRead", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(EnumType(ImageOperands::class.java, ImageOperands.values(), ImageOperands.Companion, ImageOperandsParameterFactory.defaultInst), "", OperandQuantifier.Optional))), + 99 to Instruction("OpImageWrite", arrayOf(Operand(IdRef(), "Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(IdRef(), "Texel", OperandQuantifier.Default), Operand(EnumType(ImageOperands::class.java, ImageOperands.values(), ImageOperands.Companion, ImageOperandsParameterFactory.defaultInst), "", OperandQuantifier.Optional))), + 100 to Instruction("OpImage", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default))), + 101 to Instruction("OpImageQueryFormat", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Image", OperandQuantifier.Default))), + 102 to Instruction("OpImageQueryOrder", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Image", OperandQuantifier.Default))), + 103 to Instruction("OpImageQuerySizeLod", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Image", OperandQuantifier.Default), Operand(IdRef(), "Level of Detail", OperandQuantifier.Default))), + 104 to Instruction("OpImageQuerySize", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Image", OperandQuantifier.Default))), + 105 to Instruction("OpImageQueryLod", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default))), + 106 to Instruction("OpImageQueryLevels", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Image", OperandQuantifier.Default))), + 107 to Instruction("OpImageQuerySamples", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Image", OperandQuantifier.Default))), + 109 to Instruction("OpConvertFToU", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Float Value", OperandQuantifier.Default))), + 110 to Instruction("OpConvertFToS", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Float Value", OperandQuantifier.Default))), + 111 to Instruction("OpConvertSToF", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Signed Value", OperandQuantifier.Default))), + 112 to Instruction("OpConvertUToF", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Unsigned Value", OperandQuantifier.Default))), + 113 to Instruction("OpUConvert", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Unsigned Value", OperandQuantifier.Default))), + 114 to Instruction("OpSConvert", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Signed Value", OperandQuantifier.Default))), + 115 to Instruction("OpFConvert", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Float Value", OperandQuantifier.Default))), + 116 to Instruction("OpQuantizeToF16", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default))), + 117 to Instruction("OpConvertPtrToU", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default))), + 118 to Instruction("OpSatConvertSToU", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Signed Value", OperandQuantifier.Default))), + 119 to Instruction("OpSatConvertUToS", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Unsigned Value", OperandQuantifier.Default))), + 120 to Instruction("OpConvertUToPtr", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Integer Value", OperandQuantifier.Default))), + 121 to Instruction("OpPtrCastToGeneric", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default))), + 122 to Instruction("OpGenericCastToPtr", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default))), + 123 to Instruction("OpGenericCastToPtrExplicit", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(EnumType(StorageClass::class.java, StorageClass.values(), StorageClass.Companion, StorageClassParameterFactory.defaultInst), "Storage", OperandQuantifier.Default))), + 124 to Instruction("OpBitcast", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand", OperandQuantifier.Default))), + 126 to Instruction("OpSNegate", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand", OperandQuantifier.Default))), + 127 to Instruction("OpFNegate", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand", OperandQuantifier.Default))), + 128 to Instruction("OpIAdd", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 129 to Instruction("OpFAdd", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 130 to Instruction("OpISub", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 131 to Instruction("OpFSub", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 132 to Instruction("OpIMul", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 133 to Instruction("OpFMul", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 134 to Instruction("OpUDiv", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 135 to Instruction("OpSDiv", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 136 to Instruction("OpFDiv", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 137 to Instruction("OpUMod", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 138 to Instruction("OpSRem", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 139 to Instruction("OpSMod", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 140 to Instruction("OpFRem", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 141 to Instruction("OpFMod", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 142 to Instruction("OpVectorTimesScalar", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Vector", OperandQuantifier.Default), Operand(IdRef(), "Scalar", OperandQuantifier.Default))), + 143 to Instruction("OpMatrixTimesScalar", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Matrix", OperandQuantifier.Default), Operand(IdRef(), "Scalar", OperandQuantifier.Default))), + 144 to Instruction("OpVectorTimesMatrix", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Vector", OperandQuantifier.Default), Operand(IdRef(), "Matrix", OperandQuantifier.Default))), + 145 to Instruction("OpMatrixTimesVector", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Matrix", OperandQuantifier.Default), Operand(IdRef(), "Vector", OperandQuantifier.Default))), + 146 to Instruction("OpMatrixTimesMatrix", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "LeftMatrix", OperandQuantifier.Default), Operand(IdRef(), "RightMatrix", OperandQuantifier.Default))), + 147 to Instruction("OpOuterProduct", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Vector 1", OperandQuantifier.Default), Operand(IdRef(), "Vector 2", OperandQuantifier.Default))), + 148 to Instruction("OpDot", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Vector 1", OperandQuantifier.Default), Operand(IdRef(), "Vector 2", OperandQuantifier.Default))), + 149 to Instruction("OpIAddCarry", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 150 to Instruction("OpISubBorrow", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 151 to Instruction("OpUMulExtended", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 152 to Instruction("OpSMulExtended", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 154 to Instruction("OpAny", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Vector", OperandQuantifier.Default))), + 155 to Instruction("OpAll", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Vector", OperandQuantifier.Default))), + 156 to Instruction("OpIsNan", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "x", OperandQuantifier.Default))), + 157 to Instruction("OpIsInf", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "x", OperandQuantifier.Default))), + 158 to Instruction("OpIsFinite", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "x", OperandQuantifier.Default))), + 159 to Instruction("OpIsNormal", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "x", OperandQuantifier.Default))), + 160 to Instruction("OpSignBitSet", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "x", OperandQuantifier.Default))), + 161 to Instruction("OpLessOrGreater", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "x", OperandQuantifier.Default), Operand(IdRef(), "y", OperandQuantifier.Default))), + 162 to Instruction("OpOrdered", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "x", OperandQuantifier.Default), Operand(IdRef(), "y", OperandQuantifier.Default))), + 163 to Instruction("OpUnordered", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "x", OperandQuantifier.Default), Operand(IdRef(), "y", OperandQuantifier.Default))), + 164 to Instruction("OpLogicalEqual", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 165 to Instruction("OpLogicalNotEqual", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 166 to Instruction("OpLogicalOr", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 167 to Instruction("OpLogicalAnd", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 168 to Instruction("OpLogicalNot", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand", OperandQuantifier.Default))), + 169 to Instruction("OpSelect", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Condition", OperandQuantifier.Default), Operand(IdRef(), "Object 1", OperandQuantifier.Default), Operand(IdRef(), "Object 2", OperandQuantifier.Default))), + 170 to Instruction("OpIEqual", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 171 to Instruction("OpINotEqual", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 172 to Instruction("OpUGreaterThan", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 173 to Instruction("OpSGreaterThan", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 174 to Instruction("OpUGreaterThanEqual", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 175 to Instruction("OpSGreaterThanEqual", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 176 to Instruction("OpULessThan", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 177 to Instruction("OpSLessThan", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 178 to Instruction("OpULessThanEqual", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 179 to Instruction("OpSLessThanEqual", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 180 to Instruction("OpFOrdEqual", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 181 to Instruction("OpFUnordEqual", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 182 to Instruction("OpFOrdNotEqual", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 183 to Instruction("OpFUnordNotEqual", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 184 to Instruction("OpFOrdLessThan", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 185 to Instruction("OpFUnordLessThan", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 186 to Instruction("OpFOrdGreaterThan", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 187 to Instruction("OpFUnordGreaterThan", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 188 to Instruction("OpFOrdLessThanEqual", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 189 to Instruction("OpFUnordLessThanEqual", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 190 to Instruction("OpFOrdGreaterThanEqual", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 191 to Instruction("OpFUnordGreaterThanEqual", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 194 to Instruction("OpShiftRightLogical", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Base", OperandQuantifier.Default), Operand(IdRef(), "Shift", OperandQuantifier.Default))), + 195 to Instruction("OpShiftRightArithmetic", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Base", OperandQuantifier.Default), Operand(IdRef(), "Shift", OperandQuantifier.Default))), + 196 to Instruction("OpShiftLeftLogical", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Base", OperandQuantifier.Default), Operand(IdRef(), "Shift", OperandQuantifier.Default))), + 197 to Instruction("OpBitwiseOr", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 198 to Instruction("OpBitwiseXor", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 199 to Instruction("OpBitwiseAnd", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand 1", OperandQuantifier.Default), Operand(IdRef(), "Operand 2", OperandQuantifier.Default))), + 200 to Instruction("OpNot", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Operand", OperandQuantifier.Default))), + 201 to Instruction("OpBitFieldInsert", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Base", OperandQuantifier.Default), Operand(IdRef(), "Insert", OperandQuantifier.Default), Operand(IdRef(), "Offset", OperandQuantifier.Default), Operand(IdRef(), "Count", OperandQuantifier.Default))), + 202 to Instruction("OpBitFieldSExtract", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Base", OperandQuantifier.Default), Operand(IdRef(), "Offset", OperandQuantifier.Default), Operand(IdRef(), "Count", OperandQuantifier.Default))), + 203 to Instruction("OpBitFieldUExtract", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Base", OperandQuantifier.Default), Operand(IdRef(), "Offset", OperandQuantifier.Default), Operand(IdRef(), "Count", OperandQuantifier.Default))), + 204 to Instruction("OpBitReverse", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Base", OperandQuantifier.Default))), + 205 to Instruction("OpBitCount", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Base", OperandQuantifier.Default))), + 207 to Instruction("OpDPdx", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "P", OperandQuantifier.Default))), + 208 to Instruction("OpDPdy", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "P", OperandQuantifier.Default))), + 209 to Instruction("OpFwidth", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "P", OperandQuantifier.Default))), + 210 to Instruction("OpDPdxFine", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "P", OperandQuantifier.Default))), + 211 to Instruction("OpDPdyFine", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "P", OperandQuantifier.Default))), + 212 to Instruction("OpFwidthFine", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "P", OperandQuantifier.Default))), + 213 to Instruction("OpDPdxCoarse", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "P", OperandQuantifier.Default))), + 214 to Instruction("OpDPdyCoarse", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "P", OperandQuantifier.Default))), + 215 to Instruction("OpFwidthCoarse", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "P", OperandQuantifier.Default))), + 218 to Instruction("OpEmitVertex"), + 219 to Instruction("OpEndPrimitive"), + 220 to Instruction("OpEmitStreamVertex", arrayOf(Operand(IdRef(), "Stream", OperandQuantifier.Default))), + 221 to Instruction("OpEndStreamPrimitive", arrayOf(Operand(IdRef(), "Stream", OperandQuantifier.Default))), + 224 to Instruction("OpControlBarrier", arrayOf(Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(IdScope(), "Memory", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default))), + 225 to Instruction("OpMemoryBarrier", arrayOf(Operand(IdScope(), "Memory", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default))), + 227 to Instruction("OpAtomicLoad", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default))), + 228 to Instruction("OpAtomicStore", arrayOf(Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default))), + 229 to Instruction("OpAtomicExchange", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default))), + 230 to Instruction("OpAtomicCompareExchange", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Equal", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Unequal", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default), Operand(IdRef(), "Comparator", OperandQuantifier.Default))), + 231 to Instruction("OpAtomicCompareExchangeWeak", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Equal", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Unequal", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default), Operand(IdRef(), "Comparator", OperandQuantifier.Default))), + 232 to Instruction("OpAtomicIIncrement", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default))), + 233 to Instruction("OpAtomicIDecrement", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default))), + 234 to Instruction("OpAtomicIAdd", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default))), + 235 to Instruction("OpAtomicISub", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default))), + 236 to Instruction("OpAtomicSMin", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default))), + 237 to Instruction("OpAtomicUMin", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default))), + 238 to Instruction("OpAtomicSMax", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default))), + 239 to Instruction("OpAtomicUMax", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default))), + 240 to Instruction("OpAtomicAnd", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default))), + 241 to Instruction("OpAtomicOr", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default))), + 242 to Instruction("OpAtomicXor", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default))), + 245 to Instruction("OpPhi", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(PairIdRefIdRef(), "Variable, Parent, ...", OperandQuantifier.Varying))), + 246 to Instruction("OpLoopMerge", arrayOf(Operand(IdRef(), "Merge Block", OperandQuantifier.Default), Operand(IdRef(), "Continue Target", OperandQuantifier.Default), Operand(EnumType(LoopControl::class.java, LoopControl.values(), LoopControl.Companion, LoopControlParameterFactory.defaultInst), "", OperandQuantifier.Default))), + 247 to Instruction("OpSelectionMerge", arrayOf(Operand(IdRef(), "Merge Block", OperandQuantifier.Default), Operand(EnumType(SelectionControl::class.java, SelectionControl.values(), SelectionControl.Companion, SelectionControlParameterFactory.defaultInst), "", OperandQuantifier.Default))), + 248 to Instruction("OpLabel", arrayOf(Operand(IdResult(), "", OperandQuantifier.Default))), + 249 to Instruction("OpBranch", arrayOf(Operand(IdRef(), "Target Label", OperandQuantifier.Default))), + 250 to Instruction("OpBranchConditional", arrayOf(Operand(IdRef(), "Condition", OperandQuantifier.Default), Operand(IdRef(), "True Label", OperandQuantifier.Default), Operand(IdRef(), "False Label", OperandQuantifier.Default), Operand(LiteralInteger(), "Branch weights", OperandQuantifier.Varying))), + 251 to Instruction("OpSwitch", arrayOf(Operand(IdRef(), "Selector", OperandQuantifier.Default), Operand(IdRef(), "Default", OperandQuantifier.Default), Operand(PairLiteralIntegerIdRef(), "Target", OperandQuantifier.Varying))), + 252 to Instruction("OpKill"), + 253 to Instruction("OpReturn"), + 254 to Instruction("OpReturnValue", arrayOf(Operand(IdRef(), "Value", OperandQuantifier.Default))), + 255 to Instruction("OpUnreachable"), + 256 to Instruction("OpLifetimeStart", arrayOf(Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(LiteralInteger(), "Size", OperandQuantifier.Default))), + 257 to Instruction("OpLifetimeStop", arrayOf(Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(LiteralInteger(), "Size", OperandQuantifier.Default))), + 259 to Instruction("OpGroupAsyncCopy", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(IdRef(), "Destination", OperandQuantifier.Default), Operand(IdRef(), "Source", OperandQuantifier.Default), Operand(IdRef(), "Num Elements", OperandQuantifier.Default), Operand(IdRef(), "Stride", OperandQuantifier.Default), Operand(IdRef(), "Event", OperandQuantifier.Default))), + 260 to Instruction("OpGroupWaitEvents", arrayOf(Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(IdRef(), "Num Events", OperandQuantifier.Default), Operand(IdRef(), "Events List", OperandQuantifier.Default))), + 261 to Instruction("OpGroupAll", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(IdRef(), "Predicate", OperandQuantifier.Default))), + 262 to Instruction("OpGroupAny", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(IdRef(), "Predicate", OperandQuantifier.Default))), + 263 to Instruction("OpGroupBroadcast", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default), Operand(IdRef(), "LocalId", OperandQuantifier.Default))), + 264 to Instruction("OpGroupIAdd", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(EnumType(GroupOperation::class.java, GroupOperation.values(), GroupOperation.Companion, GroupOperationParameterFactory.defaultInst), "Operation", OperandQuantifier.Default), Operand(IdRef(), "X", OperandQuantifier.Default))), + 265 to Instruction("OpGroupFAdd", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(EnumType(GroupOperation::class.java, GroupOperation.values(), GroupOperation.Companion, GroupOperationParameterFactory.defaultInst), "Operation", OperandQuantifier.Default), Operand(IdRef(), "X", OperandQuantifier.Default))), + 266 to Instruction("OpGroupFMin", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(EnumType(GroupOperation::class.java, GroupOperation.values(), GroupOperation.Companion, GroupOperationParameterFactory.defaultInst), "Operation", OperandQuantifier.Default), Operand(IdRef(), "X", OperandQuantifier.Default))), + 267 to Instruction("OpGroupUMin", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(EnumType(GroupOperation::class.java, GroupOperation.values(), GroupOperation.Companion, GroupOperationParameterFactory.defaultInst), "Operation", OperandQuantifier.Default), Operand(IdRef(), "X", OperandQuantifier.Default))), + 268 to Instruction("OpGroupSMin", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(EnumType(GroupOperation::class.java, GroupOperation.values(), GroupOperation.Companion, GroupOperationParameterFactory.defaultInst), "Operation", OperandQuantifier.Default), Operand(IdRef(), "X", OperandQuantifier.Default))), + 269 to Instruction("OpGroupFMax", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(EnumType(GroupOperation::class.java, GroupOperation.values(), GroupOperation.Companion, GroupOperationParameterFactory.defaultInst), "Operation", OperandQuantifier.Default), Operand(IdRef(), "X", OperandQuantifier.Default))), + 270 to Instruction("OpGroupUMax", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(EnumType(GroupOperation::class.java, GroupOperation.values(), GroupOperation.Companion, GroupOperationParameterFactory.defaultInst), "Operation", OperandQuantifier.Default), Operand(IdRef(), "X", OperandQuantifier.Default))), + 271 to Instruction("OpGroupSMax", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(EnumType(GroupOperation::class.java, GroupOperation.values(), GroupOperation.Companion, GroupOperationParameterFactory.defaultInst), "Operation", OperandQuantifier.Default), Operand(IdRef(), "X", OperandQuantifier.Default))), + 274 to Instruction("OpReadPipe", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pipe", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdRef(), "Packet Size", OperandQuantifier.Default), Operand(IdRef(), "Packet Alignment", OperandQuantifier.Default))), + 275 to Instruction("OpWritePipe", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pipe", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdRef(), "Packet Size", OperandQuantifier.Default), Operand(IdRef(), "Packet Alignment", OperandQuantifier.Default))), + 276 to Instruction("OpReservedReadPipe", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pipe", OperandQuantifier.Default), Operand(IdRef(), "Reserve Id", OperandQuantifier.Default), Operand(IdRef(), "Index", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdRef(), "Packet Size", OperandQuantifier.Default), Operand(IdRef(), "Packet Alignment", OperandQuantifier.Default))), + 277 to Instruction("OpReservedWritePipe", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pipe", OperandQuantifier.Default), Operand(IdRef(), "Reserve Id", OperandQuantifier.Default), Operand(IdRef(), "Index", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdRef(), "Packet Size", OperandQuantifier.Default), Operand(IdRef(), "Packet Alignment", OperandQuantifier.Default))), + 278 to Instruction("OpReserveReadPipePackets", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pipe", OperandQuantifier.Default), Operand(IdRef(), "Num Packets", OperandQuantifier.Default), Operand(IdRef(), "Packet Size", OperandQuantifier.Default), Operand(IdRef(), "Packet Alignment", OperandQuantifier.Default))), + 279 to Instruction("OpReserveWritePipePackets", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pipe", OperandQuantifier.Default), Operand(IdRef(), "Num Packets", OperandQuantifier.Default), Operand(IdRef(), "Packet Size", OperandQuantifier.Default), Operand(IdRef(), "Packet Alignment", OperandQuantifier.Default))), + 280 to Instruction("OpCommitReadPipe", arrayOf(Operand(IdRef(), "Pipe", OperandQuantifier.Default), Operand(IdRef(), "Reserve Id", OperandQuantifier.Default), Operand(IdRef(), "Packet Size", OperandQuantifier.Default), Operand(IdRef(), "Packet Alignment", OperandQuantifier.Default))), + 281 to Instruction("OpCommitWritePipe", arrayOf(Operand(IdRef(), "Pipe", OperandQuantifier.Default), Operand(IdRef(), "Reserve Id", OperandQuantifier.Default), Operand(IdRef(), "Packet Size", OperandQuantifier.Default), Operand(IdRef(), "Packet Alignment", OperandQuantifier.Default))), + 282 to Instruction("OpIsValidReserveId", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Reserve Id", OperandQuantifier.Default))), + 283 to Instruction("OpGetNumPipePackets", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pipe", OperandQuantifier.Default), Operand(IdRef(), "Packet Size", OperandQuantifier.Default), Operand(IdRef(), "Packet Alignment", OperandQuantifier.Default))), + 284 to Instruction("OpGetMaxPipePackets", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pipe", OperandQuantifier.Default), Operand(IdRef(), "Packet Size", OperandQuantifier.Default), Operand(IdRef(), "Packet Alignment", OperandQuantifier.Default))), + 285 to Instruction("OpGroupReserveReadPipePackets", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(IdRef(), "Pipe", OperandQuantifier.Default), Operand(IdRef(), "Num Packets", OperandQuantifier.Default), Operand(IdRef(), "Packet Size", OperandQuantifier.Default), Operand(IdRef(), "Packet Alignment", OperandQuantifier.Default))), + 286 to Instruction("OpGroupReserveWritePipePackets", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(IdRef(), "Pipe", OperandQuantifier.Default), Operand(IdRef(), "Num Packets", OperandQuantifier.Default), Operand(IdRef(), "Packet Size", OperandQuantifier.Default), Operand(IdRef(), "Packet Alignment", OperandQuantifier.Default))), + 287 to Instruction("OpGroupCommitReadPipe", arrayOf(Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(IdRef(), "Pipe", OperandQuantifier.Default), Operand(IdRef(), "Reserve Id", OperandQuantifier.Default), Operand(IdRef(), "Packet Size", OperandQuantifier.Default), Operand(IdRef(), "Packet Alignment", OperandQuantifier.Default))), + 288 to Instruction("OpGroupCommitWritePipe", arrayOf(Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(IdRef(), "Pipe", OperandQuantifier.Default), Operand(IdRef(), "Reserve Id", OperandQuantifier.Default), Operand(IdRef(), "Packet Size", OperandQuantifier.Default), Operand(IdRef(), "Packet Alignment", OperandQuantifier.Default))), + 291 to Instruction("OpEnqueueMarker", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Queue", OperandQuantifier.Default), Operand(IdRef(), "Num Events", OperandQuantifier.Default), Operand(IdRef(), "Wait Events", OperandQuantifier.Default), Operand(IdRef(), "Ret Event", OperandQuantifier.Default))), + 292 to Instruction("OpEnqueueKernel", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Queue", OperandQuantifier.Default), Operand(IdRef(), "Flags", OperandQuantifier.Default), Operand(IdRef(), "ND Range", OperandQuantifier.Default), Operand(IdRef(), "Num Events", OperandQuantifier.Default), Operand(IdRef(), "Wait Events", OperandQuantifier.Default), Operand(IdRef(), "Ret Event", OperandQuantifier.Default), Operand(IdRef(), "Invoke", OperandQuantifier.Default), Operand(IdRef(), "Param", OperandQuantifier.Default), Operand(IdRef(), "Param Size", OperandQuantifier.Default), Operand(IdRef(), "Param Align", OperandQuantifier.Default), Operand(IdRef(), "Local Size", OperandQuantifier.Varying))), + 293 to Instruction("OpGetKernelNDrangeSubGroupCount", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "ND Range", OperandQuantifier.Default), Operand(IdRef(), "Invoke", OperandQuantifier.Default), Operand(IdRef(), "Param", OperandQuantifier.Default), Operand(IdRef(), "Param Size", OperandQuantifier.Default), Operand(IdRef(), "Param Align", OperandQuantifier.Default))), + 294 to Instruction("OpGetKernelNDrangeMaxSubGroupSize", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "ND Range", OperandQuantifier.Default), Operand(IdRef(), "Invoke", OperandQuantifier.Default), Operand(IdRef(), "Param", OperandQuantifier.Default), Operand(IdRef(), "Param Size", OperandQuantifier.Default), Operand(IdRef(), "Param Align", OperandQuantifier.Default))), + 295 to Instruction("OpGetKernelWorkGroupSize", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Invoke", OperandQuantifier.Default), Operand(IdRef(), "Param", OperandQuantifier.Default), Operand(IdRef(), "Param Size", OperandQuantifier.Default), Operand(IdRef(), "Param Align", OperandQuantifier.Default))), + 296 to Instruction("OpGetKernelPreferredWorkGroupSizeMultiple", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Invoke", OperandQuantifier.Default), Operand(IdRef(), "Param", OperandQuantifier.Default), Operand(IdRef(), "Param Size", OperandQuantifier.Default), Operand(IdRef(), "Param Align", OperandQuantifier.Default))), + 297 to Instruction("OpRetainEvent", arrayOf(Operand(IdRef(), "Event", OperandQuantifier.Default))), + 298 to Instruction("OpReleaseEvent", arrayOf(Operand(IdRef(), "Event", OperandQuantifier.Default))), + 299 to Instruction("OpCreateUserEvent", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default))), + 300 to Instruction("OpIsValidEvent", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Event", OperandQuantifier.Default))), + 301 to Instruction("OpSetUserEventStatus", arrayOf(Operand(IdRef(), "Event", OperandQuantifier.Default), Operand(IdRef(), "Status", OperandQuantifier.Default))), + 302 to Instruction("OpCaptureEventProfilingInfo", arrayOf(Operand(IdRef(), "Event", OperandQuantifier.Default), Operand(IdRef(), "Profiling Info", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default))), + 303 to Instruction("OpGetDefaultQueue", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default))), + 304 to Instruction("OpBuildNDRange", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "GlobalWorkSize", OperandQuantifier.Default), Operand(IdRef(), "LocalWorkSize", OperandQuantifier.Default), Operand(IdRef(), "GlobalWorkOffset", OperandQuantifier.Default))), + 305 to Instruction("OpImageSparseSampleImplicitLod", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(EnumType(ImageOperands::class.java, ImageOperands.values(), ImageOperands.Companion, ImageOperandsParameterFactory.defaultInst), "", OperandQuantifier.Optional))), + 306 to Instruction("OpImageSparseSampleExplicitLod", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(EnumType(ImageOperands::class.java, ImageOperands.values(), ImageOperands.Companion, ImageOperandsParameterFactory.defaultInst), "", OperandQuantifier.Default))), + 307 to Instruction("OpImageSparseSampleDrefImplicitLod", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(IdRef(), "D~ref~", OperandQuantifier.Default), Operand(EnumType(ImageOperands::class.java, ImageOperands.values(), ImageOperands.Companion, ImageOperandsParameterFactory.defaultInst), "", OperandQuantifier.Optional))), + 308 to Instruction("OpImageSparseSampleDrefExplicitLod", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(IdRef(), "D~ref~", OperandQuantifier.Default), Operand(EnumType(ImageOperands::class.java, ImageOperands.values(), ImageOperands.Companion, ImageOperandsParameterFactory.defaultInst), "", OperandQuantifier.Default))), + 309 to Instruction("OpImageSparseSampleProjImplicitLod", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(EnumType(ImageOperands::class.java, ImageOperands.values(), ImageOperands.Companion, ImageOperandsParameterFactory.defaultInst), "", OperandQuantifier.Optional))), + 310 to Instruction("OpImageSparseSampleProjExplicitLod", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(EnumType(ImageOperands::class.java, ImageOperands.values(), ImageOperands.Companion, ImageOperandsParameterFactory.defaultInst), "", OperandQuantifier.Default))), + 311 to Instruction("OpImageSparseSampleProjDrefImplicitLod", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(IdRef(), "D~ref~", OperandQuantifier.Default), Operand(EnumType(ImageOperands::class.java, ImageOperands.values(), ImageOperands.Companion, ImageOperandsParameterFactory.defaultInst), "", OperandQuantifier.Optional))), + 312 to Instruction("OpImageSparseSampleProjDrefExplicitLod", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(IdRef(), "D~ref~", OperandQuantifier.Default), Operand(EnumType(ImageOperands::class.java, ImageOperands.values(), ImageOperands.Companion, ImageOperandsParameterFactory.defaultInst), "", OperandQuantifier.Default))), + 313 to Instruction("OpImageSparseFetch", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(EnumType(ImageOperands::class.java, ImageOperands.values(), ImageOperands.Companion, ImageOperandsParameterFactory.defaultInst), "", OperandQuantifier.Optional))), + 314 to Instruction("OpImageSparseGather", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(IdRef(), "Component", OperandQuantifier.Default), Operand(EnumType(ImageOperands::class.java, ImageOperands.values(), ImageOperands.Companion, ImageOperandsParameterFactory.defaultInst), "", OperandQuantifier.Optional))), + 315 to Instruction("OpImageSparseDrefGather", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Sampled Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(IdRef(), "D~ref~", OperandQuantifier.Default), Operand(EnumType(ImageOperands::class.java, ImageOperands.values(), ImageOperands.Companion, ImageOperandsParameterFactory.defaultInst), "", OperandQuantifier.Optional))), + 316 to Instruction("OpImageSparseTexelsResident", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Resident Code", OperandQuantifier.Default))), + 317 to Instruction("OpNoLine"), + 318 to Instruction("OpAtomicFlagTestAndSet", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default))), + 319 to Instruction("OpAtomicFlagClear", arrayOf(Operand(IdRef(), "Pointer", OperandQuantifier.Default), Operand(IdScope(), "Scope", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default))), + 320 to Instruction("OpImageSparseRead", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(EnumType(ImageOperands::class.java, ImageOperands.values(), ImageOperands.Companion, ImageOperandsParameterFactory.defaultInst), "", OperandQuantifier.Optional))), + 321 to Instruction("OpSizeOf", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pointer", OperandQuantifier.Default))), + 322 to Instruction("OpTypePipeStorage", arrayOf(Operand(IdResult(), "", OperandQuantifier.Default))), + 323 to Instruction("OpConstantPipeStorage", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(LiteralInteger(), "Packet Size", OperandQuantifier.Default), Operand(LiteralInteger(), "Packet Alignment", OperandQuantifier.Default), Operand(LiteralInteger(), "Capacity", OperandQuantifier.Default))), + 324 to Instruction("OpCreatePipeFromPipeStorage", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Pipe Storage", OperandQuantifier.Default))), + 325 to Instruction("OpGetKernelLocalSizeForSubgroupCount", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Subgroup Count", OperandQuantifier.Default), Operand(IdRef(), "Invoke", OperandQuantifier.Default), Operand(IdRef(), "Param", OperandQuantifier.Default), Operand(IdRef(), "Param Size", OperandQuantifier.Default), Operand(IdRef(), "Param Align", OperandQuantifier.Default))), + 326 to Instruction("OpGetKernelMaxNumSubgroups", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Invoke", OperandQuantifier.Default), Operand(IdRef(), "Param", OperandQuantifier.Default), Operand(IdRef(), "Param Size", OperandQuantifier.Default), Operand(IdRef(), "Param Align", OperandQuantifier.Default))), + 327 to Instruction("OpTypeNamedBarrier", arrayOf(Operand(IdResult(), "", OperandQuantifier.Default))), + 328 to Instruction("OpNamedBarrierInitialize", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Subgroup Count", OperandQuantifier.Default))), + 329 to Instruction("OpMemoryNamedBarrier", arrayOf(Operand(IdRef(), "Named Barrier", OperandQuantifier.Default), Operand(IdScope(), "Memory", OperandQuantifier.Default), Operand(IdMemorySemantics(), "Semantics", OperandQuantifier.Default))), + 330 to Instruction("OpModuleProcessed", arrayOf(Operand(LiteralString(), "Process", OperandQuantifier.Default))), + 331 to Instruction("OpExecutionModeId", arrayOf(Operand(IdRef(), "Entry Point", OperandQuantifier.Default), Operand(EnumType(ExecutionMode::class.java, ExecutionMode.values(), ExecutionMode.Companion, ExecutionModeParameterFactory.defaultInst), "Mode", OperandQuantifier.Default))), + 332 to Instruction("OpDecorateId", arrayOf(Operand(IdRef(), "Target", OperandQuantifier.Default), Operand(EnumType(Decoration::class.java, Decoration.values(), Decoration.Companion, DecorationParameterFactory.defaultInst), "", OperandQuantifier.Default))), + 4421 to Instruction("OpSubgroupBallotKHR", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Predicate", OperandQuantifier.Default))), + 4422 to Instruction("OpSubgroupFirstInvocationKHR", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default))), + 4428 to Instruction("OpSubgroupAllKHR", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Predicate", OperandQuantifier.Default))), + 4429 to Instruction("OpSubgroupAnyKHR", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Predicate", OperandQuantifier.Default))), + 4430 to Instruction("OpSubgroupAllEqualKHR", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Predicate", OperandQuantifier.Default))), + 4432 to Instruction("OpSubgroupReadInvocationKHR", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default), Operand(IdRef(), "Index", OperandQuantifier.Default))), + 5000 to Instruction("OpGroupIAddNonUniformAMD", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(EnumType(GroupOperation::class.java, GroupOperation.values(), GroupOperation.Companion, GroupOperationParameterFactory.defaultInst), "Operation", OperandQuantifier.Default), Operand(IdRef(), "X", OperandQuantifier.Default))), + 5001 to Instruction("OpGroupFAddNonUniformAMD", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(EnumType(GroupOperation::class.java, GroupOperation.values(), GroupOperation.Companion, GroupOperationParameterFactory.defaultInst), "Operation", OperandQuantifier.Default), Operand(IdRef(), "X", OperandQuantifier.Default))), + 5002 to Instruction("OpGroupFMinNonUniformAMD", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(EnumType(GroupOperation::class.java, GroupOperation.values(), GroupOperation.Companion, GroupOperationParameterFactory.defaultInst), "Operation", OperandQuantifier.Default), Operand(IdRef(), "X", OperandQuantifier.Default))), + 5003 to Instruction("OpGroupUMinNonUniformAMD", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(EnumType(GroupOperation::class.java, GroupOperation.values(), GroupOperation.Companion, GroupOperationParameterFactory.defaultInst), "Operation", OperandQuantifier.Default), Operand(IdRef(), "X", OperandQuantifier.Default))), + 5004 to Instruction("OpGroupSMinNonUniformAMD", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(EnumType(GroupOperation::class.java, GroupOperation.values(), GroupOperation.Companion, GroupOperationParameterFactory.defaultInst), "Operation", OperandQuantifier.Default), Operand(IdRef(), "X", OperandQuantifier.Default))), + 5005 to Instruction("OpGroupFMaxNonUniformAMD", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(EnumType(GroupOperation::class.java, GroupOperation.values(), GroupOperation.Companion, GroupOperationParameterFactory.defaultInst), "Operation", OperandQuantifier.Default), Operand(IdRef(), "X", OperandQuantifier.Default))), + 5006 to Instruction("OpGroupUMaxNonUniformAMD", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(EnumType(GroupOperation::class.java, GroupOperation.values(), GroupOperation.Companion, GroupOperationParameterFactory.defaultInst), "Operation", OperandQuantifier.Default), Operand(IdRef(), "X", OperandQuantifier.Default))), + 5007 to Instruction("OpGroupSMaxNonUniformAMD", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdScope(), "Execution", OperandQuantifier.Default), Operand(EnumType(GroupOperation::class.java, GroupOperation.values(), GroupOperation.Companion, GroupOperationParameterFactory.defaultInst), "Operation", OperandQuantifier.Default), Operand(IdRef(), "X", OperandQuantifier.Default))), + 5011 to Instruction("OpFragmentMaskFetchAMD", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default))), + 5012 to Instruction("OpFragmentFetchAMD", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(IdRef(), "Fragment Index", OperandQuantifier.Default))), + 5571 to Instruction("OpSubgroupShuffleINTEL", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Data", OperandQuantifier.Default), Operand(IdRef(), "InvocationId", OperandQuantifier.Default))), + 5572 to Instruction("OpSubgroupShuffleDownINTEL", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Current", OperandQuantifier.Default), Operand(IdRef(), "Next", OperandQuantifier.Default), Operand(IdRef(), "Delta", OperandQuantifier.Default))), + 5573 to Instruction("OpSubgroupShuffleUpINTEL", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Previous", OperandQuantifier.Default), Operand(IdRef(), "Current", OperandQuantifier.Default), Operand(IdRef(), "Delta", OperandQuantifier.Default))), + 5574 to Instruction("OpSubgroupShuffleXorINTEL", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Data", OperandQuantifier.Default), Operand(IdRef(), "Value", OperandQuantifier.Default))), + 5575 to Instruction("OpSubgroupBlockReadINTEL", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Ptr", OperandQuantifier.Default))), + 5576 to Instruction("OpSubgroupBlockWriteINTEL", arrayOf(Operand(IdRef(), "Ptr", OperandQuantifier.Default), Operand(IdRef(), "Data", OperandQuantifier.Default))), + 5577 to Instruction("OpSubgroupImageBlockReadINTEL", arrayOf(Operand(IdResultType(), "", OperandQuantifier.Default), Operand(IdResult(), "", OperandQuantifier.Default), Operand(IdRef(), "Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default))), + 5578 to Instruction("OpSubgroupImageBlockWriteINTEL", arrayOf(Operand(IdRef(), "Image", OperandQuantifier.Default), Operand(IdRef(), "Coordinate", OperandQuantifier.Default), Operand(IdRef(), "Data", OperandQuantifier.Default))), + ) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/export/spirv/Meta.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/export/spirv/Meta.kt new file mode 100644 index 00000000..60428900 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/export/spirv/Meta.kt @@ -0,0 +1,31 @@ +package io.github.deficuet.unitykt.internal.export.spirv + +internal class Meta private constructor() { + internal data class ToolInfo(val vendor: String, val toolName: String = "") + + companion object { + internal const val magic = 119734787u + internal val tools by lazy { + mapOf( + 0 to ToolInfo("Khronos"), + 1 to ToolInfo("LunarG"), + 2 to ToolInfo("Valve"), + 3 to ToolInfo("Codeplay"), + 4 to ToolInfo("NVIDIA"), + 5 to ToolInfo("ARM"), + 6 to ToolInfo("Khronos", "LLVM/SPIR-V Translator"), + 7 to ToolInfo("Khronos", "SPIR-V Tools Assembler"), + 8 to ToolInfo("Khronos", "Glslang Reference Front End"), + 9 to ToolInfo("Qualcomm"), + 10 to ToolInfo("AMD"), + 11 to ToolInfo("Intel"), + 12 to ToolInfo("Imagination"), + 13 to ToolInfo("Google", "Shaderc over Glslang"), + 14 to ToolInfo("Google", "spiregg"), + 15 to ToolInfo("Google", "rspirv"), + 16 to ToolInfo("X_LEGEND", "Mesa-IR/SPIR-V Translator"), + 17 to ToolInfo("Khronos", "SPIR-V Tools Linker") + ) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/export/spirv/Module.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/export/spirv/Module.kt similarity index 54% rename from src/main/kotlin/io/github/deficuet/unitykt/export/spirv/Module.kt rename to src/main/kotlin/io/github/deficuet/unitykt/internal/export/spirv/Module.kt index 226bd2eb..6c054027 100644 --- a/src/main/kotlin/io/github/deficuet/unitykt/export/spirv/Module.kt +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/export/spirv/Module.kt @@ -1,4 +1,4 @@ -package io.github.deficuet.unitykt.export.spirv +package io.github.deficuet.unitykt.internal.export.spirv import io.github.deficuet.unitykt.util.EndianByteArrayReader import java.nio.ByteOrder @@ -7,8 +7,9 @@ internal class Module private constructor( val header: Header, val instructions: List ) { - data class Header( - val version: Version, + internal data class Header( + val versionMajor: Int, + val versionMinor: Int, val generatorName: String, val generatorVendor: String, val generatorVersion: Int, @@ -17,10 +18,6 @@ internal class Module private constructor( ) private val objects = mutableMapOf() - private val debugInstructions = setOf( - "OpSourceContinued", "OpSource", "OpSourceExtension", "OpName", - "OpMemberName", "OpString", "OpLine", "OpNoLine", "OpModuleProcessed" - ) init { val debugInstructions = mutableListOf() @@ -35,20 +32,21 @@ internal class Module private constructor( continue } if (parsedInst.instruction.name.startsWith("OpType")) { - parsedInst.processType() + processType(parsedInst) } parsedInst.resolveResultType(objects) - if (parsedInst.hasResult) { - objects[parsedInst.resultId] = parsedInst + val id = parsedInst.getResultId() + if (id != 0u) { + objects[id] = parsedInst } when (parsedInst.instruction.name) { "OpSpecConstant", "OpConstant" -> { val t = parsedInst.resultType assert(t is ScalarType) - val constant = (parsedInst.resultType as ScalarType).convertConstant( - parsedInst.words, 3 - ) - parsedInst.operands[2].value = constant + val constant = convertConstant(parsedInst.resultType as ScalarType, parsedInst.words) + if (constant != null) { + parsedInst.operands[2].value = constant + } parsedInst.value = constant } } @@ -70,24 +68,23 @@ internal class Module private constructor( } } - private val ParsedInstruction.isDebug get() = debugInstructions.contains(instruction.name) - - private fun ParsedInstruction.processType() { - when(instruction.name) { + private fun processType(p: ParsedInstruction) { + when(p.instruction.name) { "OpTypeInt" -> { - resultType = IntegerType(words[2].toInt(), words[3] == 1u) + p.resultType = IntegerType(p.words[2].toInt(), p.words[3] == 1u) } "OpTypeFloat" -> { - resultType = FloatingPointType(words[2].toInt()) + p.resultType = FloatingPointType(p.words[2].toInt()) } "OpTypeVector" -> { - resultType = VectorType(objects[words[2]]!!.resultType as ScalarType, words[3].toInt()) + p.resultType = VectorType(objects.getValue(p.words[2]).resultType as ScalarType, p.words[3].toInt()) } "OpTypeMatrix" -> { - resultType = MatrixType(objects[words[2]]!!.resultType as VectorType, words[3].toInt()) + p.resultType = MatrixType(objects.getValue(p.words[2]).resultType as VectorType, p.words[3].toInt()) } "OpTypeArray" -> { - val constant = objects[words[3]]!!.value + val i = objects.getValue(p.words[3]) + val constant = i.value var size = 0 when (constant) { is UShort -> size = constant.toInt() @@ -97,63 +94,58 @@ internal class Module private constructor( is Int -> size = constant is Long -> size = constant.toInt() } - resultType = ArrayType(objects[words[2]]!!.resultType!!, size) + p.resultType = ArrayType(i.resultType!!, size) } "OpTypeRuntimeArray" -> { - resultType = RuntimeArrayType() + p.resultType = RuntimeArrayType() } - "OpTypeBool" -> resultType = BoolType() - "OpTypeOpaque" -> resultType = OpaqueType() - "OpTypeVoid" -> resultType = VoidType() + "OpTypeBool" -> p.resultType = BoolType() + "OpTypeOpaque" -> p.resultType = OpaqueType() + "OpTypeVoid" -> p.resultType = VoidType() "OpTypeImage" -> { - val dim = operands[2].getSingleEnumValue() - val isArray = (operands[4].value as UInt) != 0u - val isMultiSampled = (operands[5].value as UInt) != 0u - resultType = ImageType( + val dim = p.operands[2].getSingleEnumValue() + val isArray = (p.operands[4].value as UInt) != 0u + val isMultiSampled = (p.operands[5].value as UInt) != 0u + p.resultType = ImageType( dim, isArray, isMultiSampled, - if (operands.size > 8) operands[8].getSingleEnumValue() else AccessQualifier.ReadOnly + if (p.operands.size > 8) p.operands[8].getSingleEnumValue() else AccessQualifier.ReadOnly ) } - "OpTypeSampler" -> resultType = SamplerType() - "OpTypeSampledImage" -> resultType = SampledImageType(objects[words[2]]!!.resultType as ImageType) + "OpTypeSampler" -> p.resultType = SamplerType() + "OpTypeSampledImage" -> p.resultType = SampledImageType(objects.getValue(p.words[2]).resultType as ImageType) "OpTypeFunction" -> { - val parameterTypes = mutableListOf() - for (j in 3 until words.size) { - parameterTypes.add(objects[words[j]]!!.resultType!!) - } - resultType = FunctionType() + p.resultType = FunctionType() } - "OpTypeForwardPointer" -> resultType = PointerType(StorageClass.of(words[2])) + "OpTypeForwardPointer" -> p.resultType = PointerType(StorageClass.of(p.words[2])) "OpTypePointer" -> { - if (words[1] in objects) { - val pt = resultType as PointerType - assert(pt.storageClass == StorageClass.of(words[2])) - pt.resolveForwardReference(objects[words[3]]!!.resultType!!) + if (p.words[1] in objects) { + val pt = p.resultType as PointerType + assert(pt.storageClass == StorageClass.of(p.words[2])) + pt.resolveForwardReference(objects.getValue(p.words[3]).resultType!!) } else { - resultType = PointerType(StorageClass.of(words[2]), objects[words[3]]!!.resultType) + p.resultType = PointerType(StorageClass.of(p.words[2]), objects.getValue(p.words[3]).resultType) } } "OpTypeStruct" -> { - val member = mutableListOf() - for (j in 2 until words.size) { - member.add(objects[words[j]]!!.resultType!!) + val member = Array(p.words.size - 2) { + objects.getValue(p.words[it + 2]).resultType!! } - resultType = StructType(member) + p.resultType = StructType(member) } } } - private fun ScalarType.convertConstant(words: Array, index: Int): Any { - when (this) { + private fun convertConstant(s: ScalarType, words: Array, index: Int = 3): Any? { + when (s) { is IntegerType -> { - if (signed) { - when (width) { + if (s.signed) { + when (s.width) { 16 -> return words[index].toShort() 32 -> return words[index].toInt() 64 -> return words[index].toULong().or(words[index + 1].toULong().shl(32)).toLong() } } else { - when (width) { + when (s.width) { 16 -> return words[index].toUShort() 32 -> return words[index] 64 -> return words[index].toULong().or(words[index + 1].toULong().shl(32)) @@ -162,7 +154,7 @@ internal class Module private constructor( throw IllegalStateException("Can't construct integer literal.") } is FloatingPointType -> { - return when (width) { + return when (s.width) { 32 -> Float.fromBits(words[0].toInt()) 64 -> Double.fromBits( words[index].toULong().or(words[index + 1].toULong().shl(32)).toLong() @@ -171,41 +163,58 @@ internal class Module private constructor( } } } - throw IllegalStateException("Can't construct literal constant.") + return null } + private val ParsedInstruction.isDebug get() = debugInstructions.contains(instruction.name) + companion object { - fun readFrom(data: ByteArray): Module { - val reader = EndianByteArrayReader(data, endian = ByteOrder.LITTLE_ENDIAN) - reader += 4 //magic - val versionNum = reader.readUInt() - val majorVersion = versionNum.shr(16).toInt() - val minorVersion = versionNum.shr(8).and(0xFFu).toInt() - val version = Version(majorVersion, minorVersion) - val generatorMagic = reader.readUInt() + internal fun readFrom(data: ByteArray): Module { + val reader = EndianByteArrayReader(data) + val magic = reader.readUInt32() + if (magic != Meta.magic) { + if ( + magic.shl(24) + .or(magic.and(0xFF00u).shl(8)) + .or(magic.shr(8).and(0xFF00u)) + .or(magic.shr(24)) != Meta.magic + ) { + throw IllegalStateException("Invalid Spir-V magic number") + } + reader.endian = ByteOrder.LITTLE_ENDIAN + } + val versionNum = reader.readUInt32() + val generatorMagic = reader.readUInt32() val generatorTool = generatorMagic.shr(16).toInt() var vendor = "unknown"; var name = "" - Meta.Tools.of(generatorTool)?.let { + Meta.tools[generatorTool]?.let { vendor = it.vendor name = it.toolName } val header = Header( - version, name, vendor, generatorMagic.and(0xFFFFu).toInt(), - reader.readUInt(), reader.readUInt() + versionNum.shr(16).toInt(), + versionNum.shr(8).and(0xFFu).toInt(), + name, vendor, generatorMagic.and(0xFFFFu).toInt(), + reader.readUInt32(), reader.readUInt32() ) val instructions = mutableListOf() while (reader.position != reader.length) { - val instructionStart = reader.readUInt() + val instructionStart = reader.readUInt32() val wordCount = instructionStart.shr(16).toUShort() val opCode = instructionStart.and(0xFFFFu).toInt() val words = Array(wordCount.toInt()) { 0u } words[0] = instructionStart for (i in 1 until wordCount.toInt()) { - words[i] = reader.readUInt() + words[i] = reader.readUInt32() } instructions.add(ParsedInstruction(opCode, words)) } return Module(header, instructions) } + + private val debugInstructions = setOf( + "OpSourceContinued", "OpSource", "OpSourceExtension", "OpName", + "OpMemberName", "OpString", "OpLine", "OpNoLine", "OpModuleProcessed" + ) } } \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/export/spirv/OperandType.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/export/spirv/OperandType.kt new file mode 100644 index 00000000..dd06bb85 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/export/spirv/OperandType.kt @@ -0,0 +1,178 @@ +package io.github.deficuet.unitykt.internal.export.spirv + +import io.github.deficuet.unitykt.cast +import io.github.deficuet.unitykt.enums.FlagsAttributeEnum +import io.github.deficuet.unitykt.enums.NumericalEnumMap + +internal data class ReadValueResult(val wordsUsed: Int, val value: Any) + +internal open class OperandType { + open fun readValue(words: Array, index: Int): ReadValueResult { + return ReadValueResult(1, this::class.java) + } +} + +internal open class Literal: OperandType() + +internal open class LiteralNumber: Literal() + +internal class LiteralInteger: LiteralNumber() { + override fun readValue(words: Array, index: Int): ReadValueResult { + return ReadValueResult(1, words[index]) + } +} + +internal class LiteralString: Literal() { + override fun readValue(words: Array, index: Int): ReadValueResult { + var wordsUsed = 1; var bytesUsed = 0 + val bytes = ByteArray((words.size - index) * 4) + readWord@ + for (i in index until words.size) { + val word = words[i] + for (j in 0..3) { + val b = word.shr(j * 8).and(0xFFu) + if (b == 0u) break@readWord + else bytes[bytesUsed++] = b.toByte() + } + wordsUsed++ + } + return ReadValueResult(wordsUsed, bytes.decodeToString(0, bytesUsed)) + } +} + +internal class LiteralContextDependentNumber: Literal() + +internal class LiteralExtInstInteger: Literal() { + override fun readValue(words: Array, index: Int): ReadValueResult { + return ReadValueResult(1, words[index]) + } +} + +internal class LiteralSpecConstantOpInteger: Literal() { + override fun readValue(words: Array, index: Int): ReadValueResult { + val result = mutableListOf() + for (i in index until words.size) { + result.add(ObjectReference(words[i])) + } + return ReadValueResult(words.size - index, result) + } +} + +internal class Parameter(vararg types: OperandType) { + val operandTypes = types +} + +internal open class ParameterFactory { + open fun createParameter(value: UInt): Parameter? { + return null + } + + companion object { + internal val defaultInst = ParameterFactory() + } +} + +internal class EnumType, P: ParameterFactory>( + private val enumClass: Class, + private val enumValues: Array, + private val enumCompanion: Any, + private val factory: P +): OperandType() { + override fun readValue(words: Array, index: Int): ReadValueResult { + var wordsUsed = 0 + val value: EnumOperandValue + if (FlagsAttributeEnum.flagsAttributeEnumClass.isAssignableFrom(enumClass)) { + val result = mutableMapOf>() + for (enum in enumValues) { + val bit = enum.cast().value + if (words[index].and(bit) != 0u || (bit == 0u && words[index] == 0u)) { + result[bit] = factory.createParameter(bit)?.let { param -> + Array(param.operandTypes.size) { + val (pWordsUsed, pValue) = param.operandTypes[it].readValue( + words, 1 + wordsUsed + ) + wordsUsed += pWordsUsed + pValue + } + } ?: emptyArray() + } + } + value = BitEnumOperandValue(result, enumClass) + } else { + val result = factory.createParameter(words[index])?.let { param -> + Array(param.operandTypes.size) { + val (pWordsUsed, pValue) = param.operandTypes[it].readValue( + words, 1 + wordsUsed + ) + wordsUsed += pWordsUsed + pValue + } + } ?: emptyArray() + value = ValueEnumOperandValue( + enumCompanion.cast>().of(words[index]), + result, enumClass + ) + } + return ReadValueResult(wordsUsed, value) + } + + companion object { + fun > new( + enumClass: Class, + enumValues: Array, + enumCompanion: Any + ): EnumType { + return EnumType(enumClass, enumValues, enumCompanion, ParameterFactory.defaultInst) + } + } +} + +internal class IdScope: OperandType() { + override fun readValue(words: Array, index: Int): ReadValueResult { + return ReadValueResult(1, Scope.of(words[index])) + } +} + +internal class IdMemorySemantics: OperandType() { + override fun readValue(words: Array, index: Int): ReadValueResult { + return ReadValueResult(1, MemorySemantics.of(words[index])) + } +} + +internal open class IdType: OperandType() { + override fun readValue(words: Array, index: Int): ReadValueResult { + return ReadValueResult(1, words[index]) + } +} + +internal class IdResult: IdType() { + override fun readValue(words: Array, index: Int): ReadValueResult { + return ReadValueResult(1, ObjectReference(words[index])) + } +} + +internal class IdRef: IdType() { + override fun readValue(words: Array, index: Int): ReadValueResult { + return ReadValueResult(1, ObjectReference(words[index])) + } +} + +internal class IdResultType: IdType() + +internal class PairIdRefIdRef: OperandType() { + override fun readValue(words: Array, index: Int): ReadValueResult { + return ReadValueResult(2, Pair(ObjectReference(words[index]), ObjectReference(words[index + 1]))) + } +} + +internal class PairIdRefLiteralInteger: OperandType() { + override fun readValue(words: Array, index: Int): ReadValueResult { + return ReadValueResult(2, Pair(ObjectReference(words[index]), words[index + 1])) + } +} + +internal class PairLiteralIntegerIdRef: OperandType() { + override fun readValue(words: Array, index: Int): ReadValueResult { + return ReadValueResult(2, Pair(words[index], ObjectReference(words[index + 1]))) + } +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/export/spirv/ParsedInstruction.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/export/spirv/ParsedInstruction.kt similarity index 75% rename from src/main/kotlin/io/github/deficuet/unitykt/export/spirv/ParsedInstruction.kt rename to src/main/kotlin/io/github/deficuet/unitykt/internal/export/spirv/ParsedInstruction.kt index 5e57dcf7..bc7e7a89 100644 --- a/src/main/kotlin/io/github/deficuet/unitykt/export/spirv/ParsedInstruction.kt +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/export/spirv/ParsedInstruction.kt @@ -1,26 +1,18 @@ -package io.github.deficuet.unitykt.export.spirv +package io.github.deficuet.unitykt.internal.export.spirv -import io.github.deficuet.unitykt.util.Reference +import io.github.deficuet.unitykt.cast internal class ParsedInstruction(opCode: Int, val words: Array) { - val instruction = Instruction.fromOpcode.getValue(opCode) + val instruction = Instruction.opcodeMap.getValue(opCode) val operands = mutableListOf() - val resultId: UInt get() { - for (i in instruction.operands.indices) { - if (instruction.operands[i].type is IdResult) { - return operands[i].id - } - } - return 0u - } - val hasResult get() = resultId != 0u var resultType: Type? = null + var name: String = "" var value: Any? = null - init { parseOperands() } + init { parseOperand() } - private fun parseOperands() { + private fun parseOperand() { if (instruction.operands.isEmpty()) return var currentWord = 1 var currentOperand = 0 @@ -29,20 +21,19 @@ internal class ParsedInstruction(opCode: Int, val words: Array) { while (currentWord < words.size) { val operand = instruction.operands[currentOperand] - val valueRef = Reference() - val wordUsed = operand.type.readValue(words, currentWord, valueRef) + val (wordUsed, value) = operand.type.readValue(words, currentWord) if (operand.quantifier == OperandQuantifier.Varying) { - varyingOperandValues.add(valueRef.value) + varyingOperandValues.add(value) varyingOperand = operand } else { - operands.add(ParsedOperand(valueRef.value, operand)) + operands.add(ParsedOperand(value)) } currentWord += wordUsed if (operand.quantifier != OperandQuantifier.Varying) currentOperand++ } if (varyingOperand != null) { val varOperandValue = VaryingOperandValue(varyingOperandValues) - operands.add(ParsedOperand(varOperandValue, varyingOperand)) + operands.add(ParsedOperand(varOperandValue)) } } @@ -54,17 +45,25 @@ internal class ParsedInstruction(opCode: Int, val words: Array) { fun resolveReference(objects: Map) { for (operand in operands) { - if (operand.value is ObjectReference) { - (operand.value as ObjectReference).apply { reference = objects.getValue(id) } + val v = operand.value + if (v is ObjectReference) { + v.apply { reference = objects.getValue(id) } } } } + + fun getResultId(): UInt { + for (i in instruction.operands.indices) { + if (instruction.operands[i].type is IdResult) { + return operands[i].id + } + } + return 0u + } } -internal class ParsedOperand( - var value: Any, val operand: Operand -) { - val id get() = (value as ObjectReference).id +internal class ParsedOperand(var value: Any) { + val id get() = value.cast().id inline fun > getSingleEnumValue(): T { val v = value as ValueEnumOperandValue<*> @@ -112,4 +111,4 @@ internal class ValueEnumOperandValue>( internal class BitEnumOperandValue>( val values: Map>, override val enumClass: Class -): EnumOperandValue() \ No newline at end of file +): EnumOperandValue() diff --git a/src/main/kotlin/io/github/deficuet/unitykt/export/spirv/Type.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/export/spirv/Type.kt similarity index 93% rename from src/main/kotlin/io/github/deficuet/unitykt/export/spirv/Type.kt rename to src/main/kotlin/io/github/deficuet/unitykt/internal/export/spirv/Type.kt index 0cc3e45a..5486db3f 100644 --- a/src/main/kotlin/io/github/deficuet/unitykt/export/spirv/Type.kt +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/export/spirv/Type.kt @@ -1,4 +1,4 @@ -package io.github.deficuet.unitykt.export.spirv +package io.github.deficuet.unitykt.internal.export.spirv internal abstract class Type { open fun toString(builder: StringBuilder): StringBuilder = builder.append(toString()) @@ -34,14 +34,13 @@ internal class FloatingPointType(val width: Int): ScalarType() { } } -internal class VectorType(private val componentType: ScalarType, val componentCount: Int): Type() { +internal class VectorType(private val componentType: ScalarType, private val componentCount: Int): Type() { override fun toString(): String { return "${componentType}_$componentCount" } } internal class MatrixType(private val columnType: VectorType, private val columnCount: Int): Type() { - val rowCount by columnType::componentCount override fun toString(): String { return "${columnType}x$columnCount" } @@ -98,7 +97,7 @@ internal class ArrayType(private val elementType: Type, private val elementCount internal class RuntimeArrayType: Type() -internal class StructType(private val memberTypes: List): Type() { +internal class StructType(private val memberTypes: Array): Type() { private val memberNames = Array(memberTypes.size) { "" } operator fun set(member: UInt, name: String) { @@ -138,7 +137,3 @@ internal class PointerType(val storageClass: StorageClass, var type: Type? = nul } internal class FunctionType: Type() - -internal class PipeStorage : Type() - -internal class NamedBarrier : Type() \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/export/spirv/core.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/export/spirv/core.kt similarity index 66% rename from src/main/kotlin/io/github/deficuet/unitykt/export/spirv/core.kt rename to src/main/kotlin/io/github/deficuet/unitykt/internal/export/spirv/core.kt index abfea89b..35b65951 100644 --- a/src/main/kotlin/io/github/deficuet/unitykt/export/spirv/core.kt +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/export/spirv/core.kt @@ -1,11 +1,14 @@ -@file:Suppress("unused", "EnumEntryName") +package io.github.deficuet.unitykt.internal.export.spirv -package io.github.deficuet.unitykt.export.spirv +import io.github.deficuet.unitykt.enums.FlagsAttributeEnum +import io.github.deficuet.unitykt.enums.FlagsAttributeEnumCompanion +import io.github.deficuet.unitykt.enums.NumericalEnum +import io.github.deficuet.unitykt.enums.NumericalEnumCompanion +import io.github.deficuet.unitykt.util.isPowerOf2 internal enum class ImageOperands( - override val exp: Int, val parameter: Parameter? -): FlagsAttributeEnum -{ + override val bitPos: Int, val parameter: Parameter? +): FlagsAttributeEnum { None(-1, null), Bias(0, Parameter(IdRef())), Lod(1, Parameter(IdRef())), @@ -16,18 +19,19 @@ internal enum class ImageOperands( Sample(6, Parameter(IdRef())), MinLod(7, Parameter(IdRef())); - companion object: FlagsAttributeEnumCompanion() + companion object: FlagsAttributeEnumCompanion(ImageOperands::class.java, values(), None) } internal class ImageOperandsParameterFactory: ParameterFactory() { override fun createParameter(value: UInt): Parameter? { - return ImageOperands.values().firstOrNull { it.numeric == value.toInt() }?.parameter + if (!isPowerOf2(value)) return null + return ImageOperands.values().firstOrNull { it.value == value }?.parameter } + + companion object { internal val defaultInst = ImageOperandsParameterFactory() } } -internal enum class FPFastMathMode( - override val exp: Int -): FlagsAttributeEnum { +internal enum class FPFastMathMode(override val bitPos: Int): FlagsAttributeEnum { None(-1), NotNaN(0), NotInf(1), @@ -35,51 +39,58 @@ internal enum class FPFastMathMode( AllowRecip(3), Fast(4); - companion object: FlagsAttributeEnumCompanion() + companion object: FlagsAttributeEnumCompanion(FPFastMathMode::class.java, values(), None) } -internal class FPFastMathModeParameterFactory: ParameterFactory() - -internal enum class SelectionControl(override val exp: Int): FlagsAttributeEnum { +internal enum class SelectionControl(override val bitPos: Int): FlagsAttributeEnum { None(-1), Flatten(0), DontFlatten(1); - companion object: FlagsAttributeEnumCompanion() + companion object: FlagsAttributeEnumCompanion(SelectionControl::class.java, values(), None) } -internal class SelectionControlParameterFactory : ParameterFactory() +internal class SelectionControlParameterFactory: ParameterFactory() { + companion object { internal val defaultInst = SelectionControlParameterFactory() } +} internal enum class LoopControl( - override val exp: Int, + override val bitPos: Int, val parameter: Parameter? = null -): FlagsAttributeEnum { +): FlagsAttributeEnum { None(-1), Unroll(0), DontUnroll(1), DependencyInfinite(2), DependencyLength(3, Parameter(LiteralInteger())); - companion object: FlagsAttributeEnumCompanion() + companion object: FlagsAttributeEnumCompanion(LoopControl::class.java, values(), None) } internal class LoopControlParameterFactory: ParameterFactory() { override fun createParameter(value: UInt): Parameter? { - return LoopControl.values().firstOrNull { it.numeric == value.toInt() }?.parameter + if (!isPowerOf2(value)) return null + return LoopControl.values().firstOrNull { it.value == value }?.parameter } + + companion object { internal val defaultInst = LoopControlParameterFactory() } } -internal enum class FunctionControl(override val exp: Int): FlagsAttributeEnum { +internal enum class FunctionControl(override val bitPos: Int): FlagsAttributeEnum { None(-1), Inline(0), DontInline(1), Pure(2), - Const(3), + Const(3); + + companion object: FlagsAttributeEnumCompanion(FunctionControl::class.java, values(), None) } -internal class FunctionControlParameterFactory: ParameterFactory() +internal class FunctionControlParameterFactory: ParameterFactory() { + companion object { internal val defaultInst = FunctionControlParameterFactory() } +} -internal enum class MemorySemantics(override val exp: Int): FlagsAttributeEnum { +internal enum class MemorySemantics(override val bitPos: Int): FlagsAttributeEnum { Relaxed(-1), None(-1), Acquire(1), @@ -93,38 +104,31 @@ internal enum class MemorySemantics(override val exp: Int): FlagsAttributeEnum() + companion object: FlagsAttributeEnumCompanion(MemorySemantics::class.java, values(), Relaxed) } -internal class MemorySemanticsParameterFactory: ParameterFactory() - internal enum class MemoryAccess( - override val exp: Int, + override val bitPos: Int, val parameter: Parameter? = null -): FlagsAttributeEnum { +): FlagsAttributeEnum { None(-1), Volatile(0), Aligned(1, Parameter(LiteralInteger())), Nontemporal(2); - companion object: FlagsAttributeEnumCompanion() + companion object: FlagsAttributeEnumCompanion(MemoryAccess::class.java, values(), None) } internal class MemoryAccessParameterFactory: ParameterFactory() { override fun createParameter(value: UInt): Parameter? { - return MemoryAccess.values().firstOrNull { it.numeric == value.toInt() }?.parameter + if (!isPowerOf2(value)) return null + return MemoryAccess.values().firstOrNull { it.value == value }?.parameter } -} - -internal enum class KernelProfilingInfo(override val exp: Int): FlagsAttributeEnum { - None(-1), - CmdExecTime(0); - companion object: FlagsAttributeEnumCompanion() + companion object { internal val defaultInst = MemoryAccessParameterFactory() } } -internal class KernelProfilingInfoParameterFactory: ParameterFactory() - +@Suppress("EnumEntryName") internal enum class SourceLanguage(override val id: UInt): NumericalEnum { Unknown(0u), ESSL(1u), @@ -133,10 +137,12 @@ internal enum class SourceLanguage(override val id: UInt): NumericalEnum { OpenCL_CPP(4u), HLSL(5u); - companion object: NumericalEnumCompanion() + companion object: NumericalEnumCompanion(values(), Unknown) } -internal class SourceLanguageParameterFactory: ParameterFactory() +internal class SourceLanguageParameterFactory: ParameterFactory() { + companion object { internal val defaultInst = SourceLanguageParameterFactory() } +} internal enum class ExecutionModel(override val id: UInt): NumericalEnum { Vertex(0u), @@ -147,27 +153,36 @@ internal enum class ExecutionModel(override val id: UInt): NumericalEnum { GLCompute(5u), Kernel(6u); - companion object: NumericalEnumCompanion() + companion object: NumericalEnumCompanion(values(), Vertex) +} + +internal class ExecutionModelParameterFactory: ParameterFactory() { + companion object { internal val defaultInst = ExecutionModelParameterFactory() } } -internal class ExecutionModelParameterFactory : ParameterFactory() internal enum class AddressingModel(override val id: UInt): NumericalEnum { Logical(0u), Physical32(1u), Physical64(2u); - companion object: NumericalEnumCompanion() + companion object: NumericalEnumCompanion(values(), Logical) +} + +internal class AddressingModelParameterFactory: ParameterFactory() { + companion object { internal val defaultInst = AddressingModelParameterFactory() } } -internal class AddressingModelParameterFactory : ParameterFactory() internal enum class MemoryModel(override val id: UInt): NumericalEnum { Simple(0u), GLSL450(1u), OpenCL(2u); - companion object: NumericalEnumCompanion() + companion object: NumericalEnumCompanion(values(), Simple) +} + +internal class MemoryModelParameterFactory: ParameterFactory() { + companion object { internal val defaultInst = MemoryModelParameterFactory() } } -internal class MemoryModelParameterFactory : ParameterFactory() internal enum class ExecutionMode( override val id: UInt, @@ -214,13 +229,15 @@ internal enum class ExecutionMode( PostDepthCoverage(4446u), StencilRefReplacingEXT(5027u); - companion object: NumericalEnumCompanion() + companion object: NumericalEnumCompanion(values(), Invocations) } internal class ExecutionModeParameterFactory: ParameterFactory() { override fun createParameter(value: UInt): Parameter? { - return ExecutionMode.values().firstOrNull { it.id == value }?.parameter + return ExecutionMode.cacheTable[value]?.parameter } + + companion object { internal val defaultInst = ExecutionModeParameterFactory() } } internal enum class StorageClass(override val id: UInt): NumericalEnum { @@ -238,10 +255,12 @@ internal enum class StorageClass(override val id: UInt): NumericalEnum { Image(11u), StorageBuffer(12u); - companion object: NumericalEnumCompanion() + companion object: NumericalEnumCompanion(values(), UniformConstant) } -internal class StorageClassParameterFactory: ParameterFactory() +internal class StorageClassParameterFactory: ParameterFactory() { + companion object { internal val defaultInst = StorageClassParameterFactory() } +} internal enum class Dim(override val id: UInt): NumericalEnum { Dim1D(0u), @@ -252,10 +271,12 @@ internal enum class Dim(override val id: UInt): NumericalEnum { Buffer(5u), SubpassData(6u); - companion object: NumericalEnumCompanion() + companion object: NumericalEnumCompanion(values(), Dim1D) } -internal class DimParameterFactory: ParameterFactory() +internal class DimParameterFactory: ParameterFactory() { + companion object { internal val defaultInst = DimParameterFactory() } +} internal enum class SamplerAddressingMode(override val id: UInt): NumericalEnum { None(0u), @@ -264,19 +285,23 @@ internal enum class SamplerAddressingMode(override val id: UInt): NumericalEnum< Repeat(3u), RepeatMirrored(4u); - companion object: NumericalEnumCompanion() + companion object: NumericalEnumCompanion(values(), None) } -internal class SamplerAddressingModeParameterFactory: ParameterFactory() +internal class SamplerAddressingModeParameterFactory: ParameterFactory() { + companion object { internal val defaultInst = SamplerAddressingModeParameterFactory() } +} internal enum class SamplerFilterMode(override val id: UInt): NumericalEnum { Nearest(0u), Linear(1u); - companion object: NumericalEnumCompanion() + companion object: NumericalEnumCompanion(values(), Nearest) } -internal class SamplerFilterModeParameterFactory: ParameterFactory() +internal class SamplerFilterModeParameterFactory: ParameterFactory() { + companion object { internal val defaultInst = SamplerFilterModeParameterFactory() } +} internal enum class ImageFormat(override val id: UInt): NumericalEnum { Unknown(0u), @@ -320,61 +345,12 @@ internal enum class ImageFormat(override val id: UInt): NumericalEnum { R16ui(38u), R8ui(39u); - companion object: NumericalEnumCompanion() -} - -internal class ImageFormatParameterFactory: ParameterFactory() - -internal enum class ImageChannelOrder(override val id: UInt): NumericalEnum { - R(0u), - A(1u), - RG(2u), - RA(3u), - RGB(4u), - RGBA(5u), - BGRA(6u), - ARGB(7u), - Intensity(8u), - Luminance(9u), - Rx(10u), - RGx(11u), - RGBx(12u), - Depth(13u), - DepthStencil(14u), - sRGB(15u), - sRGBx(16u), - sRGBA(17u), - sBGRA(18u), - ABGR(19u); - - companion object: NumericalEnumCompanion() -} - -internal class ImageChannelOrderParameterFactory: ParameterFactory() - -internal enum class ImageChannelDataType(override val id: UInt): NumericalEnum { - SnormInt8(0u), - SnormInt16(1u), - UnormInt8(2u), - UnormInt16(3u), - UnormShort565(4u), - UnormShort555(5u), - UnormInt101010(6u), - SignedInt8(7u), - SignedInt16(8u), - SignedInt32(9u), - UnsignedInt8(10u), - UnsignedInt16(11u), - UnsignedInt32(12u), - HalfFloat(13u), - Float(14u), - UnormInt24(15u), - UnormInt101010_2(16u); - - companion object: NumericalEnumCompanion() -} - -internal class ImageChannelDataTypeParameterFactory: ParameterFactory() + companion object: NumericalEnumCompanion(values(), Unknown) +} + +internal class ImageFormatParameterFactory: ParameterFactory() { + companion object { internal val defaultInst = ImageFormatParameterFactory() } +} internal enum class FPRoundingMode(override val id: UInt): NumericalEnum { RTE(0u), @@ -382,29 +358,27 @@ internal enum class FPRoundingMode(override val id: UInt): NumericalEnum { RTP(2u), RTN(3u); - companion object: NumericalEnumCompanion() + companion object: NumericalEnumCompanion(values(), RTE) } -internal class FPRoundingModeParameterFactory: ParameterFactory() - internal enum class LinkageType(override val id: UInt): NumericalEnum { Export(0u), Import(1u); - companion object: NumericalEnumCompanion() + companion object: NumericalEnumCompanion(values(), Export) } -internal class LinkageTypeParameterFactory: ParameterFactory() - internal enum class AccessQualifier(override val id: UInt): NumericalEnum { ReadOnly(0u), WriteOnly(1u), ReadWrite(2u); - companion object: NumericalEnumCompanion() + companion object: NumericalEnumCompanion(values(), ReadOnly) } -internal class AccessQualifierParameterFactory: ParameterFactory() +internal class AccessQualifierParameterFactory: ParameterFactory() { + companion object { internal val defaultInst = AccessQualifierParameterFactory() } +} internal enum class FunctionParameterAttribute(override val id: UInt): NumericalEnum { Zext(0u), @@ -416,10 +390,100 @@ internal enum class FunctionParameterAttribute(override val id: UInt): Numerical NoWrite(6u), NoReadWrite(7u); - companion object: NumericalEnumCompanion() + companion object: NumericalEnumCompanion(values(), Zext) } -internal class FunctionParameterAttributeParameterFactory: ParameterFactory() +internal enum class Decoration( + override val id: UInt, + val parameter: Parameter? = null +): NumericalEnum { + RelaxedPrecision(0u), + SpecId(1u, Parameter(LiteralInteger())), + Block(2u), + BufferBlock(3u), + RowMajor(4u), + ColMajor(5u), + ArrayStride(6u, Parameter(LiteralInteger())), + MatrixStride(7u, Parameter(LiteralInteger())), + GLSLShared(8u), + GLSLPacked(9u), + CPacked(10u), + BuiltIn0(11u, Parameter(EnumType.new(BuiltIn::class.java, BuiltIn.values(), BuiltIn.Companion))), + NoPerspective(13u), + Flat(14u), + Patch(15u), + Centroid(16u), + Sample(17u), + Invariant(18u), + Restrict(19u), + Aliased(20u), + Volatile(21u), + Constant(22u), + Coherent(23u), + NonWritable(24u), + NonReadable(25u), + Uniform(26u), + SaturatedConversion(28u), + Stream(29u, Parameter(LiteralInteger())), + Location(30u, Parameter(LiteralInteger())), + Component(31u, Parameter(LiteralInteger())), + Index(32u, Parameter(LiteralInteger())), + Binding(33u, Parameter(LiteralInteger())), + DescriptorSet(34u, Parameter(LiteralInteger())), + Offset(35u, Parameter(LiteralInteger())), + XfbBuffer(36u, Parameter(LiteralInteger())), + XfbStride(37u, Parameter(LiteralInteger())), + FuncParamAttr(38u, Parameter( + EnumType.new( + FunctionParameterAttribute::class.java, + FunctionParameterAttribute.values(), + FunctionParameterAttribute.Companion + ) + )), + FPRoundingMode0(39u, Parameter( + EnumType.new( + FPRoundingMode::class.java, + FPRoundingMode.values(), + FPRoundingMode.Companion + ) + )), + FPFastMathMode0(40u, Parameter( + EnumType.new( + FPFastMathMode::class.java, + FPFastMathMode.values(), + FPFastMathMode.Companion + )) + ), + LinkageAttributes(41u, Parameter( + LiteralString(), + EnumType.new( + LinkageType::class.java, + LinkageType.values(), + LinkageType.Companion + ) + )), + NoContraction(42u), + InputAttachmentIndex(43u, Parameter(LiteralInteger())), + Alignment(44u, Parameter(LiteralInteger())), + MaxByteOffset(45u, Parameter(LiteralInteger())), + AlignmentId(46u, Parameter(IdRef())), + MaxByteOffsetId(47u, Parameter(IdRef())), + ExplicitInterpAMD(4999u), + OverrideCoverageNV(5248u), + PassthroughNV(5250u), + ViewportRelativeNV(5252u), + SecondaryViewportRelativeNV(5256u, Parameter(LiteralInteger())); + + companion object: NumericalEnumCompanion(values(), RelaxedPrecision) +} + +internal class DecorationParameterFactory: ParameterFactory() { + override fun createParameter(value: UInt): Parameter? { + return Decoration.values().firstOrNull { it.id == value }?.parameter + } + + companion object { internal val defaultInst = DecorationParameterFactory() } +} internal enum class BuiltIn(override val id: UInt): NumericalEnum { Position(0u), @@ -487,74 +551,7 @@ internal enum class BuiltIn(override val id: UInt): NumericalEnum { PositionPerViewNV(5261u), ViewportMaskPerViewNV(5262u); - companion object: NumericalEnumCompanion() -} - -internal class BuiltInParameterFactory: ParameterFactory() - -internal enum class Decoration( - override val id: UInt, - val parameter: Parameter? = null -): NumericalEnum { - RelaxedPrecision(0u), - SpecId(1u, Parameter(LiteralInteger())), - Block(2u), - BufferBlock(3u), - RowMajor(4u), - ColMajor(5u), - ArrayStride(6u, Parameter(LiteralInteger())), - MatrixStride(7u, Parameter(LiteralInteger())), - GLSLShared(8u), - GLSLPacked(9u), - CPacked(10u), - BuiltIn(11u, Parameter(EnumType.create())), - NoPerspective(13u), - Flat(14u), - Patch(15u), - Centroid(16u), - Sample(17u), - Invariant(18u), - Restrict(19u), - Aliased(20u), - Volatile(21u), - Constant(22u), - Coherent(23u), - NonWritable(24u), - NonReadable(25u), - Uniform(26u), - SaturatedConversion(28u), - Stream(29u, Parameter(LiteralInteger())), - Location(30u, Parameter(LiteralInteger())), - Component(31u, Parameter(LiteralInteger())), - Index(32u), - Binding(33u, Parameter(LiteralInteger())), - DescriptorSet(34u, Parameter(LiteralInteger())), - Offset(35u, Parameter(LiteralInteger())), - XfbBuffer(36u, Parameter(LiteralInteger())), - XfbStride(37u, Parameter(LiteralInteger())), - FuncParamAttr(38u, Parameter(EnumType.create())), - FPRoundingMode(39u, Parameter(EnumType.create())), - FPFastMathMode(40u, Parameter(EnumType.create())), - LinkageAttributes(41u, Parameter(LiteralString(), EnumType.create())), - NoContraction(42u), - InputAttachmentIndex(43u, Parameter(LiteralInteger())), - Alignment(44u, Parameter(LiteralInteger())), - MaxByteOffset(45u, Parameter(LiteralInteger())), - AlignmentId(46u, Parameter(IdRef())), - MaxByteOffsetId(47u, Parameter(IdRef())), - ExplicitInterpAMD(4999u), - OverrideCoverageNV(5248u), - PassthroughNV(5250u), - ViewportRelativeNV(5252u), - SecondaryViewportRelativeNV(5256u, Parameter(LiteralInteger())); - - companion object: NumericalEnumCompanion() -} - -internal class DecorationParameterFactory: ParameterFactory() { - override fun createParameter(value: UInt): Parameter? { - return Decoration.values().firstOrNull { it.id == value }?.parameter - } + companion object: NumericalEnumCompanion(values(), Position) } internal enum class Scope(override val id: UInt): NumericalEnum { @@ -564,31 +561,21 @@ internal enum class Scope(override val id: UInt): NumericalEnum { Subgroup(3u), Invocation(4u); - companion object: NumericalEnumCompanion() + companion object: NumericalEnumCompanion(values(), CrossDevice) } -internal class ScopeParameterFactory: ParameterFactory() - internal enum class GroupOperation(override val id: UInt): NumericalEnum { Reduce(0u), InclusiveScan(1u), ExclusiveScan(2u); - companion object: NumericalEnumCompanion() + companion object: NumericalEnumCompanion(values(), Reduce) } -internal class GroupOperationParameterFactory: ParameterFactory() - -internal enum class KernelEnqueueFlags(override val id: UInt): NumericalEnum { - NoWait(0u), - WaitKernel(1u), - WaitWorkGroup(2u); - - companion object: NumericalEnumCompanion() +internal class GroupOperationParameterFactory: ParameterFactory() { + companion object { internal val defaultInst = GroupOperationParameterFactory() } } -internal class KernelEnqueueFlagsParameterFactory: ParameterFactory() - internal enum class Capability(override val id: UInt): NumericalEnum { Matrix(0u), Shader(1u), @@ -679,7 +666,9 @@ internal enum class Capability(override val id: UInt): NumericalEnum { SubgroupBufferBlockIOINTEL(5569u), SubgroupImageBlockIOINTEL(5570u); - companion object: NumericalEnumCompanion() + companion object: NumericalEnumCompanion(values(), Matrix) } -internal class CapabilityParameterFactory: ParameterFactory() \ No newline at end of file +internal class CapabilityParameterFactory: ParameterFactory() { + companion object { internal val defaultInst = CapabilityParameterFactory() } +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/file/AssetFile.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/file/AssetFile.kt new file mode 100644 index 00000000..3888901b --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/file/AssetFile.kt @@ -0,0 +1,59 @@ +package io.github.deficuet.unitykt.internal.file + +import io.github.deficuet.unitykt.internal.ImportContextImpl +import io.github.deficuet.unitykt.util.EndianBinaryReader +import io.github.deficuet.unitykt.util.EndianByteArrayReader + +internal enum class FileType { + ASSETS, BUNDLE, WEB, RESOURCE, GZIP, BROTLI //, ZIP +} + +internal data class DirectoryInfoNode( + val path: String, + val offset: Long, + val size: Long, + val flag: UInt = 0u +) + +internal interface FileNode { + val bundleParent: FileNode + val root: ImportContextImpl + get() = if (bundleParent is ImportContextImpl) bundleParent as ImportContextImpl else bundleParent.root +} + +internal interface AssetFile: FileNode { + val name: String + + fun readFiles(reader: EndianBinaryReader, directoryInfo: List) { + for (node in directoryInfo) { + reader.position = node.offset + val nodeReader = EndianByteArrayReader( + reader.read(node.size.toInt()), + baseOffset = reader.baseOffset + node.offset + ) + when (readerFileType(nodeReader)) { + FileType.BUNDLE -> BundleFile(nodeReader, this, node.path) + FileType.WEB -> WebFile(nodeReader, this, node.path) + FileType.ASSETS -> { + if (resourceExt.none { node.path.endsWith(it) }) { + SerializedFile(nodeReader, this, node.path).also { + root.manager.assetFiles[node.path.lowercase()] = it + } + } else { + ResourceFile(nodeReader, this, node.path).also { + root.manager.resourceFiles[node.path] = it + } + } + } + FileType.RESOURCE -> ResourceFile(nodeReader, this, node.path).also { + root.manager.resourceFiles[node.path] = it + } + else -> { } + } + } + } + + companion object { + val resourceExt = arrayOf(".resS", ".resource", ".config", ".xml", ".dat") + } +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/file/BundleFile.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/file/BundleFile.kt new file mode 100644 index 00000000..cc1456b2 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/file/BundleFile.kt @@ -0,0 +1,162 @@ +package io.github.deficuet.unitykt.internal.file + +import io.github.deficuet.unitykt.util.* + +internal class ArchiveFlags private constructor() { + companion object { + const val CompressionTypeMask = 0x3Fu +// const val BlocksAndDirectoryInfoCombined = 0x40u + const val BlocksInfoAtTheEnd = 0x80u +// const val OldWebPluginCompatibility = 0x100u + const val BlockInfoNeedPaddingAtStart = 0x200u + } +} + +internal class BundleFile( + private val reader: EndianBinaryReader, + override val bundleParent: FileNode, + override val name: String +): AssetFile { + data class Block( + val compressedSize: UInt, + val uncompressedSize: UInt, + val flags: UShort + ) + + //Header + private val hSignature: String = reader.readNullString() + private val hVersion: UInt = reader.readUInt32() + + private val blocksInfo = mutableListOf() + private val directoryInfo = mutableListOf() + + init { + reader.readNullString() //hUnityVersion + reader.readNullString() //hUnityRevision + val filesReader = when (hSignature) { + "UnityArchive" -> throw UnsupportedOperationException("Unsupported file type UnityArchive") + "UnityWeb", "UnityRaw" -> { + if (hVersion == 6u) readFS() + else readWebRaw() + } + "UnityFS" -> readFS() + else -> throw UnsupportedOperationException("Unknown Bundle Signature") + } + readFiles(filesReader, directoryInfo) + filesReader.close() + reader.close() + } + + private fun readWebRaw(): EndianBinaryReader { + val isCompressed = hSignature == "UnityWeb" + if (hVersion >= 4u) { + reader.skip(20) //hash(16), crc: UInt + } + reader.skip(4) //minStreamedByte: UInt + val hSize = reader.readUInt32().toLong() + reader.skip(4) //levelsBeforeStreaming: UInt + val levelCount = reader.readInt32() + reader.skip(4 * 2 * (levelCount - 1)) + blocksInfo.add( + Block( + reader.readUInt32(), reader.readUInt32(), 0u + ) + ) + if (hVersion >= 2u) { + reader.skip(4) //completeFileSize: UInt + } + if (hVersion >= 3u) { + reader.skip(4) //fileInfoHeaderSize: UInt + } + reader.position = hSize + val uncompressedBytes = with(reader.read(blocksInfo[0].compressedSize.toInt())) { + if (isCompressed) { + CompressUtils.lzmaDecompress(this) + } else this + } + val blocksReader = EndianByteArrayReader( + uncompressedBytes, + baseOffset = hSize + ) + directoryInfo.addAll( + blocksReader.readArrayOf { + DirectoryInfoNode( + readNullString(), + readUInt32().toLong(), + readUInt32().toLong() + ) + } + ) + return blocksReader + } + + private fun readFS(): EndianBinaryReader { + reader.skip(8) //header.size: Long + val hCompressedBlockSize = reader.readUInt32() + val uncompressedBlockSize = reader.readUInt32() + val hFlags = reader.readUInt32() + if (hSignature != "UnityFS") reader.skip(1) + if (hVersion >= 7u) reader.alignStream(16) + val blockOffset = reader.position + var blocksInfoBytes: ByteArray + if (hFlags.and(ArchiveFlags.BlocksInfoAtTheEnd) != 0u) { + blocksInfoBytes = reader.withMark { + position = length - hCompressedBlockSize.toLong() + read(hCompressedBlockSize.toInt()) + } + } else { + blocksInfoBytes = reader.read(hCompressedBlockSize.toInt()) + } + when (hFlags.and(ArchiveFlags.CompressionTypeMask)) { + 1u -> blocksInfoBytes = CompressUtils.lzmaDecompress(blocksInfoBytes) + 2u, 3u -> blocksInfoBytes = CompressUtils.lz4Decompress(blocksInfoBytes, uncompressedBlockSize.toInt()) + } + val blocksInfoReader = EndianByteArrayReader(blocksInfoBytes, baseOffset = blockOffset) + blocksInfoReader.skip(16) //uncompressedDataHash + blocksInfo.addAll( + blocksInfoReader.readArrayOf { + Block( + uncompressedSize = readUInt32(), + compressedSize = readUInt32(), + flags = readUInt16() + ) + } + ) + directoryInfo.addAll( + blocksInfoReader.readArrayOf { + DirectoryInfoNode( + offset = readInt64(), + size = readInt64(), + flag = readUInt32(), + path = readNullString() + ) + } + ) + if (hFlags.and(ArchiveFlags.BlockInfoNeedPaddingAtStart) != 0u) { + reader.alignStream(16) + } + return EndianByteArrayReader( + baseOffset = blocksInfoReader.realOffset + ) { + var sum = 0 + val result = ByteArray(blocksInfo.sumOf { it.uncompressedSize }.toInt()) + for (block in blocksInfo) { + val decompressed = when (block.flags.toUInt().and(ArchiveFlags.CompressionTypeMask)) { + 1u -> CompressUtils.lzmaDecompress( + reader.read(block.compressedSize.toInt()) + ) + 2u, 3u -> CompressUtils.lz4Decompress( + reader.read(block.compressedSize.toInt()), block.uncompressedSize.toInt() + ) + else -> reader.read(block.uncompressedSize.toInt()) + } + System.arraycopy( + decompressed, 0, + result, sum, decompressed.size + ) + sum += decompressed.size + } + result + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/file/ResourceFile.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/file/ResourceFile.kt new file mode 100644 index 00000000..050b0fcf --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/file/ResourceFile.kt @@ -0,0 +1,9 @@ +package io.github.deficuet.unitykt.internal.file + +import io.github.deficuet.unitykt.util.EndianBinaryReader + +internal class ResourceFile( + internal val reader: EndianBinaryReader, + override val bundleParent: FileNode, + override val name: String +): AssetFile \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/file/SerializedFile.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/file/SerializedFile.kt new file mode 100644 index 00000000..c069a86d --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/file/SerializedFile.kt @@ -0,0 +1,416 @@ +package io.github.deficuet.unitykt.internal.file + +import io.github.deficuet.unitykt.classes.UnityObject +import io.github.deficuet.unitykt.enums.BuildTarget +import io.github.deficuet.unitykt.enums.ClassIDType +import io.github.deficuet.unitykt.internal.impl.* +import io.github.deficuet.unitykt.util.EndianBinaryReader +import io.github.deficuet.unitykt.util.EndianByteArrayReader +import io.github.deficuet.unitykt.util.readArrayOf +import java.io.File +import java.nio.ByteOrder + +internal class FormatVersion private constructor() { + companion object { +// const val Unsupported = 1u + const val Unknown_2 = 2u + const val Unknown_3 = 3u + const val Unknown_5 = 5u + const val Unknown_6 = 6u + const val Unknown_7 = 7u + const val Unknown_8 = 8u + const val Unknown_9 = 9u + const val Unknown_10 = 10u + const val HasScriptTypeIndex = 11u + const val Unknown_12 = 12u + const val HasTypeTreeHashes = 13u + const val Unknown_14 = 14u + const val SupportsStrippedObject = 15u + const val RefactoredClassId = 16u + const val RefactorTypeData = 17u +// const val RefactorShareableTypeTreeData = 18u + const val TypeTreeNodeWithTypeFlags = 19u + const val SupportsRefObject = 20u + const val StoresTypeDependencies = 21u + const val LargeFilesSupport = 22u + } +} + +internal class BuildType(private val type: String) { +// val isAlpha get() = type == "a" + val isPatch get() = type == "p" +} + +internal data class ObjectInfo( + val byteStart: Long, + val byteSize: UInt, + val typeID: Int, + val classID: Int, + val isDestroyed: UShort, + val stripped: UByte, + val mPathID: Long, + val serializedType: SerializedType? +) { + val type = ClassIDType.of(classID) +} + +internal class SerializedFile( + internal val reader: EndianBinaryReader, + override val bundleParent: FileNode, + override val name: String +): AssetFile { + class FileIdentifier private constructor( + val path: String, + val name: String + ) { + companion object { + fun fromPath(path: String) = FileIdentifier(path, File(path).name) + fun fromName(name: String) = FileIdentifier("", name) + } + } + + data class ObjectIdentifier( + val serializedFileIndex: Int, + val identifierInFile: Long + ) + + data class SerializedTypeTreeNodeInternal( + val byteSize: Int, + val index: Int, + val typeFlags: Int, + val version: Int, + val metaFlag: Int, + val level: Int, + val typeStrOffset: UInt, + val nameStrOffset: UInt + ) + + //Header + private var hMetadataSize = reader.readUInt32() + private var hFileSize = reader.readUInt32().toLong() + val hVersion = reader.readUInt32() + private var hDataOffset = reader.readUInt32().toLong() + private val hEndian: UByte +// private val hReserved: ByteArray + + private var unityVersion = "2.5.0.f5" + + private val enableTypeTree: Boolean + private var bigIDEnabled = 0 + private val objectInfoArray: Array + private val scriptTypes: Array + private val refTypes: Array + private val userInformation: String + private val types: Array + + var version: IntArray = intArrayOf(0, 0, 0, 0) + var targetPlatform = BuildTarget.UnknownPlatform + var buildType = BuildType("") + val externals = mutableListOf() + + val objectMap = mutableMapOf() + + init { + if (hVersion >= FormatVersion.Unknown_9) { + hEndian = reader.readUInt8() + reader.skip(3) //hReserved = reader.read(3) + } else { + reader.position = hFileSize - hMetadataSize.toLong() + hEndian = reader.readUInt8() + } + if (hVersion >= FormatVersion.LargeFilesSupport) { + hMetadataSize = reader.readUInt32() + hFileSize = reader.readInt64() + hDataOffset = reader.readInt64() + reader.skip(8) //unknown: Long + } + if (hEndian == 0u.toUByte()) reader.endian = ByteOrder.LITTLE_ENDIAN + if (hVersion >= FormatVersion.Unknown_7) { + unityVersion = reader.readNullString() + buildType = buildTypeRegex.findAll(unityVersion).iterator().let { + BuildType(if (it.hasNext()) it.next().value else "") + } + version = versionSplitRegex.split(unityVersion).let { digits -> + IntArray(digits.size) { index -> digits[index].toInt() } + } + } + if (hVersion >= FormatVersion.Unknown_8) { + val targetPlatformID = reader.readInt32() + if (BuildTarget.isDefined(targetPlatformID)) { + targetPlatform = BuildTarget.values().first { it.id == targetPlatformID } + } + } + enableTypeTree = if (hVersion >= FormatVersion.HasTypeTreeHashes) reader.readBool() else true + types = reader.readArrayOf { + readSerializedType(false) + } + if (hVersion >= FormatVersion.Unknown_7 && hVersion < FormatVersion.Unknown_14) { + bigIDEnabled = reader.readInt32() + } + objectInfoArray = reader.readArrayOf { + val mPathID = if (bigIDEnabled != 0) { + readInt64() + } else if (hVersion < FormatVersion.Unknown_14) { + readInt32().toLong() + } else { + alignStream() + readInt64() + } + var byteStart = if (hVersion >= FormatVersion.LargeFilesSupport) { + readInt64() + } else { + readUInt32().toLong() + } + byteStart += hDataOffset + val byteSize = readUInt32() + val typeID = readInt32() + val classID: Int; val serialisedType: SerializedType? + if (hVersion < FormatVersion.RefactoredClassId) { + classID = readUInt16().toInt() + serialisedType = types.find { it.classID == typeID } + } else { + with(types[typeID]) { + serialisedType = this + classID = this.classID + } + } + val isDestroyed: UShort = if (hVersion < FormatVersion.HasScriptTypeIndex) readUInt16() else 0u + if (hVersion >= FormatVersion.HasScriptTypeIndex && hVersion < FormatVersion.RefactorTypeData) { + serialisedType?.scriptTypeIndex = readInt16() + } + val stripped: UByte = if ( + hVersion == FormatVersion.SupportsStrippedObject || + hVersion == FormatVersion.RefactoredClassId + ) readUInt8() else 0u + ObjectInfo( + byteStart, byteSize, typeID, classID, isDestroyed, + stripped, mPathID, serialisedType + ) + } + scriptTypes = if (hVersion >= FormatVersion.HasScriptTypeIndex) { + reader.readArrayOf { + ObjectIdentifier( + serializedFileIndex = readInt32(), + identifierInFile = if (hVersion < FormatVersion.Unknown_14) { + readInt32().toLong() + } else { + alignStream() + readInt64() + } + ) + } + } else emptyArray() + reader.readArrayOf { + if (hVersion >= FormatVersion.Unknown_6) readNullString() + if (hVersion >= FormatVersion.Unknown_5) { + //guid: UUID (byte[16]) + //type: Int32 + skip(20) + } + externals.add(FileIdentifier.fromPath(readNullString())) + } + refTypes = if (hVersion >= FormatVersion.SupportsRefObject) { + reader.readArrayOf { readSerializedType(true) } + } else emptyArray() + userInformation = if (hVersion >= FormatVersion.Unknown_5) { + reader.readNullString() + } else "" + //region readObjects + for (info in objectInfoArray) { + val obj = when (info.type) { + ClassIDType.Animation -> AnimationImpl(this, info) + ClassIDType.AnimationClip -> AnimationClipImpl(this, info) + ClassIDType.Animator -> AnimatorImpl(this, info) + ClassIDType.AnimatorController -> AnimatorControllerImpl(this, info) + ClassIDType.AnimatorOverrideController -> AnimatorOverrideControllerImpl(this, info) + ClassIDType.AssetBundle -> AssetBundleImpl(this, info) + ClassIDType.AudioClip -> AudioClipImpl(this, info) + ClassIDType.Avatar -> AvatarImpl(this, info) + ClassIDType.Canvas -> CanvasImpl(this, info) +// ClassIDType.Font -> Font(this, info) TODO + ClassIDType.GameObject -> GameObjectImpl(this, info) + ClassIDType.Material -> MaterialImpl(this, info) + ClassIDType.Mesh -> MeshImpl(this, info) + ClassIDType.MeshFilter -> MeshFilterImpl(this, info) + ClassIDType.MeshRenderer -> MeshRendererImpl(this, info) + ClassIDType.MonoBehaviour -> MonoBehaviourImpl(this, info) + ClassIDType.MonoScript -> MonoScriptImpl(this, info) + ClassIDType.MovieTexture -> MovieTextureImpl(this, info) + ClassIDType.PlayerSettings -> PlayerSettingsImpl(this, info) + ClassIDType.RectTransform -> RectTransformImpl(this, info) + ClassIDType.Shader -> ShaderImpl(this, info) + ClassIDType.SkinnedMeshRenderer -> SkinnedMeshRendererImpl(this, info) + ClassIDType.Sprite -> SpriteImpl(this, info) + ClassIDType.SpriteAtlas -> SpriteAtlasImpl(this, info) + ClassIDType.TextAsset -> TextAssetImpl(this, info) + ClassIDType.Texture2D -> Texture2DImpl(this, info) + ClassIDType.Transform -> TransformImpl(this, info) + ClassIDType.VideoClip -> VideoClipImpl(this, info) + ClassIDType.ResourceManager -> ResourceManagerImpl(this, info) + else -> UnityObjectImpl(this, info) + } + objectMap[obj.mPathID] = obj + } + root.objectMap.putAll(objectMap) + //endregion + } + + private fun readSerializedType(isRefType: Boolean): SerializedType { + val classID = reader.readInt32() + var isStrippedType = false + var scriptTypeIndex: Short = -1 + var scriptID: ByteArray = byteArrayOf() + var oldTypeHash: ByteArray = byteArrayOf() + var typeTree = SerializedType.Tree() + var className = "" + var nameSpace = "" + var asmName = "" + var typeDependencies: IntArray = intArrayOf() + if (hVersion >= FormatVersion.RefactoredClassId) isStrippedType = reader.readBool() + if (hVersion >= FormatVersion.RefactorTypeData) scriptTypeIndex = reader.readInt16() + if (hVersion >= FormatVersion.HasTypeTreeHashes) { + if (isRefType && scriptTypeIndex >= 0) scriptID = reader.read(16) + else if ((hVersion < FormatVersion.RefactoredClassId && classID < 0) || + (hVersion >= FormatVersion.RefactoredClassId && classID == 114)) { + scriptID = reader.read(16) + } + oldTypeHash = reader.read(16) + } + if (enableTypeTree) { + typeTree = if (hVersion >= FormatVersion.Unknown_12 || hVersion == FormatVersion.Unknown_10) { + typeTreeBlobRead() + } else { + readTypeTree() + } + if (hVersion >= FormatVersion.StoresTypeDependencies) { + if (isRefType) { + className = reader.readNullString() + nameSpace = reader.readNullString() + asmName = reader.readNullString() + } else { + typeDependencies = reader.readInt32Array() + } + } + } + return SerializedType( + classID, + isStrippedType, + scriptTypeIndex, + typeTree, + scriptID, + oldTypeHash, + typeDependencies, + className, + nameSpace, + asmName + ) + } + + private fun EndianBinaryReader.readNodeString(value: UInt): String { + if (value.and(0x80000000u) == 0u) { + position = value.toLong() + return readNullString() + } + val offset = value.and(0x7FFFFFFFu) + return commonString[offset] ?: offset.toString() + } + + private fun typeTreeBlobRead(): SerializedType.Tree { + val nodeCount = reader.readInt32() + val stringBufferSize = reader.readInt32() + val nodeList = mutableListOf() + val nodeListInternal = mutableListOf() + for (i in 0 until nodeCount) { + nodeListInternal.add( + SerializedTypeTreeNodeInternal( + version = reader.readUInt16().toInt(), + level = reader.readUInt8().toInt(), + typeFlags = reader.readUInt8().toInt(), + typeStrOffset = reader.readUInt32(), + nameStrOffset = reader.readUInt32(), + byteSize = reader.readInt32(), + index = reader.readInt32(), + metaFlag = reader.readInt32() + ) + ) + if (hVersion >= FormatVersion.TypeTreeNodeWithTypeFlags) { + reader.skip(8) //refTypeHash: ULong + } + } + val stringBuffer = reader.read(stringBufferSize) + EndianByteArrayReader(stringBuffer).use { + for (node in nodeListInternal) { + nodeList.add( + SerializedType.TreeNode( + node, + type = it.readNodeString(node.typeStrOffset), + name = it.readNodeString(node.nameStrOffset) + ) + ) + } + } + return SerializedType.Tree(nodeList) + } + + private fun readTypeTree(): SerializedType.Tree { + val newTree = SerializedType.Tree() + val levelStack = mutableListOf(intArrayOf(0, 1)) + while (levelStack.isNotEmpty()) { + val (level, count) = levelStack.last() + if (count == 1) { + levelStack.removeLast() + } else { + levelStack.last()[1] -= 1 + } + val type = reader.readNullString() + val name = reader.readNullString() + val byteSize = reader.readInt32() + if (hVersion == FormatVersion.Unknown_2) reader.skip(4) //variableCount + val index = if (hVersion != FormatVersion.Unknown_3) reader.readInt32() else 0 + val typeFlags = reader.readInt32() + val version = reader.readInt32() + val metaFlag = if (hVersion != FormatVersion.Unknown_3) reader.readInt32() else 0 + newTree.nodes.add( + SerializedType.TreeNode( + type, name, byteSize, index, typeFlags, version, metaFlag, level + ) + ) + val childrenCount = reader.readInt32() + if (childrenCount > 0) levelStack.add(intArrayOf(level + 1, childrenCount)) + } + return newTree + } + + companion object { + private val buildTypeRegex = Regex("""([^\d.])""") + private val versionSplitRegex = Regex("""\D""") + private val commonString = mapOf( + 0u to "AABB", 5u to "AnimationClip", 19u to "AnimationCurve", 34u to "AnimationState", + 49u to "Array", 55u to "Base", 60u to "BitField", 69u to "bitset", 76u to "bool", + 81u to "char", 86u to "ColorRGBA", 96u to "Component", 106u to "data", 111u to "deque", + 117u to "double", 124u to "dynamic_array", 138u to "FastPropertyName", 155u to "first", + 161u to "float", 167u to "Font", 172u to "GameObject", 183u to "Generic Mono", 196u to "GradientNEW", + 208u to "GUID", 213u to "GUIStyle", 222u to "int", 226u to "list", 231u to "long long", + 241u to "map", 245u to "Matrix4x4f", 256u to "MdFour", 263u to "MonoBehaviour", 277u to "MonoScript", + 288u to "m_ByteSize", 299u to "m_Curve", 307u to "m_EditorClassIdentifier", 331u to "m_EditorHideFlags", + 349u to "m_Enabled", 359u to "m_ExtensionPtr", 374u to "m_GameObject", 387u to "m_Index", + 395u to "m_IsArray", 405u to "m_IsStatic", 416u to "m_MetaFlag", 427u to "m_Name", + 434u to "m_ObjectHideFlags", 452u to "m_PrefabInternal", 469u to "m_PrefabParentObject", + 490u to "m_Script", 499u to "m_StaticEditorFlags", 519u to "m_Type", 526u to "m_Version", + 536u to "Object", 543u to "pair", 548u to "PPtr", 564u to "PPtr", + 581u to "PPtr", 596u to "PPtr", 616u to "PPtr", + 633u to "PPtr", 646u to "PPtr", 659u to "PPtr", 672u to "PPtr", + 688u to "PPtr", 702u to "PPtr", 718u to "PPtr", + 734u to "Prefab", 741u to "Quaternionf", 753u to "Rectf", 759u to "RectInt", 767u to "RectOffset", + 778u to "second", 785u to "set", 789u to "short", 795u to "size", 800u to "SInt16", 807u to "SInt32", + 814u to "SInt64", 821u to "SInt8", 827u to "staticvector", 840u to "string", 847u to "TextAsset", + 857u to "TextMesh", 866u to "Texture", 874u to "Texture2D", 884u to "Transform", 894u to "TypelessData", + 907u to "UInt16", 914u to "UInt32", 921u to "UInt64", 928u to "UInt8", 934u to "unsigned int", + 947u to "unsigned long long", 966u to "unsigned short", 981u to "vector", 988u to "Vector2f", + 997u to "Vector3f", 1006u to "Vector4f", 1015u to "m_ScriptingClassIdentifier", 1042u to "Gradient", + 1051u to "Type*", 1057u to "int2_storage", 1070u to "int3_storage", 1083u to "BoundsInt", + 1093u to "m_CorrespondingSourceObject", 1121u to "m_PrefabInstance", 1138u to "m_PrefabAsset", + 1152u to "FileSize", 1161u to "Hash128" + ) + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/file/SerializedType.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/file/SerializedType.kt similarity index 83% rename from src/main/kotlin/io/github/deficuet/unitykt/file/SerializedType.kt rename to src/main/kotlin/io/github/deficuet/unitykt/internal/file/SerializedType.kt index 09f14523..97967de0 100644 --- a/src/main/kotlin/io/github/deficuet/unitykt/file/SerializedType.kt +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/file/SerializedType.kt @@ -1,284 +1,297 @@ -package io.github.deficuet.unitykt.file - -import io.github.deficuet.unitykt.util.ObjectReader -import io.github.deficuet.unitykt.util.byteArrayOf -import io.github.deficuet.unitykt.util.toChar -import kotlin.collections.set - -data class SerializedType( - val classID: Int = 0, - val isStrippedType: Boolean = false, - var scriptTypeIndex: Short = -1, - val typeTree: Tree = Tree(), - val scriptID: ByteArray = byteArrayOf(), - val oldTypeHash: ByteArray = byteArrayOf(), - val typeDependencies: IntArray = intArrayOf(), - val className: String = "", - val nameSpace: String = "", - val asmName: String = "" -) { - data class Tree( - val nodes: MutableList = mutableListOf() - ) { - private data class NodeResult( - val seq: Int, - val value: Any - ) - - fun readTypeString(reader: ObjectReader): String { - reader.position = 0 - val builder = StringBuilder() - var i = 0 - while (i < nodes.size) { - i = readNodeString(builder, nodes, reader, i) - i++ - } - return builder.toString() - } - - fun readType(reader: ObjectReader): Map { - reader.position = 0 - val dict = mutableMapOf() - var i = 1 - while (i < nodes.size) { - val node = nodes[i] - val result = readNode(reader, nodes, i) - i = result.seq - dict[node.name] = result.value - i++ - } - return dict - } - - private fun readNodeString( - builder: StringBuilder, nodes: List, - reader: ObjectReader, i: Int - ): Int { - var seq = i - val node = nodes[seq] - var append = true - var align = node.metaFlag.and(0x4000) != 0 - var value: Any? = null - when (node.type) { - "SInt8" -> value = reader.readSByte() - "UInt8" -> value = reader.readByte() - "char" -> value = reader.read(2).toChar() - "SInt16", "short" -> value = reader.readShort() - "UInt16", "unsigned short" -> value = reader.readUShort() - "SInt32", "int" -> value = reader.readInt() - "UInt32", "unsigned int", "Type*" -> value = reader.readUInt() - "SInt64", "long long" -> value = reader.readLong() - "UInt64", "unsigned long long", "FileSize" -> value = reader.readULong() - "float" -> value = reader.readFloat() - "double" -> value = reader.readDouble() - "bool" -> value = reader.readBool() - "string" -> { - append = false - val str = reader.readAlignedString() - builder.append("${"\t".repeat(node.level)}${node.type} ${node.name} = \"$str\"\r\n") - seq += nodes.getNodes(seq).size - 1 - } - "map" -> { - if (nodes[seq + 1].metaFlag.and(0x4000) != 0) align = true - append = false - val size = reader.readInt() - with(builder) { - append("${"\t".repeat(node.level)}${node.type} ${node.name}\r\n") - append("${"\t".repeat(node.level + 1)}Array Array\r\n") - append("${"\t".repeat(node.level + 1)}int size = $size\r\n") - } - val map = nodes.getNodes(seq) - seq += map.size - 1 - val first = map.getNodes(4) - val second = map.getNodes(first.size + 4) - with(builder) { - for (j in 0 until size) { - append("${"\t".repeat(node.level + 2)}[${j}]\r\n") - append("${"\t".repeat(node.level + 2)}pair data\r\n") - readNodeString(this, first, reader, 0) - readNodeString(this, second, reader, 0) - } - } - } - "TypelessData" -> { - append = false - val size = reader.readInt() - reader += size - seq += 2 - with(builder) { - append("${"\t".repeat(node.level)}${node.type} ${node.name}\r\n") - append("${"\t".repeat(node.level)}int size = $size\r\n") - } - } - else -> { - if (seq < nodes.size - 1 && nodes[seq + 1].type == "Array") { - if (nodes[seq + 1].metaFlag.and(0x4000) != 0) align = true - append = false - val size = reader.readInt() - with(builder) { - append("${"\t".repeat(node.level)}${node.type} ${node.name}\r\n") - append("${"\t".repeat(node.level + 1)}Array Array\r\n") - append("${"\t".repeat(node.level + 1)}int size = $size\r\n") - } - val vector = nodes.getNodes(seq) - seq += vector.size - 1 - for (j in 0 until size) { - builder.append("${"\t".repeat(node.level + 2)}[${j}]\r\n") - readNodeString(builder, vector, reader, 3) - } - } else { - append = false - builder.append("${"\t".repeat(node.level)}${node.type} ${node.name}\r\n") - val clazz = nodes.getNodes(seq) - seq += clazz.size - 1 - var j = 1 - while (j < clazz.size) { - j = readNodeString(builder, clazz, reader, j) - j++ - } - } - } - } - if (append) builder.append("${"\t".repeat(node.level)}${node.type} ${node.name} = $value\n") - if (align) reader.alignStream() - return seq - } - - private fun readNode(reader: ObjectReader, nodes: List, i: Int): NodeResult { - var seq = i - val node = nodes[seq] - var align = node.metaFlag.and(0x4000) != 0 - val value: Any - when (node.type) { - "SInt8" -> value = reader.readSByte() - "UInt8" -> value = reader.readByte() - "char" -> value = reader.read(2).toChar() - "SInt16", "short" -> value = reader.readShort() - "UInt16", "unsigned short" -> value = reader.readUShort() - "SInt32", "int" -> value = reader.readInt() - "UInt32", "unsigned int", "Type*" -> value = reader.readUInt() - "SInt64", "long long" -> value = reader.readLong() - "UInt64", "unsigned long long", "FileSize" -> value = reader.readULong() - "float" -> value = reader.readFloat() - "double" -> value = reader.readDouble() - "bool" -> value = reader.readBool() - "string" -> { - value = reader.readAlignedString() - seq += nodes.getNodes(seq).size - 1 - } - "map" -> { - if (nodes[seq + 1].metaFlag.and(0x4000) != 0) align = true - val map = nodes.getNodes(seq) - seq += map.size - 1 - val first = map.getNodes(4) - val second = map.getNodes(first.size + 4) - val size = reader.readInt() - val dict = mutableListOf>() - for (j in 0 until size) { - dict.add( - Pair( - readNode(reader, first, 0).value, - readNode(reader, second, 0).value - ) - ) - } - value = dict - } - "TypelessData" -> { - value = reader.readNextByteArray() - seq += 2 - } - else -> { - if (seq < nodes.size - 1 && nodes[seq + 1].type == "Array") { - if (nodes[seq + 1].metaFlag.and(0x4000) != 0) align = true - val vector = nodes.getNodes(seq) - seq += vector.size - 1 - val size = reader.readInt() - val list = mutableListOf() - for (j in 0 until size) { - list.add(readNode(reader, vector, 3).value) - } - value = list - } else { - val clazz = nodes.getNodes(seq) - seq += clazz.size - 1 - val dict = mutableMapOf() - var j = 1 - while (j < clazz.size) { - val theClass = clazz[j] - val result = readNode(reader, clazz, j) - j = result.seq - dict[theClass.name] = result.value - j++ - } - value = dict - } - } - } - if (align) reader.alignStream() - return NodeResult(seq, value) - } - - private fun List.getNodes(index: Int): List { - val nodes = mutableListOf(this[index]) - val level = this[index].level - for (i in index + 1 until size) { - val node = this[i] - if (node.level <= level) return nodes - nodes.add(node) - } - return nodes - } - } - - data class TreeNode( - val type: String, - val name: String, - val byteSize: Int, - val index: Int, - val typeFlags: Int, - val version: Int, - val metaFlag: Int, - val level: Int - ) { - constructor(data: SerializedFile.SerializedTypeTreeNodeInternal, type: String, name: String): - this( - type, name, data.byteSize, data.index, data.typeFlags, - data.version, data.metaFlag, data.level - ) - } - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (javaClass != other?.javaClass) return false - - other as SerializedType - - if (classID != other.classID) return false - if (isStrippedType != other.isStrippedType) return false - if (scriptTypeIndex != other.scriptTypeIndex) return false - if (typeTree != other.typeTree) return false - if (!scriptID.contentEquals(other.scriptID)) return false - if (!oldTypeHash.contentEquals(other.oldTypeHash)) return false - if (!typeDependencies.contentEquals(other.typeDependencies)) return false - if (className != other.className) return false - if (nameSpace != other.nameSpace) return false - if (asmName != other.asmName) return false - - return true - } - - override fun hashCode(): Int { - var result = classID - result = 31 * result + isStrippedType.hashCode() - result = 31 * result + scriptTypeIndex - result = 31 * result + typeTree.hashCode() - result = 31 * result + scriptID.contentHashCode() - result = 31 * result + oldTypeHash.contentHashCode() - result = 31 * result + typeDependencies.contentHashCode() - result = 31 * result + className.hashCode() - result = 31 * result + nameSpace.hashCode() - result = 31 * result + asmName.hashCode() - return result - } +package io.github.deficuet.unitykt.internal.file + +import io.github.deficuet.unitykt.util.ObjectReader +import io.github.deficuet.unitykt.util.toChar +import java.math.BigInteger +import kotlin.collections.set + +data class SerializedType( + val classID: Int = 0, + val isStrippedType: Boolean = false, + var scriptTypeIndex: Short = -1, + val typeTree: Tree = Tree(), + val scriptID: ByteArray = byteArrayOf(), + val oldTypeHash: ByteArray = byteArrayOf(), + val typeDependencies: IntArray = intArrayOf(), + val className: String = "", + val nameSpace: String = "", + val asmName: String = "" +) { + data class Tree( + val nodes: MutableList = mutableListOf() + ) { + private data class NodeResult( + val seq: Int, + val value: Any + ) + + internal fun readTypeString(reader: ObjectReader): String { + reader.position = 0 + val builder = StringBuilder() + var i = 0 + while (i < nodes.size) { + i = readNodeString(builder, nodes, reader, i) + i++ + } + return builder.toString() + } + + internal fun readType(reader: ObjectReader): Map { + reader.position = 0 + val dict = mutableMapOf() + var i = 1 + while (i < nodes.size) { + val node = nodes[i] + val result = readNode(reader, nodes, i) + i = result.seq + dict[node.name] = result.value + i++ + } + return dict + } + + private fun readNodeString( + builder: StringBuilder, nodes: List, + reader: ObjectReader, i: Int + ): Int { + var seq = i + val node = nodes[seq] + var append = true + var align = node.metaFlag.and(0x4000) != 0 + var value: Any? = null +// println("${node.type} ${node.name}") + when (node.type) { + "SInt8" -> value = reader.readInt8() + "UInt8" -> value = reader.readUInt8() + "char" -> value = reader.read(2).toChar() + "SInt16", "short" -> value = reader.readInt16() + "UInt16", "unsigned short" -> value = reader.readUInt16() + "SInt32", "int" -> value = reader.readInt32() + "UInt32", "unsigned int", "Type*" -> value = reader.readUInt32() + "SInt64", "long long" -> value = reader.readInt64() + "UInt64", "unsigned long long", "FileSize" -> value = reader.readUInt64() + "float" -> value = reader.readFloat() + "double" -> value = reader.readDouble() + "bool" -> value = reader.readBool() + "string" -> { + append = false + val str = reader.readAlignedString() + builder.append("${"\t".repeat(node.level)}${node.type} ${node.name} = \"$str\"\r\n") + seq += nodes.getNodes(seq).size - 1 + } + "map" -> { + if (nodes[seq + 1].metaFlag.and(0x4000) != 0) align = true + append = false + val size = reader.readInt32() + with(builder) { + append("${"\t".repeat(node.level)}${node.type} ${node.name}\r\n") + append("${"\t".repeat(node.level + 1)}Array Array\r\n") + append("${"\t".repeat(node.level + 1)}int size = $size\r\n") + } + val map = nodes.getNodes(seq) + seq += map.size - 1 + val first = map.getNodes(4) + val second = map.getNodes(first.size + 4) + with(builder) { + for (j in 0 until size) { + append("${"\t".repeat(node.level + 2)}[${j}]\r\n") + append("${"\t".repeat(node.level + 2)}pair data\r\n") + readNodeString(this, first, reader, 0) + readNodeString(this, second, reader, 0) + } + } + } + "TypelessData" -> { + append = false + val size = reader.readInt32() + reader.skip(size) + seq += 2 + with(builder) { + append("${"\t".repeat(node.level)}${node.type} ${node.name}\r\n") + append("${"\t".repeat(node.level)}int size = $size\r\n") + } + } + else -> { + if (seq < nodes.size - 1 && nodes[seq + 1].type == "Array") { + if (nodes[seq + 1].metaFlag.and(0x4000) != 0) align = true + append = false + val size = reader.readInt32() + with(builder) { + append("${"\t".repeat(node.level)}${node.type} ${node.name}\r\n") + append("${"\t".repeat(node.level + 1)}Array Array\r\n") + append("${"\t".repeat(node.level + 1)}int size = $size\r\n") + } + val vector = nodes.getNodes(seq) + seq += vector.size - 1 + for (j in 0 until size) { + builder.append("${"\t".repeat(node.level + 2)}[${j}]\r\n") + readNodeString(builder, vector, reader, 3) + } + } else { + append = false + builder.append("${"\t".repeat(node.level)}${node.type} ${node.name}\r\n") + val clazz = nodes.getNodes(seq) + seq += clazz.size - 1 + var j = 1 + while (j < clazz.size) { + j = readNodeString(builder, clazz, reader, j) + j++ + } + } + } + } + if (append) builder.append("${"\t".repeat(node.level)}${node.type} ${node.name} = $value\n") + if (align) { +// println("*** alignStream ***") + reader.alignStream() + } + return seq + } + + private fun readNode(reader: ObjectReader, nodes: List, i: Int): NodeResult { + var seq = i + val node = nodes[seq] + var align = node.metaFlag.and(0x4000) != 0 + val value: Any +// println("${node.type} ${node.name}") + when (node.type) { + "SInt8" -> value = reader.readInt8() + "UInt8" -> value = reader.readUInt8().toInt() + "char" -> value = reader.read(2).toChar() + "SInt16", "short" -> value = reader.readInt16() + "UInt16", "unsigned short" -> value = reader.readUInt16().toInt() + "SInt32", "int" -> value = reader.readInt32() + "UInt32", "unsigned int", "Type*" -> value = reader.readUInt32().toLong() + "SInt64", "long long" -> value = reader.readInt64() + "UInt64", "unsigned long long", "FileSize" -> { + val v = reader.readUInt64() + value = BigInteger(1, ByteArray(8) { + v.shr((7 - it) * 8).and(0xFFuL).toByte() + }) + } + "float" -> value = reader.readFloat() + "double" -> value = reader.readDouble() + "bool" -> value = reader.readBool() + "string" -> { + value = reader.readAlignedString() + seq += nodes.getNodes(seq).size - 1 + } + "map" -> { + if (nodes[seq + 1].metaFlag.and(0x4000) != 0) align = true + val map = nodes.getNodes(seq) + seq += map.size - 1 + val first = map.getNodes(4) + val second = map.getNodes(first.size + 4) + val size = reader.readInt32() + val dict = mutableListOf>() + for (j in 0 until size) { + dict.add( + Pair( + readNode(reader, first, 0).value, + readNode(reader, second, 0).value + ) + ) + } + value = dict + } + "TypelessData" -> { + value = reader.readInt8Array() + seq += 2 + } + else -> { + if (seq < nodes.size - 1 && nodes[seq + 1].type == "Array") { + if (nodes[seq + 1].metaFlag.and(0x4000) != 0) align = true + val vector = nodes.getNodes(seq) + seq += vector.size - 1 + val size = reader.readInt32() + val list = mutableListOf() + for (j in 0 until size) { + list.add(readNode(reader, vector, 3).value) + } + value = list + } else { + val clazz = nodes.getNodes(seq) + seq += clazz.size - 1 + val dict = mutableMapOf() + var j = 1 + while (j < clazz.size) { + val theClass = clazz[j] + val result = readNode(reader, clazz, j) + j = result.seq + dict[theClass.name] = result.value + j++ + } + value = dict + } + } + } + if (align) { +// println("*** alignStream ***") + reader.alignStream() + } + return NodeResult(seq, value) + } + + private fun List.getNodes(index: Int): List { + val nodes = mutableListOf(this[index]) + val level = this[index].level + for (i in index + 1 until size) { + val node = this[i] + if (node.level <= level) return nodes + nodes.add(node) + } + return nodes + } + } + + data class TreeNode( + val type: String, + val name: String, + val byteSize: Int, + val index: Int, + val typeFlags: Int, + val version: Int, + val metaFlag: Int, + val level: Int + ) { + internal constructor(data: SerializedFile.SerializedTypeTreeNodeInternal, type: String, name: String): + this( + type, name, data.byteSize, data.index, data.typeFlags, + data.version, data.metaFlag, data.level + ) + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as SerializedType + + if (classID != other.classID) return false + if (isStrippedType != other.isStrippedType) return false + if (scriptTypeIndex != other.scriptTypeIndex) return false + if (typeTree != other.typeTree) return false + if (!scriptID.contentEquals(other.scriptID)) return false + if (!oldTypeHash.contentEquals(other.oldTypeHash)) return false + if (!typeDependencies.contentEquals(other.typeDependencies)) return false + if (className != other.className) return false + if (nameSpace != other.nameSpace) return false + if (asmName != other.asmName) return false + + return true + } + + override fun hashCode(): Int { + var result = classID + result = 31 * result + isStrippedType.hashCode() + result = 31 * result + scriptTypeIndex + result = 31 * result + typeTree.hashCode() + result = 31 * result + scriptID.contentHashCode() + result = 31 * result + oldTypeHash.contentHashCode() + result = 31 * result + typeDependencies.contentHashCode() + result = 31 * result + className.hashCode() + result = 31 * result + nameSpace.hashCode() + result = 31 * result + asmName.hashCode() + return result + } } \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/file/WebFile.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/file/WebFile.kt new file mode 100644 index 00000000..11ffc370 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/file/WebFile.kt @@ -0,0 +1,28 @@ +package io.github.deficuet.unitykt.internal.file + +import io.github.deficuet.unitykt.util.EndianBinaryReader + +internal class WebFile( + reader: EndianBinaryReader, + override val bundleParent: FileNode, + override val name: String +): AssetFile { + + private val directoryInfo = mutableListOf() + + init { + reader.readNullString() + val headLength = reader.readInt32() + while (reader.position < headLength) { + directoryInfo.add( + DirectoryInfoNode( + offset = reader.readInt32().toLong(), + size = reader.readInt32().toLong(), + path = reader.readString(reader.readInt32()) + ) + ) + } + readFiles(reader, directoryInfo) + reader.close() + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/file/utils.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/file/utils.kt new file mode 100644 index 00000000..37624407 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/file/utils.kt @@ -0,0 +1,45 @@ +package io.github.deficuet.unitykt.internal.file + +import io.github.deficuet.unitykt.util.CompressUtils +import io.github.deficuet.unitykt.util.EndianBinaryReader +import io.github.deficuet.unitykt.util.runThenReset + +internal fun readerFileType(reader: EndianBinaryReader): FileType { + if (reader.length < 20) return FileType.RESOURCE + when (reader.runThenReset { readNullString(20) }) { + "UnityWeb", "UnityRaw", "UnityArchive", "UnityFS" -> return FileType.BUNDLE + "UnityWebData1.0" -> return FileType.WEB + else -> { + var magic = reader.runThenReset { read(2) } + if (CompressUtils.GZIP_MAGIC.contentEquals(magic)) { + return FileType.GZIP + } + magic = with(reader) { + position = 0x20 + runThenReset { read(6) } + } + if (CompressUtils.BROTLI_MAGIC.contentEquals(magic)) { + return FileType.BROTLI + } + if (isSerializedFile(reader)) return FileType.ASSETS + return FileType.RESOURCE + } + } +} + +internal fun isSerializedFile(reader: EndianBinaryReader) = reader.runThenReset { + skip(4) //m_MetadataSize: UInt + var mFileSize = readUInt32().toLong() + val mVersion = readUInt32() + var mDataOffset = readUInt32().toLong() + skip(4) //m_Endian(1), m_Reserved(3) + if (mVersion > 22u) { + if (length < 48) { + return@runThenReset false + } + skip(4) //m_MetadataSize: UInt + mFileSize = readInt64() + mDataOffset = readInt64() + } + return@runThenReset mFileSize == length && mDataOffset <= length +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/AnimationClipImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/AnimationClipImpl.kt new file mode 100644 index 00000000..08b848c2 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/AnimationClipImpl.kt @@ -0,0 +1,690 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.* +import io.github.deficuet.unitykt.enums.ClassIDType +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile +import io.github.deficuet.unitykt.math.Quaternion +import io.github.deficuet.unitykt.math.Vector3 +import io.github.deficuet.unitykt.util.* +import kotlin.math.sqrt + +internal class AnimationClipImpl( + assetFile: SerializedFile, info: ObjectInfo +): AnimationClip, AnimationClipFields(assetFile, info) { + override val mAnimationType: AnimationType get() { + checkInitialize() + return fmAnimationType + } + override val mLegacy: Boolean get() { + checkInitialize() + return fmLegacy + } + override val mCompressed: Boolean get() { + checkInitialize() + return fmCompressed + } + override val mUseHighQualityCurve: Boolean get() { + checkInitialize() + return fmUseHighQualityCurve + } + override val mRotationCurves: Array get() { + checkInitialize() + return fmRotationCurves + } + override val mCompressedRotationCurves: Array get() { + checkInitialize() + return fmCompressedRotationCurves + } + override val mEulerCurves: Array get() { + checkInitialize() + return fmEulerCurves + } + override val mPositionCurves: Array get() { + checkInitialize() + return fmPositionCurves + } + override val mScaleCurves: Array get() { + checkInitialize() + return fmScaleCurves + } + override val mFloatCurves: Array get() { + checkInitialize() + return fmFloatCurves + } + override val mPPtrCurves: Array get() { + checkInitialize() + return fmPPtrCurves + } + override val mSampleRate: Float get() { + checkInitialize() + return fmSampleRate + } + override val mWrapMode: Int get() { + checkInitialize() + return fmWrapMode + } + override val mBounds: AABBImpl? get() { + checkInitialize() + return fmBounds + } + override val mMuscleClipSize: UInt get() { + checkInitialize() + return fmMuscleClipSize + } + override val mMuscleClip: ClipMuscleConstantImpl? get() { + checkInitialize() + return fmMuscleClip + } + override val mClipBindingConstant: AnimationClipBindingConstantImpl? get() { + checkInitialize() + return fmClipBindingConstant + } + override val mEvents: Array get() { + checkInitialize() + return fmEvents + } + + override fun read() { + super.read() + val v43 = intArrayOf(4, 3) + fmLegacy = if (unityVersion[0] >= 5) { + fmAnimationType = AnimationType.Default + reader.readBool() + } else if (unityVersion[0] >= 4) { + fmAnimationType = AnimationType.of(reader.readInt32()) + fmAnimationType == AnimationType.Legacy + } else { + fmAnimationType = AnimationType.Default + true + } + fmCompressed = reader.readBool() + fmUseHighQualityCurve = if (unityVersion >= v43) reader.readBool() else false + reader.alignStream() + fmRotationCurves = reader.readArrayOf { QuaternionCurveImpl(this) } + fmCompressedRotationCurves = reader.readArrayOf { CompressedAnimationCurveImpl(this) } + fmEulerCurves = if (unityVersion >= intArrayOf(5, 3)) { + reader.readArrayOf { Vector3CurveImpl(this) } + } else emptyArray() + fmPositionCurves = reader.readArrayOf { Vector3CurveImpl(this) } + fmScaleCurves = reader.readArrayOf { Vector3CurveImpl(this) } + fmFloatCurves = reader.readArrayOf { FloatCurveImpl(this) } + fmPPtrCurves = if (unityVersion >= v43) { + reader.readArrayOf { PPtrCurveImpl(this) } + } else emptyArray() + fmSampleRate = reader.readFloat() + fmWrapMode = reader.readInt32() + fmBounds = if (unityVersion >= intArrayOf(3, 4)) AABBImpl(reader) else null + if (unityVersion[0] >= 4) { + fmMuscleClipSize = reader.readUInt32() + fmMuscleClip = ClipMuscleConstantImpl(reader) + } else { + fmMuscleClipSize = 0u; fmMuscleClip = null + } + fmClipBindingConstant = if (unityVersion >= v43) AnimationClipBindingConstantImpl(reader) else null + if (unityVersion >= intArrayOf(2018, 3)) { + reader.skip(2) //m_HasGenericRootTransform, m_HasMotionFloatCurves: Boolean + reader.alignStream() + } + fmEvents = reader.readArrayOf { AnimationEventImpl(this) } + if (unityVersion[0] >= 2017) reader.alignStream() + } +} + +internal class KeyFrameImpl(reader: ObjectReader, readerFunc: () -> T): KeyFrame { + override val time = reader.readFloat() + override val value = readerFunc() + override val inSlope = readerFunc() + override val outSlope = readerFunc() + override val weightedMode: Int + override val inWeight: T? + override val outWeight: T? + + init { + if (reader.unityVersion[0] >= 2018) { + weightedMode = reader.readInt32() + inWeight = readerFunc() + outWeight = readerFunc() + } else { + weightedMode = 0; inWeight = null; outWeight = null + } + } +} + +internal class AnimationCurveImpl(reader: ObjectReader, readerFunc: () -> T): AnimationCurve { + override val mCurve: Array> = reader.readArrayOf { KeyFrameImpl(this, readerFunc) } + override val mPreInfinity = reader.readInt32() + override val mPostInfinity = reader.readInt32() + override val mRotationOrder = if (reader.unityVersion >= intArrayOf(5, 3)) reader.readInt32() else 0 +} + +internal class QuaternionCurveImpl(reader: ObjectReader): QuaternionCurve { + override val curve = AnimationCurveImpl(reader, reader::readQuaternion) + override val path = reader.readAlignedString() +} + +internal class PackedFloatVectorImpl(reader: ObjectReader): PackedFloatVector { + override val mNumItems = reader.readUInt32() + override val mRange = reader.readFloat() + override val mStart = reader.readFloat() + override val mData: ByteArray + override val mBitSize: UByte + + init { + mData = reader.read(reader.readInt32()) + reader.alignStream() + mBitSize = reader.readUInt8() + reader.alignStream() + } + + override fun unpackFloats(itemCountInChunk: Int, chunkStride: Int, start: Int, chunkCount: Int): FloatArray { + val bitSize = mBitSize.toInt() + var bitPos = start * bitSize + var indexPos = (bitPos / 8).toUInt() + bitPos %= 8 + val scale = 1.0f / mRange + val numChunks = if (chunkCount == -1) { + mNumItems.toInt() / itemCountInChunk + } else chunkCount + val end = chunkStride * numChunks / 4 + val data = mutableListOf() + var idx = 0 + while (idx != end) { + for (i in 0 until itemCountInChunk) { + var x = 0u + var bits = 0 + while (bits < bitSize) { + x = x.or(mData[indexPos].shr(bitPos).shl(bits).toUInt()) + val num = minOf(bitSize - bits, 8 - bitPos) + bitPos += num; bits += num + if (bitPos == 8) { + indexPos++; bitPos = 0 + } + } + x = x.and(1u.shl(bitSize) - 1u) + data.add(x.toFloat() / (scale * (1.shl(bitSize) - 1)) + mStart) + } + idx += chunkStride / 4 + } + return data.toFloatArray() + } +} + +internal class PackedIntVectorImpl: PackedIntVector { + override var mNumItems: UInt + override val mData: ByteArray + override var mBitSize: UByte + + @Suppress("ConvertSecondaryConstructorToPrimary") + constructor(reader: ObjectReader) { + mNumItems = reader.readUInt32() + mData = reader.read(reader.readInt32()) + reader.alignStream() + mBitSize = reader.readUInt8() + reader.alignStream() + } + + override fun unpackInts(): IntArray { + val data = IntArray(mNumItems.toInt()) + var indexPos = 0u; var bitPos = 0 + val bitSize = mBitSize.toInt() + for (i in 0 until mNumItems.toInt()) { + var bits = 0; var value = 0 + while (bits < bitSize) { + value = value.or(mData[indexPos].shr(bitPos).shl(bits)) + val num = minOf(bitSize - bits, 8 - bitPos) + bitPos += num; bits += num + if (bitPos == 8) { + indexPos++; bitPos = 0 + } + } + data[i] = value.and(1.shl(bitSize) - 1) + } + return data + } +} + +internal class PackedQuatVectorImpl(reader: ObjectReader): PackedQuatVector { + override val mNumItems = reader.readUInt32() + override val mData: ByteArray + + init { + mData = reader.read(reader.readInt32()) + reader.alignStream() + } + + override fun unpackQuats(): Array { + val data = Array(mNumItems.toInt()) { Quaternion.Zero } + var indexPos = 0u; var bitPos = 0 + for (i in 0 until mNumItems.toInt()) { + var flags = 0u; var bits = 0 + while (bits < 3) { + flags = flags.or((mData[indexPos].shr(bitPos).shl(bits)).toUInt()) + val num = minOf(3 - bits, 8 - bitPos) + bitPos += num; bits += num + if (bitPos == 8) { + indexPos++; bitPos = 0 + } + } + flags = flags.and(7u) + val qFloats = FloatArray(4) + var sum = 0f + for (j in 0u..3u) { + if ((flags.and(3u)) != j) { + val bitSize = if (((flags.and(3u)) + 1u) % 4u == j) 9 else 10 + var x = 0u; bits = 0 + while (bits < bitSize) { + x = x.or(((mData[indexPos].shr(bitPos)).shl(bits)).toUInt()) + val num = minOf(bitSize - bits, 8 - bitPos) + bitPos += num; bits += num + if (bitPos == 8) { + indexPos++; bitPos = 0 + } + } + x = x.and(1u.shl(bitSize) - 1u) + val f = x.toFloat() / (0.5f * (1.shl(bitSize) - 1)) - 1 + sum += f * f + qFloats[j.toInt()] = f + } + } + val qLast = (flags.and(3u)).toInt() + qFloats[qLast] = sqrt(1 - sum) + if ((flags.and(4u)) != 0u) qFloats[qLast] = -qFloats[qLast] + data[i] = Quaternion(qFloats[0], qFloats[1], qFloats[2], qFloats[3]) + } + return data + } +} + +internal class CompressedAnimationCurveImpl(reader: ObjectReader): CompressedAnimationCurve { + override val mPath = reader.readAlignedString() + override val mTimes = PackedIntVectorImpl(reader) + override val mValues = PackedQuatVectorImpl(reader) + override val mSlopes = PackedFloatVectorImpl(reader) + override val mPreInfinity = reader.readInt32() + override val mPostInfinity = reader.readInt32() +} + +internal class Vector3CurveImpl(reader: ObjectReader): Vector3Curve { + override val curve = AnimationCurveImpl(reader, reader::readVector3) + override val path = reader.readAlignedString() +} + +internal class FloatCurveImpl(reader: ObjectReader): FloatCurve { + override val curve = AnimationCurveImpl(reader, reader::readFloat) + override val attribute = reader.readAlignedString() + override val path = reader.readAlignedString() + override val classID: ClassIDType + override val script: PPtr + + init { + val id = reader.readInt32() + classID = ClassIDType.of(id) + script = PPtrImpl(reader) + } +} + +internal class PPtrKeyFrameImpl(reader: ObjectReader): PPtrKeyFrame { + override val time = reader.readFloat() + override val value = PPtrImpl(reader) +} + +internal class PPtrCurveImpl(reader: ObjectReader): PPtrCurve { + override val curve = reader.readArrayOf { PPtrKeyFrameImpl(this) } + override val attribute = reader.readAlignedString() + override val path = reader.readAlignedString() + override val classID = reader.readInt32() + override val script = PPtrImpl(reader) +} + +internal class AABBImpl(reader: ObjectReader): AABB { + override val mCenter = reader.readVector3() + override val mExtent = reader.readVector3() +} + +internal class XFormImpl(reader: ObjectReader): XForm { + override val t: Vector3 + override val q: Quaternion + override val s: Vector3 + + init { + val version = reader.unityVersion + val v = intArrayOf(5, 4) + t = if (version >= v) reader.readVector3() else reader.readVector4().vector3 + q = reader.readQuaternion() + s = if (version >= v) reader.readVector3() else reader.readVector4().vector3 + } +} + +internal class HandPoseImpl(reader: ObjectReader): HandPose { + override val mGrabX = XFormImpl(reader) + override val mDoFArray = reader.readFloatArray() + override val mOverride = reader.readFloat() + override val mCloseOpen = reader.readFloat() + override val mInOut = reader.readFloat() + override val mGrab = reader.readFloat() +} + +internal class HumanGoalImpl(reader: ObjectReader): HumanGoal { + override val mX = XFormImpl(reader) + override val mWeightT = reader.readFloat() + override val mWeightR = reader.readFloat() + override val mHintT: Vector3 + override val mHintWeightT: Float + + init { + val version = reader.unityVersion + if (version[0] > 5) { + mHintT = if (version >= intArrayOf(5, 4)) reader.readVector3() else reader.readVector4().vector3 + mHintWeightT = reader.readFloat() + } else { + mHintT = Vector3.Zero + mHintWeightT = 0f + } + } +} + +internal class HumanPoseImpl(reader: ObjectReader): HumanPose { + override val mRootX = XFormImpl(reader) + override val mLookAt = if (reader.unityVersion >= intArrayOf(5, 4)) reader.readVector3() else reader.readVector4().vector3 + override val mLookAtWeight = reader.readVector4() + override val mGoalArray = reader.readArrayOf { HumanGoalImpl(this) } + override val mLeftHandPose = HandPoseImpl(reader) + override val mRightHandPose = HandPoseImpl(reader) + override val mDoFArray = reader.readFloatArray() + override val mTDoFArray = if (reader.unityVersion >= intArrayOf(5, 2)) { + reader.readArrayOf { + if (unityVersion >= intArrayOf(5, 4)) readVector3() else readVector4().vector3 + } + } else emptyArray() +} + +internal class StreamedCurveKeyImpl(reader: EndianBinaryReader): StreamedCurveKey { + override val index = reader.readInt32() + override val coeff = reader.readFloatArray(4) + override val outSlope = coeff[2] + override val value = coeff[3] + override var inSlope = 0f + + override fun nextInSlope(deltaX: Float, rhs: StreamedCurveKey): Float { + if (coeff[0] == 0f && coeff[1] == 0f && coeff[2] == 0f) return Float.POSITIVE_INFINITY + val dx = maxOf(deltaX, 0.0001f) + val dy = rhs.value - value + val length = 1f / dx / dx + val d1 = outSlope * dx + val d2 = dy * 3 - d1 * 2 - coeff[1] / length + return d2 / dx + } +} + +internal class StreamedFrameImpl(reader: EndianBinaryReader): StreamedFrame { + override val time = reader.readFloat() + override val keyList = reader.readArrayOf { StreamedCurveKeyImpl(this) } +} + +internal class StreamedClipImpl(reader: ObjectReader): StreamedClip { + override val data = reader.readUInt32Array() + override val curveCount = reader.readUInt32() + + override fun readData(): List { + val frameList = mutableListOf() + val buffer = ByteArray(data.size * 4) { + data[it / 4].shr(24 - (it % 4) * 8).toByte() + } + EndianByteArrayReader(buffer).use { + while (it.position < it.length) { + frameList.add(StreamedFrameImpl(it)) + } + } + for (frameIdx in 2 until frameList.size) { + val frame = frameList[frameIdx] + for (curveKey in frame.keyList) { + for (i in frameIdx - 1 downTo 0) { + val preFrame = frameList[i] + val preCurveKey = preFrame.keyList.firstOrNull { it.index == curveKey.index } + if (preCurveKey != null) { + curveKey.inSlope = preCurveKey.nextInSlope(frame.time - preFrame.time, curveKey) + break + } + } + } + } + return frameList + } +} + +internal class DenseClipImpl(reader: ObjectReader): DenseClip { + override val mFrameCount = reader.readInt32() + override val mCurveCount = reader.readUInt32() + override val mSampleRate = reader.readFloat() + override val mBeginTime = reader.readFloat() + override val mSampleArray = reader.readFloatArray() +} + +internal class ConstantClipImpl(reader: ObjectReader): ConstantClip { + override val data = reader.readFloatArray() +} + +internal class ValueConstantImpl(reader: ObjectReader): ValueConstant { + override val mID = reader.readUInt32() + override val mTypeID: UInt + override val mType: UInt + override val mIndex: UInt + + init { + val version = reader.unityVersion + mTypeID = if (version < intArrayOf(5, 5)) { + reader.readUInt32() + } else 0u + mType = reader.readUInt32() + mIndex = reader.readUInt32() + } +} + +internal class ValueArrayConstantImpl(reader: ObjectReader): ValueArrayConstant { + override val mValueArray = reader.readArrayOf { ValueConstantImpl(this) } +} + +internal class GenericBindingImpl: GenericBinding { + override val path: UInt + override val attribute: UInt + override val script: PPtr? + override val typeID: ClassIDType + override val customType: UByte + override val isPPtrCurve: UByte + override val isIntCurve: UByte + + constructor(reader: ObjectReader) { + path = reader.readUInt32() + attribute = reader.readUInt32() + script = PPtrImpl(reader) + val version = reader.unityVersion + typeID = ClassIDType.of( + if (version >= intArrayOf(5, 6)) reader.readInt32() else reader.readUInt16().toInt() + ) + customType = reader.readUInt8() + isPPtrCurve = reader.readUInt8() + isIntCurve = if (version >= intArrayOf(2022, 1)) reader.readUInt8() else 0u + reader.alignStream() + } + + constructor(path: UInt, attribute: UInt, typeID: ClassIDType) { + this.path = path + this.attribute = attribute + this.typeID = typeID + script = null + customType = 0u + isPPtrCurve = 0u + isIntCurve = 0u + } +} + +internal class AnimationClipBindingConstantImpl: AnimationClipBindingConstant { + override val genericBindings: Array + override val pptrCurveMapping: Array> + + constructor(reader: ObjectReader) { + genericBindings = reader.readArrayOf { GenericBindingImpl(this) } + pptrCurveMapping = reader.readArrayOf { PPtrImpl(this) } + } + + constructor(genericBindingArray: Array) { + genericBindings = genericBindingArray + pptrCurveMapping = emptyArray() + } + + override fun findBinding(index: Int): GenericBinding? { + var curves = 0 + for (b in genericBindings) { + curves += if (b.typeID == ClassIDType.Transform) { + when (b.attribute) { + 1u, 3u, 4u -> 3 + 2u -> 4 + else -> 1 + } + } else 1 + if (curves > index) return b + } + return null + } +} + +internal class ClipImpl(reader: ObjectReader): Clip { + override val mStreamedClip = StreamedClipImpl(reader) + override val mDenseClip = DenseClipImpl(reader) + override val mConstantClip: ConstantClipImpl? + override val mBinding: ValueArrayConstantImpl? + + init { + val version = reader.unityVersion + mConstantClip = if (version >= intArrayOf(4, 3)) { + ConstantClipImpl(reader) + } else null + mBinding = if (version < intArrayOf(2018, 3)) { + ValueArrayConstantImpl(reader) + } else null + } + + override fun buildGenericBindings(): AnimationClipBindingConstantImpl { + if (mBinding == null) return AnimationClipBindingConstantImpl(emptyArray()) + val bindings = mutableListOf() + var i = 0 + while (i < mBinding.mValueArray.size) { + val value = mBinding.mValueArray[i] + val binding = when (value.mID) { + //CRC(PositionX) + //kBindTransformPosition + 4174552735u -> { + i += 3 + GenericBindingImpl(value.mID, 1u, ClassIDType.Transform) + } + //CRC(QuaternionX) + //kBindTransformRotation + 2211994246u -> { + i += 4 + GenericBindingImpl(value.mID, 2u, ClassIDType.Transform) + } + //CRC(ScaleX) + //kBindTransformScale + 1512518241u -> { + i += 3 + GenericBindingImpl(value.mID, 3u, ClassIDType.Transform) + } + else -> { + i += 1 + GenericBindingImpl(0u, value.mID, ClassIDType.Animator) + } + } + bindings.add(binding) + } + return AnimationClipBindingConstantImpl(bindings.toTypedArray()) + } +} + +internal class ValueDeltaImpl(reader: ObjectReader): ValueDelta { + override val mStart = reader.readFloat() + override val mStop = reader.readFloat() +} + +internal class ClipMuscleConstantImpl(reader: ObjectReader): ClipMuscleConstant { + override val mDeltaPose: HumanPose + override val mStartX: XForm + override val mStopX: XForm? + override val mLeftFootStartX: XForm + override val mRightFootStartX: XForm + override val mMotionStartX: XForm? + override val mMotionStopX: XForm? + override val mAverageSpeed: Vector3 + override val mClip: Clip + override val mStartTime: Float + override val mStopTime: Float + override val mOrientationOffsetY: Float + override val mLevel: Float + override val mCycleOffset: Float + override val mAverageAngularSpeed: Float + override val mIndexArray: IntArray + override val mValueArrayDelta: Array + override val mValueArrayReferencePose: FloatArray + override val mMirror: Boolean + override val mLoopTime: Boolean + override val mLoopBlend: Boolean + override val mLoopBlendOrientation: Boolean + override val mLoopBlendPositionY: Boolean + override val mLoopBlendPositionXZ: Boolean + override val mStartAtOrigin: Boolean + override val mKeepOriginalOrientation: Boolean + override val mKeepOriginalPositionY: Boolean + override val mKeepOriginalPositionXZ: Boolean + override val mHeightFromFeet: Boolean + + init { + mDeltaPose = HumanPoseImpl(reader) + mStartX = XFormImpl(reader) + val version = reader.unityVersion + val v55 = intArrayOf(5, 5) + mStopX = if (version >= v55) XFormImpl(reader) else null + mLeftFootStartX = XFormImpl(reader) + mRightFootStartX = XFormImpl(reader) + if (version[0] < 5) { + mMotionStartX = XFormImpl(reader) + mMotionStopX = XFormImpl(reader) + } else { + mMotionStartX = null + mMotionStopX = null + } + mAverageSpeed = if (version >= intArrayOf(5, 4)) reader.readVector3() else reader.readVector4().vector3 + mClip = ClipImpl(reader) + mStartTime = reader.readFloat() + mStopTime = reader.readFloat() + mOrientationOffsetY = reader.readFloat() + mLevel = reader.readFloat() + mCycleOffset = reader.readFloat() + mAverageAngularSpeed = reader.readFloat() + mIndexArray = reader.readInt32Array() + if (version < intArrayOf(4, 3)) reader.readInt32Array() //m_AdditionalCurveIndexArray: List + mValueArrayDelta = reader.readArrayOf { ValueDeltaImpl(this) } + mValueArrayReferencePose = if (version >= intArrayOf(5, 3)) reader.readFloatArray() else floatArrayOf() + mMirror = reader.readBool() + mLoopTime = if (version >= intArrayOf(4, 3)) reader.readBool() else false + mLoopBlend = reader.readBool() + mLoopBlendOrientation = reader.readBool() + mLoopBlendPositionY = reader.readBool() + mLoopBlendPositionXZ = reader.readBool() + mStartAtOrigin = if (version >= v55) reader.readBool() else false + mKeepOriginalOrientation = reader.readBool() + mKeepOriginalPositionY = reader.readBool() + mKeepOriginalPositionXZ = reader.readBool() + mHeightFromFeet = reader.readBool() + reader.alignStream() + } +} + +internal class AnimationEventImpl(reader: ObjectReader): AnimationEvent { + override val time = reader.readFloat() + override val functionName = reader.readAlignedString() + override val data = reader.readAlignedString() + override val objectReferenceParameter = PPtrImpl(reader) + override val floatParameter = reader.readFloat() + override val intParameter = if (reader.unityVersion[0] >= 3) reader.readInt32() else 0 + override val messageOptions = reader.readInt32() +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/AnimationImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/AnimationImpl.kt new file mode 100644 index 00000000..58397624 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/AnimationImpl.kt @@ -0,0 +1,23 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.Animation +import io.github.deficuet.unitykt.classes.AnimationClip +import io.github.deficuet.unitykt.classes.PPtr +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile +import io.github.deficuet.unitykt.util.readArrayOf + +internal class AnimationImpl( + assetFile: SerializedFile, info: ObjectInfo +): Animation, AnimationFields(assetFile, info) { + override val mAnimations: Array> get() { + checkInitialize() + return fmAnimations + } + + override fun read() { + super.read() + PPtrImpl(reader) + fmAnimations = reader.readArrayOf { PPtrImpl(this) } + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/AnimatorControllerImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/AnimatorControllerImpl.kt new file mode 100644 index 00000000..16815cd0 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/AnimatorControllerImpl.kt @@ -0,0 +1,317 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.* +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile +import io.github.deficuet.unitykt.math.Vector3 +import io.github.deficuet.unitykt.math.Vector4 +import io.github.deficuet.unitykt.util.ObjectReader +import io.github.deficuet.unitykt.util.compareTo +import io.github.deficuet.unitykt.util.readArrayOf + +internal class AnimatorControllerImpl( + assetFile: SerializedFile, info: ObjectInfo +): AnimatorController, AnimatorControllerFields(assetFile, info) { + override val mControllerSize: UInt get() { + checkInitialize() + return fmControllerSize + } + override val mController: ControllerConstant get() { + checkInitialize() + return fmController + } + override val mTOS: Map> get() { + checkInitialize() + return fmTOS + } + override val mAnimationClip: Array> get() { + checkInitialize() + return fmAnimationClip + } + + override fun read() { + super.read() + fmControllerSize = reader.readUInt32() + fmController = ControllerConstantImpl(reader) + fmTOS = reader.readArrayOf { readUInt32() to readAlignedString() } + .groupBy({ it.first }, { it.second }) + fmAnimationClip = reader.readArrayOf { PPtrImpl(this) } + } +} + +internal class HumanPoseMaskImpl(reader: ObjectReader): HumanPoseMask { + override val word0 = reader.readUInt32() + override val word1 = reader.readUInt32() + override val word2 = if (reader.unityVersion >= intArrayOf(5, 2)) reader.readUInt32() else 0u +} + +internal class SkeletonMaskElementImpl(reader: ObjectReader): SkeletonMaskElement { + override val mPathHash = reader.readUInt32() + override val mWeight = reader.readFloat() +} + +internal class SkeletonMaskImpl(reader: ObjectReader): SkeletonMask { + override val mData = reader.readArrayOf { SkeletonMaskElementImpl(this) } +} + +internal class LayerConstantImpl(reader: ObjectReader): LayerConstant { + override val mStateMachineIndex = reader.readUInt32() + override val mStateMachineMotionSetIndex = reader.readUInt32() + override val mBodyMask = HumanPoseMaskImpl(reader) + override val mSkeletonMask = SkeletonMaskImpl(reader) + override val mBinding = reader.readUInt32() + override val mLayerBlendingMode = reader.readInt32() + override val mDefaultWeight = if (reader.unityVersion >= intArrayOf(4, 2)) reader.readFloat() else 0f + override val mIKPass = reader.readBool() + override val mSyncedLayerAffectsTiming = if (reader.unityVersion >= intArrayOf(4, 2)) reader.readBool() else false + + init { reader.alignStream() } +} + +internal class ConditionConstantImpl(reader: ObjectReader): ConditionConstant { + override val mConditionMode = reader.readUInt32() + override val mEventID = reader.readUInt32() + override val mEventThreshold = reader.readFloat() + override val mExitTime = reader.readFloat() +} + +internal class TransitionConstantImpl(reader: ObjectReader): TransitionConstant { + override val mConditionConstantArray = reader.readArrayOf { ConditionConstantImpl(this) } + override val mDestinationState = reader.readUInt32() + override val mFullPathID = if (reader.unityVersion[0] >= 5) reader.readUInt32() else 0u + override val mID = reader.readUInt32() + override val mUserID = reader.readUInt32() + override val mTransitionDuration = reader.readFloat() + override val mTransitionOffset = reader.readFloat() + override val mExitTime: Float + override val mHasExitTime: Boolean + override val mHasFixedDuration: Boolean + override val mInterruptionSource: Int + override val mOrderedInterruption: Boolean + override val mAtomic: Boolean + override val mCanTransitionToSelf: Boolean + + init { + val version = reader.unityVersion + if (version[0] >= 5) { + mExitTime = reader.readFloat() + mHasExitTime = reader.readBool() + mHasFixedDuration = reader.readBool() + reader.alignStream() + mInterruptionSource = reader.readInt32() + mOrderedInterruption = reader.readBool() + mAtomic = false + } else { + mExitTime = 0f + mHasExitTime = false + mHasFixedDuration = false + mInterruptionSource = 0 + mOrderedInterruption = false + mAtomic = reader.readBool() + } + mCanTransitionToSelf = if (version >= intArrayOf(4, 5)) reader.readBool() else false + reader.alignStream() + } +} + +internal class LeafInfoConstantImpl(reader: ObjectReader): LeafInfoConstant { + override val mIDArray = reader.readUInt32Array() + override val mIndexOffset = reader.readUInt32() +} + +internal class MotionNeighborListImpl(reader: ObjectReader): MotionNeighborList { + override val mNeighborArray = reader.readUInt32Array() +} + +internal class Blend2dDataConstantImpl(reader: ObjectReader): Blend2dDataConstant { + override val mChildPositionArray = reader.readVector2Array() + override val mChildMagnitudeArray = reader.readFloatArray() + override val mChildPairVectorArray = reader.readVector2Array() + override val mChildPairAvgMagInvArray = reader.readFloatArray() + override val mChildNeighborListArray = reader.readArrayOf { MotionNeighborListImpl(this) } +} + +internal class Blend1dDataConstantImpl(reader: ObjectReader): Blend1dDataConstant { + override val mChildThresholdArray = reader.readFloatArray() +} + +internal class BlendDirectDataConstantImpl(reader: ObjectReader): BlendDirectDataConstant { + override val mChildBlendEventIDArray = reader.readUInt32Array() + override val mNormalizedBlendValues = reader.readBool() + + init { reader.alignStream() } +} + +internal class BlendTreeNodeConstantImpl(reader: ObjectReader): BlendTreeNodeConstant { + override val mBlendType: UInt + override val mBlendEventID: UInt + override val mBlendEventYID: UInt + override val mChildIndices: Array + override val mChildThresholdArray: FloatArray + override val mBlend1dData: Blend1dDataConstant? + override val mBlend2dData: Blend2dDataConstant? + override val mBlendDirectData: BlendDirectDataConstant? + override val mClipID: UInt + override val mClipIndex: UInt + override val mDuration: Float + override val mCycleOffset: Float + override val mMirror: Boolean + + init { + val version = reader.unityVersion + val v41 = intArrayOf(4, 1) + mBlendType = if (version >= v41) reader.readUInt32() else 0u + mBlendEventID = reader.readUInt32() + mBlendEventYID = if (version >= v41) reader.readUInt32() else 0u + mChildIndices = reader.readUInt32Array() + mChildThresholdArray = if (version < v41) reader.readFloatArray() else FloatArray(0) + if (version >= v41) { + mBlend1dData = Blend1dDataConstantImpl(reader) + mBlend2dData = Blend2dDataConstantImpl(reader) + } else { + mBlend1dData = null; mBlend2dData = null + } + mBlendDirectData = if (version[0] >= 5) BlendDirectDataConstantImpl(reader) else null + mClipID = reader.readUInt32() + mClipIndex = if (version[0] == 4 && version[1] >= 5) reader.readUInt32() else 0u + mDuration = reader.readFloat() + if (version >= intArrayOf(4, 1, 3)) { + mCycleOffset = reader.readFloat() + mMirror = reader.readBool() + reader.alignStream() + } else { + mCycleOffset = 0f; mMirror = false + } + } +} + +internal class BlendTreeConstantImpl(reader: ObjectReader): BlendTreeConstant { + override val mNodeArray = reader.readArrayOf { BlendTreeNodeConstantImpl(this) } + override val mBlendEventArrayConstant = if (reader.unityVersion < intArrayOf(4, 5)) { + ValueArrayConstantImpl(reader) + } else null +} + +internal class StateConstantImpl(reader: ObjectReader): StateConstant { + override val mTransitionConstantArray = reader.readArrayOf { TransitionConstantImpl(this) } + override val mBlendTreeConstantIndexArray = reader.readInt32Array() + override val mLeafInfoArray = if (reader.unityVersion < intArrayOf(5, 2)) { + reader.readArrayOf { LeafInfoConstantImpl(this) } + } else emptyArray() + override val mBlendTreeConstantArray = reader.readArrayOf { BlendTreeConstantImpl(this) } + override val mNameID = reader.readUInt32() + override val mPathID = if (reader.unityVersion >= intArrayOf(4, 3)) reader.readUInt32() else 0u + override val mFullPathID = if (reader.unityVersion[0] >= 5) reader.readUInt32() else 0u + override val mTagID = reader.readUInt32() + override val mSpeedParamID: UInt + override val mMirrorParamID: UInt + override val mCycleOffsetParamID: UInt + override val mTimeParamID: UInt + override val mSpeed: Float + override val mCycleOffset: Float + override val mIKOnFeet: Boolean + override val mWriteDefaultValues: Boolean + override val mLoop: Boolean + override val mMirror: Boolean + + init { + val version = reader.unityVersion + if (version >= intArrayOf(5, 1)) { + mSpeedParamID = reader.readUInt32() + mMirrorParamID = reader.readUInt32() + mCycleOffsetParamID = reader.readUInt32() + } else { + mSpeedParamID = 0u + mMirrorParamID = 0u + mCycleOffsetParamID = 0u + } + mTimeParamID = if (version >= intArrayOf(2017, 2)) reader.readUInt32() else 0u + mSpeed = reader.readFloat() + mCycleOffset = if (version >= intArrayOf(4, 1)) reader.readFloat() else 0f + mIKOnFeet = reader.readBool() + mWriteDefaultValues = if (version[0] >= 5) reader.readBool() else false + mLoop = reader.readBool() + mMirror = if (version >= intArrayOf(4, 1)) reader.readBool() else false + reader.alignStream() + } +} + +internal class SelectorTransitionConstantImpl(reader: ObjectReader): SelectorTransitionConstant { + override val mDestination = reader.readUInt32() + override val mConditionConstantArray = reader.readArrayOf { ConditionConstantImpl(this) } +} + +internal class SelectorStateConstantImpl(reader: ObjectReader): SelectorStateConstant { + override val mTransitionConstantArray = reader.readArrayOf { SelectorTransitionConstantImpl(this) } + override val mFullPathID = reader.readUInt32() + override val mIsEntry = reader.readBool() + + init { reader.alignStream() } +} + +internal class StateMachineConstantImpl(reader: ObjectReader): StateMachineConstant { + override val mStateConstantArray = reader.readArrayOf { StateConstantImpl(this) } + override val mAnyStateTransitionConstantArray = reader.readArrayOf { TransitionConstantImpl(this) } + override val mSelectorStateConstantArray = if (reader.unityVersion[0] >= 5) { + reader.readArrayOf { SelectorStateConstantImpl(this) } + } else emptyArray() + override val mDefaultState = reader.readUInt32() + override val mMotionSetCount = reader.readUInt32() +} + +internal class ValueArrayImpl(reader: ObjectReader): ValueArray { + override val mBoolValues: BooleanArray + override val mIntValues: IntArray + override val mFloatValues: FloatArray + override val mVectorValues: Array + override val mPositionValues: Array + override val mQuaternionValues: Array + override val mScaleValues: Array + + init { + val version = reader.unityVersion + val v55 = intArrayOf(5, 5); val v54 = intArrayOf(5, 4) + var bool = BooleanArray(0) + var ints = IntArray(0) + var floats = FloatArray(0) + if (version < v55) { + bool = reader.readBoolArray() + reader.alignStream() + ints = reader.readInt32Array() + floats = reader.readFloatArray() + } + if (version < intArrayOf(4, 3)) { + mVectorValues = reader.readVector4Array() + mPositionValues = emptyArray() + mQuaternionValues = emptyArray() + mScaleValues = emptyArray() + } else { + mVectorValues = emptyArray() + mPositionValues = reader.readArrayOf { + if (version >= v54) reader.readVector3() + else reader.readVector4().vector3 + } + mQuaternionValues = reader.readVector4Array() + mScaleValues = reader.readArrayOf { + if (version >= v54) reader.readVector3() + else reader.readVector4().vector3 + } + if (version >= v55) { + floats = reader.readFloatArray() + ints = reader.readInt32Array() + bool = reader.readBoolArray() + reader.alignStream() + } + } + mBoolValues = bool + mIntValues = ints + mFloatValues = floats + } +} + +internal class ControllerConstantImpl(reader: ObjectReader): ControllerConstant { + override val mLayerArray = reader.readArrayOf { LayerConstantImpl(this) } + override val mStateMachineArray = reader.readArrayOf { StateMachineConstantImpl(this) } + override val mValues = ValueArrayConstantImpl(reader) + override val mDefaultValues = ValueArrayImpl(reader) +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/AnimatorImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/AnimatorImpl.kt new file mode 100644 index 00000000..19b54b16 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/AnimatorImpl.kt @@ -0,0 +1,50 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.Animator +import io.github.deficuet.unitykt.classes.Avatar +import io.github.deficuet.unitykt.classes.PPtr +import io.github.deficuet.unitykt.classes.RuntimeAnimatorController +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile +import io.github.deficuet.unitykt.util.compareTo + +internal class AnimatorImpl( + assetFile: SerializedFile, info: ObjectInfo +): Animator, AnimatorFields(assetFile, info) { + override val mAvatar: PPtr get() { + checkInitialize() + return fmAvatar + } + override val mController: PPtr get() { + checkInitialize() + return fmController + } + override val mHasTransformHierarchy: Boolean get() { + checkInitialize() + return fmHasTransformHierarchy + } + + override fun read() { + super.read() + fmAvatar = PPtrImpl(reader) + fmController = PPtrImpl(reader) + reader.skip(4) //m_CullingMode: Int + val v45 = intArrayOf(4, 5) + if (unityVersion >= v45) reader.skip(4) //m_UpdateMode: Int + reader.skip(1) //m_ApplyRootMotion: Boolean + if (v45 <= unityVersion && unityVersion[0] < 5) reader.alignStream() + if (unityVersion[0] >= 5) { + reader.skip(1) //m_LinearVelocityBlending: Boolean + if (unityVersion >= intArrayOf(2021, 2)) reader.skip(1) //m_StabilizeFeet: Boolean + reader.alignStream() + } + if (unityVersion < v45) reader.skip(1) //m_AnimatePhysics: Boolean + fmHasTransformHierarchy = if (unityVersion >= intArrayOf(4, 3)) reader.readBool() else true + if (unityVersion >= v45) reader.skip(1) //m_AllowConstantClipSamplingOptimization: Boolean + if (unityVersion[0] in 5..2017) reader.alignStream() + if (unityVersion[0] >= 2018) { + reader.skip(1) //m_KeepAnimatorControllerStateOnDisable: Boolean + reader.alignStream() + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/AnimatorOverrideControllerImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/AnimatorOverrideControllerImpl.kt new file mode 100644 index 00000000..2838a88e --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/AnimatorOverrideControllerImpl.kt @@ -0,0 +1,31 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.* +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile +import io.github.deficuet.unitykt.util.ObjectReader +import io.github.deficuet.unitykt.util.readArrayOf + +internal class AnimatorOverrideControllerImpl( + assetFile: SerializedFile, info: ObjectInfo +): AnimatorOverrideController, AnimatorOverrideControllerFields(assetFile, info) { + override val mController: PPtr get() { + checkInitialize() + return fmController + } + override val mClips: Array get() { + checkInitialize() + return fmClips + } + + override fun read() { + super.read() + fmController = PPtrImpl(reader) + fmClips = reader.readArrayOf { AnimationClipOverrideImpl(this) } + } +} + +internal class AnimationClipOverrideImpl(reader: ObjectReader): AnimationClipOverride { + override val mOriginalClip = PPtrImpl(reader) + override val mOverrideClip = PPtrImpl(reader) +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/AssetBundleImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/AssetBundleImpl.kt new file mode 100644 index 00000000..221073a3 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/AssetBundleImpl.kt @@ -0,0 +1,74 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.AssetBundle +import io.github.deficuet.unitykt.classes.AssetInfo +import io.github.deficuet.unitykt.classes.PPtr +import io.github.deficuet.unitykt.classes.UnityObject +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile +import io.github.deficuet.unitykt.util.ObjectReader +import io.github.deficuet.unitykt.util.compareTo +import io.github.deficuet.unitykt.util.readArrayOf + +internal class AssetBundleImpl( + assetFile: SerializedFile, info: ObjectInfo +): AssetBundle, AssetBundleFields(assetFile, info) { + override val mPreloadTable: Array> get() { + checkInitialize() + return fmPreloadTable + } + override val mContainer: Map> get() { + checkInitialize() + return fmContainer + } + override val mMainAsset: AssetInfo get() { + checkInitialize() + return fmMainAsset + } + override val mRuntimeCompatibility: UInt get() { + checkInitialize() + return fmRuntimeCompatibility + } + override val mAssetBundleName: String get() { + checkInitialize() + return fmAssetBundleName + } + override val mDependencies: Array get() { + checkInitialize() + return fmDependencies + } + override val mIsStreamedSceneAssetBundle: Boolean get() { + checkInitialize() + return fmIsStreamedSceneAssetBundle + } + override val mExplicitDataLayout: Int get() { + checkInitialize() + return fmExplicitDataLayout + } + override val mPathFlags: Int get() { + checkInitialize() + return fmPathFlags + } + + override fun read() { + super.read() + fmPreloadTable = reader.readArrayOf { PPtrImpl(this) } + fmContainer = reader.readArrayOf { + readAlignedString() to AssetInfoImpl(this) + }.groupBy({ it.first }, { it.second }) + fmMainAsset = AssetInfoImpl(reader) + fmRuntimeCompatibility = reader.readUInt32() + fmAssetBundleName = reader.readAlignedString() + fmDependencies = reader.readAlignedStringArray() + fmIsStreamedSceneAssetBundle = reader.readBool() + reader.alignStream() + fmExplicitDataLayout = if (unityVersion >= intArrayOf(2017, 3)) reader.readInt32() else 0 + fmPathFlags = if (unityVersion >= intArrayOf(2017, 1, 0)) reader.readInt32() else 0 + } +} + +internal class AssetInfoImpl(reader: ObjectReader): AssetInfo { + override val preloadIndex = reader.readInt32() + override val preloadSize = reader.readInt32() + override val asset = PPtrImpl(reader) +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/AudioClipImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/AudioClipImpl.kt new file mode 100644 index 00000000..2ab25eaf --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/AudioClipImpl.kt @@ -0,0 +1,159 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.AudioClip +import io.github.deficuet.unitykt.classes.AudioCompressionFormat +import io.github.deficuet.unitykt.classes.FMODSoundType +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile +import io.github.deficuet.unitykt.util.ResourceReader +import io.github.deficuet.unitykt.util.compareTo + +internal class AudioClipImpl( + assetFile: SerializedFile, info: ObjectInfo +): AudioClip, AudioClipFields(assetFile, info) { + override val mFormat: Int get() { + checkInitialize() + return fmFormat + } + override val mType: FMODSoundType get() { + checkInitialize() + return fmType + } + override val m3D: Boolean get() { + checkInitialize() + return fm3D + } + override val mUseHardware: Boolean get() { + checkInitialize() + return fmUseHardware + } + override val mLoadType: Int get() { + checkInitialize() + return fmLoadType + } + override val mChannels: Int get() { + checkInitialize() + return fmChannels + } + override val mFrequency: Int get() { + checkInitialize() + return fmFrequency + } + override val mBitsPerSample: Int get() { + checkInitialize() + return fmBitsPerSample + } + override val mLength: Float get() { + checkInitialize() + return fmLength + } + override val mIsTrackerFormat: Boolean get() { + checkInitialize() + return fmIsTrackerFormat + } + override val mSubSoundIndex: Int get() { + checkInitialize() + return fmSubSoundIndex + } + override val mPreloadAudioData: Boolean get() { + checkInitialize() + return fmPreloadAudioData + } + override val mLoadInBackground: Boolean get() { + checkInitialize() + return fmLoadInBackground + } + override val mLegacy3D: Boolean get() { + checkInitialize() + return fmLegacy3D + } + override val mCompressionFormat: AudioCompressionFormat get() { + checkInitialize() + return fmCompressionFormat + } + override val mSource: String get() { + checkInitialize() + return fmSource + } + override val mOffset: Long get() { + checkInitialize() + return fmOffset + } + override val mSize: Long get() { + checkInitialize() + return fmSize + } + + private val audioData: ResourceReader get() { + checkInitialize() + return pfAudioData + } + + override fun read() { + super.read() + if (unityVersion[0] < 5) { + fmFormat = reader.readInt32() + fmType = FMODSoundType.of(reader.readInt32()) + fm3D = reader.readBool() + fmUseHardware = reader.readBool() + reader.alignStream() + if (unityVersion >= intArrayOf(3, 2)) { + reader.skip(4) //m_Stream: Int + fmSize = reader.readInt32().toLong() + val tSize = if (fmSize % 4 != 0L) fmSize + 4 - fmSize % 4 else fmSize + if (reader.info.byteSize.toLong() + reader.info.byteStart - reader.absolutePosition != tSize) { + fmOffset = reader.readUInt32().toLong() + fmSource = "${assetFile.name}.resS" + } else { + fmOffset = 0 + fmSource = "" + } + } else { + fmSize = reader.readInt32().toLong() + fmOffset = 0 + fmSource = "" + } + fmLoadType = 0 + fmChannels = 0 + fmFrequency = 0 + fmBitsPerSample = 0 + fmLength = 0f + fmIsTrackerFormat = false + fmSubSoundIndex = 0 + fmPreloadAudioData = false + fmLoadInBackground = false + fmLegacy3D = false + fmCompressionFormat = AudioCompressionFormat.UNKNOWN + } else { + fmLoadType = reader.readInt32() + fmChannels = reader.readInt32() + fmFrequency = reader.readInt32() + fmBitsPerSample = reader.readInt32() + fmLength = reader.readFloat() + fmIsTrackerFormat = reader.readBool() + reader.alignStream() + fmSubSoundIndex = reader.readInt32() + fmPreloadAudioData = reader.readBool() + fmLoadInBackground = reader.readBool() + fmLegacy3D = reader.readBool() + reader.alignStream() + fmSource = reader.readAlignedString() + fmOffset = reader.readInt64() + fmSize = reader.readInt64() + fmCompressionFormat = AudioCompressionFormat.of(reader.readInt32()) + fmFormat = 0 + fmType = FMODSoundType.UNKNOWN + fm3D = false + fmUseHardware = false + } + pfAudioData = if (fmSource.isNotEmpty()) { + ResourceReader(fmSource, assetFile, fmOffset, fmSize) + } else { + ResourceReader(reader, reader.absolutePosition, fmSize) + }.registerToManager(assetFile.root.manager) + } + + override fun getRawData(): ByteArray { + return audioData.read() + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/AvatarImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/AvatarImpl.kt new file mode 100644 index 00000000..2bb0fbd1 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/AvatarImpl.kt @@ -0,0 +1,197 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.* +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile +import io.github.deficuet.unitykt.math.Vector +import io.github.deficuet.unitykt.util.ObjectReader +import io.github.deficuet.unitykt.util.compareTo +import io.github.deficuet.unitykt.util.readArrayOf + +internal class AvatarImpl( + assetFile: SerializedFile, info: ObjectInfo +): Avatar, AvatarFields(assetFile, info) { + override val mAvatarSize: UInt get() { + checkInitialize() + return fmAvatarSize + } + override val mAvatar: AvatarConstant get() { + checkInitialize() + return fmAvatar + } + override val mTOS: Map> get() { + checkInitialize() + return fmTOS + } + + override fun read() { + super.read() + fmAvatarSize = reader.readUInt32() + fmAvatar = AvatarConstantImpl(reader) + fmTOS = reader.readArrayOf { + with(reader) { readUInt32() to readAlignedString() } + }.groupBy({ it.first }, { it.second }) + } +} + +internal class NodeImpl(reader: ObjectReader): Node { + override val mParentId = reader.readInt32() + override val mAxesId = reader.readInt32() +} + +internal class LimitImpl(reader: ObjectReader): Limit { + override val mMin: Vector<*> + override val mMax: Vector<*> + + init { + if (reader.unityVersion >= intArrayOf(5, 4)) { + mMin = reader.readVector3() + mMax = reader.readVector3() + } else { + mMin = reader.readVector4() + mMax = reader.readVector4() + } + } +} + +internal class AxesImpl(reader: ObjectReader): Axes { + override val mPreQ = reader.readVector4() + override val mPostQ = reader.readVector4() + override val mSgn: Vector<*> + override val mLimit: Limit + override val mLength: Float + override val mType: UInt + + init { + mSgn = if (reader.unityVersion >= intArrayOf(5, 4)) { + reader.readVector3() + } else reader.readVector4() + mLimit = LimitImpl(reader) + mLength = reader.readFloat() + mType = reader.readUInt32() + } +} + +internal class SkeletonImpl(reader: ObjectReader): Skeleton { + override val mNode = reader.readArrayOf { NodeImpl(this) } + override val mID = reader.readUInt32Array() + override val mAxesArray = reader.readArrayOf { AxesImpl(this) } +} + +internal class SkeletonPoseImpl(reader: ObjectReader): SkeletonPose { + override val mX = reader.readArrayOf { XFormImpl(this) } +} + +internal class HandImpl(reader: ObjectReader): Hand { + override val mHandBoneIndex = reader.readInt32Array() +} + +internal class HandleImpl(reader: ObjectReader): Handle { + override val mX = XFormImpl(reader) + override val mParentHumanIndex = reader.readUInt32() + override val mID = reader.readUInt32() +} + +internal class ColliderImpl(reader: ObjectReader): Collider { + override val mX = XFormImpl(reader) + override val mType = reader.readUInt32() + override val mXMotionType = reader.readUInt32() + override val mYMotionType = reader.readUInt32() + override val mZMotionType = reader.readUInt32() + override val mMinLimitX = reader.readFloat() + override val mMaxLimitX = reader.readFloat() + override val mMaxLimitY = reader.readFloat() + override val mMaxLimitZ = reader.readFloat() +} + +internal class HumanImpl(reader: ObjectReader): Human { + override val mRootX = XFormImpl(reader) + override val mSkeleton = SkeletonImpl(reader) + override val mSkeletonPose = SkeletonPoseImpl(reader) + override val mLeftHand = HandImpl(reader) + override val mRightHand = HandImpl(reader) + override val mHandles: Array + override val mColliderArray: Array + override val mHumanBoneIndex: IntArray + override val mHumanBoneMass: FloatArray + override val mColliderIndex: IntArray + override val mScale: Float + override val mAriTwist: Float + override val mForeArmTwist: Float + override val mUpperLegTwist: Float + override val mLegTwist: Float + override val mArmStretch: Float + override val mLegStretch: Float + override val mFeetSpacing: Float + override val mHasLeftHand: Boolean + override val mHasRightHand: Boolean + override val mHasTDoF: Boolean + + init { + val version = reader.unityVersion + val v182 = intArrayOf(2018, 2) + if (version < v182) { + mHandles = reader.readArrayOf { HandleImpl(this) } + mColliderArray = reader.readArrayOf { ColliderImpl(this) } + } else { + mHandles = emptyArray(); mColliderArray = emptyArray() + } + mHumanBoneIndex = reader.readInt32Array() + mHumanBoneMass = reader.readFloatArray() + mColliderIndex = if (version < v182) reader.readInt32Array() else IntArray(0) + mScale = reader.readFloat() + mAriTwist = reader.readFloat() + mForeArmTwist = reader.readFloat() + mUpperLegTwist = reader.readFloat() + mLegTwist = reader.readFloat() + mArmStretch = reader.readFloat() + mLegStretch = reader.readFloat() + mFeetSpacing = reader.readFloat() + mHasLeftHand = reader.readBool() + mHasRightHand = reader.readBool() + mHasTDoF = if (version >= intArrayOf(5, 2)) reader.readBool() else false + reader.alignStream() + } +} + +internal class AvatarConstantImpl(reader: ObjectReader): AvatarConstant { + override val mAvatarSkeleton = SkeletonImpl(reader) + override val mAvatarSkeletonPose = SkeletonPoseImpl(reader) + override val mDefaultPose: SkeletonPose? + override val mSkeletonNameIDArray: Array + override val mHuman: Human + override val mHumanSkeletonIndexArray: IntArray + override val mHumanSkeletonReverseIndexArray: IntArray + override val mRootMotionBoneIndex: Int + override val mRootMotionBoneX: XForm + override val mRootMotionSkeleton: Skeleton? + override val mRootMotionSkeletonPose: SkeletonPose? + override val mRootMotionSkeletonIndexArray: IntArray + + init { + val version = reader.unityVersion + val v43 = intArrayOf(4, 3) + if (version >= v43) { + mDefaultPose = SkeletonPoseImpl(reader) + mSkeletonNameIDArray = reader.readUInt32Array() + } else { + mDefaultPose = null; mSkeletonNameIDArray = emptyArray() + } + mHuman = HumanImpl(reader) + mHumanSkeletonIndexArray = reader.readInt32Array() + mHumanSkeletonReverseIndexArray = if (version >= v43) { + reader.readInt32Array() + } else IntArray(0) + mRootMotionBoneIndex = reader.readInt32() + mRootMotionBoneX = XFormImpl(reader) + if (version >= v43) { + mRootMotionSkeleton = SkeletonImpl(reader) + mRootMotionSkeletonPose = SkeletonPoseImpl(reader) + mRootMotionSkeletonIndexArray = reader.readInt32Array() + } else { + mRootMotionSkeleton = null + mRootMotionSkeletonPose = null + mRootMotionSkeletonIndexArray = IntArray(0) + } + } +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/BehaviourImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/BehaviourImpl.kt new file mode 100644 index 00000000..eec7105a --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/BehaviourImpl.kt @@ -0,0 +1,20 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.Behaviour +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile + +internal abstract class BehaviourImpl( + assetFile: SerializedFile, info: ObjectInfo +): Behaviour, BehaviourFields(assetFile, info) { + final override val mEnabled: Byte get() { + checkInitialize() + return fmEnabled + } + + override fun read() { + super.read() + fmEnabled = reader.readInt8() + reader.alignStream() + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/CanvasImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/CanvasImpl.kt new file mode 100644 index 00000000..b8fac09e --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/CanvasImpl.kt @@ -0,0 +1,77 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.Canvas +import io.github.deficuet.unitykt.classes.PPtr +import io.github.deficuet.unitykt.classes.UnityObject +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile + +internal class CanvasImpl( + assetFile: SerializedFile, info: ObjectInfo +): Canvas, CanvasFields(assetFile, info) { + override val mRenderMode: Int get() { + checkInitialize() + return fmRenderMode + } + override val mCamera: PPtr get() { + checkInitialize() + return fmCamera + } + override val mPlaneDistance: Float get() { + checkInitialize() + return fmPlaneDistance + } + override val mPixelPerfect: Boolean get() { + checkInitialize() + return fmPixelPerfect + } + override val mReceivesEvent: Boolean get() { + checkInitialize() + return fmReceivesEvent + } + override val mOverrideSorting: Boolean get() { + checkInitialize() + return fmOverrideSorting + } + override val mOverridePixelPerfect: Boolean get() { + checkInitialize() + return fmOverridePixelPerfect + } + override val mSortingBucketNormalizedSize: Float get() { + checkInitialize() + return fmSortingBucketNormalizedSize + } + override val mAdditionalShaderChannelsFlag: Int get() { + checkInitialize() + return fmAdditionalShaderChannelsFlag + } + override val mSortingLayerID: Int get() { + checkInitialize() + return fmSortingLayerID + } + override val mSortingOrder: Short get() { + checkInitialize() + return fmSortingOrder + } + override val mTargetDisplay: Byte get() { + checkInitialize() + return fmTargetDisplay + } + + override fun read() { + super.read() + fmRenderMode = reader.readInt32() + fmCamera = PPtrImpl(reader) + fmPlaneDistance = reader.readFloat() + fmPixelPerfect = reader.readBool() + fmReceivesEvent = reader.readBool() + fmOverrideSorting = reader.readBool() + fmOverridePixelPerfect = reader.readBool() + fmSortingBucketNormalizedSize = reader.readFloat() + fmAdditionalShaderChannelsFlag = reader.readInt32() + reader.alignStream() + fmSortingLayerID = reader.readInt32() + fmSortingOrder = reader.readInt16() + fmTargetDisplay = reader.readInt8() + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/ComponentImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/ComponentImpl.kt new file mode 100644 index 00000000..d88459aa --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/ComponentImpl.kt @@ -0,0 +1,21 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.Component +import io.github.deficuet.unitykt.classes.GameObject +import io.github.deficuet.unitykt.classes.PPtr +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile + +internal abstract class ComponentImpl( + assetFile: SerializedFile, info: ObjectInfo +): Component, ComponentFields(assetFile, info) { + final override val mGameObject: PPtr get() { + checkInitialize() + return fmGameObject + } + + override fun read() { + super.read() + fmGameObject = PPtrImpl(reader) + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/EditorExtensionImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/EditorExtensionImpl.kt new file mode 100644 index 00000000..0a606574 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/EditorExtensionImpl.kt @@ -0,0 +1,19 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.EditorExtension +import io.github.deficuet.unitykt.classes.UnityObject +import io.github.deficuet.unitykt.enums.BuildTarget +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile + +internal abstract class EditorExtensionImpl( + assetFile: SerializedFile, info: ObjectInfo +): EditorExtension, EditorExtensionFields(assetFile, info) { + override fun read() { + super.read() + if (platform == BuildTarget.NoTarget) { + PPtrImpl(reader) + PPtrImpl(reader) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/GameObjectImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/GameObjectImpl.kt new file mode 100644 index 00000000..6c50cb6f --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/GameObjectImpl.kt @@ -0,0 +1,83 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.* +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile +import io.github.deficuet.unitykt.util.compareTo +import io.github.deficuet.unitykt.util.readArrayOf + +internal class GameObjectImpl( + assetFile: SerializedFile, info: ObjectInfo +): GameObject, GameObjectFields(assetFile, info) { + override val mComponents: Array> get() { + checkInitialize() + return fmComponents + } + override val mLayer: UInt get() { + checkInitialize() + return fmLayer + } + override val mName: String get() { + checkInitialize() + return fmName + } + override val mTag: UShort get() { + checkInitialize() + return fmTag + } + override val mIsActive: Boolean get() { + checkInitialize() + return fmIsActive + } + override val mTransform: Transform get() { + checkInitialize() + return fmTransform + } + override val mMeshRenderer: MeshRenderer get() { + checkInitialize() + return fmMeshRenderer + } + override val mMeshFilter: MeshFilter get() { + checkInitialize() + return fmMeshFilter + } + override val mSkinnedMeshRenderer: SkinnedMeshRenderer get() { + checkInitialize() + return fmSkinnedMeshRenderer + } + override val mAnimator: Animator get() { + checkInitialize() + return fmAnimator + } + override val mAnimation: Animation get() { + checkInitialize() + return fmAnimation + } + + override fun read() { + super.read() + fmComponents = reader.readArrayOf { + if (unityVersion < intArrayOf(5, 5)) { + skip(4) //first: Int + } + val p = PPtrImpl(this) + val obj = p.safeGetObj() + if (obj != null) { + when (obj) { + is Transform -> fmTransform = obj + is MeshRenderer -> fmMeshRenderer = obj + is MeshFilter -> fmMeshFilter = obj + is SkinnedMeshRenderer -> fmSkinnedMeshRenderer = obj + is Animator -> fmAnimator = obj + is Animation -> fmAnimation = obj + } + } + p + } + reader.alignStream() + fmLayer = reader.readUInt32() + fmName = reader.readAlignedString() + fmTag = reader.readUInt16() + fmIsActive = reader.readBool() + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/MaterialImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/MaterialImpl.kt new file mode 100644 index 00000000..ab177d8b --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/MaterialImpl.kt @@ -0,0 +1,80 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.* +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile +import io.github.deficuet.unitykt.util.ObjectReader +import io.github.deficuet.unitykt.util.compareTo +import io.github.deficuet.unitykt.util.readArrayOf + +internal class MaterialImpl( + assetFile: SerializedFile, info: ObjectInfo +): Material, MaterialFields(assetFile, info) { + override val mShader: PPtr get() { + checkInitialize() + return fmShader + } + override val mSavedProperties: UnityPropertySheet get() { + checkInitialize() + return fmSavedProperties + } + + override fun read() { + super.read() + fmShader = PPtrImpl(reader) + if (unityVersion[0] == 4 && unityVersion[1] >= 1) { + reader.readAlignedStringArray() //m_ShaderKeywords + } + if (unityVersion >= intArrayOf(2021, 3)) { + reader.readAlignedStringArray() + reader.readAlignedStringArray() + } else if (unityVersion[0] >= 5) { + reader.readAlignedString() //m_ShaderKeywords + } + if (unityVersion[0] >= 5) { + reader.skip(4) //m_LightmapFlags: UInt + } + if (unityVersion >= intArrayOf(5, 6)) { + reader.skip(1) //m_EnableInstancingVariants: Boolean + reader.alignStream() + } + if (unityVersion >= intArrayOf(4, 3)) { + reader.skip(4) //m_CustomRenderQueue: Int + } + if (unityVersion >= intArrayOf(5, 1)) { + reader.readArrayOf { + reader.readAlignedString() //first + reader.readAlignedString() //second + } + } + if (unityVersion >= intArrayOf(5, 6)) { + reader.readAlignedStringArray() + } + fmSavedProperties = UnityPropertySheetImpl(reader) + } +} + +internal class UnityTexEnvImpl(reader: ObjectReader): UnityTexEnv { + override val mTexture = PPtrImpl(reader) + override val mScale = reader.readVector2() + override val mOffset = reader.readVector2() +} + +internal class UnityPropertySheetImpl(reader: ObjectReader): UnityPropertySheet { + override val mTexEnvs = reader.readArrayOf { + reader.readAlignedString() to UnityTexEnvImpl(reader) + }.groupBy({ it.first }, { it.second }) + override val mInts = if (reader.unityVersion[0] >= 2021) { + reader.readArrayOf { + readAlignedString() to readInt32() + }.groupBy({ it.first }, { it.second }) + } else { + emptyMap() + } + override val mFloats = reader.readArrayOf { + with(reader) { readAlignedString() to readFloat() } + }.groupBy({ it.first }, { it.second }) + override val mColors = reader.readArrayOf { + with(reader) { readAlignedString() to readColor4() } + }.groupBy({ it.first }, { it.second }) +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/MeshFilterImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/MeshFilterImpl.kt new file mode 100644 index 00000000..831fc27d --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/MeshFilterImpl.kt @@ -0,0 +1,21 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.Mesh +import io.github.deficuet.unitykt.classes.MeshFilter +import io.github.deficuet.unitykt.classes.PPtr +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile + +internal class MeshFilterImpl( + assetFile: SerializedFile, info: ObjectInfo +): MeshFilter, MeshFilterFields(assetFile, info) { + override val mMesh: PPtr get() { + checkInitialize() + return fmMesh + } + + override fun read() { + super.read() + fmMesh = PPtrImpl(reader) + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/MeshImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/MeshImpl.kt new file mode 100644 index 00000000..cf7ec640 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/MeshImpl.kt @@ -0,0 +1,1035 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.* +import io.github.deficuet.unitykt.enums.OrdinalEnumCompanion +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile +import io.github.deficuet.unitykt.math.Matrix4x4 +import io.github.deficuet.unitykt.math.Vector2 +import io.github.deficuet.unitykt.math.Vector3 +import io.github.deficuet.unitykt.util.* +import java.nio.ByteOrder +import kotlin.math.sqrt + +internal class MeshImpl( + assetFile: SerializedFile, info: ObjectInfo +): Mesh, MeshFields(assetFile, info) { + override val mSubMeshes: Array get() { + checkInitialize() + return fmSubMeshes + } + override val mShapes: BlendShapeData? get() { + checkInitialize() + return fmShapes + } + override val mIndices: Array get() { + checkInitialize() + return fmIndices + } + override val mBindPose: Array get() { + checkInitialize() + return fmBindPose + } + override val mBoneNameHashes: Array get() { + checkInitialize() + return fmBoneNameHashes + } + override val mVertexCount: Int get() { + checkInitialize() + return fmVertexCount + } + override val mVertices: FloatArray get() { + checkInitialize() + return fmVertices + } + override val mSkin: Array get() { + checkInitialize() + return fmSkin + } + override val mNormals: FloatArray get() { + checkInitialize() + return fmNormals + } + override val mColors: FloatArray get() { + checkInitialize() + return fmColors + } + override val mUV0: FloatArray get() { + checkInitialize() + return fmUV0 + } + override val mUV1: FloatArray get() { + checkInitialize() + return fmUV1 + } + override val mUV2: FloatArray get() { + checkInitialize() + return fmUV2 + } + override val mUV3: FloatArray get() { + checkInitialize() + return fmUV3 + } + override val mUV4: FloatArray get() { + checkInitialize() + return fmUV4 + } + override val mUV5: FloatArray get() { + checkInitialize() + return fmUV5 + } + override val mUV6: FloatArray get() { + checkInitialize() + return fmUV6 + } + override val mUV7: FloatArray get() { + checkInitialize() + return fmUV7 + } + override val mTangents: FloatArray get() { + checkInitialize() + return fmTangents + } + private var pmUse16BitIndices = true + private var pmIndexBuffer: Array = emptyArray() + private lateinit var pmVertexData: VertexDataImpl + private var pmCompressedMesh: CompressedMeshImpl? = null + private var pmStreamData: StreamingInfoImpl? = null + + override fun read() { + super.read() + pmUse16BitIndices = if (unityVersion < intArrayOf(3, 5)) reader.readInt32() > 0 else true + if (unityVersion <= intArrayOf(2, 5)) { + val indexBufferSize = reader.readInt32() + if (pmUse16BitIndices) { + pmIndexBuffer = reader.readArrayOf(indexBufferSize / 2) { reader.readUInt16().toUInt() } + reader.alignStream() + } else { + pmIndexBuffer = reader.readUInt32Array(indexBufferSize / 4) + } + } + fmSubMeshes = reader.readArrayOf { SubMashImpl(this) } + fmShapes = if (unityVersion >= intArrayOf(4, 1)) BlendShapeDataImpl(reader) else null + if (unityVersion >= intArrayOf(4, 3)) { + fmBindPose = reader.readMatrix4x4Array() + fmBoneNameHashes = reader.readUInt32Array() + reader.skip(4) //m_RootBoneNameHash: UInt + } + if (unityVersion >= intArrayOf(2, 6)) { + if (unityVersion[0] >= 2019) { + reader.readArrayOf { MinMaxAABBImpl(this) } //m_BonesAABB + reader.readUInt32Array() //m_VariableBoneCountWeights + } + val meshCompression = reader.readUInt8().toUInt() + if (unityVersion[0] >= 4) { + //m_StreamCompression: UByte, m_IsReadable, m_KeepVertices, m_KeepIndices: Boolean + reader.skip(if (unityVersion[0] < 5) 4 else 3) + } + reader.alignStream() + if ( + unityVersion >= intArrayOf(2017, 4) || + ((unityVersion[0] == 2017 && unityVersion[1] == 3 && unityVersion[2] == 1) && buildType.isPatch) || + ((unityVersion[0] == 2017 && unityVersion[1] == 3) && meshCompression == 0u) + ) { + pmUse16BitIndices = reader.readInt32() == 0 + } + val indexBufferSize = reader.readInt32() + if (pmUse16BitIndices) { + pmIndexBuffer = reader.readArrayOf(indexBufferSize / 2) { reader.readUInt16().toUInt() } + reader.alignStream() + } else { + pmIndexBuffer = reader.readUInt32Array(indexBufferSize / 4) + } + } + if (unityVersion < intArrayOf(3, 5)) { + fmVertexCount = reader.readInt32() + fmVertices = reader.readFloatArray(fmVertexCount * 3) + fmSkin = reader.readArrayOf { BoneWeights4Impl(this) } + fmBindPose = reader.readMatrix4x4Array() + fmUV0 = reader.readFloatArray(reader.readInt32() * 2) + fmUV1 = reader.readFloatArray(reader.readInt32() * 2) + if (unityVersion[0] == 2 && unityVersion[1] <= 5) { + val tangentSpaceSize = reader.readInt32() + fmNormals = FloatArray(tangentSpaceSize * 3) + fmTangents = FloatArray(tangentSpaceSize * 4) + for (v in 0 until tangentSpaceSize) { + fmNormals[v * 3] = reader.readFloat() + fmNormals[v * 3 + 1] = reader.readFloat() + fmNormals[v * 3 + 2] = reader.readFloat() + fmTangents[v * 3] = reader.readFloat() + fmTangents[v * 3 + 1] = reader.readFloat() + fmTangents[v * 3 + 2] = reader.readFloat() + fmTangents[v * 3 + 3] = reader.readFloat() + } + } else { + fmNormals = reader.readFloatArray(reader.readInt32() * 3) + fmTangents = reader.readFloatArray(reader.readInt32() * 4) + } + } else { + if (unityVersion < intArrayOf(2018, 2)) { + fmSkin = reader.readArrayOf { BoneWeights4Impl(this) } + } + if (unityVersion[0] == 3 || (unityVersion[0] == 4 && unityVersion[1] <= 2)) { + fmBindPose = reader.readMatrix4x4Array() + } + pmVertexData = VertexDataImpl(reader) + } + if (unityVersion >= intArrayOf(2, 6)) { + pmCompressedMesh = CompressedMeshImpl(reader) + } + reader.skip(24) //AABB m_LocalAABB + if (unityVersion <= intArrayOf(3, 4)) { + fmColors = FloatArray(reader.readInt32() * 4) { + (reader.readUInt8() / 0xFFu).toFloat() + } + reader.skip(reader.readInt32() * 4 + 4) //m_CollisionVertexCount + } + reader.skip(4) //m_MeshUsageFlags: Int + if (unityVersion >= intArrayOf(2022, 1)) { + reader.skip(4) //m_CookingOptions + } + if (unityVersion[0] >= 5) { + reader.readInt8Array() //m_BakedConvexCollisionMesh + reader.alignStream() + reader.readInt8Array() //m_BakedTriangleCollisionMesh + reader.alignStream() + } + if (unityVersion >= intArrayOf(2018, 2)) { + reader.skip(8) //m_MeshMetrics: float[2] + } + if (unityVersion >= intArrayOf(2018, 3)) { + reader.alignStream() + pmStreamData = StreamingInfoImpl(reader) + } + processData() + } + + private fun processData() { + val sd = pmStreamData + if (sd?.path?.isNotEmpty() == true) { + if (pmVertexData.mVertexCount > 0u) { + ResourceReader( + sd.path, assetFile, sd.offset, sd.size.toLong() + ).use { + pmVertexData.mDataSize = it.read() + } + } + } + if (unityVersion >= intArrayOf(3, 5)) { + readVertexData() + } + if (unityVersion >= intArrayOf(2, 6)) { + decompressMesh() + } + getTriangles() + } + + private fun readVertexData() { + fmVertexCount = pmVertexData.mVertexCount.toInt() + for (chn in pmVertexData.mChannels.indices) { + val channel = pmVertexData.mChannels[chn] + if (channel.dimension > 0u) { + val stream = pmVertexData.mStreams[channel.stream.toInt()] + if (stream.channelMask.and(1u.shl(chn)) != 0u) { + if (unityVersion[0] < 2018 && chn == 2 && channel.format == 2u.toUByte()) { + channel.dimension = 4u + } + val vertexFormat = MeshHelper.toVertexFormat(channel.format, unityVersion) + val componentByteSize = vertexFormat.size.toInt() + val componentBytes = ByteArray( + fmVertexCount * channel.dimension.toInt() * componentByteSize + ) + for (v in 0 until fmVertexCount) { + val vertexOffset = stream.offset.toInt() + channel.offset.toInt() + stream.stride.toInt() * v + for (d in 0 until channel.dimension.toInt()) { + val componentOffset = vertexOffset + componentByteSize * d + val buff = pmVertexData.mDataSize[componentOffset, componentByteSize] + if (reader.endian == ByteOrder.LITTLE_ENDIAN && componentByteSize > 1) { + buff.reverse() + } + System.arraycopy( + buff, 0, componentBytes, + componentByteSize * (channel.dimension.toInt() * v + d), + componentByteSize + ) + } + } + var fa: FloatArray; var ia: IntArray + if (vertexFormat.isIntFormat) { + ia = componentBytes.toIntArray(vertexFormat) + fa = FloatArray(0) + } else { + fa = componentBytes.toFloatArray(vertexFormat) + ia = IntArray(0) + } + if (unityVersion[0] >= 2018) { + when (chn) { + 0 -> fmVertices = fa + 1 -> fmNormals = fa + 2 -> fmTangents = fa + 3 -> fmColors = fa + 4 -> fmUV0 = fa + 5 -> fmUV1 = fa + 6 -> fmUV2 = fa + 7 -> fmUV3 = fa + 8 -> fmUV4 = fa + 9 -> fmUV5 = fa + 10 -> fmUV6 = fa + 11 -> fmUV7 = fa + 12 -> { + if (fmSkin.isEmpty()) { + fmSkin = reader.readArrayOf(fmVertexCount) { BoneWeights4Impl() } + } + for (i in 0 until fmVertexCount) { + for (j in 0 until channel.dimension.toInt()) { + fmSkin[i].weight[j] = fa[i * channel.dimension.toInt() + j] + } + } + } + 13 -> { + if (fmSkin.isEmpty()) { + fmSkin = reader.readArrayOf(fmVertexCount) { BoneWeights4Impl() } + } + for (i in 0 until fmVertexCount) { + for (j in 0 until channel.dimension.toInt()) { + fmSkin[i].boneIndex[j] = ia[i * channel.dimension.toInt() + j] + } + } + } + } + } else { + when (chn) { + 0 -> fmVertices = fa + 1 -> fmNormals = fa + 2 -> fmColors = fa + 3 -> fmUV0 = fa + 4 -> fmUV1 = fa + 5 -> { + if (unityVersion[0] >= 5) { + fmUV2 = fa + } else { + fmTangents = fa + } + } + 6 -> fmUV3 = fa + 7 -> fmTangents = fa + } + } + } + } + } + } + + private fun decompressMesh() { + val cm = pmCompressedMesh + if (cm!!.mVertices.mNumItems > 0u) { + fmVertexCount = (cm.mVertices.mNumItems / 3u).toInt() + fmVertices = cm.mVertices.unpackFloats(3, 12) + } + if (cm.mUV.mNumItems > 0u) { + val uvInfo = cm.mUVInfo + if (uvInfo != 0u) { + var uvSrcOffset = 0 + for (uv in 0 until kMaxTexCoordShaderChannels) { + var texCoordBits = uvInfo.shr(uv * kInfoBitsPerUV) + texCoordBits = texCoordBits.and(1u.shl(kInfoBitsPerUV) - 1u) + if (texCoordBits.and(kUVChannelExists) != 0u) { + val uvDim = 1 + texCoordBits.and(kUVDimensionMask).toInt() + val mUV = cm.mUV.unpackFloats( + uvDim, uvDim * 4, uvSrcOffset, fmVertexCount + ) + //region setUV + when (uv) { + 0 -> fmUV0 = mUV + 1 -> fmUV1 = mUV + 2 -> fmUV2 = mUV + 3 -> fmUV3 = mUV + 4 -> fmUV4 = mUV + 5 -> fmUV5 = mUV + 6 -> fmUV6 = mUV + 7 -> fmUV7 = mUV + else -> throw IndexOutOfBoundsException() + } + //endregion + uvSrcOffset += uvDim * fmVertexCount + } + } + } else { + fmUV0 = cm.mUV.unpackFloats( + 2, 8, 0, fmVertexCount + ) + if (cm.mUV.mNumItems >= (fmVertexCount * 4).toUInt()) { + fmUV1 = cm.mUV.unpackFloats( + 2, 8, fmVertexCount * 2, fmVertexCount + ) + } + } + if (unityVersion[0] < 5 && cm.mBindPoses!!.mNumItems > 0u) { + val unpackedBindPose = cm.mBindPoses.unpackFloats(16, 64) + fmBindPose = reader.readArrayIndexedOf( + (cm.mBindPoses.mNumItems / 16u).toInt() + ) { + Matrix4x4( + Array(4) { col -> + FloatArray(4) { row -> + unpackedBindPose[it * 16 + col * 4 + row] + } + } + ) + } + } + if (cm.mNormals.mNumItems > 0u) { + val normalData = cm.mNormals.unpackFloats(2, 8) + val signs = cm.mNormalSigns.unpackInts() + fmNormals = FloatArray((cm.mNormals.mNumItems / 2u * 3u).toInt()) + for (i in 0 until (cm.mNormals.mNumItems / 2u).toInt()) { + var x = normalData[i * 2] + var y = normalData[i * 2 + 1] + val zsqr = 1 - x * x - y * y + var z: Float + if (zsqr >= 0f) { + z = sqrt(zsqr) + } else { + z = 0f + with(Vector2(x, y).unit) { + x = this.x + y = this.y + } + } + if (signs[i] == 0) z = -z + fmNormals[i * 3] = x + fmNormals[i * 3 + 1] = y + fmNormals[i * 3 + 2] = z + } + } + if (cm.mTangents.mNumItems > 0u) { + val tangentData = cm.mTangents.unpackFloats(2, 8) + val signs = cm.mTangentSigns.unpackInts() + fmTangents = FloatArray((cm.mTangents.mNumItems / 2u * 4u).toInt()) + for (i in 0 until (cm.mTangents.mNumItems / 2u).toInt()) { + var x = tangentData[i * 2] + var y = tangentData[i * 2 + 1] + val zsqr = 1 - x * x - y * y + var z: Float + if (zsqr >= 0f) { + z = sqrt(zsqr) + } else { + z = 0f + with(Vector2(x, y).unit) { + x = this.x + y = this.y + } + } + if (signs[i * 2] == 0) z = -z + val w = if (signs[i * 2 + 1] > 0) 1f else -1f + fmTangents[i * 4] = x + fmTangents[i * 4 + 1] = y + fmTangents[i * 4 + 2] = z + fmTangents[i * 4 + 3] = w + } + } + if (unityVersion[0] >= 5) { + if (cm.mFloatColors!!.mNumItems > 0u) { + fmColors = cm.mFloatColors.unpackFloats(1, 4) + } + } + if (cm.mWeights.mNumItems > 0u) { + val weights = cm.mWeights.unpackInts() + val boneIndices = cm.mBoneIndices.unpackInts() + fmSkin = reader.readArrayOf(fmVertexCount) { BoneWeights4Impl() } + var bonePos = 0; var boneIndexPos = 0; var j = 0; var sum = 0 + for (i in 0 until cm.mWeights.mNumItems.toInt()) { + with(fmSkin[bonePos]) { + weight[j] = weights[i] / 31f + boneIndex[j] = boneIndices[boneIndexPos++] + } + j++; sum += weights[i] + if (sum >= 31) { + while (j < 4) { + with(fmSkin[bonePos]) { + weight[j] = 0f + boneIndex[j] = 0 + } + j++ + } + bonePos++ + j = 0; sum = 0 + } else if (j == 3) { + with(fmSkin[bonePos]) { + weight[j] = (31 - sum) / 31f + boneIndex[j] = boneIndices[boneIndexPos++] + } + bonePos++ + j = 0; sum = 0 + } + } + } + if (cm.mTriangles.mNumItems > 0u) { + pmIndexBuffer = with(cm.mTriangles.unpackInts()) { Array(size) { this[it].toUInt() } } + } + if (with(cm.mColors) { this != null && mNumItems > 0u }) { + cm.mColors!!.mNumItems *= 4u + cm.mColors!!.mBitSize = (cm.mColors.mBitSize / 4u).toUByte() + val tempColors = cm.mColors.unpackInts() + fmColors = FloatArray(cm.mColors.mNumItems.toInt()) { + tempColors[it] / 255f + } + } + } + } + + private fun getTriangles() { + val indices = mutableListOf() + for (subMesh in fmSubMeshes) { + var firstIdx = (subMesh.firstByte / 2u).toInt() + if (!pmUse16BitIndices) { + firstIdx /= 2 + } + val indexCount = subMesh.indexCount.toInt() + if (subMesh.topology == GfxPrimitiveType.Triangles) { + for (i in 0 until indexCount step 3) { + with(indices) { + add(pmIndexBuffer[firstIdx + i]) + add(pmIndexBuffer[firstIdx + i + 1]) + add(pmIndexBuffer[firstIdx + i + 2]) + } + } + } else if (unityVersion[0] < 4 || subMesh.topology == GfxPrimitiveType.TriangleStrip) { + var triIndex = 0u + for (i in 0 until indexCount - 2) { + val a = pmIndexBuffer[firstIdx + i] + val b = pmIndexBuffer[firstIdx + i + 1] + val c = pmIndexBuffer[firstIdx + i + 2] + if (a == b || a == c || b == c) continue + if (i.and(1) == 1) { + indices.add(b) + indices.add(a) + } else { + indices.add(a) + indices.add(b) + } + indices.add(c) + triIndex += 3u + } + subMesh.indexCount = triIndex + } else if (subMesh.topology == GfxPrimitiveType.Quads) { + for (q in 0 until indexCount step 4) { + for (x in intArrayOf(0, 1, 2, 0, 2, 3)) { + indices.add(pmIndexBuffer[firstIdx + q + x]) + } + } + subMesh.indexCount = (indexCount / 2 * 3).toUInt() + } else { + throw IllegalStateException("Failed getting triangles. Submesh topology is lines or points.") + } + } + fmIndices = indices.toTypedArray() + } + + private fun ByteArray.toIntArray(vertexFormat: VertexFormat): IntArray { + val len = size / vertexFormat.size.toInt() + return IntArray(len) { + val i = it.toUInt() + when (vertexFormat) { + VertexFormat.UInt8, + VertexFormat.SInt8 -> this[i] + VertexFormat.UInt16, + VertexFormat.SInt16 -> parseUInt16(this, i * 2u).toShort().toInt() + VertexFormat.UInt32, + VertexFormat.SInt32 -> parseInt(this, i * 4u) + else -> { 0 } + } + } + } + + private fun ByteArray.toFloatArray(vertexFormat: VertexFormat): FloatArray { + val len = size / vertexFormat.size.toInt() + return FloatArray(len) { + val i = it.toUInt() + when (vertexFormat) { + VertexFormat.Float -> parseFloat(this, i * 4u) + VertexFormat.Float16 -> { + parseHalf(this, i * 2u) + } + VertexFormat.UNorm8 -> { + this[i] / 255f + } + VertexFormat.SNorm8 -> { + maxOf(this[it] / 127f, -1f) + } + VertexFormat.UNorm16 -> { + parseUInt16(this, i * 2u) / 65536f + } + VertexFormat.SNorm16 -> { + maxOf(parseUInt16(this, i * 2u).toShort() / 32767f, -1f) + } + else -> { 0f } + } + } + } + + override fun exportString(): String { + if (mVertexCount < 0) return "" + val builder = StringBuilder() + builder.append("g $mName\r\n") + if (mVertices.isEmpty()) return "" + var c = if (mVertices.size == mVertexCount * 4) 4 else 3 + for (v in 0 until mVertexCount) { + builder.append("v ${-mVertices[v * c]} ${mVertices[v * c + 1]} ${mVertices[v * c + 2]}\r\n") + } + if (mUV0.isNotEmpty()) { + c = when (mUV0.size) { + mVertexCount * 2 -> 2 + mVertexCount * 3 -> 3 + else -> 4 + } + for (vt in 0 until mVertexCount) { + builder.append("vt ${mUV0[vt * c]} ${mUV0[vt * c + 1]}\r\n") + } + } + if (mNormals.isNotEmpty()) { + when(mNormals.size) { + mVertexCount * 3 -> c = 3 + mVertexCount * 4 -> c = 4 + } + for (vn in 0 until mVertexCount) { + builder.append("vn ${-mNormals[vn * c]} ${mNormals[vn * c + 1]} ${mNormals[vn * c + 2]}\r\n") + } + } + var sum = 0 + for (i in mSubMeshes.indices) { + builder.append("g ${mName}_$i\r\n") + val end = sum + mSubMeshes[i].indexCount.toInt() / 3 + for (f in sum until end) { + val v0 = mIndices[f * 3 + 2] + 1u + val v1 = mIndices[f * 3 + 1] + 1u + val v2 = mIndices[f * 3] + 1u + builder.append("f $v0/$v0/$v0 $v1/$v1/$v1 $v2/$v2/$v2\r\n") + } + sum = end + } + return builder.toString().replace("NaN", "0") + } + + override fun exportVertices(): Array { + val c = if (mVertices.size == mVertexCount * 4) 4 else 3 + return Array(mVertexCount) { Vector3(mVertices[it * c], mVertices[it * c + 1], mVertices[it * c + 2]) } + } + + override fun exportUV(): Array { + return if (mUV0.isEmpty()) { + emptyArray() + } else { + val c = when (mUV0.size) { + mVertexCount * 2 -> 2 + mVertexCount * 3 -> 3 + else -> 4 + } + Array(mVertexCount) { Vector2(mUV0[it * c], mUV0[it * c + 1]) } + } + } + + override fun exportNormals(): Array { + return if (mNormals.isEmpty()) { + emptyArray() + } else { + var c = when (mUV0.size) { + mVertexCount * 2 -> 2 + mVertexCount * 3 -> 3 + else -> 4 + } + when(mNormals.size) { + mVertexCount * 3 -> c = 3 + mVertexCount * 4 -> c = 4 + } + Array(mVertexCount) { Vector3(mNormals[it * c], mNormals[it * c + 1], mNormals[it * c + 2]) } + } + } + + override fun exportFaces(): Array> { + var sum = 0 + return Array(mSubMeshes.size) { i -> + val end = sum + mSubMeshes[i].indexCount.toInt() / 3 + val a = Array(end - sum) { f -> + Vector3( + (mIndices[(f + sum) * 3 + 2] + 1u).toFloat(), + (mIndices[(f + sum) * 3 + 1] + 1u).toFloat(), + (mIndices[(f + sum) * 3] + 1u).toFloat() + ) + } + sum = end + a + } + } + + companion object { + private const val kInfoBitsPerUV = 4 + private const val kUVDimensionMask = 3u + private const val kUVChannelExists = 4u + private const val kMaxTexCoordShaderChannels = 8 + } +} + +internal class MeshHelper private constructor() { + companion object { + private val vertexFormatMap = mapOf( + VertexChannelFormat.Float to VertexFormat.Float, + VertexChannelFormat.Float16 to VertexFormat.Float16, + VertexChannelFormat.Color to VertexFormat.UNorm8, + VertexChannelFormat.Byte to VertexFormat.UInt8, + VertexChannelFormat.UInt32 to VertexFormat.UInt32 + ) + + private val vertexFormat2017Map = mapOf( + *Array(VertexFormat2017.array.size) { + when(val vf2017 = VertexFormat2017.of(it)) { + VertexFormat2017.Color -> vf2017 to VertexFormat.UNorm8 + else -> vf2017 to VertexFormat.valueOf(vf2017.name) + } + } + ) + + internal fun toVertexFormat(i: UByte, version: IntArray): VertexFormat { + return if (version[0] < 2017) { + val vcf = VertexChannelFormat.of(i.toInt()) + vertexFormatMap[vcf] ?: throw NoSuchElementException(vcf.name) + } else if (version[0] < 2019) { + val vf2017 = VertexFormat2017.of(i.toInt()) + vertexFormat2017Map[vf2017] ?: throw NoSuchElementException(vf2017.name) + } else { + VertexFormat.of(i.toInt()) + } + } + } +} + +internal enum class VertexChannelFormat { + Float, + Float16, + Color, + Byte, + UInt32; + + companion object: OrdinalEnumCompanion(values()) +} + +internal enum class VertexFormat2017 { + Float, + Float16, + Color, + UNorm8, + SNorm8, + UNorm16, + SNorm16, + UInt8, + SInt8, + UInt16, + SInt16, + UInt32, + SInt32; + + companion object: OrdinalEnumCompanion(values()) +} + +internal enum class VertexFormat(val size: UInt) { + Float(4u), + Float16(2u), + UNorm8(1u), + SNorm8(1u), + UNorm16(2u), + SNorm16(2u), + UInt8(1u), + SInt8(1u), + UInt16(2u), + SInt16(2u), + UInt32(4u), + SInt32(4u); + + val isIntFormat get() = this >= UInt8 + + companion object: OrdinalEnumCompanion(values()) +} + +internal class MinMaxAABBImpl(reader: EndianBinaryReader): MinMaxAABB { + override val mMin = reader.readVector3() + override val mMax = reader.readVector3() +} + +internal class CompressedMeshImpl(reader: ObjectReader): CompressedMesh { + override val mVertices = PackedFloatVectorImpl(reader) + override val mUV = PackedFloatVectorImpl(reader) + override val mBindPoses = if (reader.unityVersion[0] < 5) PackedFloatVectorImpl(reader) else null + override val mNormals = PackedFloatVectorImpl(reader) + override val mTangents = PackedFloatVectorImpl(reader) + override val mWeights = PackedIntVectorImpl(reader) + override val mNormalSigns = PackedIntVectorImpl(reader) + override val mTangentSigns = PackedIntVectorImpl(reader) + override val mFloatColors = if (reader.unityVersion[0] >= 5) PackedFloatVectorImpl(reader) else null + override val mBoneIndices = PackedIntVectorImpl(reader) + override val mTriangles = PackedIntVectorImpl(reader) + override val mColors: PackedIntVectorImpl? + override val mUVInfo: UInt + + init { + if (reader.unityVersion >= intArrayOf(3, 5)) { + if (reader.unityVersion[0] < 5) { + mColors = PackedIntVectorImpl(reader) + mUVInfo = 0u + } else { + mUVInfo = reader.readUInt32() + mColors = null + } + } else { + mUVInfo = 0u + mColors = null + } + } +} + +internal class StreamInfoImpl: StreamInfo { + override val channelMask: UInt + override val offset: UInt + override val stride: UInt + override val align: UInt + override val dividerOp: UByte + override val frequency: UShort + + internal constructor(reader: ObjectReader) { + channelMask = reader.readUInt32() + offset = reader.readUInt32() + if (reader.unityVersion[0] < 4) { + stride = reader.readUInt32() + align = reader.readUInt32() + dividerOp = 0u + frequency = 0u + } else { + stride = reader.readUInt8().toUInt() + dividerOp = reader.readUInt8() + frequency = reader.readUInt16() + align = 0u + } + } + + internal constructor(c: UInt, o: UInt, s: UInt, d: UByte, f: UShort) { + channelMask = c + offset = o + stride = s + align = 0u + dividerOp = d + frequency = f + } +} + +internal class ChannelInfoImpl: ChannelInfo { + override var stream: UByte + internal set + override var offset: UByte + internal set + override var format: UByte + internal set + override var dimension: UByte + internal set + + constructor(reader: ObjectReader) { + stream = reader.readUInt8() + offset = reader.readUInt8() + format = reader.readUInt8() + dimension = reader.readUInt8().and(0xfu) + } + + constructor() { + stream = 0u + offset = 0u + format = 0u + dimension = 0u + } +} + +internal class VertexDataImpl(reader: ObjectReader): VertexData { + override val mCurrentChannels = if (reader.unityVersion[0] < 2018) reader.readUInt32() else 0u + override val mVertexCount = reader.readUInt32() + override val mChannels: Array + override val mStreams: Array + override lateinit var mDataSize: ByteArray + internal set + + init { + val version = reader.unityVersion + var channels = emptyArray() + if (version[0] >= 4) { + channels = reader.readArrayOf { ChannelInfoImpl(this) } + } + if (version[0] < 5) { + val streamSize = if (version[0] < 4) 4 else reader.readInt32() + mStreams = reader.readArrayOf(streamSize) { StreamInfoImpl(this) } + if (version[0] < 4) { + //region getChannels + channels = Array(6) { ChannelInfoImpl() } + for (s in mStreams.indices) { + val stream = mStreams[s] +// val channelMask = BitSet.valueOf(longArrayOf(stream.channelMask.toLong())) + var offset: UByte = 0u + for (j in 0..5) { + if (stream.channelMask.and(1u.shl(j)) != 0u) { + val channel = channels[j] + channel.stream = s.toUByte() + channel.offset = offset + when (j) { + 0, 1 -> { + channel.format = 0u + channel.dimension = 3u + } + 2 -> { + channel.format = 2u + channel.dimension = 4u + } + 3, 4 -> { + channel.format = 0u + channel.dimension = 2u + } + 5 -> { + channel.format = 0u + channel.dimension = 4u + } + } + val inc = channel.dimension * MeshHelper.toVertexFormat(channel.format, version).size + offset = (offset + inc).toUByte() + } + } + } + //endregion + } + } else { + //region getStream + var offset = 0u + mStreams = Array(channels.maxOf { it.stream }.toInt() + 1) { + var chnMask = 0u + var stride = 0u + for (chn in channels.indices) { + val channel = channels[chn] + if (channel.stream.toInt() == it && channel.dimension > 0u) { + chnMask = chnMask.or(1u.shl(chn)) + stride += channel.dimension * MeshHelper.toVertexFormat(channel.format, version).size + } + } + val stream = StreamInfoImpl( + chnMask, offset, stride, 0u, 0u + ) + offset += mVertexCount * stride + offset = (offset + 15u).and(15u.inv()) + stream + } + //endregion + } + mDataSize = reader.readInt8Array() + mChannels = channels + } +} + +internal class BoneWeights4Impl: BoneWeights4 { + override val weight: FloatArray + override val boneIndex: IntArray + + constructor(reader: ObjectReader) { + weight = reader.readFloatArray(4) + boneIndex = reader.readInt32Array(4) + } + + constructor() { + weight = FloatArray(4) + boneIndex = IntArray(4) + } +} + +internal class BlendShapeVertexImpl(reader: ObjectReader): BlendShapeVertex { + override val vertex = reader.readVector3() + override val normal = reader.readVector3() + override val tangent = reader.readVector3() + override val index = reader.readUInt32() +} + +internal class MeshBlendShapeImpl(reader: ObjectReader): MeshBlendShape { + override val firstVertex: UInt + override val vertexCount: UInt + override val hasNormals: Boolean + override val hasTangents: Boolean + + init { + val version = reader.unityVersion + val v43 = intArrayOf(4, 3) + if (version < v43) { + reader.readAlignedString() //name + } + firstVertex = reader.readUInt32() + vertexCount = reader.readUInt32() + if (version < v43) { + reader.skip(24) //aabbMinDelta, aabbMaxDelta: Vector3 + } + hasNormals = reader.readBool() + hasTangents = reader.readBool() + if (version >= v43) reader.alignStream() + } +} + +internal class MeshBlendShapeChannelImpl(reader: ObjectReader): MeshBlendShapeChannel { + override val name = reader.readAlignedString() + override val nameHash = reader.readUInt32() + override val frameIndex = reader.readInt32() + override val frameCount = reader.readInt32() +} + +internal class BlendShapeDataImpl(reader: ObjectReader): BlendShapeData { + override val vertices: Array + override val shapes: Array + override val channels: Array + override val fullWeights: FloatArray + + init { + if (reader.unityVersion >= intArrayOf(4, 3)) { + vertices = reader.readArrayOf { BlendShapeVertexImpl(this) } + shapes = reader.readArrayOf { MeshBlendShapeImpl(this) } + channels = reader.readArrayOf { MeshBlendShapeChannelImpl(this) } + fullWeights = reader.readFloatArray() + } else { + reader.readArrayOf { MeshBlendShapeImpl(this) } //m_Shapes + reader.alignStream() + reader.readArrayOf { BlendShapeVertexImpl(this) } //m_ShapeVertices + vertices = emptyArray() + shapes = emptyArray() + channels = emptyArray() + fullWeights = floatArrayOf() + } + } +} + +internal class GfxPrimitiveType private constructor() { + companion object { + const val Triangles = 0 + const val TriangleStrip = 1 + const val Quads = 2 + } +} + +internal class SubMashImpl(reader: ObjectReader): SubMash { + override val firstByte = reader.readUInt32() + override var indexCount = reader.readUInt32() + internal set + override val topology = reader.readInt32() + override val triangleCount = if (reader.unityVersion[0] < 4) reader.readUInt32() else 0u + override val baseVertex = if (reader.unityVersion >= intArrayOf(2017, 3)) reader.readUInt32() else 0u + override val firstVertex: UInt + override val vertexCount: UInt + override val localAABB: AABBImpl? + + init { + if (reader.unityVersion[0] >= 3) { + firstVertex = reader.readUInt32() + vertexCount = reader.readUInt32() + localAABB = AABBImpl(reader) + } else { + firstVertex = 0u + vertexCount = 0u + localAABB = null + } + } +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/MeshRendererImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/MeshRendererImpl.kt new file mode 100644 index 00000000..454d0e40 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/MeshRendererImpl.kt @@ -0,0 +1,9 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.MeshRenderer +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile + +internal class MeshRendererImpl( + assetFile: SerializedFile, info: ObjectInfo +): MeshRenderer, MeshRendererFields(assetFile, info) \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/MonoBehaviourImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/MonoBehaviourImpl.kt new file mode 100644 index 00000000..583bdcc5 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/MonoBehaviourImpl.kt @@ -0,0 +1,26 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.MonoBehaviour +import io.github.deficuet.unitykt.classes.MonoScript +import io.github.deficuet.unitykt.classes.PPtr +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile + +internal class MonoBehaviourImpl( + assetFile: SerializedFile, info: ObjectInfo +): MonoBehaviour, MonoBehaviourFields(assetFile, info) { + override val mScript: PPtr get() { + checkInitialize() + return fmScript + } + override val mName: String get() { + checkInitialize() + return fmName + } + + override fun read() { + super.read() + fmScript = PPtrImpl(reader) + fmName = reader.readAlignedString() + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/MonoScriptImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/MonoScriptImpl.kt new file mode 100644 index 00000000..9b00853e --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/MonoScriptImpl.kt @@ -0,0 +1,34 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.MonoScript +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile +import io.github.deficuet.unitykt.util.compareTo + +internal class MonoScriptImpl( + assetFile: SerializedFile, info: ObjectInfo +): MonoScript, MonoScriptFields(assetFile, info) { + override val mClassName: String get() { + checkInitialize() + return fmClassName + } + override val mNameSpace: String get() { + checkInitialize() + return fmNameSpace + } + override val mAssemblyName: String get() { + checkInitialize() + return fmAssemblyName + } + + override fun read() { + super.read() + if (unityVersion >= intArrayOf(3, 4)) reader.skip(4) //m_ExecutionOrder: Int + reader.skip(if (unityVersion[0] < 5) 4 else 16) //m_PropertiesHash: UInt/Bytes(16) + if (unityVersion < intArrayOf(3)) reader.readAlignedString() //m_PathName: String + fmClassName = reader.readAlignedString() + fmNameSpace = if (unityVersion >= intArrayOf(3)) reader.readAlignedString() else "" + fmAssemblyName = reader.readAlignedString() + if (unityVersion < intArrayOf(2018, 2)) reader.skip(1) //m_IsEditorScript: Boolean + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/MovieTextureImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/MovieTextureImpl.kt new file mode 100644 index 00000000..acf13f19 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/MovieTextureImpl.kt @@ -0,0 +1,32 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.AudioClip +import io.github.deficuet.unitykt.classes.MovieTexture +import io.github.deficuet.unitykt.classes.PPtr +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile + +internal class MovieTextureImpl( + assetFile: SerializedFile, info: ObjectInfo +): MovieTexture, MovieTextureFields(assetFile, info) { + override val mLoop: Boolean get() { + checkInitialize() + return fmLoop + } + override val mAudioClip: PPtr get() { + checkInitialize() + return fmAudioClip + } + override val mMovieData: ByteArray get() { + checkInitialize() + return fmMovieData + } + + override fun read() { + super.read() + fmLoop = reader.readBool() + reader.alignStream() + fmAudioClip = PPtrImpl(reader) + fmMovieData = reader.readInt8Array() + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/NamedObjectImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/NamedObjectImpl.kt new file mode 100644 index 00000000..6bb8fd85 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/NamedObjectImpl.kt @@ -0,0 +1,19 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.NamedObject +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile + +internal abstract class NamedObjectImpl( + assetFile: SerializedFile, info: ObjectInfo +): NamedObject, NamedObjectFields(assetFile, info) { + final override val mName: String get() { + checkInitialize() + return fmName + } + + override fun read() { + super.read() + fmName = reader.readAlignedString() + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/PPtrImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/PPtrImpl.kt new file mode 100644 index 00000000..8a1019aa --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/PPtrImpl.kt @@ -0,0 +1,105 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.cast +import io.github.deficuet.unitykt.classes.AssetBundle +import io.github.deficuet.unitykt.classes.PPtr +import io.github.deficuet.unitykt.classes.UnityObject +import io.github.deficuet.unitykt.internal.file.FormatVersion +import io.github.deficuet.unitykt.internal.file.SerializedFile +import io.github.deficuet.unitykt.util.ObjectReader + +@PublishedApi +internal class PPtrImpl: PPtr { + override var mFileID: Int + override var mPathID: Long + override val isNull: Boolean + get() = mPathID == 0L || mFileID < 0 + private val assetFile: SerializedFile + + constructor(reader: ObjectReader) { + mFileID = reader.readInt32() + mPathID = with(reader) { + if (formatVersion < FormatVersion.Unknown_14) reader.readInt32().toLong() + else reader.readInt64() + } + assetFile = reader.assetFile + } + + constructor(fileId: Int, pathId: Long, assetFile: SerializedFile) { + mFileID = fileId + mPathID = pathId + this.assetFile = assetFile + } + + private var obj: T? = null + + fun getCache() = obj + fun setCache(o: @UnsafeVariance T) { obj = o } + + fun getAssetFile(): SerializedFile? { + if (mFileID == 0) { + return assetFile + } + val fileIndex = mFileID - 1 + if (mFileID < 0 || fileIndex >= assetFile.externals.size) { + return null + } + val manager = assetFile.root.manager + val result = manager.assetFiles[assetFile.externals[fileIndex].name.lowercase()] + if (result != null) return result + if (manager.assetRootFolder == null) return null + val bundle = assetFile.objectMap[1L] ?: return null + if (bundle !is AssetBundle) return null + if (fileIndex >= bundle.mDependencies.size) return null + val dependencyName = bundle.mDependencies[fileIndex] + try { + manager.loadFile(manager.assetRootFolder.resolve(dependencyName), assetFile.root.readerConfig) + } catch (e: Exception) { + println("An error occurred during loading dependency file ${dependencyName}: ${e.message}") + return null + } + return manager.assetFiles[assetFile.externals[fileIndex].name.lowercase()] + } + + internal fun setObj(other: @UnsafeVariance T) { + val otherAssetFile = other.cast().assetFile + val name = otherAssetFile.name + if (name.contentEquals(assetFile.name)) { + mFileID = 0 + } else { + mFileID = assetFile.externals.indexOfFirst { it.name.contentEquals(name) } + if (mFileID == -1) { + assetFile.externals.add(SerializedFile.FileIdentifier.fromName(name)) + mFileID = assetFile.externals.size + } else { + mFileID += 1 + } + } + val manager = assetFile.root.manager + if (!manager.assetFiles.containsValue(otherAssetFile)) { + manager.assetFiles[name.lowercase()] = otherAssetFile + } + mPathID = other.mPathID + setCache(other) + } + + fun getObjFrom(assetFile: SerializedFile) = assetFile.objectMap[mPathID] +} + +@PublishedApi +internal inline fun PPtrImpl.safeGetObj(): T? { + val cache = getCache() + if (cache != null) return cache + return getAssetFile()?.let { + val obj = getObjFrom(it) + if (obj != null && obj is T) { + setCache(obj) + obj + } else { + null + } + } +} + +@PublishedApi +internal inline fun PPtrImpl.getObj(): T = safeGetObj()!! diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/PlayerSettingsImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/PlayerSettingsImpl.kt new file mode 100644 index 00000000..7bd75d29 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/PlayerSettingsImpl.kt @@ -0,0 +1,46 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.PlayerSettings +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile +import io.github.deficuet.unitykt.util.compareTo + +internal class PlayerSettingsImpl( + assetFile: SerializedFile, info: ObjectInfo +): PlayerSettings, PlayerSettingsFields(assetFile, info) { + override val companyName: String get() { + checkInitialize() + return fCompanyName + } + override val productName: String get() { + checkInitialize() + return fProductName + } + + override fun read() { + super.read() + if (unityVersion >= intArrayOf(5, 4)) { + reader.skip(16) //productGUID: ByteArray(16) + } + reader.skip(1) //AndroidProfiler: Boolean + reader.alignStream() + reader.skip(8) //defaultScreenOrientation, targetDevice: Int + if (unityVersion < intArrayOf(5, 3)) { + if (unityVersion[0] < 5) { + reader.skip(4) //targetPlatform: Int + if (unityVersion >= intArrayOf(4, 6)) { + reader.skip(4) //targetIOSGraphics: Int + } + } + reader.skip(4) //targetResolution: Int + } else { + reader.skip(1) //useOnDemandResources: Boolean + reader.alignStream() + } + if (unityVersion >= intArrayOf(3, 5)) { + reader.skip(4) //accelerometerFrequency: Int + } + fCompanyName = reader.readAlignedString() + fProductName = reader.readAlignedString() + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/RectTransformImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/RectTransformImpl.kt new file mode 100644 index 00000000..4d18c12b --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/RectTransformImpl.kt @@ -0,0 +1,40 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.RectTransform +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile +import io.github.deficuet.unitykt.math.Vector2 + +internal class RectTransformImpl( + assetFile: SerializedFile, info: ObjectInfo +): RectTransform, RectTransformFields(assetFile, info) { + override val mAnchorMin: Vector2 get() { + checkInitialize() + return fmAnchorMin + } + override val mAnchorMax: Vector2 get() { + checkInitialize() + return fmAnchorMax + } + override val mAnchoredPosition: Vector2 get() { + checkInitialize() + return fmAnchoredPosition + } + override val mSizeDelta: Vector2 get() { + checkInitialize() + return fmSizeDelta + } + override val mPivot: Vector2 get() { + checkInitialize() + return fmPivot + } + + override fun read() { + super.read() + fmAnchorMin = reader.readVector2() + fmAnchorMax = reader.readVector2() + fmAnchoredPosition = reader.readVector2() + fmSizeDelta = reader.readVector2() + fmPivot = reader.readVector2() + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/RendererImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/RendererImpl.kt new file mode 100644 index 00000000..3fc7a034 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/RendererImpl.kt @@ -0,0 +1,107 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.* +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile +import io.github.deficuet.unitykt.util.ObjectReader +import io.github.deficuet.unitykt.util.compareTo +import io.github.deficuet.unitykt.util.readArrayOf + +internal abstract class RendererImpl( + assetFile: SerializedFile, info: ObjectInfo +): Renderer, RendererFields(assetFile, info) { + final override val mMaterials: Array> get() { + checkInitialize() + return fmMaterials + } + final override val mStaticBatchInfo: StaticBatchInfo? get() { + checkInitialize() + return fmStaticBatchInfo + } + final override val mSubsetIndices: Array get() { + checkInitialize() + return fmSubsetIndices + } + + override fun read() { + super.read() + val v43 = intArrayOf(4, 3) + if (unityVersion[0] < 5) { + //m_Enabled, m_CastShadows, m_ReceiveShadows: Boolean, m_LightmapIndex: UByte + reader.skip(4) + } else { + if (unityVersion >= intArrayOf(5, 4)) { + reader.skip(3) //m_Enabled: Boolean, m_CastShadows, m_ReceiveShadows: UByte + if (unityVersion >= intArrayOf(2017, 2)) { + reader.skip(1) //m_DynamicOccludee: UByte + } + if (unityVersion[0] >= 2021) { + reader.skip(1) //m_StaticShadowCaster: UByte + } + reader.skip(3) //m_MotionVectors, m_LightProbeUsage, m_ReflectionProbeUsage: UByte + if (unityVersion >= intArrayOf(2019, 3)) { + reader.skip(1) //m_RayTracingMode: UByte + } + if (unityVersion[0] >= 2020) { + reader.skip(1) //m_RayTraceProcedural: UByte + } + reader.alignStream() + } else { + reader.skip(1) //m_Enabled: Boolean + reader.alignStream() + reader.skip(2) //m_CastShadows: UByte, m_ReceiveShadows: Boolean + reader.alignStream() + } + if (unityVersion[0] >= 2018) { + reader.skip(4) //m_RenderingLayerMask: UInt + } + if (unityVersion >= intArrayOf(2018, 3)) { + reader.skip(4) //m_RendererPriority + } + reader.skip(4) //m_LightmapIndex, m_LightmapIndexDynamic: UShort + } + if (unityVersion[0] >= 3) { + reader.skip(16) //m_LightmapTilingOffset: Vector4 + } + if (unityVersion[0] >= 5) { + reader.skip(16) //m_LightmapTilingOffsetDynamic: Vector4 + } + fmMaterials = reader.readArrayOf { PPtrImpl(reader) } + if (unityVersion[0] < 3) { + reader.skip(16) //m_LightmapTilingOffset: Vector4 + fmStaticBatchInfo = null + fmSubsetIndices = emptyArray() + } else { + if (unityVersion >= intArrayOf(5, 5)) { + fmStaticBatchInfo = StaticBatchInfoImpl(reader) + fmSubsetIndices = emptyArray() + } else { + fmSubsetIndices = reader.readUInt32Array() + fmStaticBatchInfo = null + } + PPtrImpl(reader) //m_StaticBatchRoot + } + if (unityVersion >= intArrayOf(5, 4)) { + PPtrImpl(reader) //m_ProbeAnchor + PPtrImpl(reader) //m_LightProbeVolumeOverride + } else if (unityVersion >= intArrayOf(3, 5)) { + reader.skip(1) //m_UseLightProbes: Boolean + reader.alignStream() + if (unityVersion[0] >= 5) { + reader.skip(4) //m_ReflectionProbeUsage: Int + } + PPtrImpl(reader) //m_LightProbeAnchor + } + if (unityVersion >= v43) { + //m_SortingLayer: Short / m_SortingLayerID: UInt + reader.skip(if (unityVersion.contentEquals(v43)) 2 else 4) + reader.skip(2) //m_SortingOrder: Short + reader.alignStream() + } + } +} + +internal class StaticBatchInfoImpl(reader: ObjectReader): StaticBatchInfo { + override val firstSubMesh = reader.readUInt16() + override val subMeshCount = reader.readUInt16() +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/ResourceManagerImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/ResourceManagerImpl.kt new file mode 100644 index 00000000..a703f38d --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/ResourceManagerImpl.kt @@ -0,0 +1,23 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.PPtr +import io.github.deficuet.unitykt.classes.ResourceManager +import io.github.deficuet.unitykt.classes.UnityObject +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile +import io.github.deficuet.unitykt.util.readArrayOf + +internal class ResourceManagerImpl( + assetFile: SerializedFile, info: ObjectInfo +): ResourceManager, ResourceManagerFields(assetFile, info) { + override val mContainer: Map>> get() { + checkInitialize() + return fmContainer + } + + override fun read() { + super.read() + fmContainer = reader.readArrayOf { readAlignedString() to PPtrImpl(reader) } + .groupBy({ it.first }, { it.second }) + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/RuntimeAnimatorControllerImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/RuntimeAnimatorControllerImpl.kt new file mode 100644 index 00000000..87a2eca2 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/RuntimeAnimatorControllerImpl.kt @@ -0,0 +1,9 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.RuntimeAnimatorController +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile + +internal abstract class RuntimeAnimatorControllerImpl( + assetFile: SerializedFile, info: ObjectInfo +): RuntimeAnimatorController, RuntimeAnimatorControllerFields(assetFile, info) \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/ShaderImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/ShaderImpl.kt new file mode 100644 index 00000000..a56f1a37 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/ShaderImpl.kt @@ -0,0 +1,1204 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.* +import io.github.deficuet.unitykt.internal.export.smolv.SmolvDecoder +import io.github.deficuet.unitykt.internal.export.spirv.Disassembler +import io.github.deficuet.unitykt.internal.export.spirv.Module +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile +import io.github.deficuet.unitykt.util.* +import io.github.deficuet.unitykt.util.decodeToString +import java.nio.ByteOrder +import kotlin.text.Regex +import kotlin.text.StringBuilder +import kotlin.text.format +import kotlin.text.get +import kotlin.text.isNotBlank +import kotlin.text.isNotEmpty +import kotlin.text.repeat +import kotlin.text.toInt + +internal class ShaderImpl( + assetFile: SerializedFile, info: ObjectInfo +): Shader, ShaderFields(assetFile, info) { + override val mScript: ByteArray get() { + checkInitialize() + return fmScript + } + override val decompressedSize: UInt get() { + checkInitialize() + return fDecompressedSize + } + override val mSubProgramBlob: ByteArray get() { + checkInitialize() + return fmSubProgramBlob + } + override val mParsedForm: SerializedShaderImpl? get() { + checkInitialize() + return fmParsedForm + } + override val platforms: Array get() { + checkInitialize() + return fPlatforms + } + override val offsets: Array> get() { + checkInitialize() + return fOffsets + } + override val compressedLengths: Array> get() { + checkInitialize() + return fCompressedLengths + } + override val decompressedLengths: Array> get() { + checkInitialize() + return fDecompressedLengths + } + override val compressedBlob: ByteArray get() { + checkInitialize() + return fCompressedBlob + } + + override fun read() { + super.read() + if (unityVersion >= intArrayOf(5, 5)) { + fmParsedForm = SerializedShaderImpl(reader) + fPlatforms = with(reader.readUInt32Array()) { + Array(size) { ShaderCompilerPlatform.of(this[it].toInt()) } + } + if (unityVersion >= intArrayOf(2019, 3)) { + fOffsets = reader.readNestedUInt32Array() + fCompressedLengths = reader.readNestedUInt32Array() + fDecompressedLengths = reader.readNestedUInt32Array() + } else { + fOffsets = arrayOf(reader.readUInt32Array()) + fCompressedLengths = arrayOf(reader.readUInt32Array()) + fDecompressedLengths = arrayOf(reader.readUInt32Array()) + } + fCompressedBlob = reader.readInt8Array() + reader.alignStream() + reader.readArrayOf { PPtrImpl(this) } //m_Dependencies + if (unityVersion[0] >= 2018) { + reader.readArrayOf { + reader.readAlignedString() + PPtrImpl(this) // m_NonModifiableTextures + } + } + reader.skip(1) //m_ShaderIsBaked + reader.alignStream() + + fmScript = ByteArray(0) + fDecompressedSize = 0u + fmSubProgramBlob = ByteArray(0) + } else { + fmScript = reader.readInt8Array() + reader.alignStream() + reader.readAlignedString() //m_PathName + if (unityVersion >= intArrayOf(5, 3)) { + fDecompressedSize = reader.readUInt32() + fmSubProgramBlob = reader.readInt8Array() + } else { + fDecompressedSize = 0u + fmSubProgramBlob = ByteArray(0) + } + fmParsedForm = null + fPlatforms = emptyArray() + fOffsets = emptyArray() + fCompressedLengths = emptyArray() + fDecompressedLengths = emptyArray() + fCompressedBlob = ByteArray(0) + } + } + + override fun exportToString(): String { + if (mSubProgramBlob.isNotEmpty()) { + val decompressed = CompressUtils.lz4Decompress(mSubProgramBlob, decompressedSize.toInt()) + EndianByteArrayReader(decompressed).use { blobReader -> + val program = ShaderProgramImpl(blobReader, unityVersion) + return exportHeader + program.export(mScript.decodeToString()) + } + } + if (compressedBlob.isNotEmpty()) { + return exportHeader + convertSerializedShader() + } + return exportHeader + mScript.decodeToString() + } + + private fun convertSerializedShader(): String { + val programsList = mutableListOf() + for (i in platforms.indices) { + for (j in offsets[i].indices) { + val length = compressedLengths[i][j].toInt() + val compressedByte = ByteArray(length) + System.arraycopy( + compressedBlob, offsets[i][j].toInt(), + compressedByte, 0, length + ) + val decompressedByte = CompressUtils.lz4Decompress( + compressedByte, decompressedLengths[i][j].toInt() + ) + EndianByteArrayReader(decompressedByte, endian = ByteOrder.LITTLE_ENDIAN).use { blobReader -> + if (j == 0) { + programsList.add(ShaderProgramImpl(blobReader, unityVersion)) + } + programsList[i].read(blobReader, j) + } + } + } + return StringBuilder().apply { + append("Shader \"${mParsedForm!!.mName}\" {\n") + //region convertSerializedProperties + append("Properties {\n") + for (prop in mParsedForm!!.mPropInfo.mProps) { + prop.toString(this) + } + append("}\n") + //endregion + for (subShader in mParsedForm!!.mSubShaders) { + //region convertSerializedSubShader + append("SubShader {\n") + if (subShader.mLOD != 0) { + append(" LOD ${subShader.mLOD}\n") + } + subShader.mTags.toString(this, 1) + for (passe in subShader.mPasses) { + passe.toString(this, platforms, programsList) + } + append("}\n") + //endregion + } + if (mParsedForm!!.mFallbackName.isNotBlank()) { + append("Fallback \"${mParsedForm!!.mFallbackName}\"\n") + } + if (mParsedForm!!.mCustomEditorName.isNotBlank()) { + append("CustomEditor \"${mParsedForm!!.mCustomEditorName}\"\n") + } + append("}") + }.toString() + } + + companion object { + internal const val exportHeader = "" + + "//////////////////////////////////////////\n" + + "//\n" + + "// NOTE: This is *not* a valid shader file\n" + + "//\n" + + "//////////////////////////////////////////\n" + } +} + +internal class ShaderSubProgramEntryImpl(reader: EndianBinaryReader, version: IntArray): ShaderSubProgramEntry { + override val offset = reader.readInt32() + override val length = reader.readInt32() + override val segment = if (version >= intArrayOf(2019, 3)) reader.readInt32() else 0 +} + +internal class ShaderProgramImpl(reader: EndianBinaryReader, version: IntArray): ShaderProgram { + override val entries: Array = reader.readArrayOf { + ShaderSubProgramEntryImpl(this, version) + } + override val mSubPrograms = Array(entries.size) { null } + + override fun read(reader: EndianBinaryReader, segment: Int) { + for ((i, e) in entries.withIndex()) { + if (e.segment == segment) { + reader.position = e.offset.toLong() + mSubPrograms[i] = ShaderSubProgramImpl(reader) + } + } + } + + override fun export(shader: String): String { + return exportRegex.replace(shader) { + mSubPrograms[it.groups["index"]!!.value.toInt()]?.export() ?: "" + } + } + + companion object { + private val exportRegex = Regex("GpuProgramIndex (?.+)") + } +} + +internal class ShaderSubProgramImpl(private val reader: EndianBinaryReader): ShaderSubProgram { + private val mVersion = reader.readInt32() + override val mProgramType = ShaderGpuProgramType.of(reader.readInt32()) + override val mKeywords: Array + override val mLocalKeywords: Array + override val mProgramCode: ByteArray + + init { + reader.skip(if (mVersion >= 201608170) 16 else 12) + mKeywords = reader.readAlignedStringArray() + mLocalKeywords = if (mVersion in 201806140 until 202012090) { + reader.readAlignedStringArray() + } else emptyArray() + mProgramCode = reader.readInt8Array() + reader.alignStream() + } + + override fun export(): String { + val builder = StringBuilder() + if (mKeywords.isNotEmpty()) { + builder.append("Keywords { ") + mKeywords.forEach { builder.append("\"$it\" ") } + builder.append("}\n") + } + if (mLocalKeywords.isNotEmpty()) { + builder.append("Local Keywords { ") + mLocalKeywords.forEach { builder.append("\"$it\" ") } + builder.append("}\n") + } + builder.append("\"") + if (mProgramCode.isNotEmpty()) { + when (mProgramType) { + ShaderGpuProgramType.GLLegacy, + ShaderGpuProgramType.GLES31AEP, + ShaderGpuProgramType.GLES31, + ShaderGpuProgramType.GLES3, + ShaderGpuProgramType.GLES, + ShaderGpuProgramType.GLCore32, + ShaderGpuProgramType.GLCore41, + ShaderGpuProgramType.GLCore43 -> { + builder.append(mProgramCode.decodeToString()) + } + ShaderGpuProgramType.DX9VertexSM20, + ShaderGpuProgramType.DX9VertexSM30, + ShaderGpuProgramType.DX9PixelSM20, + ShaderGpuProgramType.DX9PixelSM30 -> { + builder.append("// shader disassembly not supported on DXBC") + } + ShaderGpuProgramType.DX10Level9Vertex, + ShaderGpuProgramType.DX10Level9Pixel, + ShaderGpuProgramType.DX11VertexSM40, + ShaderGpuProgramType.DX11VertexSM50, + ShaderGpuProgramType.DX11PixelSM40, + ShaderGpuProgramType.DX11PixelSM50, + ShaderGpuProgramType.DX11GeometrySM40, + ShaderGpuProgramType.DX11GeometrySM50, + ShaderGpuProgramType.DX11HullSM50, + ShaderGpuProgramType.DX11DomainSM50 -> { + builder.append("// shader disassembly not supported on DXBC") + } + ShaderGpuProgramType.MetalVS, + ShaderGpuProgramType.MetalFS -> { + val fourCC = reader.readUInt32() + if (fourCC == 0xF00DCAFEu) { + val offset = reader.readInt32() + reader.position = offset.toLong() + } + reader.readNullString() + val buff = reader.read(with(reader) { length - position }.toInt()) + builder.append(buff.decodeToString()) + } + ShaderGpuProgramType.SPIRV -> { + builder.append( + try { + mProgramCode.covertToSpirV() + } catch (e: Exception) { + "// spirv disassembly error ${e.message}\n" + } + ) + } + ShaderGpuProgramType.ConsoleVS, + ShaderGpuProgramType.ConsoleFS, + ShaderGpuProgramType.ConsoleHS, + ShaderGpuProgramType.ConsoleDS, + ShaderGpuProgramType.ConsoleGS -> { + builder.append(mProgramCode.decodeToString()) + } + else -> { builder.append("//shader disassembly not supported on $mProgramType") } + } + } + builder.append("\"") + return builder.toString() + } + + companion object { + private fun ByteArray.covertToSpirV(): String { + val builder = StringBuilder() + EndianByteArrayReader(this, endian = ByteOrder.LITTLE_ENDIAN).use { reader -> + reader.skip(4) + var minOffset = reader.length + for (i in 0..4) { + if (reader.position >= minOffset) break + val offset = reader.readInt32() + val size = reader.readInt32() + if (size > 0) { + if (offset < minOffset) minOffset = offset.toLong() + reader.withMark { + position = offset.toLong() + val decodedSize = SmolvDecoder.getDecodedBufferSize(reader) + if (decodedSize == 0) { + builder.append("\n// disassembly error: Invalid SMOL-V shader header\n") + return@withMark + } + val writer = EndianByteArrayWriter(decodedSize, ByteOrder.LITTLE_ENDIAN) + if (SmolvDecoder.decode(this, size, writer)) { + val module = Module.readFrom(writer.data) + builder.append(Disassembler().disassemble(module)) + } + } + } + } + } + return builder.toString() + } + } +} + +internal class Hash128Impl(reader: EndianBinaryReader): Hash128 { + override val bytes = reader.read(16) +} + +internal class MatrixParameterImpl(reader: EndianBinaryReader): MatrixParameter { + override val mNameIndex = reader.readInt32() + override val mIndex = reader.readInt32() + override val mArraySize = reader.readInt32() + override val mType = reader.readInt8() + override val mRowCount = reader.readInt8() + + init { reader.alignStream() } +} + +internal class VectorParameterImpl(reader: EndianBinaryReader): VectorParameter { + override val mNameIndex = reader.readInt32() + override val mIndex = reader.readInt32() + override val mArraySize = reader.readInt32() + override val mType = reader.readInt8() + override val mDim = reader.readInt8() + + init { reader.alignStream() } +} + +internal class StructParameterImpl(reader: EndianBinaryReader): StructParameter { + override val mMatrixParams: Array + override val mVectorParams: Array + + init { + reader.skip(16) //m_NameIndex, m_Index, m_ArraySize, m_StructSize: Int + mVectorParams = reader.readArrayOf { VectorParameterImpl(this) } + mMatrixParams = reader.readArrayOf { MatrixParameterImpl(this) } + } +} + +internal class SamplerParameterImpl(reader: EndianBinaryReader): SamplerParameter { + override val sampler = reader.readUInt32() + override val bindPoint = reader.readInt32() +} + +internal class SerializedTexturePropertyImpl(reader: EndianBinaryReader): SerializedTextureProperty { + override val mDefaultName = reader.readAlignedString() + override val mTexDim = TextureDimension.of(reader.readInt32()) +} + +internal class SerializedPropertyImpl(reader: EndianBinaryReader): SerializedProperty { + override val mName = reader.readAlignedString() + override val mDescription = reader.readAlignedString() + override val mAttributes = reader.readAlignedStringArray() + override val mType = SerializedPropertyType.of(reader.readInt32()) + override val mFlags = reader.readUInt32() + override val mDefValue = reader.readFloatArray(4) + override val mDefTexture = SerializedTexturePropertyImpl(reader) + + internal fun toString(builder: StringBuilder): StringBuilder { + for (attribute in mAttributes) { + builder.append("[$attribute] ") + } + builder.append("$mName (\"$mDescription\", ") + builder.append( + when (mType) { + SerializedPropertyType.Color -> "Color" + SerializedPropertyType.Vector -> "Vector" + SerializedPropertyType.Float -> "Float" + SerializedPropertyType.Range -> "Range(${mDefValue[1]}, ${mDefValue[2]})" + SerializedPropertyType.Texture -> { + when (mDefTexture.mTexDim) { + TextureDimension.Any -> "any" + TextureDimension.Tex2D -> "2D" + TextureDimension.Tex3D -> "3D" + TextureDimension.Cube -> "Cube" + TextureDimension.Tex2DArray -> "2DArray" + TextureDimension.CubeArray -> "CubeArray" + else -> "" + } + } + SerializedPropertyType.Integer -> "" + } + ) + builder.append(") = ") + builder.append( + when (mType) { + SerializedPropertyType.Color, + SerializedPropertyType.Vector -> { + "(${mDefValue[0]},${mDefValue[1]},${mDefValue[2]},${mDefValue[3]})" + } + SerializedPropertyType.Float, + SerializedPropertyType.Range -> { + mDefValue[0] + } + SerializedPropertyType.Texture -> { + "\"${mDefTexture.mDefaultName}\" { }" + } + SerializedPropertyType.Integer -> "" + } + ) + builder.append("\n") + return builder + } +} + +internal class SerializedPropertiesImpl(reader: EndianBinaryReader): SerializedProperties { + override val mProps: Array = reader.readArrayOf { + SerializedPropertyImpl(this) + } +} + +internal class SerializedShaderFloatValueImpl(reader: EndianBinaryReader): SerializedShaderFloatValue { + override val value = reader.readFloat() + override val name = reader.readAlignedString() + + internal fun convertBlendFactor(): String { + return when (value) { + 0f -> "Zero" + 2f -> "DstColor" + 3f -> "SrcColor" + 4f -> "OneMinusDstColor" + 5f -> "SrcAlpha" + 6f -> "OneMinusSrcColor" + 7f -> "DstAlpha" + 8f -> "OneMinusDstAlpha" + 9f -> "SrcAlphaSaturate" + 10f -> "OneMinusSrcAlpha" + else -> "One" + } + } + + internal fun convertBlendOp(): String { + return when (value) { + 1f -> "Sub" + 2f -> "RevSub" + 3f -> "Min" + 4f -> "Max" + 5f -> "LogicalClear" + 6f -> "LogicalSet" + 7f -> "LogicalCopy" + 8f -> "LogicalCopyInverted" + 9f -> "LogicalNoop" + 10f -> "LogicalInvert" + 11f -> "LogicalAnd" + 12f -> "LogicalNand" + 13f -> "LogicalOr" + 14f -> "LogicalNor" + 15f -> "LogicalXor" + 16f -> "LogicalEquiv" + 17f -> "LogicalAndReverse" + 18f -> "LogicalAndInverted" + 19f -> "LogicalOrReverse" + 20f -> "LogicalOrInverted" + else -> "Add" + } + } + + internal fun convertStencilOp(): String { + return when (value) { + 1f -> "Zero" + 2f -> "Replace" + 3f -> "IncrSat" + 4f -> "DecrSat" + 5f -> "Invert" + 6f -> "IncrWrap" + 7f -> "DecrWrap" + else -> "Keep" + } + } + + internal fun convertStencilComp(): String { + return when (value) { + 0f -> "Disabled" + 1f -> "Never" + 2f -> "Less" + 3f -> "Equal" + 4f -> "LEqual" + 5f -> "Greater" + 6f -> "NotEqual" + 7f -> "GEqual" + else -> "Always" + } + } +} + +internal class SerializedShaderRTBlendStateImpl(reader: EndianBinaryReader): SerializedShaderRTBlendState { + override val srcBlend = SerializedShaderFloatValueImpl(reader) + override val destBlend = SerializedShaderFloatValueImpl(reader) + override val srcBlendAlpha = SerializedShaderFloatValueImpl(reader) + override val destBlendAlpha = SerializedShaderFloatValueImpl(reader) + override val blendOp = SerializedShaderFloatValueImpl(reader) + override val blendOpAlpha = SerializedShaderFloatValueImpl(reader) + override val colMask = SerializedShaderFloatValueImpl(reader) +} + +internal class SerializedStencilOpImpl(reader: EndianBinaryReader): SerializedStencilOp { + override val pass = SerializedShaderFloatValueImpl(reader) + override val fail = SerializedShaderFloatValueImpl(reader) + override val zFail = SerializedShaderFloatValueImpl(reader) + override val comp = SerializedShaderFloatValueImpl(reader) + + internal fun toString(builder: StringBuilder, suffix: String): StringBuilder { + return builder.apply { + append(" Comp$suffix ${comp.convertStencilComp()}\n") + append(" Pass$suffix ${pass.convertStencilOp()}\n") + append(" Fail$suffix ${fail.convertStencilOp()}\n") + append(" ZFail$suffix ${zFail.convertStencilOp()}\n") + } + } +} + +internal class SerializedShaderVectorValueImpl(reader: EndianBinaryReader): SerializedShaderVectorValue { + override val x = SerializedShaderFloatValueImpl(reader) + override val y = SerializedShaderFloatValueImpl(reader) + override val z = SerializedShaderFloatValueImpl(reader) + override val w = SerializedShaderFloatValueImpl(reader) + override val name = reader.readAlignedString() +} + +internal class SerializedTagMapImpl(reader: EndianBinaryReader): SerializedTagMap { + override val tags = reader.readArrayOf { readAlignedString() to readAlignedString() } + + internal fun toString(builder: StringBuilder, indent: Int): StringBuilder { + if (tags.isNotEmpty()) { + builder.append(" ".repeat(indent)) + builder.append("Tags { ") + for (pair in tags) { + builder.append("\"${pair.first}\" = \"${pair.second}\" ") + } + builder.append("}\n") + } + return builder + } +} + +internal class SerializedShaderStateImpl(reader: ObjectReader): SerializedShaderState { + override val mName = reader.readAlignedString() + override val rtBlend: Array = reader.readArrayOf(8) { + SerializedShaderRTBlendStateImpl(this) + } + override val rtSeparateBlend = reader.readBool() + override val zClip: SerializedShaderFloatValueImpl? + override val zTest: SerializedShaderFloatValueImpl + override val zWrite: SerializedShaderFloatValueImpl + override val culling: SerializedShaderFloatValueImpl + override val conservative: SerializedShaderFloatValueImpl? + override val offsetFactor: SerializedShaderFloatValueImpl + override val offsetUnits: SerializedShaderFloatValueImpl + override val alphaToMask: SerializedShaderFloatValueImpl + override val stencilOp: SerializedStencilOpImpl + override val stencilOpFront: SerializedStencilOpImpl + override val stencilOpBack: SerializedStencilOpImpl + override val stencilReadMask: SerializedShaderFloatValueImpl + override val stencilWriteMask: SerializedShaderFloatValueImpl + override val stencilRef: SerializedShaderFloatValueImpl + override val fogStart: SerializedShaderFloatValueImpl + override val fogEnd: SerializedShaderFloatValueImpl + override val fogDensity: SerializedShaderFloatValueImpl + override val fogColor: SerializedShaderVectorValueImpl + override val fogMode: FogMode + override val gpuProgramID: Int + override val mTags: SerializedTagMapImpl + override val mLOD: Int + override val lighting: Boolean + + init { + val version = reader.unityVersion + reader.alignStream() + zClip = if (version >= intArrayOf(2017, 2)) { + SerializedShaderFloatValueImpl(reader) + } else null + zTest = SerializedShaderFloatValueImpl(reader) + zWrite = SerializedShaderFloatValueImpl(reader) + culling = SerializedShaderFloatValueImpl(reader) + conservative = if (version[0] >= 2020) SerializedShaderFloatValueImpl(reader) else null + offsetFactor = SerializedShaderFloatValueImpl(reader) + offsetUnits = SerializedShaderFloatValueImpl(reader) + alphaToMask = SerializedShaderFloatValueImpl(reader) + stencilOp = SerializedStencilOpImpl(reader) + stencilOpFront = SerializedStencilOpImpl(reader) + stencilOpBack = SerializedStencilOpImpl(reader) + stencilReadMask = SerializedShaderFloatValueImpl(reader) + stencilWriteMask = SerializedShaderFloatValueImpl(reader) + stencilRef = SerializedShaderFloatValueImpl(reader) + fogStart = SerializedShaderFloatValueImpl(reader) + fogEnd = SerializedShaderFloatValueImpl(reader) + fogDensity = SerializedShaderFloatValueImpl(reader) + fogColor = SerializedShaderVectorValueImpl(reader) + fogMode = FogMode.of(reader.readInt32()) + gpuProgramID = reader.readInt32() + mTags = SerializedTagMapImpl(reader) + mLOD = reader.readInt32() + lighting = reader.readBool() + reader.alignStream() + } + + internal fun toString(builder: StringBuilder): StringBuilder { + if (mName.isNotEmpty()) builder.append(" Name \"$mName\"\n") + if (mLOD != 0) builder.append(" LOD ${mLOD}\n") + mTags.toString(builder, 2) + rtBlend.toString(builder) + if (alphaToMask.value > 0f) builder.append(" AlphaToMask On\n") + if (zClip?.value != 1f) builder.append(" ZClip Off\n") + if (zTest.value != 4f) { + builder.append(" ZTest ") + when (zTest.value) { + 0f -> builder.append("Off") + 1f -> builder.append("Never") + 2f -> builder.append("Less") + 3f -> builder.append("Equal") + 5f -> builder.append("Greater") + 6f -> builder.append("NotEqual") + 7f -> builder.append("GEqual") + 8f -> builder.append("Always") + } + builder.append("\n") + } + if (zWrite.value != 1f) builder.append(" ZWrite Off\n") + if (culling.value != 2f) { + builder.append(" Cull ") + when (culling.value) { + 0f -> builder.append("Off") + 1f -> builder.append("Front") + } + builder.append("\n") + } + if (offsetFactor.value != 0f || offsetUnits.value != 0f) { + builder.append(" Offset ${offsetFactor.value}, ${offsetUnits.value}\n") + } + if ( + stencilRef.value != 0f || + stencilReadMask.value != 255f || + stencilWriteMask.value != 255f || + stencilOp.pass.value != 0f || + stencilOp.fail.value != 0f || + stencilOp.zFail.value != 0f || + stencilOp.comp.value != 8f || + stencilOpFront.pass.value != 0f || + stencilOpFront.fail.value != 0f || + stencilOpFront.zFail.value != 0f || + stencilOpFront.comp.value != 8f || + stencilOpBack.pass.value != 0f || + stencilOpBack.fail.value != 0f || + stencilOpBack.zFail.value != 0f || + stencilOpBack.comp.value != 8f + ) { + builder.append(" Stencil {\n") + if (stencilRef.value != 0f) builder.append(" Ref ${stencilRef.value}\n") + if (stencilReadMask.value != 255f) builder.append(" ReadMask ${stencilReadMask.value}\n") + if (stencilWriteMask.value != 255f) builder.append(" WriteMask ${stencilWriteMask.value}\n") + if ( + stencilOp.pass.value != 0f || + stencilOp.fail.value != 0f || + stencilOp.zFail.value != 0f || + stencilOp.comp.value != 8f + ) { + stencilOp.toString(builder, "") + } + if ( + stencilOpFront.pass.value != 0f || + stencilOpFront.fail.value != 0f || + stencilOpFront.zFail.value != 0f || + stencilOpFront.comp.value != 8f) + { + stencilOpFront.toString(builder, "Front") + } + if ( + stencilOpBack.pass.value != 0f || + stencilOpBack.fail.value != 0f || + stencilOpBack.zFail.value != 0f || + stencilOpBack.comp.value != 8f) + { + stencilOpBack.toString(builder, "Back") + } + builder.append(" }\n") + } + if ( + fogMode != FogMode.Unknown || + fogColor.x.value != 0f || + fogColor.y.value != 0f || + fogColor.z.value != 0f || + fogColor.w.value != 0f || + fogDensity.value != 0f || + fogStart.value != 0f || + fogEnd.value != 0f + ) { + builder.append(" Fog {\n") + if (fogMode != FogMode.Unknown) { + builder.append(" Mode ") + when (fogMode) { + FogMode.Disabled -> builder.append("Off") + FogMode.Linear -> builder.append("Linear") + FogMode.Exp -> builder.append("Exp") + FogMode.Exp2 -> builder.append("Exp2") + else -> { } + } + builder.append("\n") + } + if ( + fogColor.x.value != 0f || + fogColor.y.value != 0f || + fogColor.z.value != 0f || + fogColor.w.value != 0f + ) { + builder.append( + " Color (${fogColor.x.value},${fogColor.y.value},${fogColor.z.value},${fogColor.w.value})\n" + ) + } + if (fogDensity.value != 0f) { + builder.append(" Density ${fogDensity.value}\n") + } + if (fogStart.value != 0f || fogEnd.value != 0f) { + builder.append(" Range ${fogStart.value}, ${fogEnd.value}\n") + } + builder.append(" }\n") + } + return builder.apply { + append(" Lighting ${if (lighting) "On" else "Off"}\n") + append(" GpuProgramID ${gpuProgramID}\n") + } + } + + private fun Array.toString(builder: StringBuilder): StringBuilder { + for (i in indices) { + val blend = get(i) + if ( + blend.srcBlend.value != 1f || + blend.destBlend.value != 0f || + blend.srcBlendAlpha.value != 1f || + blend.destBlendAlpha.value != 0f + ) { + builder.append(" Blend ") + if (i != 0 || rtSeparateBlend) { + builder.append("$i ") + } + builder.append("${blend.srcBlend.convertBlendFactor()} ${blend.destBlend.convertBlendFactor()}") + if (blend.srcBlendAlpha.value != 1f || blend.destBlendAlpha.value != 0f) { + builder.append( + ", ${blend.srcBlendAlpha.convertBlendFactor()} ${blend.destBlendAlpha.convertBlendFactor()}" + ) + } + builder.append("\n") + } + if (blend.blendOp.value != 0f || blend.blendOpAlpha.value != 0f) { + builder.append(" BlendOp ") + if (i != 0 || rtSeparateBlend) { + builder.append("$i ") + } + builder.append(blend.blendOp.convertBlendOp()) + if (blend.blendOpAlpha.value != 0f) { + builder.append(", ${blend.blendOpAlpha.convertBlendOp()}") + } + builder.append("\n") + } + val value = blend.colMask.value.toInt() + if (value != 0xF) { + builder.append(" ColorMask ") + if (value == 0) builder.append(0) + else { + if (value.and(0x2) != 0) builder.append("R") + if (value.and(0x4) != 0) builder.append("G") + if (value.and(0x8) != 0) builder.append("B") + if (value.and(0x1) != 0) builder.append("A") + } + builder.append(" $i\n") + } + } + return builder + } +} + +internal class ShaderBindChannelImpl(reader: EndianBinaryReader): ShaderBindChannel { + override val source = reader.readInt8() + override val target = reader.readInt8() +} + +internal class ParserBindChannelsImpl(reader: EndianBinaryReader): ParserBindChannels { + override val mChannels: Array = reader.readArrayOf { + ShaderBindChannelImpl(reader) + } + override val mSourceMap: UInt + + init { + reader.alignStream() + mSourceMap = reader.readUInt32() + } +} + +internal class TextureParameterImpl(reader: ObjectReader): TextureParameter { + override val mNameIndex = reader.readInt32() + override val mIndex = reader.readInt32() + override val mSamplerIndex = reader.readInt32() + override val mDim: Byte + + init { + if (reader.unityVersion >= intArrayOf(2017, 3)) reader.skip(1) //m_MultiSampled: Boolean + mDim = reader.readInt8() + reader.alignStream() + } +} + +internal class BufferBindingImpl(reader: ObjectReader): BufferBinding { + override val mNameIndex = reader.readInt32() + override val mIndex = reader.readInt32() + override val mArraySize = if (reader.unityVersion[0] >= 2020) reader.readInt32() else 0 +} + +internal class ConstantBufferImpl(reader: ObjectReader): ConstantBuffer { + override val mNameIndex = reader.readInt32() + override val mMatrixParams: Array = reader.readArrayOf { MatrixParameterImpl(this) } + override val mVectorParams: Array = reader.readArrayOf { VectorParameterImpl(this) } + override val mStructParams: Array = if (reader.unityVersion >= intArrayOf(2017, 3)) { + reader.readArrayOf { StructParameterImpl(this) } + } else emptyArray() + override val mSize = reader.readInt32() + override val mIsPartialCB = if ( + with(reader.unityVersion) { + (this[0] == 2020 && this >= intArrayOf(2020, 3, 2)) || + (this >= intArrayOf(2021, 1, 4)) + } + ) { + reader.readBool() + } else false + + init { reader.alignStream() } +} + +internal class UAVParameterImpl(reader: EndianBinaryReader): UAVParameter { + override val mNameIndex = reader.readInt32() + override val mIndex = reader.readInt32() + override val mOriginalIndex = reader.readInt32() +} + +internal class SerializedProgramParametersImpl(reader: ObjectReader): SerializedProgramParameters { + override val mVectorParams: Array = reader.readArrayOf { + VectorParameterImpl(this) + } + override val mMatrixParams: Array = reader.readArrayOf { + MatrixParameterImpl(this) + } + override val mTextureParams: Array = reader.readArrayOf { + TextureParameterImpl(this) + } + override val mBufferParams: Array = reader.readArrayOf { + BufferBindingImpl(this) + } + override val mConstantBuffers: Array = reader.readArrayOf { + ConstantBufferImpl(this) + } + override val mConstantBufferBindings: Array = reader.readArrayOf { + BufferBindingImpl(this) + } + override val mUAVParams: Array = reader.readArrayOf { + UAVParameterImpl(this) + } + override val mSamplers: Array = reader.readArrayOf { + SamplerParameterImpl(this) + } +} + +internal class SerializedSubProgramImpl(reader: ObjectReader): SerializedSubProgram { + override val mBlobIndex = reader.readUInt32() + override val mChannels = ParserBindChannelsImpl(reader) + override val mKeywordIndices: Array + override val mShaderHardwareTier: Byte + override val mGpuProgramType: ShaderGpuProgramType + override val mParameters: SerializedProgramParametersImpl? + override val mVectorParams: Array + override val mMatrixParams: Array + override val mTextureParams: Array + override val mBufferParams: Array + override val mConstantBuffers: Array + override val mConstantBufferBindings: Array + override val mUAVParams: Array + override val mSamplers: Array + + init { + val version = reader.unityVersion + if (version[0] >= 2019 && version < intArrayOf(2021, 2)) { + reader.readUInt16Array() //m_GlobalKeywordIndices + reader.alignStream() + reader.readUInt16Array() //m_LocalKeywordIndices + reader.alignStream() + mKeywordIndices = emptyArray() + } else { + mKeywordIndices = reader.readUInt16Array() + if (version[0] >= 2017) reader.alignStream() + } + mShaderHardwareTier = reader.readInt8() + mGpuProgramType = ShaderGpuProgramType.of(reader.readInt8().toInt()) + reader.alignStream() + if ( + (version[0] == 2020 && version >= intArrayOf(2020, 3, 2)) || + (version >= intArrayOf(2021, 1, 1)) + ) { + mParameters = SerializedProgramParametersImpl(reader) + mVectorParams = emptyArray() + mMatrixParams = emptyArray() + mTextureParams = emptyArray() + mBufferParams = emptyArray() + mConstantBuffers = emptyArray() + mConstantBufferBindings = emptyArray() + mUAVParams = emptyArray() + mSamplers = emptyArray() + } else { + mVectorParams = reader.readArrayOf { VectorParameterImpl(this) } + mMatrixParams = reader.readArrayOf { MatrixParameterImpl(this) } + mTextureParams = reader.readArrayOf { TextureParameterImpl(this) } + mBufferParams = reader.readArrayOf { BufferBindingImpl(this) } + mConstantBuffers = reader.readArrayOf { ConstantBufferImpl(this) } + mConstantBufferBindings = reader.readArrayOf { BufferBindingImpl(this) } + mUAVParams = reader.readArrayOf { UAVParameterImpl(this) } + mSamplers = if (version[0] >= 2017) reader.readArrayOf { + SamplerParameterImpl(this) + } else emptyArray() + mParameters = null + } + if (version >= intArrayOf(2017, 2)) { + reader.skip(if (version[0] >= 2021) 8 else 4) //m_ShaderRequirements: Long/Int + } + } +} + +internal class SerializedProgramImpl(reader: ObjectReader): SerializedProgram { + override val mSubPrograms: Array = reader.readArrayOf { + SerializedSubProgramImpl(this) + } + override val mCommonParameters = if (with(reader.unityVersion) { + (this[0] == 2020 && this >= intArrayOf(2020, 3, 2)) || + (this >= intArrayOf(2021, 1, 4)) + }) SerializedProgramParametersImpl(reader) else null + override val mSerializedKeywordStateMask: Array + + init { + if (reader.unityVersion >= intArrayOf(2022, 1)) { + mSerializedKeywordStateMask = reader.readUInt16Array() + reader.alignStream() + } else { + mSerializedKeywordStateMask = emptyArray() + } + } +} + +internal class SerializedPassImpl(reader: ObjectReader): SerializedPass { + override val mEditorDataHash: Array + override val mPlatforms: ByteArray + override val mLocalKeywordMask: Array + override val mGlobalKeywordMask: Array + override val mNameIndices: Map> + override val mType: PassType + override val mState: SerializedShaderStateImpl + override val mProgramMask: UInt + override val progVertex: SerializedProgramImpl + override val progFragment: SerializedProgramImpl + override val progGeometry: SerializedProgramImpl + override val progHull: SerializedProgramImpl + override val progDomain: SerializedProgramImpl + override val progRayTracing: SerializedProgramImpl? + override val mHasInstancingVariant: Boolean + override val mUseName: String + override val mName: String + override val mTextureName: String + override val mTags: SerializedTagMapImpl + override val mSerializedKeywordStateMask: Array + + init { + val version = reader.unityVersion + if (version >= intArrayOf(2020, 2)) { + mEditorDataHash = reader.readArrayOf { Hash128Impl(this) } + reader.alignStream() + mPlatforms = reader.readInt8Array() + reader.alignStream() + if (version < intArrayOf(2021, 2)) { + mLocalKeywordMask = reader.readUInt16Array() + reader.alignStream() + mGlobalKeywordMask = reader.readUInt16Array() + reader.alignStream() + } else { + mLocalKeywordMask = emptyArray() + mGlobalKeywordMask = emptyArray() + } + } else { + mEditorDataHash = emptyArray() + mPlatforms = ByteArray(0) + mLocalKeywordMask = emptyArray() + mGlobalKeywordMask = emptyArray() + } + mNameIndices = reader.readArrayOf { + readAlignedString() to readInt32() + }.groupBy({ it.first }, { it.second }) + mType = PassType.of(reader.readInt32()) + mState = SerializedShaderStateImpl(reader) + mProgramMask = reader.readUInt32() + progVertex = SerializedProgramImpl(reader) + progFragment = SerializedProgramImpl(reader) + progGeometry = SerializedProgramImpl(reader) + progHull = SerializedProgramImpl(reader) + progDomain = SerializedProgramImpl(reader) + progRayTracing = if (version >= intArrayOf(2019, 3)) SerializedProgramImpl(reader) else null + mHasInstancingVariant = reader.readBool() + if (version[0] >= 2018) reader.skip(1) //m_HasProceduralInstancingVariant: Boolean + reader.alignStream() + mUseName = reader.readAlignedString() + mName = reader.readAlignedString() + mTextureName = reader.readAlignedString() + mTags = SerializedTagMapImpl(reader) + if (version[0] == 2021 && version[1] >= 2) { + mSerializedKeywordStateMask = reader.readUInt16Array() + reader.alignStream() + } else { + mSerializedKeywordStateMask = emptyArray() + } + } + + internal fun toString( + builder: StringBuilder, + platforms: Array, + shaderPrograms: List + ): StringBuilder { + builder.append( + when (mType) { + PassType.Normal -> " Pass " + PassType.Use -> " UsePass " + PassType.Grab -> " GrabPass " + } + ) + if (mType == PassType.Use) { + builder.append("\"$mUseName\"\n") + } else { + builder.append("{\n") + if (mType == PassType.Grab) { + if (mTextureName.isNotEmpty()) { + builder.append(" \"${mTextureName}\"\n") + } + } else { + mState.toString(builder) + if (progVertex.mSubPrograms.isNotEmpty()) { + builder.apply { + append("Program \"vp\" {\n") + progVertex.mSubPrograms.toString(this, platforms, shaderPrograms) + append("}\n") + } + } + if (progFragment.mSubPrograms.isNotEmpty()) { + builder.apply { + append("Program \"fp\" {\n") + progFragment.mSubPrograms.toString(this, platforms, shaderPrograms) + append("}\n") + } + } + if (progGeometry.mSubPrograms.isNotEmpty()) { + builder.apply { + append("Program \"gp\" {\n") + progGeometry.mSubPrograms.toString(this, platforms, shaderPrograms) + append("}\n") + } + } + if (progHull.mSubPrograms.isNotEmpty()) { + builder.apply { + append("Program \"hp\" {\n") + progHull.mSubPrograms.toString(this, platforms, shaderPrograms) + append("}\n") + } + } + if (progDomain.mSubPrograms.isNotEmpty()) { + builder.apply { + append("Program \"dp\" {\n") + progDomain.mSubPrograms.toString(this, platforms, shaderPrograms) + append("}\n") + } + } + if (progRayTracing?.mSubPrograms?.isNotEmpty() == true) { + builder.apply { + append("Program \"rtp\" {\n") + progRayTracing.mSubPrograms.toString(this, platforms, shaderPrograms) + append("}\n") + } + } + } + builder.append("}\n") + } + return builder + } + + private fun Array.toString( + builder: StringBuilder, + platforms: Array, + shaderPrograms: List + ): StringBuilder { + for (group in groupBy { it.mBlobIndex }) { + for (program in group.value.groupBy { it.mGpuProgramType }) { + for ((i, platform) in platforms.withIndex()) { + if (platform.checkProgramUsability(program.key)) { + val isTier = program.value.size > 1 + for (subProgram in program.value) { + builder.append("SubProgram \"${platform.str} ") + if (isTier) { + builder.append("hw_tier${"%02d".format(subProgram.mShaderHardwareTier)} ") + } + builder.append("\" {\n") + builder.append(shaderPrograms[i].mSubPrograms[subProgram.mBlobIndex.toInt()]?.export()) + builder.append("\n}\n") + } + break + } + } + } + } + return builder + } +} + +internal class SerializedSubShaderImpl(reader: ObjectReader): SerializedSubShader { + override val mPasses: Array = reader.readArrayOf { SerializedPassImpl(this) } + override val mTags = SerializedTagMapImpl(reader) + override val mLOD = reader.readInt32() +} + +internal class SerializedShaderDependencyImpl(reader: EndianBinaryReader): SerializedShaderDependency { + override val from = reader.readAlignedString() + override val to = reader.readAlignedString() +} + +internal class SerializedCustomEditorForRenderPipelineImpl(reader: EndianBinaryReader): SerializedCustomEditorForRenderPipeline { + override val customEditorName = reader.readAlignedString() + override val renderPipelineType = reader.readAlignedString() +} + +internal class SerializedShaderImpl(reader: ObjectReader): SerializedShader { + override val mPropInfo = SerializedPropertiesImpl(reader) + override val mSubShaders: Array = reader.readArrayOf { SerializedSubShaderImpl(this) } + override val mKeywordNames: Array + override val mKeywordFlags: ByteArray + override val mName: String + override val mCustomEditorName: String + override val mFallbackName: String + override val mDependencies: Array + override val mCustomEditorForRenderPipelines: Array + override val mDisableNoSubShadersMessage: Boolean + + init { + val version = reader.unityVersion + if (version >= intArrayOf(2021, 2)) { + mKeywordNames = reader.readAlignedStringArray() + mKeywordFlags = reader.readInt8Array() + reader.alignStream() + } else { + mKeywordNames = emptyArray() + mKeywordFlags = ByteArray(0) + } + mName = reader.readAlignedString() + mCustomEditorName = reader.readAlignedString() + mFallbackName = reader.readAlignedString() + mDependencies = reader.readArrayOf { SerializedShaderDependencyImpl(this) } + mCustomEditorForRenderPipelines = if (version[0] >= 2021) { + reader.readArrayOf { SerializedCustomEditorForRenderPipelineImpl(this) } + } else emptyArray() + mDisableNoSubShadersMessage = reader.readBool() + reader.alignStream() + } +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/SkinnedMeshRendererImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/SkinnedMeshRendererImpl.kt new file mode 100644 index 00000000..1ddd04be --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/SkinnedMeshRendererImpl.kt @@ -0,0 +1,38 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.* +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile +import io.github.deficuet.unitykt.util.compareTo +import io.github.deficuet.unitykt.util.readArrayOf + +internal class SkinnedMeshRendererImpl( + assetFile: SerializedFile, info: ObjectInfo +): SkinnedMeshRenderer, SkinnedMeshRendererFields(assetFile, info) { + override val mMesh: PPtr get() { + checkInitialize() + return fmMesh + } + override val mBones: Array> get() { + checkInitialize() + return fmBones + } + override val mBlendShapeWeights: FloatArray get() { + checkInitialize() + return fmBlendShapeWeights + } + + override fun read() { + super.read() + reader.skip(6) //m_Quality: Int, m_UpdateWhenOffscreen, m_SkinNormals: Boolean + reader.alignStream() + if (unityVersion[0] == 2 && unityVersion[1] < 6) { + PPtrImpl(reader) //m_DisableAnimationWhenOffscreen + } + fmMesh = PPtrImpl(reader) + fmBones = reader.readArrayOf { PPtrImpl(this) } + fmBlendShapeWeights = if (unityVersion >= intArrayOf(4, 3)) { + reader.readFloatArray() + } else FloatArray(0) + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/SpriteAtlasImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/SpriteAtlasImpl.kt new file mode 100644 index 00000000..386d7d93 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/SpriteAtlasImpl.kt @@ -0,0 +1,84 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.cast +import io.github.deficuet.unitykt.classes.* +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile +import io.github.deficuet.unitykt.math.Vector2 +import io.github.deficuet.unitykt.util.ObjectReader +import io.github.deficuet.unitykt.util.compareTo +import io.github.deficuet.unitykt.util.readArrayOf +import java.nio.ByteBuffer +import java.util.* + +internal class SpriteAtlasImpl( + assetFile: SerializedFile, info: ObjectInfo +): SpriteAtlas, SpriteAtlasFields(assetFile, info) { + override val mPackedSprites: Array> get() { + checkInitialize() + return fmPackedSprites + } + override val mRenderDataMap: Map, SpriteAtlasData> get() { + checkInitialize() + return fmRenderDataMap + } + override val mIsVariant: Boolean get() { + checkInitialize() + return fmIsVariant + } + + override fun read() { + super.read() + fmPackedSprites = reader.readArrayOf { PPtrImpl(this) } + reader.readAlignedStringArray() //m_PackedSpriteNamesToIndex + val buffer = ByteBuffer.allocate(16) + fmRenderDataMap = reader.readArrayOf { + buffer.put(reader.read(16)) + val second = reader.readInt64() + val value = SpriteAtlasDataImpl(reader) + val ret = (UUID(buffer.long, buffer.long) to second) to value + buffer.clear() + ret + }.toMap() + reader.readAlignedString() //m_Tag + fmIsVariant = reader.readBool() + reader.alignStream() + for (packedSprite in fmPackedSprites) { + val sprite = packedSprite.safeGetObj() + if (sprite != null) { + val sa = sprite.mSpriteAtlas + if (sa != null) { + if (sa.isNull) { + sa.cast>().setObj(this) + } else { + val old = sa.safeGetObj() + if (old != null && old.mIsVariant) { + sa.cast>().setObj(this) + } + } + } + } + } + } +} + +internal class SpriteAtlasDataImpl(reader: ObjectReader): SpriteAtlasData { + override val texture = PPtrImpl(reader) + override val alphaText = PPtrImpl(reader) + override val textureRect = reader.readRectangle() + override val textureRectOffset = reader.readVector2() + override val atlasRectOffset = if (reader.unityVersion >= intArrayOf(2017, 2)) { + reader.readVector2() + } else Vector2.Zero + override val uvTransform = reader.readVector4() + override val downScaleMultiplier = reader.readFloat() + override val settingsRaw = SpriteSettingsImpl(reader) + override val secondaryTextures: Array + + init { + if (reader.unityVersion >= intArrayOf(2020, 2)) { + secondaryTextures = reader.readArrayOf { SecondarySpriteTextureImpl(this) } + reader.alignStream() + } else secondaryTextures = emptyArray() + } +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/SpriteImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/SpriteImpl.kt new file mode 100644 index 00000000..bba745ef --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/SpriteImpl.kt @@ -0,0 +1,256 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.jimage.* +import io.github.deficuet.unitykt.classes.* +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile +import io.github.deficuet.unitykt.math.Matrix4x4 +import io.github.deficuet.unitykt.math.Rectangle +import io.github.deficuet.unitykt.math.Vector2 +import io.github.deficuet.unitykt.math.Vector4 +import io.github.deficuet.unitykt.util.ObjectReader +import io.github.deficuet.unitykt.util.compareTo +import io.github.deficuet.unitykt.util.readArrayOf +import java.awt.image.BufferedImage +import java.nio.ByteBuffer +import java.util.* +import kotlin.math.ceil +import kotlin.math.floor +import kotlin.math.roundToInt + +internal class SpriteImpl( + assetFile: SerializedFile, info: ObjectInfo +): Sprite, SpriteFields(assetFile, info) { + override val mRect: Rectangle get() { + checkInitialize() + return fmRect + } + override val mOffset: Vector2 get() { + checkInitialize() + return fmOffset + } + override val mBorder: Vector4 get() { + checkInitialize() + return fmBorder + } + override val mPixelsToUnits: Float get() { + checkInitialize() + return fmPixelsToUnits + } + override val mPivot: Vector2 get() { + checkInitialize() + return fmPivot + } + override val mExtrude: UInt get() { + checkInitialize() + return fmExtrude + } + override val mIsPolygon: Boolean get() { + checkInitialize() + return fmIsPolygon + } + override val mRenderDataKey: Pair get() { + checkInitialize() + return fmRenderDataKey + } + override val mAtlasTags: Array get() { + checkInitialize() + return fmAtlasTags + } + override val mSpriteAtlas: PPtr? get() { + checkInitialize() + return fmSpriteAtlas + } + override val mRD: SpriteRenderData get() { + checkInitialize() + return fmRD + } + override val mPhysicsShape: Array> get() { + checkInitialize() + return fmPhysicsShape + } + + override fun read() { + super.read() + val version = reader.unityVersion + fmRect = reader.readRectangle() + fmOffset = reader.readVector2() + fmBorder = if (version >= intArrayOf(4, 5)) reader.readVector4() else Vector4.Zero + fmPixelsToUnits = reader.readFloat() + fmPivot = if (version >= intArrayOf(5, 4, 1, 3)) { + reader.readVector2() + } else Vector2(0.5f, 0.5f) + fmExtrude = reader.readUInt32() + if (version >= intArrayOf(5, 3)) { + fmIsPolygon = reader.readBool() + reader.alignStream() + } else { + fmIsPolygon = false + } + if (version[0] >= 2017) { + fmRenderDataKey = ByteBuffer.wrap(reader.read(16)).let { + val ret = UUID(it.long, it.long) + it.clear() + ret + } to reader.readInt64() + fmAtlasTags = reader.readAlignedStringArray() + fmSpriteAtlas = PPtrImpl(reader) + } else { + fmRenderDataKey = Pair(UUID(0L, 0L), 0L) + fmAtlasTags = emptyArray() + fmSpriteAtlas = null + } + fmRD = SpriteRenderDataImpl(reader) + fmPhysicsShape = if (version[0] >= 2017) { + reader.readNestedVector2Array() + } else emptyArray() + } + + override fun getImage(): BufferedImage? { + val spriteAtlas = mSpriteAtlas?.safeGetObj() + if (spriteAtlas != null) { + val spriteAtlasData = spriteAtlas.mRenderDataMap[mRenderDataKey] + val tex = spriteAtlasData?.texture?.safeGetObj() + if (tex != null) { + return cutImage( + tex, spriteAtlasData.textureRect, //spriteAtlasData.textureRectOffset, + spriteAtlasData.downScaleMultiplier, spriteAtlasData.settingsRaw + ) + } + } else { + val tex = mRD.texture.safeGetObj() + if (tex != null) { + return with(mRD) { + cutImage( + tex, textureRect, //textureRectOffset, + downScaleMultiplier, settingsRaw + ) + } + } + } + return null + } + + private fun cutImage( + tex: Texture2D, + rect: Rectangle, +// offset: Vector2, + downscaleMultiplier: Float, + settingsRow: SpriteSettings + ): BufferedImage? { + var image = tex.getImage() + if (image != null) { + if (downscaleMultiplier > 0f && downscaleMultiplier != 1f) { + val w = (tex.mWidth * downscaleMultiplier).roundToInt() + val h = (tex.mHeight * downscaleMultiplier).roundToInt() + image = image.resize(w, h) + } + val x = floor(rect.x).toInt() + val y = floor(rect.y).toInt() + val right = minOf(ceil(rect.x + rect.w).toInt(), image.width) + val bottom = minOf(ceil(rect.y + rect.h).toInt(), image.height) + var spriteImage = image.getSubimage(x, y, right - x, bottom - y) + if (settingsRow.packed == 1u) { + when (settingsRow.packingRotation) { + SpritePackingRotation.FlipHorizontal -> { + spriteImage = spriteImage.use { flipX() } + } + SpritePackingRotation.FlipVertical -> { + spriteImage = spriteImage.use { flipY() } + } + SpritePackingRotation.Rotate90 -> { + spriteImage = spriteImage.use { quadrantRotate(3) } + } + SpritePackingRotation.Rotate180 -> { + spriteImage = spriteImage.use { quadrantRotate(2) } + } + else -> { } + } + } +// if (settingsRow.packingMode == SpritePackingMode.Tight) { +// TODO("Sprite image tight") +// } + return spriteImage.use { flipY() } + } + return null + } +} + +internal class SecondarySpriteTextureImpl(reader: ObjectReader): SecondarySpriteTexture { + override val texture = PPtrImpl(reader) + override val name = reader.readNullString() +} + +internal class SpriteSettingsImpl(reader: ObjectReader): SpriteSettings { + override val settingsRaw = reader.readUInt32() + override val packed = settingsRaw.and(1u) + override val packingMode = SpritePackingMode.of(settingsRaw.shr(1).and(1u)) + override val packingRotation = SpritePackingRotation.of(settingsRaw.shr(2).and(0xFu)) + override val meshType = SpriteMeshType.of(settingsRaw.shr(6).and(1u)) +} + +internal class SpriteVertexImpl(reader: ObjectReader): SpriteVertex { + override val pos = reader.readVector3() + override val uv = if (reader.unityVersion <= intArrayOf(4, 3)) reader.readVector2() else Vector2.Zero +} + +internal class SpriteRenderDataImpl(reader: ObjectReader): SpriteRenderData { + override val texture = PPtrImpl(reader) + override val alphaTexture = if (reader.unityVersion >= intArrayOf(5, 2)) PPtrImpl(reader) else null + override val secondaryTexturesSize = if (reader.unityVersion[0] >= 2019) { + reader.readArrayOf { SecondarySpriteTextureImpl(this) } + } else emptyArray() + override val mSubMeshes: Array + override val mIndexBuffer: ByteArray + override val mVertexData: VertexData? + override val vertices: Array + override val indices: Array + override val mBindPose: Array + override val mSourceSkin: Array + override val textureRect: Rectangle + override val textureRectOffset: Vector2 + override val atlasRectOffset: Vector2 + override val settingsRaw: SpriteSettings + override val uvTransform: Vector4 + override val downScaleMultiplier: Float + + init { + val version = reader.unityVersion + if (version >= intArrayOf(5, 6)) { + mSubMeshes = reader.readArrayOf { SubMashImpl(this) } + mIndexBuffer = reader.readInt8Array() + reader.alignStream() + mVertexData = VertexDataImpl(reader) + vertices = emptyArray() + indices = emptyArray() + } else { + vertices = reader.readArrayOf { SpriteVertexImpl(this) } + indices = reader.readUInt16Array() + reader.alignStream() + mSubMeshes = emptyArray() + mIndexBuffer = ByteArray(0) + mVertexData = null + } + if (version[0] >= 2018) { + mBindPose = reader.readMatrix4x4Array() + mSourceSkin = if (version[0] == 2018 && version[1] < 2) { + reader.readArrayOf { BoneWeights4Impl(this) } + } else emptyArray() + } else { + mBindPose = emptyArray() + mSourceSkin = emptyArray() + } + textureRect = reader.readRectangle() + textureRectOffset = reader.readVector2() + atlasRectOffset = if (version >= intArrayOf(5, 6)) { + reader.readVector2() + } else Vector2.Zero + settingsRaw = SpriteSettingsImpl(reader) + uvTransform = if (version >= intArrayOf(4, 5)) { + reader.readVector4() + } else Vector4.Zero + downScaleMultiplier = if (version[0] >= 2017) { + reader.readFloat() + } else 0f + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/TextAssetImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/TextAssetImpl.kt new file mode 100644 index 00000000..f6d456bb --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/TextAssetImpl.kt @@ -0,0 +1,23 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.TextAsset +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile +import io.github.deficuet.unitykt.util.decodeToString +import java.nio.charset.Charset + +internal class TextAssetImpl( + assetFile: SerializedFile, info: ObjectInfo +): TextAsset, TextAssetFields(assetFile, info) { + override val mScript: ByteArray get() { + checkInitialize() + return fmScript + } + + override fun read() { + super.read() + fmScript = reader.readInt8Array() + } + + override fun getText(charset: Charset) = mScript.decodeToString(charset) +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/Texture2DImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/Texture2DImpl.kt new file mode 100644 index 00000000..c5e28a57 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/Texture2DImpl.kt @@ -0,0 +1,549 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.GLTextureSettings +import io.github.deficuet.unitykt.classes.StreamingInfo +import io.github.deficuet.unitykt.classes.Texture2D +import io.github.deficuet.unitykt.classes.TextureFormat +import io.github.deficuet.unitykt.enums.BuildTarget +import io.github.deficuet.unitykt.extension.TextureDecoder +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile +import io.github.deficuet.unitykt.util.* +import java.awt.image.* +import kotlin.math.pow +import kotlin.math.roundToInt + +internal class Texture2DImpl( + assetFile: SerializedFile, info: ObjectInfo +): Texture2D, Texture2DFields(assetFile, info) { + override val mWidth: Int get() { + checkInitialize() + return fmWidth + } + override val mHeight: Int get() { + checkInitialize() + return fmHeight + } + override val mTextureFormat: TextureFormat get() { + checkInitialize() + return fmTextureFormat + } + override val mMipMap: Boolean get() { + checkInitialize() + return fmMipMap + } + override val mMipCount: Int get() { + checkInitialize() + return fmMipCount + } + override val mTextureSettings: GLTextureSettings get() { + checkInitialize() + return fmTextureSettings + } + override val mStreamData: StreamingInfo? get() { + checkInitialize() + return fmStreamData + } + private val imageData: ResourceReader get() { + checkInitialize() + return pfImageData + } + + override fun read() { + super.read() + val version = reader.unityVersion + fmWidth = reader.readInt32() + fmHeight = reader.readInt32() + reader.skip(4) //m_CompleteImageSize: Int + if (version[0] >= 2020) reader.skip(4) //m_MipsStripped: Int + fmTextureFormat = TextureFormat.of(reader.readInt32()) + if (version < intArrayOf(5, 2)) { + fmMipMap = reader.readBool() + fmMipCount = 0 + } else { + fmMipCount = reader.readInt32() + fmMipMap = false + } + if (version >= intArrayOf(2, 6)) reader.skip(1) //m_IsReadable: Boolean + if (version[0] >= 2020) reader.skip(1) //m_IsPreProcessed: Boolean + if (version >= intArrayOf(2019, 3)) reader.skip(1) //m_IgnoreMasterTextureLimit: Boolean + if (version[0] >= 3 && version <= intArrayOf(5, 4)) reader.skip(1) //m_ReadAllowed: Boolean + if (version >= intArrayOf(2018, 2)) reader.skip(1) //m_StreamingMipmaps: Boolean + reader.alignStream() + if (version >= intArrayOf(2018, 2)) reader.skip(4) //m_StreamingMipmapsPriority: Int + reader.skip(8) //m_ImageCount, m_TextureDimension: Int + fmTextureSettings = GLTextureSettingsImpl(reader) + if (version[0] >= 3) reader.skip(4) //m_LightmapFormat: Int + if (version >= intArrayOf(3, 5)) reader.skip(4) //m_ColorSpace: Int + if (version >= intArrayOf(2020, 2)) { + reader.readInt8Array() //m_PlatformBlob + reader.alignStream() + } + val imageDataSize = reader.readInt32() + fmStreamData = if (imageDataSize == 0 && version >= intArrayOf(5, 3)) { + StreamingInfoImpl(reader) + } else null + pfImageData = if (fmStreamData?.path?.isNotEmpty() == true) { + ResourceReader(fmStreamData!!.path, assetFile, fmStreamData!!.offset, fmStreamData!!.size.toLong()) + } else { + ResourceReader(reader, reader.absolutePosition, imageDataSize.toLong()) + }.registerToManager(assetFile.root.manager) + } + + override fun getDecompressedData(): ByteArray? { + return decompressTexture(imageData.read()) + } + + override fun getImage(): BufferedImage? { + return getDecompressedData()?.let { raw -> + BufferedImage(mWidth, mHeight, BufferedImage.TYPE_4BYTE_ABGR).apply { + data = Raster.createRaster( + ComponentSampleModel( + DataBuffer.TYPE_BYTE, mWidth, mHeight, 4, + mWidth * 4, intArrayOf(2, 1, 0, 3) + ), + DataBufferByte(raw, raw.size), null + ) + } + } + } + + private fun swapForXBOX360(b: ByteArray) { + if (platform == BuildTarget.XBOX360) b.reverse() + } + + private fun decompressTexture(data: ByteArray): ByteArray? { + val areaIndices = 0 until mWidth * mHeight + val dataSize = mWidth * mHeight * 4 + val dataSizeIndices = 0 until dataSize step 4 + val out: ByteArray? + when (mTextureFormat) { + TextureFormat.Alpha8 -> { + out = ByteArray(dataSize) { + when (it % 4) { + 3 -> data[it / 4] + else -> -1 + } + } + } + TextureFormat.ARGB4444 -> { + swapForXBOX360(data) + out = ByteArray(dataSize) { idx -> + when (idx % 4) { + 0 -> data[(idx / 4 * 2 + 1).toUInt()].and(0x0F) + .let { it.shl(4).or(it) }.toByte() + 1 -> data[(idx / 4 * 2 + 1).toUInt()].and(0xF0).shr(4) + .let { it.shl(4).or(it) }.toByte() + 2 -> data[(idx / 4 * 2).toUInt()].and(0x0F) + .let { it.shl(4).or(it) }.toByte() + else -> data[(idx / 4 * 2).toUInt()].and(0xF0).shr(4) + .let { it.shl(4).or(it) }.toByte() + } + } + } + TextureFormat.RGB24 -> { + out = ByteArray(dataSize) { + when (it % 4) { + 0 -> data[it / 4 * 3 + 2] + 1 -> data[it / 4 * 3 + 1] + 2 -> data[it / 4 * 3] + else -> -1 + } + } + } + TextureFormat.RGBA32 -> { + out = ByteArray(dataSize) { + when (it % 4) { + 0 -> data[it + 2] + 2 -> data[it - 2] + else -> data[it] + } + } + } + TextureFormat.ARGB32 -> { + out = ByteArray(dataSize) { + when (it % 4) { + 0 -> data[it + 3] + 1 -> data[it + 1] + 2 -> data[it - 1] + else -> data[it - 3] + } + } + } + TextureFormat.RGB565 -> { + swapForXBOX360(data) + out = ByteArray(dataSize) + for (i in areaIndices) { + val iu = i.toUInt() + val p = data[iu*2u].shl(8).or(data[iu*2u+1u]) + out[i * 4] = p.shl(3).or(p.shr(2).and(7)).toByte() + out[i * 4 + 1] = p.shr(3).and(0xFC).or(p.shr(9).and(3)).toByte() + out[i * 4 + 2] = p.shr(8).and(0xF8).or(p.shr(13)).toByte() + out[i * 4 + 3] = -1 + } + } + TextureFormat.RGBA4444 -> { + out = ByteArray(dataSize) { idx -> + when (idx % 4) { + 0 -> data[(idx / 4 * 2 + 1).toUInt()].and(0xF0).shr(4) + .let { it.shl(4).or(it) }.toByte() + 1 -> data[(idx / 4 * 2).toUInt()].and(0x0F) + .let { it.shl(4).or(it) }.toByte() + 2 -> data[(idx / 4 * 2).toUInt()].and(0xF0).shr(4) + .let { it.shl(4).or(it) }.toByte() + else -> data[(idx / 4 * 2 + 1).toUInt()].and(0x0F) + .let { it.shl(4).or(it) }.toByte() + } + } + } + TextureFormat.BGR24 -> { + out = ByteArray(dataSize) { + when (it % 4) { + 0 -> data[it / 4 * 3] + 1 -> data[it / 4 * 3 + 1] + 2 -> data[it / 4 * 3 + 2] + else -> -1 + } + } + } + TextureFormat.BGRA32 -> { + out = data.copyOf() + } + TextureFormat.RHalf -> { + out = ByteArray(mWidth * mHeight * 4) { + val i = it.toUInt() + when (it % 4) { + 2 -> (parseHalf(data, i / 4u * 2u) * 255f).roundToInt().toByte() + 3 -> -1 + else -> 0 + } + } + } + TextureFormat.RGHalf -> { + out = ByteArray(dataSize) { + val i = it.toUInt() + when (it % 4) { + 0 -> 0 + 1 -> (parseHalf(data, i / 4u * 4u + 2u) * 255).roundToInt().toByte() + 2 -> (parseHalf(data, i / 4u * 4u) * 255).roundToInt().toByte() + else -> -1 + } + } + } + TextureFormat.RGBAHalf -> { + out = ByteArray(dataSize) { + val i = it.toUInt() + when (it % 4) { + 0 -> (parseHalf(data, i / 4u * 8u + 4u) * 255f).roundToInt().toByte() + 1 -> (parseHalf(data, i / 4u * 8u + 2u) * 255f).roundToInt().toByte() + 2 -> (parseHalf(data, i / 4u * 8u) * 255f).roundToInt().toByte() + else -> (parseHalf(data, i / 4u * 8u + 6u) * 255f).roundToInt().toByte() + } + } + } + TextureFormat.RFloat -> { + out = ByteArray(dataSize) { + val i = it.toUInt() + when (it % 4) { + 2 -> (parseFloat(data, i / 4u * 4u) * 255f).roundToInt().toByte() + 3 -> -1 + else -> 0 + } + } + } + TextureFormat.RGFloat -> { + out = ByteArray(dataSize) { + val i = it.toUInt() + when (it % 4) { + 0 -> 0 + 1 -> (parseFloat(data, i / 4u * 8u + 4u) * 255f).roundToInt().toByte() + 2 -> (parseFloat(data, i / 4u * 8u) * 255f).roundToInt().toByte() + else -> -1 + } + } + } + TextureFormat.RGBFloat -> { + out = ByteArray(dataSize) { + val i = it.toUInt() + when (it % 4) { + 0 -> (parseFloat(data, i / 4u * 12u + 8u) * 255f).roundToInt().toByte() + 1 -> (parseFloat(data, i / 4u * 12u + 4u) * 255f).roundToInt().toByte() + 2 -> (parseFloat(data, i / 4u * 12u) * 255f).roundToInt().toByte() + else -> -1 + } + } + } + TextureFormat.RGBAFloat -> { + out = ByteArray(dataSize) { + val i = it.toUInt() + when (it % 4) { + 0 -> (parseFloat(data, i / 4u * 16u + 8u) * 255f).roundToInt().toByte() + 1 -> (parseFloat(data, i / 4u * 16u + 4u) * 255f).roundToInt().toByte() + 2 -> (parseFloat(data, i / 4u * 16u) * 255f).roundToInt().toByte() + else -> (parseFloat(data, i / 4u * 16u + 12u) * 255f).roundToInt().toByte() + } + } + } + TextureFormat.YUY2 -> { + out = ByteArray(dataSize) + var p = 0u; var o = 0 + for (y in 0 until mHeight) { + for (x in 0 until mWidth / 2) { + val y0 = data[p++] + val u0 = data[p++] + val y1 = data[p++] + val v0 = data[p++] + var c = y0 - 16 + val d = u0 - 128 + val e = v0 - 128 + out[o++] = (298 * c + 516 * d + 128).shr(8).clampByte() + out[o++] = (298 * c - 100 * d - 208 * e + 128).shr(8).clampByte() + out[o++] = (298 * c + 409 * e + 128).shr(8).clampByte() + out[o++] = -1 + c = y1 - 16 + out[o++] = (298 * c + 516 * d + 128).shr(8).clampByte() + out[o++] = (298 * c - 100 * d - 208 * e + 128).shr(8).clampByte() + out[o++] = (298 * c + 409 * e + 128).shr(8).clampByte() + out[o++] = -1 + } + } + } + TextureFormat.RGB9e5Float -> { + out = ByteArray(dataSize) + for (i in dataSizeIndices) { + val n = parseInt(data, i.toUInt()) + val scale = n.shr(27).and(0x1F) + val scalef = (2.0).pow(scale - 24) + val b = n.shr(18).and(0x1FF) + val g = n.shr(9).and(0x1FF) + val r = n.and(0x1FF) + out[i] = (b * scalef * 255).roundToInt().toByte() + out[i + 1] = (g * scalef * 255).roundToInt().toByte() + out[i + 2] = (r * scalef * 255).roundToInt().toByte() + out[i + 3] = -1 + } + } + TextureFormat.R8 -> { + out = ByteArray(dataSize) { + when (it % 4) { + 2 -> data[it / 4] + 3 -> -1 + else -> 0 + } + } + } + TextureFormat.R16 -> { + out = ByteArray(dataSize) { + val i = it.toUInt() + when (it % 4) { + 2 -> parseDownScaledInt8(data, i * 2u) + 3 -> -1 + else -> 0 + } + } + } + TextureFormat.RG16 -> { + out = ByteArray(dataSize) { + when (it % 4) { + 0 -> 0 + 1 -> data[it / 4 * 2 + 1] + 2 -> data[it / 4 * 2] + else -> -1 + } + } + } + TextureFormat.RG32 -> { + out = ByteArray(dataSize) { + val i = it.toUInt() + when (it % 4) { + 0 -> 0 + 1 -> parseDownScaledInt8(data, i / 4u * 4u + 2u) + 2 -> parseDownScaledInt8(data, i / 4u * 4u) + else -> -1 + } + } + } + TextureFormat.RGB48 -> { + out = ByteArray(dataSize) { + val i = it.toUInt() + when (it % 4) { + 0 -> parseDownScaledInt8(data, i / 4u * 6u + 4u) + 1 -> parseDownScaledInt8(data, i / 4u * 6u + 2u) + 2 -> parseDownScaledInt8(data, i / 4u * 6u) + else -> -1 + } + } + } + TextureFormat.RGBA64 -> { + out = ByteArray(dataSize) { + val i = it.toUInt() + when (it % 4) { + 0 -> parseDownScaledInt8(data, i / 4u * 8u + 4u) + 1 -> parseDownScaledInt8(data, i / 4u * 8u + 2u) + 2 -> parseDownScaledInt8(data, i / 4u * 8u) + else -> parseDownScaledInt8(data, i / 4u * 8u + 6u) + } + } + } + TextureFormat.DXT1 -> { + swapForXBOX360(data) + out = ByteArray(dataSize) + TextureDecoder.decodeDXT1(data, mWidth, mHeight, out) + } + TextureFormat.DXT1Crunched -> { + out = ByteArray(dataSize) + unpackCrunch(data)?.let { + TextureDecoder.decodeDXT1(it, mWidth, mHeight, out) + } + } + TextureFormat.DXT5 -> { + swapForXBOX360(data) + out = ByteArray(dataSize) + TextureDecoder.decodeDXT5(data, mWidth, mHeight, out) + } + TextureFormat.DXT5Crunched -> { + out = ByteArray(dataSize) + unpackCrunch(data)?.let { + TextureDecoder.decodeDXT5(it, mWidth, mHeight, out) + } + } + TextureFormat.BC4 -> { + out = ByteArray(dataSize) + TextureDecoder.decodeBC4(data, mWidth, mHeight, out) + } + TextureFormat.BC5 -> { + out = ByteArray(dataSize) + TextureDecoder.decodeBC5(data, mWidth, mHeight, out) + } + TextureFormat.BC6H -> { + out = ByteArray(dataSize) + TextureDecoder.decodeBC6(data, mWidth, mHeight, out) + } + TextureFormat.BC7 -> { + out = ByteArray(dataSize) + TextureDecoder.decodeBC7(data, mWidth, mHeight, out) + } + TextureFormat.PVRTC_RGB2, TextureFormat.PVRTC_RGBA2 -> { + out = ByteArray(dataSize) + TextureDecoder.decodePVRTC(data, mWidth, mHeight, out, true) + } + TextureFormat.PVRTC_RGB4, TextureFormat.PVRTC_RGBA4 -> { + out = ByteArray(dataSize) + TextureDecoder.decodePVRTC(data, mWidth, mHeight, out, false) + } + TextureFormat.ETC_RGB4, TextureFormat.ETC_RGB4_3DS -> { + out = ByteArray(dataSize) + TextureDecoder.decodeETC1(data, mWidth, mHeight, out) + } + TextureFormat.ATC_RGB4 -> { + out = ByteArray(dataSize) + TextureDecoder.decodeATCRGB4(data, mWidth, mHeight, out) + } + TextureFormat.ATC_RGBA8 -> { + out = ByteArray(dataSize) + TextureDecoder.decodeATCRGBA8(data, mWidth, mHeight, out) + } + TextureFormat.EAC_R -> { + out = ByteArray(dataSize) + TextureDecoder.decodeEACR(data, mWidth, mHeight, out) + } + TextureFormat.EAC_R_SIGNED -> { + out = ByteArray(dataSize) + TextureDecoder.decodeEACRSigned(data, mWidth, mHeight, out) + } + TextureFormat.EAC_RG -> { + out = ByteArray(dataSize) + TextureDecoder.decodeEACRG(data, mWidth, mHeight, out) + } + TextureFormat.EAC_RG_SIGNED -> { + out = ByteArray(dataSize) + TextureDecoder.decodeEACRGSigned(data, mWidth, mHeight, out) + } + TextureFormat.ETC2_RGB -> { + out = ByteArray(dataSize) + TextureDecoder.decodeETC2(data, mWidth, mHeight, out) + } + TextureFormat.ETC2_RGBA1 -> { + out = ByteArray(dataSize) + TextureDecoder.decodeETC2A1(data, mWidth, mHeight, out) + } + TextureFormat.ETC2_RGBA8, TextureFormat.ETC_RGBA8_3DS -> { + out = ByteArray(dataSize) + TextureDecoder.decodeETC2A8(data, mWidth, mHeight, out) + } + TextureFormat.ETC_RGB4Crunched -> { + out = ByteArray(dataSize) + unpackCrunch(data)?.let { + TextureDecoder.decodeETC1(it, mWidth, mHeight, out) + } + } + TextureFormat.ETC2_RGBA8Crunched -> { + out = ByteArray(dataSize) + unpackCrunch(data)?.let { + TextureDecoder.decodeETC2A8(it, mWidth, mHeight, out) + } + } + TextureFormat.ASTC_RGB_4x4, TextureFormat.ASTC_RGBA_4x4, TextureFormat.ASTC_HDR_4x4 -> { + out = ByteArray(dataSize) + TextureDecoder.decodeASTC(data, mWidth, mHeight, out, 4) + } + TextureFormat.ASTC_RGB_5x5, TextureFormat.ASTC_RGBA_5x5, TextureFormat.ASTC_HDR_5x5 -> { + out = ByteArray(dataSize) + TextureDecoder.decodeASTC(data, mWidth, mHeight, out, 5) + } + TextureFormat.ASTC_RGB_6x6, TextureFormat.ASTC_RGBA_6x6, TextureFormat.ASTC_HDR_6x6 -> { + out = ByteArray(dataSize) + TextureDecoder.decodeASTC(data, mWidth, mHeight, out, 6) + } + TextureFormat.ASTC_RGB_8x8, TextureFormat.ASTC_RGBA_8x8, TextureFormat.ASTC_HDR_8x8 -> { + out = ByteArray(dataSize) + TextureDecoder.decodeASTC(data, mWidth, mHeight, out, 8) + } + TextureFormat.ASTC_RGB_10x10, TextureFormat.ASTC_RGBA_10x10, TextureFormat.ASTC_HDR_10x10 -> { + out = ByteArray(dataSize) + TextureDecoder.decodeASTC(data, mWidth, mHeight, out, 10) + } + TextureFormat.ASTC_RGB_12x12, TextureFormat.ASTC_RGBA_12x12, TextureFormat.ASTC_HDR_12x12 -> { + out = ByteArray(dataSize) + TextureDecoder.decodeASTC(data, mWidth, mHeight, out, 12) + } + else -> { + //Unknown, DXT3 + out = null + } + } + return out + } + + private fun unpackCrunch(data: ByteArray): ByteArray? { + return if ( + unityVersion >= intArrayOf(2017, 3) || + mTextureFormat == TextureFormat.ETC_RGB4Crunched || + mTextureFormat == TextureFormat.ETC2_RGBA8Crunched + ) { + TextureDecoder.unpackUnityCrunch(data) + } else { + TextureDecoder.unpackCrunch(data) + } + } +} + +internal class StreamingInfoImpl(reader: ObjectReader): StreamingInfo { + override val offset = if (reader.unityVersion[0] >= 2020) reader.readInt64() else reader.readUInt32().toLong() + override val size = reader.readUInt32() + override val path = reader.readAlignedString() +} + +internal class GLTextureSettingsImpl(reader: ObjectReader): GLTextureSettings { + override val mFilterMode = reader.readInt32() + override val mAniso = reader.readInt32() + override val mMipBias = reader.readFloat() + override val mWrapMode: Int + + init { + if (reader.unityVersion[0] >= 2017) { + mWrapMode = reader.readInt32() + reader.skip(8) //m_WrapV, m_WrapW: Int + } else mWrapMode = reader.readInt32() + } +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/TextureImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/TextureImpl.kt new file mode 100644 index 00000000..6c1e26f8 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/TextureImpl.kt @@ -0,0 +1,18 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.Texture +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile +import io.github.deficuet.unitykt.util.compareTo + +internal abstract class TextureImpl( + assetFile: SerializedFile, info: ObjectInfo +): Texture, TextureFields(assetFile, info) { + override fun read() { + super.read() + // m_ForcedFallbackFormat: Int, m_DownscaleFallback: Boolean + // when >= 2020.2: m_IsAlphaChannelOptional: Boolean + reader.skip(if (unityVersion >= intArrayOf(2020, 2)) 6 else 5) + reader.alignStream() + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/TransformImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/TransformImpl.kt new file mode 100644 index 00000000..c0f2068c --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/TransformImpl.kt @@ -0,0 +1,43 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.PPtr +import io.github.deficuet.unitykt.classes.Transform +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile +import io.github.deficuet.unitykt.math.Quaternion +import io.github.deficuet.unitykt.math.Vector3 +import io.github.deficuet.unitykt.util.readArrayOf + +internal open class TransformImpl( + assetFile: SerializedFile, info: ObjectInfo +): Transform, TransformFields(assetFile, info) { + final override val mLocalRotation: Quaternion get() { + checkInitialize() + return fmLocalRotation + } + final override val mLocalPosition: Vector3 get() { + checkInitialize() + return fmLocalPosition + } + final override val mLocalScale: Vector3 get() { + checkInitialize() + return fmLocalScale + } + final override val mChildren: Array> get() { + checkInitialize() + return fmChildren + } + final override val mFather: PPtr get() { + checkInitialize() + return fmFather + } + + override fun read() { + super.read() + fmLocalRotation = reader.readQuaternion() + fmLocalPosition = reader.readVector3() + fmLocalScale = reader.readVector3() + fmChildren = reader.readArrayOf { PPtrImpl(this) } + fmFather = PPtrImpl(reader) + } +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/UnityObjectImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/UnityObjectImpl.kt new file mode 100644 index 00000000..3a7c164b --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/UnityObjectImpl.kt @@ -0,0 +1,50 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.UnityObject +import io.github.deficuet.unitykt.enums.BuildTarget +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile +import io.github.deficuet.unitykt.util.ObjectReader +import org.json.JSONObject + +internal open class UnityObjectImpl( + val assetFile: SerializedFile, + private val info: ObjectInfo +): UnityObject { + protected val reader = ObjectReader(assetFile, info) + + final override val context get() = assetFile.root + final override val type get() = info.type + final override val mPathID get() = info.mPathID + final override val unityVersion get() = assetFile.version + final override val platform get() = assetFile.targetPlatform + final override val serializedType get() = info.serializedType + final override val bytes get() = reader.bytes + val buildType get() = assetFile.buildType + + final override fun dump() = serializedType?.typeTree?.readTypeString(reader) + final override fun toTypeTree() = serializedType?.typeTree?.readType(reader) + + final override fun toTypeTreeJson(): JSONObject? { + return toTypeTree()?.let { JSONObject(it) } + } + + final override fun toTypeTreeJsonString(indent: Int): String { + return toTypeTreeJson()?.toString(indent) ?: "null" + } + + protected open fun read() { + println("Object($type) path id $mPathID initialized") + reader.position = 0 + if (platform == BuildTarget.NoTarget) reader.skip(4) //m_ObjectHideFlags: UInt + } + + private var initialized = false + + protected fun checkInitialize() { + if (!initialized) { + read() + initialized = true + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/VideoClipImpl.kt b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/VideoClipImpl.kt new file mode 100644 index 00000000..453aef8a --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/internal/impl/VideoClipImpl.kt @@ -0,0 +1,136 @@ +package io.github.deficuet.unitykt.internal.impl + +import io.github.deficuet.unitykt.classes.PPtr +import io.github.deficuet.unitykt.classes.Shader +import io.github.deficuet.unitykt.classes.StreamedResource +import io.github.deficuet.unitykt.classes.VideoClip +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile +import io.github.deficuet.unitykt.util.ObjectReader +import io.github.deficuet.unitykt.util.ResourceReader +import io.github.deficuet.unitykt.util.compareTo +import io.github.deficuet.unitykt.util.readArrayOf + +internal class VideoClipImpl( + assetFile: SerializedFile, info: ObjectInfo +): VideoClip, VideoClipFields(assetFile, info) { + override val mOriginalPath: String get() { + checkInitialize() + return fmOriginalPath + } + override val mProxyWidth: UInt get() { + checkInitialize() + return fmProxyWidth + } + override val mProxyHeight: UInt get() { + checkInitialize() + return fmProxyHeight + } + override val mWidth: UInt get() { + checkInitialize() + return fmWidth + } + override val mHeight: UInt get() { + checkInitialize() + return fmHeight + } + override val mPixelAspectRatioNumerator: UInt get() { + checkInitialize() + return fmPixelAspectRatioNumerator + } + override val mPixelAspectRatioDenominator: UInt get() { + checkInitialize() + return fmPixelAspectRatioDenominator + } + override val mFrameRate: Double get() { + checkInitialize() + return fmFrameRate + } + override val mFrameCount: ULong get() { + checkInitialize() + return fmFrameCount + } + override val mFormat: Int get() { + checkInitialize() + return fmFormat + } + override val mAudioChannelCount: Array get() { + checkInitialize() + return fmAudioChannelCount + } + override val mAudioSampleRate: Array get() { + checkInitialize() + return fmAudioSampleRate + } + override val mAudioLanguage: Array get() { + checkInitialize() + return fmAudioLanguage + } + override val mVideoShaders: Array> get() { + checkInitialize() + return fmVideoShaders + } + override val mExternalResource: StreamedResource get() { + checkInitialize() + return fmExternalResource + } + override val mHasSplitAlpha: Boolean get() { + checkInitialize() + return fmHasSplitAlpha + } + override val msRGB: Boolean get() { + checkInitialize() + return fmsRGB + } + + private val videoData: ResourceReader get() { + checkInitialize() + return pfVideoData + } + + override fun read() { + super.read() + fmOriginalPath = reader.readAlignedString() + fmProxyWidth = reader.readUInt32() + fmProxyHeight = reader.readUInt32() + fmWidth = reader.readUInt32() + fmHeight = reader.readUInt32() + if (unityVersion >= intArrayOf(2017, 2)) { + fmPixelAspectRatioNumerator = reader.readUInt32() + fmPixelAspectRatioDenominator = reader.readUInt32() + } else { + fmPixelAspectRatioNumerator = 0u + fmPixelAspectRatioDenominator = 0u + } + fmFrameRate = reader.readDouble() + fmFrameCount = reader.readUInt64() + fmFormat = reader.readInt32() + fmAudioChannelCount = reader.readUInt16Array() + reader.alignStream() + fmAudioSampleRate = reader.readUInt32Array() + fmAudioLanguage = reader.readAlignedStringArray() + fmVideoShaders = if (unityVersion[0] >= 2020) { + reader.readArrayOf { PPtrImpl(reader) } + } else emptyArray() + fmExternalResource = StreamedResourceImpl(reader) + fmHasSplitAlpha = reader.readBool() + fmsRGB = if (unityVersion[0] >= 2020) reader.readBool() else false + pfVideoData = if (fmExternalResource.mSource.isNotEmpty()) { + with(fmExternalResource) { + ResourceReader(mSource, assetFile, mOffset, mSize) + } + } else { + ResourceReader(reader, reader.absolutePosition, fmExternalResource.mSize) + }.registerToManager(assetFile.root.manager) + } + + override fun getRawData(): ByteArray { + return videoData.read() + } +} + +internal class StreamedResourceImpl(reader: ObjectReader): StreamedResource { + override val mSource = reader.readAlignedString() + override val mOffset = reader.readInt64() + override val mSize = reader.readInt64() +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/main.kt b/src/main/kotlin/io/github/deficuet/unitykt/main.kt new file mode 100644 index 00000000..cc0db919 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/main.kt @@ -0,0 +1,18 @@ +package io.github.deficuet.unitykt + +import io.github.deficuet.unitykt.classes.Sprite +import java.io.File +import javax.imageio.ImageIO + +fun main() { + val tm = System.currentTimeMillis() + val m = UnityAssetManager.new() + val c = m.loadFile("C:\\Users\\Defic\\self\\Programs\\ALAssetsDownloader\\AssetBundles\\paintingface\\safuke") +// val d = m.loadFile("C:\\Users\\Defic\\self\\Programs\\ALAssetsDownloader\\AssetBundles\\paintingface\\safuke_xinshou") + val root = "C:\\Users\\Defic\\self\\Programs\\srcode\\py\\AzurLaneScriptsDecode\\temp" + val i = c.objectMap.getAs(-3269655441389158635).getImage() + assert(i != null) + println(System.currentTimeMillis() - tm) + ImageIO.write(i, "png", File("$root/safuke8.png")) +} + diff --git a/src/main/kotlin/io/github/deficuet/unitykt/math/Color.kt b/src/main/kotlin/io/github/deficuet/unitykt/math/Color.kt index c433cbe2..787e75a9 100644 --- a/src/main/kotlin/io/github/deficuet/unitykt/math/Color.kt +++ b/src/main/kotlin/io/github/deficuet/unitykt/math/Color.kt @@ -1,48 +1,38 @@ package io.github.deficuet.unitykt.math -data class Color(val r: Double, val g: Double, val b: Double, val a: Double) { - constructor(r: Float, g: Float, b: Float, a: Float): - this(r.toDouble(), g.toDouble(), b.toDouble(), a.toDouble()) +class Color(val r: Float, val g: Float, val b: Float, val a: Float) { + val vector4: Vector4 get() = Vector4(r, g, b, a) - val vector4: Vector4 - get() = Vector4(r, g, b, a) + operator fun plus(other: Color) = Color(r + other.r, g + other.g, b + other.b, a + other.a) + operator fun minus(other: Color) = Color(r - other.r, g - other.g, b - other.b, a - other.a) + operator fun times(other: Color) = Color(r * other.r, g * other.g, b * other.b, a * other.a) + operator fun div(other: Color) = Color(r / other.r, g / other.g, b / other.b, a / other.a) - operator fun plus(other: Color): Color = - Color(r + other.r, g + other.g, b + other.b, a + other.a) - - operator fun minus(other: Color): Color = - Color(r - other.r, g - other.g, b - other.b, a - other.a) - - operator fun times(other: Color): Color = - Color(r * other.r, g * other.g, b * other.b, a * other.a) - - operator fun times(x: N): Color where N: Number, N: Comparable = - Color(r * x, g * x, b * x, a * x) + operator fun times(x: N): Color { + val n = x.toFloat() + return Color(r * n, g * n, b * n, a * n) + } - operator fun div(other: Color) = - Color(r / other.r, g / other.g, b / other.b, a / other.a) + operator fun div(x: N): Color { + val n = x.toFloat() + return Color(r / n, g / n, b / n, a / n) + } - operator fun div(x: N): Color where N: Number, N: Comparable = - Color(r / x, g / x, b / x, a / x) + override fun toString(): String { + return "Color(R: $r, G: $g, B: $b, A: $a)" + } - //Auto generated override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false other as Color - if (r != other.r) return false - if (g != other.g) return false - if (b != other.b) return false - if (a != other.a) return false - return true + return r == other.r && g == other.g && b == other.b && a == other.a } - //Auto generated override fun hashCode(): Int { - var result = r.hashCode() - result = 31 * result + g.hashCode() - result = 31 * result + b.hashCode() - result = 31 * result + a.hashCode() - return result + return r.hashCode() + .xor(g.hashCode().shl(2)) + .xor(b.hashCode().shr(2)) + .xor(a.hashCode().shr(1)) } } diff --git a/src/main/kotlin/io/github/deficuet/unitykt/math/Matrix4x4.kt b/src/main/kotlin/io/github/deficuet/unitykt/math/Matrix4x4.kt index b6430bf1..d231e1ed 100644 --- a/src/main/kotlin/io/github/deficuet/unitykt/math/Matrix4x4.kt +++ b/src/main/kotlin/io/github/deficuet/unitykt/math/Matrix4x4.kt @@ -1,91 +1,172 @@ package io.github.deficuet.unitykt.math -import io.github.deficuet.unitykt.cast - -data class Matrix4x4(private val data: DoubleArray) { - private constructor(dataBlock: () -> DoubleArray): this(dataBlock()) - - init { - if (data.size != 16) - throw IllegalStateException("There must be sixteen and only sixteen input values for Matrix.") +/** + * ``` + * column no. + * 0 1 2 3 + * ----------------------- + * 0 [ ]|[ ]|[ ]|[ ] + * row no. 1 [ ]|[ ]|[ ]|[ ] + * 2 [ ]|[ ]|[ ]|[ ] + * 3 [ ]|[ ]|[ ]|[ ] + * ``` + * @param data `float[4][4]` Array of 4 **column** `float[4]` + */ +class Matrix4x4(private val data: Array) { + private constructor(dataBlock: () -> Array): this(dataBlock()) + + operator fun get(row: Int, column: Int) = data[column][row] + + /** + * Count by row + */ + operator fun get(index: Int) = data[index % 4][index / 4] + operator fun set(row: Int, column: Int, value: Float) { data[column][row] = value } + + /** + * Count by row + */ + operator fun set(index: Int, value: Float) { data[index % 4][index / 4] = value } + + /** + * Row vector + */ + fun row(index: Int) = Vector4(data[0][index], data[1][index], data[2][index], data[3][index]) + + /** + * Column vector + */ + fun column(index: Int) = with(data[index]) { Vector4(get(0), get(1), get(2), get(3)) } + + fun transpose() = Matrix4x4 { + Array(4) { col -> + FloatArray(4) { row -> + data[row][col] + } + } } - operator fun get(column: Int, row: Int) = data[column + row * 4] - - operator fun get(index: Int) = data[index] - - operator fun set(column: Int, row: Int, value: Double) { data[column + row * 4] = value } - - operator fun set(index: Int, value: Double) { data[index] = value } - - fun row(index: Int) = with(data.sliceArray(index * 4..index * 4 + 3)) { - Vector4(get(0), get(1), get(2), get(3)) + operator fun plus(m: Matrix4x4) = Matrix4x4 { + Array(4) { col -> + FloatArray(4) { row -> + data[col][row] + m[row, col] + } + } } - fun column(index: Int) = Vector4(data[index], data[index + 4], data[index + 8], data[index + 12]) + operator fun minus(m: Matrix4x4) = Matrix4x4 { + Array(4) { col -> + FloatArray(4) { row -> + data[col][row] - m[row, col] + } + } + } - fun scale(v3: Vector3) = Matrix4x4 { - DoubleArray(16) { 0.0 }.apply { - set(0, v3.x); set(5, v3.y); set(10, v3.z); set(15, 1.0) + /** + * For matrix, usually A * B != B * A + */ + operator fun times(m: Matrix4x4) = Matrix4x4 { + Array(4) { col -> + FloatArray(4) { row -> + data[0][row] * m[0, col] + + data[1][row] * m[1, col] + + data[2][row] * m[2, col] + + data[3][row] * m[3, col] + } } } - fun translate(v3: Vector3) = Matrix4x4 { - DoubleArray(16) { if (it % 5 == 0) 1.0 else 0.0 }.apply { - set(3, v3.x); set(7, v3.y); set(11, v3.z) + operator fun times(m: N) = Matrix4x4 { + val n = m.toFloat() + Array(4) { col -> + FloatArray(4) { row -> + data[col][row] * n + } } } - fun rotate(q: Quaternion) = Matrix4x4 { - val x = q.a * 2; val y = q.b * 2; val z = q.c * 2 - val xx = q.a * x; val yy = q.b * y; val zz = q.c * z - val xy = q.a * y; val xz = q.a * z; val yz = q.b * z - val wx = q.d * x; val wy = q.d * y; val wz = q.d * z - doubleArrayOf( - 1 - yy - zz, xy + wz, xz - wy, 0.0, - xy - wz, 1 - xx - zz, yz + wx, 0.0, - xz + wy, yz - wx, 1 - xx - yy, 0.0, - 0.0, 0.0, 0.0, 1.0 - ) + /** + * A * **v** + */ + operator fun times(v4: Vector4): Vector4 { + return FloatArray(4) { row -> + data[0][row] * v4.x + data[1][row] * v4.y + + data[2][row] * v4.z + data[3][row] * v4.w + }.let { Vector4(it[0], it[1], it[2], it[3]) } } - operator fun times(m: Matrix4x4) = Matrix4x4 { - val t = this - mutableList { - for (tc in 0..3) { - for (mr in 0..3) { - var sum = 0.0 - for (i in 0..3) sum += t[tc, i] * m[i, mr] - add(sum) - } + operator fun unaryMinus() = Matrix4x4 { + Array(4) { col -> + FloatArray(4) { row -> + -data[col][row] } - }.toDoubleArray() + } } override fun hashCode(): Int { - return column(0).hashCode().xor(column(1).hashCode().shl(2)) - .xor(column(2).hashCode().shr(2)).xor(column(3).hashCode().shr(1)) + return column(0).hashCode() + .xor(column(1).hashCode().shl(2)) + .xor(column(2).hashCode().shr(2)) + .xor(column(3).hashCode().shr(1)) } override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false - return data.contentEquals(other.cast().data) + other as Matrix4x4 + for (i in 0..4) { + if (column(i) != other.column(i)) { + return false + } + } + return true } - override fun toString(): String { - return intArrayOf(0, 1, 2, 3).map { - val c = column(it) - doubleArrayOf(c.x, c.y, c.z, c.w).maxOf { - d -> "%.4f".format(d).length - } - }.joinToString(" ") { "%-${it}.4f" } - .let { "| $it |\n" }.repeat(4).format(*data.toTypedArray()).trim() + fun toString(precision: Int): String { + val strArray = data.map { fa -> + val l = fa.maxOf { f -> "%.${precision}f".format(f).length } + Array(4) { index -> "%-${l}.${precision}f".format(fa[index]) } + } + return "[" + intArrayOf(0, 1, 2, 3).map { row -> + strArray.joinToString(" ") { it[row] } + }.joinToString("\n") { " [ $it ] " }.trim() + "]" } + override fun toString() = toString(2) + companion object { - //Secondary constructor in order to avoid signature conflict due to type erasure - operator fun invoke(data: List) = Matrix4x4(data.map { it.toDouble() }.toDoubleArray()) - operator fun invoke(vararg data: Float) = invoke(data.toList()) + fun scaleMatrix(v3: Vector3) = Matrix4x4 { + val v4 = Vector4(v3, 1f) + Array(4) { col -> + FloatArray(4) { row -> + if (row == col) v4[col] else 0f + } + } + } + + fun translateMatrix(v3: Vector3) = Matrix4x4 { + Array(4) { col -> + FloatArray(4) { row -> + when (col) { + row -> 1f + 3 -> v3[row] + else -> 0f + } + } + } + } + + fun rotateMatrix(q: Quaternion) = Matrix4x4 { + val x = q.a * 2; val y = q.b * 2; val z = q.c * 2 + val xx = q.a * x; val yy = q.b * y; val zz = q.c * z + val xy = q.a * y; val xz = q.a * z; val yz = q.b * z + val wx = q.d * x; val wy = q.d * y; val wz = q.d * z + arrayOf( + floatArrayOf( 1 - yy - zz, xy + wz, xz - wy, 0f ), + floatArrayOf( xy - wz, 1 - xx - zz, yz + wx, 0f ), + floatArrayOf( xz + wy, yz - wx, 1 - xx - yy, 0f ), + floatArrayOf( 0f, 0f, 0f, 1f ) + ) + } } } diff --git a/src/main/kotlin/io/github/deficuet/unitykt/math/Quaternion.kt b/src/main/kotlin/io/github/deficuet/unitykt/math/Quaternion.kt index ba68a2f9..d2db5340 100644 --- a/src/main/kotlin/io/github/deficuet/unitykt/math/Quaternion.kt +++ b/src/main/kotlin/io/github/deficuet/unitykt/math/Quaternion.kt @@ -1,14 +1,7 @@ package io.github.deficuet.unitykt.math -import io.github.deficuet.unitykt.cast - -data class Quaternion(val a: Double, val b: Double, val c: Double, val d: Double) { - constructor(a: Float, b: Float, c: Float, d: Float): - this(a.toDouble(), b.toDouble(), c.toDouble(), d.toDouble()) - - constructor(vararg data: Float): this(data[0], data[1], data[2], data[3]) - - operator fun get(index: Int): Double { +class Quaternion(val a: Float, val b: Float, val c: Float, val d: Float) { + operator fun get(index: Int): Float { return when (index) { 0 -> a 1 -> b @@ -30,14 +23,15 @@ data class Quaternion(val a: Double, val b: Double, val c: Double, val d: Double override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false - return dot(other.cast()) > 1.0 - kEpsilon + return dot(other as Quaternion) > 1f - kEpsilon } override fun toString(): String { - return "Quaternion(a, b, c, d) = ($a, $b, $c, $d)" + return "Quaternion($a, $b, $c, $d)" } companion object { - internal const val kEpsilon = 0.000001 + val Zero = Quaternion(0f, 0f, 0f, 0f) + private const val kEpsilon = 0.000001f } } \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/math/Rectangle.kt b/src/main/kotlin/io/github/deficuet/unitykt/math/Rectangle.kt index b70514c7..04157a42 100644 --- a/src/main/kotlin/io/github/deficuet/unitykt/math/Rectangle.kt +++ b/src/main/kotlin/io/github/deficuet/unitykt/math/Rectangle.kt @@ -1,9 +1,7 @@ package io.github.deficuet.unitykt.math -data class Rectangle(val x: Double, val y: Double, val w: Double, val h: Double) { - constructor(x: Float, y: Float, w: Float, h: Float): this(x.toDouble(), y.toDouble(), w.toDouble(), h.toDouble()) - +class Rectangle(val x: Float, val y: Float, val w: Float, val h: Float) { override fun toString(): String { - return "Rectangle at ($x, $y) with width and height ($w, $h)" + return "Rectangle(pos($x, $y), size($w, $h))" } } \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/math/Vector.kt b/src/main/kotlin/io/github/deficuet/unitykt/math/Vector.kt index 229a14d5..d978f3a3 100644 --- a/src/main/kotlin/io/github/deficuet/unitykt/math/Vector.kt +++ b/src/main/kotlin/io/github/deficuet/unitykt/math/Vector.kt @@ -1,10 +1,31 @@ package io.github.deficuet.unitykt.math -abstract class Vector { - abstract val unit: Vector +interface Vector { + val unit: V + val length: Float + + operator fun get(index: Int): Float + + operator fun plus(other: V): V + operator fun minus(other: V): V + + /** + * Treat the "Vector" as a number tuple + * @see dot + */ + operator fun times(other: V): V + + /** + * Treat the "Vector" as a number tuple + */ + operator fun div(other: V): V + operator fun times(m: N): V + operator fun div(d: N): V + infix fun dot(other: V): Float + + operator fun unaryMinus(): V companion object { - internal const val kEpsilonSqrt = 0.0031622776601683794 //sqrt(0.00001) - internal const val kEpsilon2 = 1.0e-10 //0.00001 ** 2 + internal const val kEpsilon2 = 1.0e-10f //0.00001 ** 2 } -} \ No newline at end of file +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/math/Vector2.kt b/src/main/kotlin/io/github/deficuet/unitykt/math/Vector2.kt index 1f3e20f4..45e1003f 100644 --- a/src/main/kotlin/io/github/deficuet/unitykt/math/Vector2.kt +++ b/src/main/kotlin/io/github/deficuet/unitykt/math/Vector2.kt @@ -3,19 +3,18 @@ package io.github.deficuet.unitykt.math import io.github.deficuet.unitykt.cast import kotlin.math.sqrt -class Vector2(val x: Double, val y: Double): Vector() { - constructor(x: Float, y: Float): this(x.toDouble(), y.toDouble()) +class Vector2(val x: Float, val y: Float): Vector { + val vector3: Vector3 get() = Vector3(this, 0f) + val vector4: Vector4 get() = Vector4(this, 0f, 0f) - val vector3: Vector3 get() = Vector3(this, 0.0) - - val vector4: Vector4 get() = Vector4(this, 0.0, 0.0) - - val length2 get() = x * x + y * y + private val length2 get() = x * x + y * y + override val length get() = sqrt(length2) override val unit: Vector2 get() { - return if (length2 > kEpsilonSqrt) { - with(1 / sqrt(length2)) { + val l2 = length2 + return if (l2 > Vector.kEpsilon2) { + with(1 / sqrt(l2)) { Vector2(x * this, y * this) } } else { @@ -23,7 +22,7 @@ class Vector2(val x: Double, val y: Double): Vector() { } } - operator fun get(index: Int): Double { + override operator fun get(index: Int): Float { return when (index) { 0 -> x 1 -> y @@ -31,19 +30,22 @@ class Vector2(val x: Double, val y: Double): Vector() { } } - operator fun plus(other: Vector2) = Vector2(x + other.x, y + other.y) - - operator fun minus(other: Vector2) = Vector2(x - other.x, y - other.y) - - operator fun times(other: Vector2) = Vector2(x * other.x, y * other.y) + override operator fun plus(other: Vector2) = Vector2(x + other.x, y + other.y) + override operator fun minus(other: Vector2) = Vector2(x - other.x, y - other.y) + override operator fun times(other: Vector2) = Vector2(x * other.x, y * other.y) + override operator fun div(other: Vector2) = Vector2(x / other.x, y / other.y) + override operator fun unaryMinus() = Vector2(-x, -y) + override infix fun dot(other: Vector2) = x * other.x + y * other.y - operator fun div(other: Vector2) = Vector2(x / other.x, y / other.y) - - operator fun unaryMinus() = Vector2(-x, -y) - - operator fun times(m: N): Vector2 where N: Number, N: Comparable = Vector2(x * m, y * m) + override operator fun times(m: N): Vector2 { + val n = m.toFloat() + return Vector2(x * n, y * n) + } - operator fun div(d: N): Vector2 where N: Number, N: Comparable = Vector2(x / d, y / d) + override operator fun div(d: N): Vector2 { + val n = d.toFloat() + return Vector2(x / n, y / n) + } operator fun component1() = x operator fun component2() = y @@ -55,14 +57,14 @@ class Vector2(val x: Double, val y: Double): Vector() { override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false - return minus(other.cast()).length2 < kEpsilon2 + return minus(other.cast()).length2 < Vector.kEpsilon2 } override fun toString(): String { - return "Vector(x, y) = ($x, $y)" + return "Vector2($x, $y)" } companion object { - val Zero = Vector2(0.0, 0.0) + val Zero = Vector2(0f, 0f) } } diff --git a/src/main/kotlin/io/github/deficuet/unitykt/math/Vector3.kt b/src/main/kotlin/io/github/deficuet/unitykt/math/Vector3.kt index bce3c995..1e645b61 100644 --- a/src/main/kotlin/io/github/deficuet/unitykt/math/Vector3.kt +++ b/src/main/kotlin/io/github/deficuet/unitykt/math/Vector3.kt @@ -3,21 +3,19 @@ package io.github.deficuet.unitykt.math import io.github.deficuet.unitykt.cast import kotlin.math.sqrt -class Vector3(val x: Double, val y: Double, val z: Double): Vector() { - constructor(x: Float, y: Float, z: Float): this(x.toDouble(), y.toDouble(), z.toDouble()) - - constructor(v2: Vector2, z: Double): this(v2.x, v2.y, z) - +class Vector3(val x: Float, val y: Float, val z: Float): Vector { + constructor(v2: Vector2, z: Float): this(v2.x, v2.y, z) val vector2: Vector2 get() = Vector2(x, y) + val vector4: Vector4 get() = Vector4(this, 0f) - val vector4: Vector4 get() = Vector4(this, 0.0) - - val length2 get() = x * x + y * y + z * z + private val length2 get() = x * x + y * y + z * z + override val length get() = sqrt(length2) override val unit: Vector3 get() { - return if (length2 > kEpsilonSqrt) { - with(1 / sqrt(length2)) { + val l2 = length2 + return if (l2 > Vector.kEpsilon2) { + with(1 / sqrt(l2)) { Vector3(x * this, y * this, z * this) } } else { @@ -25,7 +23,7 @@ class Vector3(val x: Double, val y: Double, val z: Double): Vector() { } } - operator fun get(index: Int): Double { + override operator fun get(index: Int): Float { return when (index) { 0 -> x 1 -> y @@ -34,19 +32,32 @@ class Vector3(val x: Double, val y: Double, val z: Double): Vector() { } } - operator fun plus(other: Vector3) = Vector3(x + other.x, y + other.y, z + other.z) - - operator fun minus(other: Vector3) = Vector3(x - other.x, y - other.y, z - other.z) - - operator fun times(other: Vector3) = Vector3(x * other.x, y * other.y, z * other.z) - - operator fun div(other: Vector3) = Vector3(x / other.x, y / other.y, z / other.z) - - operator fun unaryMinus() = Vector3(-x, -y, -z) + override operator fun plus(other: Vector3) = Vector3(x + other.x, y + other.y, z + other.z) + override operator fun minus(other: Vector3) = Vector3(x - other.x, y - other.y, z - other.z) + + /** + * Treat the "Vector" as a number tuple + * @see dot + * @see cross + */ + override operator fun times(other: Vector3) = Vector3(x * other.x, y * other.y, z * other.z) + override operator fun div(other: Vector3) = Vector3(x / other.x, y / other.y, z / other.z) + override operator fun unaryMinus() = Vector3(-x, -y, -z) + override infix fun dot(other: Vector3) = x * other.x + y * other.y + z * other.z + + infix fun cross(o: Vector3): Vector3 { + return Vector3(y * o.z - z * o.y, z * o.x - x * o.z, x * o.y - y * o.x) + } - operator fun times(m: N) where N: Number, N: Comparable = Vector3(x * m, y * m, z * m) + override operator fun times(m: N): Vector3 { + val n = m.toFloat() + return Vector3(x * n, y * n, z * n) + } - operator fun div(d: N) where N: Number, N: Comparable = Vector3(x / d, y / d, z / d) + override operator fun div(d: N): Vector3 { + val n = d.toFloat() + return Vector3(x / n, y / n, z / n) + } operator fun component1() = x operator fun component2() = y @@ -59,14 +70,14 @@ class Vector3(val x: Double, val y: Double, val z: Double): Vector() { override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false - return minus(other.cast()).length2 < kEpsilon2 + return minus(other.cast()).length2 < Vector.kEpsilon2 } override fun toString(): String { - return "Vector(x, y, z) = ($x, $y, $z)" + return "Vector3($x, $y, $z)" } companion object { - val Zero = Vector3(0.0, 0.0, 0.0) + val Zero = Vector3(0f, 0f, 0f) } } \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/math/Vector4.kt b/src/main/kotlin/io/github/deficuet/unitykt/math/Vector4.kt index 93766731..31a3741f 100644 --- a/src/main/kotlin/io/github/deficuet/unitykt/math/Vector4.kt +++ b/src/main/kotlin/io/github/deficuet/unitykt/math/Vector4.kt @@ -3,29 +3,21 @@ package io.github.deficuet.unitykt.math import io.github.deficuet.unitykt.cast import kotlin.math.sqrt -class Vector4( - val x: Double, val y: Double, - val z: Double, val w: Double -): Vector() { - constructor(x: Float, y: Float, z: Float, w: Float): - this(x.toDouble(), y.toDouble(), z.toDouble(), w.toDouble()) - - constructor(v2: Vector2, z: Double, w: Double): this(v2.x, v2.y, z, w) - - constructor(v3: Vector3, w: Double): this(v3.x, v3.y, v3.z, w) - +class Vector4(val x: Float, val y: Float, val z: Float, val w: Float): Vector { + constructor(v2: Vector2, z: Float, w: Float): this(v2.x, v2.y, z, w) + constructor(v3: Vector3, w: Float): this(v3.x, v3.y, v3.z, w) val vector2: Vector2 get() = Vector2(x, y) - val vector3: Vector3 get() = Vector3(x, y, z) - val color: Color get() = Color(x, y, z, w) - val length2 get() = x * x + y * y + z * z + w * w + private val length2 get() = x * x + y * y + z * z + w * w + override val length get() = sqrt(length2) override val unit: Vector4 get() { - return if(length2 > kEpsilonSqrt) { - with(1 / sqrt(length2)) { + val l2 = length2 + return if (l2 > Vector.kEpsilon2) { + with(1 / sqrt(l2)) { Vector4(x * this, y * this, z * this, w * this) } } else { @@ -33,7 +25,7 @@ class Vector4( } } - operator fun get(index: Int): Double { + override operator fun get(index: Int): Float { return when (index) { 0 -> x 1 -> y @@ -43,21 +35,22 @@ class Vector4( } } - operator fun plus(other: Vector4) = Vector4(x + other.x, y + other.y, z + other.z, w + other.w) - - operator fun minus(other: Vector4) = Vector4(x - other.x, y - other.y, z - other.z, w - other.w) + override operator fun plus(other: Vector4) = Vector4(x + other.x, y + other.y, z + other.z, w + other.w) + override operator fun minus(other: Vector4) = Vector4(x - other.x, y - other.y, z - other.z, w - other.w) + override operator fun times(other: Vector4) = Vector4(x * other.x, y * other.y, z * other.z, w * other.w) + override operator fun div(other: Vector4) = Vector4(x / other.x, y / other.y, z / other.z, w / other.w) + override operator fun unaryMinus() = Vector4(-x, -y, -z, -w) + override infix fun dot(other: Vector4) = x * other.x + y * other.y + z * other.z + w * other.w - operator fun times(other: Vector4) = Vector4(x * other.x, y * other.y, z * other.z, w * other.w) - - operator fun div(other: Vector4) = Vector4(x / other.x, y / other.y, z / other.z, w / other.w) - - operator fun unaryMinus() = Vector4(-x, -y, -z, -w) - - operator fun times(m: N) where N: Number, N: Comparable = - Vector4(x * m, y * m, z * m, w * m) + override operator fun times(m: N): Vector4 { + val n = m.toFloat() + return Vector4(x * n, y * n, z * n, w * n) + } - operator fun div(d: N) where N: Number, N: Comparable = - Vector4(x / d, y / d, z / d, w / d) + override operator fun div(d: N): Vector4 { + val n = d.toFloat() + return Vector4(x / n, y / n, z / n, w / n) + } operator fun component1() = x operator fun component2() = y @@ -74,14 +67,14 @@ class Vector4( override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false - return minus(other.cast()).length2 < kEpsilon2 + return minus(other.cast()).length2 < Vector.kEpsilon2 } override fun toString(): String { - return "Vector(x, y, z, w) = ($x, $y, $z, $w)" + return "Vector4($x, $y, $z, $w)" } companion object { - val Zero = Vector4(0.0, 0.0, 0.0, 0.0) + val Zero = Vector4(0f, 0f, 0f, 0f) } } \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/math/utils.kt b/src/main/kotlin/io/github/deficuet/unitykt/math/utils.kt deleted file mode 100644 index fb1a4322..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/math/utils.kt +++ /dev/null @@ -1,33 +0,0 @@ -package io.github.deficuet.unitykt.math - -import io.github.deficuet.unitykt.util.UnsupportedFormatException - -internal operator fun Double.times(x: N): Double where N: Number, N: Comparable { - val operator: (Double) -> Double = when (x) { - is Byte -> { { it * x } } - is Short -> { { it * x } } - is Int -> { { it * x } } - is Long -> { { it * x } } - is Float -> { { it * x } } - is Double -> { { it * x } } - else -> throw UnsupportedFormatException("Numeric type ${x::class}") - } - return operator(this) -} - -internal operator fun Double.div(x: N): Double where N: Number, N: Comparable { - val operator: (Double) -> Double = when (x) { - is Byte -> { { it / x } } - is Short -> { { it / x } } - is Int -> { { it / x } } - is Long -> { { it / x } } - is Float -> { { it / x } } - is Double -> { { it / x } } - else -> throw UnsupportedFormatException("Numeric type ${x::class}") - } - return operator(this) -} - -internal inline fun mutableList(builder: MutableList.() -> Unit): MutableList { - return mutableListOf().apply(builder) -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/util/ByteArrayReader.kt b/src/main/kotlin/io/github/deficuet/unitykt/util/ByteArrayReader.kt new file mode 100644 index 00000000..78b5ac92 --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/util/ByteArrayReader.kt @@ -0,0 +1,16 @@ +package io.github.deficuet.unitykt.util + +import java.io.ByteArrayInputStream + +class ByteArrayReader( + array: ByteArray, offset: Int, length: Int +): ByteArrayInputStream(array, offset, length) { + constructor(array: ByteArray): this(array, 0, array.size) + constructor(array: ByteArray, offset: Int): this(array, offset, array.size) + + fun seek(newPos: Int) { + pos = newPos + } + + fun tell(): Int = pos +} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/util/CompressUtils.kt b/src/main/kotlin/io/github/deficuet/unitykt/util/CompressUtils.kt index 5872a870..5db1f428 100644 --- a/src/main/kotlin/io/github/deficuet/unitykt/util/CompressUtils.kt +++ b/src/main/kotlin/io/github/deficuet/unitykt/util/CompressUtils.kt @@ -7,12 +7,12 @@ import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream import java.util.zip.GZIPInputStream -class CompressUtils private constructor() { +internal class CompressUtils private constructor() { companion object { - val GZIP_MAGIC = byteArrayOf(0x1F, 0x8B) - val BROTLI_MAGIC = byteArrayOf("brotli") + val GZIP_MAGIC = byteArrayOf(0x1F, -0x75) + val BROTLI_MAGIC = byteArrayOf(0x62, 0x72, 0x6F, 0x74, 0x6C, 0x69) - private val lz4Decompressor = LZ4Factory.fastestInstance().fastDecompressor() + private val lz4Decompressor = LZ4Factory.nativeInstance().safeDecompressor() fun lzmaDecompress(data: ByteArray): ByteArray { val preInput = ByteArrayInputStream(data) @@ -24,16 +24,17 @@ class CompressUtils private constructor() { for (i in 0 until 8) { val v = preInput.read() if (v < 0) throw IllegalStateException("Invalid input data") - outSize = outSize or (v.toLong().shl(8 * i)) + outSize = outSize.or(v.toLong().shl(8 * i)) } - val output = ByteArrayOutputStream() - return with(Decoder()) { - SetDecoderProperties(props) - Code( - with(data) { ByteArrayInputStream(sliceArray(5 until size)) }, - output, outSize - ) - output.toByteArray() + return ByteArrayOutputStream().use { output -> + with(Decoder()) { + SetDecoderProperties(props) + Code( + ByteArrayInputStream(data, 5, data.size), + output, outSize + ) + output.toByteArray() + } } } @@ -65,4 +66,4 @@ class CompressUtils private constructor() { } } } -} \ No newline at end of file +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/util/EndianBinaryReader.kt b/src/main/kotlin/io/github/deficuet/unitykt/util/EndianBinaryReader.kt index 940e793f..ddbffcdb 100644 --- a/src/main/kotlin/io/github/deficuet/unitykt/util/EndianBinaryReader.kt +++ b/src/main/kotlin/io/github/deficuet/unitykt/util/EndianBinaryReader.kt @@ -1,166 +1,195 @@ package io.github.deficuet.unitykt.util -import io.github.deficuet.unitykt.file.ObjectInfo -import io.github.deficuet.unitykt.file.SerializedFile +import io.github.deficuet.unitykt.OffsetMode +import io.github.deficuet.unitykt.ReaderConfig +import io.github.deficuet.unitykt.internal.file.ObjectInfo +import io.github.deficuet.unitykt.internal.file.SerializedFile import io.github.deficuet.unitykt.math.* import java.io.Closeable -import java.io.FileInputStream +import java.io.File +import java.io.RandomAccessFile import java.nio.ByteBuffer import java.nio.ByteOrder import java.nio.charset.Charset -import java.nio.file.Files -import kotlin.io.path.Path -enum class FileType { - ASSETS, BUNDLE, WEB, RESOURCE //, GZIP, BROTLI +//region DataInput +sealed interface DataInput { + fun readInt8(): Byte + fun readUInt8(): UByte + fun readInt16(): Short + fun readUInt16(): UShort + fun readInt32(): Int + fun readUInt32(): UInt + fun readInt64(): Long + fun readUInt64(): ULong + fun readFloat(): Float + fun readDouble(): Double + fun readBool(): Boolean + fun readString(size: Int = -1, encoding: Charset = Charsets.UTF_8): String + fun readNullString(maxLength: Int = 32767, charset: Charset = Charsets.UTF_8): String + fun readAlignedString(encode: Charset = Charsets.UTF_8): String + fun readInt8Array(): ByteArray + fun readUInt16Array(size: Int = -1): Array + fun readInt32Array(size: Int = -1): IntArray + fun readUInt32Array(size: Int = -1): Array + fun readNestedUInt32Array(size: Int = -1): Array> + fun readFloatArray(size: Int = -1): FloatArray + fun readBoolArray(size: Int = -1): BooleanArray + fun readAlignedStringArray(size: Int = -1): Array + fun readRectangle(): Rectangle + fun readQuaternion(): Quaternion + fun readMatrix4x4(): Matrix4x4 + fun readVector2(): Vector2 + fun readVector3(): Vector3 + fun readVector4(): Vector4 + fun readColor4(): Color + fun readMatrix4x4Array(size: Int = -1): Array + fun readVector2Array(size: Int = -1): Array + fun readNestedVector2Array(size: Int = -1): Array> + fun readVector3Array(size: Int = -1): Array + fun readVector4Array(size: Int = -1): Array } +//endregion -enum class OffsetMode { - MANUAL, - /** - * Stream will seek automatically to the first non-zero byte. - */ - AUTO -} - -sealed class EndianBinaryReader(private val manualOffset: Long): Closeable { +sealed class EndianBinaryReader: Closeable, DataInput { abstract val bytes: ByteArray - /** - * Relative Position - */ abstract var position: Long - - /** - * Relative Length - */ abstract val length: Long + abstract var endian: ByteOrder /** * Relative offset to its "parent" endian binary reader. */ abstract val baseOffset: Long - abstract var endian: ByteOrder - protected set /** * Length of bytes that are ignored from the beginning. */ abstract val ignoredOffset: Long - protected abstract val offsetMode: OffsetMode var absolutePosition: Long get() = position + ignoredOffset set(value) { position = value - ignoredOffset } - /** - * @see [FileType] - */ - val fileType: FileType by lazy { - if (length < 20) return@lazy FileType.RESOURCE - when (runThenReset { readStringUntilNull(20) }) { - "UnityWeb", "UnityRaw", "UnityArchive", "UnityFS" -> return@lazy FileType.BUNDLE - "UnityWebData1.0" -> return@lazy FileType.WEB - else -> { - var magic = runThenReset { read(2) } - if (CompressUtils.GZIP_MAGIC.contentEquals(magic)) { - return@lazy FileType.WEB - } - magic = with(this) { - position = 0x20 - runThenReset { read(6) } - } - if (CompressUtils.BROTLI_MAGIC.contentEquals(magic)) { - return@lazy FileType.WEB - } - return@lazy if (isSerializedFile) FileType.ASSETS else FileType.RESOURCE - } - } - } - - private val isSerializedFile by lazy { - runThenReset { - plusAssign(4) //m_MetadataSize: UInt - var mFileSize = readUInt().toLong() - val mVersion = readUInt() - var mDataOffset = readUInt().toLong() - plusAssign(4) //m_Endian(1), m_Reserved(3) - if (mVersion > 22u) { - if (length < 48) { - return@runThenReset false - } - plusAssign(4) //m_MetadataSize: UInt - mFileSize = readLong() - mDataOffset = readLong() - } - return@runThenReset mFileSize == length && mDataOffset <= length - } - } /** * Actual position relative to its "parent" endian binary reader. */ val realOffset get() = position + baseOffset - protected fun initOffset(): Long { - return if (offsetMode == OffsetMode.MANUAL) { - manualOffset.also { position = it } - } else { - var first: Byte - do { - val array = read(1) - if (array.isEmpty()) throw IllegalStateException("Stream is Empty") - else first = array[0] - } while (first == 0.toByte()) - position -= 1 - position - } + abstract fun read(): Int + abstract fun read(buf: ByteArray): Int + abstract fun read(size: Int): ByteArray + + fun skip(n: Int): EndianBinaryReader { + position += n + return this } - operator fun plusAssign(inc: Int) { position += inc } + fun skip(n: Long): EndianBinaryReader { + position += n + return this + } - operator fun plusAssign(inc: Long) { position += inc } + open fun alignStream(alignment: Int = 4) { + skip((alignment - position % alignment) % alignment) + } +} - abstract fun read(size: Int): ByteArray +inline fun R.readArrayOf( + size: Int = -1, + crossinline constructor: R.() -> T +): Array { + val num = if (size == -1) readInt32() else size + return Array(num) { constructor() } +} - inline fun withMark(block: EndianBinaryReader.() -> T): T { - val mark = position - val result = this.block() - position = mark - return result - } +inline fun R.readArrayIndexedOf( + size: Int = -1, + crossinline constructor: R.(Int) -> T +): Array { + val num = if (size == -1) readInt32() else size + return Array(num) { constructor(it) } +} - inline fun runThenReset(crossinline block: EndianBinaryReader.() -> T): T { - val result = this.block() - position = 0 - return result - } +inline fun R.withMark(crossinline block: R.() -> T): T { + val mark = position + val result = this.block() + position = mark + return result +} - fun readSByte(): Byte = read(1)[0] //-128~127 - fun readByte(): UByte = readSByte().toUByte() //0~255 - fun readShort(): Short = ByteBuffer.wrap(read(2)).order(endian).short - fun readUShort(): UShort = readShort().toUShort() - fun readInt(): Int = ByteBuffer.wrap(read(4)).order(endian).int - fun readUInt(): UInt = readInt().toUInt() - fun readLong(): Long = ByteBuffer.wrap(read(8)).order(endian).long - fun readULong(): ULong = readLong().toULong() - fun readFloat(): Float = ByteBuffer.wrap(read(4)).order(endian).float - fun readDouble(): Double = ByteBuffer.wrap(read(8)).order(endian).double - fun readBool(): Boolean = readSByte() != 0.toByte() - fun readString(size: Int = -1, encoding: Charset = Charsets.UTF_8): String { - return if (size == -1) readStringUntilNull(charset = encoding) else read(size).decodeToString(encoding) +inline fun R.runThenReset(crossinline block: R.() -> T): T { + val result = this.block() + position = 0 + return result +} + +inline fun R.useEndian(e: ByteOrder, crossinline block: R.() -> T): T { + val cache = endian + endian = e + val result = this.block() + endian = cache + return result +} + +sealed class AbstractEndianBinaryReader(endian: ByteOrder): EndianBinaryReader() { + private val arr2 = ByteArray(2) + private val arr4 = ByteArray(4) + private val arr8 = ByteArray(8) + private val buf2 = ByteBuffer.wrap(arr2).order(endian) + private val buf4 = ByteBuffer.wrap(arr4).order(endian) + private val buf8 = ByteBuffer.wrap(arr8).order(endian) + + override var endian: ByteOrder = endian + set(value) { + buf2.order(value) + buf4.order(value) + buf8.order(value) + field = value + } + + override fun readInt8() = read().toByte() + override fun readUInt8() = read().toUByte() + override fun readInt16(): Short { + read(arr2) + return buf2.position(0).short + } + override fun readUInt16() = readInt16().toUShort() + override fun readInt32(): Int { + read(arr4) + return buf4.position(0).int + } + override fun readUInt32() = readInt32().toUInt() + override fun readInt64(): Long { + read(arr8) + return buf8.position(0).long + } + override fun readUInt64() = readInt64().toULong() + override fun readFloat(): Float { + read(arr4) + return buf4.position(0).float + } + override fun readDouble(): Double { + read(arr8) + return buf8.position(0).double + } + override fun readBool() = read() != 0 + override fun readString(size: Int, encoding: Charset): String { + return if (size == -1) readNullString(charset = encoding) else read(size).decodeToString(encoding) } - fun readStringUntilNull(maxLength: Int = 32767, charset: Charset = Charsets.UTF_8): String { + override fun readNullString(maxLength: Int, charset: Charset): String { val ret = mutableListOf() - var c: Byte? = null - while (c != 0.toByte() && ret.size < maxLength && position <= length) { - if (c != null) ret.add(c) - val nextByte = read(1) - if (nextByte.isEmpty()) throw IllegalStateException("Unterminated String: $ret") - c = nextByte[0] + var b: Int + for (i in 0 until maxLength) { + b = read() + if (b == 0) break + if (b == -1) throw IllegalStateException("Unterminated String") + ret.add(b.toByte()) } return ret.toByteArray().decodeToString(charset) } - fun readAlignedString(encode: Charset = Charsets.UTF_8): String { - val size = readInt() + override fun readAlignedString(encode: Charset): String { + val size = readInt32() if (size in 1..(length - position)) { val result = read(size).decodeToString(encode) alignStream() @@ -168,123 +197,146 @@ sealed class EndianBinaryReader(private val manualOffset: Long): Closeable { } return "" } - open fun alignStream(alignment: Int = 4) { - plusAssign((alignment - position % alignment) % alignment) - } - fun readNextByteArray(): ByteArray = read(readInt()) - inline fun readArray(frequency: Int, lambda: () -> R): Array { - return Array(frequency) { lambda() } - } - inline fun readArrayIndexed(frequency: Int, lambda: (Int) -> R): Array { - return Array(frequency) { lambda(it) } - } - fun readNextBoolArray(): BooleanArray = readArray(readInt(), this::readBool).toBooleanArray() - fun readNextUShortArray(): Array = readArray(readInt(), this::readUShort) - fun readNextIntArray(frequency: Int = -1): IntArray = - readArray(if (frequency == -1) readInt() else frequency, this::readInt).toIntArray() - fun readNextUIntArray(frequency: Int = -1): Array = - readArray(if (frequency == -1) readInt() else frequency, this::readUInt) - fun readNestedUIntArray(frequency: Int = -1): Array> = - readArray(if (frequency == -1) readInt() else frequency, this::readNextUIntArray) - fun readNextFloatArray(frequency: Int = -1): FloatArray = - readArray(if (frequency == -1) readInt() else frequency, this::readFloat).toFloatArray() - fun readNextStringArray(): Array = readArray(readInt(), this::readAlignedString) - fun readRectangle(): Rectangle = Rectangle(readFloat(), readFloat(), readFloat(), readFloat()) - fun readQuaternion(): Quaternion = Quaternion(readFloat(), readFloat(), readFloat(), readFloat()) - fun readMatrix4x4(): Matrix4x4 = Matrix4x4(*readNextFloatArray(16)) - fun readVector2(): Vector2 = Vector2(readFloat(), readFloat()) - fun readVector3(): Vector3 = Vector3(readFloat(), readFloat(), readFloat()) - fun readVector4(): Vector4 = Vector4(readFloat(), readFloat(), readFloat(), readFloat()) - fun readColor4(): Color = Color(readFloat(), readFloat(), readFloat(), readFloat()) - fun readNextMatrixArray(): Array = readArray(readInt(), this::readMatrix4x4) - fun readNextVector2Array(): Array = readArray(readInt(), this::readVector2) - fun readNextVector4Array(): Array = readArray(readInt(), this::readVector4) - inline fun readArrayOf(frequency: Int = -1, constructor: () -> T): Array { - val num = if (frequency == -1) readInt() else frequency - return readArray(num, constructor) - } - inline fun readArrayIndexedOf(frequency: Int = -1, constructor: (Int) -> T): Array { - val num = if (frequency == -1) readInt() else frequency - return readArrayIndexed(num, constructor) - } - - fun resetEndian(e: ByteOrder): EndianBinaryReader { endian = e; return this } + override fun readInt8Array() = read(readInt32()) + override fun readUInt16Array(size: Int) = readArrayOf(size) { readUInt16() } + override fun readInt32Array(size: Int) = readArrayOf(size) { readInt32() }.toIntArray() + override fun readUInt32Array(size: Int) = readArrayOf(size) { readUInt32() } + override fun readNestedUInt32Array(size: Int) = readArrayOf(size) { readUInt32Array() } + override fun readFloatArray(size: Int) = readArrayOf(size) { readFloat() }.toFloatArray() + override fun readBoolArray(size: Int) = readArrayOf(size) { readBool() }.toBooleanArray() + override fun readAlignedStringArray(size: Int) = readArrayOf(size) { readAlignedString() } + override fun readRectangle() = Rectangle(readFloat(), readFloat(), readFloat(), readFloat()) + override fun readQuaternion() = Quaternion(readFloat(), readFloat(), readFloat(), readFloat()) + override fun readMatrix4x4() = Matrix4x4(readArrayOf(4) { readFloatArray(4) }) + override fun readVector2() = Vector2(readFloat(), readFloat()) + override fun readVector3() = Vector3(readFloat(), readFloat(), readFloat()) + override fun readVector4() = Vector4(readFloat(), readFloat(), readFloat(), readFloat()) + override fun readColor4() = Color(readFloat(), readFloat(), readFloat(), readFloat()) + override fun readMatrix4x4Array(size: Int) = readArrayOf(size) { readMatrix4x4() } + override fun readVector2Array(size: Int) = readArrayOf(size) { readVector2() } + override fun readNestedVector2Array(size: Int) = readArrayOf(size) { readVector2Array() } + override fun readVector3Array(size: Int) = readArrayOf(size) { readVector3() } + override fun readVector4Array(size: Int) = readArrayOf(size) { readVector4() } } class EndianByteArrayReader( private val array: ByteArray, - override var endian: ByteOrder = ByteOrder.BIG_ENDIAN, + endian: ByteOrder = ByteOrder.BIG_ENDIAN, override val baseOffset: Long = 0, - override val offsetMode: OffsetMode = OffsetMode.MANUAL, - manualOffset: Long = 0 -): EndianBinaryReader(manualOffset) { + config: ReaderConfig = ReaderConfig() +): AbstractEndianBinaryReader(endian) { constructor( endian: ByteOrder = ByteOrder.BIG_ENDIAN, - manualOffset: Long = 0, - offsetMode: OffsetMode = OffsetMode.MANUAL, - manualIgnoredOffset: Long = 0, + baseOffset: Long = 0, + config: ReaderConfig = ReaderConfig(), arrayBuilder: () -> ByteArray - ): this(arrayBuilder(), endian, manualOffset, offsetMode, manualIgnoredOffset) + ): this(arrayBuilder(), endian, baseOffset, config) + + private val offsetMode: OffsetMode = config.offsetMode + private val manualOffset: Long = config.manualOffset - override var position = 0L - get() = field - ignoredOffset - set(value) { field = value + ignoredOffset } + private val stream: ByteArrayReader = when (offsetMode) { + OffsetMode.MANUAL -> ByteArrayReader(array, manualOffset.toInt()) + else -> ByteArrayReader(array) + } + + override val ignoredOffset: Long = when (offsetMode) { + OffsetMode.MANUAL -> manualOffset + else -> { + var first: Int + do { + first = read() + if (first == -1) throw IllegalStateException("Input byte[] is Empty") + } while (first == 0) + stream.seek(stream.tell() - 1) + stream.tell().toLong() + } + } + + override var position + get() = stream.tell() - ignoredOffset + set(value) { stream.seek((value + ignoredOffset).toInt()) } - override val ignoredOffset = initOffset() override val length get() = array.size.toLong() - ignoredOffset override val bytes: ByteArray - get() { return with(array) { sliceArray(ignoredOffset.toInt() until size) } } + get() = withMark { + position = 0 + read((length - position).toInt()) + } + + override fun read() = stream.read() + + override fun read(buf: ByteArray) = stream.read(buf) override fun read(size: Int): ByteArray { if (size <= 0 || position >= length) { return byteArrayOf() } - val ret = with(absolutePosition.toInt()) { - array.sliceArray(this until this + size) + return ByteArray(size).apply { + read(this) } - plusAssign(size) - return ret } - override fun close() { } + override fun close() { + stream.close() + } } -class EndianFileStreamReader( - filePath: String, - override var endian: ByteOrder = ByteOrder.BIG_ENDIAN, +class EndianBinaryFileReader( + file: File, + endian: ByteOrder = ByteOrder.BIG_ENDIAN, override val baseOffset: Long = 0, - override val offsetMode: OffsetMode = OffsetMode.MANUAL, - manualOffset: Long = 0 -): EndianBinaryReader(manualOffset) { + config: ReaderConfig = ReaderConfig() +): AbstractEndianBinaryReader(endian) { + private val offsetMode: OffsetMode = config.offsetMode + private val manualOffset: Long = config.manualOffset + private val stream = RandomAccessFile(file, "r") + override val ignoredOffset: Long + init { - if (!Files.isRegularFile(Path(filePath))) - throw IllegalStateException("Path $filePath must be a file.") + if (!file.isFile) + throw IllegalArgumentException("Path ${file.path} must be a file.") + ignoredOffset = when (offsetMode) { + OffsetMode.MANUAL -> { + stream.seek(manualOffset) + manualOffset + } + else -> { + var first: Int + do { + first = read() + if (first == -1) throw IllegalStateException("File is Empty") + } while (first == 0) + stream.seek(stream.filePointer - 1) + stream.filePointer + } + } } - private val stream = FileInputStream(filePath) - private val channel get() = stream.channel override var position: Long - get() = channel.position() - ignoredOffset - set(value) { channel.position(value + ignoredOffset) } + get() = stream.filePointer - ignoredOffset + set(value) { stream.seek(value + ignoredOffset) } + + override val length get() = stream.length() - ignoredOffset - override val ignoredOffset = initOffset() - override val length get() = channel.size() - ignoredOffset override val bytes: ByteArray - get() { - return withMark { - position = 0 - read((length - position).toInt()) - } + get() = withMark { + position = 0 + read((length - position).toInt()) } + override fun read() = stream.read() + + override fun read(buf: ByteArray) = stream.read(buf) + override fun read(size: Int): ByteArray { if (size <= 0 || position >= length) { return byteArrayOf() } return ByteArray(size).apply { - stream.read(this) + read(this) } } @@ -293,49 +345,41 @@ class EndianFileStreamReader( } } -/** - * Wrapper for the parent `reader` - */ -class ObjectReader internal constructor( +internal class ObjectReader constructor( private val reader: EndianBinaryReader, val assetFile: SerializedFile, - private val info: ObjectInfo -) : EndianBinaryReader(0) { + internal val info: ObjectInfo +): EndianBinaryReader(), DataInput by reader { internal constructor(assetFile: SerializedFile, info: ObjectInfo): this(assetFile.reader, assetFile, info) - val mPathID = info.mPathID - val byteSize = info.byteSize - val byteStart = info.byteStart - val formatVersion = assetFile.header.version - val unityVersion = assetFile.version - val buildType = assetFile.buildType - val platform = assetFile.targetPlatform - val type = info.type - val serializedType = info.serializedType - - override val ignoredOffset = byteStart - override val length = info.byteSize.toLong() - override var position: Long - get() = reader.position - reader.ignoredOffset - ignoredOffset - set(value) { reader.position = value + ignoredOffset } + get() = reader.position - info.byteStart + set(value) { reader.position = value + info.byteStart } + + override fun read() = reader.read() + override fun read(buf: ByteArray) = reader.read(buf) + override fun read(size: Int) = reader.read(size) + + override fun alignStream(alignment: Int) { reader.alignStream(alignment) } + + override var endian: ByteOrder + get() = reader.endian + set(value) { reader.endian = value } + + val formatVersion get() = assetFile.hVersion + val unityVersion get() = assetFile.version + + override val ignoredOffset get() = info.byteStart + override val length = info.byteSize.toLong() - override fun alignStream(alignment: Int) { - plusAssign((alignment - absolutePosition % alignment) % alignment) - } override val bytes: ByteArray - get() { - return withMark { - position = 0 - read(info.byteSize.toInt()) - } + get() = withMark { + position = 0 + read(info.byteSize.toInt()) } - override val baseOffset = reader.baseOffset - override var endian: ByteOrder = reader.endian - override val offsetMode = OffsetMode.MANUAL - override fun read(size: Int) = reader.read(size) + override val baseOffset = reader.baseOffset override fun close() { } -} \ No newline at end of file +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/util/EndianBinaryWriter.kt b/src/main/kotlin/io/github/deficuet/unitykt/util/EndianBinaryWriter.kt new file mode 100644 index 00000000..86c4934c --- /dev/null +++ b/src/main/kotlin/io/github/deficuet/unitykt/util/EndianBinaryWriter.kt @@ -0,0 +1,28 @@ +package io.github.deficuet.unitykt.util + +import java.nio.ByteBuffer +import java.nio.ByteOrder + +class EndianByteArrayWriter( + val data: ByteArray, + endian: ByteOrder = ByteOrder.BIG_ENDIAN +) { + constructor(size: Int, endian: ByteOrder = ByteOrder.BIG_ENDIAN): this(ByteArray(size), endian) + + private val buf = ByteBuffer.wrap(data).order(endian) + + val length get() = data.size + var position + get() = buf.position() + set(value) { buf.position(value) } + + var endian = endian + set(value) { + buf.order(value) + field = value + } + + fun write(b: ByteArray) { buf.put(b) } + fun writeInt32(i: Int) { buf.putInt(i) } + fun writeUInt32(i: UInt) { buf.putInt(i.toInt()) } +} diff --git a/src/main/kotlin/io/github/deficuet/unitykt/util/Reference.kt b/src/main/kotlin/io/github/deficuet/unitykt/util/Reference.kt deleted file mode 100644 index 9f7ff6b7..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/util/Reference.kt +++ /dev/null @@ -1,3 +0,0 @@ -package io.github.deficuet.unitykt.util - -class Reference { lateinit var value: T } diff --git a/src/main/kotlin/io/github/deficuet/unitykt/util/ResourceReader.kt b/src/main/kotlin/io/github/deficuet/unitykt/util/ResourceReader.kt index 760241ca..b21d6802 100644 --- a/src/main/kotlin/io/github/deficuet/unitykt/util/ResourceReader.kt +++ b/src/main/kotlin/io/github/deficuet/unitykt/util/ResourceReader.kt @@ -1,14 +1,12 @@ package io.github.deficuet.unitykt.util -import io.github.deficuet.unitykt.ImportContext -import io.github.deficuet.unitykt.UnityAssetManager -import io.github.deficuet.unitykt.file.ResourceFile -import io.github.deficuet.unitykt.file.SerializedFile +import io.github.deficuet.unitykt.internal.UnityAssetManagerImpl +import io.github.deficuet.unitykt.internal.file.SerializedFile import java.io.Closeable import java.io.File import java.io.FileNotFoundException -class ResourceReader internal constructor( +internal class ResourceReader( private val path: String, private val assetFile: SerializedFile?, private val offset: Long, @@ -19,24 +17,27 @@ class ResourceReader internal constructor( get() { if (field != null) return field else { - val file = File(path) + var file = File(path) val manager = assetFile!!.root.manager if (file.name in manager.resourceFiles) { return manager.resourceFiles.getValue(file.name).reader } - val dir = "${assetFile.root.directory}/${file.name}" - return if (!File(dir).exists()) { - throw FileNotFoundException("Can't find the resource file $dir") + file = File("${assetFile.root.parent}/${file.name}") + return if (!file.exists()) { + throw FileNotFoundException("Can't find the resource file ${file.name}") } else { shouldClose = true - field = (ImportContext(dir, manager).files.getValue(file.name) as ResourceFile).reader + field = EndianBinaryFileReader(file) field } } } - internal constructor(reader: EndianBinaryReader, offset: Long, size: Long): - this("", null, offset, size) { + constructor( + reader: EndianBinaryReader, + offset: Long, + size: Long + ): this("", null, offset, size) { this.reader = reader } @@ -51,7 +52,7 @@ class ResourceReader internal constructor( if (shouldClose) reader?.close() } - fun registerToManager(m: UnityAssetManager): ResourceReader { + fun registerToManager(m: UnityAssetManagerImpl): ResourceReader { m.otherReaderList.add(this) return this } diff --git a/src/main/kotlin/io/github/deficuet/unitykt/util/UnsupportedFormatException.kt b/src/main/kotlin/io/github/deficuet/unitykt/util/UnsupportedFormatException.kt deleted file mode 100644 index fddafce2..00000000 --- a/src/main/kotlin/io/github/deficuet/unitykt/util/UnsupportedFormatException.kt +++ /dev/null @@ -1,3 +0,0 @@ -package io.github.deficuet.unitykt.util - -class UnsupportedFormatException(msg: String): Exception(msg) \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/util/utils.kt b/src/main/kotlin/io/github/deficuet/unitykt/util/utils.kt index 1991f39e..1233facc 100644 --- a/src/main/kotlin/io/github/deficuet/unitykt/util/utils.kt +++ b/src/main/kotlin/io/github/deficuet/unitykt/util/utils.kt @@ -1,33 +1,28 @@ package io.github.deficuet.unitykt.util -import org.json.JSONArray -import org.json.JSONObject import java.nio.ByteBuffer import java.nio.ByteOrder import java.nio.charset.Charset -import java.nio.file.Files -import kotlin.io.path.Path -import kotlin.io.path.isRegularFile -import kotlin.io.path.name -internal fun Byte.toIntBits() = toUByte().toInt() - -internal fun Short.toIntBits() = toUShort().toInt() - -internal operator fun ByteArray.get(i: UInt) = get(i.toInt()).toIntBits() +internal operator fun ByteArray.get(i: UInt) = get(i.toInt()).toUByte().toInt() internal operator fun ByteArray.get(i: Int, l: Int) = sliceArray(i until i + l) +/** + * `0u` will return `true` + */ +internal fun isPowerOf2(x: UInt) = x.and(x - 1u) == 0u + internal fun ByteArray.decodeToString(charset: Charset = Charsets.UTF_8) = java.lang.String(this, charset).toString() -internal fun ByteArray.toHalf(): Float { - if (size != 2) throw IllegalStateException("There should be 2 bytes only") - val intValue = this[0].toIntBits().shl(8).or(this[1].toIntBits()) +internal fun parseHalf(data: ByteArray, pos: UInt): Float { + val intValue = data[pos].shl(8).or(data[pos+1u]) var mantissa = intValue.and(0x03FF) var exp = intValue.and(0x7C00) - if (exp == 0x7C00) exp = 0x3FC00 - else if (exp != 0) { + if (exp == 0x7C00) { + exp = 0x3FC00 + } else if (exp != 0) { exp += 0x1C000 if (mantissa == 0 && exp > 0x1C400) { return Float.fromBits( @@ -47,6 +42,20 @@ internal fun ByteArray.toHalf(): Float { ) } +internal fun parseInt(data: ByteArray, pos: UInt): Int { + return data[pos].shl(24).or(data[pos+1u].shl(16)).or(data[pos+2u].shl(8)).or(data[pos+3u]) +} + +internal fun parseFloat(data: ByteArray, pos: UInt) = Float.fromBits(parseInt(data, pos)) + +internal fun parseUInt16(data: ByteArray, pos: UInt): Int { + return data[pos].shl(8).or(data[pos+1u]) +} + +internal fun parseDownScaledInt8(data: ByteArray, pos: UInt): Byte { + return ((parseUInt16(data, pos) * 255) + 32895).shr(16).toByte() +} + internal fun ByteArray.toChar(): Char { if (size != 2) throw IllegalStateException("There should be 2 bytes only") return Char( @@ -54,10 +63,6 @@ internal fun ByteArray.toChar(): Char { ) } -internal fun byteArrayOf(vararg bytes: Int) = ByteArray(bytes.size) { bytes[it].toByte() } - -internal fun byteArrayOf(str: String) = ByteArray(str.length) { str[it].code.toByte() } - internal operator fun IntArray.compareTo(other: IntArray): Int { for (i in 0 until minOf(size, other.size)) { val result = get(i).compareTo(other[i]) @@ -67,59 +72,5 @@ internal operator fun IntArray.compareTo(other: IntArray): Int { } internal fun Int.clampByte(): Byte { - val i = this - return with(Byte.Companion) { - if (i > MAX_VALUE) MAX_VALUE else if (i < MIN_VALUE) MIN_VALUE else i.toByte() - } -} - -internal fun String.isFile(): Boolean = Files.isRegularFile(Path(this)) - -internal fun String.isDirectory(): Boolean = Files.isDirectory(Path(this)) - -internal operator fun String.invoke(v: Any) = format(v) - -@PublishedApi internal fun String.listFiles(): List { - return Files.newDirectoryStream(Path(this)).use { stream -> - stream.filter { it.isRegularFile() }.map { it.name } - } -} - -@PublishedApi internal fun Map.tryGet(key: String): V? { - return this[key] ?: this[key.uppercase()] -} - -@PublishedApi internal fun List.containsIgnoreCase(element: String): String? { - return find { it.contentEquals(element) } + return (if (this > 255) 255 else if (this < 0) 0 else this).toByte() } - -internal fun List.sum(): ByteArray { - var bytes = kotlin.byteArrayOf() - forEach { bytes += it } - return bytes -} - -internal fun T.equalsAnyOf(vararg other: T): Boolean { - for (v in other) { - if (this == v) return true - } - return false -} - -internal fun Map<*, *>.toJSONObject(): JSONObject { - return JSONObject().apply { - for (entry in this@toJSONObject) { - val key = java.lang.String.valueOf(entry.key) - val value = entry.value!! - if (value::class.java.isArray) { - put(key, JSONArray(value)) - continue - } - when (value) { - is Collection<*> -> put(key, JSONArray(value)) - is Map<*, *> -> put(key, value.toJSONObject()) - else -> put(key, value) - } - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/io/github/deficuet/unitykt/utils.kt b/src/main/kotlin/io/github/deficuet/unitykt/utils.kt index 23863284..63f5d1b9 100644 --- a/src/main/kotlin/io/github/deficuet/unitykt/utils.kt +++ b/src/main/kotlin/io/github/deficuet/unitykt/utils.kt @@ -1,72 +1,52 @@ package io.github.deficuet.unitykt -import io.github.deficuet.unitykt.data.Object +import io.github.deficuet.unitykt.classes.UnityObject +import io.github.deficuet.unitykt.enums.ClassIDType -operator fun Collection>.get(key: K): List { - return filter { - when (val f = it.first) { - is CharSequence -> f.contentEquals(key as CharSequence) - is Array<*> -> f.contentEquals(key as Array<*>) - is ByteArray -> f.contentEquals(key as ByteArray) - is CharArray -> f.contentEquals(key as CharArray) - is ShortArray -> f.contentEquals(key as ShortArray) - is IntArray -> f.contentEquals(key as IntArray) - is LongArray -> f.contentEquals(key as LongArray) - is DoubleArray -> f.contentEquals(key as DoubleArray) - is FloatArray -> f.contentEquals(key as FloatArray) - is BooleanArray -> f.contentEquals(key as BooleanArray) - else -> f == key - } - }.map { it.second } -} +/** + * Use [filterIsInstance] for finding all objects of a specific type. + */ +inline fun Iterable.firstObjectOf() = filterIsInstance()[0] + +inline fun Array.firstObjectOf() = filterIsInstance()[0] -operator fun Array>.get(key: K): List { - return filter { - when (val f = it.first) { - is CharSequence -> f.contentEquals(key as CharSequence) - is Array<*> -> f.contentEquals(key as Array<*>) - is ByteArray -> f.contentEquals(key as ByteArray) - is CharArray -> f.contentEquals(key as CharArray) - is ShortArray -> f.contentEquals(key as ShortArray) - is IntArray -> f.contentEquals(key as IntArray) - is LongArray -> f.contentEquals(key as LongArray) - is DoubleArray -> f.contentEquals(key as DoubleArray) - is FloatArray -> f.contentEquals(key as FloatArray) - is BooleanArray -> f.contentEquals(key as BooleanArray) - else -> f == key - } - }.map { it.second } +inline fun Iterable.firstOfOrNull(): O? { + return with(filterIsInstance()) { if (isEmpty()) null else this[0] } } -fun Collection>.first(key: K) = get(key)[0] +inline fun Array.firstOfOrNull(): O? { + return with(filterIsInstance()) { if (isEmpty()) null else this[0] } +} -fun Collection>.firstOrNull(key: K) = with(get(key)) { if (isEmpty()) null else this[0] } +fun Iterable.allObjectsOf(vararg types: ClassIDType): List { + return filter { it.type in types } +} -inline fun Collection.firstObjectOf() = filterIsInstance()[0] +fun Array.allObjectsOf(vararg types: ClassIDType): List { + return filter { it.type in types } +} -inline fun Collection.firstOfOrNull(): O? { - return with(filterIsInstance()) { if (isEmpty()) null else this[0] } +inline fun Iterable.safeFindWithPathID(pathId: Long): T? { + return find { it.mPathID == pathId }.safeCast() } -fun Collection.allObjectsOf(vararg type: String): List { - return filter { it.type.name in type } +inline fun Array.safeFindWithPathID(pathId: Long): T? { + return find { it.mPathID == pathId }.safeCast() } -inline fun Collection.safeFindWithPathID(pathId: Long): T? { - return find { it.mPathID == pathId }?.let { - if (it is T) it else null - } +inline fun Iterable.findWithPathID(pathId: Long): T { + return first { it.mPathID == pathId }.cast() } -inline fun Collection.findWithPathID(pathId: Long): T { - return first { it.mPathID == pathId } as T +inline fun Array.findWithPathID(pathId: Long): T { + return first { it.mPathID == pathId }.cast() } -inline fun Map.safeGetAs(pathId: Long): T? { +inline fun Map.safeGetAs(pathId: Long): T? { return this[pathId].safeCast() } -inline fun Map.getAs(pathId: Long): T { +inline fun Map.getAs(pathId: Long): T { return this[pathId].cast() }