Added new fields to the experience cache.

Experience profile moved to it's own floater, will probalby be moving again.
XP profile displays most data, though the presentation is not final
Fixed a bug with the XP selection combobox in the script editor
master
dolphin 2013-08-21 15:43:09 -07:00
parent 98628066eb
commit 257110c11e
9 changed files with 662 additions and 26 deletions

View File

@ -37,11 +37,10 @@
namespace LLExperienceCache
{
typedef std::map<LLUUID, LLUUID> PrivateKeyMap;
PrivateKeyMap experinceKeyMap;
void mapPrivateKeys(const LLSD& legacyKeys);
typedef std::map<LLUUID, LLUUID> KeyMap;
KeyMap privateToPublicKeyMap;
void mapKeys(const LLSD& legacyKeys);
std::string sLookupURL;
@ -66,6 +65,7 @@ namespace LLExperienceCache
signal_map_t sSignalMap;
bool max_age_from_cache_control(const std::string& cache_control, S32 *max_age);
void eraseExpired();
@ -89,6 +89,17 @@ namespace LLExperienceCache
sPendingQueue.erase(row[OWNER_ID].asUUID());
}
if(!row.has(OWNER_ID))
{
if(row.has(AGENT_ID) && row[AGENT_ID].asUUID().notNull())
{
row[OWNER_ID]=row[AGENT_ID];
}
else
{
row[OWNER_ID]=row[GROUP_ID];
}
}
//signal
signal_map_t::iterator sig_it = sSignalMap.find(public_key);
@ -119,7 +130,7 @@ namespace LLExperienceCache
void bootstrap(const LLSD& legacyKeys, int initialExpiration)
{
mapPrivateKeys(legacyKeys);
mapKeys(legacyKeys);
LLSD::array_const_iterator it = legacyKeys.beginArray();
for(/**/; it != legacyKeys.endArray(); ++it)
{
@ -302,7 +313,8 @@ namespace LLExperienceCache
exp[EXPIRES]=DEFAULT_EXPIRATION;
exp[EXPERIENCE_ID] = id;
exp[PROPERTIES]=PROPERTY_INVALID;
exp["DoesNotExist"]=true;
exp[MISSING]=true;
exp[QUOTA] = DEFAULT_QUOTA;
processExperience(id, exp);
LL_INFOS("ExperienceCache") << "Error result for " << id << LL_ENDL ;
@ -324,14 +336,22 @@ namespace LLExperienceCache
ask_queue_t::const_iterator it = mKeys.begin();
for ( ; it != mKeys.end(); ++it)
{
LLSD exp;
//leave the properties alone if we already have a cache entry for this xp
if(!get(it->first, exp))
{
exp[PROPERTIES]=PROPERTY_INVALID;
}
exp[EXPIRES]=retry_timestamp;
exp[EXPERIENCE_ID] = it->first;
exp["key_type"] = it->second;
exp["uuid"] = it->first;
exp["error"] = (LLSD::Integer)status;
exp[PROPERTIES]=PROPERTY_INVALID;
exp[QUOTA] = DEFAULT_QUOTA;
LLExperienceCache::processExperience(it->first, exp);
LL_INFOS("ExperienceCache") << "Error result for " << it->first << LL_ENDL ;
}
}
@ -514,22 +534,25 @@ namespace LLExperienceCache
cache_t::iterator cur = it;
LLSD& exp = cur->second;
++it;
if(exp.has(EXPIRES) && exp[EXPIRES].asReal() < now)
{
if(exp.has(EXPERIENCE_ID))
if(!exp.has(EXPERIENCE_ID))
{
LLUUID id = exp[EXPERIENCE_ID].asUUID();
S32 properties = PROPERTY_INVALID;
if(exp.has(PROPERTIES))
{
properties = exp[PROPERTIES].asInteger();
LL_INFOS("ExperienceCache") << "Removing experience with no id " << LL_ENDL ;
sCache.erase(cur);
}
if(id.notNull() && ((properties & PROPERTY_INVALID) == 0))
else
{
LLUUID id = exp[EXPERIENCE_ID].asUUID();
LLUUID private_key = exp.has(LLExperienceCache::PRIVATE_KEY) ? exp[LLExperienceCache::PRIVATE_KEY].asUUID():LLUUID::null;
if(private_key.notNull() || !exp.has("DoesNotExist"))
{
fetch(id, true);
}
else
{
LL_INFOS("ExperienceCache") << "Removing invalid experience " << id << LL_ENDL ;
sCache.erase(cur);
}
}
@ -616,15 +639,14 @@ namespace LLExperienceCache
}
void LLExperienceCache::mapPrivateKeys( const LLSD& legacyKeys )
void LLExperienceCache::mapKeys( const LLSD& legacyKeys )
{
LLSD::array_const_iterator exp = legacyKeys.beginArray();
for(/**/ ; exp != legacyKeys.endArray() ; ++exp)
{
if(exp->has(LLExperienceCache::EXPERIENCE_ID) && exp->has(LLExperienceCache::PRIVATE_KEY))
{
experinceKeyMap[(*exp)[LLExperienceCache::PRIVATE_KEY].asUUID()]=(*exp)[LLExperienceCache::EXPERIENCE_ID].asUUID();
privateToPublicKeyMap[(*exp)[LLExperienceCache::PRIVATE_KEY].asUUID()]=(*exp)[LLExperienceCache::EXPERIENCE_ID].asUUID();
}
}
}
@ -635,9 +657,8 @@ LLUUID LLExperienceCache::getExperienceId(const LLUUID& private_key, bool null_i
if (private_key.isNull())
return LLUUID::null;
PrivateKeyMap::const_iterator it=experinceKeyMap.find(private_key);
if(it == experinceKeyMap.end())
KeyMap::const_iterator it=privateToPublicKeyMap.find(private_key);
if(it == privateToPublicKeyMap.end())
{
if(null_if_not_found)
{

View File

@ -40,13 +40,21 @@ class LLUUID;
namespace LLExperienceCache
{
const std::string PRIVATE_KEY = "private_id";
const std::string MISSING = "DoesNotExist";
const std::string AGENT_ID = "agent_id";
const std::string GROUP_ID = "group_id";
const std::string EXPERIENCE_ID = "public_id";
const std::string OWNER_ID = "owner_id";
const std::string NAME = "name";
const std::string PROPERTIES = "properties";
const std::string EXPIRES = "expiration";
const std::string DESCRIPTION = "description";
const std::string DESCRIPTION = "description";
const std::string QUOTA = "quota";
const std::string MATURITY = "maturity";
const std::string METADATA = "extended_metadata";
const std::string SLURL = "slurl";
// should be in sync with experience-api/experiences/models.py
const int PROPERTY_INVALID = 1 << 0;
@ -54,10 +62,12 @@ namespace LLExperienceCache
const int PROPERTY_GRID = 1 << 4;
const int PROPERTY_PRIVATE = 1 << 5;
const int PROPERTY_DISABLED = 1 << 6;
const int PROPERTY_SUSPENDED = 1 << 7;
const int PROPERTY_SUSPENDED = 1 << 7;
// default values
const static F64 DEFAULT_EXPIRATION = 600.0;
const static S32 DEFAULT_QUOTA = 128; // this is megabytes
// Callback types for get() below
typedef boost::signals2::signal<void (const LLSD& experience)>
@ -79,7 +89,7 @@ namespace LLExperienceCache
void erase(const LLUUID& key);
bool fetch(const LLUUID& key, bool refresh=false);
void insert(LLSD& experience_data);
void insert(const LLSD& experience_data);
bool get(const LLUUID& key, LLSD& experience_data);
// If name information is in cache, callback will be called immediately.
@ -87,6 +97,7 @@ namespace LLExperienceCache
const cache_t& getCached();
// maps an experience private key to the experience id
LLUUID getExperienceId(const LLUUID& private_key, bool null_if_not_found=false);
};

View File

@ -227,6 +227,7 @@ set(viewer_SOURCE_FILES
llfloatereditwater.cpp
llfloaterenvironmentsettings.cpp
llfloaterevent.cpp
llfloaterexperienceprofile.cpp
llfloaterexperiences.cpp
llfloaterfonttest.cpp
llfloatergesture.cpp
@ -813,6 +814,7 @@ set(viewer_HEADER_FILES
llfloatereditwater.h
llfloaterenvironmentsettings.h
llfloaterevent.h
llfloaterexperienceprofile.h
llfloaterexperiences.h
llfloaterfonttest.h
llfloatergesture.h

View File

@ -0,0 +1,215 @@
/**
* @file llfloaterexperienceprofile.cpp
* @brief llfloaterexperienceprofile and related class definitions
*
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2013, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llfloaterexperienceprofile.h"
#include "llexperiencecache.h"
#include "llfloaterworldmap.h"
#include "llfloaterreg.h"
#include "lllayoutstack.h"
#include "lltextbox.h"
#include "llsdserialize.h"
#include "llexpandabletextbox.h"
#include "lltexturectrl.h"
#include "lltrans.h"
#define XML_PANEL_EXPERIENCE_PROFILE "floater_experienceprofile.xml"
#define TF_NAME "experience_title"
#define TF_DESC "experience_description"
#define TF_SLURL "LocationTextText"
#define TF_MRKT "marketplace"
#define TF_MATURITY "ContentRatingText"
#define TF_OWNER "OwnerText"
#define IMG_LOGO "logo"
#define PNL_IMAGE "image_panel"
#define PNL_DESC "description panel"
#define PNL_LOC "location panel"
#define PNL_MRKT "marketplace panel"
#define BTN_TP "teleport_btn"
#define BTN_MAP "show_on_map_btn"
#define BTN_EDIT "edit_btn"
LLFloaterExperienceProfile::LLFloaterExperienceProfile(const LLSD& data)
: LLFloater(data)
, mExperienceId(data.asUUID())
, mImagePanel(NULL)
, mDescriptionPanel(NULL)
, mLocationPanel(NULL)
, mMarketplacePanel(NULL)
{
}
LLFloaterExperienceProfile::~LLFloaterExperienceProfile()
{
}
BOOL LLFloaterExperienceProfile::postBuild()
{
mImagePanel = getChild<LLLayoutPanel>(PNL_IMAGE);
mDescriptionPanel = getChild<LLLayoutPanel>(PNL_DESC);
mLocationPanel = getChild<LLLayoutPanel>(PNL_LOC);
mMarketplacePanel = getChild<LLLayoutPanel>(PNL_MRKT);
if (mExperienceId.notNull())
{
LLExperienceCache::fetch(mExperienceId, true);
LLExperienceCache::get(mExperienceId, boost::bind(&LLFloaterExperienceProfile::experienceCallback,
getDerivedHandle<LLFloaterExperienceProfile>(), _1));
}
childSetAction(BTN_TP, boost::bind(&LLFloaterExperienceProfile::onClickTeleport, this));
childSetAction(BTN_MAP, boost::bind(&LLFloaterExperienceProfile::onClickMap, this));
childSetAction(BTN_EDIT, boost::bind(&LLFloaterExperienceProfile::onClickEdit, this));
return TRUE;
}
void LLFloaterExperienceProfile::experienceCallback(LLHandle<LLFloaterExperienceProfile> handle, const LLSD& experience )
{
LLFloaterExperienceProfile* pllpep = handle.get();
if(pllpep)
{
pllpep->refreshExperience(experience);
}
}
void LLFloaterExperienceProfile::onClickMap()
{
// LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal());
// LLFloaterReg::showInstance("world_map", "center");
}
void LLFloaterExperienceProfile::onClickTeleport()
{
// if (!getPosGlobal().isExactlyZero())
// {
// gAgent.teleportViaLocation(getPosGlobal());
// LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal());
// }
}
void LLFloaterExperienceProfile::onClickEdit()
{
}
std::string LLFloaterExperienceProfile::getMaturityString(U8 maturity)
{
if(maturity <= SIM_ACCESS_MIN)
return LLTrans::getString("SIM_ACCESS_MIN");
if(maturity <= SIM_ACCESS_PG)
return LLTrans::getString("SIM_ACCESS_PG");
if(maturity <= SIM_ACCESS_MATURE)
return LLTrans::getString("SIM_ACCESS_MATURE");
if(maturity <= SIM_ACCESS_ADULT)
return LLTrans::getString("SIM_ACCESS_ADULT");
return LLStringUtil::null;
}
void LLFloaterExperienceProfile::refreshExperience( const LLSD& experience )
{
mExperienceDetails = experience;
if(experience.has(LLExperienceCache::MISSING))
{
mImagePanel->setVisible(FALSE);
mDescriptionPanel->setVisible(FALSE);
mLocationPanel->setVisible(FALSE);
mMarketplacePanel->setVisible(FALSE);
}
LLTextBox* child = getChild<LLTextBox>(TF_NAME);
child->setText(experience[LLExperienceCache::NAME].asString());
std::string value = experience[LLExperienceCache::DESCRIPTION].asString();
LLExpandableTextBox* exchild = getChild<LLExpandableTextBox>(TF_DESC);
exchild->setText(value);
mDescriptionPanel->setVisible(value.length()>0);
value = experience[LLExperienceCache::SLURL].asString();
child = getChild<LLTextBox>(TF_SLURL);
child->setText(value);
mLocationPanel->setVisible(value.length()>0);
child = getChild<LLTextBox>(TF_MATURITY);
child->setText(getMaturityString((U8)(experience[LLExperienceCache::MATURITY].asInteger())));
child = getChild<LLTextBox>(TF_OWNER);
child->setText(experience[LLExperienceCache::OWNER_ID].asString());
value=experience[LLExperienceCache::METADATA].asString();
if(value.empty())
return;
LLPointer<LLSDParser> parser = new LLSDXMLParser();
LLSD data;
std::istringstream is = std::istringstream(value);
if(LLSDParser::PARSE_FAILURE != parser->parse(is, data, value.size()))
{
if(data.has(TF_MRKT))
{
value=data[TF_MRKT].asString();
child = getChild<LLTextBox>(TF_MRKT);
child->setText(value);
mMarketplacePanel->setVisible(TRUE);
}
else
{
mMarketplacePanel->setVisible(FALSE);
}
if(data.has(IMG_LOGO))
{
LLTextureCtrl* logo = getChild<LLTextureCtrl>(IMG_LOGO);
logo->setImageAssetID(data[IMG_LOGO].asUUID());
mImagePanel->setVisible(TRUE);
}
}
}

View File

@ -0,0 +1,70 @@
/**
* @file llfloaterexperienceprofile.h
* @brief llfloaterexperienceprofile and related class definitions
*
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2013, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLFLOATEREXPERIENCEPROFILE_H
#define LL_LLFLOATEREXPERIENCEPROFILE_H
#include "llfloater.h"
#include "lluuid.h"
#include "llsd.h"
class LLLayoutPanel;
class LLFloaterExperienceProfile : public LLFloater
{
LOG_CLASS(LLFloaterExperienceProfile);
public:
LLFloaterExperienceProfile(const LLSD& data);
virtual ~LLFloaterExperienceProfile();
void setExperienceId( const LLUUID& experience_id );
protected:
void onClickMap();
void onClickTeleport();
void onClickEdit();
static void experienceCallback(LLHandle<LLFloaterExperienceProfile> handle, const LLSD& experience);
void refreshExperience(const LLSD& experience);
BOOL postBuild();
std::string getMaturityString(U8 maturity);
LLUUID mExperienceId;
LLSD mExperienceDetails;
LLLayoutPanel* mImagePanel;
LLLayoutPanel* mDescriptionPanel;
LLLayoutPanel* mLocationPanel;
LLLayoutPanel* mMarketplacePanel;
private:
};
#endif // LL_LLFLOATEREXPERIENCEPROFILE_H

View File

@ -87,6 +87,7 @@
#include "llviewercontrol.h"
#include "llappviewer.h"
#include "llexperiencecache.h"
#include "llfloaterexperienceprofile.h"
#include "llexperienceassociationresponder.h"
const std::string HELLO_LSL =
@ -407,6 +408,22 @@ void LLLiveLSLEditor::experienceChanged()
}
}
void LLLiveLSLEditor::onViewProfile( LLUICtrl *ui, void* userdata )
{
LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata;
LLUUID id;
if(self->mExperienceEnabled->get())
{
id=self->mScriptEd->getAssociatedExperience();
if(id.notNull())
{
LLFloaterReg::showInstance("experience_profile", id, true);
}
}
}
void LLLiveLSLEditor::onToggleExperience( LLUICtrl *ui, void* userdata )
{
LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata;
@ -1306,7 +1323,7 @@ void LLLiveLSLEditor::addExperienceInfo(const LLSD& experience, BOOL enabled)
void LLLiveLSLEditor::buildExperienceList()
{
mExperiences->clear();
mExperiences->clearRows();
bool foundAssociated=false;
for(LLSD::array_const_iterator it = mExperienceIds.beginArray(); it != mExperienceIds.endArray(); ++it)
{
@ -1916,6 +1933,7 @@ BOOL LLLiveLSLEditor::postBuild()
mExperienceEnabled = getChild<LLCheckBoxCtrl>("enable_xp");
childSetCommitCallback("enable_xp", onToggleExperience, this);
childSetCommitCallback("view_profile", onViewProfile, this);
return LLPreview::postBuild();

View File

@ -49,6 +49,7 @@ class LLKeywordToken;
class LLVFS;
class LLViewerInventoryItem;
class LLScriptEdContainer;
class LLFloaterExperienceProfile;
// Inner, implementation class. LLPreviewScript and LLLiveLSLEditor each own one of these.
class LLScriptEdCore : public LLPanel
@ -234,6 +235,7 @@ public:
static void setAssociatedExperience( LLHandle<LLLiveLSLEditor> editor, const LLSD& experience );
static void onToggleExperience(LLUICtrl *ui, void* userdata);
static void onViewProfile(LLUICtrl *ui, void* userdata);
void addExperienceInfo( const LLSD& experience, BOOL enabled );
void setExperienceIds(const LLSD& experience_ids);
@ -300,6 +302,8 @@ private:
LLComboBox *mExperiences;
LLCheckBoxCtrl *mExperienceEnabled;
LLSD mExperienceIds;
LLHandle<LLFloater> mExperienceProfile;
};
#endif // LL_LLPREVIEWSCRIPT_H

View File

@ -58,6 +58,7 @@
#include "llfloatereditsky.h"
#include "llfloatereditwater.h"
#include "llfloaterenvironmentsettings.h"
#include "llfloaterexperienceprofile.h"
#include "llfloaterexperiences.h"
#include "llfloaterevent.h"
#include "llfloaterdestinations.h"
@ -207,8 +208,9 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("env_edit_water", "floater_edit_water_preset.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEditWater>);
LLFloaterReg::add("env_edit_day_cycle", "floater_edit_day_cycle.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEditDayCycle>);
LLFloaterReg::add("event", "floater_event.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEvent>);
LLFloaterReg::add("experiences", "floater_experiences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterExperiences>);
LLFloaterReg::add("event", "floater_event.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEvent>);
LLFloaterReg::add("experiences", "floater_experiences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterExperiences>);
LLFloaterReg::add("experience_profile", "floater_experienceprofile.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterExperienceProfile>);
LLFloaterReg::add("font_test", "floater_font_test.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFontTest>);

View File

@ -0,0 +1,293 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<floater
positioning="cascading"
can_close="true"
enabled="true"
can_resize="true"
height="580"
min_height="350"
min_width="300"
layout="topleft"
name="floater_experience_profile"
save_rect="yes"
single_instance="false"
reuse_instance="false"
title="EXPERIENCE PROFILE"
width="358">
<panel
background_visible="true"
follows="all"
height="570"
layout="topleft"
left="5"
min_height="350"
top="5"
width="348"
name="panel_experience_info">
<text
follows="top|left|right"
font="SansSerifHugeBold"
height="26"
layout="topleft"
left_pad="4"
name="title"
text_color="White"
top="2"
value="Experience Profile"
use_ellipses="true"
left="3"
right="-3"/>
<scroll_container
color="DkGray2"
follows="all"
height="532"
layout="topleft"
left="9"
name="xp_scroll"
opaque="true"
top_pad="10"
width="330">
<panel
bg_alpha_color="DkGray2"
follows="top|left"
height="480"
layout="topleft"
left="0"
min_height="480"
name="scrolling_panel"
top="0"
width="315"
min_width="315">
<layout_stack
follows="all"
height="480"
layout="topleft"
left="0"
top="0"
orientation="vertical"
width="315">
<layout_panel
follows="all"
height="197"
layout="topleft"
left="0"
top="0"
auto_resize="false"
visible="false"
width="315"
name="image_panel">
<texture_picker
enabled="false"
fallback_image="default_land_picture.j2c"
follows="left|top"
height="197"
layout="topleft"
left="10"
name="logo"
top="10"
width="290" />
</layout_panel>
<layout_panel
follows="all"
height="19"
layout="topleft"
left="0"
top="5"
width="313"
auto_resize="false"
>
<text
follows="left|top|right"
font="SansSerifLarge"
height="14"
layout="topleft"
left="10"
name="experience_title"
text_color="white"
top="0"
use_ellipses="true"
value="Kyle's Superhero RPG"
width="288"/>
</layout_panel>
<layout_panel
follows=""
height="50"
layout="topleft"
left="0"
top="0"
auto_resize="false"
width="315"
visible="false"
name="description panel">
<expandable_text
follows="left|top|right"
font="SansSerif"
height="50"
layout="topleft"
left="7"
name="experience_description"
top="0"
value="It is mainly just a lot of men in tights on patrol for evil-doers. It is mainly just a lot of men in tights on patrol for evil-doers. It is mainly just a lot of men in tights on patrol for evil-doers. It is mainly just a lot of men in tights on patrol for evil-doers. It is mainly just a lot of men in tights on patrol for evil-doers. "
width="293"/>
</layout_panel>
<layout_panel
follows="all"
height="69"
layout="topleft"
left="0"
top="5"
width="313"
visible="false"
auto_resize="false"
name="location panel"
>
<text
type="string"
length="1"
follows="left|top"
height="16"
layout="topleft"
left="10"
name="Location"
width="290">
Location:
</text>
<text
type="string"
length="1"
follows="left|top|right"
height="18"
layout="topleft"
left="10"
valign="center"
name="LocationTextText"
width="288">
someplace
</text>
<button
follows="bottom|left"
height="23"
label="Teleport"
layout="topleft"
name="teleport_btn"
width="151"
left="10"/>
<button
follows="bottom|left"
height="23"
label="Map"
layout="topleft"
name="map_btn"
top_pad="-23"
width="101"
left_pad="5"/>
</layout_panel>
<layout_panel
follows="all"
height="53"
layout="topleft"
left="0"
top="5"
width="313"
visible="false"
auto_resize="false"
name="marketplace panel"
>
<text
type="string"
length="1"
follows="left|top"
height="16"
layout="topleft"
left="10"
width="290">
Marketplace store:
</text>
<text
type="string"
length="1"
follows="left|top|right"
height="18"
layout="topleft"
left="10"
valign="center"
name="marketplace"
width="288">
someplace
</text>
</layout_panel>
<layout_panel
follows="left|top|right"
height="69"
left="0"
top="0"
auto_resize="false"
width="315"
>
<text
type="string"
length="1"
follows="left|top"
height="16"
layout="topleft"
left="10"
name="ContentRating"
width="100">
Rating:
</text>
<text
type="string"
length="1"
follows="left|top|right"
height="18"
layout="topleft"
left_pad="2"
valign="center"
name="ContentRatingText"
top_delta="-2"
width="188">
Adult
</text>
<text
type="string"
length="1"
follows="left|top"
height="16"
layout="topleft"
left="10"
name="Owner"
width="100">
Owner:
</text>
<text
type="string"
length="1"
follows="left|top|right"
height="18"
layout="topleft"
left_pad="2"
valign="center"
name="OwnerText"
top_delta="-2"
width="188">
Kyle
</text>
<button
follows="bottom|left"
height="23"
label="Edit"
layout="topleft"
name="edit_btn"
top_pad="0"
width="151"
left="10"/>
</layout_panel>
</layout_stack>
</panel>
</scroll_container>
</panel>
</floater>