<commit_before>//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

#include "platform/platform.h"
#include "T3D/decal/decalData.h"

#include "console/consoleTypes.h"
#include "core/stream/bitStream.h"
#include "math/mathIO.h"
#include "materials/materialManager.h"
#include "materials/baseMatInstance.h"
#include "T3D/objectTypes.h"
#include "console/engineAPI.h"

GFXImplementVertexFormat( DecalVertex )
{
   addElement( "POSITION", GFXDeclType_Float3 );
   addElement( "NORMAL", GFXDeclType_Float3 );
   addElement( "TANGENT", GFXDeclType_Float3 );
   addElement( "COLOR", GFXDeclType_Color );
   addElement( "TEXCOORD", GFXDeclType_Float2, 0 );
}

IMPLEMENT_CO_DATABLOCK_V1( DecalData );

ConsoleDocClass( DecalData,
   "@brief A datablock describing an individual decal.\n\n"

   "The textures defined by the decal Material can be divided into multiple "
   "rectangular sub-textures as shown below, with a different sub-texture "
   "selected by all decals using the same DecalData (via #frame) or each decal "
   "instance (via #randomize).\n"

   "@image html images/decal_example.png \"Example of a Decal imagemap\"\n"

   "@tsexample\n"
   "datablock DecalData(BulletHoleDecal)\n"
   "{\n"
   "   material = \"DECAL_BulletHole\";\n"
   "   size = \"5.0\";\n"
   "   lifeSpan = \"50000\";\n"
   "   randomize = \"1\";\n"
   "   texRows = \"2\";\n"
   "   texCols = \"2\";\n"
   "   clippingAngle = \"60\";\n"
   "};\n"
   "@endtsexample\n\n"
   "@see Decals\n"
   "@ingroup Decals\n"
   "@ingroup FX\n"
);

//-------------------------------------------------------------------------
// DecalData
//-------------------------------------------------------------------------

DecalData::DecalData()
{
   size = 5;
   materialName = "";

   lifeSpan = 5000;
   fadeTime = 1000;

   frame = 0;
   randomize = false;
   texRows = 1;
   texCols = 1;

   fadeStartPixelSize = -1.0f;
   fadeEndPixelSize = 200.0f;

   material = NULL;
   matInst = NULL;

   renderPriority = 10;
   clippingMasks = STATIC_COLLISION_TYPEMASK;
   clippingAngle = 89.0f;

   texCoordCount = 1;

   // TODO: We could in theory calculate if we can skip
   // normals on the decal by checking the material features.
   skipVertexNormals = false;

   for ( S32 i = 0; i < 16; i++ )
   {
      texRect[i].point.set( 0.0f, 0.0f );
      texRect[i].extent.set( 1.0f, 1.0f );
   }
}

DecalData::~DecalData()
{
   SAFE_DELETE( matInst );
}

bool DecalData::onAdd()
{
   if ( !Parent::onAdd() )
      return false;

   if (size < 0.0) {
      Con::warnf("DecalData::onAdd: size < 0");
      size = 0;
   }

   getSet()->addObject( this );

	if( texRows > 1 || texCols > 1 )
		reloadRects();

   return true;
}

void DecalData::onRemove()
{
   Parent::onRemove();
}

void DecalData::initPersistFields()
{
   addGroup( "Decal" );

      addField( "size", TypeF32, Offset( size, DecalData ),
         "Width and height of the decal in meters before scale is applied." );

      addField( "material", TypeMaterialName, Offset( materialName, DecalData ),
         "Material to use for this decal." );

      addField( "lifeSpan", TypeS32, Offset( lifeSpan, DecalData ),
         "Time (in milliseconds) before this decal will be automatically deleted." );

      addField( "fadeTime", TypeS32, Offset( fadeTime, DecalData ),
         "@brief Time (in milliseconds) over which to fade out the decal before "
         "deleting it at the end of its lifetime.\n\n"
         "@see lifeSpan" );

   endGroup( "Decal" );

   addGroup( "Rendering" );

      addField( "fadeStartPixelSize", TypeF32, Offset( fadeStartPixelSize, DecalData ),
         "@brief LOD value - size in pixels at which decals of this type begin "
         "to fade out.\n\n"
         "This should be a larger value than #fadeEndPixelSize. However, you may "
         "also set this to a negative value to disable lod-based fading." );

      addField( "fadeEndPixelSize", TypeF32, Offset( fadeEndPixelSize, DecalData ),
         "@brief LOD value - size in pixels at which decals of this type are "
         "fully faded out.\n\n"
         "This should be a smaller value than #fadeStartPixelSize." );

      addField( "renderPriority", TypeS8, Offset( renderPriority, DecalData ),
         "Default renderPriority for decals of this type (determines draw "
         "order when decals overlap)." );

      addField( "clippingAngle", TypeF32, Offset( clippingAngle, DecalData ),
         "The angle in degrees used to clip geometry that faces away from the "
         "decal projection direction." );

   endGroup( "Rendering" );

   addGroup( "Texturing" );

      addField( "frame", TypeS32, Offset( frame, DecalData ),
         "Index of the texture rectangle within the imagemap to use for this decal." );

      addField( "randomize", TypeBool, Offset( randomize, DecalData ),
         "If true, a random frame from the imagemap is selected for each "
         "instance of the decal." );

      addField( "textureCoordCount", TypeS32, Offset( texCoordCount, DecalData ),
         "Number of individual frames in the imagemap (maximum 16)." );

      addField( "texRows", TypeS32, Offset( texRows, DecalData ),
         "@brief Number of rows in the supplied imagemap.\n\n"
         "Use #texRows and #texCols if the imagemap frames are arranged in a "
         "grid; use #textureCoords to manually specify UV coordinates for "
         "irregular sized frames." );

      addField( "texCols", TypeS32, Offset( texCols, DecalData ),
         "@brief Number of columns in the supplied imagemap.\n\n"
         "Use #texRows and #texCols if the imagemap frames are arranged in a "
         "grid; use #textureCoords to manually specify UV coordinates for "
         "irregular sized frames." );

      addField( "textureCoords", TypeRectF,  Offset( texRect, DecalData ), MAX_TEXCOORD_COUNT,
         "@brief An array of RectFs (topleft.x topleft.y extent.x extent.y) "
         "representing the UV coordinates for each frame in the imagemap.\n\n"
         "@note This field should only be set if the imagemap frames are "
         "irregular in size. Otherwise use the #texRows and #texCols fields "
         "and the UV coordinates will be calculated automatically." );

   endGroup( "Texturing" );

   Parent::initPersistFields();
}

void DecalData::onStaticModified( const char *slotName, const char *newValue )
{
   Parent::onStaticModified( slotName, newValue );

   if ( !isProperlyAdded() )
      return;

   // To allow changing materials live.
   if ( dStricmp( slotName, "material" ) == 0 )
   {
      materialName = newValue;
      _updateMaterial();
   }
   // To allow changing name live.
   else if ( dStricmp( slotName, "name" ) == 0 )
   {
      lookupName = getName();
   }
   else if ( dStricmp( slotName, "renderPriority" ) == 0 )
   {
      renderPriority = getMax( renderPriority, (U8)1 );
   }
}

bool DecalData::preload( bool server, String &errorStr )
{
   if (Parent::preload(server, errorStr) == false)
      return false;

   // Server assigns name to lookupName,
   // client assigns lookupName in unpack.
   if ( server )
      lookupName = getName();

   return true;
}

void DecalData::packData( BitStream *stream )
{
   Parent::packData( stream );

   stream->write( lookupName );
   stream->write( size );
   stream->write( materialName );
   stream->write( lifeSpan );
   stream->write( fadeTime );
	stream->write( texCoordCount );

   for (S32 i = 0; i < texCoordCount; i++)
      mathWrite( *stream, texRect[i] );

   stream->write( fadeStartPixelSize );
   stream->write( fadeEndPixelSize );
   stream->write( renderPriority );
   stream->write( clippingMasks );
   stream->write( clippingAngle );

	stream->write( texRows );
   stream->write( texCols );
	stream->write( frame );
	stream->write( randomize );
}

void DecalData::unpackData( BitStream *stream )
{
   Parent::unpackData( stream );

   stream->read( &lookupName );
   stream->read( &size );
   stream->read( &materialName );
   _updateMaterial();
   stream->read( &lifeSpan );
   stream->read( &fadeTime );
	stream->read( &texCoordCount );

   for (S32 i = 0; i < texCoordCount; i++)
      mathRead(*stream, &texRect[i]);

   stream->read( &fadeStartPixelSize );
   stream->read( &fadeEndPixelSize );
   stream->read( &renderPriority );
   stream->read( &clippingMasks );
   stream->read( &clippingAngle );

	stream->read( &texRows );
   stream->read( &texCols );
	stream->read( &frame );
	stream->read( &randomize );
}

void DecalData::_initMaterial()
{
   SAFE_DELETE( matInst );

   if ( material )
      matInst = material->createMatInstance();
   else
      matInst = MATMGR->createMatInstance( "WarningMaterial" );

   GFXStateBlockDesc desc;
   desc.setZReadWrite( true, false );
   //desc.zFunc = GFXCmpLess;
   matInst->addStateBlockDesc( desc );

   matInst->init( MATMGR->getDefaultFeatures(), getGFXVertexFormat<DecalVertex>() );
   if( !matInst->isValid() )
   {
      Con::errorf( "DecalData::_initMaterial - failed to create material instance for '%s'", materialName.c_str() );
      SAFE_DELETE( matInst );
      matInst = MATMGR->createMatInstance( "WarningMaterial" );
      matInst->init( MATMGR->getDefaultFeatures(), getGFXVertexFormat< DecalVertex >() );
   }
}

void DecalData::_updateMaterial()
{
   if ( materialName.isEmpty() )
      return;

   Material *pMat = NULL;
   if ( !Sim::findObject( materialName, pMat ) )
   {
      Con::printf( "DecalData::unpackUpdate, failed to find Material of name %s!", materialName.c_str() );
      return;
   }

   material = pMat;

   // Only update material instance if we have one allocated.
   if ( matInst )
      _initMaterial();
}

Material* DecalData::getMaterial()
{
   if ( !material )
   {
      _updateMaterial();
      if ( !material )
         material = static_cast<Material*>( Sim::findObject("WarningMaterial") );
   }

   return material;
}

BaseMatInstance* DecalData::getMaterialInstance()
{
   if ( !material || !matInst || matInst->getMaterial() != material )
      _initMaterial();

   return matInst;
}

DecalData* DecalData::findDatablock( String searchName )
{
   StringTableEntry className = DecalData::getStaticClassRep()->getClassName();
   DecalData *pData;
   SimSet *set = getSet();
   SimSetIterator iter( set );

   for ( ; *iter; ++iter )
   {
      if ( (*iter)->getClassName() != className )
      {
         Con::errorf( "DecalData::findDatablock - found a class %s object in DecalDataSet!", (*iter)->getClassName() );
         continue;
      }

      pData = static_cast<DecalData*>( *iter );
      if ( pData->lookupName.equal( searchName, String::NoCase ) )
         return pData;
   }

   return NULL;
}

