diff options
Diffstat (limited to 'indra')
-rw-r--r-- | indra/llrender/llvertexbuffer.h | 2 | ||||
-rw-r--r-- | indra/newview/llfloatermodelpreview.cpp | 666 | ||||
-rw-r--r-- | indra/newview/llfloatermodelpreview.h | 36 | ||||
-rw-r--r-- | indra/newview/llmeshreduction.cpp | 15 | ||||
-rw-r--r-- | indra/newview/skins/default/textures/textures.xml | 4 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/floater_model_preview.xml | 254 |
6 files changed, 675 insertions, 302 deletions
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 953b7e6757..f40f013306 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -198,7 +198,7 @@ public: U8* getIndicesPointer() const { return useVBOs() ? (U8*) mAlignedIndexOffset : mMappedIndexData; } U8* getVerticesPointer() const { return useVBOs() ? (U8*) mAlignedOffset : mMappedData; } U32 getTypeMask() const { return mTypeMask; } - BOOL hasDataType(S32 type) const { return ((1 << type) & getTypeMask()) ? TRUE : FALSE; } + bool hasDataType(S32 type) const { return ((1 << type) & getTypeMask()); } S32 getSize() const; S32 getIndicesSize() const { return mNumIndices * sizeof(U16); } U8* getMappedData() const { return mMappedData; } diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index b82e9dd62f..625f8924a2 100644 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -67,7 +67,9 @@ #include "lleconomy.h" #include "llfocusmgr.h" #include "llfloaterperms.h" +#include "lliconctrl.h" #include "llmatrix4a.h" +#include "llmenubutton.h" #include "llmeshrepository.h" #include "llsdutil_math.h" #include "lltextbox.h" @@ -80,17 +82,21 @@ #include "llvoavatarself.h" #include "pipeline.h" #include "lluictrlfactory.h" +#include "llviewermenu.h" #include "llviewermenufile.h" #include "llviewerregion.h" +#include "llviewertexturelist.h" #include "llstring.h" #include "llbutton.h" #include "llcheckboxctrl.h" #include "llsliderctrl.h" #include "llspinctrl.h" +#include "lltoggleablemenu.h" #include "llvfile.h" #include "llvfs.h" + #include "glod/glod.h" //static @@ -132,16 +138,33 @@ std::string lod_vertices_name[] = "high_vertices", "I went off the end of the lod_vertices_name array. Me so smart." }; - -std::string lod_status_name[] = + +std::string lod_status_name[] =
+{
+ "lowest_status",
+ "low_status",
+ "medium_status",
+ "high_status",
+ "I went off the end of the lod_status_name array. Me so smart."
+};
+ +std::string lod_icon_name[] = { - "lowest_status", - "low_status", - "medium_status", - "high_status", + "status_icon_lowest", + "status_icon_low", + "status_icon_medium", + "status_icon_high", "I went off the end of the lod_status_name array. Me so smart." }; +std::string lod_status_image[] = +{ + "ModelImport_Status_Good", + "ModelImport_Status_Warning", + "ModelImport_Status_Error", + "I went off the end of the lod_status_image array. Me so smart." +}; + std::string lod_label_name[] = { "lowest_label", @@ -152,7 +175,6 @@ std::string lod_label_name[] = }; - bool validate_face(const LLVolumeFace& face) { for (U32 i = 0; i < face.mNumIndices; ++i) @@ -254,21 +276,28 @@ BOOL LLFloaterModelPreview::postBuild() return FALSE; } + setViewOption("show_textures", true); + childSetAction("lod_browse", onBrowseLOD, this); - childSetCommitCallback("lod_triangle_limit", onTriangleLimitCommit, this); childSetCommitCallback("crease_angle", onGenerateNormalsCommit, this); childSetCommitCallback("generate_normals", onGenerateNormalsCommit, this); - childSetCommitCallback("show edges", onShowEdgesCommit, this); childSetCommitCallback("lod_generate", onAutoFillCommit, this); + + childSetCommitCallback("lod_mode", onLODParamCommit, this); + childSetCommitCallback("lod_error_threshold", onLODParamCommit, this); + childSetCommitCallback("lod_triangle_limit", onLODParamCommit, this); + childSetCommitCallback("build_operator", onLODParamCommit, this); + childSetCommitCallback("queue_mode", onLODParamCommit, this); + childSetCommitCallback("border_mode", onLODParamCommit, this); + childSetCommitCallback("share_tolerance", onLODParamCommit, this); childSetTextArg("status", "[STATUS]", getString("status_idle")); //childSetLabelArg("ok_btn", "[AMOUNT]", llformat("%d",sUploadAmount)); childSetAction("ok_btn", onUpload, this); - childSetAction("consolidate", onConsolidate, this); childSetAction("clear_materials", onClearMaterials, this); childSetCommitCallback("preview_lod_combo", onPreviewLODCommit, this); @@ -283,7 +312,18 @@ BOOL LLFloaterModelPreview::postBuild() childDisable("upload_skin"); childDisable("upload_joints"); + + mViewOptionMenuButton = getChild<LLMenuButton>("options_gear_btn"); + + mCommitCallbackRegistrar.add("ModelImport.ViewOption.Action", boost::bind(&LLFloaterModelPreview::onViewOptionChecked, this, _2)); + mEnableCallbackRegistrar.add("ModelImport.ViewOption.Check", boost::bind(&LLFloaterModelPreview::isViewOptionChecked, this, _2)); + mEnableCallbackRegistrar.add("ModelImport.ViewOption.Enabled", boost::bind(&LLFloaterModelPreview::isViewOptionEnabled, this, _2)); + + + mViewOptionMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_model_import_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + mViewOptionMenuButton->setMenu(mViewOptionMenu, LLMenuButton::MP_BOTTOM_LEFT); + initDecompControls(); LLView* preview_panel = getChild<LLView>("preview_panel"); @@ -344,6 +384,42 @@ LLFloaterModelPreview::~LLFloaterModelPreview() } } +void LLFloaterModelPreview::onViewOptionChecked(const LLSD& userdata) +{ + mViewOption[userdata.asString()] = !mViewOption[userdata.asString()]; + mModelPreview->refresh(); +} + +bool LLFloaterModelPreview::isViewOptionChecked(const LLSD& userdata) +{ + return mViewOption[userdata.asString()]; +} + +bool LLFloaterModelPreview::isViewOptionEnabled(const LLSD& userdata) +{ + return !mViewOptionDisabled[userdata.asString()]; +} + +void LLFloaterModelPreview::setViewOptionEnabled(const std::string& option, bool enabled) +{ + mViewOptionDisabled[option] = !enabled; +} + +void LLFloaterModelPreview::enableViewOption(const std::string& option) +{ + setViewOptionEnabled(option, true); +} + +void LLFloaterModelPreview::disableViewOption(const std::string& option) +{ + setViewOptionEnabled(option, false); +} + +void LLFloaterModelPreview::setViewOption(const std::string& option, bool value) +{ + mViewOption[option] = value; +} + void LLFloaterModelPreview::loadModel(S32 lod) { mLoading = TRUE; @@ -351,16 +427,6 @@ void LLFloaterModelPreview::loadModel(S32 lod) (new LLMeshFilePicker(this, lod))->getFile(); } -void LLFloaterModelPreview::setLimit(S32 lod, S32 limit) -{ - if (limit != mModelPreview->mLimit[lod]) - { - mModelPreview->mLimit[lod] = limit; - mModelPreview->genLODs(lod); - mModelPreview->setPreviewLOD(lod); - } -} - //static void LLFloaterModelPreview::onImportScaleCommit(LLUICtrl*,void* userdata) { @@ -423,30 +489,6 @@ void LLFloaterModelPreview::onPreviewLODCommit(LLUICtrl* ctrl, void* userdata) fp->mModelPreview->setPreviewLOD(which_mode); } -//static -void LLFloaterModelPreview::setLimit(S32 lod, void* userdata) -{ - LLFloaterModelPreview *fp =(LLFloaterModelPreview *)userdata; - - if (!fp->mModelPreview) - { - return; - } - - S32 limit = fp->childGetValue("lod_triangle_limit").asInteger(); - - - fp->setLimit(lod, limit); -} - -//static -void LLFloaterModelPreview::onTriangleLimitCommit(LLUICtrl* ctrl, void* userdata) -{ - LLFloaterModelPreview* fp = (LLFloaterModelPreview*) userdata; - - LLFloaterModelPreview::setLimit(fp->mModelPreview->mPreviewLOD, userdata); -} - //static void LLFloaterModelPreview::onGenerateNormalsCommit(LLUICtrl* ctrl, void* userdata) { @@ -456,14 +498,6 @@ void LLFloaterModelPreview::onGenerateNormalsCommit(LLUICtrl* ctrl, void* userda } //static -void LLFloaterModelPreview::onShowEdgesCommit(LLUICtrl* ctrl, void* userdata) -{ - LLFloaterModelPreview* fp = (LLFloaterModelPreview*) userdata; - - fp->mModelPreview->refresh(); -} - -//static void LLFloaterModelPreview::onExplodeCommit(LLUICtrl* ctrl, void* userdata) { LLFloaterModelPreview* fp = LLFloaterModelPreview::sInstance; @@ -479,6 +513,15 @@ void LLFloaterModelPreview::onAutoFillCommit(LLUICtrl* ctrl, void* userdata) fp->mModelPreview->genLODs(); } +//static +void LLFloaterModelPreview::onLODParamCommit(LLUICtrl* ctrl, void* userdata) +{ + LLFloaterModelPreview* fp = (LLFloaterModelPreview*) userdata; + fp->mModelPreview->genLODs(fp->mModelPreview->mPreviewLOD); + fp->mModelPreview->updateStatusMessages(); + fp->mModelPreview->refresh(); +} + //----------------------------------------------------------------------------- // draw() @@ -881,7 +924,6 @@ void LLFloaterModelPreview::initDecompControls() childSetCommitCallback("physics_layer", LLFloaterModelPreview::refresh, LLFloaterModelPreview::sInstance); childSetCommitCallback("physics_explode", LLFloaterModelPreview::onExplodeCommit, this); - childSetCommitCallback("show physics", LLFloaterModelPreview::refresh, this); } //----------------------------------------------------------------------------- @@ -1972,12 +2014,14 @@ LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloaterModelPreview* fmp mTextureName = 0; mPreviewLOD = 0; mModelLoader = NULL; + mMaxTriangleLimit = 0; mDirty = false; + mGenLOD = false; - for (U32 i = 0; i < LLModel::NUM_LODS; i++) - { - mLimit[i] = 0; - } + mBuildShareTolerance = 0.f; + mBuildQueueMode = GLOD_QUEUE_GREEDY; + mBuildBorderMode = GLOD_BORDER_UNLOCK; + mBuildOperator = GLOD_OPERATOR_HALF_EDGE_COLLAPSE; mFMP = fmp; @@ -2256,6 +2300,7 @@ void LLModelPreview::setPhysicsFromLOD(S32 lod) mVertexBuffer[LLModel::LOD_PHYSICS].clear(); rebuildUploadData(); refresh(); + updateStatusMessages(); } } @@ -2304,16 +2349,20 @@ void LLModelPreview::loadModelCallback(S32 lod) if (lod == LLModel::LOD_HIGH) { //save a copy of the highest LOD for automatic LOD manipulation + if (mBaseModel.empty()) + { //first time we've loaded a model, auto-gen LoD + mGenLOD = true; + } + mBaseModel = mModel[lod]; mBaseScene = mScene[lod]; mVertexBuffer[5].clear(); - //mModel[lod] = NULL; } clearIncompatible(lod); mDirty = true; - + if (lod == LLModel::LOD_HIGH) { resetPreviewTarget(); @@ -2616,11 +2665,6 @@ void LLModelPreview::genLODs(S32 which_lod) S32 limit = -1; - if (which_lod != -1) - { - limit = mLimit[which_lod]; - } - U32 triangle_count = 0; for (LLModelLoader::model_list::iterator iter = mBaseModel.begin(); iter != mBaseModel.end(); ++iter) @@ -2644,29 +2688,132 @@ void LLModelPreview::genLODs(S32 which_lod) mPatch.clear(); } + U32 lod_mode = 0; + + LLCtrlSelectionInterface* iface = mFMP->childGetSelectionInterface("lod_mode"); + if (iface) + { + lod_mode = iface->getFirstSelectedIndex(); + } + + F32 lod_error_threshold = mFMP->childGetValue("lod_error_threshold").asReal(); + + if (lod_mode == 0) + { + lod_mode = GLOD_TRIANGLE_BUDGET; + if (which_lod != -1) + { + limit = mFMP->childGetValue("lod_triangle_limit").asInteger(); + } + } + else + { + lod_mode = GLOD_ERROR_THRESHOLD; + } + + U32 build_operator = 0; + + iface = mFMP->childGetSelectionInterface("build_operator"); + if (iface) + { + build_operator = iface->getFirstSelectedIndex(); + } + + if (build_operator == 0) + { + build_operator = GLOD_OPERATOR_HALF_EDGE_COLLAPSE; + } + else + { + build_operator = GLOD_OPERATOR_EDGE_COLLAPSE; + } + + U32 queue_mode; + iface = mFMP->childGetSelectionInterface("queue_mode"); + if (iface) + { + queue_mode = iface->getFirstSelectedIndex(); + } + + if (queue_mode == 0) + { + queue_mode = GLOD_QUEUE_GREEDY; + } + else if (queue_mode == 1) + { + queue_mode = GLOD_QUEUE_LAZY; + } + else + { + queue_mode = GLOD_QUEUE_INDEPENDENT; + } + + U32 border_mode = 0; + + iface = mFMP->childGetSelectionInterface("border_mode"); + if (iface) + { + border_mode = iface->getFirstSelectedIndex(); + } + + if (border_mode == 0) + { + border_mode = GLOD_BORDER_UNLOCK; + } + else + { + border_mode = GLOD_BORDER_LOCK; + } + + bool object_dirty = false; + if (border_mode != mBuildBorderMode) + { + mBuildBorderMode = border_mode; + object_dirty = true; + } + + if (queue_mode != mBuildQueueMode) + { + mBuildQueueMode = queue_mode; + object_dirty = true; + } + + if (build_operator != mBuildOperator) + { + mBuildOperator = build_operator; + object_dirty = true; + } + + F32 share_tolerance = mFMP->childGetValue("share_tolerance").asReal(); + if (share_tolerance != mBuildShareTolerance) + { + mBuildShareTolerance = share_tolerance; + object_dirty = true; + } + for (LLModelLoader::model_list::iterator iter = mBaseModel.begin(); iter != mBaseModel.end(); ++iter) { //build GLOD objects for each model in base model list LLModel* mdl = *iter; if (mGroup[mdl] == 0) { mGroup[mdl] = cur_name++; + } + + if (mObject[mdl] == 0 || object_dirty) + { + if (mObject[mdl] != 0) + { + glodDeleteObject(mObject[mdl]); + } + mObject[mdl] = cur_name++; glodNewGroup(mGroup[mdl]); stop_gloderror(); - glodGroupParameteri(mGroup[mdl], GLOD_ADAPT_MODE, GLOD_TRIANGLE_BUDGET); - stop_gloderror(); - - glodGroupParameteri(mGroup[mdl], GLOD_ERROR_MODE, GLOD_OBJECT_SPACE_ERROR); - stop_gloderror(); - - glodGroupParameterf(mGroup[mdl], GLOD_OBJECT_SPACE_ERROR_THRESHOLD, 0.025f); - stop_gloderror(); - glodNewObject(mObject[mdl], mGroup[mdl], GLOD_DISCRETE); stop_gloderror(); - + if (iter == mBaseModel.begin() && !mdl->mSkinWeights.empty()) { //regenerate vertex buffer for skinned models to prevent animation feedback during LOD generation mVertexBuffer[5].clear(); @@ -2689,38 +2836,25 @@ void LLModelPreview::genLODs(S32 which_lod) tri_count += num_indices/3; stop_gloderror(); } + + glodObjectParameteri(mObject[mdl], GLOD_BUILD_OPERATOR, build_operator); + stop_gloderror(); + + glodObjectParameteri(mObject[mdl], GLOD_BUILD_QUEUE_MODE, queue_mode); + stop_gloderror(); + + glodObjectParameteri(mObject[mdl], GLOD_BUILD_BORDER_MODE, border_mode); + stop_gloderror(); + + glodObjectParameterf(mObject[mdl], GLOD_BUILD_SHARE_TOLERANCE, share_tolerance); + stop_gloderror(); + + glodBuildObject(mObject[mdl]); + stop_gloderror(); //store what percentage of total model (in terms of triangle count) this model makes up mPercentage[mdl] = (F32) tri_count / (F32) base_triangle_count; - - //build glodobject - glodBuildObject(mObject[mdl]); - if (stop_gloderror()) - { - glodDeleteGroup(mGroup[mdl]); - stop_gloderror(); - glodDeleteObject(mObject[mdl]); - stop_gloderror(); - - mGroup[mdl] = 0; - mObject[mdl] = 0; - - if (which_lod == -1) - { - mModel[LLModel::LOD_HIGH] = mBaseModel; - } - - return; - } - - } - - //generating LODs for all entries, or this entry has a triangle budget - glodGroupParameteri(mGroup[mdl], GLOD_ADAPT_MODE, GLOD_TRIANGLE_BUDGET); - stop_gloderror(); - - glodGroupParameterf(mGroup[mdl], GLOD_OBJECT_SPACE_ERROR_THRESHOLD, 0.025f); - stop_gloderror(); + } } @@ -2732,9 +2866,8 @@ void LLModelPreview::genLODs(S32 which_lod) start = end = which_lod; } - LLSpinCtrl* lim = mFMP->getChild<LLSpinCtrl>("lod_triangle_limit", TRUE); - lim->setMaxValue(base_triangle_count); - + mMaxTriangleLimit = base_triangle_count; + for (S32 lod = start; lod >= end; --lod) { if (which_lod == -1) @@ -2768,9 +2901,21 @@ void LLModelPreview::genLODs(S32 which_lod) target_count = 4; } - glodGroupParameteri(mGroup[base], GLOD_MAX_TRIANGLES, target_count); + glodGroupParameteri(mGroup[base], GLOD_ADAPT_MODE, lod_mode); + stop_gloderror(); + + glodGroupParameteri(mGroup[base], GLOD_ADAPT_MODE, lod_mode); + stop_gloderror(); + + glodGroupParameteri(mGroup[base], GLOD_ERROR_MODE, GLOD_OBJECT_SPACE_ERROR); stop_gloderror(); + glodGroupParameteri(mGroup[base], GLOD_MAX_TRIANGLES, target_count); + stop_gloderror(); + + glodGroupParameterf(mGroup[base], GLOD_OBJECT_SPACE_ERROR_THRESHOLD, lod_error_threshold); + stop_gloderror(); + glodAdaptGroup(mGroup[base]); stop_gloderror(); @@ -2938,17 +3083,26 @@ void LLModelPreview::updateStatusMessages() } } + if (mMaxTriangleLimit == 0) + { + mMaxTriangleLimit = total_tris[LLModel::LOD_HIGH]; + } + + mFMP->childSetTextArg("submeshes_info", "[SUBMESHES]", llformat("%d", total_submeshes[LLModel::LOD_HIGH])); - std::string mesh_status_good = mFMP->getString("mesh_status_good"); - std::string mesh_status_bad = mFMP->getString("mesh_status_bad"); std::string mesh_status_na = mFMP->getString("mesh_status_na"); - std::string mesh_status_none = mFMP->getString("mesh_status_none"); + + S32 upload_status[LLModel::LOD_HIGH+1]; bool upload_ok = true; - + for (S32 lod = 0; lod <= LLModel::LOD_HIGH; ++lod) { + upload_status[lod] = 0; + + std::string message = "mesh_status_good"; + if (total_tris[lod] > 0) { mFMP->childSetText(lod_triangles_name[lod], llformat("%d", total_tris[lod])); @@ -2956,26 +3110,40 @@ void LLModelPreview::updateStatusMessages() } else { + if (lod == LLModel::LOD_HIGH) + { + upload_status[lod] = 2; + message = "mesh_status_missing_lod"; + } + else + { + for (S32 i = lod-1; i >= 0; --i) + { + if (total_tris[i] > 0) + { + upload_status[lod] = 2; + message = "mesh_status_missing_lod"; + } + } + } + mFMP->childSetText(lod_triangles_name[lod], mesh_status_na); mFMP->childSetText(lod_vertices_name[lod], mesh_status_na); } - - std::string message = mesh_status_good; - const U32 lod_high = LLModel::LOD_HIGH; if (lod != lod_high) { if (total_submeshes[lod] && total_submeshes[lod] != total_submeshes[lod_high]) { //number of submeshes is different - message = mesh_status_bad; - upload_ok = false; + message = "mesh_status_submesh_mismatch"; + upload_status[lod] = 2; } else if (!tris[lod].empty() && tris[lod].size() != tris[lod_high].size()) { //number of meshes is different - message = mesh_status_bad; - upload_ok = false; + message = "mesh_status_mesh_mismatch"; + upload_status[lod] = 2; } else if (!verts[lod].empty()) { @@ -2983,20 +3151,34 @@ void LLModelPreview::updateStatusMessages() { S32 max_verts = i < verts[lod+1].size() ? verts[lod+1][i] : 0; - if (verts[lod][i] > max_verts) - { //too many vertices in this lod - message = mesh_status_bad; - upload_ok = false; + if (max_verts > 0) + { + if (verts[lod][i] > max_verts) + { //too many vertices in this lod + message = "mesh_status_too_many_vertices"; + upload_status[lod] = 2; + } } } } - else - { //no mesh - message = mesh_status_none; - } } - mFMP->childSetText(lod_status_name[lod], message); + LLIconCtrl* icon = mFMP->getChild<LLIconCtrl>(lod_icon_name[lod]); + LLUIImagePtr img = LLUI::getUIImage(lod_status_image[upload_status[lod]]); + icon->setVisible(true); + icon->setImage(img); + + if (upload_status[lod] >= 2) + { + upload_ok = false; + } + + if (lod == mPreviewLOD) + { + mFMP->childSetText("lod_status_message_text", mFMP->getString(message)); + icon = mFMP->getChild<LLIconCtrl>("lod_status_message_icon"); + icon->setImage(img); + } } if (upload_ok) @@ -3069,20 +3251,121 @@ void LLModelPreview::updateStatusMessages() mFMP->childSetTextArg("physics_points", "[POINTS]", mesh_status_na); } + if (phys_tris > 0 || phys_hulls > 0) + { + if (!mFMP->isViewOptionEnabled("show_physics")) + { + mFMP->enableViewOption("show_physics"); + mFMP->setViewOption("show_physics", true); + } + } + else + { + mFMP->disableViewOption("show_physics"); + mFMP->setViewOption("show_physics", false); + } + + const char* lod_controls[] = + { + "lod_mode", + "lod_triangle_limit", + "lod_error_tolerance", + "build_operator_text", + "queue_mode_text", + "border_mode_text", + "share_tolerance_text", + "build_operator", + "queue_mode", + "border_mode", + "share_tolerance" + }; + const U32 num_lod_controls = sizeof(lod_controls)/sizeof(char*); + + const char* file_controls[] = + { + "lod_browse", + "lod_file" + }; + const U32 num_file_controls = sizeof(file_controls)/sizeof(char*); + //enable/disable controls based on radio groups if (mFMP->childGetValue("lod_from_file").asBoolean()) { - mFMP->childDisable("lod_triangle_limit"); - mFMP->childDisable("lod_generate"); - mFMP->childEnable("lod_file"); - mFMP->childEnable("lod_browse"); + for (U32 i = 0; i < num_file_controls; ++i) + { + mFMP->childEnable(file_controls[i]); + } + + for (U32 i = 0; i < num_lod_controls; ++i) + { + mFMP->childDisable(lod_controls[i]); + } + + } - else + else if (mFMP->childGetValue("lod_auto_generate").asBoolean()) { - mFMP->childEnable("lod_triangle_limit"); - mFMP->childEnable("lod_generate"); - mFMP->childDisable("lod_file"); - mFMP->childDisable("lod_browse"); + for (U32 i = 0; i < num_file_controls; ++i) + { + mFMP->childDisable(file_controls[i]); + } + + for (U32 i = 0; i < num_lod_controls; ++i) + { + mFMP->childEnable(lod_controls[i]); + } + + //if (threshold) + { + U32 lod_mode = 0; + LLCtrlSelectionInterface* iface = mFMP->childGetSelectionInterface("lod_mode"); + if (iface) + { + lod_mode = iface->getFirstSelectedIndex(); + } + + LLSpinCtrl* threshold = mFMP->getChild<LLSpinCtrl>("lod_error_threshold"); + LLSpinCtrl* limit = mFMP->getChild<LLSpinCtrl>("lod_triangle_limit"); + + limit->setMaxValue(mMaxTriangleLimit); + limit->setValue(total_tris[mPreviewLOD]); + + if (lod_mode == 0) + { + limit->setVisible(true); + threshold->setVisible(false); + + limit->setMaxValue(mMaxTriangleLimit); + } + else + { + limit->setVisible(false); + threshold->setVisible(true); + } + } + } + else + { // "None" is chosen + for (U32 i = 0; i < num_file_controls; ++i) + { + mFMP->childDisable(file_controls[i]); + } + + for (U32 i = 0; i < num_lod_controls; ++i) + { + mFMP->childDisable(lod_controls[i]); + } + + if (!mModel[mPreviewLOD].empty()) + { + mModel[mPreviewLOD].clear(); + mScene[mPreviewLOD].clear(); + mVertexBuffer[mPreviewLOD].clear(); + + //this can cause phasing issues with the UI, so reenter this function and return + updateStatusMessages(); + return; + } } if (mFMP->childGetValue("physics_load_from_file").asBoolean()) @@ -3116,7 +3399,7 @@ void LLModelPreview::clearBuffers() } } -void LLModelPreview::genBuffers(S32 lod, bool avatar_preview) +void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights) { U32 tri_count = 0; U32 vertex_count = 0; @@ -3167,7 +3450,7 @@ void LLModelPreview::genBuffers(S32 lod, bool avatar_preview) LLVertexBuffer* vb = NULL; - bool skinned = avatar_preview && !mdl->mSkinWeights.empty(); + bool skinned = include_skin_weights && !mdl->mSkinWeights.empty(); U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0; @@ -3249,7 +3532,17 @@ void LLModelPreview::update() mDirty = false; mResourceCost = calcResourceCost(); refresh(); + updateStatusMessages(); } + + if (mGenLOD) + { + mGenLOD = false; + genLODs(); + refresh(); + updateStatusMessages(); + } + } //----------------------------------------------------------------------------- @@ -3260,6 +3553,12 @@ BOOL LLModelPreview::render() LLMutexLock lock(this); mNeedsUpdate = FALSE; + bool edges = mFMP->isViewOptionChecked("show_edges"); + bool joint_positions = mFMP->isViewOptionChecked("show_joint_positions"); + bool skin_weight = mFMP->isViewOptionChecked("show_skin_weight"); + bool textures = mFMP->isViewOptionChecked("show_textures"); + bool physics = mFMP->isViewOptionChecked("show_physics"); + S32 width = getWidth(); S32 height = getHeight(); @@ -3291,7 +3590,7 @@ BOOL LLModelPreview::render() gGL.popMatrix(); } - bool avatar_preview = false; + bool has_skin_weights = false; bool upload_skin = mFMP->childGetValue("upload_skin").asBoolean(); bool upload_joints = mFMP->childGetValue("upload_joints").asBoolean(); @@ -3303,45 +3602,39 @@ BOOL LLModelPreview::render() LLModel* model = instance.mModel; if (!model->mSkinWeights.empty()) { - avatar_preview = true; + has_skin_weights = true; } } } - - if (upload_skin && !avatar_preview) + + if (has_skin_weights) + { //model has skin weights, enable view options for skin weights and joint positions + mFMP->enableViewOption("show_skin_weight"); + mFMP->setViewOptionEnabled("show_joint_positions", skin_weight); + mFMP->childEnable("upload_skin"); + } + else { + mFMP->childDisable("upload_skin"); + mFMP->setViewOption("show_skin_weight", false); + mFMP->disableViewOption("show_skin_weight"); + mFMP->disableViewOption("show_joint_positions"); + skin_weight = false; + } + + if (upload_skin && !has_skin_weights) + { //can't upload skin weights if model has no skin weights mFMP->childSetValue("upload_skin", false); upload_skin = false; } if (!upload_skin && upload_joints) - { + { //can't upload joints if not uploading skin weights mFMP->childSetValue("upload_joints", false); upload_joints = false; } - if (!avatar_preview) - { - mFMP->childDisable("upload_skin"); - } - else - { - mFMP->childEnable("upload_skin"); - } - - if (!upload_skin) - { - mFMP->childDisable("upload_joints"); - } - else - { - mFMP->childEnable("upload_joints"); - } - - avatar_preview = avatar_preview && upload_skin; - - - mFMP->childSetEnabled("consolidate", !avatar_preview); + mFMP->childSetEnabled("upload_joints", upload_skin); F32 explode = mFMP->childGetValue("physics_explode").asReal(); @@ -3358,7 +3651,7 @@ BOOL LLModelPreview::render() F32 z_near = 0.001f; F32 z_far = mCameraDistance+mPreviewScale.magVec()+mCameraOffset.magVec(); - if (avatar_preview) + if (skin_weight) { target_pos = gAgentAvatarp->getPositionAgent(); z_near = 0.01f; @@ -3369,6 +3662,7 @@ BOOL LLModelPreview::render() refresh(); } + glLoadIdentity(); gPipeline.enableLightsPreview(); LLQuaternion camera_rot = LLQuaternion(mCameraPitch, LLVector3::y_axis) * @@ -3393,22 +3687,32 @@ BOOL LLModelPreview::render() if (!mBaseModel.empty() && mVertexBuffer[5].empty()) { - genBuffers(-1, avatar_preview); + genBuffers(-1, skin_weight); //genBuffers(3); //genLODs(); } - bool physics = mFMP->childGetValue("show physics").asBoolean(); S32 physics_idx = mFMP->childGetValue("physics_layer").asInteger(); if (!mModel[mPreviewLOD].empty()) { - if (mVertexBuffer[mPreviewLOD].empty()) + bool regen = mVertexBuffer[mPreviewLOD].empty(); + if (!regen) + { + const std::vector<LLPointer<LLVertexBuffer> >& vb_vec = mVertexBuffer[mPreviewLOD].begin()->second; + if (!vb_vec.empty()) + { + const LLVertexBuffer* buff = vb_vec[0]; + regen = buff->hasDataType(LLVertexBuffer::TYPE_WEIGHT4) != skin_weight; + } + } + + if (regen) { - genBuffers(mPreviewLOD, avatar_preview); + genBuffers(mPreviewLOD, skin_weight); } - if (!avatar_preview) + if (!skin_weight) { for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter) { @@ -3446,7 +3750,7 @@ BOOL LLModelPreview::render() gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); glColor3f(0.4f, 0.4f, 0.4f); - if (mFMP->childGetValue("show edges").asBoolean()) + if (edges) { glLineWidth(3.f); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); @@ -3527,7 +3831,7 @@ BOOL LLModelPreview::render() glColor4ubv(hull_colors[i].mV); buff->drawArrays(LLRender::TRIANGLES, 0, buff->getNumVerts()); - if (mFMP->childGetValue("show edges").asBoolean()) + if (edges) { glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glLineWidth(3.f); @@ -3572,7 +3876,7 @@ BOOL LLModelPreview::render() gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); glColor3f(0.4f, 0.4f, 0.4f); - if (mFMP->childGetValue("show edges").asBoolean() || model == physics_model) + if (edges || model == physics_model) { if (model == physics_model) { @@ -3604,7 +3908,10 @@ BOOL LLModelPreview::render() LLVector3::z_axis, // up target_pos); // point of interest - avatar->renderCollisionVolumes(); + if (joint_positions) + { + avatar->renderCollisionVolumes(); + } for (LLModelLoader::scene::iterator iter = mScene[mPreviewLOD].begin(); iter != mScene[mPreviewLOD].end(); ++iter) { @@ -3689,7 +3996,7 @@ BOOL LLModelPreview::render() buffer->draw(LLRender::TRIANGLES, buffer->getNumIndices(), 0); glColor3f(0.4f, 0.4f, 0.4f); - if (mFMP->childGetValue("show edges").asBoolean()) + if (edges) { glLineWidth(3.f); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); @@ -3770,6 +4077,7 @@ void LLModelPreview::setPreviewLOD(S32 lod) } } refresh(); + updateStatusMessages(); } //static @@ -3792,12 +4100,6 @@ void LLFloaterModelPreview::onUpload(void* user_data) mp->closeFloater(false); } -//static -void LLFloaterModelPreview::onConsolidate(void* user_data) -{ - LLFloaterModelPreview* mp = (LLFloaterModelPreview*) user_data; - mp->mModelPreview->consolidate(); -} //static void LLFloaterModelPreview::onClearMaterials(void* user_data) diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h index 05106644dc..4037a6976c 100644 --- a/indra/newview/llfloatermodelpreview.h +++ b/indra/newview/llfloatermodelpreview.h @@ -48,6 +48,8 @@ class domProfile_COMMON; class domInstance_geometry; class domNode; class domTranslate; +class LLMenuButton; +class LLToggleableMenu; class LLModelLoader : public LLThread { @@ -142,7 +144,6 @@ public: static void onUpload(void* data); - static void onConsolidate(void* data); static void onClearMaterials(void* data); static void onModelDecompositionComplete(LLModel* model, std::vector<LLPointer<LLVertexBuffer> >& physics_mesh); @@ -152,6 +153,14 @@ public: void loadModel(S32 lod); + void onViewOptionChecked(const LLSD& userdata); + bool isViewOptionChecked(const LLSD& userdata); + bool isViewOptionEnabled(const LLSD& userdata); + void setViewOptionEnabled(const std::string& option, bool enabled); + void enableViewOption(const std::string& option); + void disableViewOption(const std::string& option); + void setViewOption(const std::string& option, bool value); + protected: friend class LLModelPreview; friend class LLMeshFilePicker; @@ -163,12 +172,10 @@ protected: static void onPreviewLODCommit(LLUICtrl*,void*); - static void onTriangleLimitCommit(LLUICtrl*,void*); - static void onGenerateNormalsCommit(LLUICtrl*,void*); static void onAutoFillCommit(LLUICtrl*,void*); - static void onShowEdgesCommit(LLUICtrl*,void*); + static void onLODParamCommit(LLUICtrl*,void*); static void onExplodeCommit(LLUICtrl*, void*); @@ -186,9 +193,6 @@ protected: void draw(); - static void setLimit(S32 lod, void* userdata); - void setLimit(S32 lod, S32 limit); - void initDecompControls(); LLModelPreview* mModelPreview; @@ -204,6 +208,13 @@ protected: LLPointer<DecompRequest> mCurRequest; + std::map<std::string, bool> mViewOption; + + //use "disabled" as false by default + std::map<std::string, bool> mViewOptionDisabled; + + LLMenuButton* mViewOptionMenuButton; + LLToggleableMenu* mViewOptionMenu; }; @@ -253,6 +264,7 @@ class LLModelPreview : public LLViewerDynamicTexture, public LLMutex BOOL mNeedsUpdate; bool mDirty; + bool mGenLOD; U32 mTextureName; F32 mCameraDistance; F32 mCameraYaw; @@ -263,9 +275,15 @@ class LLModelPreview : public LLViewerDynamicTexture, public LLMutex LLVector3 mPreviewScale; S32 mPreviewLOD; U32 mResourceCost; - S32 mLimit[LLModel::NUM_LODS]; std::string mLODFile[LLModel::NUM_LODS]; + //GLOD object parameters (must rebuild object if these change) + F32 mBuildShareTolerance; + U32 mBuildQueueMode; + U32 mBuildOperator; + U32 mBuildBorderMode; + + LLModelLoader* mModelLoader; @@ -279,7 +297,7 @@ class LLModelPreview : public LLViewerDynamicTexture, public LLMutex std::map<LLPointer<LLModel>, U32> mObject; std::map<LLPointer<LLModel>, std::vector<U32> > mPatch; std::map<LLPointer<LLModel>, F32> mPercentage; - + U32 mMaxTriangleLimit; std::map<LLPointer<LLModel>, std::vector<LLPointer<LLVertexBuffer> > > mPhysicsMesh; LLMeshUploadThread::instance_list mUploadData; diff --git a/indra/newview/llmeshreduction.cpp b/indra/newview/llmeshreduction.cpp index b50b4cf063..14e8dd37b4 100644 --- a/indra/newview/llmeshreduction.cpp +++ b/indra/newview/llmeshreduction.cpp @@ -32,19 +32,8 @@ #include "glod/glod.h" -static BOOL stop_gloderror() -{ - GLuint error = glodGetError(); - - if (error != GLOD_NO_ERROR) - { - llwarns << "GLOD error detected: " << std::hex << error << llendl; - return TRUE; - } - - return FALSE; -} +#if 0 //not used ? void create_vertex_buffers_from_model(LLModel* model, std::vector<LLPointer <LLVertexBuffer> >& vertex_buffers) { @@ -280,4 +269,4 @@ LLPointer<LLModel> LLMeshReduction::reduce(LLModel* in_model, F32 limit, S32 mod return out_model; } - +#endif diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index b8030bfa91..e522159181 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -256,6 +256,10 @@ with the same filename but different name <texture name="menu_separator" file_name="navbar/FileMenu_Divider.png" scale.left="4" scale.top="166" scale.right="0" scale.bottom="0" /> + <texture name="ModelImport_Status_Good" file_name="lag_status_good.tga" preload="false"/> + <texture name="ModelImport_Status_Warning" file_name="lag_status_warning.tga" preload="false"/> + <texture name="ModelImport_Status_Error" file_name="lag_status_critical.tga" preload="false"/> + <texture name="MouseLook_View_Off" file_name="bottomtray/MouseLook_view_off.png" preload="false" /> <texture name="MouseLook_View_On" file_name="bottomtray/MouseLook_view_on.png" preload="false" /> diff --git a/indra/newview/skins/default/xui/en/floater_model_preview.xml b/indra/newview/skins/default/xui/en/floater_model_preview.xml index f1b6024ff7..952deb26f9 100644 --- a/indra/newview/skins/default/xui/en/floater_model_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_model_preview.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater can_close="true" can_drag_on_left="false" can_minimize="false" - can_resize="true" height="520" min_height="520" min_width="630" - name="Model Preview" title="Upload Model" width="630"> + can_resize="true" height="550" min_height="550" min_width="620" + name="Model Preview" title="Upload Model" width="620"> <string name="status_idle">Idle</string> <string name="status_reading_file">Loading...</string> @@ -10,103 +10,89 @@ <string name="medium">Medium</string> <string name="low">Low</string> <string name="lowest">Lowest</string> - <string name="mesh_status_good">Good</string> - <string name="mesh_status_bad">Bad</string>" + <string name="mesh_status_good">Ship it!</string> <string name="mesh_status_na">N/A</string> <string name="mesh_status_none">None</string> + <string name="mesh_status_submesh_mismatch">Levels of detail have a different number of textureable faces.</string> + <string name="mesh_status_mesh_mismatch">Levels of detail have a different number of mesh instances.</string> + <string name="mesh_status_too_many_vertices">Level of detail has too many vertices.</string> + <string name="mesh_status_missing_lod">Missing required level of detail.</string> <string name="layer_all">All</string> <!-- Text to display in physics layer combo box for "all layers" --> <text left="15" bottom="25" follows="top|left" height="15" name="name_label"> Name: </text> - <line_editor bottom_delta="20" follows="top|left|right" height="19" max_length="254" - name="description_form" width="310" /> - <text bottom_delta="24" follows="top|left" height="15" name="preview_label"> + <line_editor bottom_delta="20" follows="top|left|right" height="19" + name="description_form" width="290" /> + + <text bottom_delta="20" left="15" follows="left|top" height="15" name="lod_label"> Preview: </text> - - <!-- Placeholder panel for 3D preview render --> - <panel - name="preview_panel" - left="15" - width="310" - height="310" - follows="all"/> - - <text bottom_delta="25" left="15" width="100" follows="bottom|left" height="15" name="streaming cost"> - Prim Cost: [COST] - </text> - - <text right="320" width="100" height="15" bottom_delta="0" follows="bottom|right" name="status">[STATUS]</text> - - <text bottom_delta="20" left="15" follows="left|bottom" height="15" name="lod_label"> - Level of Detail: - </text> - <combo_box bottom_delta="20" follows="left|bottom" height="18" - name="preview_lod_combo" width="90" tool_tip="LOD to view in preview render"> + <combo_box bottom_delta="20" follows="left|top" height="18" + name="preview_lod_combo" width="240" tool_tip="LOD to view in preview render"> <combo_item name="lowest"> - Lowest + Level of Detail: Lowest </combo_item> <combo_item name="low"> - Low + Level of Detail: Low </combo_item> <combo_item name="medium"> - Medium + Level of Detail: Medium </combo_item> <combo_item name="high"> - High + Level of Detail: High </combo_item> </combo_box> - <check_box bottom="450" left="125" follows="left|bottom" label="Show Edges" name="show edges" width="120" height="16" tool_tip="Render wireframe in preview window"/> - <check_box bottom_delta="15" left="125" follows="left|bottom" label="Show Physics" name="show physics" width="120" height="16" tool_tip="Show physics shape."/> + <menu_button follows="top|left" + image_hover_unselected="Toolbar_Left_Over" + image_overlay="OptionsMenu_Off" + image_selected="Toolbar_Left_Selected" + image_unselected="Toolbar_Left_Off" + layout="topleft" + left_pad="5" + name="options_gear_btn" + width="31" + height="25"/> + <!-- Placeholder panel for 3D preview render --> + <panel + name="preview_panel" + left="15" + width="290" + height="290" + follows="all"/> - <button bottom="510" follows="bottom|left" height="20" label="Upload" - left="15" width="80" name="ok_btn" tool_tip="Upload to simulator"/> - <button left_pad="10" follows="left|bottom" height="20" width="80" label="Cancel" name="cancel_btn"/> + <text bottom_delta="25" left="25" width="100" follows="bottom|left">Upload Details</text> + <panel top_pad="5" border="true" left="15" width="290" height="70" follows="bottom|left" + bevel_style="in" bg_alpha_color="0 0 0 0" bg_opaque_color="0 0 0 0.3"> + <text left="25" follows="bottom|left" width="140" height="15" name="streaming cost"> + Resource Cost: [COST] + </text> + <text left="25" top_pad="5" width="140" follows="bottom|left" height="15" name="physics cost"> + Physics Cost: Unknown + </text> + <text left="25" top_pad="5" follows="bottom|left" height="15" name="upload fee"> + Upload Fee: N/A + </text> + </panel> + + <text left="10" bottom="540" width="290" height="15" follows="bottom|left|right" name="status">[STATUS]</text> + + + <button bottom="540" left="430" follows="bottom|right" height="20" label="Upload" + width="80" name="ok_btn" tool_tip="Upload to simulator"/> + <button left_pad="10" follows="right|bottom" height="20" width="80" label="Cancel" name="cancel_btn"/> <tab_container follows="right|top|bottom" top="15" - left="330" - height="475" - width="280" + left="310" + height="470" + width="300" name="import_tab" border="true" tab_position="top"> - <!-- MODIFIERS PANEL --> - <panel - border="true" - label="Modifiers" - name="modifiers_panel" - left="330" - width="280" - height="450"> - - <text left="10" width="90" bottom="30" follows="top|left" height="15"> - Scale: - </text> - <text left_pad="5" width="140" follows="top|left" height="15"> - Dimensions: - </text> - - <spinner left="10" height="20" follows="top|left" width="80" top_pad="5" value="1.0" min_val="0.01" max_val="64.0" name="import_scale"/> - - <text left_pad="20" height="15" name="import_dimensions" follows="top|left"> - [X] x [Y] x [Z] m - </text> - - <text left="10" top_pad="20" follows="top_left" height="15"> - Include: - </text> - - <check_box top_pad="5" name="upload_textures" height="15" follows="top|left" label="Textures"/> - <check_box top_pad="5" name="upload_skin" height="15" follows="top|left" label="Skin weight"/> - <check_box top_pad="5" left="20" name="upload_joints" height="15" follows="top|left" label="Joint positions"/> - </panel> - - <!-- LOD PANEL --> <panel border="true" @@ -124,60 +110,110 @@ <text valign="center" halign="center" bg_visible="true" name="high_label" left="10" top_pad="0" width="65" height="18" follows="left|top" value="High"/> <text valign="center" halign="center" bg_visible="true" name="high_triangles" left_pad="0" width="65" height="18" follows="left|top" value="0"/> <text valign="center" halign="center" bg_visible="true" name="high_vertices" left_pad="0" width="65" height="18" follows="left|top" value="0"/> - <text valign="center" halign="center" bg_visible="true" name="high_status" left_pad="0" width="65" height="18" follows="left|top" value="Good"/> + <text valign="center" halign="center" bg_visible="true" name="high_status" left_pad="0" width="65" height="18" follows="left|top" value=""/> + <icon height="16" width="16" image_name="lag_status_critical.tga" mouse_opaque="true" name="status_icon_high" left_delta="20" top_delta="0" /> <text valign="center" halign="center" bg_visible="true" name="medium_label" left="10" top_pad="0" width="65" height="18" follows="left|top" value="Medium"/> <text valign="center" halign="center" bg_visible="true" name="medium_triangles" left_pad="0" width="65" height="18" follows="left|top" value="0"/> <text valign="center" halign="center" bg_visible="true" name="medium_vertices" left_pad="0" width="65" height="18" follows="left|top" value="0"/> - <text valign="center" halign="center" bg_visible="true" name="medium_status" left_pad="0" width="65" height="18" follows="left|top" value="Good"/> + <text valign="center" halign="center" bg_visible="true" name="medium_status" left_pad="0" width="65" height="18" follows="left|top" value=""/> + <icon height="16" width="16" image_name="lag_status_critical.tga" mouse_opaque="true" name="status_icon_medium" left_delta="20" top_delta="0" /> <text valign="center" halign="center" bg_visible="true" name="low_label" left="10" top_pad="0" width="65" height="18" follows="left|top" value="Low"/> <text valign="center" halign="center" bg_visible="true" name="low_triangles" left_pad="0" width="65" height="18" follows="left|top" value="0"/> <text valign="center" halign="center" bg_visible="true" name="low_vertices" left_pad="0" width="65" height="18" follows="left|top" value="0"/> - <text valign="center" halign="center" bg_visible="true" name="low_status" left_pad="0" width="65" height="18" follows="left|top" value="Good"/> + <text valign="center" halign="center" bg_visible="true" name="low_status" left_pad="0" width="65" height="18" follows="left|top" value=""/> + <icon height="16" width="16" image_name="lag_status_critical.tga" mouse_opaque="true" name="status_icon_low" left_delta="20" top_delta="0" /> <text valign="center" halign="center" bg_visible="true" name="lowest_label" left="10" top_pad="0" width="65" height="18" follows="left|top" value="Lowest"/> <text valign="center" halign="center" bg_visible="true" name="lowest_triangles" left_pad="0" width="65" height="18" follows="left|top" value="0"/> <text valign="center" halign="center" bg_visible="true" name="lowest_vertices" left_pad="0" width="65" height="18" follows="left|top" value="0"/> - <text valign="center" halign="center" bg_visible="true" name="lowest_status" left_pad="0" width="65" height="18" follows="left|top" value="Good"/> - - <text left="10" width="240" height="15" top_pad="15" follows="left|top" name="lod_tabel_footer"> + <text valign="center" halign="center" bg_visible="true" name="lowest_status" left_pad="0" width="65" height="18" follows="left|top" value=""/> + <icon height="16" width="16" image_name="lag_status_critical.tga" mouse_opaque="true" name="status_icon_lowest" left_delta="20" top_delta="0" /> + + <text left="10" width="240" height="15" top_pad="15" follows="left|top" name="lod_table_footer"> Level of Detail: [DETAIL] </text> - <text top_pad="10" height="15" follows="left|top"> + <icon height="16" width="16" left="20" follows="left|top" name="lod_status_message_icon"/> + <text left_pad="5" width="200" height="15" follows="left|top" name="lod_status_message_text"/> + + <text top_pad="10" left="10" height="15" follows="left|top"> Mesh </text> - <radio_group follows="top|left" height="100" left="30" name="lod_file_or_limit" width="240" value="lod_from_file"> - <radio_item bottom="85" label="Load from file" name="lod_from_file"/> - <radio_item bottom="40" label="Auto generate" name="lod_auuto_generate"/> + <radio_group follows="top|left" height="210" left="30" name="lod_file_or_limit" width="240" value="lod_from_file"> + <radio_item bottom="195" label="Load from file" name="lod_from_file"/> + <radio_item bottom="150" label="Auto generate" name="lod_auto_generate"/> + <radio_item bottom="0" label="None" name="lod_none"/> </radio_group> - <line_editor follows="left|top" bottom_delta="-60" width="140" left="45" value="" name="lod_file" height="20"/> + <line_editor follows="left|top" bottom_delta="-170" width="140" left="45" value="" name="lod_file" height="20"/> <button bottom_delta="3" name="lod_browse" label="Browse..." left_pad="5" follows="left|top" width="70" height="25"/> - <text follows="top|left" top_pad="22" width="140" left="45" height="15"> - Triangle Limit: + <combo_box follows="top|left" name="lod_mode" top_pad="22" width="100" left="45" height="20"> + <combo_item name="triangle_limit"> + Triangle Limit + </combo_item> + <combo_item name="error_threshold"> + Error Threshold + </combo_item> + </combo_box> + <spinner follows="top|left" name="lod_triangle_limit" left_pad="5" height="20" width="100" decimal_digits="0" enabled="true"/> + <spinner left_delta="0" bottom_delta="0" follows="top|left" name="lod_error_threshold" min_val="0" max_val="100" height="20" width="100" decimal_digits="3" visible="false" enabled="true"/> + + <text follows="top|left" name="build_operator_text" left="45" top_pad="10" width="100" height="15"> + Build Operator: + </text> + <text follows="top|left" name="queue_mode_text" left_pad="5" width="100" height="15"> + Queue Mode: + </text> + <combo_box follows="top|left" name="build_operator" top_pad="5" left="45" width="100" height="20"> + <combo_item name="half_edge_collapse"> + Half Edge Collapse + </combo_item> + <combo_item name="edge_collapse"> + Edge Collapse + </combo_item> + </combo_box> + + <combo_box follows="top|left" name="queue_mode" left_pad="5" width="100" height="20"> + <combo_item name="greedy"> + Greedy + </combo_item> + <combo_item name="lazy"> + Lazy + </combo_item> + <combo_item name="independent"> + Independent + </combo_item> + </combo_box> + + <text top_pad="10" name="border_mode_text" left="45" follows="left|top" width="100" height="15"> + Border Mode: </text> - <spinner follows="top|left" name="lod_triangle_limit" top_pad="5" height="20" width="60" decimal_digits="0" enabled="true"/> - - <button bottom_delta="3" left_pad="5" name="lod_generate" label="Generate" height="25" width="70" follows="left|top"/> - <text name="submeshes_info" follows="left|top" left="10" top_pad="7" height="15 width=240"> - Layers: [SUBMESHES] + <text left_pad="5" name="share_tolderance_text" follows="left|top" width="100" height="15"> + Share Tolerance: </text> - <button left="30" follows="top|left" top_pad="5" name="clear_materials" label="Clear Materials" width="100" height="25"/> - <button left="30" follows="top|left" top_pad="5" name="consolidate" label="Consolidate" width="100" height="25"/> - <text left="10" top_pad="10" follows="top|left" width="240" height="15"> - Normals + <combo_box follows="left|top" left="45" height="20" name="border_mode" width="100"> + <combo_item name="border_unlock"> + Unlock + </combo_item> + <combo_item name="border_lock"> + Lock + </combo_item> + </combo_box> + <spinner follows="left|top" name="share_tolerance" left_pad="5" width="100" height="20"/> + + <text left="10" top_pad="35" follows="top|left" width="240" height="15"> + Generate Normals </text> <text left="35" top_pad="5" follows="top|left" width="100" height="15"> Crease Angle: </text> - <spinner follows="top|left" top_pad="5" min_val="0" max_val="180" value="75" width="60" height="20" name="crease_angle"/> - <button follows="top|left" bottom_delta="3" left_pad="5" width="140" height="25" label="Generate Normals" name="generate_normals"/> + <spinner follows="top|left" left_pad="5" min_val="0" max_val="180" value="75" width="60" height="20" name="crease_angle"/> </panel> <!-- PANEL --> @@ -341,8 +377,32 @@ </panel> </panel> - - + <!-- MODIFIERS PANEL --> + <panel + border="true" + label="Modifiers" + name="modifiers_panel"> + <text left="10" width="90" bottom="30" follows="top|left" height="15"> + Scale: + </text> + <text left_pad="5" width="140" follows="top|left" height="15"> + Dimensions: + </text> + + <spinner left="10" height="20" follows="top|left" width="80" top_pad="5" value="1.0" min_val="0.01" max_val="64.0" name="import_scale"/> + + <text left_pad="20" height="15" name="import_dimensions" follows="top|left"> + [X] x [Y] x [Z] m + </text> + + <text left="10" top_pad="20" follows="top|left" height="15"> + Include: + </text> + + <check_box top_pad="5" name="upload_textures" height="15" follows="top|left" label="Textures"/> + <check_box top_pad="5" name="upload_skin" height="15" follows="top|left" label="Skin weight"/> + <check_box top_pad="5" left="20" name="upload_joints" height="15" follows="top|left" label="Joint positions"/> + </panel> </tab_container> <!-- |