# Create Geometry Shell

## Summary

Below is an example demonstrating how you can create a geometry shell and set the offset distance of the push modifier, via script.

## Example

Create_Geometry_Shell.dsa
```// Define an anonymous function;
// serves as our main loop,
// limits the scope of variables
(function(){

/*********************************************************************/
// String : A function for retrieving a translation if one exists
function text( sText )
{
// If the version of the application supports qsTr()
if( typeof( qsTr ) != "undefined" ){
// Return the translated (if any) text
return qsTr( sText );
}

// Return the original text
return sText;
};

/*********************************************************************/
// Boolean : A function for testing whether or not a QObject instance
// inherits one of a list of types
function inheritsType( oObject, aTypeNames )
{
// If the object does not define the 'inherits' function
if( !oObject || typeof( oObject.inherits ) != "function" ){
// We are done... it is not a QObject
return false;
}

// Iterate over the list of type names
for( var i = 0, nTypes = aTypeNames.length; i < nTypes; i += 1 ){
// If the object does not inherit the 'current' type
if( !oObject.inherits( aTypeNames[i] ) ){
// Next!!
continue;
}

// Return the result
return true;
}

// Return the result
return false;
};

/*********************************************************************/
// DzNode : A function for getting the root of a node
function getRootNode( oNode )
{
// If we have a node and it is a bone
if( oNode && inheritsType( oNode, ["DzBone"] ) ){
// We want the skeleton
return oNode.getSkeleton();
}

// Return the original node
return oNode;
};

/*********************************************************************/
// DzObject : A function for getting the object for a node
function getObjectForNode( oNode, bRoot )
{
// Get the node
var oContextNode = bRoot ? getRootNode( oNode ) : oNode;
// If we do not have a root node
if( !oContextNode ){
// We are done...
return null;
}

// Get the object of the root node
var oObject = oContextNode.getObject();
// If we do not have an object
if( !oObject ){
// We are done...
return null;
}

// Return the object
return oObject;
};

/*********************************************************************/
// DzShape : A function for getting the shape for a node
function getShapeForNode( oNode, bRoot )
{
// Get the object of the node
var oObject = getObjectForNode( oNode, bRoot );
// If we do not have an object
if( !oObject ){
// We are done...
return null;
}

// Get the shape of the root node
var oShape = oObject.getCurrentShape();
// If we do not have a shape
if( !oShape ){
// We are done...
return null;
}

// Return the shape
return oShape;
};

/*********************************************************************/
// DzGeometry : A function for getting the geometry for the root of a node
function getGeometryForNode( oNode, bRoot, bCached )
{
// Get the shape of the root node
var oShape = getShapeForNode( oNode, bRoot );
// If we do not have a shape
if( !oShape ){
// We are done...
return null;
}

// If we are getting the cached geometry
if( bCached ){
// Update the working mesh
//oShape.invalidateWorkingMesh();

// Get the object of the root node
var oObject = getObjectForNode( oNode, bRoot );

// Return the geometry
return oObject.getCachedGeom();
}

// Get the geometry of the root node
var oGeometry = oShape.getGeometry();
// If we do not have a geometry
if( !oGeometry ){
// We are done...
return null;
}

// Return the geometry
return oGeometry;
};

/*********************************************************************/
// DzGeometryShellNode : A function for creating a geometry shell for
// an item with geometry in the scene
function createShell( oNode )
{
// If we do not have a node
if( !oNode ){
// We are done...
return undefined;
}

// Get the root of the node
var oSrcNode = getRootNode( oNode );

// Get the node's cached geometry
var oGeometry = getGeometryForNode( oSrcNode, true, true );
// If we do not have geometry
if( !oGeometry ){
// We are done...
return undefined;
}

// Create a new geometry shell node
var oShellNode = new DzGeometryShellNode();

// Get the target property of the shell
var oProperty = oShellNode.getShellNodeControl();

// Exclude the shell node from the
// list of nodes that can be targeted
oProperty.exclude( oShellNode );

// Set the target to the source node
oProperty.setValue( oSrcNode );

// Set the name of the shell
oShellNode.setName( String("%1_shell").arg( oSrcNode.objectName ) );

// Get the label of the source node
var sLabel = oSrcNode.getLabel();
// Strip the number from the label
sLabel = Scene.stripLabelNumber( sLabel );
// Get a unique label
sLabel = Scene.getUniqueTopLevelLabel( String("%1 Shell").arg( sLabel ) );
// Set the label of the shell node
oShellNode.setLabel( sLabel );

// Add the shell node to the scene

// Return the shell node
return oShellNode;
};

/*********************************************************************/
// Declare working variables
var sTitle, sMessage;

// Define common strings
var sButton = text( "&OK" );

// Get the primary selection
var oNode = Scene.getPrimarySelection();

// If nothing is selected
if( !oNode ){
// Define text variables for the message
sTitle = text( "Selection Error" );
sMessage = text( "An object in the scene, with geometry, must be selected to continue." );

// Inform the user
MessageBox.information( sMessage, sTitle, sButton );

// We are done..
return;
}

// Create a shell of the node
var oShellNode = createShell( oNode );
// If a shell was not created
if( !oShellNode ){
// Define text variables for the message
sTitle = text( "Selection Error" );
sMessage = text( "A Geometry Shell could not be created for the selected object." );

// Inform the user
MessageBox.information( sMessage, sTitle, sButton );

// We are done...
return;
}

// Get the shell's object
var oObject = getObjectForNode( oShellNode, false );
// If we do not have an object
if( !oObject ){
// Define text variables for the message
sTitle = text( "Resource Error" );
sMessage = text( "An error occurred while creating a Geometry Shell for the selected object." );

// Inform the user
MessageBox.information( sMessage, sTitle, sButton );

// We are done...
return;
}

// Get the offset modifier
var oModifier = oObject.findModifier( "Offset" );
// If we do not have a modifier
if( !oModifier ){
// We are done...
return;
}

// Get the property that controls distance;
// if the application version is less than 4.9.3.137,
// use the old API, otherwise use the new API
var oProperty = App.version64 < 0x0004000900030089 ?
oModifier.getValueChannel() :
oModifier.getValueControl();
// If we do not have a property
if( !oProperty ){
// We are done...
return;
}

// Set the distance
oProperty.setValue( 0.3 );

// Finalize the function and invoke
})();```