mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-12 08:11:10 +02:00
Added modelviewer.
Added neural network code(turned off by default). Lots of editor and rendering fixes.
This commit is contained in:
@@ -139,6 +139,9 @@ protected:
|
||||
// Set textSource possible with compression.
|
||||
void SetTextLocal(const char* text, const int length);
|
||||
|
||||
// Replaces this decl's range in the backing source file with arbitrary text.
|
||||
bool WriteSourceFileText(const char* text, const int length);
|
||||
|
||||
private:
|
||||
idDecl* self;
|
||||
|
||||
@@ -218,7 +221,11 @@ public:
|
||||
virtual void ListType(const idCmdArgs& args, declType_t type);
|
||||
virtual void PrintType(const idCmdArgs& args, declType_t type);
|
||||
|
||||
virtual idDecl* CreateNewDecl(declType_t type, const char* name, const char* fileName);
|
||||
virtual bool CreateDeclFile(const char* fileName, declType_t defaultType);
|
||||
virtual idDecl* CreateNewDecl(declType_t type, const char* name, const char* fileName, bool save = true);
|
||||
virtual bool SetDeclText(declType_t type, const char* name, const char* text, bool parse = true, bool save = false);
|
||||
virtual bool SaveDecl(declType_t type, const char* name);
|
||||
virtual bool DeleteDecl(declType_t type, const char* name, bool deleteSourceText = true);
|
||||
|
||||
//BSM Added for the material editors rename capabilities
|
||||
virtual bool RenameDecl(declType_t type, const char* oldName, const char* newName);
|
||||
@@ -275,9 +282,19 @@ private:
|
||||
static idCVar decl_show;
|
||||
|
||||
private:
|
||||
idDeclFile* FindDeclFile(const char* fileName) const;
|
||||
idDeclFile* GetOrCreateDeclFile(const char* fileName, declType_t defaultType, bool createOnDisk);
|
||||
declType_t GetDefaultTypeForFileName(const char* fileName, declType_t fallback) const;
|
||||
void RemoveDeclFromSourceFile(idDeclLocal* decl);
|
||||
void FreeDeclLocal(idDeclLocal* decl);
|
||||
|
||||
static void ListDecls_f(const idCmdArgs& args);
|
||||
static void ReloadDecls_f(const idCmdArgs& args);
|
||||
static void TouchDecl_f(const idCmdArgs& args);
|
||||
static void CreateDeclFile_f(const idCmdArgs& args);
|
||||
static void CreateDecl_f(const idCmdArgs& args);
|
||||
static void SaveDecl_f(const idCmdArgs& args);
|
||||
static void DeleteDecl_f(const idCmdArgs& args);
|
||||
};
|
||||
|
||||
idCVar idDeclManagerLocal::decl_show("decl_show", "0", CVAR_SYSTEM, "set to 1 to print parses, 2 to also print references", 0, 2, idCmdSystem::ArgCompletion_Integer<0, 2>);
|
||||
@@ -867,6 +884,73 @@ int idDeclFile::LoadAndParse() {
|
||||
|
||||
const char* listDeclStrings[] = { "current", "all", "ever", NULL };
|
||||
|
||||
/*
|
||||
===================
|
||||
DeclCountLineBreaks
|
||||
===================
|
||||
*/
|
||||
static int DeclCountLineBreaks(const char* text, const int length) {
|
||||
int count = 0;
|
||||
|
||||
if (text == NULL || length <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (text[i] == '\n') {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
DeclCountFileLines
|
||||
===================
|
||||
*/
|
||||
static int DeclCountFileLines(const char* text, const int length) {
|
||||
if (text == NULL || length <= 0) {
|
||||
return 0;
|
||||
}
|
||||
return DeclCountLineBreaks(text, length) + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
DeclLineForOffset
|
||||
===================
|
||||
*/
|
||||
static int DeclLineForOffset(const char* text, const int offset) {
|
||||
if (text == NULL || offset <= 0) {
|
||||
return 1;
|
||||
}
|
||||
return DeclCountLineBreaks(text, offset) + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
DeclGetTypeFromCommandArg
|
||||
===================
|
||||
*/
|
||||
static bool DeclGetTypeFromCommandArg(const idCmdArgs& args, const int arg, declType_t& type) {
|
||||
type = declManagerLocal.GetDeclTypeFromName(args.Argv(arg));
|
||||
if (type != DECL_MAX_TYPES) {
|
||||
return true;
|
||||
}
|
||||
|
||||
common->Printf("unknown decl type '%s'\n", args.Argv(arg));
|
||||
common->Printf("valid types: ");
|
||||
for (int i = 0; i < declManagerLocal.GetNumDeclTypes(); i++) {
|
||||
idDeclType* declType = declManagerLocal.GetDeclType(i);
|
||||
if (declType != NULL) {
|
||||
common->Printf("%s ", declType->typeName.c_str());
|
||||
}
|
||||
}
|
||||
common->Printf("\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
idDeclManagerLocal::Init
|
||||
@@ -915,6 +999,10 @@ void idDeclManagerLocal::Init(void) {
|
||||
|
||||
cmdSystem->AddCommand("reloadDecls", ReloadDecls_f, CMD_FL_SYSTEM, "reloads decls");
|
||||
cmdSystem->AddCommand("touch", TouchDecl_f, CMD_FL_SYSTEM, "touches a decl");
|
||||
cmdSystem->AddCommand("createDeclFile", CreateDeclFile_f, CMD_FL_SYSTEM, "creates an empty decl file: createDeclFile <type> <file>");
|
||||
cmdSystem->AddCommand("createDecl", CreateDecl_f, CMD_FL_SYSTEM, "creates and saves a default decl: createDecl <type> <name> <file>");
|
||||
cmdSystem->AddCommand("saveDecl", SaveDecl_f, CMD_FL_SYSTEM, "saves a decl: saveDecl <type> <name>");
|
||||
cmdSystem->AddCommand("deleteDecl", DeleteDecl_f, CMD_FL_SYSTEM, "deletes a decl and removes its source text: deleteDecl <type> <name>");
|
||||
|
||||
cmdSystem->AddCommand("listTables", idListDecls_f<DECL_TABLE>, CMD_FL_SYSTEM, "lists tables", idCmdSystem::ArgCompletion_String<listDeclStrings>);
|
||||
cmdSystem->AddCommand("listMaterials", idListDecls_f<DECL_MATERIAL>, CMD_FL_SYSTEM, "lists materials", idCmdSystem::ArgCompletion_String<listDeclStrings>);
|
||||
@@ -1684,12 +1772,143 @@ void idDeclManagerLocal::PrintType(const idCmdArgs& args, declType_t type) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
idDeclManagerLocal::GetDefaultTypeForFileName
|
||||
===================
|
||||
*/
|
||||
declType_t idDeclManagerLocal::GetDefaultTypeForFileName(const char* fileName, declType_t fallback) const {
|
||||
if (fallback != DECL_MAX_TYPES || fileName == NULL || fileName[0] == '\0') {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
const char* extension = strrchr(fileName, '.');
|
||||
if (extension == NULL) {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
for (int i = 0; i < declFolders.Num(); i++) {
|
||||
if (declFolders[i] != NULL && declFolders[i]->extension.Icmp(extension) == 0) {
|
||||
return declFolders[i]->defaultType;
|
||||
}
|
||||
}
|
||||
|
||||
return fallback;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
idDeclManagerLocal::FindDeclFile
|
||||
===================
|
||||
*/
|
||||
idDeclFile* idDeclManagerLocal::FindDeclFile(const char* _fileName) const {
|
||||
if (_fileName == NULL || _fileName[0] == '\0') {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
idStr fileName = _fileName;
|
||||
fileName.BackSlashesToSlashes();
|
||||
|
||||
for (int i = 0; i < loadedFiles.Num(); i++) {
|
||||
if (loadedFiles[i]->fileName.Icmp(fileName) == 0) {
|
||||
return loadedFiles[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
idDeclManagerLocal::GetOrCreateDeclFile
|
||||
|
||||
If the file already exists on disk but has not been registered yet, it is
|
||||
registered and parsed. If it does not exist and createOnDisk is true, an
|
||||
empty file is written to fs_devpath and registered.
|
||||
===================
|
||||
*/
|
||||
idDeclFile* idDeclManagerLocal::GetOrCreateDeclFile(const char* _fileName, declType_t defaultType, bool createOnDisk) {
|
||||
if (_fileName == NULL || _fileName[0] == '\0') {
|
||||
common->Warning("idDeclManager::GetOrCreateDeclFile: empty file name");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
idStr fileName = _fileName;
|
||||
fileName.BackSlashesToSlashes();
|
||||
|
||||
idDeclFile* sourceFile = FindDeclFile(fileName.c_str());
|
||||
if (sourceFile != NULL) {
|
||||
return sourceFile;
|
||||
}
|
||||
|
||||
defaultType = GetDefaultTypeForFileName(fileName.c_str(), defaultType);
|
||||
|
||||
ID_TIME_T timestamp = 0;
|
||||
int length = fileSystem->ReadFile(fileName.c_str(), NULL, ×tamp);
|
||||
|
||||
sourceFile = new idDeclFile(fileName.c_str(), defaultType);
|
||||
loadedFiles.Append(sourceFile);
|
||||
|
||||
if (length > 0) {
|
||||
sourceFile->LoadAndParse();
|
||||
return sourceFile;
|
||||
}
|
||||
|
||||
if (length == 0) {
|
||||
sourceFile->timestamp = timestamp;
|
||||
sourceFile->checksum = MD5_BlockChecksum("", 0);
|
||||
sourceFile->fileSize = 0;
|
||||
sourceFile->numLines = 0;
|
||||
sourceFile->decls = NULL;
|
||||
return sourceFile;
|
||||
}
|
||||
|
||||
if (!createOnDisk) {
|
||||
return sourceFile;
|
||||
}
|
||||
|
||||
idFile* file = fileSystem->OpenFileWrite(fileName.c_str(), "fs_devpath");
|
||||
if (file == NULL) {
|
||||
loadedFiles.RemoveIndex(loadedFiles.Num() - 1);
|
||||
delete sourceFile;
|
||||
common->Warning("Couldn't create decl file %s", fileName.c_str());
|
||||
return NULL;
|
||||
}
|
||||
fileSystem->CloseFile(file);
|
||||
|
||||
sourceFile->timestamp = 0;
|
||||
sourceFile->checksum = MD5_BlockChecksum("", 0);
|
||||
sourceFile->fileSize = 0;
|
||||
sourceFile->numLines = 0;
|
||||
sourceFile->decls = NULL;
|
||||
fileSystem->ReadFile(fileName.c_str(), NULL, &sourceFile->timestamp);
|
||||
|
||||
return sourceFile;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
idDeclManagerLocal::CreateDeclFile
|
||||
===================
|
||||
*/
|
||||
bool idDeclManagerLocal::CreateDeclFile(const char* fileName, declType_t defaultType) {
|
||||
int typeIndex = (int)defaultType;
|
||||
|
||||
if (defaultType != DECL_MAX_TYPES && (typeIndex < 0 || typeIndex >= declTypes.Num() || declTypes[typeIndex] == NULL)) {
|
||||
common->Warning("idDeclManager::CreateDeclFile: bad default type: %i", typeIndex);
|
||||
return false;
|
||||
}
|
||||
|
||||
return GetOrCreateDeclFile(fileName, defaultType, true) != NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
idDeclManagerLocal::CreateNewDecl
|
||||
===================
|
||||
*/
|
||||
idDecl* idDeclManagerLocal::CreateNewDecl(declType_t type, const char* name, const char* _fileName) {
|
||||
idDecl* idDeclManagerLocal::CreateNewDecl(declType_t type, const char* name, const char* _fileName, bool save) {
|
||||
int typeIndex = (int)type;
|
||||
int i, hash;
|
||||
|
||||
@@ -1697,75 +1916,235 @@ idDecl* idDeclManagerLocal::CreateNewDecl(declType_t type, const char* name, con
|
||||
common->FatalError("idDeclManager::CreateNewDecl: bad type: %i", typeIndex);
|
||||
}
|
||||
|
||||
char canonicalName[MAX_STRING_CHARS];
|
||||
if (name == NULL || name[0] == '\0') {
|
||||
common->Warning("idDeclManager::CreateNewDecl: empty %s name", declTypes[typeIndex]->typeName.c_str());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
idDeclFile* sourceFile = GetOrCreateDeclFile(_fileName, type, save);
|
||||
if (sourceFile == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char canonicalName[MAX_STRING_CHARS];
|
||||
MakeNameCanonical(name, canonicalName, sizeof(canonicalName));
|
||||
|
||||
idStr fileName = _fileName;
|
||||
fileName.BackSlashesToSlashes();
|
||||
|
||||
// see if it already exists
|
||||
idDeclLocal* decl = NULL;
|
||||
hash = hashTables[typeIndex].GenerateKey(canonicalName, false);
|
||||
for (i = hashTables[typeIndex].First(hash); i >= 0; i = hashTables[typeIndex].Next(i)) {
|
||||
if (linearLists[typeIndex][i]->name.Icmp(canonicalName) == 0) {
|
||||
linearLists[typeIndex][i]->AllocateSelf();
|
||||
return linearLists[typeIndex][i]->self;
|
||||
}
|
||||
}
|
||||
|
||||
idDeclFile* sourceFile;
|
||||
|
||||
// find existing source file or create a new one
|
||||
for (i = 0; i < loadedFiles.Num(); i++) {
|
||||
if (loadedFiles[i]->fileName.Icmp(fileName) == 0) {
|
||||
decl = linearLists[typeIndex][i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < loadedFiles.Num()) {
|
||||
sourceFile = loadedFiles[i];
|
||||
}
|
||||
else {
|
||||
sourceFile = new idDeclFile(fileName, type);
|
||||
loadedFiles.Append(sourceFile);
|
||||
|
||||
// If an explicit decl already exists, keep the invariant that type/name is unique.
|
||||
if (decl != NULL && decl->sourceFile != &implicitDecls) {
|
||||
decl->AllocateSelf();
|
||||
common->Warning("%s '%s' already exists at %s:%i", declTypes[typeIndex]->typeName.c_str(),
|
||||
canonicalName, decl->sourceFile->fileName.c_str(), decl->sourceLine);
|
||||
return decl->self;
|
||||
}
|
||||
|
||||
bool createdNewDecl = false;
|
||||
if (decl == NULL) {
|
||||
decl = new idDeclLocal;
|
||||
decl->self = NULL;
|
||||
decl->name = canonicalName;
|
||||
decl->type = type;
|
||||
decl->declState = DS_UNPARSED;
|
||||
decl->referencedThisLevel = false;
|
||||
decl->everReferenced = false;
|
||||
decl->parsedOutsideLevelLoad = !insideLevelLoad;
|
||||
createdNewDecl = true;
|
||||
}
|
||||
|
||||
idDeclLocal* decl = new idDeclLocal;
|
||||
decl->name = canonicalName;
|
||||
decl->type = type;
|
||||
decl->declState = DS_UNPARSED;
|
||||
decl->AllocateSelf();
|
||||
idStr header = declTypes[typeIndex]->typeName;
|
||||
idStr defaultText = decl->self->DefaultDefinition();
|
||||
|
||||
idStr declText;
|
||||
if (sourceFile->fileSize > 0) {
|
||||
declText = "\n\n";
|
||||
}
|
||||
declText += declTypes[typeIndex]->typeName;
|
||||
declText += " ";
|
||||
declText += canonicalName;
|
||||
declText += " ";
|
||||
declText += decl->self->DefaultDefinition();
|
||||
if (declText.Length() <= 0 || declText[declText.Length() - 1] != '\n') {
|
||||
declText += "\n";
|
||||
}
|
||||
|
||||
int size = header.Length() + 1 + idStr::Length(canonicalName) + 1 + defaultText.Length();
|
||||
char* declText = (char*)_alloca(size + 1);
|
||||
|
||||
memcpy(declText, header, header.Length());
|
||||
declText[header.Length()] = ' ';
|
||||
memcpy(declText + header.Length() + 1, canonicalName, idStr::Length(canonicalName));
|
||||
declText[header.Length() + 1 + idStr::Length(canonicalName)] = ' ';
|
||||
memcpy(declText + header.Length() + 1 + idStr::Length(canonicalName) + 1, defaultText, defaultText.Length() + 1);
|
||||
|
||||
decl->SetTextLocal(declText, size);
|
||||
decl->SetTextLocal(declText.c_str(), declText.Length());
|
||||
decl->sourceFile = sourceFile;
|
||||
decl->sourceTextOffset = sourceFile->fileSize;
|
||||
decl->sourceTextLength = 0;
|
||||
decl->sourceLine = sourceFile->numLines;
|
||||
|
||||
decl->ParseLocal();
|
||||
decl->sourceLine = (sourceFile->numLines > 0) ? sourceFile->numLines : 1;
|
||||
decl->declState = DS_UNPARSED;
|
||||
|
||||
// add this decl to the source file list
|
||||
decl->nextInFile = sourceFile->decls;
|
||||
sourceFile->decls = decl;
|
||||
|
||||
// add it to the hash table and linear list
|
||||
decl->index = linearLists[typeIndex].Num();
|
||||
hashTables[typeIndex].Add(hash, linearLists[typeIndex].Append(decl));
|
||||
// add new explicit decls to the hash table and linear list
|
||||
if (createdNewDecl) {
|
||||
decl->index = linearLists[typeIndex].Num();
|
||||
hashTables[typeIndex].Add(hash, linearLists[typeIndex].Append(decl));
|
||||
}
|
||||
|
||||
decl->ParseLocal();
|
||||
|
||||
if (save && !decl->ReplaceSourceFileText()) {
|
||||
common->Warning("%s '%s' was created in memory but could not be saved to %s",
|
||||
declTypes[typeIndex]->typeName.c_str(), canonicalName, sourceFile->fileName.c_str());
|
||||
}
|
||||
|
||||
return decl->self;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
idDeclManagerLocal::SetDeclText
|
||||
===================
|
||||
*/
|
||||
bool idDeclManagerLocal::SetDeclText(declType_t type, const char* name, const char* text, bool parse, bool save) {
|
||||
int typeIndex = (int)type;
|
||||
|
||||
if (typeIndex < 0 || typeIndex >= declTypes.Num() || declTypes[typeIndex] == NULL) {
|
||||
common->FatalError("idDeclManager::SetDeclText: bad type: %i", typeIndex);
|
||||
}
|
||||
if (text == NULL) {
|
||||
common->Warning("idDeclManager::SetDeclText: NULL text for %s '%s'", declTypes[typeIndex]->typeName.c_str(), name ? name : "<NULL>");
|
||||
return false;
|
||||
}
|
||||
|
||||
idDeclLocal* decl = FindTypeWithoutParsing(type, name, false);
|
||||
if (decl == NULL) {
|
||||
common->Warning("idDeclManager::SetDeclText: %s '%s' not found", declTypes[typeIndex]->typeName.c_str(), name ? name : "<NULL>");
|
||||
return false;
|
||||
}
|
||||
|
||||
decl->SetTextLocal(text, idStr::Length(text));
|
||||
decl->declState = DS_UNPARSED;
|
||||
|
||||
if (parse) {
|
||||
decl->ParseLocal();
|
||||
}
|
||||
|
||||
if (save) {
|
||||
return decl->ReplaceSourceFileText();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
idDeclManagerLocal::SaveDecl
|
||||
===================
|
||||
*/
|
||||
bool idDeclManagerLocal::SaveDecl(declType_t type, const char* name) {
|
||||
int typeIndex = (int)type;
|
||||
|
||||
if (typeIndex < 0 || typeIndex >= declTypes.Num() || declTypes[typeIndex] == NULL) {
|
||||
common->FatalError("idDeclManager::SaveDecl: bad type: %i", typeIndex);
|
||||
}
|
||||
|
||||
idDeclLocal* decl = FindTypeWithoutParsing(type, name, false);
|
||||
if (decl == NULL) {
|
||||
common->Warning("idDeclManager::SaveDecl: %s '%s' not found", declTypes[typeIndex]->typeName.c_str(), name ? name : "<NULL>");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (decl->textSource == NULL) {
|
||||
common->Warning("idDeclManager::SaveDecl: %s '%s' has no source text", declTypes[typeIndex]->typeName.c_str(), decl->GetName());
|
||||
return false;
|
||||
}
|
||||
|
||||
return decl->ReplaceSourceFileText();
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
idDeclManagerLocal::RemoveDeclFromSourceFile
|
||||
===================
|
||||
*/
|
||||
void idDeclManagerLocal::RemoveDeclFromSourceFile(idDeclLocal* decl) {
|
||||
if (decl == NULL || decl->sourceFile == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
idDeclLocal** prev = &decl->sourceFile->decls;
|
||||
while (*prev != NULL) {
|
||||
if (*prev == decl) {
|
||||
*prev = decl->nextInFile;
|
||||
decl->nextInFile = NULL;
|
||||
return;
|
||||
}
|
||||
prev = &(*prev)->nextInFile;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
idDeclManagerLocal::FreeDeclLocal
|
||||
===================
|
||||
*/
|
||||
void idDeclManagerLocal::FreeDeclLocal(idDeclLocal* decl) {
|
||||
if (decl == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (decl->self != NULL) {
|
||||
decl->self->FreeData();
|
||||
delete decl->self;
|
||||
decl->self = NULL;
|
||||
}
|
||||
if (decl->textSource != NULL) {
|
||||
Mem_Free(decl->textSource);
|
||||
decl->textSource = NULL;
|
||||
}
|
||||
delete decl;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
idDeclManagerLocal::DeleteDecl
|
||||
===================
|
||||
*/
|
||||
bool idDeclManagerLocal::DeleteDecl(declType_t type, const char* name, bool deleteSourceText) {
|
||||
int typeIndex = (int)type;
|
||||
|
||||
if (typeIndex < 0 || typeIndex >= declTypes.Num() || declTypes[typeIndex] == NULL) {
|
||||
common->FatalError("idDeclManager::DeleteDecl: bad type: %i", typeIndex);
|
||||
}
|
||||
|
||||
idDeclLocal* decl = FindTypeWithoutParsing(type, name, false);
|
||||
if (decl == NULL) {
|
||||
common->Warning("idDeclManager::DeleteDecl: %s '%s' not found", declTypes[typeIndex]->typeName.c_str(), name ? name : "<NULL>");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (deleteSourceText && decl->sourceFile != &implicitDecls) {
|
||||
if (!decl->WriteSourceFileText("", 0)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
RemoveDeclFromSourceFile(decl);
|
||||
|
||||
int oldIndex = decl->index;
|
||||
int hashKey = hashTables[typeIndex].GenerateKey(decl->name.c_str(), false);
|
||||
hashTables[typeIndex].RemoveIndex(hashKey, oldIndex);
|
||||
linearLists[typeIndex].RemoveIndex(oldIndex);
|
||||
|
||||
for (int i = oldIndex; i < linearLists[typeIndex].Num(); i++) {
|
||||
linearLists[typeIndex][i]->index = i;
|
||||
}
|
||||
|
||||
FreeDeclLocal(decl);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
idDeclManagerLocal::RenameDecl
|
||||
@@ -2035,6 +2414,92 @@ void idDeclManagerLocal::TouchDecl_f(const idCmdArgs& args) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
idDeclManagerLocal::CreateDeclFile_f
|
||||
===================
|
||||
*/
|
||||
void idDeclManagerLocal::CreateDeclFile_f(const idCmdArgs& args) {
|
||||
if (args.Argc() != 3) {
|
||||
common->Printf("usage: createDeclFile <type> <file>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
declType_t type;
|
||||
if (!DeclGetTypeFromCommandArg(args, 1, type)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (declManagerLocal.CreateDeclFile(args.Argv(2), type)) {
|
||||
common->Printf("created decl file '%s'\n", args.Argv(2));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
idDeclManagerLocal::CreateDecl_f
|
||||
===================
|
||||
*/
|
||||
void idDeclManagerLocal::CreateDecl_f(const idCmdArgs& args) {
|
||||
if (args.Argc() != 4) {
|
||||
common->Printf("usage: createDecl <type> <name> <file>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
declType_t type;
|
||||
if (!DeclGetTypeFromCommandArg(args, 1, type)) {
|
||||
return;
|
||||
}
|
||||
|
||||
idDecl* decl = declManagerLocal.CreateNewDecl(type, args.Argv(2), args.Argv(3), true);
|
||||
if (decl != NULL) {
|
||||
common->Printf("created %s '%s' in '%s'\n", declManagerLocal.GetDeclNameFromType(type), decl->GetName(), decl->GetFileName());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
idDeclManagerLocal::SaveDecl_f
|
||||
===================
|
||||
*/
|
||||
void idDeclManagerLocal::SaveDecl_f(const idCmdArgs& args) {
|
||||
if (args.Argc() != 3) {
|
||||
common->Printf("usage: saveDecl <type> <name>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
declType_t type;
|
||||
if (!DeclGetTypeFromCommandArg(args, 1, type)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (declManagerLocal.SaveDecl(type, args.Argv(2))) {
|
||||
common->Printf("saved %s '%s'\n", declManagerLocal.GetDeclNameFromType(type), args.Argv(2));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
idDeclManagerLocal::DeleteDecl_f
|
||||
===================
|
||||
*/
|
||||
void idDeclManagerLocal::DeleteDecl_f(const idCmdArgs& args) {
|
||||
if (args.Argc() != 3) {
|
||||
common->Printf("usage: deleteDecl <type> <name>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
declType_t type;
|
||||
if (!DeclGetTypeFromCommandArg(args, 1, type)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (declManagerLocal.DeleteDecl(type, args.Argv(2), true)) {
|
||||
common->Printf("deleted %s '%s'\n", declManagerLocal.GetDeclNameFromType(type), args.Argv(2));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
idDeclManagerLocal::FindTypeWithoutParsing
|
||||
@@ -2104,6 +2569,7 @@ idDeclLocal::idDeclLocal
|
||||
=================
|
||||
*/
|
||||
idDeclLocal::idDeclLocal(void) {
|
||||
self = NULL;
|
||||
name = "unnamed";
|
||||
textSource = NULL;
|
||||
textLength = 0;
|
||||
@@ -2287,31 +2753,38 @@ void idDeclLocal::SetTextLocal(const char* text, const int length) {
|
||||
textLength = length;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
idDeclLocal::ReplaceSourceFileText
|
||||
idDeclLocal::WriteSourceFileText
|
||||
=================
|
||||
*/
|
||||
bool idDeclLocal::ReplaceSourceFileText(void) {
|
||||
bool idDeclLocal::WriteSourceFileText(const char* replacementText, const int replacementLength) {
|
||||
int oldFileLength, newFileLength;
|
||||
char* buffer;
|
||||
idFile* file;
|
||||
|
||||
common->Printf("Writing \'%s\' to \'%s\'...\n", GetName(), GetFileName());
|
||||
if (replacementText == NULL || replacementLength < 0) {
|
||||
common->Warning("idDeclLocal::WriteSourceFileText: bad replacement text for %s", GetName());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sourceFile == &declManagerLocal.implicitDecls) {
|
||||
if (sourceFile == NULL || sourceFile == &declManagerLocal.implicitDecls) {
|
||||
common->Warning("Can't save implicit declaration %s.", GetName());
|
||||
return false;
|
||||
}
|
||||
|
||||
// get length and allocate buffer to hold the file
|
||||
oldFileLength = sourceFile->fileSize;
|
||||
newFileLength = oldFileLength - sourceTextLength + textLength;
|
||||
buffer = (char*)Mem_Alloc(Max(newFileLength, oldFileLength));
|
||||
if (sourceTextOffset < 0 || sourceTextOffset > oldFileLength || sourceTextLength < 0 || sourceTextOffset + sourceTextLength > oldFileLength) {
|
||||
common->Warning("Decl %s has an invalid source range in %s.", GetName(), GetFileName());
|
||||
return false;
|
||||
}
|
||||
|
||||
// read original file
|
||||
if (sourceFile->fileSize) {
|
||||
newFileLength = oldFileLength - sourceTextLength + replacementLength;
|
||||
buffer = (char*)Mem_Alloc(Max(Max(newFileLength, oldFileLength), 1));
|
||||
|
||||
// read original file if it is known to exist
|
||||
if (sourceFile->timestamp != 0 || sourceFile->fileSize > 0) {
|
||||
file = fileSystem->OpenFileRead(GetFileName());
|
||||
if (!file) {
|
||||
Mem_Free(buffer);
|
||||
@@ -2320,12 +2793,15 @@ bool idDeclLocal::ReplaceSourceFileText(void) {
|
||||
}
|
||||
|
||||
if (file->Length() != sourceFile->fileSize || file->Timestamp() != sourceFile->timestamp) {
|
||||
fileSystem->CloseFile(file);
|
||||
Mem_Free(buffer);
|
||||
common->Warning("The file %s has been modified outside of the engine.", GetFileName());
|
||||
return false;
|
||||
}
|
||||
|
||||
file->Read(buffer, oldFileLength);
|
||||
if (oldFileLength > 0) {
|
||||
file->Read(buffer, oldFileLength);
|
||||
}
|
||||
fileSystem->CloseFile(file);
|
||||
|
||||
if (MD5_BlockChecksum(buffer, oldFileLength) != sourceFile->checksum) {
|
||||
@@ -2335,11 +2811,18 @@ bool idDeclLocal::ReplaceSourceFileText(void) {
|
||||
}
|
||||
}
|
||||
|
||||
// insert new text
|
||||
char* declText = (char*)_alloca(textLength + 1);
|
||||
GetText(declText);
|
||||
memmove(buffer + sourceTextOffset + textLength, buffer + sourceTextOffset + sourceTextLength, oldFileLength - sourceTextOffset - sourceTextLength);
|
||||
memcpy(buffer + sourceTextOffset, declText, textLength);
|
||||
int oldLineBreaks = DeclCountLineBreaks(buffer + sourceTextOffset, sourceTextLength);
|
||||
int newLineBreaks = DeclCountLineBreaks(replacementText, replacementLength);
|
||||
int textDelta = replacementLength - sourceTextLength;
|
||||
int lineDelta = newLineBreaks - oldLineBreaks;
|
||||
|
||||
// insert replacement text
|
||||
memmove(buffer + sourceTextOffset + replacementLength,
|
||||
buffer + sourceTextOffset + sourceTextLength,
|
||||
oldFileLength - sourceTextOffset - sourceTextLength);
|
||||
if (replacementLength > 0) {
|
||||
memcpy(buffer + sourceTextOffset, replacementText, replacementLength);
|
||||
}
|
||||
|
||||
// write out new file
|
||||
file = fileSystem->OpenFileWrite(GetFileName(), "fs_devpath");
|
||||
@@ -2348,30 +2831,51 @@ bool idDeclLocal::ReplaceSourceFileText(void) {
|
||||
common->Warning("Couldn't open %s for writing.", GetFileName());
|
||||
return false;
|
||||
}
|
||||
file->Write(buffer, newFileLength);
|
||||
if (newFileLength > 0) {
|
||||
file->Write(buffer, newFileLength);
|
||||
}
|
||||
fileSystem->CloseFile(file);
|
||||
|
||||
// set new file size, checksum and timestamp
|
||||
// set new file size, checksum, timestamp, and line count
|
||||
sourceFile->fileSize = newFileLength;
|
||||
sourceFile->checksum = MD5_BlockChecksum(buffer, newFileLength);
|
||||
sourceFile->numLines = DeclCountFileLines(buffer, newFileLength);
|
||||
fileSystem->ReadFile(GetFileName(), NULL, &sourceFile->timestamp);
|
||||
|
||||
// free buffer
|
||||
Mem_Free(buffer);
|
||||
|
||||
// move all decls in the same file
|
||||
for (idDeclLocal* decl = sourceFile->decls; decl; decl = decl->nextInFile) {
|
||||
if (decl->sourceTextOffset > sourceTextOffset) {
|
||||
decl->sourceTextOffset += textLength - sourceTextLength;
|
||||
if (decl != this && decl->sourceTextOffset > sourceTextOffset) {
|
||||
decl->sourceTextOffset += textDelta;
|
||||
decl->sourceLine += lineDelta;
|
||||
}
|
||||
}
|
||||
|
||||
// set new size of text in source file
|
||||
sourceTextLength = textLength;
|
||||
sourceTextLength = replacementLength;
|
||||
sourceLine = DeclLineForOffset(buffer, sourceTextOffset);
|
||||
|
||||
Mem_Free(buffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
idDeclLocal::ReplaceSourceFileText
|
||||
=================
|
||||
*/
|
||||
bool idDeclLocal::ReplaceSourceFileText(void) {
|
||||
if (textSource == NULL) {
|
||||
common->Warning("Decl %s has no text to save.", GetName());
|
||||
return false;
|
||||
}
|
||||
|
||||
common->Printf("Writing \'%s\' to \'%s\'...\n", GetName(), GetFileName());
|
||||
|
||||
char* declText = (char*)_alloca(textLength + 1);
|
||||
GetText(declText);
|
||||
return WriteSourceFileText(declText, textLength);
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
idDeclLocal::SourceFileChanged
|
||||
|
||||
Reference in New Issue
Block a user