diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 7688e434b7..3b1d2cddd8 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -186,7 +186,6 @@ set(viewer_SOURCE_FILES
fsradarmenu.cpp
fsscriptlibrary.cpp
fsslurlcommand.cpp
- fsvopartgroup.cpp
fswsassetblacklist.cpp
groupchatlistener.cpp
#growlmanager.cpp
@@ -890,7 +889,6 @@ set(viewer_HEADER_FILES
fsscriptlibrary.h
fsslurl.h
fsslurlcommand.h
- fsvopartgroup.h
fswsassetblacklist.h
groupchatlistener.h
llaccountingcost.h
diff --git a/indra/newview/fsvopartgroup.cpp b/indra/newview/fsvopartgroup.cpp
deleted file mode 100644
index 9f2fa8b6a0..0000000000
--- a/indra/newview/fsvopartgroup.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-/**
- * @file fsvopartgroup.cpp
- * @brief fsvopartgroup base class
- *
- * $LicenseInfo:firstyear=2014&license=fsviewerlgpl$
- * Phoenix Firestorm Viewer Source Code
- * Copyright (C) 2014, The Phoenix Firestorm Project, 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
- *
- * The Phoenix Firestorm Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA
- * http://www.firestormviewer.org
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llviewerpartsim.h" // For LL_MAX_PARTICLE_COUNT
-
-#include "fsvopartgroup.h"
-
-
-FSVOPartGroup::FSVOPartGroup()
-{
- for (S32 i = 0; i < sFreeIndexSize; ++i)
- {
- setFreeIndex(i, 0);
- }
- setIndexGeneration(1);
- setTotalParticles(0);
-
- U32 bitMasksTmp[ 32 ] = { 0xFFFFFFFF, 0x80000000, 0xC0000000, 0xE0000000,
- 0xF0000000, 0xF8000000, 0xFC000000, 0xFE000000,
- 0xFF000000, 0xFF800000, 0xFFC00000, 0xFFE00000,
- 0xFFF00000, 0xFFF80000, 0xFFFC0000, 0xFFFE0000,
- 0xFFFF0000, 0xFFFF8000, 0xFFFFC000, 0xFFFFE000,
- 0xFFFFF000, 0xFFFFF800, 0xFFFFFC00, 0xFFFFFE00,
- 0xFFFFFF00, 0xFFFFFF80, 0xFFFFFFC0, 0xFFFFFFE0,
- 0xFFFFFFF0, 0xFFFFFFF8, 0xFFFFFFFC, 0xFFFFFFFE };
-
- for (S32 i = 0; i < 32; ++i)
- {
- bitMasks[i] = bitMasksTmp[i];
- }
-}
-
-
-bool FSVOPartGroup::findAvailableVBSlots( S32 &idxStart, S32 &idxEnd, U32 amount )
-{
- idxStart = idxEnd = -1;
-
- if( amount + getTotalParticles() > LL_MAX_PARTICLE_COUNT )
- amount = LL_MAX_PARTICLE_COUNT - getTotalParticles();
-
- U32 u32Count = amount/32;
- U32 bitsLeft = amount - (u32Count*32);
- if( bitsLeft )
- ++u32Count;
- U32 maskLast = bitMasks[ bitsLeft ];
-
- int i = 0;
- int maxI = LL_MAX_PARTICLE_COUNT/32-u32Count;
- do
- {
- while( getFreeIndex(i) != 0xFFFFFFFF && i <= maxI )
- ++i;
-
- if( i > maxI )
- continue;
-
- int j = i;
- while( getFreeIndex(j) == 0xFFFFFFFF && j <= LL_MAX_PARTICLE_COUNT/32 && (j-i) != u32Count )
- ++j;
-
- if( j > LL_MAX_PARTICLE_COUNT/32 || (i-j) != u32Count || (getFreeIndex(j-1) & maskLast) != maskLast )
- {
- ++i;
- continue;
- }
-
- int k = 0;
- idxStart = i*32;
- idxEnd = i + amount;
- while( k != amount )
- {
- for( int l = 0; k != amount && l < 32; ++l )
- {
- U32 mask = 1 << l;
- setFreeIndex(i, getFreeIndex(i) & ~mask);
- ++k;
- }
- ++i;
- }
-
- setTotalParticles(getTotalParticles() + amount);
- return true;
-
- } while( i <= maxI);
- return false;
-}
diff --git a/indra/newview/fsvopartgroup.h b/indra/newview/fsvopartgroup.h
deleted file mode 100644
index 217840f22a..0000000000
--- a/indra/newview/fsvopartgroup.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/**
- * @file fsvopartgroup.h
- * @brief fsvopartgroup base class
- *
- * $LicenseInfo:firstyear=2014&license=fsviewerlgpl$
- * Phoenix Firestorm Viewer Source Code
- * Copyright (C) 2014, The Phoenix Firestorm Project, 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
- *
- * The Phoenix Firestorm Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA
- * http://www.firestormviewer.org
- * $/LicenseInfo$
- */
-
-#ifndef FS_VOPARTGROUP_H
-#define FS_VOPARTGROUP_H
-
-#include "stdtypes.h"
-
-#define sFreeIndexSize LL_MAX_PARTICLE_COUNT/32
-
-class FSVOPartGroup
-{
-public:
- FSVOPartGroup();
- ~FSVOPartGroup() {};
-
- U32 getFreeIndex(int i) {return sFreeIndex[i];}
- U32 getIndexGeneration() {return sIndexGeneration;}
- U32 getTotalParticles() {return sTotalParticles;}
-
- void setFreeIndex(int i, U32 val) {sFreeIndex[i] = val;}
- void setIndexGeneration(U32 val) {sIndexGeneration = val;}
- void setTotalParticles(U32 val) {sTotalParticles = val;}
-
- bool findAvailableVBSlots( S32 &idxStart, S32 &idxEnd, U32 amount );
-
-private:
- U32 sFreeIndex[sFreeIndexSize];
- U32 sIndexGeneration;
- U32 sTotalParticles;
-
- U32 bitMasks[ 32 ];
-};
-#endif // FS_VOPARTGROUP_H
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index a7378b093c..9c0205765b 100755
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -166,8 +166,6 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp)
mBoundingSphereRadius = 0.0f ;
mHasMedia = FALSE ;
-
- mParticleGeneration = 0; // Default = no particle
}
void LLFace::destroy()
@@ -185,14 +183,9 @@ void LLFace::destroy()
}
}
- // Make sure we released any allocated VB index if this was a particle
- // if (isState(LLFace::PARTICLE))
- if (isState(LLFace::PARTICLE) || mParticleGeneration )
- //
+ if (isState(LLFace::PARTICLE))
{
- LLVOPartGroup::freeVBSlot(getGeomIndex()/4,mParticleGeneration);
- mParticleGeneration = 0;
-
+ LLVOPartGroup::freeVBSlot(getGeomIndex()/4);
clearState(LLFace::PARTICLE);
}
@@ -421,16 +414,8 @@ void LLFace::setSize(S32 num_vertices, S32 num_indices, bool align)
llassert(verify());
}
-// Pass another flag to mark this index as from LLVOPartGroup, in that case it needs to be freed with LLVOPartGroup::LLVOPartGroup
-// void LLFace::setGeomIndex(U16 idx)
-void LLFace::setGeomIndex(U16 idx, U32 aParticleGeneration )
-//
+void LLFace::setGeomIndex(U16 idx)
{
- if( mParticleGeneration && mGeomIndex != idx )
- LLVOPartGroup::freeVBSlot(getGeomIndex()/4,mParticleGeneration);
-
- mParticleGeneration = aParticleGeneration;
-
if (mGeomIndex != idx)
{
mGeomIndex = idx;
diff --git a/indra/newview/llface.h b/indra/newview/llface.h
index b780322823..d3a561facc 100755
--- a/indra/newview/llface.h
+++ b/indra/newview/llface.h
@@ -207,11 +207,7 @@ public:
BOOL verify(const U32* indices_array = NULL) const;
void printDebugInfo() const;
- // Pass another flag to mark this index as from LLVOPartGroup, in that case it needs to be freed with LLVOPartGroup::LLVOPartGroup
- // void setGeomIndex(U16 idx);
- void setGeomIndex(U16 idx, U32 aParticleGeneration = 0);
- //
-
+ void setGeomIndex(U16 idx);
void setIndicesIndex(S32 idx);
void setDrawInfo(LLDrawInfo* draw_info);
@@ -363,9 +359,6 @@ public:
lhs->getTexture() < rhs->getTexture();
}
};
-
-private:
- U32 mParticleGeneration;
};
#endif // LL_LLFACE_H
diff --git a/indra/newview/llviewerpartsim.cpp b/indra/newview/llviewerpartsim.cpp
index 73f85c161d..f7eb7df46c 100755
--- a/indra/newview/llviewerpartsim.cpp
+++ b/indra/newview/llviewerpartsim.cpp
@@ -284,36 +284,16 @@ void LLViewerPartGroup::updateParticles(const F32 lastdt)
LLViewerCamera* camera = LLViewerCamera::getInstance();
LLViewerRegion *regionp = getRegion();
S32 end = (S32) mParticles.size();
-
- // Instead of walking the current particles back to front, we first make a copy, then sort by adress and refill mParticles as needed.
- mParticlesTemp.swap( mParticles );
- mParticles.erase( mParticles.begin(), mParticles.end() );
- std::sort( mParticlesTemp.begin(), mParticlesTemp.end() );
-
- // for (S32 i = 0 ; i < (S32)mParticles.size(); )
- for (S32 i = 0 ; i < (S32)mParticlesTemp.size(); ++i )
- //
+ for (S32 i = 0 ; i < (S32)mParticles.size();)
{
- // LLVector3 a(0.f, 0.f, 0.f); // Unused
- LLViewerPart* part = mParticlesTemp[i] ;
+ LLVector3 a(0.f, 0.f, 0.f);
+ LLViewerPart* part = mParticles[i] ;
dt = lastdt + mSkippedTime - part->mSkipOffset;
part->mSkipOffset = 0.f;
// Update current time
const F32 cur_time = part->mLastUpdateTime + dt;
-
- // Bail out as soon as possible to avoid all the complicated work down.
- if( cur_time > part->mMaxAge || LLViewerPart::LL_PART_DEAD_MASK == part->mFlags )
- {
- if (part->mVPCallback)
- (*part->mVPCallback)(*part, dt);
-
- delete part ;
- continue;
- }
- //
-
const F32 frac = cur_time / part->mMaxAge;
// "Drift" the object based on the source object
@@ -417,34 +397,26 @@ void LLViewerPartGroup::updateParticles(const F32 lastdt)
part->mLastUpdateTime = cur_time;
- // We did that above
// Kill dead particles (either flagged dead, or too old)
- // if ((part->mLastUpdateTime > part->mMaxAge) || (LLViewerPart::LL_PART_DEAD_MASK == part->mFlags))
- // {
- // mParticles[i] = mParticles.back() ;
- // mParticles.pop_back() ;
- // delete part ;
- // }
- // else
- //
+ if ((part->mLastUpdateTime > part->mMaxAge) || (LLViewerPart::LL_PART_DEAD_MASK == part->mFlags))
+ {
+ mParticles[i] = mParticles.back() ;
+ mParticles.pop_back() ;
+ delete part ;
+ }
+ else
{
F32 desired_size = calc_desired_size(camera, part->mPosAgent, part->mScale);
if (!posInGroup(part->mPosAgent, desired_size))
{
// Transfer particles between groups
LLViewerPartSim::getInstance()->put(part) ;
-
- // No need for any transfer, just to not add to mParticles.
- // mParticles[i] = mParticles.back() ;
- // mParticles.pop_back() ;
- //
+ mParticles[i] = mParticles.back() ;
+ mParticles.pop_back() ;
}
else
{
- // Keep current particle in this group.
- // i++ ;
- mParticles.push_back( part );
- //
+ i++ ;
}
}
}
@@ -920,76 +892,3 @@ void LLViewerPartSim::clearParticlesByOwnerID(const LLUUID& task_id)
}
}
-// Object pool for LLViewerPart
-U8 *sParts;
-U8 *sPartsEnd;
-U32 sFree[ LL_MAX_PARTICLE_COUNT/32 ];
-U32 sPartSize;
-
-S32 findFreeIndex()
-{
- for( int i = 0; i < LL_MAX_PARTICLE_COUNT/32; ++i )
- {
- if( sFree[i] )
- {
- U32 val = sFree[i];
- U32 mask = 1;
- int j(0);
- for( j = 0; j < 32; ++j )
- {
- if( mask & val )
- {
- mask = ~mask;
- break;
- }
-
- mask <<= 1;
- }
-
- sFree[ i ] = val & mask;
- return i*32+j;
- }
- }
- return -1;
-}
-
-void* LLViewerPart::operator new(size_t size)
-{
- if( !sParts )
- {
- sPartSize = sizeof( LLViewerPart );
- sPartSize += 0xF;
- sPartSize &= ~0xF;
- sParts = reinterpret_cast( ll_aligned_malloc<16>( sPartSize * LL_MAX_PARTICLE_COUNT ) );
- for( int i = 0; i < LL_MAX_PARTICLE_COUNT/32; ++i )
- sFree[ i ] = 0xFFFFFFFF;
-
- sPartsEnd = sParts + sPartSize * LL_MAX_PARTICLE_COUNT;
- }
-
- S32 i = findFreeIndex();
- if( i < 0 )
- return new char[ size ];
-
- return reinterpret_cast< void* >( sParts + sPartSize*i );
-}
-
-void LLViewerPart::operator delete(void* ptr)
-{
- if( ptr < sParts || ptr >= sPartsEnd )
- {
- delete [] (char*)ptr;
- return;
- }
-
- U32 diff = static_cast( reinterpret_cast(ptr) - sParts );
- diff /= sPartSize;
-
- U32 i = (diff & ~0x0000001F) / 32;
- U32 j = diff & 0x0000001F;
-
- U32 mask = 1 << j;
-
- sFree[ i ] |= mask;
-}
-//
diff --git a/indra/newview/llviewerpartsim.h b/indra/newview/llviewerpartsim.h
index 738d2f294a..40e8e1d45d 100755
--- a/indra/newview/llviewerpartsim.h
+++ b/indra/newview/llviewerpartsim.h
@@ -81,10 +81,6 @@ public:
static U32 sNextPartID;
- // Object pool for LLViewerPart
- void* operator new(size_t size);
- void operator delete(void* ptr);
- //
};
@@ -112,7 +108,6 @@ public:
typedef std::vector part_list_t;
part_list_t mParticles;
- part_list_t mParticlesTemp; // Temporary list for iteration in updateParticles
const LLVector3 &getCenterAgent() const { return mCenterAgent; }
S32 getCount() const { return (S32) mParticles.size(); }
diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp
index 1658811349..f90d827827 100755
--- a/indra/newview/llvopartgroup.cpp
+++ b/indra/newview/llvopartgroup.cpp
@@ -51,9 +51,6 @@ extern U64MicrosecondsImplicit gFrameTime;
LLPointer LLVOPartGroup::sVB = NULL;
S32 LLVOPartGroup::sVBSlotCursor = 0;
-#include "fsvopartgroup.h" // Fixing up/classifying Nicky D's fsvopartgroup code
-FSVOPartGroup *LLVOPartGroup::fsvopartgroup = NULL;
-
void LLVOPartGroup::initClass()
{
@@ -62,16 +59,6 @@ void LLVOPartGroup::initClass()
//static
void LLVOPartGroup::restoreGL()
{
- if (fsvopartgroup == NULL)
- {
- fsvopartgroup = new FSVOPartGroup();
- }
- // Fixing up/classifying Nicky D's fsvopartgroup code
- fsvopartgroup->setIndexGeneration( fsvopartgroup->getIndexGeneration() + 2);
-
- for( int i = 0; i < LL_MAX_PARTICLE_COUNT/32; ++i )
- fsvopartgroup->setFreeIndex(i, 0xFFFFFFFF);
- //
//TODO: optimize out binormal mask here. Specular and normal coords as well.
sVB = new LLVertexBuffer(VERTEX_DATA_MASK | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2, GL_STREAM_DRAW_ARB);
@@ -131,41 +118,12 @@ void LLVOPartGroup::destroyGL()
//static
S32 LLVOPartGroup::findAvailableVBSlot()
{
- // Fixing up/classifying Nicky D's fsvopartgroup code
- /*if (sVBSlotCursor >= LL_MAX_PARTICLE_COUNT)
+ if (sVBSlotCursor >= LL_MAX_PARTICLE_COUNT)
{ //no more available slots
return -1;
}
- return sVBSlotCursor++;*/
-
- for( int i = 0; i < LL_MAX_PARTICLE_COUNT/32; ++i )
- {
- if( fsvopartgroup->getFreeIndex(i) != 0 )
- {
- U32 val = fsvopartgroup->getFreeIndex(i);
- U32 mask = 1;
- int j(0);
- for( j = 0; j < 32; ++j )
- {
- if( mask & val )
- {
- mask = ~mask;
- break;
- }
-
- mask <<= 1;
- }
-
- fsvopartgroup->setFreeIndex(i, val & mask);
- fsvopartgroup->setTotalParticles(fsvopartgroup->getTotalParticles()+1);
-
- return i*32+j;
- }
- }
-
- return -1;
- //
+ return sVBSlotCursor++;
}
bool ll_is_part_idx_allocated(S32 idx, S32* start, S32* end)
@@ -184,9 +142,7 @@ bool ll_is_part_idx_allocated(S32 idx, S32* start, S32* end)
}
//static
-// Fixing up/classifying Nicky D's fsvopartgroup code
-// void LLVOPartGroup::freeVBSlot(S32 idx)
-void LLVOPartGroup::freeVBSlot(S32 idx, U32 generation )
+void LLVOPartGroup::freeVBSlot(S32 idx)
{
/*llassert(idx < LL_MAX_PARTICLE_COUNT && idx >= 0);
//llassert(sVBSlotCursor > sVBSlotFree);
@@ -197,23 +153,6 @@ void LLVOPartGroup::freeVBSlot(S32 idx, U32 generation )
sVBSlotCursor--;
*sVBSlotCursor = idx;
}*/
-
- if( idx < 0 || idx >= LL_MAX_PARTICLE_COUNT )
- return;
-
- // Fixing up/classifying Nicky D's fsvopartgroup code
- fsvopartgroup->setTotalParticles(fsvopartgroup->getTotalParticles()-1);
-
- if( fsvopartgroup->getIndexGeneration() != generation )
- return;
-
- U32 i = (idx & ~0x0000001F) / 32;
- U32 j = idx & 0x0000001F;
-
- U32 mask = 1 << j;
-
- fsvopartgroup->setFreeIndex(i, fsvopartgroup->getFreeIndex(i) | mask);
- //
}
LLVOPartGroup::LLVOPartGroup(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
@@ -223,10 +162,6 @@ LLVOPartGroup::LLVOPartGroup(const LLUUID &id, const LLPCode pcode, LLViewerRegi
setNumTEs(1);
setTETexture(0, LLUUID::null);
mbCanSelect = FALSE; // users can't select particle systems
- if (fsvopartgroup == NULL)
- {
- fsvopartgroup = new FSVOPartGroup();
- }
}
@@ -924,14 +859,6 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)
LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[mRenderPass];
- // Free all vb slots. Then try to allocate an adjacent block of slots for all faces
- for( std::vector::iterator itr = mFaceList.begin(); itr != mFaceList.end(); ++itr )
- (*itr)->setGeomIndex( 0 );
-
- S32 idxStart, idxEnd;
- bool bValidRange = LLVOPartGroup::getFsvopartgroup()->findAvailableVBSlots( idxStart, idxEnd, mFaceList.size() );
- //
-
for (std::vector::iterator i = mFaceList.begin(); i != mFaceList.end(); ++i)
{
LLFace* facep = *i;
@@ -939,26 +866,10 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)
//if (!facep->isState(LLFace::PARTICLE))
{ //set the indices of this face
-
- // Can we use a index from our preallocated list?
- // S32 idx = LLVOPartGroup::findAvailableVBSlot();
- S32 idx(-1);
- if( bValidRange )
- {
- if( idxStart < idxEnd )
- idx = idxStart++;
- }
- else
- idx = LLVOPartGroup::findAvailableVBSlot();
- //
-
+ S32 idx = LLVOPartGroup::findAvailableVBSlot();
if (idx >= 0)
{
- // Face needs to release the index when it gets destroyed.
- // facep->setGeomIndex(idx*4);
- facep->setGeomIndex(idx*4, LLVOPartGroup::getFsvopartgroup()->getIndexGeneration());
- //
-
+ facep->setGeomIndex(idx*4);
facep->setIndicesIndex(idx*6);
facep->setVertexBuffer(LLVOPartGroup::sVB);
facep->setPoolType(LLDrawPool::POOL_ALPHA);
diff --git a/indra/newview/llvopartgroup.h b/indra/newview/llvopartgroup.h
index eb98902444..2ef8b1c848 100755
--- a/indra/newview/llvopartgroup.h
+++ b/indra/newview/llvopartgroup.h
@@ -36,8 +36,6 @@
class LLViewerPartGroup;
-class FSVOPartGroup; // Fixing up/classifying Nicky D's fsvopartgroup code
-
class LLVOPartGroup : public LLAlphaObject
{
public:
@@ -50,9 +48,7 @@ public:
static void restoreGL();
static void destroyGL();
static S32 findAvailableVBSlot();
-
- // static void freeVBSlot(S32 idx);
- static void freeVBSlot(S32 idx, U32 generation);
+ static void freeVBSlot(S32 idx);
enum
{
@@ -108,8 +104,6 @@ public:
void setViewerPartGroup(LLViewerPartGroup *part_groupp) { mViewerPartGroupp = part_groupp; }
LLViewerPartGroup* getViewerPartGroup() { return mViewerPartGroupp; }
- static FSVOPartGroup* getFsvopartgroup() {return fsvopartgroup;}// Fixing up/classifying Nicky D's fsvopartgroup code
-
protected:
~LLVOPartGroup();
@@ -117,11 +111,6 @@ protected:
virtual LLVector3 getCameraPosition() const;
-// Fixing up/classifying Nicky D's fsvopartgroup code
-private:
- static FSVOPartGroup* fsvopartgroup;
-//
-
};