diff options
author | Jacek Antonelli | 2009-09-05 02:23:52 -0500 |
---|---|---|
committer | Jacek Antonelli | 2009-09-05 02:23:52 -0500 |
commit | acfc1b1163df4fe5b238546de5697b435cd0c79e (patch) | |
tree | 3764ee586d2464dd057c4c82ab27cc66e7e1b0f3 /linden/indra/newview | |
parent | Converted RLVa menu items to XUI. (diff) | |
parent | Updated object backup feature to Meerkat's SVN, imported floater. (diff) | |
download | meta-impy-acfc1b1163df4fe5b238546de5697b435cd0c79e.zip meta-impy-acfc1b1163df4fe5b238546de5697b435cd0c79e.tar.gz meta-impy-acfc1b1163df4fe5b238546de5697b435cd0c79e.tar.bz2 meta-impy-acfc1b1163df4fe5b238546de5697b435cd0c79e.tar.xz |
Merge branch 'objectbackup' into next
Diffstat (limited to 'linden/indra/newview')
-rw-r--r-- | linden/indra/newview/CMakeLists.txt | 2 | ||||
-rw-r--r-- | linden/indra/newview/app_settings/settings.xml | 16 | ||||
-rw-r--r-- | linden/indra/newview/llviewermenu.cpp | 145 | ||||
-rw-r--r-- | linden/indra/newview/llviewerobjectlist.cpp | 26 | ||||
-rw-r--r-- | linden/indra/newview/primbackup.cpp | 1105 | ||||
-rw-r--r-- | linden/indra/newview/primbackup.h | 132 | ||||
-rw-r--r-- | linden/indra/newview/skins/default/xui/en-us/floater_prim_import.xml | 5 | ||||
-rw-r--r-- | linden/indra/newview/skins/default/xui/en-us/menu_pie_object.xml | 6 | ||||
-rw-r--r-- | linden/indra/newview/skins/default/xui/en-us/menu_viewer.xml | 8 |
9 files changed, 1430 insertions, 15 deletions
diff --git a/linden/indra/newview/CMakeLists.txt b/linden/indra/newview/CMakeLists.txt index 1fc7549..bd38476 100644 --- a/linden/indra/newview/CMakeLists.txt +++ b/linden/indra/newview/CMakeLists.txt | |||
@@ -431,6 +431,7 @@ set(viewer_SOURCE_FILES | |||
431 | llxmlrpctransaction.cpp | 431 | llxmlrpctransaction.cpp |
432 | noise.cpp | 432 | noise.cpp |
433 | pipeline.cpp | 433 | pipeline.cpp |
434 | primbackup.cpp | ||
434 | rlvhandler.cpp | 435 | rlvhandler.cpp |
435 | rlvhelper.cpp | 436 | rlvhelper.cpp |
436 | rlvmultistringsearch.cpp | 437 | rlvmultistringsearch.cpp |
@@ -836,6 +837,7 @@ set(viewer_HEADER_FILES | |||
836 | macmain.h | 837 | macmain.h |
837 | noise.h | 838 | noise.h |
838 | pipeline.h | 839 | pipeline.h |
840 | primbackup.h | ||
839 | randgauss.h | 841 | randgauss.h |
840 | VertexCache.h | 842 | VertexCache.h |
841 | VorbisFramework.h | 843 | VorbisFramework.h |
diff --git a/linden/indra/newview/app_settings/settings.xml b/linden/indra/newview/app_settings/settings.xml index 628936c..ca9d53d 100644 --- a/linden/indra/newview/app_settings/settings.xml +++ b/linden/indra/newview/app_settings/settings.xml | |||
@@ -3215,6 +3215,22 @@ | |||
3215 | <integer>0</integer> | 3215 | <integer>0</integer> |
3216 | </array> | 3216 | </array> |
3217 | </map> | 3217 | </map> |
3218 | <key>FloaterPrimImport</key> | ||
3219 | <map> | ||
3220 | <key>Comment</key> | ||
3221 | <string>Rectangle for import/export</string> | ||
3222 | <key>Persist</key> | ||
3223 | <integer>1</integer> | ||
3224 | <key>Type</key> | ||
3225 | <string>Rect</string> | ||
3226 | <key>Value</key> | ||
3227 | <array> | ||
3228 | <integer>0</integer> | ||
3229 | <integer>25</integer> | ||
3230 | <integer>400</integer> | ||
3231 | <integer>0</integer> | ||
3232 | </array> | ||
3233 | </map> | ||
3218 | <key>FloaterRegionInfo</key> | 3234 | <key>FloaterRegionInfo</key> |
3219 | <map> | 3235 | <map> |
3220 | <key>Comment</key> | 3236 | <key>Comment</key> |
diff --git a/linden/indra/newview/llviewermenu.cpp b/linden/indra/newview/llviewermenu.cpp index 415064d..1560414 100644 --- a/linden/indra/newview/llviewermenu.cpp +++ b/linden/indra/newview/llviewermenu.cpp | |||
@@ -209,6 +209,7 @@ | |||
209 | #include "llwaterparammanager.h" | 209 | #include "llwaterparammanager.h" |
210 | 210 | ||
211 | #include "lltexlayer.h" | 211 | #include "lltexlayer.h" |
212 | #include "primbackup.h" | ||
212 | 213 | ||
213 | void init_client_menu(LLMenuGL* menu); | 214 | void init_client_menu(LLMenuGL* menu); |
214 | void init_server_menu(LLMenuGL* menu); | 215 | void init_server_menu(LLMenuGL* menu); |
@@ -2261,6 +2262,143 @@ class LLObjectMute : public view_listener_t | |||
2261 | } | 2262 | } |
2262 | }; | 2263 | }; |
2263 | 2264 | ||
2265 | class LLObjectEnableCopyUUID : public view_listener_t | ||
2266 | { | ||
2267 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | ||
2268 | { | ||
2269 | LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); | ||
2270 | bool new_value = (object != NULL); | ||
2271 | |||
2272 | gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); | ||
2273 | return true; | ||
2274 | } | ||
2275 | }; | ||
2276 | |||
2277 | class LLObjectCopyUUID : public view_listener_t | ||
2278 | { | ||
2279 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | ||
2280 | { | ||
2281 | LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); | ||
2282 | if (!object) return true; | ||
2283 | |||
2284 | LLUUID id = object->getID(); | ||
2285 | |||
2286 | char buffer[UUID_STR_LENGTH]; | ||
2287 | id.toString(buffer); | ||
2288 | |||
2289 | |||
2290 | gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(buffer)); | ||
2291 | |||
2292 | LLSelectMgr::getInstance()->deselectAll(); | ||
2293 | return true; | ||
2294 | } | ||
2295 | }; | ||
2296 | |||
2297 | |||
2298 | class LLObjectEnableExport : public view_listener_t | ||
2299 | { | ||
2300 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | ||
2301 | { | ||
2302 | LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); | ||
2303 | bool new_value = (object != NULL); | ||
2304 | if (new_value) | ||
2305 | { | ||
2306 | LLVOAvatar* avatar = find_avatar_from_object(object); | ||
2307 | new_value = (avatar == NULL); | ||
2308 | } | ||
2309 | if(new_value) | ||
2310 | { | ||
2311 | |||
2312 | struct ff : public LLSelectedNodeFunctor | ||
2313 | { | ||
2314 | ff(const LLSD& data) : LLSelectedNodeFunctor() | ||
2315 | ,userdata(data) | ||
2316 | { | ||
2317 | |||
2318 | } | ||
2319 | const LLSD& userdata; | ||
2320 | virtual bool apply(LLSelectNode* node) | ||
2321 | { | ||
2322 | if(gAgent.getID()!=node->mPermissions->getCreator()) | ||
2323 | { | ||
2324 | llwarns<<"Incorrect permission to export"<<llendl; | ||
2325 | return false; | ||
2326 | } | ||
2327 | return true; | ||
2328 | } | ||
2329 | }; | ||
2330 | |||
2331 | #ifdef LL_GRID_PERMISSIONS | ||
2332 | |||
2333 | ff * the_ff=new ff(userdata); | ||
2334 | if(LLSelectMgr::getInstance()->getSelection()->applyToNodes(the_ff,false)) | ||
2335 | { | ||
2336 | gMenuHolder->findControl(userdata["control"].asString())->setValue(true); | ||
2337 | } | ||
2338 | else | ||
2339 | { | ||
2340 | gMenuHolder->findControl(userdata["control"].asString())->setValue(false); | ||
2341 | } | ||
2342 | return true; | ||
2343 | } | ||
2344 | |||
2345 | gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); | ||
2346 | return true; | ||
2347 | #else | ||
2348 | } | ||
2349 | gMenuHolder->findControl(userdata["control"].asString())->setValue(true); | ||
2350 | return true; | ||
2351 | #endif | ||
2352 | |||
2353 | } | ||
2354 | }; | ||
2355 | |||
2356 | class LLObjectExport : public view_listener_t | ||
2357 | { | ||
2358 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | ||
2359 | { | ||
2360 | LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); | ||
2361 | if (!object) return true; | ||
2362 | |||
2363 | LLVOAvatar* avatar = find_avatar_from_object(object); | ||
2364 | |||
2365 | if (!avatar) | ||
2366 | { | ||
2367 | primbackup::getInstance()->pre_export_object(); | ||
2368 | } | ||
2369 | |||
2370 | return true; | ||
2371 | } | ||
2372 | }; | ||
2373 | |||
2374 | |||
2375 | class LLObjectEnableImport : public view_listener_t | ||
2376 | { | ||
2377 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | ||
2378 | { | ||
2379 | gMenuHolder->findControl(userdata["control"].asString())->setValue(TRUE); | ||
2380 | return true; | ||
2381 | } | ||
2382 | }; | ||
2383 | |||
2384 | class LLObjectImport : public view_listener_t | ||
2385 | { | ||
2386 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | ||
2387 | { | ||
2388 | primbackup::getInstance()->import_object(FALSE); | ||
2389 | return true; | ||
2390 | } | ||
2391 | }; | ||
2392 | |||
2393 | class LLObjectImportUpload : public view_listener_t | ||
2394 | { | ||
2395 | bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) | ||
2396 | { | ||
2397 | primbackup::getInstance()->import_object(TRUE); | ||
2398 | return true; | ||
2399 | } | ||
2400 | }; | ||
2401 | |||
2264 | bool handle_go_to() | 2402 | bool handle_go_to() |
2265 | { | 2403 | { |
2266 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) | 2404 | // [RLVa:KB] - Checked: 2009-07-06 (RLVa-1.0.0c) |
@@ -10279,6 +10417,10 @@ void initialize_menus() | |||
10279 | addMenu(new LLObjectBuy(), "Object.Buy"); | 10417 | addMenu(new LLObjectBuy(), "Object.Buy"); |
10280 | addMenu(new LLObjectEdit(), "Object.Edit"); | 10418 | addMenu(new LLObjectEdit(), "Object.Edit"); |
10281 | addMenu(new LLObjectInspect(), "Object.Inspect"); | 10419 | addMenu(new LLObjectInspect(), "Object.Inspect"); |
10420 | addMenu(new LLObjectCopyUUID(), "Object.CopyUUID"); | ||
10421 | addMenu(new LLObjectExport(), "Object.Export"); | ||
10422 | addMenu(new LLObjectImport(), "Object.Import"); | ||
10423 | addMenu(new LLObjectImportUpload(), "Object.ImportUpload"); | ||
10282 | 10424 | ||
10283 | addMenu(new LLObjectEnableOpen(), "Object.EnableOpen"); | 10425 | addMenu(new LLObjectEnableOpen(), "Object.EnableOpen"); |
10284 | addMenu(new LLObjectEnableTouch(), "Object.EnableTouch"); | 10426 | addMenu(new LLObjectEnableTouch(), "Object.EnableTouch"); |
@@ -10289,6 +10431,9 @@ void initialize_menus() | |||
10289 | addMenu(new LLObjectEnableReportAbuse(), "Object.EnableReportAbuse"); | 10431 | addMenu(new LLObjectEnableReportAbuse(), "Object.EnableReportAbuse"); |
10290 | addMenu(new LLObjectEnableMute(), "Object.EnableMute"); | 10432 | addMenu(new LLObjectEnableMute(), "Object.EnableMute"); |
10291 | addMenu(new LLObjectEnableBuy(), "Object.EnableBuy"); | 10433 | addMenu(new LLObjectEnableBuy(), "Object.EnableBuy"); |
10434 | addMenu(new LLObjectEnableCopyUUID(), "Object.EnableCopyUUID"); | ||
10435 | addMenu(new LLObjectEnableExport(), "Object.EnableExport"); | ||
10436 | addMenu(new LLObjectEnableImport(), "Object.EnableImport"); | ||
10292 | 10437 | ||
10293 | /*addMenu(new LLObjectVisibleTouch(), "Object.VisibleTouch"); | 10438 | /*addMenu(new LLObjectVisibleTouch(), "Object.VisibleTouch"); |
10294 | addMenu(new LLObjectVisibleCustomTouch(), "Object.VisibleCustomTouch"); | 10439 | addMenu(new LLObjectVisibleCustomTouch(), "Object.VisibleCustomTouch"); |
diff --git a/linden/indra/newview/llviewerobjectlist.cpp b/linden/indra/newview/llviewerobjectlist.cpp index 9ccbf99..78c1730 100644 --- a/linden/indra/newview/llviewerobjectlist.cpp +++ b/linden/indra/newview/llviewerobjectlist.cpp | |||
@@ -74,6 +74,8 @@ | |||
74 | 74 | ||
75 | #include "llappviewer.h" | 75 | #include "llappviewer.h" |
76 | 76 | ||
77 | #include "primbackup.h" | ||
78 | |||
77 | extern F32 gMinObjectDistance; | 79 | extern F32 gMinObjectDistance; |
78 | extern BOOL gAnimateTextures; | 80 | extern BOOL gAnimateTextures; |
79 | 81 | ||
@@ -163,8 +165,6 @@ U64 LLViewerObjectList::getIndex(const U32 local_id, | |||
163 | 165 | ||
164 | BOOL LLViewerObjectList::removeFromLocalIDTable(const LLViewerObject &object) | 166 | BOOL LLViewerObjectList::removeFromLocalIDTable(const LLViewerObject &object) |
165 | { | 167 | { |
166 | if(object.getRegion()) | ||
167 | { | ||
168 | U32 local_id = object.mLocalID; | 168 | U32 local_id = object.mLocalID; |
169 | LLHost region_host = object.getRegion()->getHost(); | 169 | LLHost region_host = object.getRegion()->getHost(); |
170 | U32 ip = region_host.getAddress(); | 170 | U32 ip = region_host.getAddress(); |
@@ -176,9 +176,6 @@ BOOL LLViewerObjectList::removeFromLocalIDTable(const LLViewerObject &object) | |||
176 | return sIndexAndLocalIDToUUID.erase(indexid) > 0 ? TRUE : FALSE; | 176 | return sIndexAndLocalIDToUUID.erase(indexid) > 0 ? TRUE : FALSE; |
177 | } | 177 | } |
178 | 178 | ||
179 | return FALSE ; | ||
180 | } | ||
181 | |||
182 | void LLViewerObjectList::setUUIDAndLocal(const LLUUID &id, | 179 | void LLViewerObjectList::setUUIDAndLocal(const LLUUID &id, |
183 | const U32 local_id, | 180 | const U32 local_id, |
184 | const U32 ip, | 181 | const U32 ip, |
@@ -222,6 +219,11 @@ void LLViewerObjectList::processUpdateCore(LLViewerObject* objectp, | |||
222 | 219 | ||
223 | updateActive(objectp); | 220 | updateActive(objectp); |
224 | 221 | ||
222 | if(!just_created) | ||
223 | primbackup::getInstance()->prim_update(objectp); | ||
224 | |||
225 | |||
226 | |||
225 | if (just_created) | 227 | if (just_created) |
226 | { | 228 | { |
227 | gPipeline.addObject(objectp); | 229 | gPipeline.addObject(objectp); |
@@ -251,6 +253,9 @@ void LLViewerObjectList::processUpdateCore(LLViewerObject* objectp, | |||
251 | objectp->mCreateSelected = false; | 253 | objectp->mCreateSelected = false; |
252 | gViewerWindow->getWindow()->decBusyCount(); | 254 | gViewerWindow->getWindow()->decBusyCount(); |
253 | gViewerWindow->getWindow()->setCursor( UI_CURSOR_ARROW ); | 255 | gViewerWindow->getWindow()->setCursor( UI_CURSOR_ARROW ); |
256 | |||
257 | primbackup::getInstance()->newprim(objectp); | ||
258 | |||
254 | } | 259 | } |
255 | } | 260 | } |
256 | 261 | ||
@@ -827,17 +832,10 @@ void LLViewerObjectList::removeDrawable(LLDrawable* drawablep) | |||
827 | 832 | ||
828 | for (S32 i = 0; i < drawablep->getNumFaces(); i++) | 833 | for (S32 i = 0; i < drawablep->getNumFaces(); i++) |
829 | { | 834 | { |
830 | LLFace* facep = drawablep->getFace(i) ; | 835 | LLViewerObject* objectp = drawablep->getFace(i)->getViewerObject(); |
831 | if(facep) | ||
832 | { | ||
833 | LLViewerObject* objectp = facep->getViewerObject(); | ||
834 | if(objectp) | ||
835 | { | ||
836 | mSelectPickList.erase(objectp); | 836 | mSelectPickList.erase(objectp); |
837 | } | 837 | } |
838 | } | 838 | } |
839 | } | ||
840 | } | ||
841 | 839 | ||
842 | BOOL LLViewerObjectList::killObject(LLViewerObject *objectp) | 840 | BOOL LLViewerObjectList::killObject(LLViewerObject *objectp) |
843 | { | 841 | { |
@@ -914,7 +912,7 @@ void LLViewerObjectList::killAllObjects() | |||
914 | if (!mMapObjects.empty()) | 912 | if (!mMapObjects.empty()) |
915 | { | 913 | { |
916 | llwarns << "Some objects still on map object list!" << llendl; | 914 | llwarns << "Some objects still on map object list!" << llendl; |
917 | mMapObjects.clear(); | 915 | mActiveObjects.clear(); |
918 | } | 916 | } |
919 | } | 917 | } |
920 | 918 | ||
diff --git a/linden/indra/newview/primbackup.cpp b/linden/indra/newview/primbackup.cpp new file mode 100644 index 0000000..78fd482 --- /dev/null +++ b/linden/indra/newview/primbackup.cpp | |||
@@ -0,0 +1,1105 @@ | |||
1 | |||
2 | #include "llviewerprecompiledheaders.h" | ||
3 | #include "llviewermenu.h" | ||
4 | |||
5 | |||
6 | // system library includes | ||
7 | #include <iostream> | ||
8 | #include <fstream> | ||
9 | #include <sstream> | ||
10 | |||
11 | // linden library includes | ||
12 | #include "llfilepicker.h" | ||
13 | #include "indra_constants.h" | ||
14 | #include "llsdserialize.h" | ||
15 | #include "llsdutil.h" | ||
16 | |||
17 | #include "llcallbacklist.h" | ||
18 | |||
19 | // newview includes | ||
20 | #include "llagent.h" | ||
21 | #include "llselectmgr.h" | ||
22 | #include "lltoolplacer.h" | ||
23 | |||
24 | #include "lltexturecache.h" | ||
25 | |||
26 | #include "llnotify.h" | ||
27 | |||
28 | #include "llapr.h" | ||
29 | #include "lldir.h" | ||
30 | #include "llimage.h" | ||
31 | #include "lllfsthread.h" | ||
32 | #include "llviewercontrol.h" | ||
33 | #include "llassetuploadresponders.h" | ||
34 | #include "lleconomy.h" | ||
35 | #include "llhttpclient.h" | ||
36 | #include "lluploaddialog.h" | ||
37 | #include "lldir.h" | ||
38 | #include "llinventorymodel.h" // gInventory | ||
39 | #include "llviewercontrol.h" // gSavedSettings | ||
40 | #include "llviewermenu.h" // gMenuHolder | ||
41 | #include "llagent.h" | ||
42 | #include "llfilepicker.h" | ||
43 | #include "llfloateranimpreview.h" | ||
44 | #include "llfloaterbuycurrency.h" | ||
45 | #include "llfloaterimagepreview.h" | ||
46 | #include "llfloaternamedesc.h" | ||
47 | #include "llfloatersnapshot.h" | ||
48 | #include "llinventorymodel.h" // gInventory | ||
49 | #include "llresourcedata.h" | ||
50 | #include "llstatusbar.h" | ||
51 | #include "llviewercontrol.h" // gSavedSettings | ||
52 | #include "llviewerimagelist.h" | ||
53 | #include "lluictrlfactory.h" | ||
54 | #include "llviewermenu.h" // gMenuHolder | ||
55 | #include "llviewerregion.h" | ||
56 | #include "llviewerstats.h" | ||
57 | #include "llviewerwindow.h" | ||
58 | #include "llappviewer.h" | ||
59 | #include "lluploaddialog.h" | ||
60 | // Included to allow LLTextureCache::purgeTextures() to pause watchdog timeout | ||
61 | #include "llappviewer.h" | ||
62 | #include "lltransactiontypes.h" | ||
63 | |||
64 | #include "primbackup.h" | ||
65 | |||
66 | #include "llviewerobjectlist.h" | ||
67 | |||
68 | primbackup* primbackup::sInstance = 0; | ||
69 | |||
70 | class importResponder: public LLNewAgentInventoryResponder | ||
71 | { | ||
72 | public: | ||
73 | |||
74 | importResponder(const LLSD& post_data, | ||
75 | const LLUUID& vfile_id, | ||
76 | LLAssetType::EType asset_type) | ||
77 | : LLNewAgentInventoryResponder(post_data, vfile_id, asset_type) | ||
78 | { | ||
79 | } | ||
80 | |||
81 | |||
82 | //virtual | ||
83 | virtual void uploadComplete(const LLSD& content) | ||
84 | { | ||
85 | lldebugs << "LLNewAgentInventoryResponder::result from capabilities" << llendl; | ||
86 | |||
87 | LLAssetType::EType asset_type = LLAssetType::lookup(mPostData["asset_type"].asString()); | ||
88 | LLInventoryType::EType inventory_type = LLInventoryType::lookup(mPostData["inventory_type"].asString()); | ||
89 | |||
90 | // Update L$ and ownership credit information | ||
91 | // since it probably changed on the server | ||
92 | if (asset_type == LLAssetType::AT_TEXTURE || | ||
93 | asset_type == LLAssetType::AT_SOUND || | ||
94 | asset_type == LLAssetType::AT_ANIMATION) | ||
95 | { | ||
96 | gMessageSystem->newMessageFast(_PREHASH_MoneyBalanceRequest); | ||
97 | gMessageSystem->nextBlockFast(_PREHASH_AgentData); | ||
98 | gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); | ||
99 | gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); | ||
100 | gMessageSystem->nextBlockFast(_PREHASH_MoneyData); | ||
101 | gMessageSystem->addUUIDFast(_PREHASH_TransactionID, LLUUID::null ); | ||
102 | gAgent.sendReliableMessage(); | ||
103 | |||
104 | // LLStringUtil::format_map_t args; | ||
105 | // args["[AMOUNT]"] = llformat("%d",LLGlobalEconomy::Singleton::getInstance()->getPriceUpload()); | ||
106 | // LLNotifyBox::showXml("UploadPayment", args); | ||
107 | } | ||
108 | |||
109 | // Actually add the upload to viewer inventory | ||
110 | llinfos << "Adding " << content["new_inventory_item"].asUUID() << " " | ||
111 | << content["new_asset"].asUUID() << " to inventory." << llendl; | ||
112 | if(mPostData["folder_id"].asUUID().notNull()) | ||
113 | { | ||
114 | LLPermissions perm; | ||
115 | U32 next_owner_perm; | ||
116 | perm.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null); | ||
117 | if (mPostData["inventory_type"].asString() == "snapshot") | ||
118 | { | ||
119 | next_owner_perm = PERM_ALL; | ||
120 | } | ||
121 | else | ||
122 | { | ||
123 | next_owner_perm = PERM_MOVE | PERM_TRANSFER; | ||
124 | } | ||
125 | perm.initMasks(PERM_ALL, PERM_ALL, PERM_NONE, PERM_NONE, next_owner_perm); | ||
126 | S32 creation_date_now = time_corrected(); | ||
127 | LLPointer<LLViewerInventoryItem> item | ||
128 | = new LLViewerInventoryItem(content["new_inventory_item"].asUUID(), | ||
129 | mPostData["folder_id"].asUUID(), | ||
130 | perm, | ||
131 | content["new_asset"].asUUID(), | ||
132 | asset_type, | ||
133 | inventory_type, | ||
134 | mPostData["name"].asString(), | ||
135 | mPostData["description"].asString(), | ||
136 | LLSaleInfo::DEFAULT, | ||
137 | LLInventoryItem::II_FLAGS_NONE, | ||
138 | creation_date_now); | ||
139 | gInventory.updateItem(item); | ||
140 | gInventory.notifyObservers(); | ||
141 | } | ||
142 | else | ||
143 | { | ||
144 | llwarns << "Can't find a folder to put it in" << llendl; | ||
145 | } | ||
146 | |||
147 | // remove the "Uploading..." message | ||
148 | LLUploadDialog::modalUploadFinished(); | ||
149 | |||
150 | primbackup::getInstance()->update_map(content["new_asset"].asUUID()); | ||
151 | primbackup::getInstance()->upload_next_asset(); | ||
152 | |||
153 | } | ||
154 | |||
155 | }; | ||
156 | |||
157 | |||
158 | |||
159 | class CacheReadResponder : public LLTextureCache::ReadResponder | ||
160 | { | ||
161 | public: | ||
162 | CacheReadResponder(const LLUUID& id, LLImageFormatted* image) | ||
163 | : mFormattedImage(image), mID(id) | ||
164 | { | ||
165 | setImage(image); | ||
166 | } | ||
167 | void setData(U8* data, S32 datasize, S32 imagesize, S32 imageformat, BOOL imagelocal) | ||
168 | { | ||
169 | if(imageformat==IMG_CODEC_TGA && mFormattedImage->getCodec()==IMG_CODEC_J2C) | ||
170 | { | ||
171 | llwarns<<"Bleh its a tga not saving"<<llendl; | ||
172 | mFormattedImage=NULL; | ||
173 | mImageSize=0; | ||
174 | return; | ||
175 | } | ||
176 | |||
177 | if (mFormattedImage.notNull()) | ||
178 | { | ||
179 | llassert_always(mFormattedImage->getCodec() == imageformat); | ||
180 | mFormattedImage->appendData(data, datasize); | ||
181 | } | ||
182 | else | ||
183 | { | ||
184 | mFormattedImage = LLImageFormatted::createFromType(imageformat); | ||
185 | mFormattedImage->setData(data,datasize); | ||
186 | } | ||
187 | mImageSize = imagesize; | ||
188 | mImageLocal = imagelocal; | ||
189 | } | ||
190 | |||
191 | virtual void completed(bool success) | ||
192 | { | ||
193 | if(success && (mFormattedImage.notNull()) && mImageSize>0) | ||
194 | { | ||
195 | |||
196 | llinfos << "SUCCESS getting texture "<<mID<< llendl; | ||
197 | |||
198 | std::string name; | ||
199 | mID.toString(name); | ||
200 | llinfos << "Saving to "<<(primbackup::getInstance()->getfolder()+"//"+name)<<llendl; | ||
201 | if(!mFormattedImage->save(primbackup::getInstance()->getfolder()+"//"+name)) | ||
202 | { | ||
203 | llinfos << "FAIL saving texture "<<mID<< llendl; | ||
204 | } | ||
205 | |||
206 | } | ||
207 | else | ||
208 | { | ||
209 | if(!success) | ||
210 | llwarns << "FAIL NOT SUCCESSFUL getting texture "<<mID<< llendl; | ||
211 | if(mFormattedImage.isNull()) | ||
212 | llwarns << "FAIL image is NULL "<<mID<< llendl; | ||
213 | } | ||
214 | |||
215 | primbackup::getInstance()->m_nexttextureready=true; | ||
216 | //JUST SAY NO TO APR DEADLOCKING | ||
217 | //primbackup::getInstance()->export_next_texture(); | ||
218 | } | ||
219 | private: | ||
220 | LLPointer<LLImageFormatted> mFormattedImage; | ||
221 | LLUUID mID; | ||
222 | }; | ||
223 | |||
224 | |||
225 | |||
226 | primbackup::primbackup() | ||
227 | : LLFloater( std::string("Prim Import Floater") ) | ||
228 | { | ||
229 | LLUICtrlFactory::getInstance()->buildFloater( this, "floater_prim_import.xml" ); | ||
230 | |||
231 | // reposition floater from saved settings | ||
232 | //LLRect rect = gSavedSettings.getRect( "FloaterPrimImport" ); | ||
233 | //reshape( rect.getWidth(), rect.getHeight(), FALSE ); | ||
234 | //setRect( rect ); | ||
235 | |||
236 | running=false; | ||
237 | textures.clear(); | ||
238 | assetmap.clear(); | ||
239 | current_asset=LLUUID::null; | ||
240 | m_retexture=false; | ||
241 | close(); | ||
242 | } | ||
243 | |||
244 | |||
245 | //////////////////////////////////////////////////////////////////////////////// | ||
246 | // | ||
247 | primbackup* primbackup::getInstance() | ||
248 | { | ||
249 | if ( ! sInstance ) | ||
250 | sInstance = new primbackup(); | ||
251 | |||
252 | return sInstance; | ||
253 | } | ||
254 | |||
255 | primbackup::~primbackup() | ||
256 | { | ||
257 | // save position of floater | ||
258 | gSavedSettings.setRect( "FloaterPrimImport", getRect() ); | ||
259 | sInstance = 0; | ||
260 | } | ||
261 | |||
262 | void primbackup::draw() | ||
263 | { | ||
264 | LLFloater::draw(); | ||
265 | } | ||
266 | |||
267 | void primbackup::show() | ||
268 | { | ||
269 | // set the title | ||
270 | setTitle( "stuff" ); | ||
271 | m_curobject=1; | ||
272 | m_curprim=0; | ||
273 | m_objects=0; | ||
274 | m_prims=0; | ||
275 | m_textures=0; | ||
276 | m_curtexture=0; | ||
277 | rezcount=0; | ||
278 | |||
279 | // make floater appear | ||
280 | setVisibleAndFrontmost(); | ||
281 | } | ||
282 | |||
283 | |||
284 | void primbackup::onClose( bool app_quitting ) | ||
285 | { | ||
286 | setVisible( false ); | ||
287 | // HACK for fast XML iteration replace with: | ||
288 | // destroy(); | ||
289 | } | ||
290 | |||
291 | void primbackup::updateexportnumbers() | ||
292 | { | ||
293 | |||
294 | std::stringstream sstr; | ||
295 | LLUICtrl * ctrl=this->getChild<LLUICtrl>("name_label"); | ||
296 | |||
297 | sstr<<"Export Progress \n"; | ||
298 | |||
299 | sstr << "Remaining Textures "<<textures.size()<<"\n"; | ||
300 | ctrl->setValue(LLSD("Text")=sstr.str()); | ||
301 | |||
302 | } | ||
303 | |||
304 | |||
305 | void primbackup::updateimportnumbers() | ||
306 | { | ||
307 | std::stringstream sstr; | ||
308 | LLUICtrl * ctrl=this->getChild<LLUICtrl>("name_label"); | ||
309 | |||
310 | if(m_retexture) | ||
311 | { | ||
312 | sstr << " Textures uploads remaining : "<<textures.size()<<"\n"; | ||
313 | ctrl->setValue(LLSD("Text")=sstr.str()); | ||
314 | } | ||
315 | else | ||
316 | { | ||
317 | sstr << " Textures uploads N/A \n"; | ||
318 | ctrl->setValue(LLSD("Text")=sstr.str()); | ||
319 | } | ||
320 | sstr << " Objects "<<this->m_curobject<<"/"<<this->m_objects<<"\n"; | ||
321 | ctrl->setValue(LLSD("Text")=sstr.str()); | ||
322 | |||
323 | sstr << " Rez "<<this->rezcount<<"/"<<this->m_prims; | ||
324 | ctrl->setValue(LLSD("Text")=sstr.str()); | ||
325 | |||
326 | sstr << " Build "<<this->m_curprim<<"/"<<this->m_prims; | ||
327 | ctrl->setValue(LLSD("Text")=sstr.str()); | ||
328 | |||
329 | |||
330 | } | ||
331 | |||
332 | void primbackup::pre_export_object() | ||
333 | { | ||
334 | textures.clear(); | ||
335 | llsd.clear(); | ||
336 | this_group.clear(); | ||
337 | |||
338 | // Open the file save dialog | ||
339 | LLFilePicker& file_picker = LLFilePicker::instance(); | ||
340 | if( !file_picker.getSaveFile( LLFilePicker::FFSAVE_XML ) ) | ||
341 | { | ||
342 | // User canceled save. | ||
343 | return; | ||
344 | } | ||
345 | |||
346 | file_name = file_picker.getCurFile(); | ||
347 | folder = gDirUtilp->getDirName(file_name); | ||
348 | |||
349 | export_state=EXPORT_INIT; | ||
350 | gIdleCallbacks.addFunction(exportworker, NULL); | ||
351 | } | ||
352 | |||
353 | void primbackup::exportworker(void *userdata) | ||
354 | { | ||
355 | primbackup::getInstance()->updateexportnumbers(); | ||
356 | |||
357 | switch(primbackup::getInstance()->export_state) | ||
358 | { | ||
359 | case EXPORT_INIT: | ||
360 | { | ||
361 | primbackup::getInstance()->show(); | ||
362 | LLSelectMgr::getInstance()->getSelection()->ref(); | ||
363 | |||
364 | struct ff : public LLSelectedNodeFunctor | ||
365 | { | ||
366 | virtual bool apply(LLSelectNode* node) | ||
367 | { | ||
368 | if(gAgent.getID()!=node->mPermissions->getOwner()) | ||
369 | { | ||
370 | #ifdef LL_GRID_PERMISSIONS | ||
371 | return false; | ||
372 | #else | ||
373 | return true; | ||
374 | #endif | ||
375 | } | ||
376 | else if(581632==node->mPermissions->getMaskOwner() || 2147483647==node->mPermissions->getMaskOwner()) | ||
377 | { | ||
378 | return true; | ||
379 | } | ||
380 | return false; | ||
381 | } | ||
382 | } func; | ||
383 | |||
384 | if(LLSelectMgr::getInstance()->getSelection()->applyToNodes(&func,false)) | ||
385 | primbackup::getInstance()->export_state=EXPORT_STRUCTURE; | ||
386 | else | ||
387 | { | ||
388 | llwarns<<"Incorrect permission to export"<<llendl; | ||
389 | primbackup::getInstance()->export_state=EXPORT_DONE; | ||
390 | primbackup::getInstance()->close(); | ||
391 | gIdleCallbacks.deleteFunction(exportworker); | ||
392 | LLSelectMgr::getInstance()->getSelection()->unref(); | ||
393 | |||
394 | } | ||
395 | break; | ||
396 | } | ||
397 | |||
398 | break; | ||
399 | case EXPORT_STRUCTURE: | ||
400 | { | ||
401 | struct ff : public LLSelectedObjectFunctor | ||
402 | { | ||
403 | virtual bool apply(LLViewerObject* object) | ||
404 | { | ||
405 | object->boostTexturePriority(TRUE); | ||
406 | LLViewerObject::child_list_t children = object->getChildren(); | ||
407 | children.push_front(object); //push root onto list | ||
408 | LLSD prim_llsd=primbackup::getInstance()->prims_to_llsd(children); | ||
409 | LLSD stuff; | ||
410 | stuff["root_position"] = object->getPosition().getValue(); | ||
411 | stuff["root_rotation"] = ll_sd_from_quaternion(object->getRotation()); | ||
412 | stuff["group_body"] = prim_llsd; | ||
413 | primbackup::getInstance()->llsd["data"].append(stuff); | ||
414 | return true; | ||
415 | } | ||
416 | } func; | ||
417 | |||
418 | primbackup::getInstance()->export_state=EXPORT_LLSD; | ||
419 | LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func,false); | ||
420 | LLSelectMgr::getInstance()->getSelection()->unref(); | ||
421 | |||
422 | break; | ||
423 | } | ||
424 | case EXPORT_TEXTURES: | ||
425 | if(primbackup::getInstance()->m_nexttextureready==false) | ||
426 | return; | ||
427 | |||
428 | //Ok we got work to do | ||
429 | primbackup::getInstance()->m_nexttextureready=false; | ||
430 | |||
431 | if(primbackup::getInstance()->textures.empty()) | ||
432 | { | ||
433 | primbackup::getInstance()->export_state=EXPORT_DONE; | ||
434 | return; | ||
435 | } | ||
436 | |||
437 | primbackup::getInstance()->export_next_texture(); | ||
438 | break; | ||
439 | |||
440 | case EXPORT_LLSD: | ||
441 | { | ||
442 | // Create a file stream and write to it | ||
443 | llofstream export_file(primbackup::getInstance()->file_name); | ||
444 | LLSDSerialize::toPrettyXML(primbackup::getInstance()->llsd, export_file); | ||
445 | export_file.close(); | ||
446 | primbackup::getInstance()->m_nexttextureready=true; | ||
447 | primbackup::getInstance()->export_state=EXPORT_TEXTURES; | ||
448 | } | ||
449 | break; | ||
450 | case EXPORT_DONE: | ||
451 | llinfos<<"Backup complete"<<llendl | ||
452 | gIdleCallbacks.deleteFunction(exportworker); | ||
453 | primbackup::getInstance()->close(); | ||
454 | break; | ||
455 | } | ||
456 | } | ||
457 | |||
458 | LLSD primbackup::prims_to_llsd(LLViewerObject::child_list_t child_list) | ||
459 | { | ||
460 | |||
461 | LLViewerObject* object; | ||
462 | LLSD llsd; | ||
463 | |||
464 | char localid[16]; | ||
465 | |||
466 | for (LLViewerObject::child_list_t::iterator i = child_list.begin(); i != child_list.end(); ++i) | ||
467 | { | ||
468 | object=(*i); | ||
469 | LLUUID id = object->getID(); | ||
470 | |||
471 | llinfos << "Exporting prim " << object->getID().asString() << llendl; | ||
472 | |||
473 | // Create an LLSD object that represents this prim. It will be injected in to the overall LLSD | ||
474 | // tree structure | ||
475 | LLSD prim_llsd; | ||
476 | |||
477 | if (!object->isRoot()) | ||
478 | { | ||
479 | |||
480 | // Parent id | ||
481 | snprintf(localid, sizeof(localid), "%u", object->getSubParent()->getLocalID()); | ||
482 | prim_llsd["parent"] = localid; | ||
483 | } | ||
484 | |||
485 | // Transforms | ||
486 | prim_llsd["position"] = object->getPosition().getValue(); | ||
487 | prim_llsd["scale"] = object->getScale().getValue(); | ||
488 | prim_llsd["rotation"] = ll_sd_from_quaternion(object->getRotation()); | ||
489 | |||
490 | // Flags | ||
491 | prim_llsd["shadows"] = object->flagCastShadows(); | ||
492 | prim_llsd["phantom"] = object->flagPhantom(); | ||
493 | prim_llsd["physical"] = (BOOL)(object->mFlags & FLAGS_USE_PHYSICS); | ||
494 | |||
495 | // Volume params | ||
496 | LLVolumeParams params = object->getVolume()->getParams(); | ||
497 | prim_llsd["volume"] = params.asLLSD(); | ||
498 | |||
499 | // Extra paramsb6fab961-af18-77f8-cf08-f021377a7244 | ||
500 | if (object->isFlexible()) | ||
501 | { | ||
502 | // Flexible | ||
503 | LLFlexibleObjectData* flex = (LLFlexibleObjectData*)object->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); | ||
504 | prim_llsd["flexible"] = flex->asLLSD(); | ||
505 | } | ||
506 | if (object->getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT)) | ||
507 | { | ||
508 | // Light | ||
509 | LLLightParams* light = (LLLightParams*)object->getParameterEntry(LLNetworkData::PARAMS_LIGHT); | ||
510 | prim_llsd["light"] = light->asLLSD(); | ||
511 | } | ||
512 | if (object->getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT)) | ||
513 | { | ||
514 | // Sculpt | ||
515 | LLSculptParams* sculpt = (LLSculptParams*)object->getParameterEntry(LLNetworkData::PARAMS_SCULPT); | ||
516 | prim_llsd["sculpt"] = sculpt->asLLSD(); | ||
517 | |||
518 | LLUUID sculpt_texture=sculpt->getSculptTexture(); | ||
519 | bool alreadyseen=false; | ||
520 | std::list<LLUUID>::iterator iter; | ||
521 | for(iter = textures.begin(); iter != textures.end() ; iter++) | ||
522 | { | ||
523 | if( (*iter)==sculpt_texture) | ||
524 | alreadyseen=true; | ||
525 | } | ||
526 | if(alreadyseen==false) | ||
527 | { | ||
528 | llinfos << "Found a sculpt texture, adding to list "<<sculpt_texture<<llendl; | ||
529 | textures.push_back(sculpt_texture); | ||
530 | } | ||
531 | } | ||
532 | |||
533 | // Textures | ||
534 | LLSD te_llsd; | ||
535 | U8 te_count = object->getNumTEs(); | ||
536 | for (U8 i = 0; i < te_count; i++) | ||
537 | { | ||
538 | bool alreadyseen=false; | ||
539 | te_llsd.append(object->getTE(i)->asLLSD()); | ||
540 | std::list<LLUUID>::iterator iter; | ||
541 | for(iter = textures.begin(); iter != textures.end() ; iter++) | ||
542 | { | ||
543 | if( (*iter)==object->getTE(i)->getID()) | ||
544 | alreadyseen=true; | ||
545 | } | ||
546 | if(alreadyseen==false) | ||
547 | textures.push_back(object->getTE(i)->getID()); | ||
548 | } | ||
549 | prim_llsd["textures"] = te_llsd; | ||
550 | |||
551 | // The keys in the primitive maps do not have to be localids, they can be any | ||
552 | // string. We simply use localids because they are a unique identifier | ||
553 | snprintf(localid, sizeof(localid), "%u", object->getLocalID()); | ||
554 | llsd[(const char*)localid] = prim_llsd; | ||
555 | } | ||
556 | |||
557 | updateexportnumbers(); | ||
558 | |||
559 | return llsd; | ||
560 | } | ||
561 | |||
562 | |||
563 | void primbackup::export_next_texture() | ||
564 | { | ||
565 | if(textures.empty()) | ||
566 | { | ||
567 | llinfos << "Finished exporting textures "<<llendl; | ||
568 | return; | ||
569 | } | ||
570 | |||
571 | std::list<LLUUID>::iterator iter; | ||
572 | iter = textures.begin(); | ||
573 | |||
574 | LLUUID id; | ||
575 | |||
576 | while(1) | ||
577 | { | ||
578 | if(iter==textures.end()) | ||
579 | { | ||
580 | m_nexttextureready=true; | ||
581 | return; | ||
582 | } | ||
583 | |||
584 | id=(*iter); | ||
585 | |||
586 | LLViewerImage * imagep = gImageList.hasImage(id); | ||
587 | if(imagep!=NULL) | ||
588 | { | ||
589 | S32 cur_discard = imagep->getDiscardLevel(); | ||
590 | if(cur_discard>0) | ||
591 | { | ||
592 | if(imagep->getBoostLevel()!=LLViewerImage::BOOST_PREVIEW) | ||
593 | imagep->setBoostLevel(LLViewerImage::BOOST_PREVIEW); //we want to force discard 0 this one does this. | ||
594 | } | ||
595 | else | ||
596 | { | ||
597 | break; | ||
598 | } | ||
599 | } | ||
600 | else | ||
601 | { | ||
602 | llwarns<<" We *DONT* have the texture "<<llendl; | ||
603 | } | ||
604 | iter++; | ||
605 | } | ||
606 | |||
607 | textures.remove(id); | ||
608 | |||
609 | llinfos<<"Requesting texture "<<id<<llendl; | ||
610 | LLImageJ2C * mFormattedImage = new LLImageJ2C; | ||
611 | CacheReadResponder* responder = new CacheReadResponder(id, mFormattedImage); | ||
612 | LLAppViewer::getTextureCache()->readFromCache(id,LLWorkerThread::PRIORITY_HIGH,0,999999,responder); | ||
613 | } | ||
614 | |||
615 | |||
616 | |||
617 | void primbackup::import_object(bool upload) | ||
618 | { | ||
619 | textures.clear(); | ||
620 | assetmap.clear(); | ||
621 | current_asset=LLUUID::null; | ||
622 | |||
623 | this->m_retexture=upload; | ||
624 | |||
625 | // Open the file open dialog | ||
626 | LLFilePicker& file_picker = LLFilePicker::instance(); | ||
627 | if( !file_picker.getOpenFile( LLFilePicker::FFLOAD_XML ) ) | ||
628 | { | ||
629 | // User canceled save. | ||
630 | return; | ||
631 | } | ||
632 | std::string file_name = file_picker.getFirstFile().c_str(); | ||
633 | folder = gDirUtilp->getDirName(file_name); | ||
634 | |||
635 | llifstream import_file(file_name); | ||
636 | LLSDSerialize::fromXML(llsd, import_file); | ||
637 | import_file.close(); | ||
638 | |||
639 | show(); | ||
640 | |||
641 | //Get the texture map | ||
642 | |||
643 | LLSD::map_const_iterator prim_it; | ||
644 | LLSD::array_const_iterator prim_arr_it; | ||
645 | |||
646 | this->m_curobject=1; | ||
647 | this->m_curprim=1; | ||
648 | this->m_objects=llsd["data"].size(); | ||
649 | this->m_prims=0; | ||
650 | rezcount=0; | ||
651 | |||
652 | updateimportnumbers(); | ||
653 | |||
654 | for( prim_arr_it = llsd["data"].beginArray(); prim_arr_it != llsd["data"].endArray(); prim_arr_it++) | ||
655 | { | ||
656 | |||
657 | LLSD llsd2; | ||
658 | llsd2=(*prim_arr_it)["group_body"]; | ||
659 | |||
660 | for( prim_it = llsd2.beginMap(); prim_it != llsd2.endMap(); prim_it++) | ||
661 | { | ||
662 | LLSD prim_llsd; | ||
663 | prim_llsd=llsd2[prim_it->first]; | ||
664 | LLSD::array_iterator text_it; | ||
665 | std::list<LLUUID>::iterator iter; | ||
666 | |||
667 | if(prim_llsd.has("sculpt")) | ||
668 | { | ||
669 | LLSculptParams* sculpt=new LLSculptParams(); | ||
670 | sculpt->fromLLSD(prim_llsd["sculpt"]); | ||
671 | LLUUID orig=sculpt->getSculptTexture(); | ||
672 | bool alreadyseen=false; | ||
673 | for(iter = textures.begin(); iter != textures.end() ; iter++) | ||
674 | { | ||
675 | if( (*iter)==orig) | ||
676 | alreadyseen=true; | ||
677 | } | ||
678 | if(alreadyseen==false) | ||
679 | { | ||
680 | llinfos << "Found a new SCULPT texture to upload "<<orig<<llendl; | ||
681 | textures.push_back(orig); | ||
682 | } | ||
683 | } | ||
684 | |||
685 | |||
686 | LLSD te_llsd; | ||
687 | te_llsd=prim_llsd["textures"]; | ||
688 | |||
689 | |||
690 | for(text_it=te_llsd.beginArray(); text_it !=te_llsd.endArray(); text_it++) | ||
691 | { | ||
692 | LLSD the_te; | ||
693 | the_te=(*text_it); | ||
694 | LLTextureEntry te; | ||
695 | te.fromLLSD(the_te); | ||
696 | |||
697 | te.getID(); | ||
698 | bool alreadyseen=false; | ||
699 | |||
700 | for(iter = textures.begin(); iter != textures.end() ; iter++) | ||
701 | { | ||
702 | if( (*iter)==te.getID()) | ||
703 | alreadyseen=true; | ||
704 | } | ||
705 | if(alreadyseen==false) | ||
706 | { | ||
707 | llinfos << "Found a new texture to upload "<<te.getID()<<llendl; | ||
708 | textures.push_back(te.getID()); | ||
709 | } | ||
710 | } | ||
711 | |||
712 | } | ||
713 | } | ||
714 | |||
715 | if(m_retexture==TRUE) | ||
716 | upload_next_asset(); | ||
717 | else | ||
718 | import_object1a(); | ||
719 | } | ||
720 | |||
721 | LLVector3 primbackup::offset_agent(LLVector3 offset) | ||
722 | { | ||
723 | LLVector3 pos= gAgent.getPositionAgent(); | ||
724 | LLQuaternion agent_rot=LLQuaternion(gAgent.getAtAxis(),gAgent.getLeftAxis(),gAgent.getUpAxis()); | ||
725 | pos=(offset*agent_rot+pos); | ||
726 | return pos; | ||
727 | } | ||
728 | |||
729 | void primbackup::rez_agent_offset(LLVector3 offset) | ||
730 | { | ||
731 | // This will break for a sitting agent | ||
732 | LLToolPlacer* mPlacer = new LLToolPlacer(); | ||
733 | mPlacer->setObjectType(LL_PCODE_CUBE); | ||
734 | //LLVector3 pos=offset_agent(offset); | ||
735 | mPlacer->placeObject((S32)(offset.mV[0]), (S32)(offset.mV[1]), 0); | ||
736 | } | ||
737 | |||
738 | void primbackup::import_object1a() | ||
739 | { | ||
740 | running=true; | ||
741 | |||
742 | show(); | ||
743 | |||
744 | group_prim_import_iter=llsd["data"].beginArray(); | ||
745 | root_root_pos=(*group_prim_import_iter)["root_position"]; | ||
746 | |||
747 | this->m_objects=llsd["data"].size(); | ||
748 | this->m_curobject=1; | ||
749 | import_next_object(); | ||
750 | } | ||
751 | |||
752 | void primbackup::import_next_object() | ||
753 | { | ||
754 | toselect.clear(); | ||
755 | rezcount=0; | ||
756 | |||
757 | this_group=(*group_prim_import_iter)["group_body"]; | ||
758 | prim_import_iter=this_group.beginMap(); | ||
759 | |||
760 | m_curprim=0; | ||
761 | m_prims=this_group.size(); | ||
762 | updateimportnumbers(); | ||
763 | LLVector3 lgpos=(*group_prim_import_iter)["root_position"]; | ||
764 | |||
765 | group_offset=lgpos-root_root_pos; | ||
766 | root_pos=offset_agent(LLVector3(2.0,0,0)); | ||
767 | root_rot=ll_quaternion_from_sd((*group_prim_import_iter)["root_rotation"]); | ||
768 | |||
769 | rez_agent_offset(LLVector3(0.0,2.0,0.0)); | ||
770 | // Now we must wait for the callback when ViewerObjectList gets the new objects and we have the correct number selected | ||
771 | } | ||
772 | |||
773 | // This function takes a pointer to a viewerobject and applys the prim definition that prim_llsd has | ||
774 | void primbackup::xmltoprim(LLSD prim_llsd,LLViewerObject * object) | ||
775 | { | ||
776 | LLUUID id = object->getID(); | ||
777 | expecting_update = object->getID(); | ||
778 | LLSelectMgr::getInstance()->selectObjectAndFamily(object); | ||
779 | |||
780 | if(prim_llsd.has("parent")) | ||
781 | { | ||
782 | //we are not the root node. | ||
783 | LLVector3 pos=prim_llsd["position"]; | ||
784 | LLQuaternion rot=ll_quaternion_from_sd(prim_llsd["rotation"]); | ||
785 | object->setPositionRegion((pos*root_rot)+(root_pos+group_offset)); | ||
786 | object->setRotation(rot*root_rot); | ||
787 | } | ||
788 | else | ||
789 | { | ||
790 | object->setPositionRegion(root_pos+group_offset); | ||
791 | LLQuaternion rot=ll_quaternion_from_sd(prim_llsd["rotation"]); | ||
792 | object->setRotation(rot); | ||
793 | } | ||
794 | |||
795 | object->setScale(prim_llsd["scale"]); | ||
796 | |||
797 | if(prim_llsd.has("shadows")) | ||
798 | if(prim_llsd["shadows"].asInteger()==1) | ||
799 | object->setFlags(FLAGS_CAST_SHADOWS,true); | ||
800 | |||
801 | if(prim_llsd.has("phantom")) | ||
802 | if(prim_llsd["phantom"].asInteger()==1) | ||
803 | object->setFlags(FLAGS_PHANTOM,true); | ||
804 | |||
805 | if(prim_llsd.has("physical")) | ||
806 | if(prim_llsd["physical"].asInteger()==1) | ||
807 | object->setFlags(FLAGS_USE_PHYSICS,true); | ||
808 | |||
809 | // Volume params | ||
810 | LLVolumeParams volume_params = object->getVolume()->getParams(); | ||
811 | volume_params.fromLLSD(prim_llsd["volume"]) ; | ||
812 | object->updateVolume(volume_params); | ||
813 | |||
814 | if(prim_llsd.has("sculpt")) | ||
815 | { | ||
816 | LLSculptParams* sculpt=new LLSculptParams(); | ||
817 | sculpt->fromLLSD(prim_llsd["sculpt"]); | ||
818 | |||
819 | //TODO check if map is valid and only set texture is map is valid and changes | ||
820 | |||
821 | if(assetmap[sculpt->getSculptTexture()].notNull()) | ||
822 | { | ||
823 | LLUUID replacment=assetmap[sculpt->getSculptTexture()]; | ||
824 | sculpt->setSculptTexture(replacment); | ||
825 | } | ||
826 | |||
827 | object->setParameterEntry(LLNetworkData::PARAMS_SCULPT,(LLNetworkData&)(*sculpt),true); | ||
828 | } | ||
829 | |||
830 | if(prim_llsd.has("light")) | ||
831 | { | ||
832 | LLLightParams * light=new LLLightParams(); | ||
833 | light->fromLLSD(prim_llsd["light"]); | ||
834 | object->setParameterEntry(LLNetworkData::PARAMS_LIGHT,(LLNetworkData&)(*light),true); | ||
835 | } | ||
836 | |||
837 | if(prim_llsd.has("flexible")) | ||
838 | { | ||
839 | LLFlexibleObjectData* flex=new LLFlexibleObjectData(); | ||
840 | flex->fromLLSD(prim_llsd["flexible"]); | ||
841 | object->setParameterEntry(LLNetworkData::PARAMS_FLEXIBLE,(LLNetworkData&)(*flex),true); | ||
842 | } | ||
843 | |||
844 | |||
845 | // Textures | ||
846 | LLSD te_llsd; | ||
847 | llinfos << "Processing textures for prim" << llendl; | ||
848 | |||
849 | te_llsd=prim_llsd["textures"]; | ||
850 | |||
851 | LLSD::array_iterator text_it; | ||
852 | U8 i=0; | ||
853 | i=0; | ||
854 | |||
855 | for(text_it=te_llsd.beginArray(); text_it !=te_llsd.endArray(); text_it++) | ||
856 | { | ||
857 | LLSD the_te; | ||
858 | the_te=(*text_it); | ||
859 | LLTextureEntry te; | ||
860 | te.fromLLSD(the_te); | ||
861 | |||
862 | if(assetmap[te.getID()].notNull()) | ||
863 | { | ||
864 | LLUUID replacment=assetmap[te.getID()]; | ||
865 | te.setID(replacment); | ||
866 | } | ||
867 | |||
868 | object->setTE(i,te); // | ||
869 | i++; | ||
870 | } | ||
871 | |||
872 | llinfos << "Textures done!" << llendl; | ||
873 | |||
874 | //bump the iterator now so the callbacks hook together nicely | ||
875 | //if(prim_import_iter!=this_group.endMap()) | ||
876 | // prim_import_iter++; | ||
877 | |||
878 | object->sendRotationUpdate(); | ||
879 | object->sendTEUpdate(); | ||
880 | object->sendShapeUpdate(); | ||
881 | LLSelectMgr::getInstance()->sendMultipleUpdate(UPD_SCALE |UPD_POSITION); | ||
882 | |||
883 | LLSelectMgr::getInstance()->deselectAll(); | ||
884 | } | ||
885 | |||
886 | //This is fired when the update packet is processed so we know the prim settings have stuck | ||
887 | void primbackup::prim_update(LLViewerObject* object) | ||
888 | { | ||
889 | if(!running) | ||
890 | return; | ||
891 | |||
892 | if(object!=NULL) | ||
893 | if(object->mID!=expecting_update) | ||
894 | return; | ||
895 | |||
896 | m_curprim++; | ||
897 | updateimportnumbers(); | ||
898 | |||
899 | prim_import_iter++; | ||
900 | |||
901 | LLUUID x; | ||
902 | expecting_update=x.null; | ||
903 | |||
904 | if(prim_import_iter==this_group.endMap()) | ||
905 | { | ||
906 | llinfos<<"Trying to link"<<llendl; | ||
907 | |||
908 | if(toselect.size()>1) | ||
909 | { | ||
910 | std::reverse(toselect.begin(),toselect.end()); | ||
911 | //Now link | ||
912 | LLSelectMgr::getInstance()->deselectAll(); | ||
913 | LLSelectMgr::getInstance()->selectObjectAndFamily(toselect,true); | ||
914 | LLSelectMgr::getInstance()->sendLink(); | ||
915 | LLViewerObject * root=toselect.back(); | ||
916 | root->setRotation(root_rot); | ||
917 | } | ||
918 | |||
919 | this->m_curobject++; | ||
920 | group_prim_import_iter++; | ||
921 | if(group_prim_import_iter!=llsd["data"].endArray()) | ||
922 | { | ||
923 | import_next_object(); | ||
924 | return; | ||
925 | } | ||
926 | |||
927 | running=false; | ||
928 | this->close(); | ||
929 | return; | ||
930 | } | ||
931 | |||
932 | LLSD prim_llsd; | ||
933 | prim_llsd=this_group[prim_import_iter->first]; | ||
934 | |||
935 | if(toselect.empty()) | ||
936 | { | ||
937 | llwarns << "error: ran out of objects to mod" << llendl; | ||
938 | return; | ||
939 | } | ||
940 | |||
941 | if(prim_import_iter!=this_group.endMap()) | ||
942 | { | ||
943 | //rez_agent_offset(LLVector3(1.0,0,0)); | ||
944 | LLSD prim_llsd=this_group[prim_import_iter->first]; | ||
945 | process_iter++; | ||
946 | xmltoprim(prim_llsd,(*process_iter)); | ||
947 | } | ||
948 | } | ||
949 | |||
950 | // Callback when we rez a new object when the importer is running. | ||
951 | bool primbackup::newprim(LLViewerObject * pobject) | ||
952 | { | ||
953 | if(running) | ||
954 | { | ||
955 | rezcount++; | ||
956 | toselect.push_back(pobject); | ||
957 | updateimportnumbers(); | ||
958 | prim_import_iter++; | ||
959 | |||
960 | if(prim_import_iter!=this_group.endMap()) | ||
961 | { | ||
962 | |||
963 | pobject->setPosition(this->offset_agent(LLVector3(0,1.0,0))); | ||
964 | LLSelectMgr::getInstance()->sendMultipleUpdate(UPD_POSITION); | ||
965 | |||
966 | rez_agent_offset(LLVector3(1.0,0,0)); | ||
967 | } | ||
968 | else | ||
969 | { | ||
970 | llinfos << "All prims rezed, moving to build stage" <<llendl; | ||
971 | prim_import_iter=this_group.beginMap(); | ||
972 | LLSD prim_llsd=this_group[prim_import_iter->first]; | ||
973 | process_iter=toselect.begin(); | ||
974 | xmltoprim(prim_llsd,(*process_iter)); | ||
975 | } | ||
976 | } | ||
977 | |||
978 | return true; | ||
979 | } | ||
980 | |||
981 | void primbackup::update_map(LLUUID uploaded_asset) | ||
982 | { | ||
983 | if(current_asset.isNull()) | ||
984 | return; | ||
985 | |||
986 | assetmap.insert(std::pair<LLUUID,LLUUID>(current_asset,uploaded_asset)); | ||
987 | llinfos << "Mapping "<<current_asset<<" to "<<uploaded_asset<<llendl; | ||
988 | |||
989 | } | ||
990 | |||
991 | |||
992 | void myupload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_type, | ||
993 | std::string name, | ||
994 | std::string desc, S32 compression_info, | ||
995 | LLAssetType::EType destination_folder_type, | ||
996 | LLInventoryType::EType inv_type, | ||
997 | U32 next_owner_perm, | ||
998 | const std::string& display_name, | ||
999 | LLAssetStorage::LLStoreAssetCallback callback, | ||
1000 | void *userdata) | ||
1001 | { | ||
1002 | if(gDisconnected) | ||
1003 | { | ||
1004 | return ; | ||
1005 | } | ||
1006 | |||
1007 | LLAssetID uuid = tid.makeAssetID(gAgent.getSecureSessionID()); | ||
1008 | |||
1009 | // At this point, we're ready for the upload. | ||
1010 | std::string upload_message = "Uploading...\n\n"; | ||
1011 | upload_message.append(display_name); | ||
1012 | LLUploadDialog::modalUploadDialog(upload_message); | ||
1013 | |||
1014 | std::string url = gAgent.getRegion()->getCapability("NewFileAgentInventory"); | ||
1015 | if (!url.empty()) | ||
1016 | { | ||
1017 | LLSD body; | ||
1018 | body["folder_id"] = gInventory.findCategoryUUIDForType((destination_folder_type == LLAssetType::AT_NONE) ? asset_type : destination_folder_type); | ||
1019 | body["asset_type"] = LLAssetType::lookup(asset_type); | ||
1020 | body["inventory_type"] = LLInventoryType::lookup(inv_type); | ||
1021 | body["name"] = name; | ||
1022 | body["description"] = desc; | ||
1023 | |||
1024 | std::ostringstream llsdxml; | ||
1025 | LLSDSerialize::toXML(body, llsdxml); | ||
1026 | lldebugs << "posting body to capability: " << llsdxml.str() << llendl; | ||
1027 | //LLHTTPClient::post(url, body, new LLNewAgentInventoryResponder(body, uuid, asset_type)); | ||
1028 | LLHTTPClient::post(url, body, new importResponder(body, uuid, asset_type)); | ||
1029 | |||
1030 | } | ||
1031 | else | ||
1032 | { | ||
1033 | llinfos << "NewAgentInventory capability not found, FUCK!" << llendl; | ||
1034 | } | ||
1035 | } | ||
1036 | |||
1037 | |||
1038 | |||
1039 | void primbackup::upload_next_asset() | ||
1040 | { | ||
1041 | if(textures.empty()) | ||
1042 | { | ||
1043 | llinfos<<" Texture list is empty, moving to rez statge"<< llendl; | ||
1044 | current_asset=LLUUID::null; | ||
1045 | import_object1a(); | ||
1046 | return; | ||
1047 | } | ||
1048 | |||
1049 | this->updateimportnumbers(); | ||
1050 | |||
1051 | std::list<LLUUID>::iterator iter; | ||
1052 | iter=textures.begin(); | ||
1053 | LLUUID id=(*iter); | ||
1054 | textures.pop_front(); | ||
1055 | |||
1056 | llinfos<<"Got texture ID "<<id<< "trying to upload"<<llendl; | ||
1057 | |||
1058 | current_asset=id; | ||
1059 | std::string struid; | ||
1060 | id.toString(struid); | ||
1061 | std::string filename=folder+"//"+struid; | ||
1062 | |||
1063 | |||
1064 | LLAssetID uuid; | ||
1065 | LLTransactionID tid; | ||
1066 | |||
1067 | // gen a new transaction ID for this asset | ||
1068 | tid.generate(); | ||
1069 | uuid = tid.makeAssetID(gAgent.getSecureSessionID()); | ||
1070 | |||
1071 | S32 file_size; | ||
1072 | apr_file_t* fp = ll_apr_file_open(filename, LL_APR_RB, &file_size); | ||
1073 | if (fp) | ||
1074 | { | ||
1075 | const S32 buf_size = 65536; | ||
1076 | U8 copy_buf[buf_size]; | ||
1077 | LLVFile file(gVFS, uuid, LLAssetType::AT_TEXTURE, LLVFile::WRITE); | ||
1078 | file.setMaxSize(file_size); | ||
1079 | |||
1080 | while ((file_size = ll_apr_file_read(fp, copy_buf, buf_size))) | ||
1081 | { | ||
1082 | file.write(copy_buf, file_size); | ||
1083 | } | ||
1084 | apr_file_close(fp); | ||
1085 | } | ||
1086 | else | ||
1087 | { | ||
1088 | llwarns<<"Unable to access output file "<<filename<<llendl; | ||
1089 | upload_next_asset(); | ||
1090 | return; | ||
1091 | } | ||
1092 | |||
1093 | myupload_new_resource( | ||
1094 | tid, LLAssetType::AT_TEXTURE, struid, | ||
1095 | struid, 0, | ||
1096 | LLAssetType::AT_TEXTURE, | ||
1097 | LLInventoryType::defaultForAssetType(LLAssetType::AT_TEXTURE), | ||
1098 | 0x0, | ||
1099 | "Uploaded texture", | ||
1100 | NULL, | ||
1101 | NULL); | ||
1102 | |||
1103 | |||
1104 | } | ||
1105 | |||
diff --git a/linden/indra/newview/primbackup.h b/linden/indra/newview/primbackup.h new file mode 100644 index 0000000..fddc35f --- /dev/null +++ b/linden/indra/newview/primbackup.h | |||
@@ -0,0 +1,132 @@ | |||
1 | |||
2 | #include "llviewerinventory.h" | ||
3 | |||
4 | #define LL_GRID_PERMISSIONS 1 | ||
5 | |||
6 | enum export_states {EXPORT_INIT,EXPORT_STRUCTURE,EXPORT_TEXTURES,EXPORT_LLSD,EXPORT_DONE}; | ||
7 | |||
8 | class primbackup : public LLFloater | ||
9 | |||
10 | { | ||
11 | public: | ||
12 | //Export state machine | ||
13 | enum export_states export_state; | ||
14 | |||
15 | //Export idle callback | ||
16 | static void exportworker(void *userdata); | ||
17 | |||
18 | //Static accessor | ||
19 | static primbackup* getInstance(); | ||
20 | |||
21 | virtual ~primbackup(); | ||
22 | |||
23 | //Floater stuff | ||
24 | virtual void show(); | ||
25 | virtual void draw(); | ||
26 | virtual void onClose( bool app_quitting ); | ||
27 | |||
28 | //Import entry point | ||
29 | void import_object(bool upload=FALSE); | ||
30 | |||
31 | //Export entry point | ||
32 | void pre_export_object(); | ||
33 | |||
34 | //Update map from texture worker | ||
35 | void update_map(LLUUID uploaded_asset); | ||
36 | |||
37 | //Move to next texture upload | ||
38 | void upload_next_asset(); | ||
39 | |||
40 | // is ready for next texture? | ||
41 | bool m_nexttextureready; | ||
42 | |||
43 | //Folder public geter | ||
44 | std::string getfolder() {return folder;}; | ||
45 | |||
46 | //Prim updated callback | ||
47 | void prim_update(LLViewerObject* object); | ||
48 | |||
49 | //New prim call back | ||
50 | bool newprim(LLViewerObject * pobject); | ||
51 | |||
52 | private: | ||
53 | |||
54 | //Static singleton stuff | ||
55 | primbackup(); | ||
56 | static primbackup* sInstance; | ||
57 | |||
58 | // are we active flag | ||
59 | bool running; | ||
60 | |||
61 | //file and folder name control | ||
62 | std::string file_name; | ||
63 | std::string folder; | ||
64 | |||
65 | // True if we need to rebase the assets | ||
66 | bool m_retexture; | ||
67 | |||
68 | //Counts of import and export objects and textures and prims | ||
69 | int m_objects,m_curobject; | ||
70 | int m_prims,m_curprim; | ||
71 | int m_textures,m_curtexture; | ||
72 | |||
73 | // No prims rezed | ||
74 | int rezcount; | ||
75 | |||
76 | // Update the floater with status numbers | ||
77 | void updateimportnumbers(); | ||
78 | void updateexportnumbers(); | ||
79 | |||
80 | //Convert a selection list of objects to LLSD | ||
81 | LLSD prims_to_llsd(LLViewerObject::child_list_t child_list); | ||
82 | |||
83 | // Start the import process | ||
84 | void import_object1a(); | ||
85 | |||
86 | //Export the next texture in list | ||
87 | void export_next_texture(); | ||
88 | |||
89 | //apply LLSD to object | ||
90 | void xmltoprim(LLSD prim_llsd,LLViewerObject * pobject); | ||
91 | |||
92 | |||
93 | //rez a prim at a given position (note not agent offset X/Y screen for raycast) | ||
94 | void rez_agent_offset(LLVector3 offset); | ||
95 | |||
96 | //Move to the next import group | ||
97 | void import_next_object(); | ||
98 | |||
99 | //Get an offset from the agent based on rotation and current pos | ||
100 | LLVector3 offset_agent(LLVector3 offset); | ||
101 | |||
102 | // Rebase map | ||
103 | std::map<LLUUID,LLUUID> assetmap; | ||
104 | |||
105 | //Export texture list | ||
106 | std::list<LLUUID> textures; | ||
107 | |||
108 | //Import object tracking | ||
109 | std::vector<LLViewerObject *> toselect; | ||
110 | std::vector<LLViewerObject *>::iterator process_iter; | ||
111 | |||
112 | //Working LLSD holders | ||
113 | LLUUID current_asset; | ||
114 | LLSD llsd; | ||
115 | LLSD this_group; | ||
116 | LLUUID expecting_update; | ||
117 | |||
118 | //working llsd itterators for objects and linksets | ||
119 | LLSD::map_const_iterator prim_import_iter; | ||
120 | LLSD::array_const_iterator group_prim_import_iter; | ||
121 | |||
122 | // Root pos and central root pos for link set | ||
123 | LLVector3 root_pos; | ||
124 | LLVector3 root_root_pos; | ||
125 | LLVector3 group_offset; | ||
126 | |||
127 | //Agent inital pos and rot when starting import | ||
128 | LLQuaternion root_rot; | ||
129 | LLQuaternion agent_rot; | ||
130 | |||
131 | }; | ||
132 | |||
diff --git a/linden/indra/newview/skins/default/xui/en-us/floater_prim_import.xml b/linden/indra/newview/skins/default/xui/en-us/floater_prim_import.xml new file mode 100644 index 0000000..191b31e --- /dev/null +++ b/linden/indra/newview/skins/default/xui/en-us/floater_prim_import.xml | |||
@@ -0,0 +1,5 @@ | |||
1 | <?xml version="1.0" encoding="utf-8" standalone="yes" ?> | ||
2 | <floater can_close="true" can_drag_on_left="true" can_minimize="false" | ||
3 | can_resize="false" height="80" name="Import" title="Import progress" width="200" mouse_opaque="true"> | ||
4 | <text height="15" left="10" name="name_label" top="-10"> Progress </text> | ||
5 | </floater> | ||
diff --git a/linden/indra/newview/skins/default/xui/en-us/menu_pie_object.xml b/linden/indra/newview/skins/default/xui/en-us/menu_pie_object.xml index 8d059c1..ac3d359 100644 --- a/linden/indra/newview/skins/default/xui/en-us/menu_pie_object.xml +++ b/linden/indra/newview/skins/default/xui/en-us/menu_pie_object.xml | |||
@@ -54,7 +54,11 @@ | |||
54 | <on_click function="Object.ReportAbuse" /> | 54 | <on_click function="Object.ReportAbuse" /> |
55 | <on_enable function="Object.EnableReportAbuse" /> | 55 | <on_enable function="Object.EnableReportAbuse" /> |
56 | </menu_item_call> | 56 | </menu_item_call> |
57 | <menu_item_separator /> | 57 | <menu_item_call label="Backup" enabled="false" hidden="false" |
58 | mouse_opaqu="true" name="Export"> | ||
59 | <on_click function="Object.Export" /> | ||
60 | <on_enable function="Object.EnableExport" /> | ||
61 | </menu_item_call> | ||
58 | <menu_item_call enabled="true" label="Inspect" mouse_opaque="true" name="Object Inspect"> | 62 | <menu_item_call enabled="true" label="Inspect" mouse_opaque="true" name="Object Inspect"> |
59 | <on_click function="Object.Inspect" /> | 63 | <on_click function="Object.Inspect" /> |
60 | <on_enable function="Object.EnableInspect" /> | 64 | <on_enable function="Object.EnableInspect" /> |
diff --git a/linden/indra/newview/skins/default/xui/en-us/menu_viewer.xml b/linden/indra/newview/skins/default/xui/en-us/menu_viewer.xml index 11e54ef..3681b62 100644 --- a/linden/indra/newview/skins/default/xui/en-us/menu_viewer.xml +++ b/linden/indra/newview/skins/default/xui/en-us/menu_viewer.xml | |||
@@ -8,6 +8,14 @@ | |||
8 | 8 | ||
9 | <menu name="File" create_jump_keys="true" label="File" | 9 | <menu name="File" create_jump_keys="true" label="File" |
10 | opaque="true" tear_off="true"> | 10 | opaque="true" tear_off="true"> |
11 | <menu_item_call enabled="false" hidden="false" label="Import" mouse_opaque="true" name="Import"> | ||
12 | <on_click function="Object.Import" /> | ||
13 | <on_enable function="Object.EnableImport" /> | ||
14 | </menu_item_call> | ||
15 | <menu_item_call enabled="false" hidden="false" label="Upload + Import" mouse_opaque="true" name="Import"> | ||
16 | <on_click function="Object.ImportUpload" /> | ||
17 | <on_enable function="Object.EnableImport" /> | ||
18 | </menu_item_call> | ||
11 | <menu_item_call name="Upload Image" | 19 | <menu_item_call name="Upload Image" |
12 | label="Upload Image (L$[COST])..." | 20 | label="Upload Image (L$[COST])..." |
13 | shortcut="control|U"> | 21 | shortcut="control|U"> |