@@ -49,6 +49,69 @@ module InteropTypes =
4949 val mutable Data : System.IntPtr
5050 val mutable Size : int32
5151
52+ let MaxModSnapProfileXFormLen = 8
53+
54+ [<Struct; StructLayout( LayoutKind.Sequential, CharSet= CharSet.Unicode) >]
55+ type ModSnapProfileXFormString = {
56+ [<MarshalAs( UnmanagedType.ByValTStr, SizeConst = 256 ) >]
57+ Text : string
58+ }
59+
60+ let makeXFormString ( s : string ) =
61+ let maxChars = 255
62+ let trimmed =
63+ if System.String.IsNullOrEmpty s then " "
64+ elif s.Length > maxChars then s.Substring( 0 , maxChars)
65+ else s
66+ { Text = trimmed }
67+
68+ /// The profile that was used to snapshot the mod. Manage code will typically reverse Pos and UV transforms during mod load,
69+ /// but unmanaged code can handle other details such as generating tangent space or packing vectors in correct format.
70+ /// Not all mods will have this, so unmanaged code should check the "Valid" field to see if it is populated.
71+ [<Struct; StructLayout( LayoutKind.Sequential, CharSet= CharSet.Unicode) >]
72+ type ModSnapProfile = {
73+ /// Whether the fields have been set on this profile, unmanaged code uses this to determine
74+ /// whether to use it or not (essentially makes it a implicit "option" type)
75+ [<MarshalAs( UnmanagedType.U1) >]
76+ Valid: bool
77+
78+ /// Name of this profile
79+ [<MarshalAs( UnmanagedType.ByValTStr, SizeConst= 256 ) >]
80+ Name: string
81+
82+ /// Number of position transforms
83+ PosXLength: int
84+ [<MarshalAs( UnmanagedType.ByValArray, SizeConst= 8 ) >]
85+ /// Position transforms
86+ PosX: ModSnapProfileXFormString []
87+
88+ /// Number of UV transforms
89+ UVXLength: int
90+ [<MarshalAs( UnmanagedType.ByValArray, SizeConst= 8 ) >]
91+ /// UV transforms
92+ UVX: ModSnapProfileXFormString []
93+
94+ /// Whether to flip tangents
95+ [<MarshalAs( UnmanagedType.U1) >]
96+ FlipTangent: bool
97+
98+ /// How vectors should be encoded in d3d data
99+ [<MarshalAs( UnmanagedType.ByValTStr, SizeConst= 256 ) >]
100+ VecEncoding: string
101+ }
102+
103+ // Example empty value for InteropProfile
104+ let EmptyModSnapProfile = {
105+ Valid = false
106+ Name = " "
107+ PosXLength = 0
108+ PosX = Array.create MaxModSnapProfileXFormLen ( makeXFormString " " )
109+ UVXLength = 0
110+ UVX = Array.create MaxModSnapProfileXFormLen ( makeXFormString " " )
111+ FlipTangent = false
112+ VecEncoding = " "
113+ }
114+
52115 /// Various mod metadata. Derived from Mesh, DBReference, and DBMod types.
53116 [<StructLayout( LayoutKind.Sequential, CharSet= CharSet.Unicode) >]
54117 type ModData = {
@@ -79,6 +142,7 @@ module InteropTypes =
79142 ParentModName: string
80143 [<MarshalAs( UnmanagedType.ByValTStr, SizeConst= 8192 ) >]
81144 PixelShaderPath: string
145+ SnapProfile: ModSnapProfile
82146 }
83147
84148 /// Default value. Also used as an error return value, since we don't throw exceptions accross interop.
@@ -101,6 +165,7 @@ module InteropTypes =
101165 ParentModName = " "
102166 PixelShaderPath = " "
103167 UpdateTangentSpace = - 1
168+ SnapProfile = EmptyModSnapProfile
104169 }
105170
106171 [<StructLayout( LayoutKind.Sequential, Pack= 4 ) >]
0 commit comments