299 lines
6.6 KiB
C++
299 lines
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;
|
||
|
}
|