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

📄 mpqwindow.cpp

📁 骨骼动画....把魔兽模型解出的代码..
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//+-----------------------------------------------------------------------------
BOOL MPQ_WINDOW::CloseMpq()
{
	RemoveFileTree(&RootNode);
	Mpq.Close();

	MpqLoaded = FALSE;
	MpqFileName = "";

	UpdateTreeView();
	UpdateWindowStatus();

	return TRUE;
}


//+-----------------------------------------------------------------------------
//| Updates the window status
//+-----------------------------------------------------------------------------
VOID MPQ_WINDOW::UpdateWindowStatus()
{
	std::string Title;

	GrayMenuItem(MpqFileClose, !MpqLoaded);

	Title = EDITOR_MPQ_NAME;
	if(MpqLoaded) Title += (" (" + Common.GetFileName(MpqFileName) + ")");

	SetText(Title);
}


//+-----------------------------------------------------------------------------
//| Opens a file from the mpq archive
//+-----------------------------------------------------------------------------
BOOL MPQ_WINDOW::OpenMpqFile(CONST std::string& FileName)
{
	BUFFER Buffer;
	SHELLEXECUTEINFO Info;
	std::string Extention;
	std::string TempFileName;

	Extention = Common.LowerCase(Common.GetExtention(FileName));

	if(InvalidExtention(Extention))
	{
		Error.SetMessage("This file cannot be opened from here!\nExport it first then open it!");
		return FALSE;
	}
	else if(ModelExtention(Extention))
	{
		BUFFER Buffer;

		if(!Mpq.LoadFile(FileName, Buffer)) return FALSE;
		if(!MainWindow.LoadFileFromBuffer(FileName, Buffer)) return FALSE;

		MainWindow.MakeModelNeverSaved();

		return TRUE;
	}
	else if(TextureExtention(Extention))
	{
		BUFFER Buffer;

		if(!Mpq.LoadFile(FileName, Buffer)) return FALSE;
		if(!MainWindow.LoadFileFromBuffer(FileName, Buffer)) return FALSE;

		MainWindow.MakeModelNeverSaved();

		return TRUE;
	}

	TempFileName = TemporaryFile.GetTemporaryDirectory() + "\\" + Common.GetFileName(FileName);

	if(!Mpq.LoadFile(FileName, Buffer)) return FALSE;
	if(!TemporaryFile.CreateTemporaryFile(TempFileName, Buffer)) return FALSE;

	ZeroMemory(&Info, sizeof(SHELLEXECUTEINFO));
	Info.cbSize = sizeof(SHELLEXECUTEINFO);
	Info.fMask = SEE_MASK_NOCLOSEPROCESS;
	Info.hwnd = Window;
	Info.lpVerb = "open";
	Info.lpFile = TempFileName.c_str();
	Info.hInstApp = GetModuleHandle(NULL);
	Info.nShow = SW_SHOW;

	if(ScriptExtention(Extention) || (FileName == PATH_LISTFILE))
	{
		Info.lpFile = "Notepad";
		Info.lpParameters = TempFileName.c_str();
	}

	if(!ShellExecuteEx(&Info))
	{
		Error.SetMessage("Unable to open \"" + TempFileName + "\"!\nProbably an unassociated extention!");
		TemporaryFile.DestroyTemporaryFile(TempFileName);
		return FALSE;
	}

	if(Info.hProcess == NULL) return TRUE;

	if(!TemporaryFile.LaunchThread(new FILE_PROCESS(Info.hProcess, TempFileName)))
	{
		TemporaryFile.DestroyTemporaryFile(TempFileName);
		return FALSE;
	}

	return TRUE;
}


//+-----------------------------------------------------------------------------
//| Exports a file from the mpq archive
//+-----------------------------------------------------------------------------
BOOL MPQ_WINDOW::ExportMpqFile(CONST std::string& FileName, CONST std::string& RealFileName)
{
	BUFFER Buffer;

	if(!Mpq.LoadFile(FileName, Buffer)) return FALSE;
	if(!FileLoader.SaveToFile(RealFileName, Buffer)) return FALSE;

	return TRUE;
}


