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

📄 charcontrol.cpp

📁 wowmodelview魔兽世界的模型查看工具。下了看看吧
💻 CPP
📖 第 1 页 / 共 5 页
字号:

	numbers.clear();
	choices.Clear();
	cats.clear();
	catnames.Clear();
	catnames.Add("Known ridable models");
	catnames.Add("Other models");

	static bool filelistInitialized = false;

	if (!filelistInitialized) {
		set<string> filelist;

		//#ifdef _WIN32
			hash_set<string> knownRidable;
		//#else
		//	__gnu_cxx::hash_set<std::string> knownRidable;
		//#endif

		getFileLists(filelist, filterCreatures);

		FILE *f = fopen("ridable.csv","r");
		if (f) {
			wxString tmp;
			while (!feof(f)) {
				char buf[1024];
				fgets(buf, 1024, f);
				size_t l = strlen(buf);
				if (buf[l-1]=='\n') 
					buf[l-1]=0;
				tmp = buf;
				tmp.LowerCase();
				knownRidable.insert(tmp.c_str());
				//creaturemodels.push_back(string(buf));
			}
		}
		
		for (set<string>::iterator it = filelist.begin(); it != filelist.end(); ++it) {
			wxString str(*it);
			creaturemodels.push_back(str);
			str.MakeLower();
			ridablelist.push_back(knownRidable.find(str)!=knownRidable.end());
		}
		filelistInitialized = true;
	}

	choices.Add("---- None ----");
	cats.push_back(0);
	
	for (size_t i=0; i<creaturemodels.size(); i++) {
		choices.Add(wxString(creaturemodels[i].c_str() + 9, *wxConvCurrent));
		cats.push_back(ridablelist[i]?0:1);
	}

	// TODO: obtain a list of "known ridable" models, and filter the list into two categories
	itemDialog = new FilteredChoiceDialog(this, UPDATE_MOUNT, canvas->GetParent(), _T("Choose a mount"), _T("Creatures"), choices);
	CategoryChoiceDialog *itemDialog = new CategoryChoiceDialog(this, UPDATE_MOUNT, canvas->GetParent(), _T("Choose a mount"), _T("Creatures"), choices, cats, catnames);
	itemDialog->Move(itemDialog->GetParent()->GetPosition() + wxPoint(4,64));
	itemDialog->Check(1, false);
	itemDialog->DoFilter();
	itemDialog->Show();

	// TODO: figure out why the damn dialog is so big and ugly
	const int w = 250;
	itemDialog->SetSizeHints(w,-1,-1,-1,-1,-1);
	itemDialog->SetSize(w, -1); 
	this->itemDialog = itemDialog;
#endif
}

void CharControl::OnUpdateItem(int type, int id)
{
	switch (type) {
	case UPDATE_ITEM:
		cd.equipment[choosingSlot] = numbers[id];
		if (slotHasModel(choosingSlot))
			RefreshItem(choosingSlot);
		labels[choosingSlot]->SetLabel(wxString(items.get(cd.equipment[choosingSlot]).name.c_str(), *wxConvCurrent));

		// Check if its a 'guild tabard'
		if (choosingSlot == CS_TABARD) 
			td.showCustom = (labels[choosingSlot]->GetLabel() == "Guild Tabard");

		break;
	case UPDATE_SET:
		id = numbers[id];
		if (id) {
			for (int i=0; i<NUM_CHAR_SLOTS; i++) {
				if (i!=CS_HAND_LEFT && i!=CS_HAND_RIGHT) cd.equipment[i] = 0;
			}
			cd.loadSet(sets, items, id);
			RefreshEquipment();
		}
		break;
	case UPDATE_START:
		id = numbers[id];
		if (id) {
			for (int i=0; i<NUM_CHAR_SLOTS; i++) cd.equipment[i] = 0;
			cd.loadStart(start, items, id);
			RefreshEquipment();
		}
		break;
	case UPDATE_MOUNT:
		if (canvas->root->model) {
			delete canvas->root->model;
			canvas->root->model = 0;
			canvas->model = 0;
		}

		if (id == 0) {
			// clearing the mount
			modelViewer->animControl->UpdateModel(model);
			model->isMounted = false;
			canvas->model = model;
			canvas->ResetView();
			charAtt->scale = canvas->root->scale;
			charAtt->id = 0;
		} else {
			//wxString fn(creaturemodels[id-1].c_str());
			Model *m = new Model(creaturemodels[id-1], true);

			// TODO: check if model is ridable
			canvas->root->model = m;
			canvas->model = m;
			modelViewer->animControl->UpdateModel(m);
			for (size_t i=0; i<model->header.nAnimations; i++) {
				if (model->anims[i].animID == 91) {
					model->animManager->Stop();
					model->currentAnim = (int)i;
					model->animManager->Set(0,(short)i,0);
					break;
				}
			}
			
			//model->currentAnim = 132;

			charAtt->parent = canvas->root;
			model->isMounted = true;
			//charAtt->id = 42;

			// Need to set this - but from what
			// Model data doesn't contain sizes for different race/gender
			// Character data doesn't contain sizes for different mounts
			// possibly some formula that from both models that needs to be calculated.
			// For "Taxi" mounts scale should be 1.0f I think, for now I'll ignore them
			// I really have no idea!  
			if(creaturemodels[id-1].substr(9,9) == "Kodobeast")
				charAtt->scale = 2.25f;
			else
				charAtt->scale = 1.0f;
			
			//Model *mChar = static_cast<Model*>(charAtt->model);
			//charAtt->scale = m->rad / mChar->rad;

			// Human Male = 2.0346599
			// NE Male = 2.5721216
			// NE Female = 2.2764397

			// RidingFrostSaber = 2.4360743
			// 1.00000

			//canvas->root->scale = 0.5f;
			//Attachment *att = charAtt->addChild("World\\ArtTest\\Boxtest\\xyz.m2", 24, -1);
			//m-> = att->scale;
			//delete att;

			canvas->ResetView();
			canvas->vRot.x = 0; // mounted characters look better from the side
		}
		break;

	case UPDATE_CREATURE_ITEM:
		cd.equipment[choosingSlot] = numbers[id];
		RefreshCreatureItem(choosingSlot);
		
		return;
	}

	if (canvas->modelType == MT_NPC)
		RefreshNPCModel();
	else
		RefreshModel();
}