void DecalData::inspectPostApply()
{
	reloadRects();
}

void DecalData::reloadRects()
{
	F32 rowsBase = 0;
	F32 colsBase = 0;
	bool canRenderRowsByFrame = false;
	bool canRenderColsByFrame = false;
	S32 id = 0;

	texRect[id].point.x = 0.f;
	texRect[id].extent.x = 1.f;
	texRect[id].point.y = 0.f;
	texRect[id].extent.y = 1.f;

	texCoordCount = (texRows * texCols) - 1;

	if( texCoordCount > 16 )
	{
		Con::warnf("Coordinate max must be lower than 16 to be a valid decal !");
		texRows = 1;
		texCols = 1;
		texCoordCount = 1;
	}

	// use current datablock information in order to build a template to extract
	// coordinates from.
	if( texRows > 1 )
	{
		rowsBase = ( 1.f / texRows );
		canRenderRowsByFrame = true;
	}
	if( texCols > 1 )
	{
		colsBase = ( 1.f / texCols );
		canRenderColsByFrame = true;
	}

	// if were able, lets enter the loop
   if( frame >= 0 && (canRenderRowsByFrame || canRenderColsByFrame) )
	{
		// columns first then rows
		for ( S32 colId = 1; colId <= texCols; colId++ )
		{
			for ( S32 rowId = 1; rowId <= texRows; rowId++, id++ )
			{
				// if were over the coord count, lets go
				if(id > texCoordCount)
					return;

				// keep our dimensions correct
				if(rowId > texRows)
					rowId = 1;

				if(colId > texCols)
					colId = 1;

				// start setting our rect values per frame
				if( canRenderRowsByFrame )
				{
					texRect[id].point.x = rowsBase * ( rowId - 1 );
					texRect[id].extent.x = rowsBase;
				}

				if( canRenderColsByFrame )
				{
					texRect[id].point.y = colsBase * ( colId - 1 );
					texRect[id].extent.y = colsBase;
				}
			}
		}
	}
}

DefineEngineMethod(DecalData, postApply, void, (),,
   "Recompute the imagemap sub-texture rectangles for this DecalData.\n"
   "@tsexample\n"
   "// Inform the decal object to reload its imagemap and frame data.\n"
   "%decalData.texRows = 4;\n"
   "%decalData.postApply();\n"
   "@endtsexample\n")
{
   object->inspectPostApply();
}
<commit_msg>corrects ghosted decal datablock lookup flaw<commit_after>//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

#include "platform/platform.h"
#include "T3D/decal/decalData.h"

#include "console/consoleTypes.h"
#include "core/stream/bitStream.h"
#include "math/mathIO.h"
#include "materials/materialManager.h"
#include "materials/baseMatInstance.h"
#include "T3D/objectTypes.h"
#include "console/engineAPI.h"

GFXImplementVertexFormat( DecalVertex )
{
   addElement( "POSITION", GFXDeclType_Float3 );
   addElement( "NORMAL", GFXDeclType_Float3 );
   addElement( "TANGENT", GFXDeclType_Float3 );
   addElement( "COLOR", GFXDeclType_Color );
   addElement( "TEXCOORD", GFXDeclType_Float2, 0 );
}

IMPLEMENT_CO_DATABLOCK_V1( DecalData );

ConsoleDocClass( DecalData,
   "@brief A datablock describing an individual decal.\n\n"

   "The textures defined by the decal Material can be divided into multiple "
   "rectangular sub-textures as shown below, with a different sub-texture "
   "selected by all decals using the same DecalData (via #frame) or each decal "
   "instance (via #randomize).\n"

   "@image html images/decal_example.png \"Example of a Decal imagemap\"\n"

   "@tsexample\n"
   "datablock DecalData(BulletHoleDecal)\n"
   "{\n"
   "   material = \"DECAL_BulletHole\";\n"
   "   size = \"5.0\";\n"
   "   lifeSpan = \"50000\";\n"
   "   randomize = \"1\";\n"
   "   texRows = \"2\";\n"
   "   texCols = \"2\";\n"
   "   clippingAngle = \"60\";\n"
   "};\n"
   "@endtsexample\n\n"
   "@see Decals\n"
   "@ingroup Decals\n"
   "@ingroup FX\n"
);

//-------------------------------------------------------------------------
// DecalData
//-------------------------------------------------------------------------

DecalData::DecalData()
{
   size = 5;
   materialName = "";

   lifeSpan = 5000;
   fadeTime = 1000;

   frame = 0;
   randomize = false;
   texRows = 1;
   texCols = 1;

   fadeStartPixelSize = -1.0f;
   fadeEndPixelSize = 200.0f;

   material = NULL;
   matInst = NULL;

   renderPriority = 10;
   clippingMasks = STATIC_COLLISION_TYPEMASK;
   clippingAngle = 89.0f;

   texCoordCount = 1;

   // TODO: We could in theory calculate if we can skip
   // normals on the decal by checking the material features.
   skipVertexNormals = false;

   for ( S32 i = 0; i < 16; i++ )
   {
      texRect[i].point.set( 0.0f, 0.0f );
      texRect[i].extent.set( 1.0f, 1.0f );
   }
}

DecalData::~DecalData()
{
   SAFE_DELETE( matInst );
}

bool DecalData::onAdd()
{
   if ( !Parent::onAdd() )
      return false;

   if (size < 0.0) {
      Con::warnf("DecalData::onAdd: size < 0");
      size = 0;
   }

   getSet()->addObject( this );

	if( texRows > 1 || texCols > 1 )
		reloadRects();

   return true;
}

void DecalData::onRemove()
{
   Parent::onRemove();
}

void DecalData::initPersistFields()
{
   addGroup( "Decal" );

      addField( "size", TypeF32, Offset( size, DecalData ),
         "Width and height of the decal in meters before scale is applied." );

      addField( "material", TypeMaterialName, Offset( materialName, DecalData ),
         "Material to use for this decal." );

      addField( "lifeSpan", TypeS32, Offset( lifeSpan, DecalData ),
         "Time (in milliseconds) before this decal will be automatically deleted." );

      addField( "fadeTime", TypeS32, Offset( fadeTime, DecalData ),
         "@brief Time (in milliseconds) over which to fade out the decal before "
         "deleting it at the end of its lifetime.\n\n"
         "@see lifeSpan" );

   endGroup( "Decal" );

   addGroup( "Rendering" );

      addField( "fadeStartPixelSize", TypeF32, Offset( fadeStartPixelSize, DecalData ),
         "@brief LOD value - size in pixels at which decals of this type begin "
         "to fade out.\n\n"
         "This should be a larger value than #fadeEndPixelSize. However, you may "
         "also set this to a negative value to disable lod-based fading." );

      addField( "fadeEndPixelSize", TypeF32, Offset( fadeEndPixelSize, DecalData ),
         "@brief LOD value - size in pixels at which decals of this type are "
         "fully faded out.\n\n"
         "This should be a smaller value than #fadeStartPixelSize." );

      addField( "renderPriority", TypeS8, Offset( renderPriority, DecalData ),
         "Default renderPriority for decals of this type (determines draw "
         "order when decals overlap)." );

      addField( "clippingAngle", TypeF32, Offset( clippingAngle, DecalData ),
         "The angle in degrees used to clip geometry that faces away from the "
         "decal projection direction." );

   endGroup( "Rendering" );

   addGroup( "Texturing" );

      addField( "frame", TypeS32, Offset( frame, DecalData ),
         "Index of the texture rectangle within the imagemap to use for this decal." );

      addField( "randomize", TypeBool, Offset( randomize, DecalData ),
         "If true, a random frame from the imagemap is selected for each "
         "instance of the decal." );

      addField( "textureCoordCount", TypeS32, Offset( texCoordCount, DecalData ),
         "Number of individual frames in the imagemap (maximum 16)." );

      addField( "texRows", TypeS32, Offset( texRows, DecalData ),
         "@brief Number of rows in the supplied imagemap.\n\n"
         "Use #texRows and #texCols if the imagemap frames are arranged in a "
         "grid; use #textureCoords to manually specify UV coordinates for "
         "irregular sized frames." );

      addField( "texCols", TypeS32, Offset( texCols, DecalData ),
         "@brief Number of columns in the supplied imagemap.\n\n"
         "Use #texRows and #texCols if the imagemap frames are arranged in a "
         "grid; use #textureCoords to manually specify UV coordinates for "
         "irregular sized frames." );

      addField( "textureCoords", TypeRectF,  Offset( texRect, DecalData ), MAX_TEXCOORD_COUNT,
         "@brief An array of RectFs (topleft.x topleft.y extent.x extent.y) "
         "representing the UV coordinates for each frame in the imagemap.\n\n"
         "@note This field should only be set if the imagemap frames are "
         "irregular in size. Otherwise use the #texRows and #texCols fields "
         "and the UV coordinates will be calculated automatically." );

   endGroup( "Texturing" );

   Parent::initPersistFields();
}

void DecalData::onStaticModified( const char *slotName, const char *newValue )
{
   Parent::onStaticModified( slotName, newValue );

   if ( !isProperlyAdded() )
      return;

   // To allow changing materials live.
   if ( dStricmp( slotName, "material" ) == 0 )
   {
      materialName = newValue;
      _updateMaterial();
   }
   // To allow changing name live.
   else if ( dStricmp( slotName, "name" ) == 0 )
   {
      lookupName = getName();
   }
   else if ( dStricmp( slotName, "renderPriority" ) == 0 )
   {
      renderPriority = getMax( renderPriority, (U8)1 );
   }
}

bool DecalData::preload( bool server, String &errorStr )
{
   if (Parent::preload(server, errorStr) == false)
      return false;

   // Server assigns name to lookupName,
   // client assigns lookupName in unpack.
   if ( server )
      lookupName = getName();

   return true;
}

void DecalData::packData( BitStream *stream )
{
   Parent::packData( stream );

   stream->write( lookupName );
   stream->write( size );
   stream->write( materialName );
   stream->write( lifeSpan );
   stream->write( fadeTime );
	stream->write( texCoordCount );

   for (S32 i = 0; i < texCoordCount; i++)
      mathWrite( *stream, texRect[i] );

   stream->write( fadeStartPixelSize );
   stream->write( fadeEndPixelSize );
   stream->write( renderPriority );
   stream->write( clippingMasks );
   stream->write( clippingAngle );

	stream->write( texRows );
   stream->write( texCols );
	stream->write( frame );
	stream->write( randomize );
}