//+-----------------------------------------------------------------------------
//| Updates the treeview
//+-----------------------------------------------------------------------------
VOID MPQ_WINDOW::UpdateTreeView()
{
	FILE_NODE* CurrentNode;
	FILE_NODE* CurrentChildNode;
	TVINSERTSTRUCT InsertItem;
	HTREEITEM TreeViewItem;
	std::list<FILE_NODE*> Stack;
	INT FolderIconIndex;
	INT UnknownIconIndex;

	TreeView.Clear();

	InsertItem.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
	InsertItem.item.hItem = NULL;
	InsertItem.item.state = 0;
	InsertItem.item.stateMask = 0;
	InsertItem.item.cChildren = 0;

	FolderIconIndex = Icon.GetFolderIconIndex();
	UnknownIconIndex = Icon.GetUnknownIconIndex();

	RootNode.TreeViewItem = TVI_ROOT;
	Stack.push_back(&RootNode);

	while(Stack.size() > 0)
	{
		CurrentNode = Stack.back();
		Stack.pop_back();

		if(!Filter.ValidFilter(CurrentNode->FilterData)) continue;

		CurrentChildNode = CurrentNode->FileConnection.FirstChildNode;
		while(CurrentChildNode != NULL)
		{
			Stack.push_back(CurrentChildNode);
			CurrentChildNode = CurrentChildNode->NextNode;
		}

		CurrentChildNode = CurrentNode->FolderConnection.FirstChildNode;
		while(CurrentChildNode != NULL)
		{
			Stack.push_back(CurrentChildNode);
			CurrentChildNode = CurrentChildNode->NextNode;
		}

		if(CurrentNode == &RootNode) continue;

		InsertItem.item.pszText = const_cast<CHAR*>(CurrentNode->FileName.c_str());
		InsertItem.item.cchTextMax = static_cast<INT>(CurrentNode->FileName.size());
		InsertItem.item.iImage = (CurrentNode->IsFolder ? FolderIconIndex : Icon.GetIconIndex(CurrentNode->Extention));
		InsertItem.item.iSelectedImage = InsertItem.item.iImage;
		InsertItem.item.lParam = reinterpret_cast<LPARAM>(CurrentNode);
		InsertItem.hParent = CurrentNode->ParentNode->TreeViewItem;
		InsertItem.hInsertAfter = TVI_LAST;

		TreeViewItem = TreeView_InsertItem(TreeView.GetWindow(), &InsertItem);
		if(TreeViewItem == NULL) continue;

		CurrentNode->TreeViewItem = TreeViewItem;
	}

	CurrentlySelectedFile = NULL;
	CurrentlySelectedPopupFile = NULL;
}


//+-----------------------------------------------------------------------------
//| Resizes the treeview
//+-----------------------------------------------------------------------------
VOID MPQ_WINDOW::ResizeTreeView()
{
	TreeView.SetDimension(GetWidth(), GetHeight());
}


//+-----------------------------------------------------------------------------
//| Loads the listfile from the mpq (or from a custom listfile)
//+-----------------------------------------------------------------------------
BOOL MPQ_WINDOW::LoadListFile(CONST std::string& FileName)
{
	std::string Name;
	std::ifstream File;
	std::string ListFileName;
	BOOL UseCustomListFile = TRUE;
	std::list<std::string> FileList;
	std::list<std::string>::iterator i;

	Filter.BuildFilter(RootNode.FilterData, "");
	ListFileName = Common.GetProgramDirectory() + "\\" + PATH_LIST_FILES + Common.GetName(FileName) + ".txt";

	File.open(ListFileName.c_str(), std::ios::in);
	if(File.fail()) UseCustomListFile = FALSE;

	if(UseCustomListFile)
	{
		while(!File.eof())
		{
			Name = "";
			std::getline(File, Name);

			Common.RemoveWhiteSpace(Name);
			if(Name != "")
			{
				if(!AddFileToFileTree(Name)) return FALSE;
			}
		}
	}
	else
	{
		Mpq.GetFileList(FileList);

		i = FileList.begin();
		while(i != FileList.end())
		{
			Name = (*i);

			Common.RemoveWhiteSpace(Name);
			if(Name != "")
			{
				if(!AddFileToFileTree(Name)) return FALSE;
			}

			i++;
		}
	}

	return TRUE;
}


