You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
443 lines
13 KiB
443 lines
13 KiB
4 years ago
|
/*==LICENSE==*
|
||
|
|
||
|
CyanWorlds.com Engine - MMOG client, server and tools
|
||
|
Copyright (C) 2011 Cyan Worlds, Inc.
|
||
|
|
||
|
This program is free software: you can redistribute it and/or modify
|
||
|
it under the terms of the GNU 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 General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License
|
||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
||
|
Additional permissions under GNU GPL version 3 section 7
|
||
|
|
||
|
If you modify this Program, or any covered work, by linking or
|
||
|
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||
|
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||
|
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||
|
(or a modified version of those libraries),
|
||
|
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||
|
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||
|
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||
|
licensors of this Program grant you additional
|
||
|
permission to convey the resulting work. Corresponding Source for a
|
||
|
non-source form of such a combination shall include the source code for
|
||
|
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||
|
work.
|
||
|
|
||
|
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||
|
or by snail mail at:
|
||
|
Cyan Worlds, Inc.
|
||
|
14617 N Newport Hwy
|
||
|
Mead, WA 99021
|
||
|
|
||
|
*==LICENSE==*/
|
||
|
//#include "plClothingMtl.h"
|
||
|
#include "../../AssetMan/PublicInterface/AssManBaseTypes.h"
|
||
|
#include "max.h"
|
||
|
|
||
|
class plClothingEditBox
|
||
|
{
|
||
|
protected:
|
||
|
int fCtrlID;
|
||
|
int fPBEditID;
|
||
|
|
||
|
plClothingEditBox() {};
|
||
|
|
||
|
void IGetText(IParamBlock2 *pb, HWND hCtrl)
|
||
|
{
|
||
|
// Get the previous value
|
||
|
const char *oldVal = pb->GetStr(fPBEditID);
|
||
|
if (!oldVal)
|
||
|
oldVal = "";
|
||
|
|
||
|
// Get the text from the edit and store it in the paramblock
|
||
|
int len = GetWindowTextLength(hCtrl)+1;
|
||
|
if (len > 1)
|
||
|
{
|
||
|
char *buf = TRACKED_NEW char[len];
|
||
|
GetWindowText(hCtrl, buf, len);
|
||
|
|
||
|
// If the old value is different from the current one, update
|
||
|
if (strcmp(oldVal, buf))
|
||
|
pb->SetValue(fPBEditID, 0, buf);
|
||
|
|
||
|
delete [] buf;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// If the old value wasn't empty, update
|
||
|
if (*oldVal != '\0')
|
||
|
pb->SetValue(fPBEditID, 0, "");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public:
|
||
|
plClothingEditBox(int ctrlID, int pbEditID) : fCtrlID(ctrlID), fPBEditID(pbEditID) {}
|
||
|
|
||
|
void UpdateText(IParamBlock2 *pb, HWND hWnd)
|
||
|
{
|
||
|
const char *str = pb->GetStr(fPBEditID);
|
||
|
SetDlgItemText(hWnd, fCtrlID, (str != nil ? str : ""));
|
||
|
}
|
||
|
|
||
|
BOOL ProcessMsg(IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
// If this isn't a message we process, return
|
||
|
if (!(msg == WM_INITDIALOG || msg == WM_DESTROY ||
|
||
|
(msg == WM_COMMAND && LOWORD(wParam) == fCtrlID)))
|
||
|
return FALSE;
|
||
|
|
||
|
IParamBlock2 *pb = map->GetParamBlock();
|
||
|
|
||
|
// Initializing the dialog, set the text box
|
||
|
if (msg == WM_INITDIALOG)
|
||
|
{
|
||
|
UpdateText(pb, hWnd);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// Being destroyed, but we may not have gotten the text from the edit box
|
||
|
// (EN_KILLFOCUS seems to be sent after the window isn't recieving any more messages)
|
||
|
if (msg == WM_DESTROY)
|
||
|
{
|
||
|
IGetText(pb, GetDlgItem(hWnd, fCtrlID));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
int notification = HIWORD(wParam);
|
||
|
HWND hCtrl = (HWND)lParam;
|
||
|
|
||
|
// Disable Max accelerators when the edit box gets focus
|
||
|
if (notification == EN_SETFOCUS)
|
||
|
{
|
||
|
//plMaxAccelerators::Disable();
|
||
|
DisableAccelerators();
|
||
|
return TRUE;
|
||
|
}
|
||
|
// The edit control is losing focus, get it's contents
|
||
|
else if (notification == EN_KILLFOCUS)
|
||
|
{
|
||
|
IGetText(pb, hCtrl);
|
||
|
//plMaxAccelerators::Enable();
|
||
|
EnableAccelerators();
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
class ClothingBasicDlgProc;
|
||
|
extern ClothingBasicDlgProc gClothingBasicDlgProc;
|
||
|
|
||
|
static ParamBlockDesc2 gClothingMtlPB
|
||
|
(
|
||
|
plClothingMtl::kBlkBasic, _T("Clothing"), IDS_PASS_BASIC, GetClothingMtlDesc(),
|
||
|
P_AUTO_CONSTRUCT + P_AUTO_UI + P_CALLSETS_ON_LOAD, plClothingMtl::kRefBasic,
|
||
|
|
||
|
// UI
|
||
|
IDD_CLOTHING, IDS_PASS_BASIC, 0, 0, &gClothingBasicDlgProc,
|
||
|
|
||
|
plClothingMtl::kTileset, _T("tileset"), TYPE_INT, 0, 0,
|
||
|
p_default, 0,
|
||
|
end,
|
||
|
|
||
|
plClothingMtl::kTexmap, _T("texmap"), TYPE_TEXMAP_TAB, plClothingMtl::kMaxTiles, 0, 0,
|
||
|
end,
|
||
|
|
||
|
plClothingMtl::kDescription, _T("ItemDescription"), TYPE_STRING, 0, 0,
|
||
|
p_ui, TYPE_EDITBOX, IDC_CLOTHING_DESCRIPTION,
|
||
|
end,
|
||
|
|
||
|
plClothingMtl::kThumbnail, _T("Thumbnail"), TYPE_TEXMAP, 0, 0,
|
||
|
end,
|
||
|
|
||
|
plClothingMtl::kLayer, _T("Layer"), TYPE_INT, 0, 0,
|
||
|
p_default, plClothingElement::kLayerTint1,
|
||
|
end,
|
||
|
|
||
|
plClothingMtl::kTexmapSkin, _T("SkinLayer"), TYPE_TEXMAP_TAB, plClothingMtl::kMaxTiles, 0, 0,
|
||
|
end,
|
||
|
|
||
|
plClothingMtl::kTexmap2, _T("TintLayer2"), TYPE_TEXMAP_TAB, plClothingMtl::kMaxTiles, 0, 0,
|
||
|
end,
|
||
|
|
||
|
plClothingMtl::kDefault, _T("Default"), TYPE_BOOL, 0, 0,
|
||
|
p_ui, TYPE_SINGLECHEKBOX, IDC_CLOTHING_DEFAULT,
|
||
|
p_default, 0,
|
||
|
end,
|
||
|
|
||
|
plClothingMtl::kCustomTextSpecs, _T("TextSpecs"), TYPE_STRING, 0, 0,
|
||
|
end,
|
||
|
|
||
|
plClothingMtl::kTexmapBase, _T("BaseLayer"), TYPE_TEXMAP_TAB, plClothingMtl::kMaxTiles, 0, 0,
|
||
|
end,
|
||
|
|
||
|
plClothingMtl::kTexmapSkinBlend1, _T("SkinBlend(1)"), TYPE_TEXMAP_TAB, plClothingMtl::kMaxTiles, 0, 0,
|
||
|
end,
|
||
|
|
||
|
plClothingMtl::kTexmapSkinBlend2, _T("SkinBlend(2)"), TYPE_TEXMAP_TAB, plClothingMtl::kMaxTiles, 0, 0,
|
||
|
end,
|
||
|
|
||
|
plClothingMtl::kTexmapSkinBlend3, _T("SkinBlend(3)"), TYPE_TEXMAP_TAB, plClothingMtl::kMaxTiles, 0, 0,
|
||
|
end,
|
||
|
|
||
|
plClothingMtl::kTexmapSkinBlend4, _T("SkinBlend(4)"), TYPE_TEXMAP_TAB, plClothingMtl::kMaxTiles, 0, 0,
|
||
|
end,
|
||
|
|
||
|
plClothingMtl::kTexmapSkinBlend5, _T("SkinBlend(5)"), TYPE_TEXMAP_TAB, plClothingMtl::kMaxTiles, 0, 0,
|
||
|
end,
|
||
|
|
||
|
plClothingMtl::kTexmapSkinBlend6, _T("SkinBlend(6)"), TYPE_TEXMAP_TAB, plClothingMtl::kMaxTiles, 0, 0,
|
||
|
end,
|
||
|
|
||
|
plClothingMtl::kDefaultTint1, _T("DefaultTint1"), TYPE_RGBA, 0, 0,
|
||
|
p_ui, TYPE_COLORSWATCH, IDC_CLOTHING_TINT1,
|
||
|
p_default, Color(1,1,1),
|
||
|
end,
|
||
|
|
||
|
plClothingMtl::kDefaultTint2, _T("DefaultTint2"), TYPE_RGBA, 0, 0,
|
||
|
p_ui, TYPE_COLORSWATCH, IDC_CLOTHING_TINT2,
|
||
|
p_default, Color(1,1,1),
|
||
|
end,
|
||
|
|
||
|
plClothingMtl::kForcedAcc, _T("ForcedAcc"), TYPE_STRING, 0, 0,
|
||
|
p_ui, TYPE_EDITBOX, IDC_CLOTHING_FORCED_ACC,
|
||
|
end,
|
||
|
|
||
|
end
|
||
|
);
|
||
|
|
||
|
class ClothingBasicDlgProc : public ParamMap2UserDlgProc
|
||
|
{
|
||
|
protected:
|
||
|
plClothingEditBox fCustomText;
|
||
|
|
||
|
public:
|
||
|
ClothingBasicDlgProc() : fCustomText(IDC_CLOTHING_CUSTOM_TEXT_SPECS, plClothingMtl::kCustomTextSpecs) {}
|
||
|
~ClothingBasicDlgProc() {}
|
||
|
|
||
|
void UpdateDisplay(IParamMap2 *pmap)
|
||
|
{
|
||
|
HWND hWnd = pmap->GetHWnd();
|
||
|
IParamBlock2 *pb = pmap->GetParamBlock();
|
||
|
|
||
|
plClothingMtl *mtl = (plClothingMtl *)pb->GetOwner();
|
||
|
HWND cbox = NULL;
|
||
|
plPlasmaMAXLayer *layer;
|
||
|
PBBitmap *pbbm;
|
||
|
ICustButton *bmSelectBtn;
|
||
|
char buff[256];
|
||
|
|
||
|
// Setup the tiles
|
||
|
int i, j;
|
||
|
int layerSet = pb->GetInt(ParamID(plClothingMtl::kLayer));
|
||
|
int layerIdx = plClothingMtl::LayerToPBIdx[layerSet];
|
||
|
for (j = 0; j < plClothingMtl::kMaxTiles; j++)
|
||
|
{
|
||
|
layer = (plPlasmaMAXLayer *)pb->GetTexmap(ParamID(layerIdx), 0, j);
|
||
|
pbbm = (layer == nil ? nil : layer->GetPBBitmap());
|
||
|
|
||
|
bmSelectBtn = GetICustButton(GetDlgItem(hWnd, plClothingMtl::ButtonConstants[j]));
|
||
|
bmSelectBtn->SetText(pbbm ? (TCHAR*)pbbm->bi.Filename() : "(none)");
|
||
|
ReleaseICustButton(bmSelectBtn);
|
||
|
}
|
||
|
|
||
|
// And the thumbnail...
|
||
|
layer = (plPlasmaMAXLayer *)pb->GetTexmap(ParamID(plClothingMtl::kThumbnail));
|
||
|
if (layer == nil)
|
||
|
{
|
||
|
layer = TRACKED_NEW plLayerTex;
|
||
|
pb->SetValue(ParamID(plClothingMtl::kThumbnail), 0, layer);
|
||
|
}
|
||
|
pbbm = layer->GetPBBitmap();
|
||
|
if (pbbm)
|
||
|
{
|
||
|
bmSelectBtn = GetICustButton(GetDlgItem(hWnd, IDC_CLOTHING_THUMBNAIL));
|
||
|
bmSelectBtn->SetText((TCHAR*)pbbm->bi.Filename());
|
||
|
ReleaseICustButton(bmSelectBtn);
|
||
|
}
|
||
|
|
||
|
int setIdx = pb->GetInt(ParamID(plClothingMtl::kTileset));
|
||
|
ComboBox_SetCurSel(GetDlgItem(hWnd, IDC_CLOTHING_TILESET), setIdx);
|
||
|
ComboBox_SetCurSel(GetDlgItem(hWnd, IDC_CLOTHING_LAYER), pb->GetInt(ParamID(plClothingMtl::kLayer)));
|
||
|
mtl->InitTilesets();
|
||
|
plClothingTileset *tileset = mtl->fTilesets.Get(setIdx);
|
||
|
for (i = 0; i < tileset->fElements.GetCount(); i++)
|
||
|
{
|
||
|
plClothingElement *element = tileset->fElements.Get(i);
|
||
|
SendMessage(GetDlgItem(hWnd, plClothingMtl::TextConstants[2 * i]),
|
||
|
WM_SETTEXT, NULL, (LPARAM)element->fName);
|
||
|
sprintf(buff, "(%d, %d)", element->fWidth, element->fHeight);
|
||
|
SendMessage(GetDlgItem(hWnd, plClothingMtl::TextConstants[2 * i + 1]),
|
||
|
WM_SETTEXT, NULL, (LPARAM)buff);
|
||
|
|
||
|
ShowWindow(GetDlgItem(hWnd, plClothingMtl::TextConstants[2 * i]), SW_SHOW);
|
||
|
ShowWindow(GetDlgItem(hWnd, plClothingMtl::TextConstants[2 * i + 1]), SW_SHOW);
|
||
|
ShowWindow(GetDlgItem(hWnd, plClothingMtl::ButtonConstants[i]), SW_SHOW);
|
||
|
}
|
||
|
for (i = tileset->fElements.GetCount(); i < plClothingMtl::kMaxTiles; i++)
|
||
|
{
|
||
|
ShowWindow(GetDlgItem(hWnd, plClothingMtl::TextConstants[2 * i]), SW_HIDE);
|
||
|
ShowWindow(GetDlgItem(hWnd, plClothingMtl::TextConstants[2 * i + 1]), SW_HIDE);
|
||
|
ShowWindow(GetDlgItem(hWnd, plClothingMtl::ButtonConstants[i]), SW_HIDE);
|
||
|
}
|
||
|
mtl->ReleaseTilesets();
|
||
|
|
||
|
fCustomText.UpdateText(pb, hWnd);
|
||
|
}
|
||
|
|
||
|
virtual void Update(TimeValue t, Interval& valid, IParamMap2* pmap) { UpdateDisplay(pmap); }
|
||
|
|
||
|
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
// Check if it is for our edit box
|
||
|
if (fCustomText.ProcessMsg(map, hWnd, msg, wParam, lParam))
|
||
|
return TRUE;
|
||
|
|
||
|
int id = LOWORD(wParam);
|
||
|
int code = HIWORD(wParam);
|
||
|
|
||
|
IParamBlock2 *pb = map->GetParamBlock();
|
||
|
plClothingMtl *mtl = (plClothingMtl *)pb->GetOwner();
|
||
|
HWND cbox = NULL;
|
||
|
plPlasmaMAXLayer *layer;
|
||
|
PBBitmap *pbbm;
|
||
|
ICustButton *bmSelectBtn;
|
||
|
int layerIdx = plClothingMtl::LayerToPBIdx[pb->GetInt(ParamID(plClothingMtl::kLayer))];
|
||
|
|
||
|
switch (msg)
|
||
|
{
|
||
|
case WM_INITDIALOG:
|
||
|
int j;
|
||
|
mtl->InitTilesets();
|
||
|
cbox = GetDlgItem(hWnd, IDC_CLOTHING_TILESET);
|
||
|
for (j = 0; j < mtl->fTilesets.GetCount(); j++)
|
||
|
SendMessage(cbox, CB_ADDSTRING, 0, (LPARAM)mtl->fTilesets.Get(j)->fName);
|
||
|
|
||
|
mtl->ReleaseTilesets();
|
||
|
|
||
|
cbox = GetDlgItem(hWnd, IDC_CLOTHING_LAYER);
|
||
|
for (j = 0; j < plClothingElement::kLayerMax; j++)
|
||
|
ComboBox_AddString(cbox, plClothingMtl::LayerStrings[j]);
|
||
|
|
||
|
return TRUE;
|
||
|
|
||
|
case WM_COMMAND:
|
||
|
if (id == IDC_CLOTHING_TILESET)
|
||
|
{
|
||
|
int setIdx = SendMessage(GetDlgItem(hWnd, id), CB_GETCURSEL, 0, 0);
|
||
|
pb->SetValue(plClothingMtl::kTileset, t, setIdx);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
if (id == IDC_CLOTHING_LAYER)
|
||
|
{
|
||
|
|
||
|
pb->SetValue(plClothingMtl::kLayer, t, ComboBox_GetCurSel(GetDlgItem(hWnd, id)));
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
if (id == IDC_CLOTHING_THUMBNAIL)
|
||
|
{
|
||
|
layer = (plPlasmaMAXLayer *)pb->GetTexmap(ParamID(plClothingMtl::kThumbnail));
|
||
|
if (layer == nil)
|
||
|
return FALSE;
|
||
|
|
||
|
BitmapInfo bi;
|
||
|
bi.SetName(layer->GetPBBitmap() == nil ? "" : layer->GetPBBitmap()->bi.Name());
|
||
|
|
||
|
BOOL selectedNewBitmap = layer->HandleBitmapSelection();
|
||
|
if (selectedNewBitmap)
|
||
|
{
|
||
|
pbbm = layer->GetPBBitmap();
|
||
|
bmSelectBtn = GetICustButton(GetDlgItem(hWnd, IDC_CLOTHING_THUMBNAIL));
|
||
|
bmSelectBtn->SetText(pbbm != nil ? (TCHAR*)pbbm->bi.Filename() : "(none)");
|
||
|
ReleaseICustButton(bmSelectBtn);
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
int buttonIdx = -1;
|
||
|
if (id == IDC_CLOTHING_TEXTURE1) buttonIdx = 0;
|
||
|
else if (id == IDC_CLOTHING_TEXTURE2) buttonIdx = 1;
|
||
|
else if (id == IDC_CLOTHING_TEXTURE3) buttonIdx = 2;
|
||
|
else if (id == IDC_CLOTHING_TEXTURE4) buttonIdx = 3;
|
||
|
|
||
|
if (buttonIdx != -1)
|
||
|
{
|
||
|
layer = (plPlasmaMAXLayer *)pb->GetTexmap(ParamID(layerIdx), 0, buttonIdx);
|
||
|
if (layer == nil)
|
||
|
{ // First time we've set a layer on this spot
|
||
|
layer = TRACKED_NEW plLayerTex;
|
||
|
pb->SetValue(ParamID(layerIdx), 0, layer, buttonIdx);
|
||
|
}
|
||
|
|
||
|
jvUniqueId oldId;
|
||
|
layer->GetBitmapAssetId(oldId);
|
||
|
|
||
|
BitmapInfo bi;
|
||
|
bi.SetName(layer->GetPBBitmap() == nil ? "" : layer->GetPBBitmap()->bi.Name());
|
||
|
|
||
|
BOOL selectedNewBitmap = layer->HandleBitmapSelection();
|
||
|
if (selectedNewBitmap)
|
||
|
{
|
||
|
// Check if it's ok, and undo if not.
|
||
|
hsBool choiceOk = true;
|
||
|
|
||
|
pbbm = layer->GetPBBitmap();
|
||
|
if (pbbm != nil)
|
||
|
{
|
||
|
mtl->InitTilesets();
|
||
|
|
||
|
plClothingTileset *tileset = mtl->fTilesets.Get(pb->GetInt(plClothingMtl::kTileset));
|
||
|
plClothingElement *element = tileset->fElements.Get(buttonIdx);
|
||
|
float targRatio = (float)element->fWidth / (float)element->fHeight;
|
||
|
float ratio = (float)pbbm->bi.Width() / (float)pbbm->bi.Height();
|
||
|
|
||
|
if (targRatio != ratio)
|
||
|
{
|
||
|
choiceOk = false;
|
||
|
hsMessageBox("That image's width/height ratio does not match the one for this tile. "
|
||
|
"Restoring the old selection.", "Invalid image", hsMessageBoxNormal);
|
||
|
}
|
||
|
else if (pbbm->bi.Width() < element->fWidth)
|
||
|
{
|
||
|
choiceOk = false;
|
||
|
hsMessageBox("The chosen image is too small for that tile slot. "
|
||
|
"Restoring the old selection.", "Invalid image", hsMessageBoxNormal);
|
||
|
}
|
||
|
|
||
|
mtl->ReleaseTilesets();
|
||
|
}
|
||
|
if (!choiceOk)
|
||
|
{
|
||
|
layer->SetBitmapAssetId(oldId);
|
||
|
layer->SetBitmap(&bi);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
bmSelectBtn = GetICustButton(GetDlgItem(hWnd, plClothingMtl::ButtonConstants[buttonIdx]));
|
||
|
bmSelectBtn->SetText(pbbm != nil ? (TCHAR*)pbbm->bi.Filename() : "(none)");
|
||
|
ReleaseICustButton(bmSelectBtn);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
void DeleteThis() {}
|
||
|
};
|
||
|
static ClothingBasicDlgProc gClothingBasicDlgProc;
|