5 # \date 2010-05-24 13:42GMT
6 # \author Jan Boon (Kaetemi)
7 # Python port of game data build pipeline.
10 # NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
11 # Copyright (C) 2009-2014 by authors
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU Affero General Public License as
15 # published by the Free Software Foundation, either version 3 of the
16 # License, or (at your option) any later version.
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU Affero General Public License for more details.
23 # You should have received a copy of the GNU Affero General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
27 import time
, sys
, os
, shutil
, subprocess
, distutils
.dir_util
28 sys
.path
.append("../../configuration")
30 if os
.path
.isfile("log.log"):
32 log
= open("log.log", "w")
34 from buildsite
import *
37 from directories
import *
40 printLog(log
, "-------")
41 printLog(log
, "--- Build shape")
42 printLog(log
, "-------")
43 printLog(log
, time
.strftime("%Y-%m-%d %H:%MGMT", time
.gmtime(time
.time())))
47 ExecTimeout
= findTool(log
, ToolDirectories
, ExecTimeoutTool
, ToolSuffix
)
48 BuildShadowSkin
= findTool(log
, ToolDirectories
, BuildShadowSkinTool
, ToolSuffix
)
49 BuildClodtex
= findTool(log
, ToolDirectories
, BuildClodtexTool
, ToolSuffix
)
50 LightmapOptimizer
= findTool(log
, ToolDirectories
, LightmapOptimizerTool
, ToolSuffix
)
51 TgaToDds
= findTool(log
, ToolDirectories
, TgaToDdsTool
, ToolSuffix
)
52 BuildCoarseMesh
= findTool(log
, ToolDirectories
, BuildCoarseMeshTool
, ToolSuffix
)
54 shapeDirectory
= ExportBuildDirectory
+ "/" + ShapeNotOptimizedExportDirectory
55 if BuildShadowSkinEnabled
:
56 mkPath(log
, shapeDirectory
)
57 shadowSkinBuildDirectory
= ExportBuildDirectory
+ "/" + ShapeShadowSkinBuildDirectory
58 printLog(log
, ">>> BuildShadowSkin <<<")
59 shadowSkinShapes
= findFilesNoSubdir(log
, shapeDirectory
, ".shape")
60 for shadowSkinShape
in shadowSkinShapes
:
61 srcShape
= shapeDirectory
+ "/" + shadowSkinShape
62 dstShape
= shadowSkinBuildDirectory
+ "/" + shadowSkinShape
63 if needUpdateLogRemoveDest(log
, srcShape
, dstShape
):
64 subprocess
.call([ BuildShadowSkin
, srcShape
, dstShape
, str(BuildShadowSkinRatio
), str(BuildShadowSkinMaxface
) ])
65 shapeDirectory
= shadowSkinBuildDirectory
67 mkPath(log
, shapeDirectory
)
68 mkPath(log
, ExportBuildDirectory
+ "/" + ShapeClodtexBuildDirectory
)
69 if ClodConfigFile
!= "":
70 mkPath(log
, ExportBuildDirectory
+ "/" + ClodExportDirectory
)
71 printLog(log
, ">>> Build CLodTex <<<")
72 subprocess
.call([ BuildClodtex
, "-d", DatabaseDirectory
+ "/" + ClodConfigFile
, ExportBuildDirectory
+ "/" + ClodExportDirectory
, shapeDirectory
, ExportBuildDirectory
+ "/" + ShapeClodtexBuildDirectory
])
74 printLog(log
, ">>> Copy Shape <<<")
75 copyFilesExtNoTreeIfNeeded(log
, shapeDirectory
, ExportBuildDirectory
+ "/" + ShapeClodtexBuildDirectory
, ".shape")
77 printLog(log
, ">>> Copy non-ShadowSkin non-CLodTex Shape <<<")
78 shapeDirectory
= ExportBuildDirectory
+ "/" + ShapeNotOptimizedExportDirectory
79 mkPath(log
, shapeDirectory
)
80 mkPath(log
, ExportBuildDirectory
+ "/" + ShapeClodtexBuildDirectory
)
81 copyFilesExtNoTreeIfNeeded(log
, shapeDirectory
, ExportBuildDirectory
+ "/" + ShapeClodtexBuildDirectory
, ".shape")
82 shapeDirectory
= ExportBuildDirectory
+ "/" + ShapeClodtexBuildDirectory
84 # copy lightmap_not_optimized to lightmap
85 printLog(log
, ">>> Optimize lightmaps <<<")
86 loPathLightmapsOriginal
= ExportBuildDirectory
+ "/" + ShapeLightmapNotOptimizedExportDirectory
87 loPathShapesOriginal
= ExportBuildDirectory
+ "/" + ShapeClodtexBuildDirectory
88 mkPath(log
, loPathLightmapsOriginal
)
89 loPathLightmaps
= ExportBuildDirectory
+ "/" + ShapeLightmapBuildDirectory
90 loPathShapes
= ExportBuildDirectory
+ "/" + ShapeOptimizedBuildDirectory
91 loPathTags
= ExportBuildDirectory
+ "/" + ShapeTagExportDirectory
92 mkPath(log
, loPathLightmaps
)
93 mkPath(log
, loPathShapes
)
94 mkPath(log
, loPathTags
)
95 if needUpdateDirByTagLog(log
, loPathLightmapsOriginal
, ".txt", loPathLightmaps
, ".txt") or needUpdateDirNoSubdir(log
, loPathLightmapsOriginal
, loPathLightmaps
) or needUpdateDirNoSubdir(log
, loPathShapesOriginal
, loPathShapes
) or needUpdateDirNoSubdir(log
, loPathShapes
, loPathLightmaps
) or needUpdateDirNoSubdir(log
, loPathTags
, loPathLightmaps
):
96 removeFilesRecursive(log
, loPathLightmaps
)
97 copyFiles(log
, loPathLightmapsOriginal
, loPathLightmaps
)
98 removeFilesRecursive(log
, loPathShapes
)
99 copyFiles(log
, loPathShapesOriginal
, loPathShapes
)
100 # Optimize lightmaps if any. Additionnaly, output a file indicating which lightmaps are 8 bits
101 # lightmap_optimizer <path_lightmaps> <path_shapes> [path_tags] [path_flag8bit]
102 subprocess
.call([ LightmapOptimizer
, loPathLightmaps
, loPathShapes
, loPathTags
, ExportBuildDirectory
+ "/" + ShapeLightmapBuildDirectory
+ "/list_lm_8bit.txt" ])
104 printLog(log
, "SKIP *")
106 # Convert lightmap in 16 bits mode if they are not 8 bits lightmap
107 printLog(log
, ">>> Convert lightmaps in 16 or 8 bits <<<")
108 mkPath(log
, ExportBuildDirectory
+ "/" + ShapeLightmapBuildDirectory
)
109 mkPath(log
, ExportBuildDirectory
+ "/" + ShapeLightmap16BitsBuildDirectory
)
110 lightMapTgas
= findFilesNoSubdir(log
, ExportBuildDirectory
+ "/" + ShapeLightmapBuildDirectory
, ".tga")
112 listLm8BitFile
= open(ExportBuildDirectory
+ "/" + ShapeLightmapBuildDirectory
+ "/list_lm_8bit.txt", "r")
113 for line
in listLm8BitFile
:
114 lineStrip
= line
.strip()
115 if (len(lineStrip
) > 0):
116 listLm8Bit
+= [ lineStrip
]
117 for lightMapTga
in lightMapTgas
:
118 srcTga
= ExportBuildDirectory
+ "/" + ShapeLightmapBuildDirectory
+ "/" + lightMapTga
119 dstTga
= ExportBuildDirectory
+ "/" + ShapeLightmap16BitsBuildDirectory
+ "/" + lightMapTga
120 if needUpdateLogRemoveDest(log
, srcTga
, dstTga
):
121 if lightMapTga
in listLm8Bit
: # THIS MAY NOT WORK, PLEASE VERIFY CONTENTS OF list_lm_8bit.txt!!!
122 subprocess
.call([ TgaToDds
, srcTga
, "-o", dstTga
, "-a", "tga8" ])
124 subprocess
.call([ TgaToDds
, srcTga
, "-o", dstTga
, "-a", "tga16" ])
126 # Corse meshes for this process ?
127 if len(CoarseMeshTextureNames
) > 0:
128 printLog(log
, ">>> Build coarse meshes <<<")
129 shapeWithCoarseMesh
= ExportBuildDirectory
+ "/" + ShapeWithCoarseMeshExportDirectory
130 mkPath(log
, shapeWithCoarseMesh
)
131 shapeWithCoarseMeshBuilded
= ExportBuildDirectory
+ "/" + ShapeWithCoarseMeshBuildDirectory
132 mkPath(log
, shapeWithCoarseMeshBuilded
)
133 # This builds from shapeWithCoarseMesh .shape to shapeWithCoarseMesh .tga
134 # And from shapeWithCoarseMesh .shape to shapeWithCoarseMeshBuilded .shape
135 # Then builds from shapeWithCoarseMesh .tga to shapeWithCoarseMeshBuilded .tga
136 # Depends on MapLookupDirectories
137 needUpdateMaps
= needUpdateMultiDirNoSubdirMultiFileExt(log
, ExportBuildDirectory
, MapLookupDirectories
, shapeWithCoarseMesh
, CoarseMeshTextureNames
, ".tga") or needUpdateMultiDirNoSubdir(log
, ExportBuildDirectory
, MapLookupDirectories
, shapeWithCoarseMeshBuilded
)
139 printLog(log
, "DETECT UPDATE Maps->*")
141 printLog(log
, "DETECT SKIP Maps->*")
142 needUpdateShapeShape
= needUpdateDirByTagLog(log
, shapeWithCoarseMesh
, ".shape", shapeWithCoarseMeshBuilded
, ".shape")
143 if needUpdateShapeShape
:
144 printLog(log
, "DETECT UPDATE Shape->Shape")
146 printLog(log
, "DETECT SKIP Shape->Shape")
147 needUpdateShapeCoarse
= needUpdateDirNoSubdirExtMultiFileExt(log
, shapeWithCoarseMesh
, ".shape", shapeWithCoarseMesh
, CoarseMeshTextureNames
, ".tga")
148 if needUpdateShapeCoarse
:
149 printLog(log
, "DETECT UPDATE Shape->Coarse")
151 printLog(log
, "DETECT SKIP Shape->Coarse")
152 if needUpdateMaps
or needUpdateShapeShape
or needUpdateShapeCoarse
:
153 cf
= open("config_generated.cfg", "w")
154 cf
.write("texture_mul_size = " + TextureMulSizeValue
+ ";\n")
156 cf
.write("search_path = \n")
158 cf
.write("\t\"" + shapeWithCoarseMesh
+ "\", \n")
159 for dir in MapLookupDirectories
:
160 cf
.write("\t\"" + ExportBuildDirectory
+ "/" + dir + "\", \n")
163 cf
.write("list_mesh = \n")
165 # For each shape with coarse mesh
166 files
= findFiles(log
, shapeWithCoarseMesh
, "", ".shape")
168 sourceFile
= shapeWithCoarseMesh
+ "/" + file
169 if os
.path
.isfile(sourceFile
):
170 destFile
= shapeWithCoarseMeshBuilded
+ "/" + file
171 cf
.write("\t\"" + file + "\", \"" + destFile
+ "\", \n")
174 cf
.write("output_textures = \n")
176 # For each shape with coarse mesh
177 for tn
in CoarseMeshTextureNames
:
178 cf
.write("\t\"" + shapeWithCoarseMesh
+ "/" + tn
+ ".tga\", \n")
181 subprocess
.call([ BuildCoarseMesh
, "config_generated.cfg" ])
182 os
.remove("config_generated.cfg")
183 needUpdateCoarse
= needUpdateDirNoSubdirExtMultiFileExt(log
, shapeWithCoarseMesh
, ".tga", shapeWithCoarseMeshBuilded
, CoarseMeshTextureNames
, ".dds")
185 printLog(log
, "DETECT UPDATE Coarse->DDS")
187 printLog(log
, "DETECT SKIP Coarse->DDS")
188 # Convert the coarse texture to dds
190 for tn
in CoarseMeshTextureNames
:
191 subprocess
.call([ TgaToDds
, shapeWithCoarseMesh
+ "/" + tn
+ ".tga", "-o", shapeWithCoarseMeshBuilded
+ "/" + tn
+ ".dds", "-a", "5" ])
193 printLog(log
, ">>> No coarse meshes <<<")