2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
26 ===========================================================================
28 #include "../../idlib/precompiled.h"
31 #include "MaterialDoc.h"
32 #include "MaterialView.h"
35 * Constructor for MaterialDoc.
37 MaterialDoc::MaterialDoc(void) {
44 * Destructor for MaterialDoc.
46 MaterialDoc::~MaterialDoc(void) {
51 * Initializes the MaterialDoc instance with a specific idMaterial. This method will
52 * parse the material into the internal dictionary representation and optionally
53 * allow the idMaterial object to reparse the source.
54 * @param material The idMaterial instance to use.
55 * @param parseMaterial Flag to determine if the material should be parsed into the editor representation.
56 * @param parseRenderMaterial Flag to determine if the idMaterial object should be reparsed.
58 void MaterialDoc::SetRenderMaterial(idMaterial* material, bool parseMaterial, bool parseRenderMatierial) {
60 renderMaterial = material;
63 if(!parseMaterial || !renderMaterial)
66 if(parseRenderMatierial) {
67 char *declText = (char *) _alloca( material->GetTextLength() + 1 );
68 material->GetText( declText );
70 renderMaterial->GetText(declText);
71 ParseMaterialText(declText);
77 name = material->GetName();
81 char *declText = (char *) _alloca( material->GetTextLength() + 1 );
82 material->GetText( declText );
84 renderMaterial->GetText(declText);
85 src.LoadMemory(declText, strlen(declText), "Material");
91 * Returns the number of stages in this material.
93 int MaterialDoc::GetStageCount() {
94 return editMaterial.stages.Num();
98 * Returns the index of the stage with the specified type and name or -1
99 * if the stage does not exist.
100 * @param stageType The type of stage to find.
101 * @param name The name of the stage to find.
103 int MaterialDoc::FindStage(int stageType, const char* name) {
105 for(int i = 0; i < editMaterial.stages.Num(); i++) {
106 int type = GetAttributeInt(i, "stagetype");
107 idStr localname = GetAttribute(i, "name");
108 if(stageType == type && !localname.Icmp(name))
115 * Returns a copy of the specified stage.
116 * @param stage The stage to return.
118 MEStage_t MaterialDoc::GetStage(int stage) {
119 assert(stage >= 0 && stage < GetStageCount());
120 return *editMaterial.stages[stage];
125 * Specifies the enabled state of a single stage.
126 * @param stage The stage to change.
127 * @param enabled The enabled state.
129 void MaterialDoc::EnableStage(int stage, bool enabled) {
131 assert(stage >= 0 && stage < GetStageCount());
132 editMaterial.stages[stage]->enabled = enabled;
138 * Sets the enabled state of all stages.
139 * @param enabled The enabled state.
141 void MaterialDoc::EnableAllStages(bool enabled) {
142 for(int i = 0; i < GetStageCount(); i++) {
143 editMaterial.stages[i]->enabled = enabled;
148 * Returns the enabled state of a stage.
149 * @param stage The stage to check.
151 bool MaterialDoc::IsStageEnabled(int stage) {
152 assert(stage >= 0 && stage < GetStageCount());
153 return editMaterial.stages[stage]->enabled;
157 * Returns an attribute string from the material or a stage.
158 * @param stage The stage or -1 for the material.
159 * @param attribName The name of the attribute.
160 * @param defaultString The default value if the attribute is not specified.
162 const char* MaterialDoc::GetAttribute(int stage, const char* attribName, const char* defaultString) {
165 return editMaterial.materialData.GetString(attribName, defaultString);
167 assert(stage >= 0 && stage < GetStageCount());
168 MEStage_t* pStage = editMaterial.stages[stage];
169 return pStage->stageData.GetString(attribName, defaultString);
174 * Returns an attribute int from the material or a stage.
175 * @param stage The stage or -1 for the material.
176 * @param attribName The name of the attribute.
177 * @param defaultString The default value if the attribute is not specified.
179 int MaterialDoc::GetAttributeInt(int stage, const char* attribName, const char* defaultString) {
181 return editMaterial.materialData.GetInt(attribName, defaultString);
183 assert(stage >= 0 && stage < GetStageCount());
184 MEStage_t* pStage = editMaterial.stages[stage];
185 return pStage->stageData.GetInt(attribName, defaultString);
190 * Returns an attribute float from the material or a stage.
191 * @param stage The stage or -1 for the material.
192 * @param attribName The name of the attribute.
193 * @param defaultString The default value if the attribute is not specified.
195 float MaterialDoc::GetAttributeFloat(int stage, const char* attribName, const char* defaultString) {
197 return editMaterial.materialData.GetFloat(attribName, defaultString);
199 assert(stage >= 0 && stage < GetStageCount());
200 MEStage_t* pStage = editMaterial.stages[stage];
201 return pStage->stageData.GetFloat(attribName, defaultString);
206 * Returns an attribute bool from the material or a stage.
207 * @param stage The stage or -1 for the material.
208 * @param attribName The name of the attribute.
209 * @param defaultString The default value if the attribute is not specified.
211 bool MaterialDoc::GetAttributeBool(int stage, const char* attribName, const char* defaultString) {
213 return editMaterial.materialData.GetBool(attribName, defaultString);
215 assert(stage >= 0 && stage < GetStageCount());
216 MEStage_t* pStage = editMaterial.stages[stage];
217 return pStage->stageData.GetBool(attribName, defaultString);
222 * Sets an attribute string in the material or a stage.
223 * @param stage The stage or -1 for the material.
224 * @param attribName The name of the attribute.
225 * @param value The value to set.
226 * @param addUndo Flag that specifies if the system should add an undo operation.
228 void MaterialDoc::SetAttribute(int stage, const char* attribName, const char* value, bool addUndo) {
230 //Make sure we need to set the attribute
231 idStr orig = GetAttribute(stage, attribName);
232 if(orig.Icmp(value)) {
236 dict = &editMaterial.materialData;
238 assert(stage >= 0 && stage < GetStageCount());
239 dict = &editMaterial.stages[stage]->stageData;
243 //Create a new Modifier for this change so we can undo and redo later
244 AttributeMaterialModifierString* mod = new AttributeMaterialModifierString(manager, name, stage, attribName, value, orig);
245 manager->AddMaterialUndoModifier(mod);
248 dict->Set(attribName, value);
250 manager->AttributeChanged(this, stage, attribName);
256 * Sets an attribute int in the material or a stage.
257 * @param stage The stage or -1 for the material.
258 * @param attribName The name of the attribute.
259 * @param value The value to set.
260 * @param addUndo Flag that specifies if the system should add an undo operation.
262 void MaterialDoc::SetAttributeInt(int stage, const char* attribName, int value, bool addUndo) {
263 //Make sure we need to set the attribute
264 int orig = GetAttributeInt(stage, attribName);
269 dict = &editMaterial.materialData;
271 assert(stage >= 0 && stage < GetStageCount());
272 dict = &editMaterial.stages[stage]->stageData;
275 dict->SetInt(attribName, value);
277 manager->AttributeChanged(this, stage, attribName);
283 * Sets an attribute float in the material or a stage.
284 * @param stage The stage or -1 for the material.
285 * @param attribName The name of the attribute.
286 * @param value The value to set.
287 * @param addUndo Flag that specifies if the system should add an undo operation.
289 void MaterialDoc::SetAttributeFloat(int stage, const char* attribName, float value, bool addUndo) {
290 //Make sure we need to set the attribute
291 float orig = GetAttributeFloat(stage, attribName);
296 dict = &editMaterial.materialData;
298 assert(stage >= 0 && stage < GetStageCount());
299 dict = &editMaterial.stages[stage]->stageData;
302 dict->SetFloat(attribName, value);
304 manager->AttributeChanged(this, stage, attribName);
310 * Sets an attribute bool in the material or a stage.
311 * @param stage The stage or -1 for the material.
312 * @param attribName The name of the attribute.
313 * @param value The value to set.
314 * @param addUndo Flag that specifies if the system should add an undo operation.
316 void MaterialDoc::SetAttributeBool(int stage, const char* attribName, bool value, bool addUndo) {
317 //Make sure we need to set the attribute
318 bool orig = GetAttributeBool(stage, attribName);
323 dict = &editMaterial.materialData;
325 assert(stage >= 0 && stage < GetStageCount());
326 dict = &editMaterial.stages[stage]->stageData;
330 //Create a new Modifier for this change so we can undo and redo later
331 AttributeMaterialModifierBool* mod = new AttributeMaterialModifierBool(manager, name, stage, attribName, value, orig);
332 manager->AddMaterialUndoModifier(mod);
335 dict->SetBool(attribName, value);
337 manager->AttributeChanged(this, stage, attribName);
343 * Sets the material name.
344 * @param materialName The new name of the material.
345 * @param addUndo Flag that specifies if the system should add an undo operation.
347 void MaterialDoc::SetMaterialName(const char* materialName, bool addUndo) {
348 idStr oldName = name;
350 declManager->RenameDecl(DECL_MATERIAL, oldName, materialName);
351 name = renderMaterial->GetName();
354 RenameMaterialModifier* mod = new RenameMaterialModifier(manager, name, oldName);
355 manager->AddMaterialUndoModifier(mod);
358 manager->MaterialNameChanged(oldName, this);
362 //Need to do an instant apply for material name changes
363 ApplyMaterialChanges();
367 * Sets the entire dictionary for a material or stage
368 * @param stage The stage or -1 for the material.
369 * @param data The dictionary to copy.
371 void MaterialDoc::SetData(int stage, idDict* data) {
374 dict = &editMaterial.materialData;
376 assert(stage >= 0 && stage < GetStageCount());
377 dict = &editMaterial.stages[stage]->stageData;
384 * Called when the editor modifies the source of the material.
385 * @param text The new source text.
387 void MaterialDoc::SourceModify(SourceModifyOwner* owner) {
389 sourceModifyOwner = owner;
395 * Returns true if the source text of this material has been edited.
397 bool MaterialDoc::IsSourceModified() {
402 * Applies any source changes to the edit representation of the material.
404 void MaterialDoc::ApplySourceModify(idStr& text) {
408 //Changes in the source need to clear any undo redo buffer because we have no idea what has changed
409 manager->ClearUndo();
410 manager->ClearRedo();
415 src.LoadMemory(text, text.Length(), "Material");
418 LEXFL_NOSTRINGCONCAT | // multiple strings seperated by whitespaces are not concatenated
419 LEXFL_NOSTRINGESCAPECHARS | // no escape characters inside strings
420 LEXFL_ALLOWPATHNAMES | // allow path seperators in names
421 LEXFL_ALLOWMULTICHARLITERALS | // allow multi character literals
422 LEXFL_ALLOWBACKSLASHSTRINGCONCAT | // allow multiple strings seperated by '\' to be concatenated
423 LEXFL_NOFATALERRORS // just set a flag instead of fatal erroring
427 if(!src.ReadToken(&token)) {
428 src.Warning( "Missing decl name" );
433 sourceModify = false;
435 //Check to see if the name has changed
436 if(token.Icmp(name)) {
437 SetMaterialName(token, false);
443 * Returns the appropriate source for the editing
445 const char* MaterialDoc::GetEditSourceText() {
447 return GenerateSourceText();
451 * Adds a stage to the material.
452 * @param stageType The type of the stage: normal or special.
453 * @param stageName The name of the stage.
454 * @param addUndo Flag that specifies if the system should add an undo operation.
456 void MaterialDoc::AddStage(int stageType, const char* stageName, bool addUndo) {
457 MEStage_t* newStage = new MEStage_t();
459 int index = editMaterial.stages.Append(newStage);
460 newStage->stageData.Set("name", stageName);
461 newStage->stageData.SetInt("stagetype", stageType);
462 newStage->enabled = true;
465 StageInsertModifier* mod = new StageInsertModifier(manager, name, index, stageType, stageName);
466 manager->AddMaterialUndoModifier(mod);
469 manager->StageAdded(this, index);
475 * Inserts a new stage to the material at a specified location.
476 * @param stage The location to insert the stage.
477 * @param stageType The type of the stage: normal or special.
478 * @param stageName The name of the stage.
479 * @param addUndo Flag that specifies if the system should add an undo operation.
481 void MaterialDoc::InsertStage(int stage, int stageType, const char* stageName, bool addUndo) {
482 MEStage_t* newStage = new MEStage_t();
484 editMaterial.stages.Insert(newStage, stage);
485 newStage->stageData.Set("name", stageName);
486 newStage->stageData.SetInt("stagetype", stageType);
487 newStage->enabled = true;
490 StageInsertModifier* mod = new StageInsertModifier(manager, name, stage, stageType, stageName);
491 manager->AddMaterialUndoModifier(mod);
494 manager->StageAdded(this, stage);
500 * Removes a stage from the material.
501 * @param stage The stage to remove.
502 * @param addUndo Flag that specifies if the system should add an undo operation.
504 void MaterialDoc::RemoveStage(int stage, bool addUndo) {
505 assert(stage >= 0 && stage < GetStageCount());
508 //Add modifier to undo this operation
509 StageDeleteModifier* mod = new StageDeleteModifier(manager, name, stage, editMaterial.stages[stage]->stageData);
510 manager->AddMaterialUndoModifier(mod);
513 //delete the stage and remove it from the list
514 delete editMaterial.stages[stage];
515 editMaterial.stages.RemoveIndex(stage);
517 manager->StageDeleted(this, stage);
523 * Removes all stages from the material.
525 void MaterialDoc::ClearStages() {
527 //Delete each stage and clear the list
528 for(int i = GetStageCount() - 1; i >= 0; i--) {
534 * Moves a stage from one location to another.
535 * @param from The original location of the stage.
536 * @param to The new location of the stage.
537 * @param addUndo Flag that specifies if the system should add an undo operation.
539 void MaterialDoc::MoveStage(int from, int to, bool addUndo) {
540 assert(from >= 0 && from < GetStageCount());
541 assert(to >= 0 && to < GetStageCount());
549 MEStage_t* pMove = editMaterial.stages[from];
550 editMaterial.stages.Insert(pMove, to);
555 editMaterial.stages.RemoveIndex(from);
557 manager->StageMoved(this, origFrom, origTo);
560 StageMoveModifier *mod = new StageMoveModifier(manager, name, origFrom, origTo);
561 manager->AddMaterialUndoModifier(mod);
568 * Applies any changes to the material
569 * @param force If true then the material will be applied regardless of the number of changes.
571 void MaterialDoc::ApplyMaterialChanges(bool force) {
573 if(force || applyWaiting) {
575 if(sourceModify && sourceModifyOwner) {
576 idStr text = sourceModifyOwner->GetSourceText();
577 ApplySourceModify(text);
582 char *declText = (char *) _alloca( renderMaterial->GetTextLength() + 1 );
583 renderMaterial->GetText( declText );
585 renderMaterial->GetText(declText);
587 ParseMaterialText(declText);
589 applyWaiting = false;
592 manager->MaterialApplied(this);
597 * Saves the material.
599 void MaterialDoc::Save() {
601 EnableAllStages(true);
603 //Apply the material so that the renderMaterial has the source text
605 ApplyMaterialChanges(true);
607 //Replace the text with nothing
608 renderMaterial->SetText(" ");
611 if(renderMaterial->Save()) {
617 manager->MaterialSaved(this);
619 MessageBox(GetMaterialEditorWindow(), va("Unable to save '%s'. It may be read-only", name.c_str()), "Save Error", MB_OK | MB_ICONERROR);
624 * Deletes the material.
626 void MaterialDoc::Delete() {
633 * Sets the proper internal states and notifies the MaterialDocManager once a material has been changed.
635 void MaterialDoc::OnMaterialChanged() {
641 manager->MaterialChanged(this);
645 * Passes text to a render material for parsing.
646 * @param source The text that sould be applied to the idMaterial.
648 void MaterialDoc::ParseMaterialText(const char* source) {
651 src.LoadMemory(source, strlen(source), "material");
653 LEXFL_NOSTRINGCONCAT | // multiple strings seperated by whitespaces are not concatenated
654 LEXFL_NOSTRINGESCAPECHARS | // no escape characters inside strings
655 LEXFL_ALLOWPATHNAMES | // allow path seperators in names
656 LEXFL_ALLOWMULTICHARLITERALS | // allow multi character literals
657 LEXFL_ALLOWBACKSLASHSTRINGCONCAT | // allow multiple strings seperated by '\' to be concatenated
658 LEXFL_NOFATALERRORS // just set a flag instead of fatal erroring
661 //Skip the name becuase the material parsing code expects it
662 src.SkipUntilString("{");*/
664 //Now let the material parse the text
665 renderMaterial->Parse(source, strlen(source));
669 * Parses the source text from an idMaterial and initializes the editor dictionary representation
671 * @param src The idLexer object that contains the material text.
673 void MaterialDoc::ParseMaterial(idLexer* src) {
677 //Parse past the name
678 src->SkipUntilString("{");
681 if ( !src->ExpectAnyToken( &token ) ) {
682 //Todo: Add some error checking here
686 if ( token == "}" ) {
690 if(ParseMaterialDef(&token, src, MaterialDefManager::MATERIAL_DEF_MATERIAL, &editMaterial.materialData)) {
694 if ( !token.Icmp( "diffusemap" ) ) {
695 //Added as a special stage
697 src->ReadRestOfLine( str );
698 AddSpecialMapStage("diffusemap", str);
700 else if ( !token.Icmp( "specularmap" ) ) {
702 src->ReadRestOfLine( str );
703 AddSpecialMapStage("specularmap", str);
705 else if ( !token.Icmp( "bumpmap" ) ) {
707 src->ReadRestOfLine( str );
708 AddSpecialMapStage("bumpmap", str);
710 else if( token == "{" ) {
717 * Parses a single stage from the source text from an idMaterial and initializes the editor dictionary
718 * representation of the material.
719 * @param src The idLexer object that contains the material text.
721 void MaterialDoc::ParseStage(idLexer* src) {
723 MEStage_t* newStage = new MEStage_t();
724 int index = editMaterial.stages.Append(newStage);
726 newStage->stageData.SetInt("stagetype", STAGE_TYPE_NORMAL);
727 newStage->enabled = true;
733 if ( !src->ExpectAnyToken( &token ) ) {
734 //Todo: Add some error checking here
738 if ( token == "}" ) {
742 if(ParseMaterialDef(&token, src, MaterialDefManager::MATERIAL_DEF_STAGE, &newStage->stageData)) {
746 if(!token.Icmp("name")) {
749 src->ReadRestOfLine( str );
750 str.StripTrailing('\"');
751 str.StripLeading('\"');
752 newStage->stageData.Set("name", str);
758 newStage->stageData.GetString("name", "", name);
759 if(name.Length() <= 0)
760 newStage->stageData.Set("name", va("Stage %d", index+1));
765 * Adds a special stage to the material.
766 * @param stageName The name of the special stage bumpmap, diffusemap or specularmap
767 * @param map The map for the special stage.
769 void MaterialDoc::AddSpecialMapStage(const char* stageName, const char* map) {
770 MEStage_t* newStage = new MEStage_t();
771 int index = editMaterial.stages.Append(newStage);
772 newStage->stageData.Set("name", stageName);
773 newStage->stageData.Set("map", map);
774 newStage->stageData.SetInt("stagetype", STAGE_TYPE_SPECIALMAP);
775 newStage->enabled = true;
779 * Finds the appropriate material definition for the supplied token and initializes the
780 * internal dictionary data.
781 * @param token The token to lookup
782 * @param src The idLexer that contains the material source text.
783 * @param type The type of attribute grouping to use material, stage or special stage.
784 * @param dict The dictionary to initialize.
786 bool MaterialDoc::ParseMaterialDef(idToken* token, idLexer* src, int type, idDict* dict) {
788 MaterialDefList* defs = MaterialDefManager::GetMaterialDefs(type);
790 for(int i = 0; i < defs->Num(); i++) {
791 if(!token->Icmp((*defs)[i]->dictName)) {
793 switch((*defs)[i]->type) {
794 case MaterialDef::MATERIAL_DEF_TYPE_STRING:
797 src->ReadRestOfLine( str );
798 if((*defs)[i]->quotes) {
799 str.StripTrailing('\"');
800 str.StripLeading('\"');
802 dict->Set((*defs)[i]->dictName, str);
805 case MaterialDef::MATERIAL_DEF_TYPE_BOOL:
807 src->SkipRestOfLine();
808 dict->SetBool((*defs)[i]->dictName, true);
811 case MaterialDef::MATERIAL_DEF_TYPE_FLOAT:
814 src->ReadRestOfLine( str );
815 dict->Set((*defs)[i]->dictName, str);
818 case MaterialDef::MATERIAL_DEF_TYPE_INT:
821 src->ReadRestOfLine( str );
822 dict->Set((*defs)[i]->dictName, str);
833 * Cleans up the edit material by deleting the stage data structures.
835 void MaterialDoc::ClearEditMaterial() {
837 for(int i = 0; i < GetStageCount(); i++) {
838 delete editMaterial.stages[i];
840 editMaterial.stages.Clear();
841 editMaterial.materialData.Clear();
845 * Writes the internal dictionary data to the standard format.
847 const char* MaterialDoc::GenerateSourceText() {
851 f.WriteFloatString("\n\n/*\n"
852 "\tGenerated by the Material Editor.\n"
853 "\tType 'materialeditor' at the console to launch the material editor.\n"
856 f.WriteFloatString("%s\n", name.c_str());
857 f.WriteFloatString( "{\n" );
858 WriteMaterialDef(-1, &f, MaterialDefManager::MATERIAL_DEF_MATERIAL, 1);
860 for(int i = 0; i < editMaterial.stages.Num(); i++) {
861 if(editMaterial.stages[i]->enabled) {
866 f.WriteFloatString( "}\n" );
868 return f.GetDataPtr();
873 * Writes the internal dictionary data to the standard format and replaces the
874 * idMaterial source text with the newly generated text.
876 void MaterialDoc::ReplaceSourceText() {
877 renderMaterial->SetText(GenerateSourceText());
881 * Writes a single stage.
882 * @param stage The stage to write.
883 * @param file The file where the stage should be wirtten
885 void MaterialDoc::WriteStage(int stage, idFile_Memory* file) {
887 //idStr stageName = GetAttribute(stage, "name");
888 int type = GetAttributeInt(stage, "stagetype");
889 //if(!stageName.Icmp("diffusemap") || !stageName.Icmp("specularmap") || !stageName.Icmp("bumpmap")) {
890 if(type == STAGE_TYPE_SPECIALMAP) {
891 WriteSpecialMapStage(stage, file);
895 file->WriteFloatString( "\t{\n" );
896 idStr name = GetAttribute(stage, "name");
897 if(name.Length() > 0) {
898 file->WriteFloatString("\t\tname\t\"%s\"\n", name.c_str());
900 WriteMaterialDef(stage, file, MaterialDefManager::MATERIAL_DEF_STAGE, 2);
901 file->WriteFloatString( "\t}\n" );
906 * Writes a single special stage.
907 * @param stage The stage to write.
908 * @param file The file where the stage should be wirtten
910 void MaterialDoc::WriteSpecialMapStage(int stage, idFile_Memory* file) {
911 idStr stageName = GetAttribute(stage, "name");
912 idStr map = GetAttribute(stage, "map");
914 file->WriteFloatString( "\t%s\t%s\n", stageName.c_str(), map.c_str() );
918 * Writes a set of material attributes to a file.
919 * @param stage The stage to write or -1 for the material.
920 * @param file The file where the stage should be wirtten.
921 * @param type The attribute grouping to use.
922 * @param indent The number of tabs to indent the text.
924 void MaterialDoc::WriteMaterialDef(int stage, idFile_Memory* file, int type, int indent) {
927 for(int i = 0; i < indent; i++) {
931 MaterialDefList* defs = MaterialDefManager::GetMaterialDefs(type);
932 for(int i = 0; i < defs->Num(); i++) {
933 switch((*defs)[i]->type) {
934 case MaterialDef::MATERIAL_DEF_TYPE_STRING:
936 idStr attrib = GetAttribute(stage, (*defs)[i]->dictName);
937 if(attrib.Length() > 0) {
938 if((*defs)[i]->quotes)
939 file->WriteFloatString("%s%s\t\"%s\"\n", prefix.c_str(), (*defs)[i]->dictName.c_str(), attrib.c_str());
941 file->WriteFloatString("%s%s\t%s\n", prefix.c_str(), (*defs)[i]->dictName.c_str(), attrib.c_str());
945 case MaterialDef::MATERIAL_DEF_TYPE_BOOL:
947 if(GetAttributeBool(stage, (*defs)[i]->dictName))
948 file->WriteFloatString("%s%s\t\n",prefix.c_str(), (*defs)[i]->dictName.c_str());
951 case MaterialDef::MATERIAL_DEF_TYPE_FLOAT:
953 float val = GetAttributeFloat(stage, (*defs)[i]->dictName);
954 file->WriteFloatString("%s%s\t%f\n", prefix.c_str(), (*defs)[i]->dictName.c_str(), val);
957 case MaterialDef::MATERIAL_DEF_TYPE_INT:
959 int val = GetAttributeInt(stage, (*defs)[i]->dictName);
960 file->WriteFloatString("%s%s\t%d\n", prefix.c_str(), (*defs)[i]->dictName.c_str(), val);