void DecalData::unpackData( BitStream *stream )
{
   Parent::unpackData( stream );

   stream->read( &lookupName );
   assignName(lookupName);
   stream->read( &size );
   stream->read( &materialName );
   _updateMaterial();
   stream->read( &lifeSpan );
   stream->read( &fadeTime );
	stream->read( &texCoordCount );

   for (S32 i = 0; i < texCoordCount; i++)
      mathRead(*stream, &texRect[i]);

   stream->read( &fadeStartPixelSize );
   stream->read( &fadeEndPixelSize );
   stream->read( &renderPriority );
   stream->read( &clippingMasks );
   stream->read( &clippingAngle );

	stream->read( &texRows );
   stream->read( &texCols );
	stream->read( &frame );
	stream->read( &randomize );
}

void DecalData::_initMaterial()
{
   SAFE_DELETE( matInst );

   if ( material )
      matInst = material->createMatInstance();
   else
      matInst = MATMGR->createMatInstance( "WarningMaterial" );

   GFXStateBlockDesc desc;
   desc.setZReadWrite( true, false );
   //desc.zFunc = GFXCmpLess;
   matInst->addStateBlockDesc( desc );

   matInst->init( MATMGR->getDefaultFeatures(), getGFXVertexFormat<DecalVertex>() );
   if( !matInst->isValid() )
   {
      Con::errorf( "DecalData::_initMaterial - failed to create material instance for '%s'", materialName.c_str() );
      SAFE_DELETE( matInst );
      matInst = MATMGR->createMatInstance( "WarningMaterial" );
      matInst->init( MATMGR->getDefaultFeatures(), getGFXVertexFormat< DecalVertex >() );
   }
}

void DecalData::_updateMaterial()
{
   if ( materialName.isEmpty() )
      return;

   Material *pMat = NULL;
   if ( !Sim::findObject( materialName, pMat ) )
   {
      Con::printf( "DecalData::unpackUpdate, failed to find Material of name %s!", materialName.c_str() );
      return;
   }

   material = pMat;

   // Only update material instance if we have one allocated.
   if ( matInst )
      _initMaterial();
}

Material* DecalData::getMaterial()
{
   if ( !material )
   {
      _updateMaterial();
      if ( !material )
         material = static_cast<Material*>( Sim::findObject("WarningMaterial") );
   }

   return material;
}

BaseMatInstance* DecalData::getMaterialInstance()
{
   if ( !material || !matInst || matInst->getMaterial() != material )
      _initMaterial();

   return matInst;
}

DecalData* DecalData::findDatablock( String searchName )
{
   StringTableEntry className = DecalData::getStaticClassRep()->getClassName();
   DecalData *pData;
   SimSet *set = getSet();
   SimSetIterator iter( set );

   for ( ; *iter; ++iter )
   {
      if ( (*iter)->getClassName() != className )
      {
         Con::errorf( "DecalData::findDatablock - found a class %s object in DecalDataSet!", (*iter)->getClassName() );
         continue;
      }

      pData = static_cast<DecalData*>( *iter );
      if ( pData->lookupName.equal( searchName, String::NoCase ) )
         return pData;
   }

   return NULL;
}

void DecalData::inspectPostApply()
{
	reloadRects();
}

void DecalData::reloadRects()
{
	F32 rowsBase = 0;
	F32 colsBase = 0;
	bool canRenderRowsByFrame = false;
	bool canRenderColsByFrame = false;
	S32 id = 0;

	texRect[id].point.x = 0.f;
	texRect[id].extent.x = 1.f;
	texRect[id].point.y = 0.f;
	texRect[id].extent.y = 1.f;

	texCoordCount = (texRows * texCols) - 1;

	if( texCoordCount > 16 )
	{
		Con::warnf("Coordinate max must be lower than 16 to be a valid decal !");
		texRows = 1;
		texCols = 1;
		texCoordCount = 1;
	}

	// use current datablock information in order to build a template to extract
	// coordinates from.
	if( texRows > 1 )
	{
		rowsBase = ( 1.f / texRows );
		canRenderRowsByFrame = true;
	}
	if( texCols > 1 )
	{
		colsBase = ( 1.f / texCols );
		canRenderColsByFrame = true;
	}

	// if were able, lets enter the loop
   if( frame >= 0 && (canRenderRowsByFrame || canRenderColsByFrame) )
	{
		// columns first then rows
		for ( S32 colId = 1; colId <= texCols; colId++ )
		{
			for ( S32 rowId = 1; rowId <= texRows; rowId++, id++ )
			{
				// if were over the coord count, lets go
				if(id > texCoordCount)
					return;

				// keep our dimensions correct
				if(rowId > texRows)
					rowId = 1;

				if(colId > texCols)
					colId = 1;

				// start setting our rect values per frame
				if( canRenderRowsByFrame )
				{
					texRect[id].point.x = rowsBase * ( rowId - 1 );
					texRect[id].extent.x = rowsBase;
				}

				if( canRenderColsByFrame )
				{
					texRect[id].point.y = colsBase * ( colId - 1 );
					texRect[id].extent.y = colsBase;
				}
			}
		}
	}
}

