@@ -5,57 +5,75 @@ import * as os from 'os';
5
5
import * as path from 'path' ;
6
6
import config from './config' ;
7
7
8
- export interface IExecIfcStepsContext extends IDownloadAssetsStepsContext {
8
+ export interface IExecBlenderStepsContext extends IDownloadAssetsStepsContext {
9
9
convertedAssetsDir : string ;
10
10
}
11
11
12
12
export function describe ( ) : IStepDescription {
13
13
return {
14
- code : 'exec-ifcopenshell ' ,
15
- name : 'Execute IfcOpenShell to convert IFC files into Collada files' ,
14
+ code : 'exec-blender ' ,
15
+ name : 'Execute Blender to convert STEP files into FBX files' ,
16
16
priority : 11 , // after assets download
17
17
} ;
18
18
}
19
19
20
- export function shouldProcess ( conv : IConversion , context : IExecIfcStepsContext ) {
20
+ /**
21
+ * The predicate to process only STEP/STP files
22
+ * @param path
23
+ */
24
+ function isStep ( path : string ) {
25
+ const lowerCasePath = path . toLowerCase ( ) ;
26
+ return lowerCasePath . endsWith ( '.step' ) || lowerCasePath . endsWith ( '.stp' ) ;
27
+ }
28
+
29
+ export function shouldProcess ( conv : IConversion , context : IExecBlenderStepsContext ) {
21
30
return context . assetsPaths &&
22
31
context . assetsPaths . length &&
23
- context . assetsPaths . some ( assetPath => assetPath . toLowerCase ( ) . endsWith ( '.ifc' ) ) ;
32
+ context . assetsPaths . some ( isStep ) ;
24
33
}
25
34
26
- export async function process ( conv : IConversion , context : IExecIfcStepsContext , progress : ProgressFn ) : Promise < void > {
35
+ export async function process ( conv : IConversion ,
36
+ context : IExecBlenderStepsContext ,
37
+ progress : ProgressFn ) : Promise < void > {
27
38
//=> Create a temporary folder for the assets
28
- const tmpDir = path . resolve ( `${ os . tmpdir ( ) } /chuck/exec-ifcopenshell -${ Date . now ( ) } ` ) ;
39
+ const tmpDir = path . resolve ( `${ os . tmpdir ( ) } /chuck/exec-blender -${ Date . now ( ) } ` ) ;
29
40
await fs . mkdirp ( tmpDir ) ;
30
41
31
42
context . convertedAssetsDir = tmpDir ;
32
43
const convertOptions = conv . conversionOptions ;
33
44
34
45
//=> Execute each conversion sequentially
35
- // @todo If IfcConvert is mono-threaded, we could make it concurrent
36
46
for ( const assetPath of context . assetsPaths ) {
37
- if ( assetPath . toLowerCase ( ) . endsWith ( '.ifc' ) ) {
38
- await progress ( 'convert-start' , `Converting "${ assetPath } " from IFC to Collada ` ) ;
47
+ if ( isStep ( assetPath ) ) {
48
+ await progress ( 'convert-start' , `Converting "${ assetPath } " from STEP to FBX ` ) ;
39
49
await convertAndStoreAssets ( convertOptions , context , assetPath ) ;
40
50
}
41
51
}
42
52
}
43
53
44
- export async function cleanup ( context : IExecIfcStepsContext ) : Promise < void > {
54
+ export async function cleanup ( context : IExecBlenderStepsContext ) : Promise < void > {
45
55
await fs . remove ( context . convertedAssetsDir ) ;
46
56
}
47
57
48
58
async function convertAndStoreAssets (
49
59
convertOptions : string [ ] ,
50
- context : IExecIfcStepsContext ,
51
- ifcFilePath : string
60
+ context : IExecBlenderStepsContext ,
61
+ stepFilePath : string
52
62
) : Promise < string > {
53
- const colladaFileName = path . parse ( ifcFilePath ) . name + '.dae ' ;
54
- const colladaFilePath = path . resolve ( `${ context . convertedAssetsDir } /${ colladaFileName } ` ) ;
63
+ const fbxFileName = path . parse ( stepFilePath ) . name + '.fbx ' ;
64
+ const fbxFilePath = path . resolve ( `${ context . convertedAssetsDir } /${ fbxFileName } ` ) ;
55
65
56
- const spawnArgs = [ ifcFilePath , colladaFilePath , '-y' ] . concat ( convertOptions ) ;
66
+ // Expected command:
67
+ // blender -b --python .\step_to_fbx.py --python-exit-code 1 -- "path/file.stp" "path/file.fbx"
68
+ const spawnArgs = [
69
+ '-b' ,
70
+ '--python' , path . join ( __dirname , '..' , 'src' , 'convert.py' ) . toString ( ) ,
71
+ '--python-exit-code' , '1' ,
72
+ '--' ,
73
+ stepFilePath ,
74
+ fbxFilePath ] . concat ( convertOptions ) ;
57
75
58
- const converterProcess = spawn ( config . ifcConvertPath , spawnArgs ) ;
76
+ const converterProcess = spawn ( config . blenderPath , spawnArgs ) ;
59
77
60
78
//=> Watch process' stdout to log in real time, and keep the complete output in case of crash
61
79
let stdoutAggregator = '' ;
@@ -70,22 +88,22 @@ async function convertAndStoreAssets(
70
88
//=> Watch for the process to terminate, check return code
71
89
converterProcess . once ( 'close' , ( code ) => {
72
90
if ( code !== 0 ) {
73
- const message = `Conversion of IFC file ${ path . basename ( ifcFilePath ) } to Collada has failed!` ;
74
- return reject ( new IfcConvertCrashError ( message , stdoutAggregator ) ) ;
91
+ const message = `Conversion of STEP file ${ path . basename ( stepFilePath ) } to FBX has failed!` ;
92
+ return reject ( new BlenderCrashError ( message , stdoutAggregator ) ) ;
75
93
}
76
94
77
- const index = context . assetsPaths . findIndex ( path => path === ifcFilePath ) ;
78
- context . assetsPaths [ index ] = colladaFilePath ;
95
+ const index = context . assetsPaths . findIndex ( path => path === stepFilePath ) ;
96
+ context . assetsPaths [ index ] = fbxFilePath ;
79
97
80
- resolve ( colladaFilePath ) ;
98
+ resolve ( fbxFilePath ) ;
81
99
} ) ;
82
100
} ) ;
83
101
}
84
102
85
- export class IfcConvertCrashError extends Error {
86
- constructor ( message : string , public readonly ifcConvertLog : string ) {
103
+ export class BlenderCrashError extends Error {
104
+ constructor ( message : string , public readonly BlenderLog : string ) {
87
105
super ( message ) ;
88
106
89
- Object . setPrototypeOf ( this , IfcConvertCrashError . prototype ) ;
107
+ Object . setPrototypeOf ( this , BlenderCrashError . prototype ) ;
90
108
}
91
109
}
0 commit comments