diff --git a/code/nel/include/nel/misc/bitmap.h b/code/nel/include/nel/misc/bitmap.h index 0466cd673..f96cd39b9 100644 --- a/code/nel/include/nel/misc/bitmap.h +++ b/code/nel/include/nel/misc/bitmap.h @@ -375,6 +375,12 @@ public: void makeOpaque(); + /** + * Make fully transparent pixels (alpha 0) black. + */ + void makeTransparentPixelsBlack(); + + /** * Return if the bitmap has uniform alpha values for all pixels. * \param alpha return the uniform value if return is true @@ -609,7 +615,7 @@ public: /** * Extended version of blit. The destinaion of the blit is 'this' bitmap * Source and dest rect are clamped as necessary. - * For now, only RGBA is uspported (an asertion occurs otherwise) + * For now, only RGBA is supported (an asertion occurs otherwise) * mipmap are not updated. * IMPORTANT : copy to self is not handled correctly */ diff --git a/code/nel/src/misc/bitmap.cpp b/code/nel/src/misc/bitmap.cpp index 3f22dc752..a996c8546 100644 --- a/code/nel/src/misc/bitmap.cpp +++ b/code/nel/src/misc/bitmap.cpp @@ -369,6 +369,51 @@ void CBitmap::makeOpaque() } +/*-------------------------------------------------------------------*\ + makeTransparentPixelsBlack +\*-------------------------------------------------------------------*/ +void CBitmap::makeTransparentPixelsBlack() +{ + if (_Width*_Height == 0) return; + + uint pixelSize; + + switch (PixelFormat) + { + case RGBA: pixelSize = 4; break; + case AlphaLuminance: pixelSize = 2; break; + default: return; + } + + uint colorsSize = pixelSize - 1; + + for (uint8 m = 0; m < _MipMapCount; ++m) + { + // get a pointer on original data + uint8 *data = _Data[m].getPtr(); + + // end of data + uint8 *endData = data + _Data[m].size(); + + // first alpha + data += pixelSize - 1; + + // replace all alpha values by 255 + while (data < endData) + { + // fully transparent pixel + if (*data == 0) + { + // make colors black + memset(data - colorsSize, 0, colorsSize); + } + + data += pixelSize; + } + } +} + + /*-------------------------------------------------------------------*\ isAlphaUniform \*-------------------------------------------------------------------*/ diff --git a/code/nel/src/misc/cmd_args.cpp b/code/nel/src/misc/cmd_args.cpp index 6ec3fd485..e6211faaf 100644 --- a/code/nel/src/misc/cmd_args.cpp +++ b/code/nel/src/misc/cmd_args.cpp @@ -141,7 +141,7 @@ bool CCmdArgs::needAdditionalArg() const const TArg &arg = _Args[i]; // they don't have any short or long name, but need a name in help - if (arg.shortName.empty() && arg.longName.empty() && !arg.helpName.empty() && arg.required) + if (arg.shortName.empty() && arg.longName.empty() && !arg.helpName.empty() && arg.required && !arg.found) return true; } @@ -363,7 +363,7 @@ bool CCmdArgs::parse(const std::vector &argv) } // process help if requested or if required arguments are missing - if (haveLongArg("help") || (needAdditionalArg() && !haveAdditionalArg())) + if (haveLongArg("help") || needAdditionalArg()) { displayHelp(); return false; diff --git a/code/nel/tools/3d/build_interface/main.cpp b/code/nel/tools/3d/build_interface/main.cpp index c56934662..859e2caf5 100644 --- a/code/nel/tools/3d/build_interface/main.cpp +++ b/code/nel/tools/3d/build_interface/main.cpp @@ -210,11 +210,12 @@ int main(int argc, char **argv) args.setDescription("Build a huge interface texture from several small elements to optimize video memory usage."); args.addArg("s", "subset", "existing_uv_txt_name", "Build a subset of an existing interface definition while preserving the existing texture ids, to support freeing up VRAM by switching to the subset without rebuilding the entire interface."); + args.addArg("x", "extract", "", "Extract all interface elements from to ."); args.addAdditionalArg("output_filename", "PNG or TGA file to generate", true); args.addAdditionalArg("input_path", "Path that containts interfaces elements", false); if (!args.parse(argc, argv)) return 1; - + // build as a subset of existing interface bool buildSubset = false; string existingUVfilename; @@ -225,6 +226,9 @@ int main(int argc, char **argv) existingUVfilename = args.getArg("s").front(); } + // extract all interface elements + bool extractElements = args.haveArg("x"); + std::vector inputDirs = args.getAdditionalArg("input_path"); string fmtName = args.getAdditionalArg("output_filename").front(); @@ -232,6 +236,111 @@ int main(int argc, char **argv) // append PNG extension if no one provided if (fmtName.rfind('.') == string::npos) fmtName += ".png"; + if (extractElements) + { + if (inputDirs.empty()) + { + outString(toString("ERROR: No input directories specified")); + return -1; + } + + // name of UV file + existingUVfilename = fmtName.substr(0, fmtName.rfind('.')); + existingUVfilename += ".txt"; + + // Load existing UV file + CIFile iFile; + string filename = CPath::lookup(existingUVfilename, false); + + if (filename.empty() || !iFile.open(filename)) + { + outString(toString("ERROR: Unable to open %s", existingUVfilename.c_str())); + return -1; + } + + // Load existing bitmap file + CIFile bitmapFile; + + if (!bitmapFile.open(fmtName)) + { + outString(toString("ERROR: Unable to open %s", fmtName.c_str())); + return -1; + } + + // load bitmap + CBitmap textureBitmap; + uint8 colors = textureBitmap.load(bitmapFile); + + // file already loaded in memory, close it + bitmapFile.close(); + + if (colors != 32) + { + outString(toString("ERROR: %s is not a RGBA bitmap", existingUVfilename.c_str())); + return -1; + } + + // make sure transparent pixels are black + textureBitmap.makeTransparentPixelsBlack(); + + float textureWidth = (float)textureBitmap.getWidth(); + float textureHeight = (float)textureBitmap.getHeight(); + + char bufTmp[256], tgaName[256]; + string sTGAname; + float uvMinU, uvMinV, uvMaxU, uvMaxV; + while (!iFile.eof()) + { + iFile.getline(bufTmp, 256); + + if (sscanf(bufTmp, "%s %f %f %f %f", tgaName, &uvMinU, &uvMinV, &uvMaxU, &uvMaxV) != 5) + { + nlwarning("Can't parse %s", bufTmp); + continue; + } + + float xf = uvMinU * textureWidth; + float yf = uvMinV * textureHeight; + float widthf = (uvMaxU - uvMinU) * textureWidth; + float heightf = (uvMaxV - uvMinV) * textureHeight; + + uint x = (uint)xf; + uint y = (uint)yf; + uint width = (uint)widthf; + uint height = (uint)heightf; + + if ((float)x != xf || (float)y != yf || (float)width != widthf || (float)height != heightf) + { + nlwarning("Wrong round"); + } + + if (width && height) + { + // create bitmap + CBitmap bitmap; + bitmap.resize(width, height); + bitmap.blit(textureBitmap, x, y, width, height, 0, 0); + + sTGAname = inputDirs.front() + "/" + tgaName; + + if (writeFileDependingOnFilename(sTGAname, bitmap)) + { + outString(toString("Writing file %s", sTGAname.c_str())); + } + else + { + outString(toString("Unable to writing file %s", sTGAname.c_str())); + } + } + else + { + outString(toString("Bitmap with wrong size")); + } + } + + return 0; + } + vector AllMapNames; vector::iterator it = inputDirs.begin(), itEnd = inputDirs.end(); @@ -350,6 +459,9 @@ int main(int argc, char **argv) UVMax[i].V = UVMax[i].V / (float)GlobalTexture.getHeight(); } + // make sure transparent pixels are black + GlobalTexture.makeTransparentPixelsBlack(); + // Write global texture file if (writeFileDependingOnFilename(fmtName, GlobalTexture)) { @@ -365,7 +477,7 @@ int main(int argc, char **argv) { fmtName = fmtName.substr(0, fmtName.rfind('.')); fmtName += ".txt"; - FILE *f = nlfopen(fmtName, "wt"); + FILE *f = nlfopen(fmtName, "wb"); if (f != NULL) { for (sint i = 0; i < mapSize; ++i) @@ -399,7 +511,7 @@ int main(int argc, char **argv) // Write subset UV text file fmtName = fmtName.substr(0, fmtName.rfind('.')); fmtName += ".txt"; - FILE *f = nlfopen(fmtName, "wt"); + FILE *f = nlfopen(fmtName, "wb"); if (f == NULL) { @@ -419,17 +531,27 @@ int main(int argc, char **argv) continue; } + sTGAname = toLower(string(tgaName)); + + // search position of extension + std::string tgaExt = CFile::getExtension(sTGAname); + + // remove extension + sTGAname = CFile::getFilenameWithoutExtension(sTGAname); + sint i; - sTGAname = toLower(string(tgaName)); string findTGAName; for (i = 0; i < mapSize; ++i) { // get the string whitout path - findTGAName = toLower(CFile::getFilename(AllMapNames[i])); + findTGAName = toLower(CFile::getFilenameWithoutExtension(AllMapNames[i])); if( findTGAName == sTGAname ) break; } + + // append extension + sTGAname += "." + tgaExt; if( i == mapSize ) { @@ -439,8 +561,7 @@ int main(int argc, char **argv) else { // present in subset: use new uv's - fprintf (f, "%s %.12f %.12f %.12f %.12f\n", sTGAname.c_str(), UVMin[i].U, UVMin[i].V, - UVMax[i].U, UVMax[i].V); + fprintf (f, "%s %.12f %.12f %.12f %.12f\n", sTGAname.c_str(), UVMin[i].U, UVMin[i].V, UVMax[i].U, UVMax[i].V); } } fclose (f); diff --git a/code/ryzom/client/macosx/ryzom.icns b/code/ryzom/client/macosx/ryzom.icns index 45e7bace1..606034de0 100644 Binary files a/code/ryzom/client/macosx/ryzom.icns and b/code/ryzom/client/macosx/ryzom.icns differ diff --git a/code/ryzom/client/src/CMakeLists.txt b/code/ryzom/client/src/CMakeLists.txt index b4afe6e75..d9afe57f8 100644 --- a/code/ryzom/client/src/CMakeLists.txt +++ b/code/ryzom/client/src/CMakeLists.txt @@ -60,13 +60,18 @@ IF(WITH_RYZOM_CLIENT) # on Mac, create a .App Bundle if(APPLE) + # We could force another build version for the bundle + IF(NOT RYZOM_BUILD) + SET(RYZOM_BUILD ${RYZOM_VERSION_SHORT}) + ENDIF() + SET(MACOSX_BUNDLE_INFO_STRING "Ryzom") SET(MACOSX_BUNDLE_ICON_FILE "ryzom.icns") SET(MACOSX_BUNDLE_GUI_IDENTIFIER "com.winchgate.Ryzom") SET(MACOSX_BUNDLE_LONG_VERSION_STRING ${RYZOM_VERSION}) SET(MACOSX_BUNDLE_BUNDLE_NAME "Ryzom") SET(MACOSX_BUNDLE_SHORT_VERSION_STRING ${RYZOM_VERSION_SHORT}) - SET(MACOSX_BUNDLE_BUNDLE_VERSION ${RYZOM_VERSION_SHORT}) + SET(MACOSX_BUNDLE_BUNDLE_VERSION ${RYZOM_BUILD}) SET(MACOSX_BUNDLE_COPYRIGHT ${COPYRIGHT}) SET(RYZOM_OUTPUT_DIR ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${MACOSX_BUNDLE_BUNDLE_NAME}.app) SET(RYZOM_CONTENTS_DIR ${RYZOM_OUTPUT_DIR}/Contents) diff --git a/code/ryzom/tools/client/ryzom_installer/src/utils.cpp b/code/ryzom/tools/client/ryzom_installer/src/utils.cpp index fc6a2ff7c..5ec1413e8 100644 --- a/code/ryzom/tools/client/ryzom_installer/src/utils.cpp +++ b/code/ryzom/tools/client/ryzom_installer/src/utils.cpp @@ -586,6 +586,9 @@ CLogHelper::CLogHelper(const QString &logPath) NLMISC::DisableNLDebug = true; #endif + // define process name before enabling log + NLMISC::CLog::setProcessName("ryzom_installer"); + // don't create a file for the moment, we'll create it manually NLMISC::createDebug(NULL, false);