DefineEngineMethod(DecalData, postApply, void, (),,
   "Recompute the imagemap sub-texture rectangles for this DecalData.\n"
   "@tsexample\n"
   "// Inform the decal object to reload its imagemap and frame data.\n"
   "%decalData.texRows = 4;\n"
   "%decalData.postApply();\n"
   "@endtsexample\n")
{
   object->inspectPostApply();
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: commandenvironmentproxy.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: kso $ $Date: 2001-02-15 13:32:27 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

/**************************************************************************
                                TODO
 **************************************************************************

 *************************************************************************/

#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XCOMPONENT_HPP_
#include <com/sun/star/lang/XComponent.hpp>
#endif
#ifndef _COM_SUN_STAR_UCB_XCONTENTIDENTIFIERFACTORY_HPP_
#include <com/sun/star/ucb/XContentIdentifierFactory.hpp>
#endif
#ifndef _COM_SUN_STAR_UCB_XCONTENTPROVIDER_HPP_
#include <com/sun/star/ucb/XContentProvider.hpp>
#endif
#ifndef _COM_SUN_STAR_UCB_XCONTENTPROVIDERMANAGER_HPP_
#include <com/sun/star/ucb/XContentProviderManager.hpp>
#endif

#ifndef _OSL_MUTEX_HXX_
#include <osl/mutex.hxx>
#endif

#ifndef _UCBHELPER_COMMANDENVIRONMENTPROXY_HXX
#include <ucbhelper/commandenvironmentproxy.hxx>
#endif

using namespace com::sun::star::lang;
using namespace com::sun::star::task;
using namespace com::sun::star::ucb;
using namespace com::sun::star::uno;
using namespace rtl;

namespace ucb
{

//=========================================================================
//=========================================================================
//
// struct CommandEnvironmentProxy_Impl.
//
//=========================================================================
//=========================================================================

struct CommandEnvironmentProxy_Impl
{
    osl::Mutex                       m_aMutex;
    Reference< XCommandEnvironment > m_xEnv;
    Reference< XInteractionHandler > m_xInteractionHandler;
    Reference< XProgressHandler >    m_xProgressHandler;
    sal_Bool m_bGotInteractionHandler;
    sal_Bool m_bGotProgressHandler;

    CommandEnvironmentProxy_Impl(
        const Reference< XCommandEnvironment >& rxEnv )
    : m_xEnv( rxEnv ), m_bGotInteractionHandler( sal_False ),
      m_bGotProgressHandler( sal_False ) {}
};

//=========================================================================
//=========================================================================
//
// CommandEnvironmentProxy Implementation.
//
//=========================================================================
//=========================================================================

CommandEnvironmentProxy::CommandEnvironmentProxy(
                        const Reference< XCommandEnvironment >& rxEnv )
{
    m_pImpl = new CommandEnvironmentProxy_Impl( rxEnv );
}

//=========================================================================
// virtual
CommandEnvironmentProxy::~CommandEnvironmentProxy()
{
    delete m_pImpl;
}

//=========================================================================
//
// XInterface methods
//
//=========================================================================

XINTERFACE_IMPL_2( CommandEnvironmentProxy,
                   XTypeProvider,
                   XCommandEnvironment );

//=========================================================================
//
// XTypeProvider methods
//
//=========================================================================

XTYPEPROVIDER_IMPL_2( CommandEnvironmentProxy,
                      XTypeProvider,
                      XCommandEnvironment );

//=========================================================================
//
// XCommandEnvironemnt methods.
//
//=========================================================================

// virtual
Reference< XInteractionHandler > SAL_CALL
CommandEnvironmentProxy::getInteractionHandler()
    throw ( RuntimeException )
{
    if ( m_pImpl->m_xEnv.is() )
    {
        if ( !m_pImpl->m_bGotInteractionHandler )
        {
            osl::MutexGuard aGuard( m_pImpl->m_aMutex );
            if ( !m_pImpl->m_bGotInteractionHandler )
            {
                m_pImpl->m_xInteractionHandler
                                = m_pImpl->m_xEnv->getInteractionHandler();
                m_pImpl->m_bGotInteractionHandler = sal_True;
            }
        }
    }
    return m_pImpl->m_xInteractionHandler;
}

//=========================================================================
// virtual
Reference< XProgressHandler > SAL_CALL
CommandEnvironmentProxy::getProgressHandler()
    throw ( RuntimeException )
{
    if ( m_pImpl->m_xEnv.is() )
    {
        if ( !m_pImpl->m_bGotProgressHandler )
        {
            osl::MutexGuard aGuard( m_pImpl->m_aMutex );
            if ( !m_pImpl->m_bGotProgressHandler )
            {
                m_pImpl->m_xProgressHandler
                                = m_pImpl->m_xEnv->getProgressHandler();
                m_pImpl->m_bGotProgressHandler = sal_True;
            }
        }
    }
    return m_pImpl->m_xProgressHandler;
}

} /* namespace ucb */

<commit_msg>INTEGRATION: CWS ooo19126 (1.2.178); FILE MERGED 2005/09/05 13:13:55 rt 1.2.178.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: commandenvironmentproxy.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 16:36:28 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

/**************************************************************************
                                TODO
 **************************************************************************

 *************************************************************************/

#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XCOMPONENT_HPP_
#include <com/sun/star/lang/XComponent.hpp>
#endif
#ifndef _COM_SUN_STAR_UCB_XCONTENTIDENTIFIERFACTORY_HPP_
#include <com/sun/star/ucb/XContentIdentifierFactory.hpp>
#endif
#ifndef _COM_SUN_STAR_UCB_XCONTENTPROVIDER_HPP_
#include <com/sun/star/ucb/XContentProvider.hpp>
#endif
#ifndef _COM_SUN_STAR_UCB_XCONTENTPROVIDERMANAGER_HPP_
#include <com/sun/star/ucb/XContentProviderManager.hpp>
#endif

#ifndef _OSL_MUTEX_HXX_
#include <osl/mutex.hxx>
#endif

#ifndef _UCBHELPER_COMMANDENVIRONMENTPROXY_HXX
#include <ucbhelper/commandenvironmentproxy.hxx>
#endif

using namespace com::sun::star::lang;
using namespace com::sun::star::task;
using namespace com::sun::star::ucb;
using namespace com::sun::star::uno;
using namespace rtl;

namespace ucb
{

//=========================================================================
//=========================================================================
//
// struct CommandEnvironmentProxy_Impl.
//
//=========================================================================
//=========================================================================

struct CommandEnvironmentProxy_Impl
{
    osl::Mutex                       m_aMutex;
    Reference< XCommandEnvironment > m_xEnv;
    Reference< XInteractionHandler > m_xInteractionHandler;
    Reference< XProgressHandler >    m_xProgressHandler;
    sal_Bool m_bGotInteractionHandler;
    sal_Bool m_bGotProgressHandler;

    CommandEnvironmentProxy_Impl(
        const Reference< XCommandEnvironment >& rxEnv )
    : m_xEnv( rxEnv ), m_bGotInteractionHandler( sal_False ),
      m_bGotProgressHandler( sal_False ) {}
};

//=========================================================================
//=========================================================================
//
// CommandEnvironmentProxy Implementation.
//
//=========================================================================
//=========================================================================

CommandEnvironmentProxy::CommandEnvironmentProxy(
                        const Reference< XCommandEnvironment >& rxEnv )
{
    m_pImpl = new CommandEnvironmentProxy_Impl( rxEnv );
}

//=========================================================================
// virtual
CommandEnvironmentProxy::~CommandEnvironmentProxy()
{
    delete m_pImpl;
}

//=========================================================================
//
// XInterface methods
//
//=========================================================================

XINTERFACE_IMPL_2( CommandEnvironmentProxy,
                   XTypeProvider,
                   XCommandEnvironment );

//=========================================================================
//
// XTypeProvider methods
//
//=========================================================================

XTYPEPROVIDER_IMPL_2( CommandEnvironmentProxy,
                      XTypeProvider,
                      XCommandEnvironment );

//=========================================================================
//
// XCommandEnvironemnt methods.
//
//=========================================================================

// virtual
Reference< XInteractionHandler > SAL_CALL
CommandEnvironmentProxy::getInteractionHandler()
    throw ( RuntimeException )
{
    if ( m_pImpl->m_xEnv.is() )
    {
        if ( !m_pImpl->m_bGotInteractionHandler )
        {
            osl::MutexGuard aGuard( m_pImpl->m_aMutex );
            if ( !m_pImpl->m_bGotInteractionHandler )
            {
                m_pImpl->m_xInteractionHandler
                                = m_pImpl->m_xEnv->getInteractionHandler();
                m_pImpl->m_bGotInteractionHandler = sal_True;
            }
        }
    }
    return m_pImpl->m_xInteractionHandler;
}

//=========================================================================
// virtual
Reference< XProgressHandler > SAL_CALL
CommandEnvironmentProxy::getProgressHandler()
    throw ( RuntimeException )
{
    if ( m_pImpl->m_xEnv.is() )
    {
        if ( !m_pImpl->m_bGotProgressHandler )
        {
            osl::MutexGuard aGuard( m_pImpl->m_aMutex );
            if ( !m_pImpl->m_bGotProgressHandler )
            {
                m_pImpl->m_xProgressHandler
                                = m_pImpl->m_xEnv->getProgressHandler();
                m_pImpl->m_bGotProgressHandler = sal_True;
            }
        }
    }
    return m_pImpl->m_xProgressHandler;
}

} /* namespace ucb */

<|endoftext|>


<commit_before>#ifndef _DESHA1_HPP
#define _DESHA1_HPP
/*-------------------------------------------------------------------------
 * drawElements C++ Base Library
 * -----------------------------
 *
 * Copyright 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief SHA1 hash functions
 *//*--------------------------------------------------------------------*/

#include "deDefs.hpp"

#include "deSha1.h"

#include <string>
#include <vector>

namespace de
{

class Sha1
{
public:
				Sha1		(const deSha1& hash) : m_hash(hash) {}

	static Sha1	parse		(const std::string& str);
	static Sha1	compute		(size_t size, const void* data);

	bool		operator==	(const Sha1& other) const { return deSha1_equal(&m_hash, &other.m_hash); }
	bool		operator!=	(const Sha1& other) const { return !(*this == other); }

private:
	deSha1		m_hash;
};

class Sha1Stream
{
public:
					Sha1Stream	(void);
	void			process		(size_t size, const void* data);
	Sha1			finalize	(void);

private:
	deSha1Stream	m_stream;
};

// Utility functions for building hash from values.
// \note This is not same as serializing the values and computing hash from the data.
//       Some extra care is required when dealing with types that have platform
//       specific size.
//       All vectors and strings will include their size in the hash. Following codes
//       produce different results:
//           stream << "Hi" << "Hello";
//       and
//           stream << "HiHello";

inline Sha1Stream& operator<< (Sha1Stream& stream, bool b)
{
	const deUint8 value = b ? 1 : 0;
	stream.process(sizeof(value), &value);
	return stream;
}

inline Sha1Stream& operator<< (Sha1Stream& stream, deUint32 value)
{
	const deUint8 data[] =
	{
		(deUint8)(0xFFu & (value >> 24)),
		(deUint8)(0xFFu & (value >> 16)),
		(deUint8)(0xFFu & (value >> 8)),
		(deUint8)(0xFFu & (value >> 0))
	};

	stream.process(sizeof(data), data);
	return stream;
}

inline Sha1Stream& operator<< (Sha1Stream& stream, deInt32 value)
{
	return stream << (deUint32)value;
}

inline Sha1Stream& operator<< (Sha1Stream& stream, deUint64 value)
{
	const deUint8 data[] =
	{
		(deUint8)(0xFFull & (value >> 56)),
		(deUint8)(0xFFull & (value >> 48)),
		(deUint8)(0xFFull & (value >> 40)),
		(deUint8)(0xFFull & (value >> 32)),
		(deUint8)(0xFFull & (value >> 24)),
		(deUint8)(0xFFull & (value >> 16)),
		(deUint8)(0xFFull & (value >> 8)),
		(deUint8)(0xFFull & (value >> 0))
	};

	stream.process(sizeof(data), data);
	return stream;
}

inline Sha1Stream& operator<< (Sha1Stream& stream, deInt64 value)
{
	return stream << (deUint64)value;
}

template<typename T>
inline Sha1Stream& operator<< (Sha1Stream& stream, const std::vector<T>& values)
{
	stream << (deUint64)values.size();

	for (size_t ndx = 0; ndx < values.size(); ndx++)
		stream << values[ndx];

	return stream;
}

inline Sha1Stream& operator<< (Sha1Stream& stream, const std::string& str)
{
	stream << (deUint64)str.size();
	stream.process(str.size(), str.c_str());
	return stream;
}

} // de

#endif // _DESHA1_HPP
<commit_msg>Fix warning<commit_after>#ifndef _DESHA1_HPP
#define _DESHA1_HPP
/*-------------------------------------------------------------------------
 * drawElements C++ Base Library
 * -----------------------------
 *
 * Copyright 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief SHA1 hash functions
 *//*--------------------------------------------------------------------*/

#include "deDefs.hpp"

#include "deSha1.h"

#include <string>
#include <vector>

namespace de
{

class Sha1
{
public:
				Sha1		(const deSha1& hash) : m_hash(hash) {}

	static Sha1	parse		(const std::string& str);
	static Sha1	compute		(size_t size, const void* data);

	bool		operator==	(const Sha1& other) const { return deSha1_equal(&m_hash, &other.m_hash) == DE_TRUE; }
	bool		operator!=	(const Sha1& other) const { return !(*this == other); }

private:
	deSha1		m_hash;
};

class Sha1Stream
{
public:
					Sha1Stream	(void);
	void			process		(size_t size, const void* data);
	Sha1			finalize	(void);

private:
	deSha1Stream	m_stream;
};

// Utility functions for building hash from values.
// \note This is not same as serializing the values and computing hash from the data.
//       Some extra care is required when dealing with types that have platform
//       specific size.
//       All vectors and strings will include their size in the hash. Following codes
//       produce different results:
//           stream << "Hi" << "Hello";
//       and
//           stream << "HiHello";

inline Sha1Stream& operator<< (Sha1Stream& stream, bool b)
{
	const deUint8 value = b ? 1 : 0;
	stream.process(sizeof(value), &value);
	return stream;
}

inline Sha1Stream& operator<< (Sha1Stream& stream, deUint32 value)
{
	const deUint8 data[] =
	{
		(deUint8)(0xFFu & (value >> 24)),
		(deUint8)(0xFFu & (value >> 16)),
		(deUint8)(0xFFu & (value >> 8)),
		(deUint8)(0xFFu & (value >> 0))
	};

	stream.process(sizeof(data), data);
	return stream;
}

inline Sha1Stream& operator<< (Sha1Stream& stream, deInt32 value)
{
	return stream << (deUint32)value;
}

inline Sha1Stream& operator<< (Sha1Stream& stream, deUint64 value)
{
	const deUint8 data[] =
	{
		(deUint8)(0xFFull & (value >> 56)),
		(deUint8)(0xFFull & (value >> 48)),
		(deUint8)(0xFFull & (value >> 40)),
		(deUint8)(0xFFull & (value >> 32)),
		(deUint8)(0xFFull & (value >> 24)),
		(deUint8)(0xFFull & (value >> 16)),
		(deUint8)(0xFFull & (value >> 8)),
		(deUint8)(0xFFull & (value >> 0))
	};

	stream.process(sizeof(data), data);
	return stream;
}

inline Sha1Stream& operator<< (Sha1Stream& stream, deInt64 value)
{
	return stream << (deUint64)value;
}

template<typename T>
inline Sha1Stream& operator<< (Sha1Stream& stream, const std::vector<T>& values)
{
	stream << (deUint64)values.size();

	for (size_t ndx = 0; ndx < values.size(); ndx++)
		stream << values[ndx];

	return stream;
}

inline Sha1Stream& operator<< (Sha1Stream& stream, const std::string& str)
{
	stream << (deUint64)str.size();
	stream.process(str.size(), str.c_str());
	return stream;
}

} // de

#endif // _DESHA1_HPP
<|endoftext|>


<commit_before>/*
 * linker32.cpp
 *
 *  Created on: Jul 23, 2014
 *      Author: Pimenta
 */

#include <cstdint>
#include <cstring>
#include <cstdio>
#include <fstream>
#include <set>
#include <map>
#include <string>

using namespace std;

typedef uint32_t uword_t;

#ifndef MEM_WORDS
#define MEM_WORDS 0x2000
#endif

#ifndef WORD_WIDTH
#define WORD_WIDTH 32
#endif

struct ObjectFile32 {
    uword_t offset;
    map<string, uword_t> exported;
    map<string, set<uword_t>> imported;
    set<uword_t> relative;
    uword_t mem_size;
    uword_t* mem;

    ~ObjectFile32() {
      delete[] mem;
    }

    void setStarter() {
      offset = 0;
      imported["start"].emplace(3);
      relative.emplace(1);
      relative.emplace(2);
      relative.emplace(3);
      mem_size = 4;
      mem = new uword_t[4];
      mem[0] = 0;
      mem[1] = 0;
      mem[2] = 0;
      mem[3] = 0;
    }

    void read(const char* fn, uword_t offs) {
      offset = offs;

      fstream f(fn, fstream::in | fstream::binary);

      uword_t tmp;

      // read number of exported symbols
      f.read((char*)&tmp, sizeof(uword_t));

      // read exported symbols
      for (uword_t i = 0; i < tmp; ++i) {
        string sym;
        uword_t addr;

        // string
        {
          char c;
          f.read(&c, sizeof(char));
          while (c != '\0') {
            sym += c;
            f.read(&c, sizeof(char));
          }
        }

        // address
        f.read((char*)&addr, sizeof(uword_t));

        exported[sym] = addr;
      }

      // read number of symbols of pending references
      f.read((char*)&tmp, sizeof(uword_t));

      // read symbols of pending references
      for (uword_t i = 0; i < tmp; ++i) {
        string sym;

        // string
        {
          char c;
          f.read(&c, sizeof(char));
          while (c != '\0') {
            sym += c;
            f.read(&c, sizeof(char));
          }
        }

        uword_t tmp2;

        // read number of references to current symbol
        f.read((char*)&tmp2, sizeof(uword_t));

        // read references to current symbol
        for (uword_t j = 0; j < tmp2; ++j) {
          uword_t addr;
          f.read((char*)&addr, sizeof(uword_t));
          imported[sym].emplace(addr);
        }
      }

      // read number of relative addresses
      f.read((char*)&tmp, sizeof(uword_t));

      // read relative addresses
      for (uword_t i = 0; i < tmp; ++i) {
        uword_t addr;
        f.read((char*)&addr, sizeof(uword_t));
        relative.emplace(addr);
      }

      // read assembled code size
      f.read((char*)&mem_size, sizeof(uword_t));

      // read assembled code
      mem = new uword_t[mem_size];
      f.read((char*)mem, sizeof(uword_t)*mem_size);

      f.close();
    }
};

int linker32(int argc, char* argv[]) {
  if (argc < 3) {
    fprintf(stderr, "Usage mode: subleq-ld <object_files...> <meminit_file>\n");
    return 0;
  }

  bool executable = string(argv[1]) == "-exec";

  // read object files
  ObjectFile32 files[argc - 2];
  if (executable) {
    files[0].setStarter();
  }
  else {
    files[0].read(argv[1], 0);
  }
  for (int i = 1; i < argc - 2; ++i) {
    files[i].read(argv[i + 1], files[i - 1].offset + files[i - 1].mem_size);
  }

  uword_t mem_size = 0;
  uword_t* mem = new uword_t[MEM_WORDS];
  map<string, uword_t> symbols;
  map<string, set<uword_t>> references;
  set<uword_t> relatives;

  for (auto& file : files) {
    // assemble global symbol table
    for (auto& sym : file.exported) {
      symbols[sym.first] = sym.second + file.offset;
    }

    // assemble global reference table
    for (auto& sym : file.imported) {
      set<uword_t>& refs = references[sym.first];
      for (auto addr : sym.second) {
        refs.emplace(addr + file.offset);
      }
    }

    // assemble global relative address table
    for (auto addr : file.relative) {
      relatives.emplace(addr + file.offset);
      file.mem[addr] += file.offset; // relocating
    }

    // copy object code
    memcpy(&mem[mem_size], file.mem, file.mem_size*sizeof(uword_t));
    mem_size += file.mem_size;
  }

  // solve references
  for (auto ref = references.begin(); ref != references.end();) {
    auto sym = symbols.find(ref->first);
    if (sym == symbols.end()) {
      ref++;
    }
    else {
      for (auto addr : ref->second) {
        mem[addr] = sym->second;
      }
      references.erase(ref++);
    }
  }

  // output
  fstream f(argv[argc - 1], fstream::out | fstream::binary);
  uword_t tmp;

  // write number of exported symbols
  tmp = symbols.size();
  f.write((const char*)&tmp, sizeof(uword_t));

  // write exported symbols
  for (auto& sym : symbols) {
    // string
    f.write(sym.first.c_str(), sym.first.size() + 1);

    // address
    tmp = sym.second;
    f.write((const char*)&tmp, sizeof(uword_t));
  }

  // write number of symbols of pending references
  tmp = references.size();
  f.write((const char*)&tmp, sizeof(uword_t));

  // write symbols of pending references
  for (auto& sym : references) {
    // string
    f.write(sym.first.c_str(), sym.first.size() + 1);

    // write number of references to current symbol
    tmp = sym.second.size();
    f.write((const char*)&tmp, sizeof(uword_t));

    // write references to current symbol
    for (auto ref : sym.second) {
      tmp = ref;
      f.write((const char*)&tmp, sizeof(uword_t));
    }
  }

  // write number of relative addresses
  tmp = relatives.size();
  f.write((const char*)&tmp, sizeof(uword_t));

  // write relative addresses
  for (auto addr : relatives) {
    tmp = addr;
    f.write((const char*)&tmp, sizeof(uword_t));
  }

  // write assembled code size
  f.write((const char*)&mem_size, sizeof(uword_t));

  // write assembled code
  f.write((const char*)mem, sizeof(uword_t)*mem_size);

  f.close();

  // output mif
  f.open((string(argv[argc - 1]) + ".mif").c_str(), fstream::out);
  char buf[20];
  f << "DEPTH = " << MEM_WORDS << ";\n";
  f << "WIDTH = " << WORD_WIDTH << ";\n";
  f << "ADDRESS_RADIX = HEX;\n";
  f << "DATA_RADIX = HEX;\n";
  f << "CONTENT\n";
  f << "BEGIN\n";
  f << "\n";
  for (uword_t i = 0; i < mem_size; ++i) {
    sprintf(buf, "%08x", i);
    f << buf;
    sprintf(buf, "%08x", mem[i]);
    f << " : " << buf << ";\n";
  }
  f << "\n";
  f << "END;\n";
  f.close();

  delete[] mem;

  return 0;
}
<commit_msg>Fixing bug<commit_after>/*
 * linker32.cpp
 *
 *  Created on: Jul 23, 2014
 *      Author: Pimenta
 */

#include <cstdint>
#include <cstring>
#include <cstdio>
#include <fstream>
#include <set>
#include <map>
#include <string>

using namespace std;

typedef uint32_t uword_t;

#ifndef MEM_WORDS
#define MEM_WORDS 0x2000
#endif

#ifndef WORD_WIDTH
#define WORD_WIDTH 32
#endif

struct ObjectFile32 {
    uword_t offset;
    map<string, uword_t> exported;
    map<string, set<uword_t>> imported;
    set<uword_t> relative;
    uword_t mem_size;
    uword_t* mem;

    ~ObjectFile32() {
      delete[] mem;
    }

    void setStarter() {
      offset = 0;
      imported["start"].emplace(2);
      relative.emplace(0);
      relative.emplace(1);
      relative.emplace(2);
      mem_size = 4;
      mem = new uword_t[4];
      mem[0] = 3;
      mem[1] = 3;
      mem[2] = 0;
      mem[3] = 0;
    }

    void read(const char* fn, uword_t offs) {
      offset = offs;

      fstream f(fn, fstream::in | fstream::binary);

      uword_t tmp;

      // read number of exported symbols
      f.read((char*)&tmp, sizeof(uword_t));

      // read exported symbols
      for (uword_t i = 0; i < tmp; ++i) {
        string sym;
        uword_t addr;

        // string
        {
          char c;
          f.read(&c, sizeof(char));
          while (c != '\0') {
            sym += c;
            f.read(&c, sizeof(char));
          }
        }

        // address
        f.read((char*)&addr, sizeof(uword_t));

        exported[sym] = addr;
      }

      // read number of symbols of pending references
      f.read((char*)&tmp, sizeof(uword_t));

      // read symbols of pending references
      for (uword_t i = 0; i < tmp; ++i) {
        string sym;

        // string
        {
          char c;
          f.read(&c, sizeof(char));
          while (c != '\0') {
            sym += c;
            f.read(&c, sizeof(char));
          }
        }

        uword_t tmp2;

        // read number of references to current symbol
        f.read((char*)&tmp2, sizeof(uword_t));

        // read references to current symbol
        for (uword_t j = 0; j < tmp2; ++j) {
          uword_t addr;
          f.read((char*)&addr, sizeof(uword_t));
          imported[sym].emplace(addr);
        }
      }

      // read number of relative addresses
      f.read((char*)&tmp, sizeof(uword_t));

      // read relative addresses
      for (uword_t i = 0; i < tmp; ++i) {
        uword_t addr;
        f.read((char*)&addr, sizeof(uword_t));
        relative.emplace(addr);
      }

      // read assembled code size
      f.read((char*)&mem_size, sizeof(uword_t));

      // read assembled code
      mem = new uword_t[mem_size];
      f.read((char*)mem, sizeof(uword_t)*mem_size);

      f.close();
    }
};

int linker32(int argc, char* argv[]) {
  if (argc < 3) {
    fprintf(stderr, "Usage mode: subleq-ld <object_files...> <meminit_file>\n");
    return 0;
  }

  bool executable = string(argv[1]) == "-exec";

  // read object files
  ObjectFile32 files[argc - 2];
  if (executable) {
    files[0].setStarter();
  }
  else {
    files[0].read(argv[1], 0);
  }
  for (int i = 1; i < argc - 2; ++i) {
    files[i].read(argv[i + 1], files[i - 1].offset + files[i - 1].mem_size);
  }

  uword_t mem_size = 0;
  uword_t* mem = new uword_t[MEM_WORDS];
  map<string, uword_t> symbols;
  map<string, set<uword_t>> references;
  set<uword_t> relatives;

  for (auto& file : files) {
    // assemble global symbol table
    for (auto& sym : file.exported) {
      symbols[sym.first] = sym.second + file.offset;
    }

    // assemble global reference table
    for (auto& sym : file.imported) {
      set<uword_t>& refs = references[sym.first];
      for (auto addr : sym.second) {
        refs.emplace(addr + file.offset);
      }
    }

    // assemble global relative address table
    for (auto addr : file.relative) {
      relatives.emplace(addr + file.offset);
      file.mem[addr] += file.offset; // relocating
    }

    // copy object code
    memcpy(&mem[mem_size], file.mem, file.mem_size*sizeof(uword_t));
    mem_size += file.mem_size;
  }

  // solve references
  for (auto ref = references.begin(); ref != references.end();) {
    auto sym = symbols.find(ref->first);
    if (sym == symbols.end()) {
      ref++;
    }
    else {
      for (auto addr : ref->second) {
        mem[addr] = sym->second;
      }
      references.erase(ref++);
    }
  }

  // output
  fstream f(argv[argc - 1], fstream::out | fstream::binary);
  uword_t tmp;

  // write number of exported symbols
  tmp = symbols.size();
  f.write((const char*)&tmp, sizeof(uword_t));

  // write exported symbols
  for (auto& sym : symbols) {
    // string
    f.write(sym.first.c_str(), sym.first.size() + 1);

    // address
    tmp = sym.second;
    f.write((const char*)&tmp, sizeof(uword_t));
  }

  // write number of symbols of pending references
  tmp = references.size();
  f.write((const char*)&tmp, sizeof(uword_t));

  // write symbols of pending references
  for (auto& sym : references) {
    // string
    f.write(sym.first.c_str(), sym.first.size() + 1);

    // write number of references to current symbol
    tmp = sym.second.size();
    f.write((const char*)&tmp, sizeof(uword_t));

    // write references to current symbol
    for (auto ref : sym.second) {
      tmp = ref;
      f.write((const char*)&tmp, sizeof(uword_t));
    }
  }

  // write number of relative addresses
  tmp = relatives.size();
  f.write((const char*)&tmp, sizeof(uword_t));

  // write relative addresses
  for (auto addr : relatives) {
    tmp = addr;
    f.write((const char*)&tmp, sizeof(uword_t));
  }

  // write assembled code size
  f.write((const char*)&mem_size, sizeof(uword_t));

  // write assembled code
  f.write((const char*)mem, sizeof(uword_t)*mem_size);

  f.close();

  // output mif
  f.open((string(argv[argc - 1]) + ".mif").c_str(), fstream::out);
  char buf[20];
  f << "DEPTH = " << MEM_WORDS << ";\n";
  f << "WIDTH = " << WORD_WIDTH << ";\n";
  f << "ADDRESS_RADIX = HEX;\n";
  f << "DATA_RADIX = HEX;\n";
  f << "CONTENT\n";
  f << "BEGIN\n";
  f << "\n";
  for (uword_t i = 0; i < mem_size; ++i) {
    sprintf(buf, "%08x", i);
    f << buf;
    sprintf(buf, "%08x", mem[i]);
    f << " : " << buf << ";\n";
  }
  f << "\n";
  f << "END;\n";
  f.close();

  delete[] mem;

  return 0;
}
<|endoftext|>


<commit_before>/****************************************************************/
/*               DO NOT MODIFY THIS HEADER                      */
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*           (c) 2010 Battelle Energy Alliance, LLC             */
/*                   ALL RIGHTS RESERVED                        */
/*                                                              */
/*          Prepared by Battelle Energy Alliance, LLC           */
/*            Under Contract No. DE-AC07-05ID14517              */
/*            With the U. S. Department of Energy               */
/*                                                              */
/*            See COPYRIGHT for full restrictions               */
/****************************************************************/

#include "MeshExtruder.h"
#include "Moose.h"
#include "Parser.h"
#include "InputParameters.h"

// libMesh includes
#include "mesh.h"
#include "boundary_info.h"
#include "elem.h"
#include "cell_prism6.h"
#include "cell_hex8.h"
#include "node.h"

// Static Initialization
const unsigned int MeshExtruder::Quad4_to_Hex8_side_map[4] = {1,2,3,4};
const unsigned int MeshExtruder::Tri3_to_Prism6_side_map[3] = {1,2,3};

template<>
InputParameters validParams<MeshExtruder>()
{
  InputParameters params = validParams<MooseMesh>();

  params.addRequiredParam<std::string>("file", "The 2D Mesh file to extrude");
  params.addRequiredParam<unsigned int>("num_layers", "The number of layers in the extruded mesh");
  params.addRequiredParam<Real>("height", "The height of the Mesh");
  params.addRequiredParam<unsigned int>("extrusion_axis", "The axis that the mesh will be extruded upon");
  params.addParam<std::vector<unsigned int> >("bottom_sidesets", "A list of boundaries that will be applied to the bottom of the extruded mesh");
  params.addParam<std::vector<unsigned int> >("top_sidesets", "A list of boundaries that will be applied to the top of the extruded mesh");
  return params;
}

MeshExtruder::MeshExtruder(const std::string & name, InputParameters parameters):
    MooseMesh(name, parameters),
    _num_layers(getParam<unsigned int>("num_layers")),
    _height(getParam<Real>("height")),
    _extrusion_axis(getParam<unsigned int>("extrusion_axis"))
{
  // Read in the 2D Mesh
  _src_mesh.read(getParam<std::string>("file"));

  _src_mesh.prepare_for_use();

  extrude(_mesh);
}

void
MeshExtruder::extrude(libMesh::MeshBase &dest_mesh)
{
  const Real layer_ht = _height/_num_layers;

  MeshBase::const_node_iterator nd_end = _src_mesh.local_nodes_end();
  MeshBase::const_element_iterator el_end = _src_mesh.local_elements_end();

  unsigned int n_local_nodes = _src_mesh.n_local_nodes();
  mooseAssert(_src_mesh.mesh_dimension() == 2, "Can only extrude 2D meshes (right now)");
  dest_mesh.set_mesh_dimension(_src_mesh.mesh_dimension()+1);
  for (unsigned int layer_n = 0; layer_n <= _num_layers; ++layer_n)
  {
    // Add the extruded nodes to the new mesh
    MeshBase::const_node_iterator nd     = _src_mesh.local_nodes_begin();

    for ( ; nd != nd_end; ++nd)
    {
      Node *new_node = new Node(**nd);

      new_node->set_id(new_node->id() + layer_n * n_local_nodes);

      // Update the extruded coordinate
      (*new_node)(_extrusion_axis) = (*new_node)(_extrusion_axis) + layer_n * layer_ht;

      dest_mesh.add_node(new_node);
    }
  }

  for (unsigned int layer_n = 0; layer_n <= _num_layers; ++layer_n)
  {
    // Add the extruded elements to the new mesh
    MeshBase::const_element_iterator el = _src_mesh.local_elements_begin();

    // We have one less layer of elements than layers of nodes
    if (layer_n < _num_layers)
    {
      for ( ; el != el_end; ++el)
      {
        Elem *elem;
        unsigned int top_side_num;
        switch ((*el)->type())
        {
        case QUAD4:
          elem = dest_mesh.add_elem(new Hex8);
          elem->subdomain_id() = (*el)->subdomain_id();
          top_side_num = 5;

          // The first four nodes are on the current level
          for (unsigned int node_num = 0; node_num < 4; node_num++)
          {
            unsigned int dest_node_id = (*el)->get_node(node_num)->id() + layer_n * n_local_nodes;
            elem->set_node(node_num) = dest_mesh.node_ptr(dest_node_id);
          }
          // The next four nodes are on the next level
          for (unsigned int node_num = 4; node_num < 8; node_num++)
          {
            unsigned int dest_node_id = (*el)->get_node(node_num-4)->id() + (layer_n+1) * n_local_nodes;
            elem->set_node(node_num) = dest_mesh.node_ptr(dest_node_id);
          }

          // Propogate sides
          for (short int side = 0; side < 4; ++side)
          {
            std::vector<short int> boundary_ids = _src_mesh.boundary_info->boundary_ids(*el, side);

            if (!boundary_ids.empty())
              dest_mesh.boundary_info->add_side(elem, Quad4_to_Hex8_side_map[side], boundary_ids);
          }
          break;
        case TRI3:
          elem = dest_mesh.add_elem(new Prism6);
          elem->subdomain_id() = (*el)->subdomain_id();
          top_side_num = 4;

          // The first thre nodes are on the current level
          for (unsigned int node_num = 0; node_num < 3; node_num++)
          {
            unsigned int dest_node_id = (*el)->get_node(node_num)->id() + layer_n * n_local_nodes;
            elem->set_node(node_num) = dest_mesh.node_ptr(dest_node_id);
          }
          // The next three nodes are on the next level
          for (unsigned int node_num = 3; node_num < 6; node_num++)
          {
            unsigned int dest_node_id = (*el)->get_node(node_num-3)->id() + (layer_n+1) * n_local_nodes;
            elem->set_node(node_num) = dest_mesh.node_ptr(dest_node_id);
          }

          // Propogate sides
          for (short int side = 0; side < 4; ++side)
          {
            std::vector<short int> boundary_ids = _src_mesh.boundary_info->boundary_ids(*el, side);

            if (!boundary_ids.empty())
              dest_mesh.boundary_info->add_side(elem, Tri3_to_Prism6_side_map[side], boundary_ids);
          }
          break;
        default:
          std::cout << ((*el)->type());

          mooseError("Element type not setup");
        }

        // bottom sidesets
        if (layer_n == 0 && isParamValid("bottom_sidesets"))
        {
          std::vector<unsigned int> boundaries = getParam<std::vector<unsigned int> >("bottom_sidesets");
          for (std::vector<unsigned int>::const_iterator iter=boundaries.begin(); iter!=boundaries.end(); ++iter)
            dest_mesh.boundary_info->add_side(elem, 0, *iter);
        }
        // top sidesets
        else if (layer_n == _num_layers-1 && isParamValid("top_sidesets"))
        {
          std::vector<unsigned int> boundaries = getParam<std::vector<unsigned int> >("top_sidesets");
          for (std::vector<unsigned int>::const_iterator iter=boundaries.begin(); iter!=boundaries.end(); ++iter)
            dest_mesh.boundary_info->add_side(elem, top_side_num, *iter);
        }
      }
    }
  }
}
<commit_msg>Mesh Extruder Fixes in parallel, small parallel mesh fix in Pronghorn - Refs #749<commit_after>/****************************************************************/
/*               DO NOT MODIFY THIS HEADER                      */
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*           (c) 2010 Battelle Energy Alliance, LLC             */
/*                   ALL RIGHTS RESERVED                        */
/*                                                              */
/*          Prepared by Battelle Energy Alliance, LLC           */
/*            Under Contract No. DE-AC07-05ID14517              */
/*            With the U. S. Department of Energy               */
/*                                                              */
/*            See COPYRIGHT for full restrictions               */
/****************************************************************/

#include "MeshExtruder.h"
#include "Moose.h"
#include "Parser.h"
#include "InputParameters.h"

// libMesh includes
#include "mesh.h"
#include "boundary_info.h"
#include "elem.h"
#include "cell_prism6.h"
#include "cell_hex8.h"
#include "node.h"

// Static Initialization
const unsigned int MeshExtruder::Quad4_to_Hex8_side_map[4] = {1,2,3,4};
const unsigned int MeshExtruder::Tri3_to_Prism6_side_map[3] = {1,2,3};

template<>
InputParameters validParams<MeshExtruder>()
{
  InputParameters params = validParams<MooseMesh>();

  params.addRequiredParam<std::string>("file", "The 2D Mesh file to extrude");
  params.addRequiredParam<unsigned int>("num_layers", "The number of layers in the extruded mesh");
  params.addRequiredParam<Real>("height", "The height of the Mesh");
  params.addRequiredParam<unsigned int>("extrusion_axis", "The axis that the mesh will be extruded upon");
  params.addParam<std::vector<unsigned int> >("bottom_sidesets", "A list of boundaries that will be applied to the bottom of the extruded mesh");
  params.addParam<std::vector<unsigned int> >("top_sidesets", "A list of boundaries that will be applied to the top of the extruded mesh");
  return params;
}

MeshExtruder::MeshExtruder(const std::string & name, InputParameters parameters):
    MooseMesh(name, parameters),
    _num_layers(getParam<unsigned int>("num_layers")),
    _height(getParam<Real>("height")),
    _extrusion_axis(getParam<unsigned int>("extrusion_axis"))
{
  // Read in the 2D Mesh
  _src_mesh.read(getParam<std::string>("file"));

  _src_mesh.prepare_for_use();

  extrude(_mesh);
}

void
MeshExtruder::extrude(libMesh::MeshBase &dest_mesh)
{
  const Real layer_ht = _height/_num_layers;

  MeshBase::const_node_iterator nd_end = _src_mesh.active_nodes_end();
  MeshBase::const_element_iterator el_end = _src_mesh.active_elements_end();

  unsigned int n_active_nodes = _src_mesh.n_nodes();
  mooseAssert(_src_mesh.mesh_dimension() == 2, "Can only extrude 2D meshes (right now)");
  dest_mesh.set_mesh_dimension(_src_mesh.mesh_dimension()+1);
  for (unsigned int layer_n = 0; layer_n <= _num_layers; ++layer_n)
  {
    // Add the extruded nodes to the new mesh
    MeshBase::const_node_iterator nd     = _src_mesh.active_nodes_begin();

    for ( ; nd != nd_end; ++nd)
    {
      Node *new_node = new Node(**nd);

      new_node->set_id((*nd)->id() + layer_n * n_active_nodes);

      // Update the extruded coordinate
      (*new_node)(_extrusion_axis) = (*new_node)(_extrusion_axis) + layer_n * layer_ht;

      dest_mesh.add_node(new_node);
    }
  }

  for (unsigned int layer_n = 0; layer_n <= _num_layers; ++layer_n)
  {
    // Add the extruded elements to the new mesh
    MeshBase::const_element_iterator el = _src_mesh.active_elements_begin();

    // We have one less layer of elements than layers of nodes
    if (layer_n < _num_layers)
    {
      for ( ; el != el_end; ++el)
      {
        Elem *elem;
        unsigned int top_side_num;
        switch ((*el)->type())
        {
        case QUAD4:
          elem = dest_mesh.add_elem(new Hex8);
          elem->subdomain_id() = (*el)->subdomain_id();
          top_side_num = 5;

          // The first four nodes are on the current level
          for (unsigned int node_num = 0; node_num < 4; node_num++)
          {
            unsigned int dest_node_id = (*el)->get_node(node_num)->id() + layer_n * n_active_nodes;
            elem->set_node(node_num) = dest_mesh.node_ptr(dest_node_id);
          }
          // The next four nodes are on the next level
          for (unsigned int node_num = 4; node_num < 8; node_num++)
          {
            unsigned int dest_node_id = (*el)->get_node(node_num-4)->id() + (layer_n+1) * n_active_nodes;
            elem->set_node(node_num) = dest_mesh.node_ptr(dest_node_id);
          }

          // Propogate sides
          for (short int side = 0; side < 4; ++side)
          {
            std::vector<short int> boundary_ids = _src_mesh.boundary_info->boundary_ids(*el, side);

            if (!boundary_ids.empty())
              dest_mesh.boundary_info->add_side(elem, Quad4_to_Hex8_side_map[side], boundary_ids);
          }
          break;
        case TRI3:
          elem = dest_mesh.add_elem(new Prism6);
          elem->subdomain_id() = (*el)->subdomain_id();
          top_side_num = 4;

          // The first thre nodes are on the current level
          for (unsigned int node_num = 0; node_num < 3; node_num++)
          {
            unsigned int dest_node_id = (*el)->get_node(node_num)->id() + layer_n * n_active_nodes;
            elem->set_node(node_num) = dest_mesh.node_ptr(dest_node_id);
          }
          // The next three nodes are on the next level
          for (unsigned int node_num = 3; node_num < 6; node_num++)
          {
            unsigned int dest_node_id = (*el)->get_node(node_num-3)->id() + (layer_n+1) * n_active_nodes;
            elem->set_node(node_num) = dest_mesh.node_ptr(dest_node_id);
          }

          // Propogate sides
          for (short int side = 0; side < 4; ++side)
          {
            std::vector<short int> boundary_ids = _src_mesh.boundary_info->boundary_ids(*el, side);

            if (!boundary_ids.empty())
              dest_mesh.boundary_info->add_side(elem, Tri3_to_Prism6_side_map[side], boundary_ids);
          }
          break;
        default:
          std::cout << ((*el)->type());

          mooseError("Element type not setup");
        }

        // bottom sidesets
        if (layer_n == 0 && isParamValid("bottom_sidesets"))
        {
          std::vector<unsigned int> boundaries = getParam<std::vector<unsigned int> >("bottom_sidesets");
          for (std::vector<unsigned int>::const_iterator iter=boundaries.begin(); iter!=boundaries.end(); ++iter)
            dest_mesh.boundary_info->add_side(elem, 0, *iter);
        }
        // top sidesets
        else if (layer_n == _num_layers-1 && isParamValid("top_sidesets"))
        {
          std::vector<unsigned int> boundaries = getParam<std::vector<unsigned int> >("top_sidesets");
          for (std::vector<unsigned int>::const_iterator iter=boundaries.begin(); iter!=boundaries.end(); ++iter)
            dest_mesh.boundary_info->add_side(elem, top_side_num, *iter);
        }
      }
    }
  }
}
<|endoftext|>


<commit_before>#include "dataset_iterator.hpp"

#include <stack>
#include <algorithm>

#include "data/attribute/constants.hpp"

namespace dicom
{

namespace data
{

namespace dataset
{

using namespace attribute;
using namespace data::dictionary;

dataset_iterator::dataset_iterator(typename std::map<attribute::tag_type, attribute::elementfield>::iterator it):
   cit {it},
   delimiter {it},
   dictionary {get_default_dictionaries()}
{
   nested_set_sizes.push({0, 0});
}

dataset_iterator dataset_iterator::operator++()
{
   return next();
}

dataset_iterator dataset_iterator::operator++(int)
{
   dataset_iterator ret = cit;
   cit = next();
   return ret;
}

dataset_iterator dataset_iterator::operator--()
{
   return previous();
}

dataset_iterator dataset_iterator::operator--(int)
{
   dataset_iterator ret = cit;
   cit = previous();
   return ret;
}

std::pair<attribute::tag_type, attribute::elementfield>
dataset_iterator::operator*() const
{
   return *cit;
}

std::pair<const attribute::tag_type, attribute::elementfield> const*
dataset_iterator::operator->() const
{
   return &*cit;
}

bool operator==(const dataset_iterator& lhs, const dataset_iterator& rhs)
{
   return lhs.cit == rhs.cit;
}

bool operator!=(const dataset_iterator& lhs, const dataset_iterator& rhs)
{
   return !(lhs == rhs);
}

std::map<attribute::tag_type, attribute::elementfield>::iterator
dataset_iterator::step_into_nested(std::map<attribute::tag_type, attribute::elementfield>::iterator curr)
{
   parent_its.push(curr); // save current position of the iterator
   nested_set_sizes.push({0, curr->second.value_len});
   std::vector<dataset_type> nested_set;
   get_value_field<VR::SQ>(curr->second, nested_set);

   nested_set.erase(std::remove_if(nested_set.begin(), nested_set.end(),
                                   [](const dataset_type& set) { return set.empty(); }),
                    nested_set.end());

   nested_sets.push(nested_set);
   items.push({0, nested_sets.top().size()});
   if (nested_set.size() == 0 || /* empty set*/ nested_set[0].size() == 0) {
      return step_outof_nested();
   } else {
      curr = nested_sets.top().begin()->begin();
      return curr;
   }
}

std::map<attribute::tag_type, attribute::elementfield>::iterator dataset_iterator::step_outof_nested()
{
   auto last = parent_its.top();
   parent_its.pop();
   nested_sets.pop();
   items.pop();
   nested_set_sizes.pop();
   return ++last;
}

std::map<attribute::tag_type, attribute::elementfield>::iterator
dataset_iterator::step_backw_into_nested(std::map<attribute::tag_type, attribute::elementfield>::iterator prev)
{
   bool explicitlength = true;
   parent_its.push(prev);
   nested_set_sizes.push({prev->second.value_len, prev->second.value_len});
   if (nested_set_sizes.top().curr_nestedset_max != 0xffff) {
      nested_set_sizes.top().curr_nestedset_size = nested_set_sizes.top().curr_nestedset_max;
   } else {
      explicitlength = false;
   }
   std::vector<dataset_type> nested_set;
   get_value_field<VR::SQ>(prev->second, nested_set);
   nested_sets.push(nested_set);
   items.push({nested_sets.size()-1, nested_sets.size()});
   auto curr = --nested_sets.top()[items.top().nested_items_max-1].end();
   return explicitlength ? curr : --curr;
}

std::map<attribute::tag_type, attribute::elementfield>::iterator dataset_iterator::step_backw_outof_nested()
{
   auto last = parent_its.top();
   parent_its.pop();
   nested_sets.pop();
   items.pop();
   nested_set_sizes.pop();
   return last;
}

std::map<attribute::tag_type, attribute::elementfield>::iterator dataset_iterator::next()
{
   // accumulate the size of the nested set's elements if a sequence size was
   // explicitly specified
   if (nested_set_sizes.top().curr_nestedset_max != 0xffff
       && cit->first != Item
       && cit->first != ItemDelimitationItem
       && cit->first != SequenceDelimitationItem) {
      nested_set_sizes.top().curr_nestedset_size += cit->second.value_len + 4 + 4;
   }

   /// @todo check what happens when the last item in a sequence is another SQ
   /// -> maybe put else if branch outside as a "standalone" if.
   if (cit->first == SequenceDelimitationItem || cit->first == ItemDelimitationItem
       || (is_in_nested() && (cit->second.value_rep != VR::SQ || dictionary.lookup(cit->first).vr[0] != VR::SQ) && nested_set_sizes.top().curr_nestedset_size >= nested_set_sizes.top().curr_nestedset_max)) {
//      || (is_in_nested() && cit->second.value_rep != VR::SQ && nested_set_sizes.top().curr_nestedset_size >= nested_set_sizes.top().curr_nestedset_max)) {
      // sequence delimitation item encountered, check if there are more items.
      // Otherwise, step out of the current sequence.
      auto& nes_items = items.top().nested_items_curr;
      //last = cit->first;
      if (nes_items < items.top().nested_items_max-1) {
         nes_items++;
         return (cit = nested_sets.top()[nes_items].begin());
      } else if (cit->first == ItemDelimitationItem) {
         return ++cit; // we still have the sequenceDelimitationItem
      } else {
         delimiter = cit = step_outof_nested();
         return delimiter;
      }
   } else if (cit->second.value_rep.is_initialized()) {
      //last = cit->first;
      // found another sequence in the current set; step into it.
      if (cit->second.value_rep == VR::SQ) {
         cit = step_into_nested(cit);
         return cit;
      }
   } else if (dictionary.lookup(cit->first).vr[0] == VR::SQ) {
      // found another sequence in the current set; step into it.
      cit = step_into_nested(cit);
      return cit;
   }

   return ++cit;
}

std::map<attribute::tag_type, attribute::elementfield>::iterator dataset_iterator::previous()
{
   auto curr = cit;
   --cit;
   if (is_in_nested() &&
       std::any_of(nested_sets.top().begin(), nested_sets.top().end(), [curr](const dataset_type& set) { return set.begin() == curr; })) {
      // current iterator points into a sequence, at the beginning of a item
      // vector. Check if there are more previous elements in the item vector,
      // if not step backwards out of the sequence.
      if (items.top().nested_items_curr > 0) {
         items.top().nested_items_curr--;
         return (cit = (nested_sets.top()[items.top().nested_items_curr].end()--));
      } else {
         return (cit = step_backw_outof_nested());
      }
   } else if ((cit->second.value_rep.is_initialized() && cit->second.value_rep == VR::SQ) ||
              dictionary.lookup(cit->first).vr[0] == VR::SQ) {
      // previous item will be a sequence, step backwards into it.
      return (cit = step_backw_into_nested(cit));
   }

   if (nested_set_sizes.top().curr_nestedset_max != 0xffff
       && cit->first != Item
       && cit->first != ItemDelimitationItem
       && cit->first != SequenceDelimitationItem) {
      nested_set_sizes.top().curr_nestedset_size -= cit->second.value_len - (4 + 4);
   }

   return cit;
}

bool dataset_iterator::is_in_nested() const
{
   return parent_its.size() > 0;
}

dataset_iterator_adaptor::dataset_iterator_adaptor(std::map<tag_type, elementfield> ds):
   dataset {ds}
{
}

dataset_iterator dataset_iterator_adaptor::begin()
{
   return dataset.begin();
}

dataset_iterator dataset_iterator_adaptor::end()
{
   return dataset.end();
}

}

}

}

<commit_msg>fix bug in detection of a item end<commit_after>#include "dataset_iterator.hpp"

#include <stack>
#include <algorithm>

#include "data/attribute/constants.hpp"

namespace dicom
{

namespace data
{

namespace dataset
{

using namespace attribute;
using namespace data::dictionary;

dataset_iterator::dataset_iterator(typename std::map<attribute::tag_type, attribute::elementfield>::iterator it):
   cit {it},
   delimiter {it},
   dictionary {get_default_dictionaries()}
{
   nested_set_sizes.push({0, 0});
}

dataset_iterator dataset_iterator::operator++()
{
   return next();
}

dataset_iterator dataset_iterator::operator++(int)
{
   dataset_iterator ret = cit;
   cit = next();
   return ret;
}

dataset_iterator dataset_iterator::operator--()
{
   return previous();
}

dataset_iterator dataset_iterator::operator--(int)
{
   dataset_iterator ret = cit;
   cit = previous();
   return ret;
}

std::pair<attribute::tag_type, attribute::elementfield>
dataset_iterator::operator*() const
{
   return *cit;
}

std::pair<const attribute::tag_type, attribute::elementfield> const*
dataset_iterator::operator->() const
{
   return &*cit;
}

bool operator==(const dataset_iterator& lhs, const dataset_iterator& rhs)
{
   return lhs.cit == rhs.cit;
}

bool operator!=(const dataset_iterator& lhs, const dataset_iterator& rhs)
{
   return !(lhs == rhs);
}

std::map<attribute::tag_type, attribute::elementfield>::iterator
dataset_iterator::step_into_nested(std::map<attribute::tag_type, attribute::elementfield>::iterator curr)
{
   parent_its.push(curr); // save current position of the iterator
   nested_set_sizes.push({0, curr->second.value_len});
   std::vector<dataset_type> nested_set;
   get_value_field<VR::SQ>(curr->second, nested_set);

   nested_set.erase(std::remove_if(nested_set.begin(), nested_set.end(),
                                   [](const dataset_type& set) { return set.empty(); }),
                    nested_set.end());

   nested_sets.push(nested_set);
   items.push({0, nested_sets.top().size()});
   if (nested_set.size() == 0 || /* empty set*/ nested_set[0].size() == 0) {
      return step_outof_nested();
   } else {
      curr = nested_sets.top().begin()->begin();
      return curr;
   }
}

std::map<attribute::tag_type, attribute::elementfield>::iterator dataset_iterator::step_outof_nested()
{
   auto last = parent_its.top();
   parent_its.pop();
   nested_sets.pop();
   items.pop();
   nested_set_sizes.pop();
   return ++last;
}

std::map<attribute::tag_type, attribute::elementfield>::iterator
dataset_iterator::step_backw_into_nested(std::map<attribute::tag_type, attribute::elementfield>::iterator prev)
{
   bool explicitlength = true;
   parent_its.push(prev);
   nested_set_sizes.push({prev->second.value_len, prev->second.value_len});
   if (nested_set_sizes.top().curr_nestedset_max != 0xffff) {
      nested_set_sizes.top().curr_nestedset_size = nested_set_sizes.top().curr_nestedset_max;
   } else {
      explicitlength = false;
   }
   std::vector<dataset_type> nested_set;
   get_value_field<VR::SQ>(prev->second, nested_set);
   nested_sets.push(nested_set);
   items.push({nested_sets.size()-1, nested_sets.size()});
   auto curr = --nested_sets.top()[items.top().nested_items_max-1].end();
   return explicitlength ? curr : --curr;
}

std::map<attribute::tag_type, attribute::elementfield>::iterator dataset_iterator::step_backw_outof_nested()
{
   auto last = parent_its.top();
   parent_its.pop();
   nested_sets.pop();
   items.pop();
   nested_set_sizes.pop();
   return last;
}

std::map<attribute::tag_type, attribute::elementfield>::iterator dataset_iterator::next()
{
   // accumulate the size of the nested set's elements if a sequence size was
   // explicitly specified
   if (nested_set_sizes.top().curr_nestedset_max != 0xffff
       && cit->first != Item
       && cit->first != ItemDelimitationItem
       && cit->first != SequenceDelimitationItem) {
      nested_set_sizes.top().curr_nestedset_size += cit->second.value_len + 4 + 4;
   }

   /// @todo check what happens when the last item in a sequence is another SQ
   /// -> maybe put else if branch outside as a "standalone" if.
   if (cit->first == SequenceDelimitationItem || cit->first == ItemDelimitationItem
       || (is_in_nested() && nested_set_sizes.top().curr_nestedset_max != 0xffffffff  && (cit->second.value_rep != VR::SQ || dictionary.lookup(cit->first).vr[0] != VR::SQ) && nested_set_sizes.top().curr_nestedset_size >= nested_set_sizes.top().curr_nestedset_max)) {
//      || (is_in_nested() && cit->second.value_rep != VR::SQ && nested_set_sizes.top().curr_nestedset_size >= nested_set_sizes.top().curr_nestedset_max)) {
      // sequence delimitation item encountered, check if there are more items.
      // Otherwise, step out of the current sequence.
      auto& nes_items = items.top().nested_items_curr;
      //last = cit->first;
      if (nes_items < items.top().nested_items_max-1) {
         nes_items++;
         return (cit = nested_sets.top()[nes_items].begin());
      } else if (cit->first == ItemDelimitationItem) {
         return ++cit; // we still have the sequenceDelimitationItem
      } else {
         delimiter = cit = step_outof_nested();
         return delimiter;
      }
   } else if (cit->second.value_rep.is_initialized()) {
      //last = cit->first;
      // found another sequence in the current set; step into it.
      if (cit->second.value_rep == VR::SQ) {
         cit = step_into_nested(cit);
         return cit;
      }
   } else if (dictionary.lookup(cit->first).vr[0] == VR::SQ) {
      // found another sequence in the current set; step into it.
      cit = step_into_nested(cit);
      return cit;
   }

   return ++cit;
}

std::map<attribute::tag_type, attribute::elementfield>::iterator dataset_iterator::previous()
{
   auto curr = cit;
   --cit;
   if (is_in_nested() &&
       std::any_of(nested_sets.top().begin(), nested_sets.top().end(), [curr](const dataset_type& set) { return set.begin() == curr; })) {
      // current iterator points into a sequence, at the beginning of a item
      // vector. Check if there are more previous elements in the item vector,
      // if not step backwards out of the sequence.
      if (items.top().nested_items_curr > 0) {
         items.top().nested_items_curr--;
         return (cit = (nested_sets.top()[items.top().nested_items_curr].end()--));
      } else {
         return (cit = step_backw_outof_nested());
      }
   } else if ((cit->second.value_rep.is_initialized() && cit->second.value_rep == VR::SQ) ||
              dictionary.lookup(cit->first).vr[0] == VR::SQ) {
      // previous item will be a sequence, step backwards into it.
      return (cit = step_backw_into_nested(cit));
   }

   if (nested_set_sizes.top().curr_nestedset_max != 0xffff
       && cit->first != Item
       && cit->first != ItemDelimitationItem
       && cit->first != SequenceDelimitationItem) {
      nested_set_sizes.top().curr_nestedset_size -= cit->second.value_len - (4 + 4);
   }

   return cit;
}

bool dataset_iterator::is_in_nested() const
{
   return parent_its.size() > 0;
}

dataset_iterator_adaptor::dataset_iterator_adaptor(std::map<tag_type, elementfield> ds):
   dataset {ds}
{
}

dataset_iterator dataset_iterator_adaptor::begin()
{
   return dataset.begin();
}

dataset_iterator dataset_iterator_adaptor::end()
{
   return dataset.end();
}

}

}

}

<|endoftext|>