#include <maya/MIOStream.h>
#include <math.h>
#include <stdlib.h>
#include "ownerEmitter.h"
#include <maya/MVectorArray.h>
#include <maya/MDoubleArray.h>
#include <maya/MIntArray.h>
#include <maya/MMatrix.h>
#include <maya/MArrayDataBuilder.h>
#include <maya/MFnDependencyNode.h>
#include <maya/MFnNumericAttribute.h>
#include <maya/MFnUnitAttribute.h>
#include <maya/MFnVectorArrayData.h>
#include <maya/MFnDoubleArrayData.h>
#include <maya/MFnArrayAttrsData.h>
#include <maya/MFnMatrixData.h>
MTypeId ownerEmitter::id( 0x80015 );
 
ownerEmitter::ownerEmitter()
:   lastWorldPoint(0, 0, 0, 1)
{
}
ownerEmitter::~ownerEmitter()
{
}
void *ownerEmitter::creator()
{
    return new ownerEmitter;
}
{
}
{
    
    
    if( !(plug == mOutput) )
    
    
    
    
    McheckErr(status, "ERROR in plug.logicalIndex.\n");
    
    
    
    McheckErr(status, "ERROR in hOutArray = block.outputArrayValue.\n");
    
    
    McheckErr(status, "ERROR in bOutArray = hOutArray.builder.\n");
    
    
    McheckErr(status, "ERROR in hOut = bOutArray.addElement.\n");
    
    
    
    
    McheckErr(status, "ERROR in fnOutput.create.\n");
    
    
    
    bool beenFull = isFullValue( multiIndex, block );
    if( beenFull )
    {
    }
    
    
    
    
    
    
    
    ownerPosition( block, inPosAry );
    
    
    ownerVelocity( multiIndex, block, inVelAry );
    
    
    
    unsigned inPosLength = inPosAry.
length();
 
    if( (inPosLength == 0) || (inPosLength != inVelAry.
length()) )
 
    {
        
        
        
    }
    
    
    
    
    MTime cT = currentTimeValue( block );
 
    MTime sT = startTimeValue( multiIndex, block );
 
    MTime dT = deltaTimeValue( multiIndex, block );
 
    if( (cT <= sT) || (dT <= 0.0) )
    {
        
        
        
        
        
        
        
        
    }
    
    
    status = emitCountPerPoint( plug, block, inPosLength, emitCountPP );
    
    
    double speed = speedValue( block );
    MVector dirV = directionVector( block );
 
    double inheritFactor = inheritFactorValue( multiIndex, block );
    
    
    
    
    
    MVector rotatedV = useRotation ( dirV );
 
    
    
    emit( inPosAry, inVelAry, emitCountPP,
            dt, speed, inheritFactor, rotatedV, fnOutPos, fnOutVel );
    
    
}
void ownerEmitter::emit
    (
        double dt,                      
        double speed,                   
        double inheritFactor,           
    )
{
    
    
    int posLength = inPosAry.
length();
 
    int velLength = inVelAry.
length();
 
    int countLength = emitCountPP.
length();
 
    if( (posLength != velLength) || (posLength != countLength) )
        return;
    
    
    int index;
    int totalCount = 0;
    for( index = 0; index < countLength; index ++ )
        totalCount += emitCountPP[index];
    if( totalCount <= 0 )
        return;
    
    
    
    
    int emitCount;
    for( index = 0; index < posLength; index++ )
    {
        emitCount = emitCountPP[index];
        if( emitCount <= 0 )
            continue;
        sPos = inPosAry[index];
        sVel = inVelAry[index];
        prePos = sPos - sVel * dt;
        for( int i = 0; i < emitCount; i++ )
        {
            double alpha = ( (double)i + drand48() ) / (double)emitCount;
            newPos = (1 - alpha) * prePos + alpha * sPos;
            newVel = dirV * speed;
            newPos += newVel * ( dt * (1 - alpha) );
            newVel += sVel * inheritFactor;
            
            
        }
    }
}
void ownerEmitter::ownerPosition
    (
    )
{
    bool hasOwner = false;
    {
        {
            
            
            for( 
unsigned int i = 0; i < posArray.
length(); i ++ )
 
                ownerPosArray.
append( posArray[i] );
            
            
            hasOwner = true;
        }
    }
    
    
    
    if( !hasOwner )
    {
        MPoint worldPos(0.0, 0.0, 0.0);
 
        status = getWorldPosition( worldPos );
        worldV[0] = worldPos[0];
        worldV[1] = worldPos[1];
        worldV[2] = worldPos[2];
        ownerPosArray.
append( worldV );
    }
}
void ownerEmitter::ownerVelocity
    (
        int plugIndex,
    )
{
    bool hasOwner = false;
    {
        {
            
            
            for( 
unsigned int i = 0; i < velArray.
length(); i ++ )
 
                ownerVelArray.
append( velArray[i] );
            
            
            hasOwner = true;
        }
    }
    
    
    
    if( !hasOwner )
    {
        MPoint worldPos(0.0, 0.0, 0.0);
 
        status = getWorldPosition( worldPos );
        MTime dT = deltaTimeValue( plugIndex, block );
 
        if( dt > 0.0 )
            velV = (worldPos - lastWorldPoint) / dt;
        lastWorldPoint = worldPos;
    }
}
{
    
    
    MObject worldMatrixAttr = fnThisNode.attribute( 
"worldMatrix" );
 
    
    
    
    MPlug matrixPlug( thisNode, worldMatrixAttr );
 
    matrixPlug = matrixPlug.elementByLogicalIndex( 0 );
    
    
    status = matrixPlug.getValue( matrixObject );
    if( !status )
    {
        status.
perror(
"ownerEmitter::getWorldPosition: get matrixObject");
        return( status );
    }
    if( !status )
    {
        status.
perror(
"ownerEmitter::getWorldPosition: get worldMatrixData");
        return( status );
    }
    if( !status )
    {
        status.
perror(
"ownerEmitter::getWorldPosition: get worldMatrix");
        return( status );
    }
    
    
    point[0] = worldMatrix( 3, 0 );
    point[1] = worldMatrix( 3, 1 );
    point[2] = worldMatrix( 3, 2 );
    return( status );
}
{
    
    
    MObject worldMatrixAttr = fnThisNode.attribute( 
"worldMatrix" );
 
    
    
    
    MPlug matrixPlug( thisNode, worldMatrixAttr );
 
    matrixPlug = matrixPlug.elementByLogicalIndex( 0 );
    McheckErr(status, "ERROR getting hWMatrix from dataBlock.\n");
    {
        point[0] = wMatrix(3, 0);
        point[1] = wMatrix(3, 1);
        point[2] = wMatrix(3, 2);
    }
    return( status );
}
{
    
    
    MObject worldMatrixAttr = fnThisNode.attribute( 
"worldMatrix" );
 
    
    
    
    MPlug matrixPlug( thisNode, worldMatrixAttr );
 
    matrixPlug = matrixPlug.elementByLogicalIndex( 0 );
    
    
    status = matrixPlug.getValue( matrixObject );
    if( !status )
    {
        status.
perror(
"ownerEmitter::getWorldPosition: get matrixObject");
        return ( direction );
    }
    if( !status )
    {
        status.
perror(
"ownerEmitter::getWorldPosition: get worldMatrixData");
        return( direction );
    }
    if( !status )
    {
        status.
perror(
"ownerEmitter::getWorldPosition: get worldMatrix");
        return( direction );
    }
    rotatedVector = direction * worldMatrix;
    return( rotatedVector );
}
MStatus ownerEmitter::emitCountPerPoint
 
    (
        int length,                 
    )
{
    McheckErr(status, "ERROR in emitCountPerPoint: when plug.logicalIndex.\n");
    
    
    double rate = rateValue( block );
    MTime dt = deltaTimeValue( plugIndex, block );
 
    
    
    int intCount = (int)dblCount;
    for( int i = 0; i < length; i++ )
    {
        emitCountPP.
append( intCount );
    }
}
{
    MFnPlugin plugin(obj, PLUGIN_COMPANY, 
"3.0", 
"Any");
 
    status = plugin.registerNode( "ownerEmitter", ownerEmitter::id,
                            &ownerEmitter::creator, &ownerEmitter::initialize,
    if (!status) {
        status.
perror(
"registerNode");
        return status;
    }
    return status;
}
{
    status = plugin.deregisterNode( ownerEmitter::id );
    if (!status) {
        status.
perror(
"deregisterNode");
        return status;
    }
    return status;
}