//+-----------------------------------------------------------------------------
//| Adds a file to the file tree
//+-----------------------------------------------------------------------------
BOOL MPQ_WINDOW::AddFileToFileTree(CONST std::string& FileName)
{
	std::string Name;
	std::list<std::string> PathList;
	std::list<std::string>::iterator i;
	FILE_NODE* NewNode;
	FILE_NODE* CurrentNode;

	SplitPath(FileName, Name, PathList);

	CurrentNode = &RootNode;

	i = PathList.begin();
	while(i != PathList.end())
	{
		CurrentNode = CreateFolder(CurrentNode, (*i));
		if(CurrentNode == NULL)
		{
			Error.SetMessage("Unable to add \"" + FileName + "\" to the treeview!");
			return FALSE;
		}

		i++;
	}

	NewNode = new FILE_NODE();
	if(NewNode == NULL)
	{
		Error.SetMessage("Unable to add \"" + FileName + "\" to the treeview, memory allocation failed!");
		return FALSE;
	}

	NewNode->FileNameAndPath = FileName;
	NewNode->FileName = Name;
	NewNode->Extention = Common.LowerCase(Common.GetExtention(Name));

	if(NewNode->FileName == PATH_LISTFILE) NewNode->Extention = "txt";

	AddChild(CurrentNode, &CurrentNode->FileConnection, NewNode);

	Filter.BuildFilter(NewNode->FilterData, NewNode->Extention);
	UpdateFilterData(NewNode, NewNode->FilterData);

	return TRUE;
}


//+-----------------------------------------------------------------------------
//| Removes all childs of a file node
//+-----------------------------------------------------------------------------
VOID MPQ_WINDOW::RemoveFileTree(FILE_NODE* FileNode)
{
	FILE_NODE* CurrentNode;
	FILE_NODE* NextNode;

	CurrentNode = FileNode->FileConnection.FirstChildNode;
	while(CurrentNode != NULL)
	{
		NextNode = CurrentNode->NextNode;

		RemoveFileTree(CurrentNode);
		delete CurrentNode;

		CurrentNode = NextNode;
	}

	CurrentNode = FileNode->FolderConnection.FirstChildNode;
	while(CurrentNode != NULL)
	{
		NextNode = CurrentNode->NextNode;

		RemoveFileTree(CurrentNode);
		delete CurrentNode;

		CurrentNode = NextNode;
	}

	FileNode->FileConnection.FirstChildNode = NULL;
	FileNode->FileConnection.LastChildNode = NULL;
	FileNode->FolderConnection.FirstChildNode = NULL;
	FileNode->FolderConnection.LastChildNode = NULL;
}


//+-----------------------------------------------------------------------------
//| Finds the child of a file node
//+-----------------------------------------------------------------------------
FILE_NODE* MPQ_WINDOW::FindChild(FILE_NODE* FileNode, FILE_NODE_CONNECTION* Connection, CONST std::string& Name)
{
	FILE_NODE* ChildNode;
	std::string LowerCaseName;

	LowerCaseName = Common.LowerCase(Name);

	ChildNode = Connection->FirstChildNode;
	while(ChildNode != NULL)
	{
		if(Common.LowerCase(ChildNode->FileName) == LowerCaseName) return ChildNode;
		ChildNode = ChildNode->NextNode;
	}

	return NULL;
}


//+-----------------------------------------------------------------------------
//| Finds or creates a folder node
//+-----------------------------------------------------------------------------
FILE_NODE* MPQ_WINDOW::CreateFolder(FILE_NODE* FileNode, CONST std::string& Name)
{
	FILE_NODE* ChildNode;

	ChildNode = FindChild(FileNode, &FileNode->FolderConnection, Name);
	if(ChildNode != NULL) return ChildNode;

	ChildNode = new FILE_NODE();
	if(ChildNode == NULL) return NULL;

	ChildNode->IsFolder = TRUE;
	ChildNode->IconCollectionIndex = Icon.GetFolderIconIndex();
	ChildNode->FileName = Name;

	if(ChildNode->FileName != "")
	{
		ChildNode->FileName[0] = std::toupper(ChildNode->FileName[0]);
	}

	Filter.BuildFilter(ChildNode->FilterData, "");

	AddChild(FileNode, &FileNode->FolderConnection, ChildNode);

	return ChildNode;
}