void CharControl::OnTabardSpin(wxSpinEvent &event)
{
	if (canvas->modelType == MT_NPC)
		return;

	switch (event.GetId())
	{
	case ID_TABARD_ICON:
		td.Icon = event.GetPosition();
		break;
	case ID_TABARD_ICONCOLOR:
		td.IconColor = event.GetPosition();
		break;
	case ID_TABARD_BORDER:
        td.Border = event.GetPosition();
		if (td.Border > 5)
		{
			td.BorderColor = 0;
			tabardSpins[SPIN_TABARD_BORDERCOLOR]->SetValue(0);
			tabardSpins[SPIN_TABARD_BORDERCOLOR]->SetRange(0, 3);
		}
		else
			tabardSpins[SPIN_TABARD_BORDERCOLOR]->SetRange(0, 16);
		break;
	case ID_TABARD_BORDERCOLOR:
		td.BorderColor = event.GetPosition();
		break;
	case ID_TABARD_BACKGROUND:
		td.Background = event.GetPosition();
		break;
	}

	RefreshModel();
}

string TabardDetails::GetBackgroundTex(int slot)
{
	ostringstream tmpStream;

	string tmpU = "textures\\GuildEmblems\\Background_";
	if (Background < 10)
		tmpU += "0";
	tmpStream << Background;
	tmpU += tmpStream.str();
	tmpU += "_TU_U.blp";
	
	string tmpL = tmpU;
	tmpL[37] = 'L';

	if (slot == CR_TORSO_UPPER)
		return tmpU;
	else
		return tmpL;
}

string TabardDetails::GetBorderTex(int slot)
{
	ostringstream tmpStream;

	string tmpU = "textures\\GuildEmblems\\Border_";

	if (Border < 10)
		tmpU += "0";
	tmpStream << Border << "_";
	tmpU += tmpStream.str();
	tmpStream.flush();
	tmpStream.str("");

	if (BorderColor < 10)
		tmpU += "0";
	tmpStream << BorderColor;
	tmpU += tmpStream.str();

	tmpU += "_TU_U.blp";
	
	string tmpL = tmpU;
	tmpL[36] = 'L';

	if (slot == CR_TORSO_UPPER)
		return tmpU;
	else
		return tmpL;
}

string TabardDetails::GetIconTex(int slot)
{
	ostringstream tmpStream;

	string tmpU = "textures\\GuildEmblems\\Emblem_";

	if(Icon < 10)
		tmpU += "0";
	tmpStream << Icon << "_";
	tmpU += tmpStream.str();
	tmpStream.flush();
	tmpStream.str("");

	if(IconColor < 10)
		tmpU += "0";
	tmpStream << IconColor;
	tmpU += tmpStream.str();

	tmpU += "_TU_U.blp";
	
	string tmpL = tmpU;
	tmpL[tmpU.length() - 7] = 'L';

	if(slot == CR_TORSO_UPPER)
		return tmpU;
	else
		return tmpL;
}

