diff --git a/code/nel/include/nel/misc/bitmap.h b/code/nel/include/nel/misc/bitmap.h
index f96cd39b9..7e5994152 100644
--- a/code/nel/include/nel/misc/bitmap.h
+++ b/code/nel/include/nel/misc/bitmap.h
@@ -636,11 +636,17 @@ public:
- /** Get the pixel at the given coorrdinate.
+ /** Get the pixel at the given coordinate.
* Works in RGBA and DXTC modes.
* Outside of the bitmap it returns Black (or if mipmap is not found)
*/
CRGBA getPixelColor(sint x, sint y, uint32 numMipMap = 0) const;
+
+ /** Set the pixel at the given coordinate.
+ * Works in RGBA mode only.
+ */
+ void setPixelColor(sint x, sint y, CRGBA c, uint32 numMipMap = 0);
+
/**
* Horizontal flip (all the columns are flipped)
* Works only with RGBA, and DXTC formats (only if w/h is a power of 2)
diff --git a/code/nel/src/misc/bitmap.cpp b/code/nel/src/misc/bitmap.cpp
index a996c8546..47bdf3886 100644
--- a/code/nel/src/misc/bitmap.cpp
+++ b/code/nel/src/misc/bitmap.cpp
@@ -136,7 +136,8 @@ uint8 CBitmap::load(NLMISC::IStream &f, uint mipMapSkip)
}
#ifdef USE_JPEG
- if (fileType == JPG_HEADER)
+ // only compare fist word
+ if (memcmp(&fileType, &JPG_HEADER, 2) == 0)
{
#ifdef NEL_ALL_BITMAP_WHITE
uint8 result = readJPG(f);
@@ -4509,6 +4510,20 @@ CRGBA CBitmap::getPixelColor(sint x, sint y, uint32 numMipMap /*=0*/) const
return CRGBA::Black;
}
+//-----------------------------------------------
+void CBitmap::setPixelColor(sint x, sint y, CRGBA c, uint32 numMipMap)
+{
+ nlassert(PixelFormat == RGBA);
+
+ uint w = getWidth(numMipMap);
+ uint h = getHeight(numMipMap);
+
+ if (w == 0 || x < 0 || y < 0 || x >= (sint)w || y >= (sint)h) return;
+
+ uint8 *pix = &getPixels(numMipMap)[(x + y * w) << 2];
+
+ memcpy(pix, &c, sizeof(CRGBA));
+}
//-----------------------------------------------
void CBitmap::swap(CBitmap &other)
diff --git a/code/nel/tools/3d/CMakeLists.txt b/code/nel/tools/3d/CMakeLists.txt
index ff5c37db0..08fd9e776 100644
--- a/code/nel/tools/3d/CMakeLists.txt
+++ b/code/nel/tools/3d/CMakeLists.txt
@@ -36,6 +36,7 @@ IF(WITH_NEL_TOOLS)
build_interface
get_neighbors
textures_optimizer
+ textures_tool
tga_cut
tga_resize)
ENDIF()
diff --git a/code/nel/tools/3d/textures_tool/CMakeLists.txt b/code/nel/tools/3d/textures_tool/CMakeLists.txt
new file mode 100644
index 000000000..203167162
--- /dev/null
+++ b/code/nel/tools/3d/textures_tool/CMakeLists.txt
@@ -0,0 +1,9 @@
+FILE(GLOB SRC *.cpp *.h)
+
+ADD_EXECUTABLE(textures_tool ${SRC})
+
+TARGET_LINK_LIBRARIES(textures_tool nelmisc)
+NL_DEFAULT_PROPS(textures_tool "NeL, Tools, 3D: Textures Tool")
+NL_ADD_RUNTIME_FLAGS(textures_tool)
+
+INSTALL(TARGETS textures_tool RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d)
diff --git a/code/nel/tools/3d/textures_tool/main.cpp b/code/nel/tools/3d/textures_tool/main.cpp
new file mode 100644
index 000000000..589ab8d72
--- /dev/null
+++ b/code/nel/tools/3d/textures_tool/main.cpp
@@ -0,0 +1,269 @@
+// NeL - MMORPG Framework
+// Copyright (C) 2010 Winch Gate Property Limited
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+
+#include "nel/misc/file.h"
+#include "nel/misc/common.h"
+#include "nel/misc/bitmap.h"
+#include "nel/misc/path.h"
+#include "nel/misc/cmd_args.h"
+#include "nel/misc/vector_2d.h"
+
+struct CPoint
+{
+ CPoint(sint _x, sint _y) :x(_x), y(_y)
+ {
+ }
+
+ CPoint operator + (const CPoint &p) const
+ {
+ return CPoint(x + p.x, y + p.y);
+ }
+
+ sint x;
+ sint y;
+};
+
+const CPoint Up(0, -1);
+const CPoint Down(0, 1);
+const CPoint Left(-1, 0);
+const CPoint Right(1, 0);
+
+const NLMISC::CRGBA DiscardColor = NLMISC::CRGBA::Red;
+const NLMISC::CRGBA KeepColor = NLMISC::CRGBA::Blue;
+
+typedef std::vector CPoints;
+
+bool fillPoint(NLMISC::CBitmap &bitmap, sint width, CPoints &points)
+{
+ if (points.empty()) return false;
+
+ // take last point in queue
+ CPoint p(points.back());
+ points.pop_back();
+
+ NLMISC::CRGBA c = bitmap.getPixelColor(p.x, p.y);
+
+ if (c == NLMISC::CRGBA::White)
+ {
+ // white is used for background
+
+ // replace with color we want to discard
+ bitmap.setPixelColor(p.x, p.y, DiscardColor);
+
+ uint w = bitmap.getWidth();
+ uint h = bitmap.getHeight();
+
+ // put adjacent pixels in queue to process later
+ if (p.y > 0) points.push_back(p + Up);
+ if (p.y < h-1) points.push_back(p + Down);
+ if (p.x > 0) points.push_back(p + Left);
+ if (p.x < w-1) points.push_back(p + Right);
+ }
+ else if (c == NLMISC::CRGBA::Black)
+ {
+ // black is used for vertices
+
+ // increase them by border width
+ for (sint y = -width; y <= width; ++y)
+ {
+ for (sint x = -width; x <= width; ++x)
+ {
+ bitmap.setPixelColor(p.x + x, p.y + y, KeepColor);
+ }
+ }
+ }
+
+ return true;
+}
+
+int main(int argc, char **argv)
+{
+ NLMISC::CApplicationContext applicationContext;
+
+ // Parse Command Line.
+ //====================
+ NLMISC::CCmdArgs args;
+
+ args.setDescription("Textures tool");
+ args.addArg("c", "colorize", "color", "Colorize textures using a color (in HTML hexdecimal format like #rrggbb)");
+ args.addArg("f", "fill", "color or image", "Fill background part with color or image");
+ args.addArg("w", "width", "width of border", "Width of the border to fill (default 0)");
+ args.addArg("b", "background", "background color", "Color to use to fill background");
+ args.addArg("o", "output", "filename", "Output filename");
+ args.addAdditionalArg("filename", "File to process", true, true);
+
+ if (!args.parse(argc, argv)) return 1;
+
+ std::string filename = args.getAdditionalArg("filename").front();
+
+ std::string output = args.haveArg("o") ? args.getArg("o").front() : "";
+
+ if (args.haveArg("c"))
+ {
+ // colorize
+ NLMISC::CIFile file;
+
+ NLMISC::CRGBA color;
+ color.fromString(args.getArg("c").front());
+
+ if (file.open(filename))
+ {
+ NLMISC::CBitmap bitmap;
+
+ if (bitmap.load(file))
+ {
+ NLMISC::CObjectVector &pixels = bitmap.getPixels();
+
+ NLMISC::CRGBA *pRGBA = (NLMISC::CRGBA*)&pixels[0];
+
+ uint32 size = bitmap.getSize();
+
+ for (uint j = 0; j < size; ++j)
+ {
+ // TODO: find what computation do
+// *(pRGBA++)-> = color;
+ }
+
+ NLMISC::COFile out;
+
+ if (out.open(output))
+ {
+ bitmap.writePNG(out, 24);
+ }
+ }
+ }
+ }
+
+ if (args.haveArg("f"))
+ {
+ // fill areas in a bitmap with another texture or color
+
+ // for example :
+ // textures_tool -f normal.png -w 2 -b #000000 uvmap.png -o test_normal.png
+ // will use a copy 1024x1024 texture map on a 4096x4096 UV Map preserving the different areas
+
+ std::string foregroundColorOrFilename = args.getArg("f").front();
+
+ NLMISC::CRGBA foregroundColor = NLMISC::CRGBA::Black, backgroundColor = NLMISC::CRGBA::Black;
+
+ NLMISC::CBitmap textureBitmap;
+
+ bool useTexture = false;
+
+ // f parameter is required
+ if (NLMISC::CFile::fileExists(foregroundColorOrFilename))
+ {
+ // load texture
+ NLMISC::CIFile textureFile;
+
+ if (!textureFile.open(foregroundColorOrFilename))
+ {
+ nlwarning("Unable to open %s", foregroundColorOrFilename.c_str());
+ return 1;
+ }
+
+ // decode texture
+ if (!textureBitmap.load(textureFile))
+ {
+ nlwarning("Unable to decode %s", foregroundColorOrFilename.c_str());
+ return 1;
+ }
+
+ useTexture = true;
+ }
+ else
+ {
+ // parse color from argument
+ foregroundColor.fromString(foregroundColorOrFilename);
+ }
+
+ if (args.haveArg("b"))
+ {
+ // parse HTML color from argument
+ backgroundColor.fromString(args.getArg("b").front());
+ }
+
+ sint width = 0;
+
+ if (args.haveArg("w"))
+ {
+ // parse width of borders
+ NLMISC::fromString(args.getArg("w").front(), width);
+ }
+
+ // load bitmap
+ NLMISC::CIFile file;
+
+ if (!file.open(filename))
+ {
+ nlwarning("Unable to open %s", filename.c_str());
+ return 1;
+ }
+
+ // decode bitmap
+ NLMISC::CBitmap inBitmap;
+
+ if (!inBitmap.load(file))
+ {
+ nlwarning("Unable to decode %s", filename.c_str());
+ return 1;
+ }
+
+ CPoints Points;
+
+ // we can't have more than width * height points, so allocate memory for all of them
+ Points.reserve(inBitmap.getWidth() * inBitmap.getHeight());
+
+ // first point to process
+ Points.push_back(CPoint(0, 0));
+
+ // process all points from 0, 0
+ while(fillPoint(inBitmap, width, Points)) { }
+
+ // create a new bitmap for output
+ NLMISC::CBitmap outBitmap;
+ outBitmap.resize(inBitmap.getWidth(), inBitmap.getHeight());
+
+ // copy points colors to new bitmap
+ for (sint y = 0, h = inBitmap.getHeight(); y < h; ++y)
+ {
+ for (sint x = 0, w = inBitmap.getWidth(); x < w; ++x)
+ {
+ if (inBitmap.getPixelColor(x, y) != DiscardColor)
+ {
+ // we copy this point, repeat texture image if using it
+ outBitmap.setPixelColor(x, y, useTexture ? textureBitmap.getPixelColor(x % textureBitmap.getWidth(), y % textureBitmap.getHeight()) : foregroundColor);
+ }
+ else
+ {
+ // put a background color
+ outBitmap.setPixelColor(x, y, backgroundColor);
+ }
+ }
+ }
+
+ // save output bitmap
+ NLMISC::COFile outFile;
+
+ if (outFile.open(output))
+ {
+ outBitmap.writePNG(outFile, 24);
+ }
+ }
+
+ return 0;
+}
diff --git a/code/ryzom/tools/leveldesign/mission_compiler_lib/steps.cpp b/code/ryzom/tools/leveldesign/mission_compiler_lib/steps.cpp
index f989fbd8a..613621ca8 100644
--- a/code/ryzom/tools/leveldesign/mission_compiler_lib/steps.cpp
+++ b/code/ryzom/tools/leveldesign/mission_compiler_lib/steps.cpp
@@ -553,7 +553,7 @@ public:
// parse ai instance list
vector vs = md.getPropertyArray(prim, "ai_instances", true, false);
-/* if (vs..empty())
+/* if (vs.empty())
{
string err = toString("crash block need at least one ai instance !");
throw EParseException(prim, err.c_str());