//+-----------------------------------------------------------------------------
//| Adds a child node to a node
//+-----------------------------------------------------------------------------
VOID MPQ_WINDOW::AddChild(FILE_NODE* FileNode, FILE_NODE_CONNECTION* Connection, FILE_NODE* ChildNode)
{
	FILE_NODE* CurrentChildNode;
	std::string ChildNodeName;
	BOOL LocationFound = FALSE;

	ChildNodeName = Common.LowerCase(ChildNode->FileName);

	CurrentChildNode = Connection->FirstChildNode;
	while(CurrentChildNode != NULL)
	{
		if(ChildNodeName > Common.LowerCase(CurrentChildNode->FileName)) break;
		CurrentChildNode = CurrentChildNode->NextNode;
	}

	if(CurrentChildNode != NULL)
	{
		ChildNode->NextNode = CurrentChildNode;
		ChildNode->PreviousNode = CurrentChildNode->PreviousNode;
		ChildNode->ParentNode = FileNode;

		CurrentChildNode->PreviousNode = ChildNode;
		if(ChildNode->PreviousNode) ChildNode->PreviousNode->NextNode = ChildNode;

		if(Connection->FirstChildNode == CurrentChildNode) Connection->FirstChildNode = ChildNode;

		return;
	}

	ChildNode->NextNode = NULL;
	ChildNode->PreviousNode = Connection->LastChildNode;
	ChildNode->ParentNode = FileNode;

	if(Connection->FirstChildNode == NULL) Connection->FirstChildNode = ChildNode;
	if(Connection->LastChildNode != NULL) Connection->LastChildNode->NextNode = ChildNode;
	Connection->LastChildNode = ChildNode;
}


//+-----------------------------------------------------------------------------
//| Updates the node and its parents with the filter data
//+-----------------------------------------------------------------------------
VOID MPQ_WINDOW::UpdateFilterData(FILE_NODE* FileNode, FILTER_DATA& FilterData)
{
	FILE_NODE* CurrentNode;

	CurrentNode = FileNode->ParentNode;
	while(CurrentNode != NULL)
	{
		Filter.ExtendFilter(CurrentNode->FilterData, FileNode->FilterData);
		CurrentNode = CurrentNode->ParentNode;
	}
}


//+-----------------------------------------------------------------------------
//| Splits a path into a list of path parts
//+-----------------------------------------------------------------------------
VOID MPQ_WINDOW::SplitPath(CONST std::string& Path, std::string& FileName, std::list<std::string>& PathList)
{
	INT i;
	std::string TempPath = Path;

	i = static_cast<INT>(TempPath.find("\\"));
	while(i != std::string::npos)
	{
		if(i > 0) PathList.push_back(TempPath.substr(0, i));
		TempPath.erase(0, i + 1);

		i = static_cast<INT>(TempPath.find("\\"));
	}

	FileName = TempPath;
}


//+-----------------------------------------------------------------------------
//| Checks if the extention is invalid
//+-----------------------------------------------------------------------------
BOOL MPQ_WINDOW::InvalidExtention(CONST std::string& Extention)
{
	if(Extention == "exe") return TRUE;
	if(Extention == "dll") return TRUE;
	if(Extention == "w3m") return TRUE;
	if(Extention == "w3x") return TRUE;
	if(Extention == "w3n") return TRUE;
	if(Extention == "w3g") return TRUE;
	if(Extention == "mpq") return TRUE;

	return FALSE;
}


//+-----------------------------------------------------------------------------
//| Checks if the extention is a model
//+-----------------------------------------------------------------------------
BOOL MPQ_WINDOW::ModelExtention(CONST std::string& Extention)
{
	return ResourceLoader.IsModelExtention(Extention);
}


//+-----------------------------------------------------------------------------
//| Checks if the extention is a texture
//+-----------------------------------------------------------------------------
BOOL MPQ_WINDOW::TextureExtention(CONST std::string& Extention)
{
	return ResourceLoader.IsTextureExtention(Extention);
}


//+-----------------------------------------------------------------------------
//| Checks if the extention is a script file
//+-----------------------------------------------------------------------------
BOOL MPQ_WINDOW::ScriptExtention(CONST std::string& Extention)
{
	if(Extention == "ai")  return TRUE;
	if(Extention == "wai") return TRUE;
	if(Extention == "j")   return TRUE;
	if(Extention == "js")  return TRUE;
	if(Extention == "pld") return TRUE;

	return FALSE;
}

⌨️ 快捷键说明

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