⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 charcontrol.cpp

📁 wowmodelview魔兽世界的模型查看工具。下了看看吧
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// 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 + -