📄 charcontrol.cpp
字号:
// our headers
#include "util.h"
#include "charcontrol.h"
#include "modelviewer.h"
#include "itemselection.h"
#ifdef _WIN32
using namespace stdext;
#endif
enum {
SPIN_SKIN_COLOR,
SPIN_FACE_TYPE,
SPIN_HAIR_COLOR,
SPIN_HAIR_STYLE,
SPIN_FACIAL_HAIR,
SPIN_FACIAL_COLOR,
NUM_SPIN_BTNS
};
enum {
SPIN_TABARD_ICON = 0,
SPIN_TABARD_ICONCOLOR,
SPIN_TABARD_BORDER,
SPIN_TABARD_BORDERCOLOR,
SPIN_TABARD_BACKGROUND,
NUM_TABARD_BTNS
};
IMPLEMENT_CLASS(CharControl, wxWindow)
BEGIN_EVENT_TABLE(CharControl, wxWindow)
EVT_SIZE(CharControl::OnSize)
EVT_SPIN(ID_SKIN_COLOR, CharControl::OnSpin)
EVT_SPIN(ID_FACE_TYPE, CharControl::OnSpin)
EVT_SPIN(ID_HAIR_COLOR, CharControl::OnSpin)
EVT_SPIN(ID_HAIR_STYLE, CharControl::OnSpin)
EVT_SPIN(ID_FACIAL_HAIR, CharControl::OnSpin)
EVT_SPIN(ID_FACIAL_COLOR, CharControl::OnSpin)
EVT_SPIN(ID_TABARD_ICON, CharControl::OnTabardSpin)
EVT_SPIN(ID_TABARD_ICONCOLOR, CharControl::OnTabardSpin)
EVT_SPIN(ID_TABARD_BORDER, CharControl::OnTabardSpin)
EVT_SPIN(ID_TABARD_BORDERCOLOR, CharControl::OnTabardSpin)
EVT_SPIN(ID_TABARD_BACKGROUND, CharControl::OnTabardSpin)
/*
EVT_CHECKBOX(ID_SHOW_UNDERWEAR, CharControl::OnCheck)
EVT_CHECKBOX(ID_SHOW_EARS, CharControl::OnCheck)
EVT_CHECKBOX(ID_SHOW_HAIR, CharControl::OnCheck)
EVT_BUTTON(ID_SAVE_EQUIPMENT, CharControl::OnButton)
EVT_BUTTON(ID_LOAD_EQUIPMENT, CharControl::OnButton)
EVT_BUTTON(ID_CLEAR_EQUIPMENT, CharControl::OnButton)
EVT_BUTTON(ID_LOAD_SET, CharControl::OnButton)
EVT_BUTTON(ID_LOAD_START, CharControl::OnButton)
*/
EVT_BUTTON(ID_MOUNT, CharControl::OnButton)
EVT_BUTTON(ID_EQUIPMENT + CS_HEAD, CharControl::OnButton)
EVT_BUTTON(ID_EQUIPMENT + CS_NECK, CharControl::OnButton)
EVT_BUTTON(ID_EQUIPMENT + CS_SHOULDER, CharControl::OnButton)
EVT_BUTTON(ID_EQUIPMENT + CS_SHIRT, CharControl::OnButton)
EVT_BUTTON(ID_EQUIPMENT + CS_CHEST, CharControl::OnButton)
EVT_BUTTON(ID_EQUIPMENT + CS_BELT, CharControl::OnButton)
EVT_BUTTON(ID_EQUIPMENT + CS_PANTS, CharControl::OnButton)
EVT_BUTTON(ID_EQUIPMENT + CS_BOOTS, CharControl::OnButton)
EVT_BUTTON(ID_EQUIPMENT + CS_BRACERS, CharControl::OnButton)
EVT_BUTTON(ID_EQUIPMENT + CS_GLOVES, CharControl::OnButton)
EVT_BUTTON(ID_EQUIPMENT + CS_CAPE, CharControl::OnButton)
EVT_BUTTON(ID_EQUIPMENT + CS_HAND_RIGHT, CharControl::OnButton)
EVT_BUTTON(ID_EQUIPMENT + CS_HAND_LEFT, CharControl::OnButton)
EVT_BUTTON(ID_EQUIPMENT + CS_TABARD, CharControl::OnButton)
END_EVENT_TABLE()
CharControl::CharControl(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size)
//:items("items.csv")
{
// If they are using the Test Patch and a test item list exist, use it instead.
if(useTestPatch && wxFile::Exists("testitems.csv"))
items.open("testitems.csv");
else
items.open("items.csv");
if(Create(parent, id, pos, size, 0, _T("CharControlFrame")) == false) {
wxMessageBox("Failed to create a window frame for the Character Control!", "Error");
wxLogMessage("Failed to create a window frame for the Character Control!");
return;
}
wxFlexGridSizer *top = new wxFlexGridSizer(1);
top->AddGrowableCol(0);
wxGridSizer *gs = new wxGridSizer(2, 5, 5);
#define ADD_CONTROLS(type, id, caption) \
gs->Add(new wxStaticText(this, -1, caption), wxSizerFlags().Align(wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL)); \
gs->Add(spins[type] = new wxSpinButton(this, id, wxDefaultPosition, wxDefaultSize, wxSP_HORIZONTAL|wxSP_WRAP), wxSizerFlags(1).Align(wxALIGN_CENTER_VERTICAL));
ADD_CONTROLS(SPIN_SKIN_COLOR, ID_SKIN_COLOR, _("Skin color"))
ADD_CONTROLS(SPIN_FACE_TYPE, ID_FACE_TYPE, _("Face type"))
ADD_CONTROLS(SPIN_HAIR_COLOR, ID_HAIR_COLOR, _("Hair color"))
ADD_CONTROLS(SPIN_HAIR_STYLE, ID_HAIR_STYLE, _("Hair style"))
ADD_CONTROLS(SPIN_FACIAL_HAIR, ID_FACIAL_HAIR, _("Facial hair/deco"))
ADD_CONTROLS(SPIN_FACIAL_COLOR, ID_FACIAL_COLOR, _("Facial deco color"))
#undef ADD_CONTROLS
top->Add(gs,wxSizerFlags().Proportion(1).Expand().Border(wxALL, 10));
for (int i=0; i<NUM_CHAR_SLOTS; i++) {
buttons[i] = NULL;
labels[i] = NULL;
}
top->Add(new wxStaticText(this, -1, _T("Equipment"), wxDefaultPosition, wxSize(200,20), wxALIGN_CENTRE), wxSizerFlags().Border(wxTOP, 10));
wxFlexGridSizer *gs2 = new wxFlexGridSizer(2, 5, 5);
gs2->AddGrowableCol(1);
#define ADD_CONTROLS(type, caption) \
gs2->Add(buttons[type]=new wxButton(this, ID_EQUIPMENT + type, caption), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL)); \
gs2->Add(labels[type]=new wxStaticText(this, -1, _("---- None ----")), wxSizerFlags().Proportion(1).Expand().Align(wxALIGN_CENTER_VERTICAL).Border(wxRIGHT, 10));
ADD_CONTROLS(CS_HEAD, _("Head"))
//ADD_CONTROLS(CS_NECK, _T("Neck"))
ADD_CONTROLS(CS_SHOULDER, _("Shoulder"))
ADD_CONTROLS(CS_SHIRT, _("Shirt"))
ADD_CONTROLS(CS_CHEST, _("Chest"))
ADD_CONTROLS(CS_BELT, _("Belt"))
ADD_CONTROLS(CS_PANTS, _("Legs"))
ADD_CONTROLS(CS_BOOTS, _("Boots"))
ADD_CONTROLS(CS_BRACERS, _("Bracers"))
ADD_CONTROLS(CS_GLOVES, _("Gloves"))
ADD_CONTROLS(CS_CAPE, _("Cape"))
ADD_CONTROLS(CS_HAND_RIGHT, _("Right hand"))
ADD_CONTROLS(CS_HAND_LEFT, _("Left hand"))
ADD_CONTROLS(CS_TABARD, _("Tabard"))
#undef ADD_CONTROLS
top->Add(gs2, wxEXPAND);
// Create our tabard customisation spin buttons
wxGridSizer *gs3 = new wxGridSizer(2, 5, 5);
#define ADD_CONTROLS(type, id, caption) \
gs3->Add(new wxStaticText(this, -1, caption), wxSizerFlags().Align(wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL)); \
gs3->Add(tabardSpins[type]=new wxSpinButton(this, id, wxDefaultPosition, wxDefaultSize, wxSP_HORIZONTAL|wxSP_WRAP), wxSizerFlags(1).Align(wxALIGN_CENTER_VERTICAL));
ADD_CONTROLS(SPIN_TABARD_ICON, ID_TABARD_ICON, _("Icon"))
ADD_CONTROLS(SPIN_TABARD_ICONCOLOR, ID_TABARD_ICONCOLOR, _("Icon Color"))
ADD_CONTROLS(SPIN_TABARD_BORDER, ID_TABARD_BORDER, _("Border"))
ADD_CONTROLS(SPIN_TABARD_BORDERCOLOR, ID_TABARD_BORDERCOLOR, _("Border Color"))
ADD_CONTROLS(SPIN_TABARD_BACKGROUND, ID_TABARD_BACKGROUND, _("Background Color"))
#undef ADD_CONTROLS
top->Add(new wxStaticText(this, -1, _("Tabard details")), wxSizerFlags().Align(wxALIGN_CENTRE).Border(wxALL, 1));
top->Add(gs3, wxEXPAND);
top->Add(new wxButton(this, ID_MOUNT, _("Choose mount")), wxSizerFlags().Align(wxALIGN_CENTRE).Border(wxTOP, 15));
//p->SetSizer(top);
top->SetSizeHints(this);
Show(true);
SetAutoLayout(true);
SetSizer(top);
Layout();
randomLooks = true;
choosingSlot = 0;
itemDialog = 0;
}
CharControl::~CharControl()
{
// unload whatever we need to
}
void CharControl::OnSize(wxSizeEvent &event)
{
//p->SetSize(this->GetSize());
}
bool CharControl::Init()
{
chartex = 0;
hairtex = 0;
furtex = 0;
capetex = 0;
gobtex = 0;
td.showCustom = false;
bSheathe = false;
cd.useNPC = 0;
cd.showEars = true;
cd.showHair = true;
cd.showFacialHair = true;
cd.showUnderwear = true;
// set max values for custom tabard
td.maxBackground = 50;
td.maxBorder = 9;
td.maxBorderColor = 16;
td.maxIcon = 169;
td.maxIconColor = 16;
if(!hairdb.open()) return false;
if(!chardb.open()) return false;
if(!racedb.open()) return false;
if(!classdb.open()) return false;
if(!facialhairdb.open()) return false;
if(!itemdb.open()) return false;
if(!visualdb.open()) return false;
if(!effectdb.open()) return false;
if(!subclassdb.open()) return false;
if(!sets.open()) return false;
if(!start.open()) return false;
//if(!helmetdb.open()) return false;
if(!npcdb.open()) return false;
items.cleanup(itemdb);
sets.cleanup(items);
return true;
}
//void CharControl::UpdateModel(Model *m)
void CharControl::UpdateModel(Attachment *a)
{
charAtt = a;
model = (Model*)a->model;
if (chartex==0)
glGenTextures(1, &chartex);
cd.reset();
td.showCustom = false;
// hide most geosets
for (size_t i=0; i<model->geosets.size(); i++) {
int id = model->geosets[i].id;
model->showGeosets[i] = (id==0);
}
size_t p1 = model->name.find_first_of('\\', 0);
size_t p2 = model->name.find_first_of('\\', p1+1);
size_t p3 = model->name.find_first_of('\\', p2+1);
std::string raceName = model->name.substr(p1+1,p2-p1-1);
std::string genderName = model->name.substr(p2+1,p3-p2-1);
int race, gender;
try {
CharRacesDB::Record raceRec = racedb.getByName(raceName.c_str());
race = raceRec.getUInt(CharRacesDB::RaceID);
gender = (genderName == "Female") ? 1 : 0;
} catch (CharRacesDB::NotFound) {
// wtf
race = 0;
gender = 0;
}
// get max values
cd.maxSkinColor = chardb.getColorsFor(race, gender, CharSectionsDB::SkinType, 0, cd.useNPC);
if (cd.maxSkinColor == 0) {
wxMessageBox("The selected character does not have any NPC skins!\nSwitching back to normal character skins.");
cd.useNPC = 0;
cd.maxSkinColor = chardb.getColorsFor(race, gender, CharSectionsDB::SkinType, 0, cd.useNPC);
}
cd.maxFaceType = chardb.getSectionsFor(race, gender, CharSectionsDB::FaceType, 0, cd.useNPC);
cd.maxHairColor = chardb.getColorsFor(race, gender, CharSectionsDB::HairType, 0, 0);
cd.maxFacialHair = facialhairdb.getStylesFor(race, gender);
cd.maxFacialColor = cd.maxHairColor;
if (cd.useNPC)
modelViewer->optMenu->Check(ID_USENPCSKINS, 1);
else
modelViewer->optMenu->Check(ID_USENPCSKINS, 0);
cd.race = race;
cd.gender = gender;
std::set<int> styles;
for (CharHairGeosetsDB::Iterator it = hairdb.begin(); it != hairdb.end(); ++it) {
if (it->getUInt(CharHairGeosetsDB::Race)==race && it->getUInt(CharHairGeosetsDB::Gender)==gender) {
styles.insert(it->getUInt(CharHairGeosetsDB::Section));
}
}
cd.maxHairStyle = (int)styles.size();
if (cd.maxFaceType==0) cd.maxFaceType = 1;
if (cd.maxSkinColor==0) cd.maxSkinColor = 1;
if (cd.maxHairColor==0) cd.maxHairColor = 1;
if (cd.maxHairStyle==0) cd.maxHairStyle = 1;
if (cd.maxFacialHair==0) cd.maxFacialHair = 1;
spins[0]->SetRange(0, cd.maxSkinColor-1);
spins[1]->SetRange(0, cd.maxFaceType-1);
spins[2]->SetRange(0, cd.maxHairColor-1);
spins[3]->SetRange(0, cd.maxHairStyle-1);
spins[4]->SetRange(0, cd.maxFacialHair-1);
spins[5]->SetRange(0, cd.maxHairColor-1);
if (randomLooks) {
// Choose random values for the looks! ^_^
cd.skinColor = randint(0, cd.maxSkinColor-1);
cd.faceType = randint(0, cd.maxFaceType-1);
cd.hairColor = randint(0, cd.maxHairColor-1);
cd.hairStyle = randint(0, cd.maxHairStyle-1);
cd.facialHair = randint(0, cd.maxFacialHair-1);
cd.facialColor = cd.hairColor;
}
td.Icon = randint(0, td.maxIcon);
td.IconColor = randint(0, td.maxIconColor);
td.Border = randint(0, td.maxBorder);
td.BorderColor = 0;
td.Background = randint(0, td.maxBackground);
spins[SPIN_SKIN_COLOR]->SetValue(cd.skinColor);
spins[SPIN_FACE_TYPE]->SetValue(cd.faceType);
spins[SPIN_HAIR_COLOR]->SetValue(cd.hairColor);
spins[SPIN_HAIR_STYLE]->SetValue(cd.hairStyle);
spins[SPIN_FACIAL_HAIR]->SetValue(cd.facialHair);
spins[SPIN_FACIAL_COLOR]->SetValue(cd.facialColor);
tabardSpins[SPIN_TABARD_ICON]->SetValue(td.Icon);
tabardSpins[SPIN_TABARD_ICONCOLOR]->SetValue(td.IconColor);
tabardSpins[SPIN_TABARD_BORDER]->SetValue(td.Border);
tabardSpins[SPIN_TABARD_BORDERCOLOR]->SetValue(td.BorderColor);
tabardSpins[SPIN_TABARD_BACKGROUND]->SetValue(td.Background);
tabardSpins[SPIN_TABARD_ICON]->SetRange(0, td.maxIcon);
tabardSpins[SPIN_TABARD_ICONCOLOR]->SetRange(0, td.maxIconColor);
tabardSpins[SPIN_TABARD_BORDER]->SetRange(0, td.maxBorder);
tabardSpins[SPIN_TABARD_BORDERCOLOR]->SetRange(0, td.maxBorderColor);
tabardSpins[SPIN_TABARD_BACKGROUND]->SetRange(0, td.maxBackground);
for (int i=0; i<NUM_SPIN_BTNS; i++) spins[i]->Refresh(false);
for (int i=0; i<NUM_TABARD_BTNS; i++) tabardSpins[i]->Refresh(false);
for (int i=0; i<NUM_CHAR_SLOTS; i++) {
if (labels[i]) labels[i]->SetLabel(_T("---- None ----"));
}
// HACK: for goblin males, explicitly load a hair texture
if (race==9 && gender==0) {
gobtex = texturemanager.add("Creature\\Goblin\\Goblin.blp");
} else {
if (gobtex) texturemanager.del(gobtex);
gobtex = 0;
}
RefreshModel();
}
void CharControl::UpdateNPCModel(Attachment *a, unsigned int id)
{
charAtt = a;
Model *m = (Model*)a->model;
model = m;
if (chartex==0)
glGenTextures(1, &chartex);
cd.reset();
td.showCustom = false;
// hide most geosets
for (size_t i=0; i<model->geosets.size(); i++) {
int id = model->geosets[i].id;
model->showGeosets[i] = (id==0);
}
size_t p1 = m->name.find_first_of('\\', 0);
size_t p2 = m->name.find_first_of('\\', p1+1);
size_t p3 = m->name.find_first_of('\\', p2+1);
std::string raceName = m->name.substr(p1+1,p2-p1-1);
std::string genderName = m->name.substr(p2+1,p3-p2-1);
int race, gender;
try {
CharRacesDB::Record raceRec = racedb.getByName(raceName.c_str());
race = raceRec.getUInt(CharRacesDB::RaceID);
gender = (genderName == "Female") ? 1 : 0;
} catch (CharRacesDB::NotFound) {
// wtf
race = 0;
gender = 0;
}
cd.race = race;
cd.gender = gender;
NPCDB::Record npcrec = npcdb.getByNPCID(id);
// facial hair geosets
try {
cd.hairColor = npcrec.getUInt(NPCDB::HairColor);
cd.hairStyle = npcrec.getUInt(NPCDB::HairStyle);
cd.facialHair = npcrec.getUInt(NPCDB::FacialHair);
cd.facialColor = cd.hairColor;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -