diff --git a/indra/newview/llfloatercustomize.cpp b/indra/newview/llfloatercustomize.cpp index 337cf1956..787d61c84 100644 --- a/indra/newview/llfloatercustomize.cpp +++ b/indra/newview/llfloatercustomize.cpp @@ -1700,17 +1700,11 @@ BOOL LLFloaterCustomize::postBuild() childSetAction("Make Outfit", LLFloaterCustomize::onBtnMakeOutfit, (void*)this); childSetAction("Ok", LLFloaterCustomize::onBtnOk, (void*)this); childSetAction("Cancel", LLFloater::onClickClose, (void*)this); - // OGPX : if using agent domain, disable saving appearance until inventory and assets is working - // since it doesn't work in OGP right now, disable it, since enabling it hits an error case. - // OGPX TODO: test with it enabled with Agent Domain that manages Inventory and Assets - // This was originally added as part of OGP9 svn branch because the viewer deeply deeply - // assumes that there *will* be an inventory there. If you never get an inventory, - // Make Outfit breaks badly. - //if (!gSavedSettings.getString("CmdLineRegionURI").empty()) - //{ - // childSetEnabled("Make Outfit", FALSE); - //} + // reX + childSetAction("Import", LLFloaterCustomize::onBtnImport, (void*)this); + childSetAction("Export", LLFloaterCustomize::onBtnExport, (void*)this); + // Wearable panels initWearablePanels(); @@ -1779,6 +1773,128 @@ void LLFloaterCustomize::setCurrentWearableType( EWearableType type ) } } +// reX: new function +void LLFloaterCustomize::onBtnImport( void* userdata ) +{ + LLFilePicker& file_picker = LLFilePicker::instance(); + if( !file_picker.getOpenFile( LLFilePicker::FFLOAD_XML ) ) + { + // User canceled import. + return; + } + + const std::string filename = file_picker.getFirstFile(); + + FILE* fp = LLFile::fopen(filename, "rb"); + + //char text_buffer[2048]; /* Flawfinder: ignore */ + S32 c; + S32 typ; + S32 count; + S32 param_id=0; + F32 param_weight=0; + S32 fields_read; + + for( S32 i=0; i < WT_COUNT; i++ ) + { + fields_read = fscanf( fp, "type %d\n", &typ); + if( fields_read != 1 ) + { + llwarns << "Bad asset type: early end of file" << llendl; + return; + } + + fields_read = fscanf( fp, "parameters %d\n", &count); + if( fields_read != 1 ) + { + llwarns << "Bad parameters : early end of file" << llendl; + return; + } + for(c=0;csetVisualParamWeight( param_id, param_weight, TRUE); + gAgent.getAvatarObject()->updateVisualParams(); + } + } + + fclose(fp); + return; +} + +// reX: new function +void LLFloaterCustomize::onBtnExport( void* userdata ) +{ + LLFilePicker& file_picker = LLFilePicker::instance(); + if( !file_picker.getSaveFile( LLFilePicker::FFSAVE_XML ) ) + { + // User canceled export. + return; + } + + LLViewerInventoryItem* item; + BOOL is_modifiable; + + const std::string filename = file_picker.getFirstFile(); + + FILE* fp = LLFile::fopen(filename, "wb"); + + for( S32 i=0; i < WT_COUNT; i++ ) + { + is_modifiable = FALSE; + LLWearable* old_wearable = gAgent.getWearable((EWearableType)i); + if( old_wearable ) + { + item = (LLViewerInventoryItem*)gAgent.getWearableInventoryItem((EWearableType)i); + if(item) + { + const LLPermissions& perm = item->getPermissions(); + is_modifiable = perm.allowModifyBy(gAgent.getID(), gAgent.getGroupID()); + } + } + if (is_modifiable) + { + old_wearable->FileExportParams(fp); + } + if (!is_modifiable) + { + fprintf( fp, "type %d\n",i); + fprintf( fp, "parameters 0\n"); + } + } + + for( S32 i=0; i < WT_COUNT; i++ ) + { + is_modifiable = FALSE; + LLWearable* old_wearable = gAgent.getWearable((EWearableType)i); + if( old_wearable ) + { + item = (LLViewerInventoryItem*)gAgent.getWearableInventoryItem((EWearableType)i); + if(item) + { + const LLPermissions& perm = item->getPermissions(); + is_modifiable = perm.allowModifyBy(gAgent.getID(), gAgent.getGroupID()); + } + } + if (is_modifiable) + { + old_wearable->FileExportTextures(fp); + } + if (!is_modifiable) + { + fprintf( fp, "type %d\n",i); + fprintf( fp, "textures 0\n"); + } + } + + fclose(fp); +} + // static void LLFloaterCustomize::onBtnOk( void* userdata ) { diff --git a/indra/newview/llfloatercustomize.h b/indra/newview/llfloatercustomize.h index 28a525e4f..5648cc6af 100644 --- a/indra/newview/llfloatercustomize.h +++ b/indra/newview/llfloatercustomize.h @@ -109,6 +109,8 @@ public: static void onBtnOk( void* userdata ); static void onBtnMakeOutfit( void* userdata ); static void onMakeOutfitCommit( LLMakeOutfitDialog* dialog, void* userdata ); + static void onBtnImport( void* userdata ); + static void onBtnExport( void* userdata ); static void onTabChanged( void* userdata, bool from_click ); static void onTabPrecommit( void* userdata, bool from_click ); diff --git a/indra/newview/llwearable.cpp b/indra/newview/llwearable.cpp index 75e0f2a62..f83fa4dbb 100644 --- a/indra/newview/llwearable.cpp +++ b/indra/newview/llwearable.cpp @@ -194,6 +194,50 @@ std::string terse_F32_to_string( F32 f ) return r; } +// reX: new function +BOOL LLWearable::FileExportParams( FILE* file ) +{ + // wearable type + S32 type = (S32)mType; + fprintf( file, "type %d\n", type ); + + // parameters + S32 num_parameters = mVisualParamMap.size(); + fprintf( file, "parameters %d\n", num_parameters ); + + for (param_map_t::iterator iter = mVisualParamMap.begin(); + iter != mVisualParamMap.end(); ++iter) + { + S32 param_id = iter->first; + F32 param_weight = iter->second; + fprintf( file, "%d %s\n", param_id, terse_F32_to_string(param_weight).c_str() ); + } + + return TRUE; +} + +// reX: new function +BOOL LLWearable::FileExportTextures( FILE* file ) +{ + // wearable type + S32 type = (S32)mType; + fprintf( file, "type %d\n", type ); + + // texture entries + S32 num_textures = mTEMap.size(); + fprintf( file, "textures %d\n", num_textures ); + + for (te_map_t::iterator iter = mTEMap.begin(); + iter != mTEMap.end(); ++iter) + { + S32 te = iter->first; + LLUUID& image_id = iter->second; + fprintf( file, "%d %s\n", te, image_id.asString().c_str() ); + } + + return TRUE; +} + BOOL LLWearable::exportFile( LLFILE* file ) { // header and version diff --git a/indra/newview/llwearable.h b/indra/newview/llwearable.h index 4ad882b8b..253ae97b0 100644 --- a/indra/newview/llwearable.h +++ b/indra/newview/llwearable.h @@ -81,6 +81,9 @@ public: BOOL exportFile(LLFILE* file); BOOL importFile(LLFILE* file); + BOOL FileExportParams(FILE* file); + BOOL FileExportTextures(FILE* file); + EWearableType getType() const { return mType; } void setType( EWearableType type ) { mType = type; } diff --git a/indra/newview/skins/default/xui/en-us/floater_customize.xml b/indra/newview/skins/default/xui/en-us/floater_customize.xml index 17b3a5f37..2dea4626a 100644 --- a/indra/newview/skins/default/xui/en-us/floater_customize.xml +++ b/indra/newview/skins/default/xui/en-us/floater_customize.xml @@ -1319,6 +1319,12 @@ scratch and wear it. left="8" mouse_opaque="true" name="HeightTextI" v_pad="0" width="140"> (imperial) +