khanat-opennel-code/code/ryzom/tools/leveldesign/georges_dll/icon_wnd.cpp
2010-09-24 10:27:31 +02:00

299 lines
No EOL
6.6 KiB
C++

// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// 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 <http://www.gnu.org/licenses/>.
// icon_wnd.cpp: implementation of the CIconWnd class.
//
#include "stdafx.h"
#include "georges_edit.h"
#include "icon_wnd.h"
#include "nel/misc/path.h"
#include "nel/misc/file.h"
#include "nel/misc/bitmap.h"
using namespace NLMISC;
using namespace std;
string CIconWnd::IconPath = "";
CIconWnd::CIconWnd()
{
pWndIcon = NULL;
pWndIconColor = NULL;
pWndIconBack = NULL;
pWndIconBackColor = NULL;
pWndIconOver = NULL;
pWndIconOverColor = NULL;
pWndIconOver2 = NULL;
pWndIconOver2Color = NULL;
}
CIconWnd::~CIconWnd()
{
}
BEGIN_MESSAGE_MAP(CIconWnd, CWnd)
//{{AFX_MSG_MAP(CIconWnd)
ON_WM_PAINT()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CIconWnd::OnPaint()
{
CPaintDC dc(this);
// update data
if (updateStr())
updateIcon();
// Get client dc
RECT client;
GetClientRect(&client);
dc.Rectangle(&client);
for (uint y=0 ; y<bitmap.getHeight() ; y++)
{
for (uint x=0 ; x<bitmap.getWidth() ; x++)
{
CRGBA c = bitmap.getPixelColor(x, y);
dc.SetPixel(x, y, RGB(c.R, c.G, c.B));
}
}
}
void CIconWnd::create (DWORD wStyle, RECT &pos, CWnd *parent, uint dialogIndex)
{
Id = dialogIndex;
// Register window class
LPCTSTR className = AfxRegisterWndClass(CS_OWNDC);
// Create this window
CWnd::Create(className, "empty", wStyle, pos, parent, dialogIndex);
}
bool CIconWnd::updateStr()
{
// check if icons need to be recomputed
bool needUpdate = false;
if (updateWnd(pWndIcon, strIcon))
needUpdate = true;
if (updateWnd(pWndIconColor, strIconColor))
needUpdate = true;
if (updateWnd(pWndIconBack, strIconBack))
needUpdate = true;
if (updateWnd(pWndIconBackColor, strIconBackColor))
needUpdate = true;
if (updateWnd(pWndIconOver, strIconOver))
needUpdate = true;
if (updateWnd(pWndIconOverColor, strIconOverColor))
needUpdate = true;
if (updateWnd(pWndIconOver2, strIconOver2))
needUpdate = true;
if (updateWnd(pWndIconOver2Color, strIconOver2Color))
needUpdate = true;
return needUpdate;
}
void CIconWnd::updateIcon()
{
// Get IconPath
if (IconPath == "")
{
CConfigFile::CVar *var = theApp.ConfigFile.getVarPtr("IconPath");
if (var)
{
IconPath = var->asString();
for (uint i=0 ; i<var->size() ; i++)
CPath::addSearchPath(var->asString(i), true, false, NULL);
}
else
{
nlinfo("!! IconPath missing in .cfg, Please complete the config file !!");
IconPath = "\\\\amiga\\3d\\Database\\Interfaces\\";
nlinfo("default to : IconPath = \"\\\\amiga\\3d\\Database\\Interfaces\\\"");
CPath::addSearchPath(IconPath, true, false, NULL);
}
}
NLMISC::CBitmap icon;
NLMISC::CRGBA color;
bitmap.reset();
bitmap.convertToType(NLMISC::CBitmap::RGBA);
bitmap.resample(40, 40);
// back icon
if (loadIcon(strIconBack, icon))
{
// back icon color
if (getColorFromStr(strIconBackColor, color))
modulateIcon(icon, color);
bitmap = icon;
// base icon
addIconLayer(bitmap, strIcon, strIconColor);
}
else
{
// base icon
loadIcon(strIcon, icon);
// base icon color
if (getColorFromStr(strIconColor, color))
modulateIcon(icon, color);
bitmap = icon;
}
// overlay icon
addIconLayer(bitmap, strIconOver, strIconOverColor);
// overlay 2 icon
addIconLayer(bitmap, strIconOver2, strIconOver2Color);
}
bool CIconWnd::loadIcon(const std::string &filename, NLMISC::CBitmap &bmp)
{
// Try to get the file path
string filepath = CPath::lookup(filename, false, false);
if (filepath == "")
{
bmp.makeDummy();
bmp.convertToType(NLMISC::CBitmap::RGBA);
bmp.resample(40, 40);
return false;
}
// load icon
CIFile f;
f.open(filepath);
bmp.load(f);
bmp.convertToType(NLMISC::CBitmap::RGBA);
bmp.resample(40, 40);
f.close();
return true;
}
bool CIconWnd::getColorFromStr(const std::string &s, NLMISC::CRGBA &c)
{
// Convert string to color
sint r, g, b;
if (sscanf (s.c_str(), "%d,%d,%d", &r, &g, &b) == 3)
{
clamp (r, 0, 255);
clamp (g, 0, 255);
clamp (b, 0, 255);
c = CRGBA(r, g, b);
return true;
}
return false;
}
void CIconWnd::blendIcons(NLMISC::CBitmap &dst, const NLMISC::CBitmap &src)
{
// blend between two icons
nlassert(dst.getWidth() == src.getWidth());
nlassert(dst.getHeight() == src.getHeight());
CObjectVector<uint8> &data = dst.getPixels();
for (uint y=0 ; y<dst.getHeight() ; y++)
{
for (uint x=0 ; x<dst.getWidth() ; x++)
{
CRGBA c;
c.blendFromui(dst.getPixelColor(x, y), src.getPixelColor(x, y), src.getPixelColor(x, y).A);
data[(x+y*dst.getWidth())*4] = c.R;
data[(x+y*dst.getWidth())*4+1] = c.G;
data[(x+y*dst.getWidth())*4+2] = c.B;
data[(x+y*dst.getWidth())*4+3] = c.A;
}
}
}
void CIconWnd::modulateIcon(NLMISC::CBitmap &dst, const NLMISC::CRGBA &col)
{
// modulate an icon by a color
CObjectVector<uint8> &data = dst.getPixels();
for (uint y=0 ; y<dst.getHeight() ; y++)
{
for (uint x=0 ; x<dst.getWidth() ; x++)
{
CRGBA c;
c.modulateFromColor(col, dst.getPixelColor(x, y));
data[(x+y*dst.getWidth())*4] = c.R;
data[(x+y*dst.getWidth())*4+1] = c.G;
data[(x+y*dst.getWidth())*4+2] = c.B;
data[(x+y*dst.getWidth())*4+3] = dst.getPixelColor(x, y).A;
}
}
}
void CIconWnd::addIconLayer(NLMISC::CBitmap &dst, const std::string iconStr, const std::string iconCol)
{
NLMISC::CBitmap icon;
NLMISC::CRGBA color;
if (loadIcon(iconStr, icon))
{
if (getColorFromStr(iconCol, color))
modulateIcon(icon, color);
blendIcons(dst, icon);
}
}
bool CIconWnd::updateWnd(CWnd *pWnd, std::string &str)
{
char buffer[512];
if (pWnd)
{
pWnd->GetWindowText(buffer, 512);
if (buffer != str)
{
str = buffer;
return true;
}
}
return false;
}