void CharDetails::save(wxString fn, TabardDetails *td)
{
	// TODO: save/load as xml?
	// wx/xml/xml.h says the api will change, do not use etc etc.

	ofstream f(fn.fn_str(), ios_base::out|ios_base::trunc);
	f << race << " " << gender << endl;
	f << skinColor << " " << faceType << " " << hairColor << " " << hairStyle << " " << facialHair << " " << facialColor << endl;
	for (int i=0; i<NUM_CHAR_SLOTS; i++) {
		f << equipment[i] << endl;
	}

	// 5976 is the ID value for "Guild Tabard"
	if (equipment[CS_TABARD] == 5976) {
		f << td->Background << " " << td->Border << " " << td->BorderColor << " " << td->Icon << " " << td->IconColor << endl;
	}
	f.close();
}

bool CharDetails::load(wxString fn, TabardDetails *td)
{
	int r, g;
	ifstream f(fn.fn_str());
	f >> r >> g;
	bool same = false;
	if (r==race && g==gender) {
		f >> skinColor >> faceType >> hairColor >> hairStyle >> facialHair >> facialColor;
		same = true;
	} else {
		int dummy;
		for (int i=0; i<6; i++) f >> dummy;
	}
	for (int i=0; i<NUM_CHAR_SLOTS; i++) {
		f >> equipment[i];
	}

	// 5976 is the ID value for "Guild Tabard"
	if (equipment[CS_TABARD] == 5976 && !f.eof()) {
		f >> td->Background >> td->Border >> td->BorderColor >> td->Icon >> td->IconColor;
		td->showCustom = true;
	}

	f.close();
	return same;
}

void CharDetails::loadSet(ItemSetDB &sets, ItemDatabase &items, int setid)
{
	try {
		ItemSetDB::Record rec = sets.getById(setid);
		for (size_t i=0; i<ItemSetDB::NumItems; i++) {
			int id = rec.getInt(ItemSetDB::ItemIDBase + i);
			if (id==0) continue;
			const ItemRecord &r = items.get(id);
			if (r.type > 0) {
				// find a slot for it
				for (int s=0; s<NUM_CHAR_SLOTS; s++) {
					if (correctType(r.type, s)) {
						equipment[s] = id;
						break;
					}
				}
			}
		}
	} catch (ItemSetDB::NotFound) {}
}

void CharDetails::loadStart(StartOutfitDB &start, ItemDatabase &items, int setid)
{
	try {
		StartOutfitDB::Record rec = start.getById(setid);
		for (size_t i=0; i<StartOutfitDB::NumItems; i++) {
			int id = rec.getInt(StartOutfitDB::ItemIDBase + i);
			if (id==0) continue;
			const ItemRecord &r = items.get(id);
			if (r.type > 0) {
				// find a slot for it
				for (int s=0; s<NUM_CHAR_SLOTS; s++) {
					if (correctType(r.type, s)) {
						equipment[s] = id;
						break;
					}
				}
			}
		}
	} catch (ItemSetDB::NotFound) {}
}

const std::string CharControl::selectCharModel()
{
	wxArrayString arr;
	std::vector<int> ids;
	for (CharRacesDB::Iterator it = racedb.begin(); it != racedb.end(); ++it) {
		char buf[64];
		sprintf(buf,"%s Male", it->getString(CharRacesDB::FullName));
		arr.Add(buf);
		sprintf(buf,"%s Female", it->getString(CharRacesDB::FullName));
		arr.Add(buf);
		ids.push_back(it->getInt(CharRacesDB::RaceID));
	}
	wxSingleChoiceDialog dialog(this, _T("Choose a character model"), _T("Races"), arr);
	if (dialog.ShowModal() == wxID_OK) {
		int sel = dialog.GetSelection();
		int raceid = ids[sel >> 1];
		int gender = sel & 1;
		string genderStr = gender ? "Female" : "Male";
		try {
			CharRacesDB::Record r = racedb.getById(raceid);
			std::string path = "Character\\";
			path += r.getString(CharRacesDB::Name);
			path += "\\" + genderStr + "\\";
			path += r.getString(CharRacesDB::Name);
			path += genderStr + ".m2";
			return path;
		} catch (CharRacesDB::NotFound) {
			return ""; // wtf
		}
	}
	return "";
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -