2
2
using OtterGui ;
3
3
using Penumbra . GameData ;
4
4
using Penumbra . GameData . Files ;
5
+ using Penumbra . Import . Models ;
5
6
using Penumbra . Import . Models . Export ;
6
7
using Penumbra . Meta . Manipulations ;
7
8
using Penumbra . String . Classes ;
@@ -27,8 +28,8 @@ private class MdlTab : IWritable
27
28
28
29
private bool _dirty ;
29
30
public bool PendingIo { get ; private set ; }
30
- public List < Exception > IoExceptions { get ; private set ; } = [ ] ;
31
- public List < string > IoWarnings { get ; private set ; } = [ ] ;
31
+ public List < Exception > IoExceptions { get ; } = [ ] ;
32
+ public List < string > IoWarnings { get ; } = [ ] ;
32
33
33
34
public MdlTab ( ModEditWindow edit , byte [ ] bytes , string path )
34
35
{
@@ -79,7 +80,7 @@ private void FindGamePaths(string path)
79
80
return ;
80
81
}
81
82
82
- PendingIo = true ;
83
+ BeginIo ( ) ;
83
84
var task = Task . Run ( ( ) =>
84
85
{
85
86
// TODO: Is it worth trying to order results based on option priorities for cases where more than one match is found?
@@ -91,12 +92,7 @@ private void FindGamePaths(string path)
91
92
. ToList ( ) ;
92
93
} ) ;
93
94
94
- task . ContinueWith ( t =>
95
- {
96
- RecordIoExceptions ( t . Exception ) ;
97
- GamePaths = t . Result ;
98
- PendingIo = false ;
99
- } ) ;
95
+ task . ContinueWith ( t => { GamePaths = FinalizeIo ( t ) ; } ) ;
100
96
}
101
97
102
98
private EstManipulation [ ] GetCurrentEstManipulations ( )
@@ -132,33 +128,22 @@ public void Export(string outputPath, Utf8GamePath mdlPath)
132
128
return ;
133
129
}
134
130
135
- PendingIo = true ;
131
+ BeginIo ( ) ;
136
132
_edit . _models . ExportToGltf ( ExportConfig , Mdl , sklbPaths , ReadFile , outputPath )
137
- . ContinueWith ( task =>
138
- {
139
- RecordIoExceptions ( task . Exception ) ;
140
- if ( task is { IsCompletedSuccessfully : true , Result : not null } )
141
- IoWarnings = task . Result . GetWarnings ( ) . ToList ( ) ;
142
- PendingIo = false ;
143
- } ) ;
133
+ . ContinueWith ( FinalizeIo ) ;
144
134
}
145
135
146
136
/// <summary> Import a model from an interchange format. </summary>
147
137
/// <param name="inputPath"> Disk path to load model data from. </param>
148
138
public void Import ( string inputPath )
149
139
{
150
- PendingIo = true ;
140
+ BeginIo ( ) ;
151
141
_edit . _models . ImportGltf ( inputPath )
152
142
. ContinueWith ( task =>
153
143
{
154
- RecordIoExceptions ( task . Exception ) ;
155
- if ( task is { IsCompletedSuccessfully : true , Result : ( not null , _) } )
156
- {
157
- IoWarnings = task . Result . Item2 . GetWarnings ( ) . ToList ( ) ;
158
- FinalizeImport ( task . Result . Item1 ) ;
159
- }
160
-
161
- PendingIo = false ;
144
+ var mdlFile = FinalizeIo ( task , result => result . Item1 , result => result . Item2 ) ;
145
+ if ( mdlFile != null )
146
+ FinalizeImport ( mdlFile ) ;
162
147
} ) ;
163
148
}
164
149
@@ -186,7 +171,7 @@ private void FinalizeImport(MdlFile newMdl)
186
171
/// <summary> Merge material configuration from the source onto the target. </summary>
187
172
/// <param name="target"> Model that will be updated. </param>
188
173
/// <param name="source"> Model to copy material configuration from. </param>
189
- public void MergeMaterials ( MdlFile target , MdlFile source )
174
+ private static void MergeMaterials ( MdlFile target , MdlFile source )
190
175
{
191
176
target . Materials = source . Materials ;
192
177
@@ -201,7 +186,7 @@ public void MergeMaterials(MdlFile target, MdlFile source)
201
186
/// <summary> Merge attribute configuration from the source onto the target. </summary>
202
187
/// <param name="target"> Model that will be updated. ></param>
203
188
/// <param name="source"> Model to copy attribute configuration from. </param>
204
- public static void MergeAttributes ( MdlFile target , MdlFile source )
189
+ private static void MergeAttributes ( MdlFile target , MdlFile source )
205
190
{
206
191
target . Attributes = source . Attributes ;
207
192
@@ -255,14 +240,47 @@ private static void MergeElementIds(MdlFile target, MdlFile source)
255
240
target . ElementIds = [ .. elementIds ] ;
256
241
}
257
242
243
+ private void BeginIo ( )
244
+ {
245
+ PendingIo = true ;
246
+ IoWarnings . Clear ( ) ;
247
+ IoExceptions . Clear ( ) ;
248
+ }
249
+
250
+ private void FinalizeIo ( Task < IoNotifier > task )
251
+ => FinalizeIo < IoNotifier , object ? > ( task , _ => null , notifier => notifier ) ;
252
+
253
+ private TResult ? FinalizeIo < TResult > ( Task < TResult > task )
254
+ => FinalizeIo ( task , result => result , null ) ;
255
+
256
+ private TResult ? FinalizeIo < TTask , TResult > ( Task < TTask > task , Func < TTask , TResult > getResult , Func < TTask , IoNotifier > ? getNotifier )
257
+ {
258
+ TResult ? result = default ;
259
+ RecordIoExceptions ( task . Exception ) ;
260
+ if ( task is { IsCompletedSuccessfully : true , Result : not null } )
261
+ {
262
+ result = getResult ( task . Result ) ;
263
+ if ( getNotifier != null )
264
+ IoWarnings . AddRange ( getNotifier ( task . Result ) . GetWarnings ( ) ) ;
265
+ }
266
+
267
+ PendingIo = false ;
268
+
269
+ return result ;
270
+ }
271
+
258
272
private void RecordIoExceptions ( Exception ? exception )
259
273
{
260
- IoExceptions = exception switch
274
+ switch ( exception )
261
275
{
262
- null => [ ] ,
263
- AggregateException ae => [ .. ae . Flatten ( ) . InnerExceptions ] ,
264
- _ => [ exception ] ,
265
- } ;
276
+ case null : break ;
277
+ case AggregateException ae :
278
+ IoExceptions . AddRange ( ae . Flatten ( ) . InnerExceptions ) ;
279
+ break ;
280
+ default :
281
+ IoExceptions . Add ( exception ) ;
282
+ break ;
283
+ }
266
284
}
267
285
268
286
/// <summary> Read a file from the active collection or game. </summary>
0 commit comments