Allow user to configure LOD suffixes to suit their workflow.

meow-7.2.2
Beq 2022-06-05 22:26:52 +01:00
parent ed8eebc7e4
commit 16b63a990e
10 changed files with 482 additions and 67 deletions

View File

@ -116,14 +116,17 @@ std::string colladaVersion[VERSIONTYPE_COUNT+1] =
"Unsupported"
};
static const std::string lod_suffix[LLModel::NUM_LODS] =
{
"_LOD0",
"_LOD1",
"_LOD2",
"",
"_PHYS",
};
// <FS:Beq> moved to allow configuration
// static const std::string lod_suffix[LLModel::NUM_LODS] =
// {
// "_LOD0",
// "_LOD1",
// "_LOD2",
// "",
// "_PHYS",
// };
// </FS:Beq>
const U32 LIMIT_MATERIALS_OUTPUT = 12;
@ -931,7 +934,11 @@ LLDAELoader::LLDAELoader(
std::map<std::string, std::string>& jointAliasMap,
U32 maxJointsPerMesh,
U32 modelLimit,
bool preprocess)
// <FS:Beq> mesh loader suffix configuration
// bool preprocess)
bool preprocess,
const LODSuffixArray& lod_suffix)
// </FS:Beq>
: LLModelLoader(
filename,
lod,
@ -947,12 +954,21 @@ LLDAELoader::LLDAELoader(
mGeneratedModelLimit(modelLimit),
mPreprocessDAE(preprocess)
{
// <FS:Beq> mesh loader suffix configuration
for(int i=0;i<LLModel::NUM_LODS;i++)
{
LLDAELoader::sLODSuffix[i] = lod_suffix[i];
}
// </FS:Beq>
}
LLDAELoader::~LLDAELoader()
{
}
//static
LODSuffixArray LLDAELoader::sLODSuffix{};// <FS:Beq/> configurable lod suffixes
struct ModelSort
{
bool operator()(const LLPointer< LLModel >& lhs, const LLPointer< LLModel >& rhs)
@ -2208,8 +2224,17 @@ void LLDAELoader::processElement( daeElement* element, bool& badElement, DAE* da
{
label += (char)((int)'a' + model->mSubmodelID);
}
model->mLabel = label + lod_suffix[mLod];
// <FS:Beq> Support altenate LOD naming conventions
// model->mLabel = label + sLODSuffix[mLod];
if ( sLODSuffix[mLod].size() > 0 )
{
model->mLabel = label + '_' + sLODSuffix[mLod];
}
else
{
model->mLabel = label;
}
// </FS:Beq>
}
else
{
@ -2485,13 +2510,19 @@ std::string LLDAELoader::getElementLabel(daeElement *element)
// static
size_t LLDAELoader::getSuffixPosition(std::string label)
{
// <FS:Ansariel> Bug fixes in mesh importer by Drake Arconis
// <FS:Beq> Selectable suffixes
//if ((label.find("_LOD") != -1) || (label.find("_PHYS") != -1))
if ((label.find("_LOD") != std::string::npos) || (label.find("_PHYS") != std::string::npos))
// </FS:Ansariel>
//{
// return label.rfind('_');
//}
for(int i=0; i < LLModel::NUM_LODS; i++)
{
return label.rfind('_');
if (sLODSuffix[i].size() && label.find(sLODSuffix[i]) != std::string::npos)
{
return label.rfind('_');
}
}
// </FS:Beq>
return -1;
}
@ -2636,8 +2667,17 @@ bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector<LLModel*>& mo
LLModel* ret = new LLModel(volume_params, 0.f);
std::string model_name = getLodlessLabel(mesh);
ret->mLabel = model_name + lod_suffix[mLod];
// <FS:Beq> Support altenate LOD naming conventions
// ret->mLabel = model_name + sLODSuffix[mLod];
if ( sLODSuffix[mLod].size() > 0 )
{
ret->mLabel = model_name + '_' + sLODSuffix[mLod];
}
else
{
ret->mLabel = model_name;
}
// </FS:Beq>
llassert(!ret->mLabel.empty());
// Like a monkey, ready to be shot into space
@ -2695,7 +2735,10 @@ bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector<LLModel*>& mo
{
LLModel* next = new LLModel(volume_params, 0.f);
next->mSubmodelID = ++submodelID;
next->mLabel = model_name + (char)((int)'a' + next->mSubmodelID) + lod_suffix[mLod];
// <FS:Beq> configurable lod suffixes
// next->mLabel = model_name + (char)((int)'a' + next->mSubmodelID) + lod_suffix[mLod];
next->mLabel = model_name + (char)((int)'a' + next->mSubmodelID) + sLODSuffix[mLod];
// </FS:Beq>
next->getVolumeFaces() = remainder;
next->mNormalizedScale = ret->mNormalizedScale;
next->mNormalizedTranslation = ret->mNormalizedTranslation;

View File

@ -39,6 +39,7 @@ class domController;
class domSkin;
class domMesh;
using LODSuffixArray = std::array<std::string,LLModel::NUM_LODS>; // <FS:Beq/> configurable lod suffixes
class LLDAELoader : public LLModelLoader
{
public:
@ -59,7 +60,11 @@ public:
std::map<std::string, std::string>& jointAliasMap,
U32 maxJointsPerMesh,
U32 modelLimit,
bool preprocess);
// <FS:Beq> configrable lod suffix support
// bool preprocess);
bool preprocess,
const LODSuffixArray& lod_suffix);
// </FS:Beq>
virtual ~LLDAELoader() ;
virtual bool OpenFile(const std::string& filename);
@ -104,6 +109,7 @@ protected:
static std::string getLodlessLabel(daeElement *element);
static std::string preprocessDAE(std::string filename);
static LODSuffixArray sLODSuffix; // <FS:Beq/> mesh loader suffix configuration
private:
U32 mGeneratedModelLimit; // Attempt to limit amount of generated submodels

View File

@ -634,10 +634,13 @@ void LLModel::generateNormals(F32 angle_cutoff)
}
}
extern std::string stripSuffix(std::string); // <FS:Beq/> mesh loader suffix configuration
std::string LLModel::getName() const
{
return mRequestedLabel.empty() ? mLabel : mRequestedLabel;
// <FS:Beq> remove the LOD suffix when used as the model name.
// return mRequestedLabel.empty() ? mLabel : mRequestedLabel;
return mRequestedLabel.empty() ? stripSuffix(mLabel) : mRequestedLabel;
// </FS:Beq>
}
//static

View File

@ -218,7 +218,7 @@ void LLModelLoader::setLoadState(U32 state)
{
mStateCallback(state, mOpaqueData);
}
extern std::string stripSuffix(std::string); // <FS:Beq/> mesh loader suffix configuration
bool LLModelLoader::loadFromSLM(const std::string& filename)
{
//only need to populate mScene with data from slm
@ -320,7 +320,10 @@ bool LLModelLoader::loadFromSLM(const std::string& filename)
&& !instance_label.empty())
{
// restore model names
std::string name = instance_label;
// <FS:Beq> This is going to get confusing here. We are juggling internal LOD names, with potentially overridden user ones.
// std::string name = instance_label;
std::string name = stripSuffix(instance_label);
// </FS:Beq>
switch (lod)
{
case LLModel::LOD_IMPOSTOR: name += "_LOD0"; break;

View File

@ -9239,6 +9239,62 @@
<key>Backup</key>
<integer>0</integer>
</map>
<key>FSMeshLowestLodSuffix</key>
<map>
<key>Comment</key>
<string>Suffix to use for Lowest LOD models and files (DAE).</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>LOD0</string>
</map>
<key>FSMeshLowLodSuffix</key>
<map>
<key>Comment</key>
<string>Suffix to use for Low LOD models and files (DAE).</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>LOD1</string>
</map>
<key>FSMeshMediumLodSuffix</key>
<map>
<key>Comment</key>
<string>Suffix to use for Medium LOD models and files (DAE).</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>LOD2</string>
</map>
<key>FSMeshHighLodSuffix</key>
<map>
<key>Comment</key>
<string>Suffix to use for High LOD models and files (DAE).</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string></string>
</map>
<key>FSMeshPhysicsSuffix</key>
<map>
<key>Comment</key>
<string>Suffix to use for Physics models and files (DAE).</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>PHYS</string>
</map>
<key>FSMeshUploadAutoEnableWeights</key>
<map>
<key>Comment</key>

View File

@ -122,6 +122,12 @@ void LLMeshFilePicker::notify(const std::vector<std::string>& filenames)
}
}
// <FS:Beq> support for settings panel of floater
const void updateUDPhysics(const std::vector<std::string>& filenames, LLFilePicker::ELoadFilter type)
{
gSavedSettings.setString("FSPhysicsPresetUser1", filenames[0]);
}
// </FS:Beq>
//-----------------------------------------------------------------------------
// LLFloaterModelPreview()
//-----------------------------------------------------------------------------
@ -146,6 +152,14 @@ mAvatarTabIndex(0)
}
}
// <FS:Beq> support for settings panel of floater
//static
void LLFloaterModelPreview::onSelectUDPhysics(LLUICtrl* ctrl, void* userdata)
{
(new LLFilePickerReplyThread(boost::bind(&updateUDPhysics, _1, _2), LLFilePicker::FFLOAD_COLLADA, false))->getFile();
}
// </FS:Beq>
//-----------------------------------------------------------------------------
// postBuild()
//-----------------------------------------------------------------------------
@ -209,6 +223,9 @@ BOOL LLFloaterModelPreview::postBuild()
getChild<LLColorSwatchCtrl>("mesh_preview_physics_fill_color")->setCommitCallback(preview_refresh_cb);
getChild<LLColorSwatchCtrl>("mesh_preview_degenerate_edge_color")->setCommitCallback(preview_refresh_cb);
getChild<LLColorSwatchCtrl>("mesh_preview_degenerate_fill_color")->setCommitCallback(preview_refresh_cb);
getChild<LLComboBox>("lod_suffix_combo")->setCommitCallback(boost::bind(&LLFloaterModelPreview::onSuffixStandardSelected, this, _1)); // mesh loader suffix configuration
getChild<LLButton>("set_user_def_phys")->setCommitCallback(boost::bind(&LLFloaterModelPreview::onSelectUDPhysics, this, _1)); // mesh loader suffix configuration
// </FS:Beq>
childDisable("upload_skin");
@ -1185,6 +1202,75 @@ void LLFloaterModelPreview::onPhysicsUseLOD(LLUICtrl* ctrl, void* userdata)
}
}
// <FS:Beq> mesh loader suffix configuration
//static
void LLFloaterModelPreview::onSuffixStandardSelected(LLUICtrl* ctrl, void* userdata)
{
S32 which{0};
// SL standard LODs are the reverse of every other game engine (LOD0 least detail)
// SL has no suffix for the HIGH LOD
const std::array<std::string,5> sl_suffixes = {
"LOD0",
"LOD1",
"LOD2",
"",
"PHYS"
};
// Game engines (UE, Unity, CryEngine, Godot, etc.) all use LOD0 as highest.
// They typically also label the high with a suffix too
const std::array<std::string,5> std_suffixes = {
"LOD3",
"LOD2",
"LOD1",
"LOD0",
"PHYS"
};
// Human friendly. When making things manually people naturally use names.
const std::array<std::string,5> desc_suffixes = {
"LOWEST",
"LOW",
"MED",
"HIGH",
"PHYS"
};
LLCtrlSelectionInterface* iface = sInstance->childGetSelectionInterface("lod_suffix_combo");
if (iface)
{
which = iface->getFirstSelectedIndex();
}
else
{
LL_WARNS() << "no UI element found! nothing changed" << LL_ENDL;
return;
}
switch (which)
{
case 1: // SL
for (int i = 0; i < LLModel::NUM_LODS; i++)
{
gSavedSettings.setString(LLModelPreview::sSuffixVarNames[i], sl_suffixes[i]);
}
break;
case 2: // standard
for (int i = 0; i < LLModel::NUM_LODS; i++)
{
gSavedSettings.setString(LLModelPreview::sSuffixVarNames[i], std_suffixes[i]);
}
break;
case 3: // descriptive english
for (int i = 0; i < LLModel::NUM_LODS; i++)
{
gSavedSettings.setString(LLModelPreview::sSuffixVarNames[i], desc_suffixes[i]);
}
break;
default:
LL_WARNS() << "no standard selected, nothing changed" << LL_ENDL;
break;
};
}
// </FS:Beq>
//static
void LLFloaterModelPreview::onCancel(LLUICtrl* ctrl, void* data)
{

View File

@ -106,7 +106,7 @@ public:
void loadModel(S32 lod, const std::string& file_name, bool force_disable_slm = false);
void loadHighLodModel();
void onViewOptionChecked(LLUICtrl* ctrl);
void onUploadOptionChecked(LLUICtrl* ctrl);
bool isViewOptionChecked(const LLSD& userdata);
@ -167,6 +167,8 @@ protected:
static void onPhysicsOptimize(LLUICtrl* ctrl, void* userdata);
static void onPhysicsDecomposeBack(LLUICtrl* ctrl, void* userdata);
static void onPhysicsSimplifyBack(LLUICtrl* ctrl, void* userdata);
static void onSuffixStandardSelected(LLUICtrl* ctrl, void* userdata); // <FS:Beq> mesh loader suffix configuration
static void onSelectUDPhysics(LLUICtrl* ctrl, void* userdata); // <FS:Beq/> custom setter for upload preview settings tab
void draw();

View File

@ -92,6 +92,17 @@ bool LLModelPreview::sIgnoreLoadedCallback = false;
// </FS:Beq>
const F32 SKIN_WEIGHT_CAMERA_DISTANCE = 16.f;
// <FS:Beq> mesh loader suffix configuration
//static
const std::array<std::string,5> LLModelPreview::sSuffixVarNames
{
"FSMeshLowestLodSuffix",
"FSMeshLowLodSuffix",
"FSMeshMediumLodSuffix",
"FSMeshHighLodSuffix",
"FSMeshPhysicsSuffix"
};
// </FS:Beq>
LLViewerFetchedTexture* bindMaterialDiffuseTexture(const LLImportMaterial& material)
{
LLViewerFetchedTexture *texture = LLViewerTextureManager::getFetchedTexture(material.getDiffuseMap(), FTT_DEFAULT, TRUE, LLGLTexture::BOOST_PREVIEW);
@ -110,13 +121,19 @@ LLViewerFetchedTexture* bindMaterialDiffuseTexture(const LLImportMaterial& mater
std::string stripSuffix(std::string name)
{
// <FS:Ansariel> Bug fixes in mesh importer by Drake Arconis
// <FS:Beq> Selectable suffixes
//if ((name.find("_LOD") != -1) || (name.find("_PHYS") != -1))
if ((name.find("_LOD") != std::string::npos) || (name.find("_PHYS") != std::string::npos))
// </FS:Ansariel>
// {
// return name.substr(0, name.rfind('_'));
// }
for(int i=0; i < LLModel::NUM_LODS; i++)
{
return name.substr(0, name.rfind('_'));
}
const auto& suffix = gSavedSettings.getString(LLModelPreview::sSuffixVarNames[i]);
if (suffix.size() && name.find(suffix) != std::string::npos)
{
return name.substr(0, name.rfind('_'));
}
} // </FS:Beq>
return name;
}
@ -125,12 +142,24 @@ std::string getLodSuffix(S32 lod)
std::string suffix;
switch (lod)
{
case LLModel::LOD_IMPOSTOR: suffix = "_LOD0"; break;
case LLModel::LOD_LOW: suffix = "_LOD1"; break;
case LLModel::LOD_MEDIUM: suffix = "_LOD2"; break;
case LLModel::LOD_PHYSICS: suffix = "_PHYS"; break;
case LLModel::LOD_HIGH: break;
// <FS:Beq> selectable suffixes
// case LLModel::LOD_IMPOSTOR: suffix = "_LOD0"; break;
// case LLModel::LOD_LOW: suffix = "_LOD1"; break;
// case LLModel::LOD_MEDIUM: suffix = "_LOD2"; break;
// case LLModel::LOD_PHYSICS: suffix = "_PHYS"; break;
// case LLModel::LOD_HIGH: break;
case LLModel::LOD_IMPOSTOR: suffix = gSavedSettings.getString("FSMeshLowestLodSuffix"); break;
case LLModel::LOD_LOW: suffix = gSavedSettings.getString("FSMeshLowLodSuffix"); break;
case LLModel::LOD_MEDIUM: suffix = gSavedSettings.getString("FSMeshMediumLodSuffix"); break;
case LLModel::LOD_HIGH: suffix = gSavedSettings.getString("FSMeshHighLodSuffix"); break;
case LLModel::LOD_PHYSICS: suffix = gSavedSettings.getString("FSMeshPhysicsSuffix"); break;
default:break;
}
if(suffix.size())
{
suffix = "_" + suffix;
}
// </FS:Beq>
return suffix;
}
@ -461,8 +490,10 @@ void LLModelPreview::rebuildUploadData()
// then the indexed method will be attempted below.
LLMatrix4 transform;
std::string name_to_match = instance.mLabel;
// <FS:Beq> user defined LOD names
// std::string name_to_match = instance.mLabel;
std::string name_to_match = stripSuffix(instance.mLabel);
// </FS:Beq>
llassert(!name_to_match.empty());
int extensionLOD;
@ -503,7 +534,10 @@ void LLModelPreview::rebuildUploadData()
int searchLOD = (i > LLModel::LOD_HIGH) ? LLModel::LOD_HIGH : i;
while ((searchLOD <= LLModel::LOD_HIGH) && !lod_model)
{
std::string name_to_match = instance.mLabel;
// <FS:Beq> user defined LOD names
// std::string name_to_match = instance.mLabel;
std::string name_to_match = stripSuffix(instance.mLabel);
// </FS:Beq>
llassert(!name_to_match.empty());
std::string toAdd = getLodSuffix(searchLOD);
@ -536,6 +570,13 @@ void LLModelPreview::rebuildUploadData()
{
std::ostringstream out;
out << "Attempting to use model index " << idx;
// <FS:Beq> better debug (watch for dangling single line else)
if(i==4)
{
out << " for PHYS";
}
else
// </FS:Beq>
out << " for LOD" << i;
out << " of " << instance.mLabel;
LL_INFOS() << out.str() << LL_ENDL;
@ -881,6 +922,12 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable
std::map<std::string, std::string> joint_alias_map;
getJointAliases(joint_alias_map);
std::array<std::string,LLModel::NUM_LODS> lod_suffix;
for(int i=0; i < LLModel::NUM_LODS; i++)
{
lod_suffix[i] = gSavedSettings.getString(sSuffixVarNames[i]);
}
mModelLoader = new LLDAELoader(
filename,
lod,
@ -894,7 +941,10 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable
joint_alias_map,
LLSkinningUtil::getMaxJointCount(),
gSavedSettings.getU32("ImporterModelLimit"),
gSavedSettings.getBOOL("ImporterPreprocessDAE"));
// <FS:Beq> allow LOD suffix configuration
// gSavedSettings.getBOOL("ImporterPreprocessDAE"));
gSavedSettings.getBOOL("ImporterPreprocessDAE"),
lod_suffix);
if (force_disable_slm)
{
@ -1230,7 +1280,7 @@ void LLModelPreview::loadModelCallback(S32 loaded_lod)
// this actually works like "ImporterLegacyMatching" for this particular LOD
for (U32 idx = 0; idx < mModel[loaded_lod].size() && idx < mBaseModel.size(); ++idx)
{
std::string name = mBaseModel[idx]->mLabel;
std::string name = stripSuffix(mBaseModel[idx]->mLabel);
std::string loaded_name = stripSuffix(mModel[loaded_lod][idx]->mLabel);
if (loaded_name != name)
@ -1881,7 +1931,15 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d
volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
mModel[lod][mdl_idx] = new LLModel(volume_params, 0.f);
std::string name = base->mLabel + getLodSuffix(lod);
// <FS:Beq> Support altenate LOD naming conventions
// std::string name = base->mLabel + getLodSuffix(lod);
std::string name = stripSuffix(base->mLabel);
std::string suffix = getLodSuffix(lod);
if ( suffix.size() > 0 )
{
name += suffix;
}
// </FS:Beq>
mModel[lod][mdl_idx]->mLabel = name;
mModel[lod][mdl_idx]->mSubmodelID = base->mSubmodelID;
@ -3167,7 +3225,7 @@ void LLModelPreview::lookupLODModelFiles(S32 lod)
// Note: we cannot use gDirUtilp here because the getExtension forces a tolower which would then break uppercase extensions on Linux/Mac
std::size_t offset = lod_filename.find_last_of('.');
std::string ext = (offset == std::string::npos || offset == 0) ? "" : lod_filename.substr(offset+1);
lod_filename = gDirUtilp->getDirName(lod_filename) + gDirUtilp->getDirDelimiter() + gDirUtilp->getBaseFileName(lod_filename, true) + getLodSuffix(next_lod) + "." + ext;
lod_filename = gDirUtilp->getDirName(lod_filename) + gDirUtilp->getDirDelimiter() + stripSuffix(gDirUtilp->getBaseFileName(lod_filename, true)) + getLodSuffix(next_lod) + "." + ext;
std::ostringstream out;
out << "Looking for file: " << lod_filename << " for LOD " << next_lod;
LL_DEBUGS("MeshUpload") << out.str() << LL_ENDL;

View File

@ -120,6 +120,7 @@ class LLModelPreview : public LLViewerDynamicTexture, public LLMutex
typedef boost::signals2::signal<void(bool)> model_updated_signal_t;
public:
static const std::array<std::string,5> sSuffixVarNames; // <FS:Beq/> mesh loader suffix configuration
typedef enum
{

View File

@ -1471,30 +1471,187 @@
tool_tip="Automatically show weights in preview for meshes with rigging info"
name="mesh_preview_auto_show_weights"/>
<text
follows="left|top"
layout="topleft"
left="24"
height="12"
name="mesh_preview_ud_preset_label"
top_pad="5"
width="110">
LOD Suffixes:
</text>
<combo_box
follows="left|top"
height="18"
left_pad="0"
name="lod_suffix_combo"
width="250"
top_delta="0"
tool_tip="Pick a preset or set your own">
<combo_item name="choose_one">Choose a standard or manually edit...</combo_item>
<combo_item name="suff_sl">SL Standard (Lowest=LOD0)</combo_item>
<combo_item name="suff_unity">Games Engine Standard (Lowest=LOD3)</combo_item>
<combo_item name="suff_descriptive">Words (high,med...)</combo_item>
</combo_box>
<text
follows="left|top"
layout="topleft"
left="24"
height="12"
name="mesh_preview_ud_preset_label"
top_pad="10"
width="200">
Physics User Defined Preset:
halign="right"
width="60">
Lowest:
</text>
<line_editor
control_name="FSPhysicsPresetUser1"
border_style="line"
border_thickness="1"
follows="left|top"
font="SansSerif"
height="23"
top_delta="-7"
layout="topleft"
left_pad="5"
max_length_chars="4096"
name="ud_physics"
tool_tip="Full system path to a simple Collada mesh definition to be used for physics."
width="270" />
<line_editor
control_name="FSMeshLowestLodSuffix"
border_style="line"
border_thickness="1"
follows="left|top"
font="SansSerif"
height="23"
top_delta="-5"
layout="topleft"
left_pad="5"
max_length_chars="10"
name="suf_lowest"
tool_tip="The Suffix used to identify the Lowest LOD file on disk and models within a file."
width="60" />
<text
follows="left|top"
layout="topleft"
left_pad="5"
halign="right"
height="12"
name="suf_low_lab"
top_delta="5"
width="40">
Low:
</text>
<line_editor
control_name="FSMeshLowLodSuffix"
border_style="line"
border_thickness="1"
follows="left|top"
font="SansSerif"
height="23"
top_delta="-5"
layout="topleft"
left_pad="5"
max_length_chars="10"
name="suf_low"
tool_tip="The Suffix used to identify the Low LOD file on disk and models within a file."
width="60" />
<text
follows="left|top"
top_delta="5"
layout="topleft"
left_pad="5"
height="12"
name="suf_low_lab"
halign="right"
width="40">
Medium:
</text>
<line_editor
control_name="FSMeshMediumLodSuffix"
border_style="line"
border_thickness="1"
follows="left|top"
font="SansSerif"
height="23"
top_delta="-5"
layout="topleft"
left_pad="5"
max_length_chars="10"
name="suf_medium"
tool_tip="The Suffix used to identify the Medium LOD file on disk and models within a file."
width="60" />
<text
follows="left|top"
layout="topleft"
left_pad="5"
height="12"
halign="right"
name="suf_med_lab"
top_delta="5"
width="40">
High:
</text>
<line_editor
control_name="FSMeshHighLodSuffix"
border_style="line"
border_thickness="1"
follows="left|top"
font="SansSerif"
height="23"
top_delta="-5"
layout="topleft"
left_pad="5"
max_length_chars="10"
name="suf_high"
tool_tip="The Suffix used to identify the High LOD file on disk and models within a file."
width="60" />
<text
follows="left|top"
layout="topleft"
left_pad="5"
height="12"
name="suf_low_lab"
top_delta="5"
width="40">
Physics:
</text>
<line_editor
control_name="FSMeshPhysicsSuffix"
border_style="line"
border_thickness="1"
follows="left|top"
font="SansSerif"
height="23"
top_delta="-5"
layout="topleft"
left_pad="5"
max_length_chars="10"
name="suf_physics"
tool_tip="The Suffix used to identify the Physics file on disk and models within a file."
width="60" />
<text
follows="left|top"
layout="topleft"
left="24"
height="12"
name="mesh_preview_ud_preset_label"
top_pad="15"
width="170">
Physics User Defined Preset:
</text>
<line_editor
control_name="FSPhysicsPresetUser1"
border_style="line"
border_thickness="1"
follows="left|top"
font="SansSerif"
height="23"
top_delta="-5"
layout="topleft"
left_pad="5"
max_length_chars="4096"
name="ud_physics"
tool_tip="Full system path to a simple Collada mesh definition to be used for physics."
width="270" />
<button
follows="left|top"
height="23"
label="Browse"
label_selected="Browse"
left_pad="5"
name="set_user_def_phys"
top_delta="0"
width="100">
</button>
<text
follows="left|top"
layout="topleft"
left="10"
@ -1522,7 +1679,7 @@
control_name="MeshPreviewCanvasColor"
follows="top|left"
left_pad="14"
height="64"
height="48"
width="120"
top_delta="-12"
can_apply_immediately="true"
@ -1533,7 +1690,7 @@
control_name="MeshPreviewEdgeColor"
follows="top|left"
left_pad="24"
height="64"
height="48"
width="120"
can_apply_immediately="true"
label="Model Edge"
@ -1543,7 +1700,7 @@
control_name="PreviewAmbientColor"
follows="top|left"
left_pad="24"
height="64"
height="48"
width="120"
can_apply_immediately="true"
label="Ambient Light"
@ -1559,7 +1716,7 @@
valign="center"
mouse_opaque="false"
name="physics_settings_label"
top_pad="20"
top_pad="10"
width="100">
Physics:
</text>
@ -1567,7 +1724,7 @@
control_name="MeshPreviewPhysicsEdgeColor"
follows="top|left"
left_pad="14"
height="64"
height="48"
can_apply_immediately="true"
width="120"
top_delta="-12"
@ -1577,8 +1734,8 @@
<color_swatch
control_name="MeshPreviewPhysicsFillColor"
follows="top|left"
left_pad="20"
height="64"
left_pad="24"
height="48"
width="120"
can_apply_immediately="true"
label="Physics Fill"
@ -1594,7 +1751,7 @@
valign="center"
mouse_opaque="false"
name="physics_issues_setting_label"
top_pad="24"
top_pad="10"
width="100">
Physics Issues:
</text>
@ -1602,7 +1759,7 @@
control_name="MeshPreviewDegenerateEdgeColor"
follows="top|left"
left_pad="14"
height="64"
height="48"
width="120"
top_delta="-12"
can_apply_immediately="true"
@ -1613,7 +1770,7 @@
control_name="MeshPreviewDegenerateFillColor"
follows="top|left"
left_pad="24"
height="64"
height="48"
width="120"
can_apply_immediately="true"
label="Bad Triangle Fill"