aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview
diff options
context:
space:
mode:
authorMcCabe Maxsted2010-08-25 08:18:10 -0700
committerMcCabe Maxsted2010-08-28 05:01:41 -0700
commitf248ce248c8ac0f75fd0219542f4c329204d00f4 (patch)
treef71b916f7da180d739c82ff6324304f41b6e7df2 /linden/indra/newview
parentMade disable max build constraints also disable max position spinner values (diff)
downloadmeta-impy-f248ce248c8ac0f75fd0219542f4c329204d00f4.zip
meta-impy-f248ce248c8ac0f75fd0219542f4c329204d00f4.tar.gz
meta-impy-f248ce248c8ac0f75fd0219542f4c329204d00f4.tar.bz2
meta-impy-f248ce248c8ac0f75fd0219542f4c329204d00f4.tar.xz
Ported local textures from Emerald (requires boost filesystem and system libs to work)
Diffstat (limited to 'linden/indra/newview')
-rw-r--r--linden/indra/newview/CMakeLists.txt2
-rw-r--r--linden/indra/newview/app_settings/settings.xml16
-rw-r--r--linden/indra/newview/floaterlocalassetbrowse.H305
-rw-r--r--linden/indra/newview/floaterlocalassetbrowse.cpp1028
-rw-r--r--linden/indra/newview/lltexturectrl.cpp129
-rw-r--r--linden/indra/newview/lltexturectrl.h1
-rw-r--r--linden/indra/newview/llviewerimage.h3
-rw-r--r--linden/indra/newview/llviewerobjectlist.h2
-rw-r--r--linden/indra/newview/llvovolume.h3
-rw-r--r--linden/indra/newview/skins/default/xui/en-us/floater_local_asset_browse.xml261
-rw-r--r--linden/indra/newview/skins/default/xui/en-us/floater_texture_ctrl.xml67
11 files changed, 1799 insertions, 18 deletions
diff --git a/linden/indra/newview/CMakeLists.txt b/linden/indra/newview/CMakeLists.txt
index 7dfe3d2..13c972a 100644
--- a/linden/indra/newview/CMakeLists.txt
+++ b/linden/indra/newview/CMakeLists.txt
@@ -71,6 +71,7 @@ set(viewer_SOURCE_FILES
71 floaterbusy.cpp 71 floaterbusy.cpp
72 floatergriddefault.cpp 72 floatergriddefault.cpp
73 floatergridmanager.cpp 73 floatergridmanager.cpp
74 floaterlocalassetbrowse.cpp
74 floatervoicelicense.cpp 75 floatervoicelicense.cpp
75 hbfloatergrouptitles.cpp 76 hbfloatergrouptitles.cpp
76 hippoGridManager.cpp 77 hippoGridManager.cpp
@@ -504,6 +505,7 @@ set(viewer_HEADER_FILES
504 floaterbusy.h 505 floaterbusy.h
505 floatergriddefault.h 506 floatergriddefault.h
506 floatergridmanager.h 507 floatergridmanager.h
508 floaterlocalassetbrowse.h
507 floatervoicelicense.h 509 floatervoicelicense.h
508 hbfloatergrouptitles.h 510 hbfloatergrouptitles.h
509 hippoGridManager.h 511 hippoGridManager.h
diff --git a/linden/indra/newview/app_settings/settings.xml b/linden/indra/newview/app_settings/settings.xml
index 53a708e..b01544a 100644
--- a/linden/indra/newview/app_settings/settings.xml
+++ b/linden/indra/newview/app_settings/settings.xml
@@ -239,6 +239,22 @@
239 <integer>0</integer> 239 <integer>0</integer>
240 </array> 240 </array>
241 </map> 241 </map>
242 <key>FloaterLocalbitmapbrowserRect</key>
243 <map>
244 <key>Comment</key>
245 <string>LOLRectangle</string>
246 <key>Persist</key>
247 <integer>1</integer>
248 <key>Type</key>
249 <string>Rect</string>
250 <key>Value</key>
251 <array>
252 <integer>0</integer>
253 <integer>400</integer>
254 <integer>400</integer>
255 <integer>0</integer>
256 </array>
257 </map>
242 <key>FloaterPrimImport</key> 258 <key>FloaterPrimImport</key>
243 <map> 259 <map>
244 <key>Comment</key> 260 <key>Comment</key>
diff --git a/linden/indra/newview/floaterlocalassetbrowse.H b/linden/indra/newview/floaterlocalassetbrowse.H
new file mode 100644
index 0000000..6ee1c75
--- /dev/null
+++ b/linden/indra/newview/floaterlocalassetbrowse.H
@@ -0,0 +1,305 @@
1/**
2* @file floaterlocalassetbrowse.h
3* @brief Local texture support
4*
5* $LicenseInfo:firstyear=2009&license=viewergpl$
6*
7* Copyright (c) 2010, author unknown
8*
9* Imprudence Viewer Source Code
10* The source code in this file ("Source Code") is provided to you
11* under the terms of the GNU General Public License, version 2.0
12* ("GPL"). Terms of the GPL can be found in doc/GPL-license.txt in
13* this distribution, or online at
14* http://secondlifegrid.net/programs/open_source/licensing/gplv2
15*
16* There are special exceptions to the terms and conditions of the GPL as
17* it is applied to this Source Code. View the full text of the exception
18* in the file doc/FLOSS-exception.txt in this software distribution, or
19* online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
20*
21* By copying, modifying or distributing this software, you acknowledge
22* that you have read and understood your obligations described above,
23* and agree to abide by those obligations.
24*
25* ALL SOURCE CODE IS PROVIDED "AS IS." THE AUTHOR MAKES NO
26* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
27* COMPLETENESS OR PERFORMANCE.
28* $/LicenseInfo$
29*/
30
31/* Local Asset Browser: header
32
33tag: vaa emerald local_asset_browser
34
35*/
36
37
38#ifndef VAA_LOCALBROWSER
39#define VAA_LOCALBROWSER
40
41#include "llfloater.h"
42#include "llscrolllistctrl.h"
43#include "lltexturectrl.h"
44#include "lldrawable.h"
45
46
47/*=======================================*/
48/* Global structs / enums / defines */
49/*=======================================*/
50
51#define LF_FLOATER_EXPAND_WIDTH 735
52#define LF_FLOATER_CONTRACT_WIDTH 415
53#define LF_FLOATER_HEIGHT 260
54
55#define LOCAL_USE_MIPMAPS true
56#define LOCAL_DISCARD_LEVEL 0
57#define NO_IMAGE LLUUID::null
58
59#define TIMER_HEARTBEAT 3.0
60
61#define SLAM_FOR_DEBUG true
62
63enum bitmaplist_cols
64{
65 BITMAPLIST_COL_NAME,
66 BITMAPLIST_COL_ID
67};
68
69/* upload & sculpt update related */
70struct affected_object
71{
72 LLViewerObject* object;
73 std::vector<LLFace*> face_list;
74 bool local_sculptmap;
75
76};
77
78/* texture picker defines */
79
80#define LOCAL_TEXTURE_PICKER_NAME "texture picker"
81#define LOCAL_TEXTURE_PICKER_LIST_NAME "local_name_list"
82#define LOCAL_TEXTURE_PICKER_RECURSE true
83#define LOCAL_TEXTURE_PICKER_CREATEIFMISSING true
84
85
86/*=======================================*/
87/* LocalBitmap: unit class */
88/*=======================================*/
89/*
90 The basic unit class responsible for
91 containing one loaded local texture.
92*/
93
94class LocalBitmap
95{
96 public:
97 LocalBitmap(std::string filename);
98 virtual ~LocalBitmap(void);
99 friend class LocalAssetBrowser;
100
101 public: /* [enums, typedefs, etc] */
102 enum link_status
103 {
104 LINK_UNKNOWN, /* default fallback */
105 LINK_ON,
106 LINK_OFF,
107 LINK_BROKEN,
108 LINK_UPDATING /* currently redundant, but left in case necessary later. */
109 };
110
111 enum extension_type
112 {
113 IMG_EXTEN_BMP,
114 IMG_EXTEN_TGA,
115 IMG_EXTEN_JPG,
116 IMG_EXTEN_PNG
117 };
118
119 enum bitmap_type
120 {
121 TYPE_TEXTURE = 0,
122 TYPE_SCULPT = 1,
123 TYPE_LAYER = 2
124 };
125
126 public: /* [information query functions] */
127 std::string getShortName(void);
128 std::string getFileName(void);
129 LLUUID getID(void);
130 LLSD getLastModified(void);
131 std::string getLinkStatus(void);
132 bool getUpdateBool(void);
133 void setType( S32 );
134 bool getIfValidBool(void);
135 S32 getType(void);
136 void getDebugInfo(void);
137
138 private: /* [maintenence functions] */
139 void updateSelf(void);
140 bool decodeSelf(LLImageRaw* rawimg);
141 void setUpdateBool(void);
142
143 LocalBitmap* getThis(void);
144 std::vector<LLFace*> getFaceUsesThis(LLDrawable*);
145 std::vector<affected_object> getUsingObjects(bool seek_by_type = true,
146 bool seek_textures = false, bool seek_sculptmaps = false);
147
148 protected: /* [basic properties] */
149 std::string shortname;
150 std::string filename;
151 extension_type extension;
152 LLUUID id;
153 LLSD last_modified;
154 link_status linkstatus;
155 bool keep_updating;
156 bool valid;
157 S32 bitmap_type;
158 bool sculpt_dirty;
159 bool volume_dirty;
160};
161
162/*=======================================*/
163/* LocalAssetBrowser: main class */
164/*=======================================*/
165/*
166 Responsible for internal workings.
167 Instantiated at the top of the source file.
168 Sits in memory until the viewer is closed.
169
170*/
171
172
173class LocalAssetBrowser
174{
175 public:
176 LocalAssetBrowser();
177 virtual ~LocalAssetBrowser();
178 friend class FloaterLocalAssetBrowser;
179 friend class LocalAssetBrowserTimer;
180 static void UpdateTextureCtrlList(LLScrollListCtrl*);
181 static void setLayerUpdated(bool toggle) { mLayerUpdated = toggle; }
182 static void setSculptUpdated(bool toggle) { mSculptUpdated = toggle; }
183 static void AddBitmap(void);
184 static void DelBitmap( std::vector<LLScrollListItem*>, S32 column = BITMAPLIST_COL_ID );
185
186 /* UpdateTextureCtrlList was made public cause texturectrl requests it once on spawn
187 ( added: when it's own add/remove funcs are used. )
188 i've made it update on spawn instead of on pressing 'local' because the former does it once,
189 the latter - each time the button's pressed. */
190
191 private:
192 static void onChangeHappened(void);
193 static void onUpdateBool(LLUUID);
194 static void onSetType(LLUUID, S32);
195 static LocalBitmap* GetBitmapUnit(LLUUID);
196 static bool IsDoingUpdates(void);
197 static void PingTimer(void);
198 static void PerformTimedActions(void);
199 static void PerformSculptUpdates(LocalBitmap*);
200
201 protected:
202 static std::vector<LocalBitmap*> loaded_bitmaps;
203 typedef std::vector<LocalBitmap*>::iterator local_list_iter;
204 static bool mLayerUpdated;
205 static bool mSculptUpdated;
206};
207
208/*==================================================*/
209/* FloaterLocalAssetBrowser : interface class */
210/*==================================================*/
211/*
212 Responsible for talking to the user.
213 Instantiated by user request.
214 Destroyed when the floater is closed.
215
216*/
217class FloaterLocalAssetBrowser : public LLFloater
218{
219public:
220 FloaterLocalAssetBrowser();
221 virtual ~FloaterLocalAssetBrowser();
222 static void show(void*);
223
224
225
226private:
227 /* Widget related callbacks */
228 // Button callback declarations
229 static void onClickAdd(void* userdata);
230 static void onClickDel(void* userdata);
231 static void onClickMore(void* userdata);
232 static void onClickLess(void* userdata);
233 static void onClickUpload(void* userdata);
234
235 // ScrollList callback declarations
236 static void onChooseBitmapList(LLUICtrl* ctrl, void* userdata);
237
238 // Checkbox callback declarations
239 static void onClickUpdateChkbox(LLUICtrl* ctrl, void* userdata);
240
241 // Combobox type select
242 static void onCommitTypeCombo(LLUICtrl* ctrl, void* userdata);
243
244 // Widgets
245 LLButton* mAddBtn;
246 LLButton* mDelBtn;
247 LLButton* mMoreBtn;
248 LLButton* mLessBtn;
249 LLButton* mUploadBtn;
250
251 LLScrollListCtrl* mBitmapList;
252 LLScrollListCtrl* mUsedList;
253 LLTextureCtrl* mTextureView;
254 LLCheckBoxCtrl* mUpdateChkBox;
255
256 LLLineEditor* mPathTxt;
257 LLLineEditor* mUUIDTxt;
258 LLLineEditor* mNameTxt;
259
260 LLTextBox* mLinkTxt;
261 LLTextBox* mTimeTxt;
262 LLComboBox* mTypeComboBox;
263
264 LLTextBox* mCaptionPathTxt;
265 LLTextBox* mCaptionUUIDTxt;
266 LLTextBox* mCaptionLinkTxt;
267 LLTextBox* mCaptionNameTxt;
268 LLTextBox* mCaptionTimeTxt;
269
270 /* static pointer to self, wai? oh well. */
271 static FloaterLocalAssetBrowser* sLFInstance;
272
273 // non-widget functions
274 static void FloaterResize(bool expand);
275 static void UpdateRightSide(void);
276
277public:
278 static void UpdateBitmapScrollList(void);
279
280
281};
282
283/*==================================================*/
284/* LocalAssetBrowserTimer : timer class */
285/*==================================================*/
286/*
287 A small, simple timer class inheriting from
288 LLEventTimer, responsible for pinging the
289 LocalAssetBrowser class to perform it's
290 updates / checks / etc.
291
292*/
293class LocalAssetBrowserTimer : public LLEventTimer
294{
295 public:
296 LocalAssetBrowserTimer();
297 ~LocalAssetBrowserTimer();
298 virtual BOOL tick();
299 void start();
300 void stop();
301 bool isRunning();
302};
303
304#endif
305
diff --git a/linden/indra/newview/floaterlocalassetbrowse.cpp b/linden/indra/newview/floaterlocalassetbrowse.cpp
new file mode 100644
index 0000000..bf1bcad
--- /dev/null
+++ b/linden/indra/newview/floaterlocalassetbrowse.cpp
@@ -0,0 +1,1028 @@
1/**
2* @file floaterlocalassetbrowse.cpp
3* @brief Local texture support
4*
5* $LicenseInfo:firstyear=2009&license=viewergpl$
6*
7* Copyright (c) 2010, author unknown
8*
9* Imprudence Viewer Source Code
10* The source code in this file ("Source Code") is provided to you
11* under the terms of the GNU General Public License, version 2.0
12* ("GPL"). Terms of the GPL can be found in doc/GPL-license.txt in
13* this distribution, or online at
14* http://secondlifegrid.net/programs/open_source/licensing/gplv2
15*
16* There are special exceptions to the terms and conditions of the GPL as
17* it is applied to this Source Code. View the full text of the exception
18* in the file doc/FLOSS-exception.txt in this software distribution, or
19* online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
20*
21* By copying, modifying or distributing this software, you acknowledge
22* that you have read and understood your obligations described above,
23* and agree to abide by those obligations.
24*
25* ALL SOURCE CODE IS PROVIDED "AS IS." THE AUTHOR MAKES NO
26* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
27* COMPLETENESS OR PERFORMANCE.
28* $/LicenseInfo$
29*/
30
31/*
32
33tag: vaa emerald local_asset_browser
34
35this feature is still a work in progress.
36
37*/
38
39/* basic headers */
40#include "llviewerprecompiledheaders.h"
41#include "lluictrlfactory.h"
42
43/* boost madness from hell */
44#ifdef equivalent
45 #undef equivalent
46#endif
47#include <boost/filesystem.hpp>
48
49/* own class header && upload floater header */
50#include "floaterlocalassetbrowse.h"
51//#include "floaterlocaluploader.h" <- in development.
52
53/* image compression headers. */
54#include "llimagebmp.h"
55#include "llimagetga.h"
56#include "llimagejpeg.h"
57#include "llimagepng.h"
58
59/* misc headers */
60#include <time.h>
61#include <ctime>
62#include "llviewerimagelist.h"
63#include "llviewerobjectlist.h"
64#include "llfilepicker.h"
65#include "llviewermenufile.h"
66#include "llfloaterimagepreview.h"
67
68/* repeated in header */
69#include "lltexturectrl.h"
70#include "llscrolllistctrl.h"
71#include "llviewercontrol.h"
72
73/* including to force rebakes when needed */
74#include "llagent.h"
75#include "llvoavatar.h"
76
77/* sculpt refresh */
78#include "llvovolume.h"
79#include "llface.h"
80
81
82/*=======================================*/
83/* Instantiating manager class */
84/* and formally declaring it's list */
85/*=======================================*/
86LocalAssetBrowser* gLocalBrowser;
87LocalAssetBrowserTimer* gLocalBrowserTimer;
88std::vector<LocalBitmap*> LocalAssetBrowser::loaded_bitmaps;
89bool LocalAssetBrowser::mLayerUpdated;
90bool LocalAssetBrowser::mSculptUpdated;
91
92/*=======================================*/
93/* LocalBitmap: unit class */
94/*=======================================*/
95/*
96 The basic unit class responsible for
97 containing one loaded local texture.
98*/
99
100LocalBitmap::LocalBitmap(std::string fullpath)
101{
102 this->valid = false;
103 if ( gDirUtilp->fileExists(fullpath) )
104 {
105 /* taking care of basic properties */
106 this->id.generate();
107 this->filename = fullpath;
108 this->linkstatus = LINK_OFF;
109 this->keep_updating = false;
110 this->shortname = gDirUtilp->getBaseFileName(this->filename, true);
111 this->bitmap_type = TYPE_TEXTURE;
112 this->sculpt_dirty = false;
113 this->volume_dirty = false;
114 this->valid = false;
115
116 /* taking care of extension type now to avoid switch madness */
117 std::string temp_exten = gDirUtilp->getExtension(this->filename);
118
119 if (temp_exten == "bmp") { this->extension = IMG_EXTEN_BMP; }
120 else if (temp_exten == "tga") { this->extension = IMG_EXTEN_TGA; }
121 else if (temp_exten == "jpg" || temp_exten == "jpeg") { this->extension = IMG_EXTEN_JPG; }
122 else if (temp_exten == "png") { this->extension = IMG_EXTEN_PNG; }
123 else { return; } // no valid extension.
124
125 /* getting file's last modified */
126 const std::time_t time = boost::filesystem::last_write_time( boost::filesystem::path( this->filename ) );
127 this->last_modified = asctime( localtime(&time) );
128
129 /* checking if the bitmap is valid && decoding if it is */
130 LLImageRaw* raw_image = new LLImageRaw();
131 if ( this->decodeSelf(raw_image) )
132 {
133 /* creating a shell LLViewerImage and fusing raw image into it */
134 LLViewerImage* viewer_image = new LLViewerImage( "file://"+this->filename, this->id, LOCAL_USE_MIPMAPS );
135 viewer_image->createGLTexture( LOCAL_DISCARD_LEVEL, raw_image );
136 viewer_image->mCachedRawImage = raw_image;
137
138 /* making damn sure gImageList will not delete it prematurely */
139 viewer_image->ref();
140
141 /* finalizing by adding LLViewerImage instance into gImageList */
142 gImageList.addImage(viewer_image);
143
144 /* filename is valid, bitmap is decoded and valid, i can haz liftoff! */
145 this->valid = true;
146 }
147 }
148}
149
150LocalBitmap::~LocalBitmap()
151{
152}
153
154/* [maintenence functions] */
155void LocalBitmap::updateSelf()
156{
157 if ( this->linkstatus == LINK_ON || this->linkstatus == LINK_UPDATING )
158 {
159 /* making sure file still exists */
160 if ( !gDirUtilp->fileExists(this->filename) ) { this->linkstatus = LINK_BROKEN; return; }
161
162 /* exists, let's check if it's lastmod has changed */
163 const std::time_t temp_time = boost::filesystem::last_write_time( boost::filesystem::path( this->filename ) );
164 LLSD new_last_modified = asctime( localtime(&temp_time) );
165 if ( this->last_modified.asString() == new_last_modified.asString() ) { return; }
166
167 /* here we update the image */
168 LLImageRaw* new_imgraw = new LLImageRaw();
169
170 if ( !decodeSelf(new_imgraw) ) { this->linkstatus = LINK_UPDATING; return; }
171 else { this->linkstatus = LINK_ON; }
172
173 LLViewerImage* image = gImageList.hasImage(this->id);
174
175 if (!image->mForSculpt)
176 { image->createGLTexture( LOCAL_DISCARD_LEVEL, new_imgraw ); }
177 else
178 { image->mCachedRawImage = new_imgraw; }
179
180 /* finalizing by updating lastmod to current */
181 this->last_modified = new_last_modified;
182
183 /* setting unit property to reflect that it has been changed */
184 switch (this->bitmap_type)
185 {
186 case TYPE_TEXTURE:
187 { break; }
188
189 case TYPE_SCULPT:
190 {
191 /* sets a bool to run through all visible sculpts in one go, and update the ones necessary. */
192 this->sculpt_dirty = true;
193 this->volume_dirty = true;
194 gLocalBrowser->setSculptUpdated( true );
195 break;
196 }
197
198 case TYPE_LAYER:
199 {
200 /* sets a bool to rebake layers after the iteration is done with */
201 gLocalBrowser->setLayerUpdated( true );
202 break;
203 }
204
205 default:
206 { break; }
207
208 }
209 }
210
211}
212
213bool LocalBitmap::decodeSelf(LLImageRaw* rawimg)
214{
215 switch (this->extension)
216 {
217 case IMG_EXTEN_BMP:
218 {
219 LLPointer<LLImageBMP> bmp_image = new LLImageBMP;
220 if ( !bmp_image->load(filename) ) { break; }
221 if ( !bmp_image->decode(rawimg, 0.0f) ) { break; }
222
223 rawimg->biasedScaleToPowerOfTwo( LLViewerImage::MAX_IMAGE_SIZE_DEFAULT );
224 return true;
225 }
226
227 case IMG_EXTEN_TGA:
228 {
229 LLPointer<LLImageTGA> tga_image = new LLImageTGA;
230 if ( !tga_image->load(filename) ) { break; }
231 if ( !tga_image->decode(rawimg) ) { break; }
232
233 if( ( tga_image->getComponents() != 3) &&
234 ( tga_image->getComponents() != 4) ) { break; }
235
236 rawimg->biasedScaleToPowerOfTwo( LLViewerImage::MAX_IMAGE_SIZE_DEFAULT );
237 return true;
238 }
239
240 case IMG_EXTEN_JPG:
241 {
242 LLPointer<LLImageJPEG> jpeg_image = new LLImageJPEG;
243 if ( !jpeg_image->load(filename) ) { break; }
244 if ( !jpeg_image->decode(rawimg, 0.0f) ) { break; }
245
246 rawimg->biasedScaleToPowerOfTwo( LLViewerImage::MAX_IMAGE_SIZE_DEFAULT );
247 return true;
248 }
249
250 case IMG_EXTEN_PNG:
251 {
252 LLPointer<LLImagePNG> png_image = new LLImagePNG;
253 if ( !png_image->load(filename) ) { break; }
254 if ( !png_image->decode(rawimg, 0.0f) ) { break; }
255
256 rawimg->biasedScaleToPowerOfTwo( LLViewerImage::MAX_IMAGE_SIZE_DEFAULT );
257 return true;
258 }
259
260 default:
261 break;
262 }
263 return false;
264}
265
266void LocalBitmap::setUpdateBool()
267{
268 if ( this->linkstatus != LINK_BROKEN )
269 {
270 if ( !this->keep_updating )
271 {
272 this->linkstatus = LINK_ON;
273 this->keep_updating = true;
274 }
275 else
276 {
277 this->linkstatus = LINK_OFF;
278 this->keep_updating = false;
279 }
280 }
281 else
282 {
283 this->keep_updating = false;
284 }
285}
286
287void LocalBitmap::setType( S32 type )
288{
289 this->bitmap_type = type;
290}
291
292/* [information query functions] */
293std::string LocalBitmap::getShortName()
294{
295 return this->shortname;
296}
297
298std::string LocalBitmap::getFileName()
299{
300 return this->filename;
301}
302
303LLUUID LocalBitmap::getID()
304{
305 return this->id;
306}
307
308LLSD LocalBitmap::getLastModified()
309{
310 return this->last_modified;
311}
312
313std::string LocalBitmap::getLinkStatus()
314{
315 switch(this->linkstatus)
316 {
317 case LINK_ON:
318 return "On";
319
320 case LINK_OFF:
321 return "Off";
322
323 case LINK_BROKEN:
324 return "Broken";
325
326 case LINK_UPDATING:
327 return "Updating";
328
329 default:
330 return "Unknown";
331 }
332}
333
334bool LocalBitmap::getUpdateBool()
335{
336 return this->keep_updating;
337}
338
339bool LocalBitmap::getIfValidBool()
340{
341 return this->valid;
342}
343
344LocalBitmap* LocalBitmap::getThis()
345{
346 return this;
347}
348
349S32 LocalBitmap::getType()
350{
351 return this->bitmap_type;
352}
353
354std::vector<LLFace*> LocalBitmap::getFaceUsesThis(LLDrawable* drawable)
355{
356 std::vector<LLFace*> matching_faces;
357
358 for ( S32 face_iter = 0; face_iter <= drawable->getNumFaces(); face_iter++ )
359 {
360 LLFace* newface = drawable->getFace(face_iter);
361
362 if ( this->id == newface->getTexture()->getID() )
363 { matching_faces.push_back(newface); }
364 }
365
366 return matching_faces;
367}
368
369std::vector<affected_object> LocalBitmap::getUsingObjects(bool seek_by_type, bool seek_textures, bool seek_sculptmaps)
370{
371 std::vector<affected_object> affected_vector;
372
373 for( LLDynamicArrayPtr< LLPointer<LLViewerObject>, 256 >::iterator iter = gObjectList.mObjects.begin();
374 iter != gObjectList.mObjects.end(); iter++ )
375 {
376 LLViewerObject* obj = *iter;
377 affected_object shell;
378 shell.object = obj;
379 shell.local_sculptmap = false;
380 bool obj_relevant = false;
381
382 if ( obj && obj->mDrawable )
383 {
384 /* looking for textures */
385 if ( seek_textures || ( seek_by_type && this->bitmap_type == TYPE_TEXTURE ) )
386 {
387 std::vector<LLFace*> affected_faces = this->getFaceUsesThis( obj->mDrawable );
388 if ( !affected_faces.empty() )
389 {
390 shell.face_list = affected_faces;
391 obj_relevant = true;
392 }
393 }
394
395 /* looking for sculptmaps */
396 if ( ( seek_sculptmaps || ( seek_by_type && this->bitmap_type == TYPE_SCULPT ) )
397 && obj->isSculpted() && obj->getVolume()
398 && this->id == obj->getVolume()->getParams().getSculptID()
399 )
400 {
401 shell.local_sculptmap = true;
402 obj_relevant = true;
403 }
404 }
405
406 if (obj_relevant)
407 { affected_vector.push_back(shell); }
408 }
409
410
411
412 return affected_vector;
413}
414
415void LocalBitmap::getDebugInfo()
416{
417 /* debug function: dumps everything human readable into llinfos */
418 llinfos << "===[local bitmap debug]===" << "\n"
419 << "path: " << this->filename << "\n"
420 << "name: " << this->shortname << "\n"
421 << "extension: " << this->extension << "\n"
422 << "uuid: " << this->id << "\n"
423 << "last modified: " << this->last_modified << "\n"
424 << "link status: " << this->getLinkStatus() << "\n"
425 << "keep updated: " << this->keep_updating << "\n"
426 << "type: " << this->bitmap_type << "\n"
427 << "is valid: " << this->valid << "\n"
428 << "==========================" << llendl;
429
430}
431
432/*=======================================*/
433/* LocalAssetBrowser: internal class */
434/*=======================================*/
435/*
436 Responsible for internal workings.
437 Instantiated at the top of the source file.
438 Sits in memory until the viewer is closed.
439*/
440
441LocalAssetBrowser::LocalAssetBrowser()
442{
443 this->mLayerUpdated = false;
444 this->mSculptUpdated = false;
445}
446
447LocalAssetBrowser::~LocalAssetBrowser()
448{
449
450}
451
452void LocalAssetBrowser::AddBitmap()
453{
454 LLFilePicker& picker = LLFilePicker::instance();
455 if ( !picker.getMultipleOpenFiles(LLFilePicker::FFLOAD_IMAGE) )
456 { return; }
457
458 bool change_happened = false;
459 std::string filename = picker.getFirstFile();
460 while( !filename.empty() )
461 {
462 LocalBitmap* unit = new LocalBitmap( filename );
463
464 if ( unit->getIfValidBool() )
465 {
466 loaded_bitmaps.push_back( unit );
467 change_happened = true;
468 }
469
470 filename = picker.getNextFile();
471 }
472
473 if ( change_happened )
474 { onChangeHappened(); }
475}
476
477void LocalAssetBrowser::DelBitmap( std::vector<LLScrollListItem*> delete_vector, S32 column )
478{
479 bool change_happened = false;
480 for( std::vector<LLScrollListItem*>::iterator list_iter = delete_vector.begin();
481 list_iter != delete_vector.end(); list_iter++ )
482 {
483 LLScrollListItem* list_item = *list_iter;
484 if ( list_item )
485 {
486 LLUUID id = list_item->getColumn(column)->getValue().asUUID();
487 for (local_list_iter iter = loaded_bitmaps.begin();
488 iter != loaded_bitmaps.end();)
489 {
490 LocalBitmap* unit = (*iter)->getThis();
491
492 if ( unit->getID() == id )
493 {
494 LLViewerImage* image = gImageList.hasImage(id);
495 gImageList.deleteImage( image );
496 image->unref();
497
498 iter = loaded_bitmaps.erase(iter);
499 delete unit;
500 unit = NULL;
501
502 change_happened = true;
503 }
504 else
505 { iter++; }
506 }
507 }
508 }
509
510 if ( change_happened )
511 { onChangeHappened(); }
512}
513
514void LocalAssetBrowser::onUpdateBool(LLUUID id)
515{
516 LocalBitmap* unit = GetBitmapUnit( id );
517 if ( unit )
518 {
519 unit->setUpdateBool();
520 PingTimer();
521 }
522}
523
524void LocalAssetBrowser::onSetType(LLUUID id, S32 type)
525{
526 LocalBitmap* unit = GetBitmapUnit( id );
527 if ( unit )
528 { unit->setType(type); }
529}
530
531LocalBitmap* LocalAssetBrowser::GetBitmapUnit(LLUUID id)
532{
533 local_list_iter iter = loaded_bitmaps.begin();
534 for (; iter != loaded_bitmaps.end(); iter++)
535 {
536 if ( (*iter)->getID() == id )
537 {
538 return (*iter)->getThis();
539 }
540 }
541
542 return NULL;
543}
544
545bool LocalAssetBrowser::IsDoingUpdates()
546{
547 local_list_iter iter = loaded_bitmaps.begin();
548 for (; iter != loaded_bitmaps.end(); iter++)
549 {
550 if ( (*iter)->getUpdateBool() )
551 { return true; } /* if at least one unit in the list needs updates - we need a timer. */
552 }
553
554 return false;
555}
556
557
558/* Reaction to a change in bitmaplist, this function finds a texture picker floater's appropriate scrolllist
559 and passes this scrolllist's pointer to UpdateTextureCtrlList for processing.
560 it also processes timer start/stops as needed */
561void LocalAssetBrowser::onChangeHappened()
562{
563 /* own floater update */
564 FloaterLocalAssetBrowser::UpdateBitmapScrollList();
565
566 /* texturepicker related */
567 const LLView::child_list_t* child_list = gFloaterView->getChildList();
568 LLView::child_list_const_iter_t child_list_iter = child_list->begin();
569
570 for (; child_list_iter != child_list->end(); child_list_iter++)
571 {
572 LLView* view = *child_list_iter;
573 if ( view->getName() == LOCAL_TEXTURE_PICKER_NAME )
574 {
575 LLScrollListCtrl* ctrl = view->getChild<LLScrollListCtrl>
576 ( LOCAL_TEXTURE_PICKER_LIST_NAME,
577 LOCAL_TEXTURE_PICKER_RECURSE,
578 LOCAL_TEXTURE_PICKER_CREATEIFMISSING );
579
580 if ( ctrl ) { UpdateTextureCtrlList(ctrl); }
581 }
582 }
583
584 /* poking timer to see if it's still needed/still not needed */
585 PingTimer();
586
587}
588
589void LocalAssetBrowser::PingTimer()
590{
591 if ( !loaded_bitmaps.empty() && IsDoingUpdates() )
592 {
593 if (!gLocalBrowserTimer)
594 { gLocalBrowserTimer = new LocalAssetBrowserTimer(); }
595
596 if ( !gLocalBrowserTimer->isRunning() )
597 { gLocalBrowserTimer->start(); }
598 }
599
600 else
601 {
602 if (gLocalBrowserTimer)
603 {
604 if ( gLocalBrowserTimer->isRunning() )
605 { gLocalBrowserTimer->stop(); }
606 }
607 }
608}
609
610/* This function refills the texture picker floater's scrolllist with the updated contents of bitmaplist */
611void LocalAssetBrowser::UpdateTextureCtrlList(LLScrollListCtrl* ctrl)
612{
613 if ( ctrl ) // checking again in case called externally for some silly reason.
614 {
615 ctrl->clearRows();
616 if ( !loaded_bitmaps.empty() )
617 {
618 local_list_iter iter = loaded_bitmaps.begin();
619 for ( ; iter != loaded_bitmaps.end(); iter++ )
620 {
621 LLSD element;
622 element["columns"][0]["column"] = "unit_name";
623 element["columns"][0]["type"] = "text";
624 element["columns"][0]["value"] = (*iter)->shortname;
625
626 element["columns"][1]["column"] = "unit_id_HIDDEN";
627 element["columns"][1]["type"] = "text";
628 element["columns"][1]["value"] = (*iter)->id;
629
630 ctrl->addElement(element);
631 }
632 }
633 }
634}
635
636void LocalAssetBrowser::PerformTimedActions(void)
637{
638 // perform checking if updates are needed && update if so.
639 local_list_iter iter;
640 for (iter = loaded_bitmaps.begin(); iter != loaded_bitmaps.end(); iter++)
641 { (*iter)->updateSelf(); }
642
643 // one or more sculpts have been updated, refreshing them.
644 if ( mSculptUpdated )
645 {
646 LocalAssetBrowser::local_list_iter iter;
647 for(iter = loaded_bitmaps.begin(); iter != loaded_bitmaps.end(); iter++)
648 {
649 if ( (*iter)->sculpt_dirty )
650 {
651 PerformSculptUpdates( (*iter)->getThis() );
652 (*iter)->sculpt_dirty = false;
653 }
654 }
655 mSculptUpdated = false;
656 }
657
658 // one of the layer bitmaps has been updated, we need to rebake.
659 if ( mLayerUpdated )
660 {
661 LLVOAvatar* avatar = gAgent.getAvatarObject();
662 if (avatar) { avatar->forceBakeAllTextures(SLAM_FOR_DEBUG); }
663
664 mLayerUpdated = false;
665 }
666}
667
668void LocalAssetBrowser::PerformSculptUpdates(LocalBitmap* unit)
669{
670
671 /* looking for sculptmap using objects only */
672 std::vector<affected_object> object_list = unit->getUsingObjects(false, false, true);
673 if (object_list.empty()) { return; }
674
675 for( std::vector<affected_object>::iterator iter = object_list.begin();
676 iter != object_list.end(); iter++ )
677 {
678 affected_object aobj = *iter;
679 if ( aobj.object )
680 {
681 if ( !aobj.local_sculptmap ) { continue; } // should never get here. only in case of misuse.
682
683 // update code [begin]
684 if ( unit->volume_dirty )
685 {
686 LLImageRaw* rawimage = gImageList.hasImage( unit->getID() )->getCachedRawImage();
687
688 aobj.object->getVolume()->sculpt(rawimage->getWidth(), rawimage->getHeight(),
689 rawimage->getComponents(), rawimage->getData(), 0);
690 unit->volume_dirty = false;
691 }
692
693 // tell affected drawable it's got updated
694 aobj.object->mDrawable->getVOVolume()->setSculptChanged( true );
695 aobj.object->mDrawable->getVOVolume()->markForUpdate( true );
696 // update code [end]
697 }
698
699 }
700
701}
702
703/*==================================================*/
704/* FloaterLocalAssetBrowser : floater class */
705/*==================================================*/
706/*
707 Responsible for talking to the user.
708 Instantiated by user request.
709 Destroyed when the floater is closed.
710
711*/
712
713// Floater Globals
714FloaterLocalAssetBrowser* FloaterLocalAssetBrowser::sLFInstance = NULL;
715
716// widgets:
717 LLButton* mAddBtn;
718 LLButton* mDelBtn;
719 LLButton* mMoreBtn;
720 LLButton* mLessBtn;
721 LLButton* mUploadBtn;
722
723
724 LLScrollListCtrl* mBitmapList;
725 LLTextureCtrl* mTextureView;
726 LLCheckBoxCtrl* mUpdateChkBox;
727
728 LLLineEditor* mPathTxt;
729 LLLineEditor* mUUIDTxt;
730 LLLineEditor* mNameTxt;
731
732 LLTextBox* mLinkTxt;
733 LLTextBox* mTimeTxt;
734 LLComboBox* mTypeComboBox;
735
736 LLTextBox* mCaptionPathTxt;
737 LLTextBox* mCaptionUUIDTxt;
738 LLTextBox* mCaptionLinkTxt;
739 LLTextBox* mCaptionNameTxt;
740 LLTextBox* mCaptionTimeTxt;
741
742FloaterLocalAssetBrowser::FloaterLocalAssetBrowser()
743: LLFloater(std::string("local_bitmap_browser_floater"))
744{
745 // xui creation:
746 LLUICtrlFactory::getInstance()->buildFloater(this, "floater_local_asset_browse.xml");
747
748 // setting element/xui children:
749 mAddBtn = getChild<LLButton>("add_btn");
750 mDelBtn = getChild<LLButton>("del_btn");
751 mMoreBtn = getChild<LLButton>("more_btn");
752 mLessBtn = getChild<LLButton>("less_btn");
753 mUploadBtn = getChild<LLButton>("upload_btn");
754
755 mBitmapList = getChild<LLScrollListCtrl>("bitmap_list");
756 mTextureView = getChild<LLTextureCtrl>("texture_view");
757 mUpdateChkBox = getChild<LLCheckBoxCtrl>("keep_updating_checkbox");
758
759 mPathTxt = getChild<LLLineEditor>("path_text");
760 mUUIDTxt = getChild<LLLineEditor>("uuid_text");
761 mNameTxt = getChild<LLLineEditor>("name_text");
762
763 mLinkTxt = getChild<LLTextBox>("link_text");
764 mTimeTxt = getChild<LLTextBox>("time_text");
765 mTypeComboBox = getChild<LLComboBox>("type_combobox");
766
767 mCaptionPathTxt = getChild<LLTextBox>("path_caption_text");
768 mCaptionUUIDTxt = getChild<LLTextBox>("uuid_caption_text");
769 mCaptionLinkTxt = getChild<LLTextBox>("link_caption_text");
770 mCaptionNameTxt = getChild<LLTextBox>("name_caption_text");
771 mCaptionTimeTxt = getChild<LLTextBox>("time_caption_text");
772
773 // pre-disabling line editors, they're for view only and buttons that shouldn't be on on-spawn.
774 mPathTxt->setEnabled( false );
775 mUUIDTxt->setEnabled( false );
776 mNameTxt->setEnabled( false );
777
778 mDelBtn->setEnabled( false );
779 mUploadBtn->setEnabled( false );
780
781 // setting button callbacks:
782 mAddBtn->setClickedCallback( onClickAdd, this);
783 mDelBtn->setClickedCallback( onClickDel, this);
784 mMoreBtn->setClickedCallback( onClickMore, this);
785 mLessBtn->setClickedCallback( onClickLess, this);
786 mUploadBtn->setClickedCallback( onClickUpload, this);
787
788 // combo callback
789 mTypeComboBox->setCommitCallback(onCommitTypeCombo);
790
791 // scrolllist callbacks
792 mBitmapList->setCommitCallback(onChooseBitmapList);
793
794 // checkbox callbacks
795 mUpdateChkBox->setCommitCallback(onClickUpdateChkbox);
796
797}
798
799void FloaterLocalAssetBrowser::show(void*)
800{
801 if (!sLFInstance)
802 sLFInstance = new FloaterLocalAssetBrowser();
803 sLFInstance->open();
804 sLFInstance->UpdateBitmapScrollList();
805}
806
807FloaterLocalAssetBrowser::~FloaterLocalAssetBrowser()
808{
809 sLFInstance=NULL;
810}
811
812void FloaterLocalAssetBrowser::onClickAdd(void* userdata)
813{
814 gLocalBrowser->AddBitmap();
815}
816
817void FloaterLocalAssetBrowser::onClickDel(void* userdata)
818{
819 gLocalBrowser->DelBitmap( sLFInstance->mBitmapList->getAllSelected() );
820}
821
822/* what stopped me from using a single button and simply changing it's label
823 is the fact that i'd need to hardcode the button labels here, and that is griff. */
824void FloaterLocalAssetBrowser::onClickMore(void* userdata)
825{
826 FloaterResize(true);
827}
828
829void FloaterLocalAssetBrowser::onClickLess(void* userdata)
830{
831 FloaterResize(false);
832}
833
834void FloaterLocalAssetBrowser::onClickUpload(void* userdata)
835{
836 std::string filename = gLocalBrowser->GetBitmapUnit(
837 (LLUUID)sLFInstance->mBitmapList->getSelectedItemLabel(BITMAPLIST_COL_ID) )->getFileName();
838
839 if ( !filename.empty() )
840 {
841 LLFloaterImagePreview* floaterp = new LLFloaterImagePreview(filename);
842 LLUICtrlFactory::getInstance()->buildFloater(floaterp, "floater_image_preview.xml");
843 }
844}
845
846void FloaterLocalAssetBrowser::onChooseBitmapList(LLUICtrl* ctrl, void *userdata)
847{
848 bool button_status = sLFInstance->mBitmapList->isEmpty();
849 sLFInstance->mDelBtn->setEnabled(!button_status);
850 sLFInstance->mUploadBtn->setEnabled(!button_status);
851
852 sLFInstance->UpdateRightSide();
853}
854
855void FloaterLocalAssetBrowser::onClickUpdateChkbox(LLUICtrl *ctrl, void *userdata)
856{
857 std::string temp_str = sLFInstance->mBitmapList->getSelectedItemLabel(BITMAPLIST_COL_ID);
858 if ( !temp_str.empty() )
859 {
860 gLocalBrowser->onUpdateBool( (LLUUID)temp_str );
861 sLFInstance->UpdateRightSide();
862 }
863}
864
865void FloaterLocalAssetBrowser::onCommitTypeCombo(LLUICtrl* ctrl, void *userdata)
866{
867 std::string temp_str = sLFInstance->mBitmapList->getSelectedItemLabel(BITMAPLIST_COL_ID);
868
869 if ( !temp_str.empty() )
870 {
871 S32 selection = sLFInstance->mTypeComboBox->getCurrentIndex();
872 gLocalBrowser->onSetType( (LLUUID)temp_str, selection );
873
874 }
875}
876
877void FloaterLocalAssetBrowser::FloaterResize(bool expand)
878{
879 sLFInstance->mMoreBtn->setVisible(!expand);
880 sLFInstance->mLessBtn->setVisible(expand);
881 sLFInstance->mTextureView->setVisible(expand);
882 sLFInstance->mUpdateChkBox->setVisible(expand);
883 sLFInstance->mCaptionPathTxt->setVisible(expand);
884 sLFInstance->mCaptionUUIDTxt->setVisible(expand);
885 sLFInstance->mCaptionLinkTxt->setVisible(expand);
886 sLFInstance->mCaptionNameTxt->setVisible(expand);
887 sLFInstance->mCaptionTimeTxt->setVisible(expand);
888 sLFInstance->mTypeComboBox->setVisible(expand);
889
890 sLFInstance->mTimeTxt->setVisible(expand);
891 sLFInstance->mPathTxt->setVisible(expand);
892 sLFInstance->mUUIDTxt->setVisible(expand);
893 sLFInstance->mLinkTxt->setVisible(expand);
894 sLFInstance->mNameTxt->setVisible(expand);
895
896 if(expand)
897 {
898 sLFInstance->reshape(LF_FLOATER_EXPAND_WIDTH, LF_FLOATER_HEIGHT);
899 sLFInstance->setResizeLimits(LF_FLOATER_EXPAND_WIDTH, LF_FLOATER_HEIGHT);
900 sLFInstance->UpdateRightSide();
901 }
902 else
903 {
904 sLFInstance->reshape(LF_FLOATER_CONTRACT_WIDTH, LF_FLOATER_HEIGHT);
905 sLFInstance->setResizeLimits(LF_FLOATER_CONTRACT_WIDTH, LF_FLOATER_HEIGHT);
906 }
907
908}
909
910void FloaterLocalAssetBrowser::UpdateBitmapScrollList()
911{
912 if ( !sLFInstance ) { return; }
913
914 sLFInstance->mBitmapList->clearRows();
915 if (!gLocalBrowser->loaded_bitmaps.empty())
916 {
917
918 LocalAssetBrowser::local_list_iter iter;
919 for(iter = gLocalBrowser->loaded_bitmaps.begin(); iter != gLocalBrowser->loaded_bitmaps.end(); iter++)
920 {
921 LLSD element;
922 element["columns"][BITMAPLIST_COL_NAME]["column"] = "bitmap_name";
923 element["columns"][BITMAPLIST_COL_NAME]["type"] = "text";
924 element["columns"][BITMAPLIST_COL_NAME]["value"] = (*iter)->getShortName();
925
926 element["columns"][BITMAPLIST_COL_ID]["column"] = "bitmap_uuid";
927 element["columns"][BITMAPLIST_COL_ID]["type"] = "text";
928 element["columns"][BITMAPLIST_COL_ID]["value"] = (*iter)->getID();
929
930 sLFInstance->mBitmapList->addElement(element);
931 }
932
933 }
934 sLFInstance->UpdateRightSide();
935}
936
937void FloaterLocalAssetBrowser::UpdateRightSide()
938{
939 /*
940 Since i'm not keeping a bool on if the floater is expanded or not, i'll
941 just check if one of the widgets that shows when the floater is expanded is visible.
942
943 Also obviously before updating - checking if something IS actually selected :o
944 */
945
946 if ( !sLFInstance->mTextureView->getVisible() ) { return; }
947
948 if ( !sLFInstance->mBitmapList->getAllSelected().empty() )
949 {
950 LocalBitmap* unit = gLocalBrowser->GetBitmapUnit( LLUUID(sLFInstance->mBitmapList->getSelectedItemLabel(BITMAPLIST_COL_ID)) );
951
952 if ( unit )
953 {
954 sLFInstance->mTextureView->setImageAssetID( unit->getID() );
955 sLFInstance->mUpdateChkBox->set( unit->getUpdateBool() );
956 sLFInstance->mPathTxt->setText( unit->getFileName() );
957 sLFInstance->mUUIDTxt->setText( unit->getID().asString() );
958 sLFInstance->mNameTxt->setText( unit->getShortName() );
959 sLFInstance->mTimeTxt->setText( unit->getLastModified().asString() );
960 sLFInstance->mLinkTxt->setText( unit->getLinkStatus() );
961 sLFInstance->mTypeComboBox->selectNthItem( unit->getType() );
962
963 sLFInstance->mTextureView->setEnabled(true);
964 sLFInstance->mUpdateChkBox->setEnabled(true);
965 sLFInstance->mTypeComboBox->setEnabled(true);
966 }
967 }
968 else
969 {
970 sLFInstance->mTextureView->setImageAssetID( NO_IMAGE );
971 sLFInstance->mTextureView->setEnabled( false );
972 sLFInstance->mUpdateChkBox->set( false );
973 sLFInstance->mUpdateChkBox->setEnabled( false );
974
975 sLFInstance->mTypeComboBox->selectFirstItem();
976 sLFInstance->mTypeComboBox->setEnabled( false );
977
978 sLFInstance->mPathTxt->setText( LLStringExplicit("None") );
979 sLFInstance->mUUIDTxt->setText( LLStringExplicit("None") );
980 sLFInstance->mNameTxt->setText( LLStringExplicit("None") );
981 sLFInstance->mLinkTxt->setText( LLStringExplicit("None") );
982 sLFInstance->mTimeTxt->setText( LLStringExplicit("None") );
983 }
984}
985
986
987/*==================================================*/
988/* LocalAssetBrowserTimer: timer class */
989/*==================================================*/
990/*
991 A small, simple timer class inheriting from
992 LLEventTimer, responsible for pinging the
993 LocalAssetBrowser class to perform it's
994 updates / checks / etc.
995
996*/
997
998LocalAssetBrowserTimer::LocalAssetBrowserTimer() : LLEventTimer( (F32)TIMER_HEARTBEAT )
999{
1000
1001}
1002
1003LocalAssetBrowserTimer::~LocalAssetBrowserTimer()
1004{
1005
1006}
1007
1008BOOL LocalAssetBrowserTimer::tick()
1009{
1010 gLocalBrowser->PerformTimedActions();
1011 return FALSE;
1012}
1013
1014void LocalAssetBrowserTimer::start()
1015{
1016 mEventTimer.start();
1017}
1018
1019void LocalAssetBrowserTimer::stop()
1020{
1021 mEventTimer.stop();
1022}
1023
1024bool LocalAssetBrowserTimer::isRunning()
1025{
1026 return mEventTimer.getStarted();
1027}
1028
diff --git a/linden/indra/newview/lltexturectrl.cpp b/linden/indra/newview/lltexturectrl.cpp
index 7946604..38849f9 100644
--- a/linden/indra/newview/lltexturectrl.cpp
+++ b/linden/indra/newview/lltexturectrl.cpp
@@ -68,6 +68,12 @@
68#include "lluictrlfactory.h" 68#include "lluictrlfactory.h"
69#include "lltrans.h" 69#include "lltrans.h"
70 70
71// tag: vaa emerald local_asset_browser [begin]
72#include "floaterlocalassetbrowse.h"
73#include "llscrolllistctrl.h"
74#include "llfilepicker.h"
75#define LOCALLIST_COL_ID 1
76// tag: vaa emerald local_asset_browser [end]
71 77
72static const S32 CLOSE_BTN_WIDTH = 100; 78static const S32 CLOSE_BTN_WIDTH = 100;
73const S32 PIPETTE_BTN_WIDTH = 32; 79const S32 PIPETTE_BTN_WIDTH = 32;
@@ -163,6 +169,18 @@ public:
163 static void onSearchEdit(const std::string& search_string, void* user_data ); 169 static void onSearchEdit(const std::string& search_string, void* user_data );
164 static void onTextureSelect( const LLTextureEntry& te, void *data ); 170 static void onTextureSelect( const LLTextureEntry& te, void *data );
165 171
172 // tag: vaa emerald local_asset_browser [begin]
173// static void onBtnLocal( void* userdata );
174// static void onBtnServer( void* userdata );
175// static void switchModes( bool localmode, void* userdata );
176
177 static void onBtnAdd( void* userdata );
178 static void onBtnRemove( void* userdata );
179 static void onBtnBrowser( void* userdata );
180
181 static void onLocalScrollCommit ( LLUICtrl* ctrl, void *userdata );
182 // tag: vaa emerald local_asset_browser [end]
183
166protected: 184protected:
167 LLPointer<LLViewerImage> mTexturep; 185 LLPointer<LLViewerImage> mTexturep;
168 LLTextureCtrl* mOwner; 186 LLTextureCtrl* mOwner;
@@ -192,6 +210,7 @@ protected:
192 BOOL mNoCopyTextureSelected; 210 BOOL mNoCopyTextureSelected;
193 F32 mContextConeOpacity; 211 F32 mContextConeOpacity;
194 LLSaveFolderState mSavedFolderState; 212 LLSaveFolderState mSavedFolderState;
213 LLScrollListCtrl* mLocalScrollCtrl; // tag: vaa emerald local_asset_browser
195}; 214};
196 215
197LLFloaterTexturePicker::LLFloaterTexturePicker( 216LLFloaterTexturePicker::LLFloaterTexturePicker(
@@ -236,6 +255,18 @@ LLFloaterTexturePicker::LLFloaterTexturePicker(
236 childSetAction("Blank", LLFloaterTexturePicker::onBtnWhite,this); 255 childSetAction("Blank", LLFloaterTexturePicker::onBtnWhite,this);
237 childSetAction("Invisible", LLFloaterTexturePicker::onBtnInvisible,this); 256 childSetAction("Invisible", LLFloaterTexturePicker::onBtnInvisible,this);
238 257
258 // tag: vaa emerald local_asset_browser [begin]
259// childSetAction("Local", LLFloaterTexturePicker::onBtnLocal, this);
260// childSetAction("Server", LLFloaterTexturePicker::onBtnServer, this);
261 childSetAction("Add", LLFloaterTexturePicker::onBtnAdd, this);
262 childSetAction("Remove", LLFloaterTexturePicker::onBtnRemove, this);
263 childSetAction("Browser", LLFloaterTexturePicker::onBtnBrowser, this);
264
265 mLocalScrollCtrl = getChild<LLScrollListCtrl>("local_name_list");
266 mLocalScrollCtrl->setCallbackUserData(this);
267 mLocalScrollCtrl->setCommitCallback(onLocalScrollCommit);
268 LocalAssetBrowser::UpdateTextureCtrlList( mLocalScrollCtrl );
269 // tag: vaa emerald local_asset_browser [end]
239 270
240 childSetCommitCallback("show_folders_check", onShowFolders, this); 271 childSetCommitCallback("show_folders_check", onShowFolders, this);
241 childSetVisible("show_folders_check", FALSE); 272 childSetVisible("show_folders_check", FALSE);
@@ -763,6 +794,70 @@ void LLFloaterTexturePicker::onBtnSelect(void* userdata)
763 self->close(); 794 self->close();
764} 795}
765 796
797// tag: vaa emerald local_asset_browser [begin]
798
799// static, switches between showing inventory instance for global bitmaps
800// to showing the scroll list for local ones and back.
801/*
802void LLFloaterTexturePicker::onBtnLocal(void *userdata)
803{
804 switchModes( true, userdata );
805}
806
807void LLFloaterTexturePicker::onBtnServer(void *userdata)
808{
809 switchModes( false, userdata );
810}
811
812void LLFloaterTexturePicker::switchModes(bool localmode, void *userdata)
813{
814 LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
815
816 // servermode widgets
817 self->childSetVisible("Local", !localmode);
818 self->childSetVisible("Default", !localmode);
819 self->childSetVisible("None", !localmode);
820 self->childSetVisible("Blank", !localmode);
821 self->mSearchEdit->setVisible(!localmode);
822 self->mInventoryPanel->setVisible(!localmode);
823
824 // localmode widgets
825 self->childSetVisible("Server", localmode);
826 self->childSetVisible("Add", localmode);
827 self->childSetVisible("Remove", localmode);
828 self->childSetVisible("Browser", localmode);
829 self->mLocalScrollCtrl->setVisible(localmode);
830}
831*/
832void LLFloaterTexturePicker::onBtnAdd(void *userdata)
833{
834 LocalAssetBrowser::AddBitmap();
835}
836
837void LLFloaterTexturePicker::onBtnRemove(void *userdata)
838{
839 LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
840 LocalAssetBrowser::DelBitmap( self->mLocalScrollCtrl->getAllSelected(), LOCALLIST_COL_ID );
841}
842
843void LLFloaterTexturePicker::onBtnBrowser(void *userdata)
844{
845 FloaterLocalAssetBrowser::show(NULL);
846}
847
848// static, reacts to user clicking a valid field in the local scroll list.
849void LLFloaterTexturePicker::onLocalScrollCommit(LLUICtrl *ctrl, void *userdata)
850{
851 LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
852 LLUUID id = (LLUUID)self->mLocalScrollCtrl->getSelectedItemLabel( LOCALLIST_COL_ID );
853
854 self->mOwner->setImageAssetID( id );
855 if ( self->childGetValue("apply_immediate_check").asBoolean() )
856 { self->mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_CHANGE, id); } // calls an overridden function.
857}
858
859// tag: vaa emerald local_asset_browser [end]
860
766// static 861// static
767void LLFloaterTexturePicker::onBtnPipette( void* userdata ) 862void LLFloaterTexturePicker::onBtnPipette( void* userdata )
768{ 863{
@@ -1272,6 +1367,40 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op)
1272 } 1367 }
1273} 1368}
1274 1369
1370// tag: vaa emerald local_asset_browser [begin]
1371
1372/*
1373 overriding onFloaterCommit to forcefeed it a uuid.
1374 also, i still don't get the difference beween mImageItemID and mImageAssetID,
1375 they seem to affect the same thing? using mImageAssetID.
1376*/
1377void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLUUID id)
1378{
1379 LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
1380
1381 if( floaterp && getEnabled())
1382 {
1383 mImageItemID = id;
1384 mImageAssetID = id; //floaterp->getAssetID(); // using same as on above func.
1385 // seems to work anyway.
1386
1387 if (op == TEXTURE_SELECT && mOnSelectCallback)
1388 {
1389 mOnSelectCallback(this, mCallbackUserData);
1390 }
1391 else if (op == TEXTURE_CANCEL && mOnCancelCallback)
1392 {
1393 mOnCancelCallback(this, mCallbackUserData);
1394 }
1395 else
1396 {
1397 onCommit();
1398 }
1399 }
1400}
1401
1402// tag: vaa emerald local_asset_browser [end]
1403
1275void LLTextureCtrl::setImageAssetID( const LLUUID& asset_id ) 1404void LLTextureCtrl::setImageAssetID( const LLUUID& asset_id )
1276{ 1405{
1277 if( mImageAssetID != asset_id ) 1406 if( mImageAssetID != asset_id )
diff --git a/linden/indra/newview/lltexturectrl.h b/linden/indra/newview/lltexturectrl.h
index dccdbc5..27ac1e1 100644
--- a/linden/indra/newview/lltexturectrl.h
+++ b/linden/indra/newview/lltexturectrl.h
@@ -140,6 +140,7 @@ public:
140 140
141 void onFloaterClose(); 141 void onFloaterClose();
142 void onFloaterCommit(ETexturePickOp op); 142 void onFloaterCommit(ETexturePickOp op);
143 void onFloaterCommit(ETexturePickOp op, LLUUID id); // tag: vaa emerald local_asset_browser
143 144
144 // This call is returned when a drag is detected. Your callback 145 // This call is returned when a drag is detected. Your callback
145 // should return TRUE if the drag is acceptable. 146 // should return TRUE if the drag is acceptable.
diff --git a/linden/indra/newview/llviewerimage.h b/linden/indra/newview/llviewerimage.h
index fc27f17..c82b68b 100644
--- a/linden/indra/newview/llviewerimage.h
+++ b/linden/indra/newview/llviewerimage.h
@@ -313,6 +313,9 @@ public:
313 313
314 void addFace(LLFace* facep) ; 314 void addFace(LLFace* facep) ;
315 void removeFace(LLFace* facep) ; 315 void removeFace(LLFace* facep) ;
316
317 friend class LocalBitmap; // tag: vaa emerald local_asset_browser
318
316private: 319private:
317 /*virtual*/ void cleanup(); // Cleanup the LLViewerImage (so we can reinitialize it) 320 /*virtual*/ void cleanup(); // Cleanup the LLViewerImage (so we can reinitialize it)
318 321
diff --git a/linden/indra/newview/llviewerobjectlist.h b/linden/indra/newview/llviewerobjectlist.h
index 721bab1..07920cb 100644
--- a/linden/indra/newview/llviewerobjectlist.h
+++ b/linden/indra/newview/llviewerobjectlist.h
@@ -65,6 +65,8 @@ public:
65 ~LLViewerObjectList(); 65 ~LLViewerObjectList();
66 66
67 void destroy(); 67 void destroy();
68
69 friend class LocalBitmap; // tag: vaa emerald local_asset_browser
68 70
69 // For internal use only. Does NOT take a local id, takes an index into 71 // For internal use only. Does NOT take a local id, takes an index into
70 // an internal dynamic array. 72 // an internal dynamic array.
diff --git a/linden/indra/newview/llvovolume.h b/linden/indra/newview/llvovolume.h
index 960f6da..a78aa37 100644
--- a/linden/indra/newview/llvovolume.h
+++ b/linden/indra/newview/llvovolume.h
@@ -211,6 +211,9 @@ public:
211 BOOL isVolumeGlobal() const; 211 BOOL isVolumeGlobal() const;
212 BOOL canBeFlexible() const; 212 BOOL canBeFlexible() const;
213 BOOL setIsFlexible(BOOL is_flexible); 213 BOOL setIsFlexible(BOOL is_flexible);
214
215 // tag: vaa emerald local_asset_browser
216 void setSculptChanged(BOOL has_changed) { mSculptChanged = has_changed; }
214 217
215protected: 218protected:
216 S32 computeLODDetail(F32 distance, F32 radius); 219 S32 computeLODDetail(F32 distance, F32 radius);
diff --git a/linden/indra/newview/skins/default/xui/en-us/floater_local_asset_browse.xml b/linden/indra/newview/skins/default/xui/en-us/floater_local_asset_browse.xml
new file mode 100644
index 0000000..3ea7ce4
--- /dev/null
+++ b/linden/indra/newview/skins/default/xui/en-us/floater_local_asset_browse.xml
@@ -0,0 +1,261 @@
1<?xml version="1.0" encoding="utf-8" standalone="yes"?>
2<!-- Local Asset Browser: xui -->
3<!-- floater definition start -->
4
5<floater
6 name="local_bitmap_browser_floater"
7 title="Local Bitmap Browser"
8 can_resize="true"
9 can_minimize="true"
10 can_close="true"
11 can_drag_on_left="false"
12 width="415"
13 height="260"
14 min_width="415"
15 min_height="260"
16 rect_control="FloaterLocalbitmapbrowserRect"
17 >
18
19 <!-- floater definition end, left side begin -->
20
21 <button
22 name="add_btn"
23 label="Add"
24 left="12.5"
25 bottom="10"
26 width="90"
27 height="20"
28 />
29 <button
30 name="del_btn"
31 label="Remove"
32 left_delta="100"
33 bottom_delta="0"
34 width="90"
35 height="20"
36 />
37 <button
38 name="upload_btn"
39 label="Upload"
40 left_delta="100"
41 bottom_delta="0"
42 width="90"
43 height="20"
44 />
45 <button
46 name="more_btn"
47 label="More"
48 left_delta="100"
49 bottom_delta="0"
50 width="90"
51 height="20"
52 />
53 <button
54 name="less_btn"
55 label="Less"
56 left_delta="0"
57 bottom_delta="0"
58 width="90"
59 height="20"
60 visible="false"
61 />
62
63 <scroll_list
64 name="bitmap_list"
65 left="10"
66 bottom_delta="30"
67 width="395"
68 height="200"
69 column_padding="0"
70 can_resize="false"
71 draw_heading="true"
72 multi_select="true"
73 search_column="1"
74 follows="bottom|top"
75 >
76 <column name="bitmap_name" label="Name" dynamicwidth="true" />
77 <column name="bitmap_uuid" label="UUID" width="240" />
78 </scroll_list>
79
80 <!-- left side done, right side begin -->
81
82 <line_editor
83 bevel_style="in"
84 border_style="line"
85 border_thickness="1"
86 mouse_opaque="true"
87 follows="top"
88 height="16"
89 bottom_delta="16"
90 left_delta="405"
91 name="path_text"
92 select_all_on_focus_received="true"
93 width="305"
94 visible="false"
95 />
96
97 <text name="path_caption_text"
98 left_delta="0"
99 bottom_delta="20"
100 follows="top"
101 width="100"
102 height="16"
103 visible="false"
104 >
105 Local path:
106 </text>
107
108 <line_editor
109 bevel_style="in"
110 border_style="line"
111 border_thickness="1"
112 mouse_opaque="true"
113 follows="top"
114 height="16"
115 bottom_delta="20"
116 left_delta="0"
117 name="uuid_text"
118 select_all_on_focus_received="true"
119 width="305"
120 visible="false"
121 />
122
123 <text name="uuid_caption_text"
124 left_delta="0"
125 follows="top"
126 bottom_delta="21"
127 width="260"
128 height="16"
129 visible="false"
130 >
131 Local UdddUID:
132 </text>
133
134 <texture_picker
135 allow_no_texture="false"
136 height="100"
137 width="80"
138 default_image_name="Default"
139 can_apply_immediately="true"
140 follows="left|top"
141 label="Texture"
142 bottom_delta="20"
143 left_delta="0"
144 mouse_opaque="true"
145 name="texture_view"
146 visible="false"
147 />
148
149 <check_box
150 bottom_delta="15"
151 left_delta="100"
152 follows="top"
153 height="16"
154 initial_value="true"
155 label="Keep updating"
156 mouse_opaque="true"
157 name="keep_updating_checkbox"
158 tool_tip="Enable or disable periodic checks if the source bitmap on your hard drive has been updated"
159 width="166"
160 visible="false"
161 enabled="true"
162 />
163
164 <combo_box
165 visible="false"
166 allow_text_entry="false"
167 bottom_delta="0"
168 follows="top"
169 height="18"
170 left_delta="120"
171 max_chars="20"
172 mouse_opaque="true"
173 name="type_combobox"
174 width="83"
175 >
176
177 <combo_item name="type_texture" value="type_texture">
178 Texture
179 </combo_item>
180
181 <combo_item name="type_sculptie" value="type_sculptie">
182 Sculptmap
183 </combo_item>
184
185 <combo_item name="type_layer" value="type_layer">
186 Clothing
187 </combo_item>
188
189 </combo_box>
190
191 <text name="time_caption_text"
192 left_delta="-115"
193 bottom_delta="25"
194 follows="top"
195 width="260"
196 height="16"
197 visible="false"
198 >
199 Time:
200 </text>
201
202 <text name="time_text"
203 left_delta="50"
204 bottom_delta="0"
205 follows="top"
206 width="260"
207 height="16"
208 visible="false"
209 >
210 (date here)
211 </text>
212
213 <text name="link_caption_text"
214 left_delta="-50"
215 bottom_delta="20"
216 follows="top"
217 width="260"
218 height="16"
219 visible="false"
220 >
221 Link:
222 </text>
223
224 <text name="link_text"
225 left_delta="50"
226 bottom_delta="0"
227 follows="top"
228 width="260"
229 height="16"
230 visible="false"
231 >
232 (link status)
233 </text>
234
235 <text name="name_caption_text"
236 left_delta="-50"
237 bottom_delta="20"
238 follows="top"
239 width="260"
240 height="16"
241 visible="false"
242 >
243 Name:
244 </text>
245
246 <line_editor
247 bevel_style="in"
248 border_style="line"
249 border_thickness="1"
250 mouse_opaque="true"
251 follows="top"
252 height="16"
253 bottom_delta="0"
254 left_delta="50"
255 name="name_text"
256 select_all_on_focus_received="true"
257 width="150"
258 visible="false"
259 />
260
261</floater>
diff --git a/linden/indra/newview/skins/default/xui/en-us/floater_texture_ctrl.xml b/linden/indra/newview/skins/default/xui/en-us/floater_texture_ctrl.xml
index 97b12e0..34cb851 100644
--- a/linden/indra/newview/skins/default/xui/en-us/floater_texture_ctrl.xml
+++ b/linden/indra/newview/skins/default/xui/en-us/floater_texture_ctrl.xml
@@ -1,8 +1,8 @@
1<?xml version="1.0" encoding="utf-8" standalone="yes" ?> 1<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
2<floater bottom="-516" can_close="true" can_drag_on_left="false" can_minimize="false" 2<floater bottom="-516" can_close="true" can_drag_on_left="false" can_minimize="false"
3 can_resize="true" can_tear_off="true" enabled="true" height="290" 3 can_resize="true" can_tear_off="true" enabled="true" height="330"
4 left="478" min_height="290" min_width="410" mouse_opaque="true" 4 left="478" min_height="330" min_width="460" mouse_opaque="true"
5 name="texture picker" title="Pick: Texture" width="410"> 5 name="texture picker" title="Pick: Texture" width="460">
6 <string name="choose_picture"> 6 <string name="choose_picture">
7 Click to choose a picture 7 Click to choose a picture
8 </string> 8 </string>
@@ -30,31 +30,62 @@
30 <button bottom="-252" enabled="false" follows="left|bottom" font="SansSerifSmall" 30 <button bottom="-252" enabled="false" follows="left|bottom" font="SansSerifSmall"
31 halign="center" height="20" label="Invisible" label_selected="Invisible" left="72" 31 halign="center" height="20" label="Invisible" label_selected="Invisible" left="72"
32 mouse_opaque="true" name="Invisible" scale_image="true" width="64" /> 32 mouse_opaque="true" name="Invisible" scale_image="true" width="64" />
33 <check_box bottom="-44" enabled="true" follows="left|top" font="SansSerifSmall" 33
34 height="24" initial_value="true" label="Show Folders" left="175" 34 <check_box bottom="-305" enabled="true" follows="left|bottom" font="SansSerifSmall"
35 height="20" initial_value="true" label="Show Folders" left="4"
35 mouse_opaque="true" name="show_folders_check" radio_style="false" 36 mouse_opaque="true" name="show_folders_check" radio_style="false"
36 width="201" /> 37 width="150" />
37 <search_editor bottom="-36" enabled="true" follows="left|top|right" height="16" 38
38 label="Type here to search" left="175" mouse_opaque="true" 39 <check_box bottom="-322" enabled="true" follows="left|bottom" font="SansSerifSmall"
39 name="inventory search editor" width="231" />
40 <inventory_panel allow_multi_select="false" border="true" bottom="-256" enabled="true"
41 follows="left|top|right|bottom" height="216" left="175" mouse_opaque="true"
42 name="inventory panel" sort_order="TexturePickerSortOrder" width="231" />
43 <check_box bottom="-282" enabled="true" follows="left|bottom" font="SansSerifSmall"
44 height="20" initial_value="true" label="Apply Immediately" left="4" 40 height="20" initial_value="true" label="Apply Immediately" left="4"
45 mouse_opaque="true" name="apply_immediate_check" radio_style="false" 41 mouse_opaque="true" name="apply_immediate_check" radio_style="false"
46 width="150" /> 42 width="150" />
47 <button bottom="-282" enabled="true" follows="left|bottom" font="SansSerif" 43 <button bottom="-322" enabled="true" follows="left|bottom" font="SansSerif"
48 halign="center" height="32" image_selected="eye_button_active.tga" 44 halign="center" height="32" image_selected="eye_button_active.tga"
49 image_unselected="eye_button_inactive.tga" label="" label_selected="" 45 image_unselected="eye_button_inactive.tga" label="" label_selected=""
50 left="139" mouse_opaque="true" name="Pipette" scale_image="true" width="32" /> 46 left="139" mouse_opaque="true" name="Pipette" scale_image="true" width="32" />
51 <button bottom="-282" enabled="true" follows="right|bottom" font="SansSerif" 47 <button bottom="-322" enabled="true" follows="right|bottom" font="SansSerif"
52 halign="center" height="20" label="Cancel" label_selected="Cancel" 48 halign="center" height="20" label="Cancel" label_selected="Cancel"
53 left="186" mouse_opaque="true" name="Cancel" scale_image="true" width="100" /> 49 left="176" mouse_opaque="true" name="Cancel" scale_image="true" width="100" />
54 <button bottom="-282" enabled="true" follows="right|bottom" font="SansSerif" 50 <button bottom="-322" enabled="true" follows="right|bottom" font="SansSerif"
55 halign="center" height="20" label="Select" label_selected="Select" 51 halign="center" height="20" label="Select" label_selected="Select"
56 left="290" mouse_opaque="true" name="Select" scale_image="true" width="100" /> 52 left="280" mouse_opaque="true" name="Select" scale_image="true" width="100" />
57 <string name="pick title"> 53 <string name="pick title">
58 Pick: 54 Pick:
59 </string> 55 </string>
56
57 <tab_container border="false" bottom_delta="0" width="410" height="300" left="175" mouse_opaque="false" name="actions_tab_container" tab_position="top" follows="left|top|right|bottom">
58 <panel border="false" bottom_delta="0" follows="right|top" height="300" label="Inventory" left="0" mouse_opaque="false" name="server_tab" width="410">
59 <search_editor bottom_delta="-20" enabled="true" follows="left|top|right" height="16"
60 label="Type here to search" left="0" mouse_opaque="true"
61 name="inventory search editor" width="271" />
62 <inventory_panel allow_multi_select="false" border="true" bottom="-270" enabled="true"
63 follows="left|top|right|bottom" height="245" left="0" mouse_opaque="true"
64 name="inventory panel" sort_order="TexturePickerSortOrder" width="271" />
65 </panel>
66 <panel border="false" bottom_delta="0" follows="left|top" height="300" label="My Computer" left="175" mouse_opaque="false" name="local_tab" width="410">
67 <!-- tag: vaa emerald local_asset_browser [begin] -->
68 <button bottom_delta="-26" enabled="true" follows="left|top" font="SansSerifSmall" halign="center" height="20" label="Add" label_selected="Add" left="4" mouse_opaque="true" name="Add" scale_image="true" width="64" visible="true" />
69 <button bottom_delta="0" enabled="true" follows="left|top" font="SansSerifSmall" halign="center" height="20" label="Remove" label_selected="Remove" left="72" mouse_opaque="true" name="Remove" scale_image="true" width="64" visible="true" />
70 <button bottom_delta="0" enabled="true" follows="left|top" font="SansSerifSmall" halign="center" height="20" label="Browser" label_selected="Browser" left="140" mouse_opaque="true" name="Browser" scale_image="true" width="64" visible="true" />
71 <scroll_list
72 name="local_name_list"
73 left="0"
74 bottom="-255"
75 width="271"
76 height="225"
77 follows="left|top|right|bottom"
78 column_padding="0"
79 can_resize="false"
80 draw_heading="true"
81 multi_select="true"
82 search_column="1"
83 visible="true"
84 >
85 <column name="unit_name" label="Name" dynamicwidth="true" />
86 <column name="unit_id_HIDDEN" label="ID" width="0" />
87 </scroll_list>
88 <!-- tag: vaa emerald local_asset_browser [end] -->
89 </panel>
90 </tab_container>
60</floater> 91</floater>