SH-2889 Add visual auto-muting controls
parent
655505d304
commit
18e7f1bffd
|
|
@ -2078,6 +2078,7 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge
|
|||
mFaceMask = 0x0;
|
||||
mDetail = detail;
|
||||
mSculptLevel = -2;
|
||||
mSurfaceArea = 1.f; //only calculated for sculpts, defaults to 1 for all other prims
|
||||
mIsMeshAssetLoaded = FALSE;
|
||||
mLODScaleBias.setVec(1,1,1);
|
||||
mHullPoints = NULL;
|
||||
|
|
@ -3144,6 +3145,8 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components,
|
|||
{
|
||||
F32 area = sculptGetSurfaceArea();
|
||||
|
||||
mSurfaceArea = area;
|
||||
|
||||
const F32 SCULPT_MAX_AREA = 384.f;
|
||||
|
||||
if (area < SCULPT_MIN_AREA || area > SCULPT_MAX_AREA)
|
||||
|
|
|
|||
|
|
@ -963,6 +963,7 @@ public:
|
|||
S32 getNumFaces() const;
|
||||
S32 getNumVolumeFaces() const { return mVolumeFaces.size(); }
|
||||
F32 getDetail() const { return mDetail; }
|
||||
F32 getSurfaceArea() const { return mSurfaceArea; }
|
||||
const LLVolumeParams& getParams() const { return mParams; }
|
||||
LLVolumeParams getCopyOfParams() const { return mParams; }
|
||||
const LLProfile& getProfile() const { return *mProfilep; }
|
||||
|
|
@ -1065,6 +1066,7 @@ public:
|
|||
BOOL mUnique;
|
||||
F32 mDetail;
|
||||
S32 mSculptLevel;
|
||||
F32 mSurfaceArea; //unscaled surface area
|
||||
BOOL mIsMeshAssetLoaded;
|
||||
|
||||
LLVolumeParams mParams;
|
||||
|
|
|
|||
|
|
@ -9024,6 +9024,28 @@
|
|||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>RenderAutoMuteByteLimit</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Maximum bytes of attachments before an avatar is automatically visually muted (0 for no limit).</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>RenderAutoMuteSurfaceAreaLimit</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Maximum surface area of attachments before an avatar is automatically visually muted (0 for no limit).</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>RenderUseShaderLOD</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
|
|||
|
|
@ -1077,6 +1077,7 @@ BOOL LLDrawable::isVisible() const
|
|||
LLSpatialBridge::LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask)
|
||||
: LLSpatialPartition(data_mask, render_by_group, GL_STREAM_DRAW_ARB)
|
||||
{
|
||||
mBridge = this;
|
||||
mDrawable = root;
|
||||
root->setSpatialBridge(this);
|
||||
|
||||
|
|
@ -1105,6 +1106,15 @@ LLSpatialBridge::~LLSpatialBridge()
|
|||
{
|
||||
group->mSpatialPartition->remove(this, group);
|
||||
}
|
||||
|
||||
//delete octree here so listeners will still be able to access bridge specific state
|
||||
destroyTree();
|
||||
}
|
||||
|
||||
void LLSpatialBridge::destroyTree()
|
||||
{
|
||||
delete mOctree;
|
||||
mOctree = NULL;
|
||||
}
|
||||
|
||||
void LLSpatialBridge::updateSpatialExtents()
|
||||
|
|
|
|||
|
|
@ -1187,6 +1187,8 @@ void LLSpatialGroup::clearOcclusionState(U32 state, S32 mode)
|
|||
|
||||
LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) :
|
||||
mState(0),
|
||||
mGeometryBytes(0),
|
||||
mSurfaceArea(0.f),
|
||||
mBuilt(0.f),
|
||||
mOctreeNode(node),
|
||||
mSpatialPartition(part),
|
||||
|
|
@ -1412,6 +1414,17 @@ void LLSpatialGroup::handleDestruction(const TreeNode* node)
|
|||
}
|
||||
}
|
||||
|
||||
//clean up avatar attachment stats
|
||||
LLSpatialBridge* bridge = mSpatialPartition->asBridge();
|
||||
if (bridge)
|
||||
{
|
||||
if (bridge->mAvatar.notNull())
|
||||
{
|
||||
bridge->mAvatar->mAttachmentGeometryBytes -= mGeometryBytes;
|
||||
bridge->mAvatar->mAttachmentSurfaceArea -= mSurfaceArea;
|
||||
}
|
||||
}
|
||||
|
||||
clearDrawMap();
|
||||
mVertexBuffer = NULL;
|
||||
mBufferMap.clear();
|
||||
|
|
@ -1767,7 +1780,7 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera)
|
|||
//==============================================
|
||||
|
||||
LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 buffer_usage)
|
||||
: mRenderByGroup(render_by_group)
|
||||
: mRenderByGroup(render_by_group), mBridge(NULL)
|
||||
{
|
||||
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
|
||||
mOcclusionEnabled = TRUE;
|
||||
|
|
|
|||
|
|
@ -405,6 +405,9 @@ public:
|
|||
bridge_list_t mBridgeList;
|
||||
buffer_map_t mBufferMap; //used by volume buffers to attempt to reuse vertex buffers
|
||||
|
||||
U32 mGeometryBytes; //used by volumes to track how many bytes of geometry data are in this node
|
||||
F32 mSurfaceArea; //used by volumes to track estimated surface area of geometry in this node
|
||||
|
||||
F32 mBuilt;
|
||||
OctreeNode* mOctreeNode;
|
||||
LLSpatialPartition* mSpatialPartition;
|
||||
|
|
@ -474,8 +477,8 @@ public:
|
|||
BOOL isVisible(const LLVector3& v);
|
||||
bool isHUDPartition() ;
|
||||
|
||||
virtual LLSpatialBridge* asBridge() { return NULL; }
|
||||
virtual BOOL isBridge() { return asBridge() != NULL; }
|
||||
LLSpatialBridge* asBridge() { return mBridge; }
|
||||
BOOL isBridge() { return asBridge() != NULL; }
|
||||
|
||||
void renderPhysicsShapes();
|
||||
void renderDebug();
|
||||
|
|
@ -487,6 +490,9 @@ public:
|
|||
|
||||
public:
|
||||
LLSpatialGroup::OctreeNode* mOctree;
|
||||
LLSpatialBridge* mBridge; // NULL for non-LLSpatialBridge instances, otherwise, mBridge == this
|
||||
// use a pointer instead of making "isBridge" and "asBridge" virtual so it's safe
|
||||
// to call asBridge() from the destructor
|
||||
BOOL mOcclusionEnabled; // if TRUE, occlusion culling is performed
|
||||
BOOL mInfiniteFarClip; // if TRUE, frustum culling ignores far clip plane
|
||||
U32 mBufferUsage;
|
||||
|
|
@ -511,8 +517,9 @@ public:
|
|||
|
||||
LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask);
|
||||
|
||||
virtual BOOL isSpatialBridge() const { return TRUE; }
|
||||
void destroyTree();
|
||||
|
||||
virtual BOOL isSpatialBridge() const { return TRUE; }
|
||||
virtual void updateSpatialExtents();
|
||||
virtual void updateBinRadius();
|
||||
virtual void setVisible(LLCamera& camera_in, std::vector<LLDrawable*>* results = NULL, BOOL for_select = FALSE);
|
||||
|
|
@ -523,11 +530,12 @@ public:
|
|||
virtual void shiftPos(const LLVector4a& vec);
|
||||
virtual void cleanupReferences();
|
||||
virtual LLSpatialPartition* asPartition() { return this; }
|
||||
virtual LLSpatialBridge* asBridge() { return this; }
|
||||
|
||||
|
||||
virtual LLCamera transformCamera(LLCamera& camera);
|
||||
|
||||
LLDrawable* mDrawable;
|
||||
LLPointer<LLVOAvatar> mAvatar;
|
||||
|
||||
};
|
||||
|
||||
class LLCullResult
|
||||
|
|
|
|||
|
|
@ -947,6 +947,10 @@ U32 info_display_from_string(std::string info_display)
|
|||
{
|
||||
return LLPipeline::RENDER_DEBUG_COMPOSITION;
|
||||
}
|
||||
else if ("attachment bytes" == info_display)
|
||||
{
|
||||
return LLPipeline::RENDER_DEBUG_ATTACHMENT_BYTES;
|
||||
}
|
||||
else if ("glow" == info_display)
|
||||
{
|
||||
return LLPipeline::RENDER_DEBUG_GLOW;
|
||||
|
|
|
|||
|
|
@ -651,6 +651,8 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
|
|||
LLViewerObject(id, pcode, regionp),
|
||||
mIsDummy(FALSE),
|
||||
mSpecialRenderMode(0),
|
||||
mAttachmentGeometryBytes(0),
|
||||
mAttachmentSurfaceArea(0.f),
|
||||
mTurning(FALSE),
|
||||
mPelvisToFoot(0.f),
|
||||
mLastSkeletonSerialNum( 0 ),
|
||||
|
|
@ -3363,6 +3365,16 @@ void LLVOAvatar::slamPosition()
|
|||
mRoot.updateWorldMatrixChildren();
|
||||
}
|
||||
|
||||
bool LLVOAvatar::isVisuallyMuted()
|
||||
{
|
||||
static LLCachedControl<U32> max_attachment_bytes(gSavedSettings, "RenderAutoMuteByteLimit");
|
||||
static LLCachedControl<F32> max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit");
|
||||
|
||||
return LLMuteList::getInstance()->isMuted(getID()) ||
|
||||
(mAttachmentGeometryBytes > max_attachment_bytes && max_attachment_bytes > 0) ||
|
||||
(mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// updateCharacter()
|
||||
// called on both your avatar and other avatars
|
||||
|
|
@ -3429,8 +3441,9 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
|
|||
size.setSub(ext[1],ext[0]);
|
||||
F32 mag = size.getLength3().getF32()*0.5f;
|
||||
|
||||
|
||||
F32 impostor_area = 256.f*512.f*(8.125f - LLVOAvatar::sLODFactor*8.f);
|
||||
if (LLMuteList::getInstance()->isMuted(getID()))
|
||||
if (isVisuallyMuted())
|
||||
{ // muted avatars update at 16 hz
|
||||
mUpdatePeriod = 16;
|
||||
}
|
||||
|
|
@ -8333,6 +8346,11 @@ void LLVOAvatar::idleUpdateRenderCost()
|
|||
|
||||
static std::set<LLUUID> all_textures;
|
||||
|
||||
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_ATTACHMENT_BYTES))
|
||||
{ //set debug text to attachment geometry bytes here so render cost will override
|
||||
setDebugText(llformat("%.1f KB, %.2f m^2", mAttachmentGeometryBytes/1024.f, mAttachmentSurfaceArea));
|
||||
}
|
||||
|
||||
if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME))
|
||||
{
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -380,6 +380,8 @@ private:
|
|||
|
||||
public:
|
||||
U32 renderImpostor(LLColor4U color = LLColor4U(255,255,255,255), S32 diffuse_channel = 0);
|
||||
bool isVisuallyMuted();
|
||||
|
||||
U32 renderRigid();
|
||||
U32 renderSkinned(EAvatarRenderPass pass);
|
||||
F32 getLastSkinTime() { return mLastSkinTime; }
|
||||
|
|
@ -391,6 +393,9 @@ public:
|
|||
static void restoreGL();
|
||||
BOOL mIsDummy; // for special views
|
||||
S32 mSpecialRenderMode; // special lighting
|
||||
U32 mAttachmentGeometryBytes; //number of bytes in attached geometry
|
||||
F32 mAttachmentSurfaceArea; //estimated surface area of attachments
|
||||
|
||||
private:
|
||||
bool shouldAlphaMask();
|
||||
|
||||
|
|
|
|||
|
|
@ -4097,6 +4097,32 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
|||
|
||||
LLFastTimer ftm2(FTM_REBUILD_VOLUME_VB);
|
||||
|
||||
LLVOAvatar* pAvatarVO = NULL;
|
||||
|
||||
LLSpatialBridge* bridge = group->mSpatialPartition->asBridge();
|
||||
if (bridge)
|
||||
{
|
||||
if (bridge->mAvatar.isNull())
|
||||
{
|
||||
LLViewerObject* vobj = bridge->mDrawable->getVObj();
|
||||
if (vobj)
|
||||
{
|
||||
bridge->mAvatar = vobj->getAvatar();
|
||||
}
|
||||
}
|
||||
|
||||
pAvatarVO = bridge->mAvatar;
|
||||
}
|
||||
|
||||
if (pAvatarVO)
|
||||
{
|
||||
pAvatarVO->mAttachmentGeometryBytes -= group->mGeometryBytes;
|
||||
pAvatarVO->mAttachmentSurfaceArea -= group->mSurfaceArea;
|
||||
}
|
||||
|
||||
group->mGeometryBytes = 0;
|
||||
group->mSurfaceArea = 0;
|
||||
|
||||
group->clearDrawMap();
|
||||
|
||||
mFaceList.clear();
|
||||
|
|
@ -4133,12 +4159,24 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
|||
|
||||
LLVOVolume* vobj = drawablep->getVOVolume();
|
||||
|
||||
if (!vobj)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (vobj->isMesh() &&
|
||||
(vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded() || !gMeshRepo.meshRezEnabled()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
LLVolume* volume = vobj->getVolume();
|
||||
if (volume)
|
||||
{
|
||||
const LLVector3& scale = vobj->getScale();
|
||||
group->mSurfaceArea += volume->getSurfaceArea() * llmax(llmax(scale.mV[0], scale.mV[1]), scale.mV[2]);
|
||||
}
|
||||
|
||||
llassert_always(vobj);
|
||||
vobj->updateTextureVirtualSize(true);
|
||||
vobj->preRebuild();
|
||||
|
|
@ -4183,7 +4221,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
|||
//Determine if we've received skininfo that contains an
|
||||
//alternate bind matrix - if it does then apply the translational component
|
||||
//to the joints of the avatar.
|
||||
LLVOAvatar* pAvatarVO = vobj->getAvatar();
|
||||
bool pelvisGotSet = false;
|
||||
|
||||
if ( pAvatarVO )
|
||||
|
|
@ -4253,13 +4290,16 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
|||
|
||||
if (type == LLDrawPool::POOL_ALPHA)
|
||||
{
|
||||
if (te->getFullbright())
|
||||
if (te->getColor().mV[3] > 0.f)
|
||||
{
|
||||
pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA);
|
||||
}
|
||||
else
|
||||
{
|
||||
pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA);
|
||||
if (te->getFullbright())
|
||||
{
|
||||
pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA);
|
||||
}
|
||||
else
|
||||
{
|
||||
pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (te->getShiny())
|
||||
|
|
@ -4392,8 +4432,11 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
|||
}
|
||||
else
|
||||
{
|
||||
drawablep->setState(LLDrawable::HAS_ALPHA);
|
||||
alpha_faces.push_back(facep);
|
||||
if (te->getColor().mV[3] > 0.f)
|
||||
{
|
||||
drawablep->setState(LLDrawable::HAS_ALPHA);
|
||||
alpha_faces.push_back(facep);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -4510,6 +4553,12 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
|||
}
|
||||
|
||||
mFaceList.clear();
|
||||
|
||||
if (pAvatarVO)
|
||||
{
|
||||
pAvatarVO->mAttachmentGeometryBytes += group->mGeometryBytes;
|
||||
pAvatarVO->mAttachmentSurfaceArea += group->mSurfaceArea;
|
||||
}
|
||||
}
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_VOLUME_GEOM("Volume Geometry");
|
||||
|
|
@ -4838,6 +4887,9 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
|
|||
}
|
||||
}
|
||||
|
||||
group->mGeometryBytes += buffer->getSize() + buffer->getIndicesSize();
|
||||
|
||||
|
||||
buffer_map[mask][*face_iter].push_back(buffer);
|
||||
|
||||
//add face geometry
|
||||
|
|
|
|||
|
|
@ -9420,7 +9420,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
|
|||
|
||||
assertInitialized();
|
||||
|
||||
BOOL muted = LLMuteList::getInstance()->isMuted(avatar->getID());
|
||||
bool muted = avatar->isVisuallyMuted();
|
||||
|
||||
pushRenderTypeMask();
|
||||
|
||||
|
|
|
|||
|
|
@ -432,34 +432,35 @@ public:
|
|||
|
||||
enum LLRenderDebugMask
|
||||
{
|
||||
RENDER_DEBUG_COMPOSITION = 0x0000001,
|
||||
RENDER_DEBUG_VERIFY = 0x0000002,
|
||||
RENDER_DEBUG_BBOXES = 0x0000004,
|
||||
RENDER_DEBUG_OCTREE = 0x0000008,
|
||||
RENDER_DEBUG_WIND_VECTORS = 0x0000010,
|
||||
RENDER_DEBUG_OCCLUSION = 0x0000020,
|
||||
RENDER_DEBUG_POINTS = 0x0000040,
|
||||
RENDER_DEBUG_TEXTURE_PRIORITY = 0x0000080,
|
||||
RENDER_DEBUG_TEXTURE_AREA = 0x0000100,
|
||||
RENDER_DEBUG_FACE_AREA = 0x0000200,
|
||||
RENDER_DEBUG_PARTICLES = 0x0000400,
|
||||
RENDER_DEBUG_GLOW = 0x0000800,
|
||||
RENDER_DEBUG_TEXTURE_ANIM = 0x0001000,
|
||||
RENDER_DEBUG_LIGHTS = 0x0002000,
|
||||
RENDER_DEBUG_BATCH_SIZE = 0x0004000,
|
||||
RENDER_DEBUG_ALPHA_BINS = 0x0008000,
|
||||
RENDER_DEBUG_RAYCAST = 0x0010000,
|
||||
RENDER_DEBUG_SHAME = 0x0020000,
|
||||
RENDER_DEBUG_SHADOW_FRUSTA = 0x0040000,
|
||||
RENDER_DEBUG_SCULPTED = 0x0080000,
|
||||
RENDER_DEBUG_AVATAR_VOLUME = 0x0100000,
|
||||
RENDER_DEBUG_BUILD_QUEUE = 0x0200000,
|
||||
RENDER_DEBUG_AGENT_TARGET = 0x0400000,
|
||||
RENDER_DEBUG_UPDATE_TYPE = 0x0800000,
|
||||
RENDER_DEBUG_PHYSICS_SHAPES = 0x1000000,
|
||||
RENDER_DEBUG_NORMALS = 0x2000000,
|
||||
RENDER_DEBUG_LOD_INFO = 0x4000000,
|
||||
RENDER_DEBUG_RENDER_COMPLEXITY = 0x8000000
|
||||
RENDER_DEBUG_COMPOSITION = 0x00000001,
|
||||
RENDER_DEBUG_VERIFY = 0x00000002,
|
||||
RENDER_DEBUG_BBOXES = 0x00000004,
|
||||
RENDER_DEBUG_OCTREE = 0x00000008,
|
||||
RENDER_DEBUG_WIND_VECTORS = 0x00000010,
|
||||
RENDER_DEBUG_OCCLUSION = 0x00000020,
|
||||
RENDER_DEBUG_POINTS = 0x00000040,
|
||||
RENDER_DEBUG_TEXTURE_PRIORITY = 0x00000080,
|
||||
RENDER_DEBUG_TEXTURE_AREA = 0x00000100,
|
||||
RENDER_DEBUG_FACE_AREA = 0x00000200,
|
||||
RENDER_DEBUG_PARTICLES = 0x00000400,
|
||||
RENDER_DEBUG_GLOW = 0x00000800,
|
||||
RENDER_DEBUG_TEXTURE_ANIM = 0x00001000,
|
||||
RENDER_DEBUG_LIGHTS = 0x00002000,
|
||||
RENDER_DEBUG_BATCH_SIZE = 0x00004000,
|
||||
RENDER_DEBUG_ALPHA_BINS = 0x00008000,
|
||||
RENDER_DEBUG_RAYCAST = 0x00010000,
|
||||
RENDER_DEBUG_SHAME = 0x00020000,
|
||||
RENDER_DEBUG_SHADOW_FRUSTA = 0x00040000,
|
||||
RENDER_DEBUG_SCULPTED = 0x00080000,
|
||||
RENDER_DEBUG_AVATAR_VOLUME = 0x00100000,
|
||||
RENDER_DEBUG_BUILD_QUEUE = 0x00200000,
|
||||
RENDER_DEBUG_AGENT_TARGET = 0x00400000,
|
||||
RENDER_DEBUG_UPDATE_TYPE = 0x00800000,
|
||||
RENDER_DEBUG_PHYSICS_SHAPES = 0x01000000,
|
||||
RENDER_DEBUG_NORMALS = 0x02000000,
|
||||
RENDER_DEBUG_LOD_INFO = 0x04000000,
|
||||
RENDER_DEBUG_RENDER_COMPLEXITY = 0x08000000,
|
||||
RENDER_DEBUG_ATTACHMENT_BYTES = 0x10000000,
|
||||
};
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -2499,6 +2499,16 @@
|
|||
<menu_item_check.on_click
|
||||
function="Advanced.ToggleInfoDisplay"
|
||||
parameter="rendercomplexity" />
|
||||
</menu_item_check>
|
||||
<menu_item_check
|
||||
label="Attachment Bytes"
|
||||
name="attachment bytes">
|
||||
<menu_item_check.on_check
|
||||
function="Advanced.CheckInfoDisplay"
|
||||
parameter="attachment bytes" />
|
||||
<menu_item_check.on_click
|
||||
function="Advanced.ToggleInfoDisplay"
|
||||
parameter="attachment bytes" />
|
||||
</menu_item_check>
|
||||
<menu_item_check
|
||||
label="Sculpt"
|
||||
|
|
|
|||
Loading…
Reference in New Issue