summaryrefslogtreecommitdiffstats
path: root/tools/globalcode
diff options
context:
space:
mode:
Diffstat (limited to 'tools/globalcode')
-rw-r--r--tools/globalcode/utility/GLExt.cpp1129
-rw-r--r--tools/globalcode/utility/GLExt.h191
-rw-r--r--tools/globalcode/utility/MExt.cpp2030
-rw-r--r--tools/globalcode/utility/MExt.h226
-rw-r--r--tools/globalcode/utility/MExt_template.cpp273
-rw-r--r--tools/globalcode/utility/MExt_template.h146
-rw-r--r--tools/globalcode/utility/MUI.cpp220
-rw-r--r--tools/globalcode/utility/MUI.h82
-rw-r--r--tools/globalcode/utility/mayahandles.cpp105
-rw-r--r--tools/globalcode/utility/mayahandles.h42
-rw-r--r--tools/globalcode/utility/nodehelper.h37
-rw-r--r--tools/globalcode/utility/overlaymarquee.cpp222
-rw-r--r--tools/globalcode/utility/overlaymarquee.h55
-rw-r--r--tools/globalcode/utility/stdafx.h19
-rw-r--r--tools/globalcode/utility/transformmatrix.cpp904
-rw-r--r--tools/globalcode/utility/transformmatrix.h247
-rw-r--r--tools/globalcode/utility/util.c724
-rw-r--r--tools/globalcode/utility/util.h88
-rw-r--r--tools/globalcode/utility/winutil.c69
-rw-r--r--tools/globalcode/utility/winutil.h37
20 files changed, 6846 insertions, 0 deletions
diff --git a/tools/globalcode/utility/GLExt.cpp b/tools/globalcode/utility/GLExt.cpp
new file mode 100644
index 0000000..4b069ba
--- /dev/null
+++ b/tools/globalcode/utility/GLExt.cpp
@@ -0,0 +1,1129 @@
+#include "precompiled/PCH.h"
+//-----------------------------------------------------------------------------
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// GLExt.cpp
+//
+// Description: Functions that do drawing using the OpenGL API.
+//
+// Modification History:
+// + Created Aug 21, 2001 -- bkusy
+//-----------------------------------------------------------------------------
+
+//----------------------------------------
+// System Includes
+//----------------------------------------
+#include <windows.h>
+#include <assert.h>
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <GL/glaux.h>
+
+//----------------------------------------
+// Project Includes
+//----------------------------------------
+#include "GLExt.h"
+
+//----------------------------------------
+// Forward References
+//----------------------------------------
+
+//----------------------------------------
+// Constants, Typedefs and Statics
+//----------------------------------------
+
+//=============================================================================
+// GLExt::drawCamera3D
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( double scale, double tx = 0.0f, double ty = 0.0f, double tz = 0.0f, float width = 1.0f )
+//
+// Return: void
+//
+//=============================================================================
+void GLExt::drawCamera3D( double scale, double tx, double ty, double tz, float width )
+{
+ glPushAttrib( GL_CURRENT_BIT | GL_LINE_BIT | GL_POLYGON_BIT );
+
+ //Store old line width
+ GLfloat oldWidth;
+ glGetFloatv( GL_LINE_WIDTH, &oldWidth );
+
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ glPushMatrix();
+ glScaled(scale, scale, scale);
+ glTranslated(tx, ty, tz);
+
+ //Set line width
+ glLineWidth( width );
+
+ glBegin( GL_LINES );
+ //X-Z
+ glVertex3d(-0.5, 0.0, 0.5 );
+ glVertex3d( 0.5, 0.0, 0.5 );
+
+ glVertex3d( 0.5, 0.0, 0.5 );
+ glVertex3d( 0.5, 0.0, -0.5 );
+
+ glVertex3d( 0.5, 0.0, -0.5 );
+ glVertex3d( -0.5, 0.0, -0.5 );
+
+ glVertex3d( -0.5, 0.0, -0.5 );
+ glVertex3d( -0.5, 0.0, 0.5 );
+
+ glVertex3d( 0.125, 0.0, -0.5 );
+ glVertex3d( 0.325, 0.0, -0.75 );
+
+ glVertex3d( 0.325, 0.0, -0.75 );
+ glVertex3d( -0.325, 0.0, -0.75 );
+
+ glVertex3d( -0.325, 0.0, -0.75 );
+ glVertex3d( -0.125, 0.0, -0.5 );
+
+ //Y-Z
+ glVertex3d( 0.0, -0.5, 0.5 );
+ glVertex3d( 0.0, 0.5, 0.5 );
+
+ glVertex3d( 0.0, 0.5, 0.5 );
+ glVertex3d( 0.0, 0.5, -0.5 );
+
+ glVertex3d( 0.0, 0.5, -0.5 );
+ glVertex3d( 0.0, -0.5, -0.5 );
+
+ glVertex3d( 0.0, -0.5, -0.5 );
+ glVertex3d( 0.0, -0.5, 0.5 );
+
+ glVertex3d( 0.0, 0.125, -0.5 );
+ glVertex3d( 0.0, 0.325, -0.75 );
+
+ glVertex3d( 0.0, 0.325, -0.75 );
+ glVertex3d( 0.0, -0.325, -0.75 );
+
+ glVertex3d( 0.0, -0.325, -0.75 );
+ glVertex3d( 0.0, -0.125, -0.5 );
+ glEnd();
+ glPopMatrix();
+ //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+ glLineWidth( oldWidth );
+
+ glPopAttrib();
+}
+
+//-----------------------------------------------------------------------------
+// d r a w C r o s s H a i r 3 D
+//
+// Synopsis: Draws a camera symbol
+//
+// Parameters: scale - the scale to draw at.
+// x - the x coordinate of the symbol.
+// y - the y coordinate of the symbol.
+// z - the z coordinate of the symbol.
+// width - line width
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void GLExt::drawCrossHair3D( double scale, double tx, double ty, double tz, float width )
+{
+ glPushAttrib( GL_CURRENT_BIT | GL_LINE_BIT | GL_POLYGON_BIT );
+
+ //Store old line width
+ GLfloat oldWidth;
+ glGetFloatv( GL_LINE_WIDTH, &oldWidth );
+
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ glPushMatrix();
+ glScaled(scale, scale, scale);
+ glTranslated(tx, ty, tz);
+
+ //Set line width
+ glLineWidth( width );
+
+ glBegin( GL_LINES );
+ glVertex3d(-1.0, 0.0, 0.0 );
+ glVertex3d( 1.0, 0.0, 0.0 );
+
+ glVertex3d( 0.0, -1.0, 0.0 );
+ glVertex3d( 0.0, 1.0, 0.0 );
+
+ glVertex3d( 0.0, 0.0, -1.0 );
+ glVertex3d( 0.0, 0.0, 1.0 );
+ glEnd();
+ glPopMatrix();
+ //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+ glLineWidth( oldWidth );
+
+ glPopAttrib();
+}
+
+//-----------------------------------------------------------------------------
+// d r a w C r o s s H a i r 3 D
+//
+// Synopsis: Draws a camera symbol
+//
+// Parameters: scale - the scale to draw the symbol at.
+// p - where to draw the symbol.
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void GLExt::drawCrossHair3D( double scale, const MPoint& p, float width )
+{
+ drawCrossHair3D( scale, p.x, p.y, p.z, width );
+}
+
+
+//-----------------------------------------------------------------------------
+// d r a w P y r a m i d
+//
+// Synopsis: Draws a pyramid using OpenGL.
+//
+// Parameters: scale - factor of scaling for the pyramid.
+// tx - x position translation.
+// ty - y position translation.
+// tz - z position translation.
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void GLExt::drawPyramid( double scale, double tx, double ty, double tz, float width )
+{
+ glPushAttrib( GL_CURRENT_BIT | GL_LINE_BIT | GL_POLYGON_BIT );
+
+ //Store old line width
+ GLfloat oldWidth;
+ glGetFloatv( GL_LINE_WIDTH, &oldWidth );
+
+ //Set line width
+ glLineWidth( width );
+
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ glPushMatrix();
+ glScaled(scale, scale, scale);
+ glTranslated(tx, ty, tz);
+ glBegin( GL_QUAD_STRIP );
+ glVertex3d(0.5, 0 ,0.5);
+ glVertex3d(0, 1, 0);
+ glVertex3d(0.5, 0, -0.5);
+ glVertex3d(0, 1, 0);
+ glVertex3d(-0.5, 0, -0.5);
+ glVertex3d(0, 1, 0);
+ glVertex3d(-0.5, 0 ,0.5);
+ glVertex3d(0, 1, 0);
+ glVertex3d(0.5, 0 ,0.5);
+ glVertex3d(0, 1, 0);
+ glEnd();
+ glPopMatrix();
+ //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+ glLineWidth( oldWidth );
+
+ glPopAttrib();
+}
+
+//-----------------------------------------------------------------------------
+// d r a w P y r a m i d
+//
+// Synopsis: Draws a pyramid using OpenGL.
+//
+// Parameters: scale - factor of scaling for the pyramid.
+// p0 - the point at which to draw the pyramid.
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void GLExt::drawPyramid( double scale, const MPoint& p0, float width )
+{
+ drawPyramid( scale, p0.x, p0.y, p0.z, width );
+}
+
+//-----------------------------------------------------------------------------
+// d r a w S p h e r e
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//------------------------------------------------------radius-----------------------
+void GLExt::drawSphere( double scale, double tx, double ty, double tz, float width )
+{
+ glPushAttrib( GL_CURRENT_BIT | GL_LINE_BIT | GL_POLYGON_BIT );
+ //Store old line width
+ GLfloat oldWidth;
+ glGetFloatv( GL_LINE_WIDTH, &oldWidth );
+
+ //Set line width
+ glLineWidth( width );
+
+ glPushMatrix();
+ glScaled(scale, scale, scale);
+ glTranslated(tx, ty, tz);
+
+ GLUquadricObj* quadric = gluNewQuadric();
+ gluQuadricDrawStyle( quadric, GLU_LINE );
+ gluSphere( quadric, 1.0, 12, 6 );
+
+ glPopMatrix();
+
+ glLineWidth( oldWidth );
+ glPopAttrib();
+}
+
+//-----------------------------------------------------------------------------
+// d r a w S p h e r e
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void GLExt::drawSphere( double scale, const MPoint& p, float width )
+{
+ drawSphere( scale, p.x, p.y, p.z, width );
+}
+
+//-----------------------------------------------------------------------------
+// d r a w L i n e
+//
+// Synopsis: Draws a line between the two points.
+//
+// Parameters: The coordinates of the two points.
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void GLExt::drawLine( double x0, double y0, double z0,
+ double x1, double y1, double z1,
+ float width )
+{
+ glPushAttrib( GL_CURRENT_BIT | GL_LINE_BIT | GL_POLYGON_BIT );
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+
+ //Store old line width
+ GLfloat oldWidth;
+ glGetFloatv( GL_LINE_WIDTH, &oldWidth );
+
+ //Set line width
+ glLineWidth( width );
+
+ glBegin( GL_LINES );
+ glVertex3f( (float)x0, (float)y0, (float)z0 );
+ glVertex3f( (float)x1, (float)y1, (float)z1 );
+ glEnd();
+
+ //Reset line width
+ glLineWidth( oldWidth );
+
+ //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ glPopAttrib();
+}
+
+//-----------------------------------------------------------------------------
+// d r a w L i n e
+//
+// Synopsis: Draws a line between the two points.
+//
+// Parameters: The points to draw the line between.
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void GLExt::drawLine( const MPoint& p0, const MPoint& p1, float width )
+{
+ drawLine( p0.x, p0.y, p0.z, p1.x, p1.y, p1.z, width );
+}
+
+//=============================================================================
+// GLExt::drawArrow
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( const MPoint& p0, const MPoint& p1, float width, float scale )
+//
+// Return: void
+//
+//=============================================================================
+void GLExt::drawArrow( const MPoint& p0, const MPoint& p1, float width, float scale )
+{
+ glPushAttrib( GL_CURRENT_BIT | GL_LINE_BIT | GL_POLYGON_BIT );
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+
+ //Store old line width
+ GLfloat oldWidth;
+ glGetFloatv( GL_LINE_WIDTH, &oldWidth );
+
+ MVector scaledVector;
+ scaledVector = p1 - p0;
+ scaledVector /= scale;
+
+ //Figure out a cross product...
+ MVector normal;
+
+ normal = scaledVector^( MVector(0, 1.0, 0 ) );
+ normal.normalize();
+ normal *= scaledVector.length();
+
+ MPoint head0, head1;
+
+ head0 = (p1 - scaledVector + normal );
+ head1 = (p1 - scaledVector - normal );
+
+ //Set line width
+ glLineWidth( width );
+
+ glBegin( GL_LINES );
+ glVertex3f( (float)p0.x, (float)p0.y, (float)p0.z );
+ glVertex3f( (float)p1.x, (float)p1.y, (float)p1.z );
+
+ glVertex3f( (float)p1.x, (float)p1.y, (float)p1.z );
+ glVertex3f( (float)head0.x, (float)head0.y, (float)head0.z );
+
+ glVertex3f( (float)p1.x, (float)p1.y, (float)p1.z );
+ glVertex3f( (float)head1.x, (float)head1.y, (float)head1.z );
+ glEnd();
+
+ //Reset line width
+ glLineWidth( oldWidth );
+
+ //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ glPopAttrib();
+}
+
+//-----------------------------------------------------------------------------
+// d r a w B o x
+//
+// Synopsis: Draws a box using OpenGL.
+//
+// Parameters: The coordinates of the minimal and maximal corners of the box.
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void GLExt::drawBox( double x0, double y0, double z0,
+ double x1, double y1, double z1,
+ float width )
+{
+ glPushAttrib( GL_CURRENT_BIT | GL_LINE_BIT | GL_POLYGON_BIT );
+ //Store old line width
+ GLfloat oldWidth;
+ glGetFloatv( GL_LINE_WIDTH, &oldWidth );
+
+ //Set line width
+ glLineWidth( width );
+
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ glBegin( GL_QUADS );
+
+ glVertex3f( (float)x0, (float)y0, (float)z0 );
+ glVertex3f( (float)x0, (float)y0, (float)z1 );
+ glVertex3f( (float)x1, (float)y0, (float)z1 );
+ glVertex3f( (float)x1, (float)y0, (float)z0 );
+
+ glVertex3f( (float)x0, (float)y1, (float)z0 );
+ glVertex3f( (float)x0, (float)y1, (float)z1 );
+ glVertex3f( (float)x1, (float)y1, (float)z1 );
+ glVertex3f( (float)x1, (float)y1, (float)z0 );
+
+ glEnd();
+
+ glBegin( GL_LINES );
+
+ glVertex3f( (float)x0, (float)y0, (float)z0 );
+ glVertex3f( (float)x0, (float)y1, (float)z0 );
+
+ glVertex3f( (float)x0, (float)y0, (float)z1 );
+ glVertex3f( (float)x0, (float)y1, (float)z1 );
+
+ glVertex3f( (float)x1, (float)y0, (float)z1 );
+ glVertex3f( (float)x1, (float)y1, (float)z1 );
+
+ glVertex3f( (float)x1, (float)y0, (float)z0 );
+ glVertex3f( (float)x1, (float)y1, (float)z0 );
+ glEnd();
+ //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+ glLineWidth( oldWidth );
+ glPopAttrib();
+}
+
+//-----------------------------------------------------------------------------
+// d r a w B o x
+//
+// Synopsis: Draws a box using OpenGL.
+//
+// Parameters: p0 - the minimal corner of the box.
+// p1 - the maximal corner of the box.
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void GLExt::drawBox( const MPoint& p0, const MPoint& p1, float width )
+{
+ drawBox( p0.x, p0.y, p0.z, p1.x, p1.y, p1.z, width );
+}
+
+//-----------------------------------------------------------------------------
+// d r a w X Z P l a n e
+//
+// Synopsis: Draws a finite plane in the XZ plane using OpenGL.
+//
+// Parameters: x0, z0 - the minimal vertex of the finite plane.
+// x1, z1 - the maximal vertex of the finite plane.
+// y - the height of the plane.
+//
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void GLExt::drawXZPlane( double xscale,
+ double yscale,
+ double zscale,
+ double x0,
+ double z0,
+ double x1,
+ double z1,
+ double y,
+ float width
+ )
+{
+ glPushAttrib( GL_CURRENT_BIT | GL_LINE_BIT | GL_POLYGON_BIT );
+ //Store old line width
+ GLfloat oldWidth;
+ glGetFloatv( GL_LINE_WIDTH, &oldWidth );
+
+ //Set line width
+ glLineWidth( width );
+
+ glPushMatrix();
+ glScaled(xscale, yscale, zscale);
+
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE );
+ glBegin( GL_QUADS );
+
+ glVertex3f( (float)x0, (float)y, (float)z0 );
+ glVertex3f( (float)x0, (float)y, (float)z1 );
+ glVertex3f( (float)x1, (float)y, (float)z1 );
+ glVertex3f( (float)x1, (float)y, (float)z0 );
+
+ glEnd();
+
+ glPopMatrix();
+
+ glLineWidth( oldWidth );
+ glPopAttrib();
+}
+
+//-----------------------------------------------------------------------------
+// d r a w X Z P l a n e
+//
+// Synopsis: Draws a finite plane in the XZ plane using OpenGL.
+//
+// Parameters: p0 - the minimal vertex of the finite plane.
+// p1 - the maximal vertex of the finite plane.
+//
+// Returns: NOTHING
+//
+// Constraints: The y component of p1 is ignored and the plane is drawn at
+// the height of the first point.
+//
+//-----------------------------------------------------------------------------
+void GLExt::drawXZPlane( double xscale,
+ double yscale,
+ double zscale,
+ const MPoint& v0,
+ const MPoint& v1,
+ float width
+ )
+{
+ drawXZPlane( xscale, yscale, zscale, v0.x, v0.z, v1.x, v1.z, v0.y, width );
+}
+
+//=============================================================================
+// GLExt::drawP
+//=============================================================================
+// Description: Comment
+//
+// Parameters: (double scale, double tx, double ty, double tz, float width)
+//
+// Return: void
+//
+//=============================================================================
+void GLExt::drawP(double scale, double tx, double ty, double tz, float width)
+{
+ glPushAttrib( GL_CURRENT_BIT | GL_LINE_BIT | GL_POLYGON_BIT );
+ //Store old line width
+ GLfloat oldWidth;
+ glGetFloatv( GL_LINE_WIDTH, &oldWidth );
+
+ //Set line width
+ glLineWidth( width );
+
+ glPushMatrix();
+ glScaled(scale, scale, scale);
+ glTranslated(tx, ty, tz);
+ glBegin( GL_LINE_LOOP );
+ //Draw a "P" for pickup.
+ glVertex3d( 0,0,0);
+ glVertex3d( 0, 2.0, 0);
+ glVertex3d( 0.7, 2.0, 0);
+ glVertex3d( 1.2, 1.7, 0);
+ glVertex3d( 1.2, 1.3, 0);
+ glVertex3d( 0.7, 1, 0);
+ glVertex3d( 0, 1, 0);
+ glEnd();
+ glPopMatrix();
+
+ glLineWidth( oldWidth );
+ glPopAttrib();
+}
+
+//=============================================================================
+// GLExt::drawStickMan
+//=============================================================================
+// Description: Comment
+//
+// Parameters: (double scale, double tx, double ty, double tz, float width)
+//
+// Return: void
+//
+//=============================================================================
+void GLExt::drawStickMan(double scale, double tx, double ty, double tz, float width)
+{
+ glPushAttrib( GL_CURRENT_BIT | GL_LINE_BIT | GL_POLYGON_BIT );
+ //Store old line width
+ GLfloat oldWidth;
+ glGetFloatv( GL_LINE_WIDTH, &oldWidth );
+
+ //Set line width
+ glLineWidth( width );
+
+ glPushMatrix();
+ glScaled(scale, scale, scale);
+ glTranslated(tx, ty, tz);
+ glBegin( GL_LINES );
+ glVertex3d( 0,0.6,0);
+ glVertex3d( 0, 1.5, 0);
+ glVertex3d( -0.5, 1.2, 0.0);
+ glVertex3d( 0.5, 1.2, 0);
+ glEnd();
+ glBegin( GL_LINE_STRIP );
+ glVertex3d( -0.5, 0, 0 );
+ glVertex3d( 0, 0.6, 0 );
+ glVertex3d( 0.5, 0, 0 );
+ glEnd();
+ glBegin( GL_QUADS );
+ glVertex3d( -0.125, 1.5, 0 );
+ glVertex3d( -0.125, 1.75, 0 );
+ glVertex3d( 0.125, 1.75, 0 );
+ glVertex3d( 0.125, 1.5, 0 );
+ glEnd();
+ glPopMatrix();
+
+ glLineWidth( oldWidth );
+ glPopAttrib();
+}
+
+//=============================================================================
+// GLExt::drawCar
+//=============================================================================
+// Description: Comment
+//
+// Parameters: (double scale, double tx, double ty, double tz, float width)
+//
+// Return: void
+//
+//=============================================================================
+void GLExt::drawCar(double scale, double tx, double ty, double tz, float width)
+{
+ glPushAttrib( GL_CURRENT_BIT | GL_LINE_BIT | GL_POLYGON_BIT );
+ //Store old line width
+ GLfloat oldWidth;
+ glGetFloatv( GL_LINE_WIDTH, &oldWidth );
+
+ //Set line width
+ glLineWidth( width );
+
+ glPushMatrix();
+ glScaled(scale, scale, scale);
+ glTranslated(tx, ty, tz);
+ glBegin( GL_LINE_LOOP );
+ glVertex3d( 0, 0, 0);
+ glVertex3d( 0, 0, -0.25);
+ glVertex3d( 0, -0.2, -0.5 );
+ glVertex3d( 0, 0, -0.75 );
+ glVertex3d( 0, 0, -1.0 );
+ glVertex3d( 0, 0.4, -1.0 );
+ glVertex3d( 0, 0.4, -0.5 );
+ glVertex3d( 0, 0.7, -0.45 );
+ glVertex3d( 0, 0.7, 0.25 );
+ glVertex3d( 0, 0.4, 0.4 );
+ glVertex3d( 0, 0.3, 1.0 );
+ glVertex3d( 0, 0, 1.0 );
+ glVertex3d( 0, 0, 0.75 );
+ glVertex3d( 0, -0.2, 0.5 );
+ glVertex3d( 0, 0, 0.25 );
+ glEnd();
+ glPopMatrix();
+
+ glLineWidth( oldWidth );
+ glPopAttrib();
+}
+
+//=============================================================================
+// GLExt::drawA
+//=============================================================================
+// Description: Comment
+//
+// Parameters: (double scale, double tx, double ty, double tz, float width)
+//
+// Return: void
+//
+//=============================================================================
+void GLExt::drawA(double scale, double tx, double ty, double tz, float width)
+{
+ glPushAttrib( GL_CURRENT_BIT | GL_LINE_BIT | GL_POLYGON_BIT );
+ //Store old line width
+ GLfloat oldWidth;
+ glGetFloatv( GL_LINE_WIDTH, &oldWidth );
+
+ //Set line width
+ glLineWidth( width );
+
+ //Draw an "A" on top of the pyramid
+ glPushMatrix();
+ glScaled(scale, scale, scale);
+ glTranslated(tx, ty, tz);
+ glBegin( GL_LINES );
+ glVertex3d( 0, 2.0, 0);
+ glVertex3d( -0.7, 0, 0);
+ glVertex3d( 0, 2.0, 0);
+ glVertex3d( 0.7, 0, 0);
+ glVertex3d( -0.7, 1.2, 0);
+ glVertex3d( 0.7, 1.2, 0);
+ glEnd();
+ glPopMatrix();
+
+ glLineWidth( oldWidth );
+ glPopAttrib();
+}
+
+//=============================================================================
+// GLExt::drawD
+//=============================================================================
+// Description: Comment
+//
+// Parameters: (double scale, double tx, double ty, double tz, float width)
+//
+// Return: void
+//
+//=============================================================================
+void GLExt::drawD(double scale, double tx, double ty, double tz, float width)
+{
+ glPushAttrib( GL_CURRENT_BIT | GL_LINE_BIT | GL_POLYGON_BIT );
+ //Store old line width
+ GLfloat oldWidth;
+ glGetFloatv( GL_LINE_WIDTH, &oldWidth );
+
+ //Set line width
+ glLineWidth( width );
+
+ //Draw a "D" on top of the pyramid
+ glPushMatrix();
+ glScaled(scale, scale, scale);
+ glTranslated(tx, ty, tz);
+ glTranslated( -0.6, 0, 0);
+ glBegin( GL_LINE_LOOP );
+ //Draw a "D" for dropoff.
+ glVertex3d( 0, 0, 0);
+ glVertex3d( 0, 2.0, 0);
+ glVertex3d( 0.6, 2.0, 0);
+ glVertex3d( 1.1, 1.7, 0);
+ glVertex3d( 1.2, 1, 0);
+ glVertex3d( 1.1, 0.3, 0);
+ glVertex3d( 0.6, 0, 0);
+ glEnd();
+ glPopMatrix();
+ glLineWidth( oldWidth );
+ glPopAttrib();
+}
+
+//=============================================================================
+// GLExt::drawE
+//=============================================================================
+// Description: Comment
+//
+// Parameters: (double scale, double tx, double ty, double tz, float width)
+//
+// Return: void
+//
+//=============================================================================
+void GLExt::drawE(double scale, double tx, double ty, double tz, float width)
+{
+ glPushAttrib( GL_CURRENT_BIT | GL_LINE_BIT | GL_POLYGON_BIT );
+ //Store old line width
+ GLfloat oldWidth;
+ glGetFloatv( GL_LINE_WIDTH, &oldWidth );
+
+ //Set line width
+ glLineWidth( width );
+
+ //Draw the Letter "E" on top of the pyramid
+ glPushMatrix();
+ glScaled(scale, scale, scale);
+ glTranslated(tx, ty, tz);
+ glBegin( GL_LINES );
+ glVertex3d( -0.4, 2, 0);
+ glVertex3d( -0.4, 0, 0);
+ glVertex3d( -0.4, 1, 0);
+ glVertex3d( 0.3, 1, 0);
+ glVertex3d( -0.4, 0, 0);
+ glVertex3d( 0.4, 0, 0);
+ glVertex3d( -0.4, 2, 0);
+ glVertex3d( 0.4, 2, 0);
+ glEnd();
+ glPopMatrix();
+
+ glLineWidth( oldWidth );
+ glPopAttrib();
+}
+
+//=============================================================================
+// GLExt::drawS
+//=============================================================================
+// Description: Comment
+//
+// Parameters: (double scale, double tx, double ty, double tz, float width)
+//
+// Return: void
+//
+//=============================================================================
+void GLExt::drawS(double scale, double tx, double ty, double tz, float width)
+{
+ glPushAttrib( GL_CURRENT_BIT | GL_LINE_BIT | GL_POLYGON_BIT );
+ //Store old line width
+ GLfloat oldWidth;
+ glGetFloatv( GL_LINE_WIDTH, &oldWidth );
+
+ //Set line width
+ glLineWidth( width );
+
+ glPushMatrix();
+ glScaled(scale,scale,scale);
+ glTranslated(tx, ty, tz);
+ glTranslated( -0.75, 0, 0);
+ glBegin( GL_LINE_STRIP );
+ //Draw an "S" for sound
+ glVertex3d( 0, 0.3, 0);
+ glVertex3d( 0.4, 0, 0);
+ glVertex3d( 1.2, 0, 0);
+ glVertex3d( 1.5, 0.4, 0);
+ glVertex3d( 1.2, 0.8, 0);
+ glVertex3d( 0.3, 1.25, 0);
+ glVertex3d( 0.05, 1.5, 0);
+ glVertex3d( 0.25, 1.9, 0);
+ glVertex3d( 0.9, 2.0, 0);
+ glVertex3d( 1.4, 1.75, 0);
+ glEnd();
+ glPopMatrix();
+
+ glLineWidth( oldWidth );
+ glPopAttrib();
+}
+
+//=============================================================================
+// GLExt::drawCross
+//=============================================================================
+// Description: Comment
+//
+// Parameters: (double scale, double tx, double ty, double tz, float width)
+//
+// Return: void
+//
+//=============================================================================
+void GLExt::drawCross(double scale, double tx, double ty, double tz, float width)
+{
+ glPushAttrib( GL_CURRENT_BIT | GL_LINE_BIT | GL_POLYGON_BIT );
+ //Store old line width
+ GLfloat oldWidth;
+ glGetFloatv( GL_LINE_WIDTH, &oldWidth );
+
+ //Set line width
+ glLineWidth( width );
+
+ glPushMatrix();
+ glScaled( scale, scale, scale );
+ glTranslated( tx, ty, tz );
+ glBegin( GL_LINES );
+ glVertex3d( -1, 0, 0 );
+ glVertex3d( 1, 0, 0 );
+
+ glVertex3d( 0, 1, 0 );
+ glVertex3d( 0, -1, 0 );
+
+ glVertex3d( 0, 0, 1 );
+ glVertex3d( 0, 0, -1 );
+ glEnd();
+ glPopMatrix();
+
+ glLineWidth( oldWidth );
+ glPopAttrib();
+}
+
+//=============================================================================
+// GLExt::drawLBolt
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( double scale, double tx, double ty, double tz, float width )
+//
+// Return: void
+//
+//=============================================================================
+void GLExt::drawLBolt( double scale, double tx, double ty, double tz, float width )
+{
+ glPushAttrib( GL_CURRENT_BIT | GL_LINE_BIT | GL_POLYGON_BIT );
+ //Store old line width
+ GLfloat oldWidth;
+ glGetFloatv( GL_LINE_WIDTH, &oldWidth );
+
+ //Set line width
+ glLineWidth( width );
+
+ glPushMatrix();
+ glScaled(scale,scale,scale);
+ glTranslated(tx, ty, tz);
+ glBegin( GL_LINE_STRIP );
+ glVertex3d( 0, 0, 0);
+ glVertex3d( 0.5, 0.8, 0);
+ glVertex3d( -0.2, 1.4, 0);
+ glVertex3d( 0, 2.2, 0);
+ glVertex3d( -0.5, 1.4, 0);
+ glVertex3d( 0.2, 0.8, 0);
+ glVertex3d( 0, 0, 0 );
+ glEnd();
+ glPopMatrix();
+
+ glLineWidth( oldWidth );
+ glPopAttrib();
+}
+
+//=============================================================================
+// GLExt::drawI
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( double scale, double tx, double ty, double tz, float width )
+//
+// Return: void
+//
+//=============================================================================
+void GLExt::drawI( double scale, double tx, double ty, double tz, float width )
+{
+ glPushAttrib( GL_CURRENT_BIT | GL_LINE_BIT | GL_POLYGON_BIT );
+ //Store old line width
+ GLfloat oldWidth;
+ glGetFloatv( GL_LINE_WIDTH, &oldWidth );
+
+ //Set line width
+ glLineWidth( width );
+
+ glPushMatrix();
+ glScaled(scale,scale,scale);
+ glTranslated(tx, ty, tz);
+ glBegin( GL_LINE_STRIP );
+ glVertex3d( -0.6, 2, 0);
+ glVertex3d( 0.6, 2, 0);
+ glVertex3d( 0, 2, 0);
+ glVertex3d( 0, 0, 0);
+ glVertex3d( -0.6, 0, 0);
+ glVertex3d( 0.6, 0, 0);
+ glEnd();
+ glPopMatrix();
+
+ glLineWidth( oldWidth );
+ glPopAttrib();
+}
+
+//=============================================================================
+// GLExt::drawW
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( double scale, double tx, double ty, double tz, float width )
+//
+// Return: void
+//
+//=============================================================================
+void GLExt::drawW( double scale, double tx, double ty, double tz, float width )
+{
+ glPushAttrib( GL_CURRENT_BIT | GL_LINE_BIT | GL_POLYGON_BIT );
+ //Store old line width
+ GLfloat oldWidth;
+ glGetFloatv( GL_LINE_WIDTH, &oldWidth );
+
+ //Set line width
+ glLineWidth( width );
+
+ glPushMatrix();
+ glScaled(scale,scale,scale);
+ glTranslated(tx, ty, tz);
+ glBegin( GL_LINE_STRIP );
+ glVertex3d( -1.0, 2.0, 0);
+ glVertex3d( -0.5, 0, 0);
+ glVertex3d( 0, 1.5, 0);
+ glVertex3d( 0.5, 0, 0);
+ glVertex3d( 1.0, 2.0, 0);
+ glEnd();
+ glPopMatrix();
+
+ glLineWidth( oldWidth );
+ glPopAttrib();
+}
+
+//=============================================================================
+// GLExt::drawM
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( double scale, double tx, double ty, double tz, float width )
+//
+// Return: void
+//
+//=============================================================================
+void GLExt::drawM( double scale, double tx, double ty, double tz, float width )
+{
+ glPushAttrib( GL_CURRENT_BIT | GL_LINE_BIT | GL_POLYGON_BIT );
+ //Store old line width
+ GLfloat oldWidth;
+ glGetFloatv( GL_LINE_WIDTH, &oldWidth );
+
+ //Set line width
+ glLineWidth( width );
+
+ glPushMatrix();
+ glScaled(scale,scale,scale);
+ glTranslated(tx, ty, tz);
+ glBegin( GL_LINE_STRIP );
+ glVertex3d( -1.0, 0, 0);
+ glVertex3d( -0.5, 2.0, 0);
+ glVertex3d( 0, 0.5, 0);
+ glVertex3d( 0.5, 2.0, 0);
+ glVertex3d( 1.0, 0, 0);
+ glEnd();
+ glPopMatrix();
+
+ glLineWidth( oldWidth );
+ glPopAttrib();
+}
+
+//=============================================================================
+// GLExt::drawC
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( double scale, double tx, double ty, double tz, float width )
+//
+// Return: void
+//
+//=============================================================================
+void GLExt::drawC( double scale, double tx, double ty, double tz, float width )
+{
+ glPushAttrib( GL_CURRENT_BIT | GL_LINE_BIT | GL_POLYGON_BIT );
+ //Store old line width
+ GLfloat oldWidth;
+ glGetFloatv( GL_LINE_WIDTH, &oldWidth );
+
+ //Set line width
+ glLineWidth( width );
+
+ glPushMatrix();
+ glScaled(scale,scale,scale);
+ glTranslated(tx, ty, tz);
+ glBegin( GL_LINE_STRIP );
+ //Draw an "C" for carStart
+ glVertex3d( 0.7, 0.5, 0);
+ glVertex3d( 0.35, 0, 0);
+ glVertex3d( -0.35, 0, 0);
+ glVertex3d( -0.7, 0.5, 0);
+ glVertex3d( -0.7, 1.5, 0);
+ glVertex3d( -0.35, 2.0, 0);
+ glVertex3d( 0.35, 2.0, 0);
+ glVertex3d( 0.7, 1.5, 0);
+ glEnd();
+ glPopMatrix();
+
+ glLineWidth( oldWidth );
+ glPopAttrib();
+}
+
+//=============================================================================
+// GLExt::drawO
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( double scale, double tx, double ty, double tz, float width )
+//
+// Return: void
+//
+//=============================================================================
+void GLExt::drawO( double scale, double tx, double ty, double tz, float width )
+{
+ scale = 100.0f;
+
+ glPushAttrib( GL_CURRENT_BIT | GL_LINE_BIT | GL_POLYGON_BIT );
+ //Store old line width
+ GLfloat oldWidth;
+ glGetFloatv( GL_LINE_WIDTH, &oldWidth );
+
+ //Set line width
+ glLineWidth( width );
+
+ glPushMatrix();
+ glTranslated(tx, ty, tz);
+ glScaled(scale,scale,scale);
+ glBegin( GL_LINE_STRIP );
+ //Draw an "O"
+ glVertex3d( 0.7, 0.5, 0);
+ glVertex3d( 0, 0, 0);
+ glVertex3d( -0.7, 0.5, 0);
+ glVertex3d( -0.7, 1.5, 0);
+ glVertex3d( 0, 2.0, 0);
+ glVertex3d( 0.7, 1.5, 0);
+ glVertex3d( 0.7, 0.5, 0);
+ glEnd();
+ glPopMatrix();
+
+ glLineWidth( oldWidth );
+ glPopAttrib();
+}
+
diff --git a/tools/globalcode/utility/GLExt.h b/tools/globalcode/utility/GLExt.h
new file mode 100644
index 0000000..ae62a4f
--- /dev/null
+++ b/tools/globalcode/utility/GLExt.h
@@ -0,0 +1,191 @@
+#ifndef _GLEXT_H
+#define _GLEXT_H
+//-----------------------------------------------------------------------------
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// GLExt.h
+//
+// Description: Functions that do drawing using the OpenGL API.
+//
+// Modification History:
+// + Created Aug 21, 2001 -- bkusy
+// + grossly modified by Cary Brisebois
+//-----------------------------------------------------------------------------
+
+//----------------------------------------
+// System Includes
+//----------------------------------------
+
+//----------------------------------------
+// Project Includes
+//----------------------------------------
+
+//----------------------------------------
+// Forward References
+//----------------------------------------
+class MPoint;
+
+//----------------------------------------
+// Constants, Typedefs and Statics
+//----------------------------------------
+
+class GLExt
+{
+public:
+ static void drawCamera3D( double scale, double tx = 0.0f,
+ double ty = 0.0f,
+ double tz = 0.0f,
+ float width = 1.0f );
+
+ static void drawCrossHair3D( double scale, double tx = 0.0f,
+ double ty = 0.0f,
+ double tz = 0.0f,
+ float width = 1.0f );
+
+ static void drawCrossHair3D( double scale,
+ const MPoint& p,
+ float width = 1.0f );
+
+
+ static void drawPyramid( double scale, double tx = 0.0f,
+ double ty = 0.0f,
+ double tz = 0.0f,
+ float width = 1.0f );
+
+ static void drawPyramid( double scale,
+ const MPoint& p0,
+ float width = 1.0f );
+
+ static void drawLine( double x0, double y0, double z0,
+ double x1, double y1, double z1,
+ float width = 1.0f );
+
+ static void drawLine( const MPoint& p0,
+ const MPoint& p1,
+ float width = 1.0f );
+
+ static void drawArrow( const MPoint& p0,
+ const MPoint& p1,
+ float width = 1.0f,
+ float scale = 6.0f );
+
+ static void drawBox( double x0, double y0, double z0,
+ double x1, double y1, double z1,
+ float width = 1.0f );
+
+ static void drawBox( const MPoint& p0,
+ const MPoint& p1,
+ float width = 1.0f );
+
+ static void drawSphere( double scale, double tx = 0,
+ double ty = 0, double tz = 0,
+ float width = 1.0f );
+
+ static void drawSphere( double scale,
+ const MPoint& p,
+ float width = 1.0f );
+
+ static void drawXZPlane( double xscale,
+ double yscale,
+ double zscale,
+ double x0,
+ double z0,
+ double x1,
+ double z1,
+ double y,
+ float width = 1.0f
+ );
+
+ static void drawXZPlane( double xscale,
+ double yscale,
+ double zscale,
+ const MPoint& v0,
+ const MPoint& v1,
+ float width = 1.0f
+ );
+ static void drawP( double scale,
+ double tx = 0,
+ double ty = 0,
+ double tz = 0,
+ float width = 1.0f );
+
+ static void drawStickMan( double scale,
+ double tx = 0,
+ double ty = 0,
+ double tz = 0,
+ float width = 1.0f );
+
+ static void drawCar( double scale,
+ double tx = 0,
+ double ty = 0,
+ double tz = 0,
+ float width = 1.0f );
+
+ static void drawA( double scale,
+ double tx = 0,
+ double ty = 0,
+ double tz = 0,
+ float width = 1.0f );
+
+ static void drawD( double scale,
+ double tx = 0,
+ double ty = 0,
+ double tz = 0,
+ float width = 1.0f );
+
+ static void drawE( double scale,
+ double tx = 0,
+ double ty = 0,
+ double tz = 0,
+ float width = 1.0f );
+
+ static void drawS( double scale,
+ double tx = 0,
+ double ty = 0,
+ double tz = 0,
+ float width = 1.0f );
+
+ static void drawCross( double scale,
+ double tx = 0,
+ double ty = 0,
+ double tz = 0,
+ float width = 1.0f );
+
+ static void drawLBolt( double scale,
+ double tx = 0,
+ double ty = 0,
+ double tz = 0,
+ float width = 1.0f );
+
+ static void drawI( double scale,
+ double tx = 0,
+ double ty = 0,
+ double tz = 0,
+ float width = 1.0f );
+
+ static void drawW( double scale,
+ double tx = 0,
+ double ty = 0,
+ double tz = 0,
+ float width = 1.0f );
+
+ static void drawM( double scale,
+ double tx = 0,
+ double ty = 0,
+ double tz = 0,
+ float width = 1.0f );
+
+ static void drawC( double scale,
+ double tx = 0,
+ double ty = 0,
+ double tz = 0,
+ float width = 1.0f );
+
+ static void drawO( double scale,
+ double tx = 0,
+ double ty = 0,
+ double tz = 0,
+ float width = 1.0f );
+};
+
+#endif
diff --git a/tools/globalcode/utility/MExt.cpp b/tools/globalcode/utility/MExt.cpp
new file mode 100644
index 0000000..6523859
--- /dev/null
+++ b/tools/globalcode/utility/MExt.cpp
@@ -0,0 +1,2030 @@
+//-----------------------------------------------------------------------------
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// MExt.cpp
+//
+// Description: Functions that extend the Maya API to perform other common
+// tasks.
+//
+// Modification History:
+// + Created Aug 21, 2001 -- bkusy
+//-----------------------------------------------------------------------------
+#include "precompiled/PCH.h"
+
+//----------------------------------------
+// System Includes
+//----------------------------------------
+//#include <windows.h>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <math.h>
+
+/* Using precompiled headers
+#include <maya/M3dView.h>
+#include <maya/MArgList.h>
+#include <maya/MDagPath.h>
+#include <maya/MDoubleArray.h>
+#include <maya/MDGModifier.h>
+#include <maya/MDoubleArray.h>
+#include <maya/MGlobal.h>
+#include <maya/MFnDagNode.h>
+#include <maya/MFnData.h>
+#include <maya/MFnDependencyNode.h>
+#include <maya/MFnDoubleArrayData.h>
+#include <maya/MFnMatrixData.h>
+#include <maya/MFnTransform.h>
+#include <maya/MFnTypedAttribute.h>
+#include <maya/MItDag.h>
+#include <maya/MItSelectionList.h>
+#include <maya/MMatrix.h>
+#include <maya/MObject.h>
+#include <maya/MPlug.h>
+#include <maya/MPlugArray.h>
+#include <maya/MPoint.h>
+#include <maya/MSelectionList.h>
+#include <maya/MStatus.h>
+#include <maya/MString.h>
+#include <maya/MTransformationMatrix.h>
+#include <maya/MTypeId.h>
+#include <maya/MVector.h>
+*/
+
+//----------------------------------------
+// Project Includes
+//----------------------------------------
+#include "MExt.h"
+#include "util.h"
+
+//----------------------------------------
+// Constants, Typedefs and Statics
+//----------------------------------------
+static const double EPSILON = 0.00001;
+static const int SCRATCHPAD_SIZE = 256;
+static char scratchpad[ SCRATCHPAD_SIZE + 1 ];
+
+
+//-----------------------------------------------------------------------------
+// G e t S c a l e d
+//
+// Synopsis: Retrieves an attribute that is first scaled by the scale in
+// the node's parenting transform.
+//
+// Parameters: vertex - reference parameter to receive scaled attribute.
+// node - the node the attribute is on.
+// attr - the attribute to retrieve.
+//
+// Returns: The status of the request, hopefully MS::kSuccess.
+//
+// Constraints: This method only applies the scale that is stored in the
+// immediate parent of the node. Prior parenting tranforms have
+// no effect.
+//-----------------------------------------------------------------------------
+void MExt::Attr::GetScaled( MPoint* vertex,
+ const MObject& node,
+ const MObject& attr
+ )
+{
+ MStatus status;
+
+ //
+ // Get the nodes parenting transform.
+ //
+ MFnDagNode fnNode( node, &status );
+ assert( status );
+
+ MObject transform = fnNode.parent( 0, &status );
+ assert( status );
+
+ MFnTransform fnTransform( transform, &status );
+ assert( status );
+
+ //
+ // Get the scale in the parenting transform.
+ //
+ double scale[3];
+ status = fnTransform.getScale( scale );
+ assert( status );
+
+ //
+ // Get the attribute.
+ //
+ Get( vertex, node, attr );
+
+ //
+ // Scale the attribute.
+ //
+ vertex->x *= scale[0];
+ vertex->y *= scale[1];
+ vertex->z *= scale[2];
+}
+
+//-----------------------------------------------------------------------------
+// S e t S c a l e d
+//
+// Synopsis: Sets the attribute after taking into account the scale set in
+// the immediate parenting transform. If the attribute initially
+// has a value of (10,10,10) and a scaling vector of
+// (0.5, 2.0, 0.5) is in the parenting transform. The attribute
+// will be stored as (20,5,20) so that it will reflect the
+// original value when the attribute is retrieved through the
+// transform at a later time.
+//
+// Parameters: vertex - the vertex values to set the attribute to.
+// node - the node to set the attribute on.
+// attr - the attribute to set.
+//
+// Returns: NOTHING
+//
+// Constraints: Only the scaling in the immediate parenting transform is taken
+// into account.
+//
+//-----------------------------------------------------------------------------
+void MExt::Attr::SetScaled( const MPoint& vertex,
+ MObject& node,
+ MObject& attr
+ )
+{
+ MStatus status;
+
+ //
+ // Get the nodes parenting transform.
+ //
+ MFnDagNode fnNode( node, &status );
+ assert( status );
+
+ MObject transform = fnNode.parent( 0, &status );
+ assert( status );
+
+ MFnTransform fnTransform( transform, &status );
+ assert( status );
+
+ //
+ // Get the scale in the parenting transform.
+ //
+ double scale[3];
+ status = fnTransform.getScale( scale );
+ assert( status );
+
+ //
+ // Create the "unscaled" vertex.
+ //
+ MPoint scaledVertex = vertex;
+ scaledVertex.x = scaledVertex.x / scale[0];
+ scaledVertex.y = scaledVertex.y / scale[1];
+ scaledVertex.z = scaledVertex.z / scale[2];
+
+ Set( scaledVertex, node, attr );
+}
+
+//-----------------------------------------------------------------------------
+// S e t S c a l e d
+//
+// Synopsis: Sets the attribute after taking into account the scale set in
+// the immediate parenting transform. If the attribute initially
+// has a value of (10,10,10) and a scaling vector of
+// (0.5, 2.0, 0.5) is in the parenting transform. The attribute
+// will be stored as (20,5,20) so that it will reflect the
+// original value when the attribute is retrieved through the
+// transform at a later time.
+//
+// Parameters: vertex - the vertex values to set the attribute to.
+// node - the node to set the attribute on.
+// attr - the name of the attribute.
+//
+// Returns: NOTHING
+//
+// Constraints: Only the scaling in the immediate parenting transform is taken
+// into account.
+//
+//-----------------------------------------------------------------------------
+void MExt::Attr::SetScaled( const MPoint& vertex,
+ MObject& node,
+ const MString& attr
+ )
+{
+ MStatus status;
+
+ //
+ // Get the attribute object that corresponds to the named attribute.
+ //
+ MFnDagNode fnNode( node, &status );
+ assert( status );
+
+ MPlug plug = fnNode.findPlug( attr, &status );
+ assert( status );
+
+ SetScaled( vertex, node, plug.attribute() );
+}
+
+//-----------------------------------------------------------------------------
+// O p t i o n P a r s e r : : O p t i o n P a r s e r
+//
+// Synopsis: Constructor
+//
+// Parameters: args - the MArgList passed into functions like doIt();
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+MExt::OptionParser::OptionParser( const char* command, const MArgList& args ) :
+ m_argc( 0 ),
+ m_argv( 0 ),
+ m_opt( 0 )
+{
+ assert( command );
+
+ typedef char* charPointer;
+
+ //
+ // Create our simultated argument environment. We add one to m_argc because
+ // we are inserting the command name as well.
+ //
+ m_argc = args.length() + 1;
+ m_argv = new charPointer[ m_argc ];
+ assert( m_argv );
+
+ //
+ // Copy in the command name.
+ //
+ m_argv[0] = new char[ strlen( command ) + 1 ];
+ assert( m_argv[0] );
+ strcpy( m_argv[0], command );
+
+ //
+ // Copy in the arguments from argList.
+ //
+ int i;
+ for ( i = 1; i < m_argc; i++ )
+ {
+ MString arg;
+ args.get( i - 1, arg );
+ m_argv[i] = new char[ strlen( arg.asChar() ) + 1 ];
+ assert( m_argv[i] );
+ strcpy( m_argv[i], arg.asChar() );
+ }
+
+ //
+ // Initialize the parser.
+ //
+ util_getopt_init();
+}
+
+//-----------------------------------------------------------------------------
+// O p t i o n P a r s e r : : ~ O p t i o n P a r s e r
+//
+// Synopsis: Destructor
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+MExt::OptionParser::~OptionParser()
+{
+ if ( m_argv )
+ {
+ int i;
+ for ( i = 0; i < m_argc; i++ )
+ {
+ if ( m_argv[i] )
+ {
+ delete m_argv[i];
+ }
+ }
+
+ delete m_argv;
+ }
+
+ m_argc = 0;
+
+ if ( m_opt )
+ {
+ delete m_opt;
+ m_opt = 0;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// O p t i o n P a r s e r : : s e t O p t i o n s
+//
+// Synopsis: Specify the options that will be parsed.
+//
+// Parameters: optionSpec - the specification string. eg. "hgu:t:" would
+// specify two boolean flags, "h" and "g" ( they
+// do not take arguments ), and two argument flags,
+// "u" and "t", that take arguments. Flags that
+// take arguments must be followed by a ":".
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void MExt::OptionParser::setOptions( const char* optionSpec )
+{
+ int len = strlen( optionSpec ) + 1;
+ m_opt = new char[ len + 1 ];
+ assert( m_opt );
+
+ strncpy( m_opt, optionSpec, len );
+}
+
+//-----------------------------------------------------------------------------
+// O p t i o n P a r s e r : : n e x t O p t i o n
+//
+// Synopsis: Get the next option.
+//
+// Parameters: NONE
+//
+// Returns: The character flag for the next option or -1 if no more
+// options.
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+int MExt::OptionParser::nextOption()
+{
+ int result = util_getopt( m_argc, m_argv, m_opt );
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+// O p t i o n P a r s e r : : g e t A r g
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+MString MExt::OptionParser::getArg()
+{
+ MString result( util_optarg );
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+// O p t i o n V a r : : G e t
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+bool MExt::OptionVar::Get( char* buffer, unsigned int buffer_size, const char* symbol )
+{
+ bool doesExist = false;
+
+ MString command = "optionVar -exists ";
+ command += symbol;
+
+ int exists;
+ MGlobal::executeCommand( command, exists );
+
+ if ( exists )
+ {
+ command = "optionVar -query ";
+ command += symbol;
+
+ MString result;
+ MGlobal::executeCommand( command, result );
+
+ assert( result.length() < buffer_size );
+ strncpy( buffer, result.asChar(), buffer_size );
+
+ doesExist = true;
+ }
+
+ return doesExist;
+}
+
+
+//-----------------------------------------------------------------------------
+// O p t i o n V a r : : S e t
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void MExt::OptionVar::Set( const char* buffer, const char* symbol )
+{
+ MString command;
+ command = "optionVar -stringValue ";
+ command += symbol;
+ command += " \"";
+ command += buffer;
+ command += "\"";
+
+ MGlobal::executeCommand( command );
+}
+
+//-----------------------------------------------------------------------------
+// A d d C h i l d
+//
+// Synopsis: Make a locator node the child of another by parenting the transforms.
+//
+// Parameters: parentLocatorNode - locator node to be the parent
+// childLocatorNode - locator node to be the child
+//
+// Returns: NOTHING
+//
+// Constraints: Must both have transforms.
+//
+//-----------------------------------------------------------------------------
+void MExt::AddChild( MObject& parentLocatorNode, MObject& childLocatorNode )
+{
+// assert( parentLocatorNode.apiType() == MFn::kLocator );
+// assert( childLocatorNode.apiType() == MFn::kLocator );
+
+ //Get the transform of the parent node
+ MFnDagNode fnDag( parentLocatorNode );
+ MObject parentTransform = fnDag.parent( 0 );
+
+ //Get teh transform of the child node.
+ fnDag.setObject( childLocatorNode );
+ MObject childTransform = fnDag.parent( 0 );
+
+ //Parent the fence to the wall
+ fnDag.setObject( parentTransform );
+ fnDag.addChild( childTransform );
+}
+
+//-----------------------------------------------------------------------------
+// C o n n e c t
+//
+// Synopsis: Connect two nodes via the specified attributes.
+//
+// Parameters: node - the source node.
+// attr - the source attribute.
+// otherNode - the destination node.
+// otherAttr - the destination attribute.
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void MExt::Connect( MObject& node,
+ MObject& attr,
+ MObject& otherNode,
+ MObject& otherAttr
+ )
+{
+ MStatus status;
+
+ MDGModifier modifier;
+ status = modifier.connect( node, attr, otherNode, otherAttr );
+ assert( status );
+
+ status = modifier.doIt();
+ if ( !status ) MGlobal::displayError( status.errorString() );
+ assert( status );
+}
+
+void MExt::Connect( MObject& node,
+ const char* attr,
+ MObject& otherNode,
+ const char* otherAttr
+ )
+{
+ MStatus status;
+
+ MFnDependencyNode fnNode;
+
+ fnNode.setObject( node );
+ MPlug nodePlug = fnNode.findPlug( MString( attr ), &status );
+ assert( status );
+
+
+ fnNode.setObject( otherNode );
+ MPlug otherNodePlug = fnNode.findPlug( MString( otherAttr ), &status );
+ assert( status );
+
+ MDGModifier modifier;
+ status = modifier.connect( node, nodePlug.attribute(), otherNode, otherNodePlug.attribute() );
+ assert( status );
+
+ status = modifier.doIt();
+ if ( !status ) MGlobal::displayError( status.errorString() );
+ assert( status );
+}
+
+//-----------------------------------------------------------------------------
+// C r e a t e N o d e
+//
+// Synopsis:
+//
+// Parameters: node - reference parameter to receive node MObject.
+// transform - reference parameter to receive the parenting
+// transform.
+// type - the type of node to create.
+// name - the name to assign to the node. If NULL default
+// name is used.
+// group - MObject representing the group under which to
+// attach the new node. If NULL then the new node
+// is attached at the DAG root.
+//
+// Returns: the status of the request -- hopefully MS::kSuccess.
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void MExt::CreateNode( MObject* node,
+ MObject* transform,
+ const MString& type,
+ const MString* name,
+ const MObject& group
+ )
+{
+ MStatus status;
+
+ //
+ // Determine names for the nodes. This must be done before the
+ // nodes are created so as to avoid conflicting with the default
+ // names that Maya will assign them prior to us renaming them.
+ //
+ MString nodeName = type;
+ if ( name ) nodeName = *name;
+ MString transformName = ( "TForm" + nodeName );
+
+ MakeNameUnique( &nodeName, nodeName, group );
+ MakeNameUnique( &transformName, transformName, group );
+
+ //
+ // Create the transform.
+ //
+ MFnTransform fnTransform;
+ fnTransform.create( MObject::kNullObj, &status );
+ assert( status );
+
+ //
+ // Create the node under the transform.
+ //
+ MFnDagNode fnNode;
+ fnNode.create( type, fnTransform.object(), &status );
+ assert( status );
+
+ if ( group != MObject::kNullObj )
+ {
+ //
+ // Place the new node under the group node.
+ //
+ MFnTransform fnGroup( group, &status );
+ assert( status );
+
+ status = fnGroup.addChild( fnTransform.object() );
+ assert( status );
+ }
+
+ //
+ // Name the nodes.
+ //
+ fnTransform.setName( transformName, &status );
+ assert( status );
+
+ fnNode.setName( nodeName, &status );
+ assert( status );
+
+ //
+ // Return the node and transform objects in the reference parameters.
+ //
+ if ( transform )
+ {
+ *transform = fnTransform.object();
+ }
+
+ if ( node )
+ {
+ *node = fnNode.object();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// C r e a t e N o d e
+//
+// Synopsis:
+//
+// Parameters: node - reference parameter to receive node MObject.
+// transform - reference parameter to receive the parenting
+// transform.
+// type - the type of node to create.
+// name - the name to assign to the node. If NULL default
+// name is used.
+// group - MObject representing the group under which to
+// attach the new node. If NULL then the new node
+// is attached at the DAG root.
+//
+// Returns: the status of the request -- hopefully MS::kSuccess.
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void MExt::CreateNode( MObject& node,
+ MObject& transform,
+ const MString& type,
+ const MString* name,
+ const MObject& group
+ )
+{
+ MStatus status;
+
+ //
+ // Determine names for the nodes. This must be done before the
+ // nodes are created so as to avoid conflicting with the default
+ // names that Maya will assign them prior to us renaming them.
+ //
+ MString nodeName = type;
+ if ( name ) nodeName = *name;
+ MString transformName = ( "TForm" + nodeName );
+
+ MakeNameUnique( &nodeName, nodeName, group );
+ MakeNameUnique( &transformName, transformName, group );
+
+ //
+ // Create the transform.
+ //
+ MFnTransform fnTransform;
+ fnTransform.create( MObject::kNullObj, &status );
+ assert( status );
+
+ //
+ // Create the node under the transform.
+ //
+ MFnDagNode fnNode;
+ fnNode.create( type, fnTransform.object(), &status );
+ assert( status );
+
+ if ( group != MObject::kNullObj )
+ {
+ //
+ // Place the new node under the group node.
+ //
+ MFnTransform fnGroup( group, &status );
+ assert( status );
+
+ status = fnGroup.addChild( fnTransform.object() );
+ assert( status );
+ }
+
+ //
+ // Name the nodes.
+ //
+ fnTransform.setName( transformName, &status );
+ assert( status );
+
+ fnNode.setName( nodeName, &status );
+ assert( status );
+
+ //
+ // Return the node and transform objects in the reference parameters.
+ //
+ transform = fnTransform.object();
+ node = fnNode.object();
+}
+
+//-----------------------------------------------------------------------------
+// C r e a t e V e r t e x A t t r i b u t e
+//
+// Synopsis: Intended for use within the initialize() method for a node
+// class. Creates a vertex attribute using a double array.
+//
+// Parameters: name - the name of the attribute.
+// breif_name - the brief name of the attribute.
+//
+// Returns: the attribute object.
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void MExt::CreateVertexAttribute( MObject* attr,
+ const char* name,
+ const char* briefName
+ )
+{
+ MStatus status;
+
+ MDoubleArray doubleArray;
+ MFnDoubleArrayData doubleArrayData;
+ MObject defaultVertex = doubleArrayData.create( doubleArray, &status );
+ assert( status );
+
+ MFnTypedAttribute fnAttribute;
+ *attr = fnAttribute.create( name,
+ briefName,
+ MFnData::kDoubleArray,
+ defaultVertex,
+ &status
+ );
+ assert( status );
+}
+
+//=============================================================================
+// MExt::DeleteNode
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( MObject& node, bool deleteParent )
+//
+// Return: void
+//
+//=============================================================================
+void MExt::DeleteNode( MObject& node, bool deleteParent )
+{
+ //Get the parent and delete it too if it's a transform and the bool says so.
+
+ MStatus status;
+ MObject parent;
+
+ if ( deleteParent )
+ {
+ //Get the parent please.
+ MFnDagNode fnDag( node );
+ parent = fnDag.parent( 0, &status );
+ assert( status );
+ }
+
+ //Delete this node
+ MGlobal::deleteNode( node );
+
+ if ( deleteParent )
+ {
+ //Delete the parent.
+ MGlobal::deleteNode( parent );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// D i s c o n n e c t A l l
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void MExt::DisconnectAll( MObject& node, MObject& attr )
+{
+ MStatus status;
+
+ MFnDependencyNode fnNode( node, &status );
+ assert( status );
+
+ //
+ // Get the plug for the attribute to be disconnected.
+ //
+ MPlug plug = fnNode.findPlug( attr, &status );
+ assert( status );
+
+ //
+ // Find all connections and disconnect them.
+ //
+ MDGModifier modifier;
+ MPlugArray sources;
+ MPlugArray targets;
+ MExt::ResolveConnections( &sources, &targets, plug, true, true );
+
+ unsigned int count = sources.length();
+ unsigned int i;
+
+ for ( i = 0; i < count; i++ )
+ {
+ status = modifier.disconnect( sources[i], targets[i] );
+ assert( status );
+ }
+
+ status = modifier.doIt();
+ assert( status );
+}
+
+void MExt::DisconnectAll( MObject& node, const char* attrName )
+{
+ MStatus status;
+
+ MFnDependencyNode fnNode( node, &status );
+ assert( status );
+
+ //
+ // Get the plug for the attribute to be disconnected.
+ //
+ MPlug plug = fnNode.findPlug( MString( attrName ), &status );
+ assert( status );
+
+ //
+ // Find all connections and disconnect them.
+ //
+ MDGModifier modifier;
+ MPlugArray sources;
+ MPlugArray targets;
+ MExt::ResolveConnections( &sources, &targets, plug, true, true );
+
+ unsigned int count = sources.length();
+ unsigned int i;
+
+ for ( i = 0; i < count; i++ )
+ {
+ status = modifier.disconnect( sources[i], targets[i] );
+ assert( status );
+ }
+
+ status = modifier.doIt();
+ assert( status );
+}
+
+//-----------------------------------------------------------------------------
+// D i s p l a y E r r o r
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+int MExt::DisplayError( const char* fmt, ... )
+{
+ va_list argp;
+ va_start( argp, fmt );
+ int size = _vsnprintf( scratchpad, SCRATCHPAD_SIZE, fmt, argp );
+ MGlobal::displayError( scratchpad );
+ return size;
+}
+
+//-----------------------------------------------------------------------------
+// D i s p l a y W a r n i n g
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+int MExt::DisplayWarning( const char* fmt, ... )
+{
+ va_list argp;
+ va_start( argp, fmt );
+ int size = _vsnprintf( scratchpad, SCRATCHPAD_SIZE, fmt, argp );
+ MGlobal::displayWarning( scratchpad );
+ return size;
+}
+
+//-----------------------------------------------------------------------------
+// D i s p l a y I n f o
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+int MExt::DisplayInfo( const char* fmt, ... )
+{
+ va_list argp;
+ va_start( argp, fmt );
+ int size = _vsnprintf( scratchpad, SCRATCHPAD_SIZE, fmt, argp );
+ MGlobal::displayInfo( scratchpad );
+ return size;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// F i l t e r S e l e c t i o n L i s t
+//
+// Synopsis: Filters the given source list for nodes of "typeName" and
+// places them in the filtered list. If transforms are in the
+// source list all their children are filtered as well.
+//
+// Parameters: filteredList - reference paremeter to receive the filtered
+// list.
+// typeName - the type name to check for.
+// sourceList - the list to filter.
+//
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void MExt::FilterSelectionList( MSelectionList* filteredList,
+ const MString& typeName,
+ const MSelectionList& sourceList
+ )
+{
+ assert( filteredList );
+
+ MItSelectionList it_source( sourceList );
+ while( ! it_source.isDone() )
+ {
+ MObject node;
+ it_source.getDependNode( node );
+
+ MFnDependencyNode fnNode;
+ fnNode.setObject( node );
+
+ if ( fnNode.typeName() == typeName )
+ {
+ filteredList->add( fnNode.object() );
+ }
+ else if ( strcmp( "transform" , fnNode.typeName().asChar() ) == 0 )
+ {
+ SelectNodesBelowRoot( filteredList, typeName, fnNode.object() );
+ }
+
+ it_source.next();
+ }
+}
+
+//=============================================================================
+// MExt::FindAllSkeletonRoots
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( MObjectArray* objects )
+//
+// Return: bool
+//
+//=============================================================================
+bool MExt::FindAllSkeletonRoots( MObjectArray* objects )
+{
+ MStatus status;
+ bool returnVal = false;
+
+ MItDag dagIt( MItDag::kDepthFirst, MFn::kTransform, &status );
+ assert( status );
+
+ while( !dagIt.isDone() )
+ {
+ MFnTransform fnTransform( dagIt.item() );
+
+ MPlug p3dBoolPlug = fnTransform.findPlug( MString("p3dBooleanAttributes"), &status );
+ if ( status )
+ {
+ //This has p3d info.
+ int value = 0;
+ p3dBoolPlug.getValue( value );
+
+ if ( value & 0x0002 ) //This is the skelton root bit... HACK
+ {
+ objects->append( fnTransform.object() );
+ returnVal = true;
+ }
+ }
+
+ dagIt.next();
+ }
+
+ return returnVal;
+}
+
+//=============================================================================
+// MExt::FindAllTransforms
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( MObjectArray* transforms, const MObject& root )
+//
+// Return: bool
+//
+//=============================================================================
+bool MExt::FindAllTransforms( MObjectArray* transforms, const MObject& root )
+{
+ bool returnVal = false;
+
+ MItDag dagIt( MItDag::kDepthFirst, MFn::kTransform );
+ MDagPath path;
+ MDagPath::getAPathTo( root, path );
+
+ dagIt.reset( path, MItDag::kDepthFirst, MFn::kTransform );
+
+ while ( !dagIt.isDone() )
+ {
+ transforms->append( dagIt.item() );
+ returnVal = true;
+
+ dagIt.next();
+ }
+
+ return returnVal;
+}
+
+//-----------------------------------------------------------------------------
+// F i n d D a g N o d e B y N a m e
+//
+// Synopsis: Find a node in the DAG using its name as the search key.
+//
+// Parameters: path - reference object to receive the path of the found
+// node.
+// name - the name to search for.
+// root - only search under this node.
+//
+// Returns: true if found, false otherwise.
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+bool MExt::FindDagNodeByName( MDagPath* path,
+ const MString& name,
+ const MObject& root
+ )
+{
+ MStatus status;
+
+ MItDag it_dag;
+ if ( root != MObject::kNullObj )
+ {
+ status = it_dag.reset( root );
+ if ( MS::kSuccess != status ) return false;
+ }
+
+ bool found = false;
+ while ( !found && !it_dag.isDone() )
+ {
+ MFnDependencyNode node( it_dag.item(), &status );
+ assert( status );
+ if ( name == node.name() )
+ {
+ found = true;
+ if ( path )
+ {
+ it_dag.getPath( *path );
+ }
+ }
+ it_dag.next();
+ }
+
+ return found;
+}
+
+//-----------------------------------------------------------------------------
+// F i n d D a g N o d e B y N a m e
+//
+// Synopsis: Find a node in the DAG using its name as the search key.
+//
+// Parameters: path - reference object to receive the path of the found
+// node.
+// name - the name to search for.
+// root - only search under the node named root.
+//
+// Returns: true if found, false otherwise.
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+bool MExt::FindDagNodeByName( MDagPath* path,
+ const MString& name,
+ const MString& root
+ )
+{
+ MDagPath myPath;
+ bool found = FindDagNodeByName( &myPath, root );
+ if ( found )
+ {
+ found = FindDagNodeByName( path, name, myPath.node() );
+ }
+
+ return found;
+}
+
+//-----------------------------------------------------------------------------
+// G e t W o r l d P o s i t i o n
+//
+// Synopsis: Retrieves the world position of the given node.
+//
+// Parameters: wp - reference parameter to receive the world positioin.
+// node - the node object to retrieve the world position of.
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void MExt::GetWorldPosition( MPoint* wp, const MObject& node )
+{
+ MStatus status;
+
+ MFnDependencyNode fnNode( node );
+
+ //
+ // Attempt to get the world matrix attribute.
+ //
+ MObject attrObject = fnNode.attribute( "worldMatrix", &status );
+ assert( status );
+
+ //
+ // Build the world matrix plug. Use the first element on the plug.
+ //
+ MPlug plug( const_cast<MObject&>(node), attrObject );
+ plug = plug.elementByLogicalIndex( 0, &status );
+ assert( status );
+
+ //
+ // Get the world matrix. We have to go through a few Maya layers on this
+ // one.
+ //
+ MObject matrixObject;
+ status = plug.getValue( matrixObject );
+ assert( status );
+
+ MFnMatrixData matrixData( matrixObject, &status );
+ assert( status );
+
+ MMatrix matrix = matrixData.matrix( &status );
+ assert( status );
+
+ //
+ // The translation vector of the matrix is our position.
+ //
+ wp->x = matrix( 3, 0 );
+ wp->y = matrix( 3, 1 );
+ wp->z = matrix( 3, 2 );
+}
+
+
+//-----------------------------------------------------------------------------
+// G e t W o r l d P o s i t i o n B e t w e e n
+//
+// Synopsis: Retrieves the world position of a point between the the given nodes.
+//
+// Parameters: node1 - The first node
+// node1 - The second node
+// betweenPoint - receives the point between the two nodes
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+MPoint MExt::GetWorldPositionBetween( MObject& node1, MObject& node2 )
+{
+ MVector newWPVect;
+ MPoint node1WP;
+ MPoint node2WP;
+
+ MExt::GetWorldPosition( &node1WP, node1 );
+ MExt::GetWorldPosition( &node2WP, node2 );
+
+ newWPVect = node2WP - node1WP;
+ newWPVect /= 2.0f;
+ newWPVect += node1WP;
+
+ MPoint newPoint( newWPVect );
+ return newPoint;
+}
+
+//=============================================================================
+// MExt::GetWorldMatrix
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( MObject& node )
+//
+// Return: MMatrix
+//
+//=============================================================================
+MMatrix MExt::GetWorldMatrix( MObject& node )
+{
+ MStatus status;
+
+ MFnDependencyNode fnNode( node );
+
+ //
+ // Attempt to get the world matrix attribute.
+ //
+ MObject attrObject = fnNode.attribute( "worldMatrix", &status );
+ assert( status );
+
+ //
+ // Build the world matrix plug. Use the first element on the plug.
+ //
+ MPlug plug( const_cast<MObject&>(node), attrObject );
+ plug = plug.elementByLogicalIndex( 0, &status );
+ assert( status );
+
+ //
+ // Get the world matrix. We have to go through a few Maya layers on this
+ // one.
+ //
+ MObject matrixObject;
+ status = plug.getValue( matrixObject );
+ assert( status );
+
+ MFnMatrixData matrixData( matrixObject, &status );
+ assert( status );
+
+ MMatrix matrix = matrixData.matrix( &status );
+ assert( status );
+
+ return matrix;
+}
+
+//-----------------------------------------------------------------------------
+// MExt : : I s C o n n e c t e d
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+bool MExt::IsConnected( MObject& node, const char* attr )
+{
+ MStatus status;
+ MFnDependencyNode fnNode;
+
+
+ fnNode.setObject( node );
+
+ MPlug plug = fnNode.findPlug( MString( attr ), &status );
+ assert( status );
+
+ return plug.isConnected();
+}
+
+bool MExt::IsConnected( MObject& node, MObject& attr )
+{
+ MStatus status;
+ MFnDependencyNode fnNode;
+
+
+ fnNode.setObject( node );
+
+ MPlug plug = fnNode.findPlug( attr, &status );
+ assert( status );
+
+ return plug.isConnected();
+}
+
+bool MExt::IsConnected( MPlug& plug1, MPlug& plug2 )
+{
+ MPlugArray plugArray;
+
+ plug1.connectedTo( plugArray, true, true );
+
+ unsigned int i;
+ for ( i = 0; i < plugArray.length(); ++i )
+ {
+ if ( plugArray[i] == plug2 )
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// M a k e N a m e U n i q u e
+//
+// Synopsis: Append numerical suffixes to a name to make it unique under
+// a specified root node.
+//
+// Parameters: unique - a reference parameter to receive the new unique name.
+// name - the original name.
+// root - the node under which the name must be unique.
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void MExt::MakeNameUnique( MString* unique,
+ const MString& name,
+ const MObject& root
+ )
+{
+ const int bufferSize = 256;
+
+ MString myName = name;
+ assert( myName.length() < bufferSize );
+
+ if ( FindDagNodeByName( 0, myName, root ) )
+ {
+ char buffer[ bufferSize ];
+ strncpy( buffer, myName.asChar(), bufferSize );
+
+ //
+ // Isolate the base name by removing any numerical suffixes.
+ //
+ char* suffix = const_cast<char*>(util_reverseSpan( buffer, "0123456789" ));
+ if ( suffix )
+ {
+ *suffix = '\0';
+ }
+
+ myName = buffer;
+ int isuffix = 0;
+ while( FindDagNodeByName( 0, myName, root ) )
+ {
+ isuffix++;
+ myName = buffer;
+ myName += isuffix;
+ }
+
+ }
+
+ *unique = myName;
+}
+
+//-----------------------------------------------------------------------------
+// M a k e N a m e U n i q u e
+//
+// Synopsis: Append numerical suffixes to a name to make it unique under
+// a specified root node.
+//
+// Parameters: unique - a reference parameter to receive the new unique name.
+// name - the original name.
+// root - name of the node under which the name must be unique.
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void MExt::MakeNameUnique( MString* unique,
+ const MString& name,
+ const MString& root
+ )
+{
+ MObject rootObject = MObject::kNullObj;
+ MDagPath path;
+ if ( FindDagNodeByName( &path, root ) )
+ {
+ rootObject = path.node();
+ }
+
+ MakeNameUnique( unique, name, rootObject );
+}
+
+//=============================================================================
+// MExt::MeshClickIntersect
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( short xClick, short yClick, MPoint& intersect, bool closest = true )
+//
+// Return: bool
+//
+//=============================================================================
+bool MExt::MeshClickIntersect( short xClick,
+ short yClick,
+ MPoint& intersect,
+ bool closest )
+{
+ //Get the mesh below the clicked point and find it's y height.
+ short xStart, xEnd, yStart, yEnd;
+
+ xStart = 0;
+ xEnd = M3dView::active3dView().portWidth();
+ yStart = M3dView::active3dView().portHeight();
+ yEnd = 0;
+
+ MGlobal::selectFromScreen( xStart,
+ yStart,
+ xEnd,
+ yEnd,
+ MGlobal::kReplaceList );
+
+ MSelectionList selectionList;
+
+ MGlobal::getActiveSelectionList( selectionList );
+
+ if ( selectionList.length() > 0 )
+ {
+ //Go through each selected object and see if the ray intersects it.
+ MItSelectionList selectIt( selectionList, MFn::kMesh );
+
+ MPoint nearClick, farClick;
+ M3dView activeView = M3dView::active3dView();
+ activeView.viewToWorld( xClick, yClick, nearClick, farClick );
+ MVector rayDir( MVector( farClick ) - MVector( nearClick ) );
+ MPointArray intersectPoints;
+ MDagPath objDag;
+
+ bool found = false;
+
+ MPoint resultPoint;
+
+ if ( closest )
+ {
+ resultPoint.x = 100000.0;
+ resultPoint.y = 100000.0;
+ resultPoint.z = 100000.0;
+ }
+ else
+ {
+ resultPoint.x = 0;
+ resultPoint.y = 0;
+ resultPoint.z = 0;
+ }
+
+ while ( !selectIt.isDone() )
+ {
+ selectIt.getDagPath( objDag );
+
+ MFnMesh mesh( objDag );
+
+ mesh.intersect( nearClick, rayDir, intersectPoints, 0.001f, MSpace::kWorld );
+
+ unsigned int i;
+ for ( i = 0; i < intersectPoints.length(); ++i )
+ {
+ //test each point...
+ if ( closest )
+ {
+ if ( intersectPoints[i].distanceTo(nearClick) < (resultPoint.distanceTo(nearClick) ) )
+ {
+ resultPoint = intersectPoints[i];
+ found = true;
+ }
+ }
+ else
+ {
+ if ( intersectPoints[i].distanceTo(nearClick) > (resultPoint.distanceTo(nearClick) ) )
+ {
+ resultPoint = intersectPoints[i];
+ found = true;
+ }
+ }
+ }
+
+ selectIt.next();
+ }
+
+ if ( found )
+ {
+ intersect = resultPoint;
+ MGlobal::clearSelectionList();
+ return true;
+ }
+ }
+
+ MGlobal::clearSelectionList();
+ return false;
+}
+
+//=============================================================================
+// MExt::MeshIntersectAlongVector
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( MPoint from, MPoint direction, MPoint& intersect, bool closest = true )
+//
+// Return: bool
+//
+//=============================================================================
+bool MExt::MeshIntersectAlongVector( MPoint from,
+ MPoint direction,
+ MPoint& intersect,
+ bool closest )
+{
+ MSelectionList selectionList;
+ selectionList.clear();
+
+ MItDag itDag(MItDag::kDepthFirst, MFn::kMesh );
+
+ while ( !itDag.isDone() )
+ {
+ MDagPath dagPath;
+ itDag.getPath( dagPath );
+
+ selectionList.add( dagPath );
+
+ itDag.next();
+ }
+
+ if ( selectionList.length() > 0 )
+ {
+ //Go through each selected object and see if the ray intersects it.
+ MItSelectionList selectIt( selectionList, MFn::kMesh );
+
+ MPointArray intersectPoints;
+ MDagPath objDag;
+
+ bool found = false;
+
+ MPoint resultPoint;
+
+ if ( closest )
+ {
+ resultPoint.x = 100000.0;
+ resultPoint.y = 100000.0;
+ resultPoint.z = 100000.0;
+ }
+ else
+ {
+ resultPoint.x = 0;
+ resultPoint.y = 0;
+ resultPoint.z = 0;
+ }
+
+ while ( !selectIt.isDone() )
+ {
+ selectIt.getDagPath( objDag );
+
+ MStatus status;
+
+ MFnMesh mesh( objDag, &status );
+ assert( status );
+
+
+ const char* name = mesh.name().asChar();
+
+ mesh.intersect( from, direction, intersectPoints, 0.001f, MSpace::kWorld );
+
+ unsigned int i;
+ for ( i = 0; i < intersectPoints.length(); ++i )
+ {
+ //test each point...
+ if ( closest )
+ {
+ if ( intersectPoints[i].distanceTo(from) < (resultPoint.distanceTo(from) ) )
+ {
+ resultPoint = intersectPoints[i];
+ found = true;
+ }
+ }
+ else
+ {
+ if ( intersectPoints[i].distanceTo(from) > (resultPoint.distanceTo(from) ) )
+ {
+ resultPoint = intersectPoints[i];
+ found = true;
+ }
+ }
+ }
+
+ selectIt.next();
+ }
+
+ if ( found )
+ {
+ intersect = resultPoint;
+ MGlobal::clearSelectionList();
+ return true;
+ }
+ }
+
+ MGlobal::clearSelectionList();
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// P l u g H a s C o n n e c t i o n
+//
+// Synopsis: Determines if there are any connections on the specified plug.
+//
+// Parameters: connectedNode - reference parameter to receive the associated
+// node for the first connection found.
+// plug - the plug to get the connections for.
+// asSrc - if true, retrieve connections where "plug" is
+// the source of the connection.
+// asDst - if true, retrieve connections where "plug" is
+// the target of the connection.
+//
+// Returns: true, if the plug has connections; false, otherwise
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+bool MExt::PlugHasConnection( MObject* connectedNode,
+ MPlug& plug,
+ bool asDst,
+ bool asSrc,
+ const char* type
+ )
+{
+ bool isOk = false;
+
+ MPlug myPlug;
+ isOk = PlugHasConnection( &myPlug, plug, asDst, asSrc, type );
+
+ if ( isOk )
+ {
+ if ( connectedNode ) *connectedNode = myPlug.node();
+ }
+
+ return isOk;
+}
+
+//-----------------------------------------------------------------------------
+// P l u g H a s C o n n e c t i o n
+//
+// Synopsis: Determines if there are any connections on the specified plug.
+//
+// Parameters: connectedPlug - reference parameter to receive the plug of
+// the first connection found.
+// plug - the plug to get the connections for.
+// asSrc - if true, retrieve connections where "plug" is
+// the source of the connection.
+// asDst - if true, retrieve connections where "plug" is
+// the target of the connection.
+//
+// Returns: true, if the plug has connections; false, otherwise
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+bool MExt::PlugHasConnection( MPlug* connectedPlug,
+ MPlug& plug,
+ bool asDst,
+ bool asSrc,
+ const char* type
+ )
+{
+ MPlugArray buffer;
+
+ if ( asSrc )
+ {
+ MPlugArray destinations;
+ ResolveConnections( &buffer, &destinations, plug, false, true );
+
+ unsigned int i;
+ for( i = 0; i < destinations.length(); i++ )
+ {
+ bool isOk = true;
+ if ( type )
+ {
+ MFnDependencyNode fnNode( destinations[i].node() );
+ if ( fnNode.typeName() != type )
+ {
+ isOk = false;
+ }
+ }
+
+ if ( isOk )
+ {
+ if ( connectedPlug ) *connectedPlug = destinations[i];
+ return true;
+ }
+ }
+ }
+
+ if ( asDst )
+ {
+ MPlugArray sources;
+ ResolveConnections( &sources, &buffer, plug, true, false );
+
+ unsigned int i;
+ for( i = 0; i < sources.length(); i++ )
+ {
+ bool isOk = true;
+ if ( type )
+ {
+ MFnDependencyNode fnNode( sources[i].node() );
+ if ( fnNode.typeName() != type )
+ {
+ isOk = false;
+ }
+ }
+
+ if ( isOk )
+ {
+ if ( connectedPlug ) *connectedPlug = sources[i];
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// R e s o l v e C o n n e c t i o n s
+//
+// Synopsis: Retrieves the plugs that are connected to this plug. This
+// will work on plugs that are associated with array as well as
+// non-array attributes.
+//
+// Parameters: sources - reference parameter to recieve list of
+// connection sources.
+// targets - reference parameter to recieve list of
+// connection targets.
+// plug - the plug to get the connections for.
+// asSrc - if true, retrieve connections where "plug" is
+// the source of the connection.
+// asDst - if true, retrieve connections where "plug" is
+// the target of the connection.
+//
+// Returns: true, if the plug has connections; false, otherwise
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void MExt::ResolveConnections( MPlugArray* sources,
+ MPlugArray* targets,
+ MPlug& plug,
+ bool asDst,
+ bool asSrc
+ )
+{
+ assert( sources );
+ assert( targets );
+
+ MStatus status;
+ MPlugArray myPlugs;
+ unsigned int count = 0;
+ unsigned int i = 0;
+
+ if ( plug.isArray() )
+ {
+ count = plug.numElements( &status );
+ assert( status );
+
+ for ( i = 0; i < count; i++ )
+ {
+ MPlug element = plug.elementByPhysicalIndex( i, &status );
+ assert( status );
+
+ if ( element.isConnected() )
+ {
+
+ MString name = element.name();
+ const char* dbg_name = name.asChar();
+
+ myPlugs.append( element );
+ }
+ }
+ }
+ else
+ {
+ myPlugs.append( plug );
+ }
+
+ sources->clear();
+ targets->clear();
+ count = myPlugs.length();
+ for ( i = 0; i < count; i++ )
+ {
+ MPlugArray connectedPlugs;
+
+ if ( asDst )
+ {
+ myPlugs[i].connectedTo( connectedPlugs, true, false, &status );
+ assert( status );
+
+ if ( connectedPlugs.length() > 0 )
+ {
+ sources->append( connectedPlugs[0] );
+ targets->append( myPlugs[i] );
+ }
+ }
+
+ if ( asSrc )
+ {
+ myPlugs[i].connectedTo( connectedPlugs, false, true, &status );
+ assert( status );
+
+ if ( connectedPlugs.length() > 0 )
+ {
+ sources->append( myPlugs[i] );
+ targets->append( connectedPlugs[0] );
+ }
+ }
+ }
+
+ assert( sources->length() == targets->length() );
+}
+
+//-----------------------------------------------------------------------------
+// S e l e c t N o d e s B e l o w R o o t
+//
+// Synopsis: Select nodes meeting the specified criteria and place them
+// in the provided selection list.
+//
+// Parameters: list - the list to receive the nodes.
+// typeId - the typeId of the node type to select.
+// root - the root of the subsection of the DAG to search.
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void MExt::SelectNodesBelowRoot( MSelectionList* list,
+ const MString& typeName,
+ const MObject& root,
+ MSelectionList* intersectionList
+ )
+{
+ assert( list );
+
+ MStatus status;
+
+ bool mergeWithExisting = true;
+
+ MItDag itor;
+
+ if ( root != MObject::kNullObj )
+ {
+ itor.reset( root );
+ }
+
+ while( ! itor.isDone() )
+ {
+ MFnDependencyNode fnNode;
+ fnNode.setObject( itor.item() );
+
+ if ( fnNode.typeName() == typeName )
+ {
+ bool doAdd = true;
+
+ if ( intersectionList )
+ {
+ MDagPath path;
+ status = MDagPath::getAPathTo( fnNode.object(), path );
+
+ //
+ // We only add the item if it is in the intersectionList.
+ //
+ if ( ! intersectionList->hasItem( path ) )
+ {
+ doAdd = false;
+ }
+ }
+
+ if ( doAdd )
+ {
+ list->add( fnNode.object(), mergeWithExisting );
+ }
+ }
+
+ itor.next();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// S e t W o r l d P o s i t i o n
+//
+// Synopsis: Sets the world position of the given node.
+//
+// Parameters: wp - the new world position.
+// node - the node for which to set the position.
+//
+// Returns: Hopefully MS::kSuccess, but other MS::????? errors will occur
+// if the object is not a suitable type of node.
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void MExt::SetWorldPosition( const MPoint& wp, const MObject& node )
+{
+ MStatus status;
+
+ MFnDependencyNode fnNode( node );
+
+ //
+ // Attempt to get the world matrix attribute.
+ //
+ MObject attrObject = fnNode.attribute( "worldMatrix", &status );
+ assert( status );
+
+ //
+ // Build the world matrix plug. Use the first element on the plug.
+ //
+ MPlug plug( const_cast<MObject&>(node), attrObject );
+ plug = plug.elementByLogicalIndex( 0, &status );
+ assert( status );
+
+ //
+ // Get the world matrix. We have to go through a few Maya layers on this
+ // one.
+ //
+ MObject matrixObject;
+ status = plug.getValue( matrixObject );
+ assert( status );
+
+ MFnMatrixData matrixData( matrixObject, &status );
+ assert( status );
+
+ //
+ // Create a world tranformation matrix.
+ //
+ MTransformationMatrix matrix( matrixData.matrix( &status ) );
+ assert( status );
+
+ //
+ // Get the world translation vector.
+ //
+ MVector worldTranslation = matrix.translation( MSpace::kWorld, &status );
+
+
+ //
+ // Get the nodes immediate transform and create a function wrapper for it.
+ //
+ MDagPath nodePath;
+ status = MDagPath::getAPathTo( node, nodePath );
+ assert( status );
+
+ MObject transformObject = nodePath.transform( &status );
+ assert( status );
+
+ MFnTransform fnTransform( transformObject, &status );
+ assert( status );
+
+ //
+ // Get the node translation vector.
+ //
+ MVector nodeTranslation = fnTransform.translation( MSpace::kTransform, &status );
+
+ //
+ // The exclusive translation vector is that vector which reflect the
+ // amount of translation the node undergoes as a result of transforms
+ // exclusive of its immediate parent.
+ //
+ MVector exclusiveTranslation = worldTranslation - nodeTranslation;
+
+ //
+ // Set the nodeTranslation to that or our desired world position less the
+ // exclusiveTranslation vector.
+ //
+ MVector position( wp );
+ nodeTranslation = position - exclusiveTranslation;
+
+ //
+ // Push the result back into the transform and we are done.
+ //
+ status = fnTransform.setTranslation( nodeTranslation, MSpace::kTransform );
+ assert( status );
+
+}
+
+//-----------------------------------------------------------------------------
+// v i e w T o W o r l d A t Y
+//
+// Synopsis: Convert the specified view coordinates to world coordinates on
+// the specified y plane.
+//
+// Parameters: world - reference parameter to recieve the world coordinates.
+// view - the view position to be converted.
+// y - the y plane to translate to.
+//
+// Returns: The status of the request. Will return failure if the the
+// view plane is perpendicular to the y-plane.
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void MExt::ViewToWorldAtY( MPoint* wc, MPoint& vc, double y )
+{
+ assert( wc );
+
+ MStatus status = MS::kFailure;
+
+ M3dView view = M3dView::active3dView();
+ MPoint rayOrigin;
+ MVector rayVector;
+ status = view.viewToWorld( static_cast<short>(vc.x),
+ static_cast<short>(vc.y),
+ rayOrigin,
+ rayVector
+ );
+ assert( status );
+
+ MPoint result;
+ if ( fabs(rayVector.y) > EPSILON )
+ {
+ //
+ // The following formulas for x and z use the point slope formula in
+ // the form
+ // x = ( y - y0 ) / M + x0
+ // = ( y - y0 ) / ( dy / dx ) + x0
+ // = ( ( y - y0 ) / dy ) * dx + x0
+ //
+ double coeff = ( y - rayOrigin.y ) / rayVector.y;
+ wc->x = ( coeff * rayVector.x ) + rayOrigin.x;
+ wc->y = y;
+ wc->z = ( coeff * rayVector.z ) + rayOrigin.z;
+ }
+}
diff --git a/tools/globalcode/utility/MExt.h b/tools/globalcode/utility/MExt.h
new file mode 100644
index 0000000..e4b6444
--- /dev/null
+++ b/tools/globalcode/utility/MExt.h
@@ -0,0 +1,226 @@
+#include "precompiled/PCH.h"
+
+#ifndef _MEXT_H
+#define _MEXT_H
+//-----------------------------------------------------------------------------
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// MExt.h
+//
+// Description: Functions that extend the Maya API to perform other common
+// tasks.
+//
+// Modification History:
+// + Created Aug 21, 2001 -- bkusy
+//-----------------------------------------------------------------------------
+
+//----------------------------------------
+// System Includes
+//----------------------------------------
+/* Using precompiled headers.
+#include <maya/MStringArray.h>
+#include <maya/MPoint.h>
+#include <maya/MObject.h>
+#include <maya/MPlug.h>
+*/
+
+//----------------------------------------
+// Project Includes
+//----------------------------------------
+#include "MExt_template.h"
+
+//----------------------------------------
+// Forward References
+//----------------------------------------
+class MString;
+class MDagPath;
+class MArgList;
+class MPlug;
+class MObject;
+class MSelectionList;
+class MTypeId;
+class MDoubleArray;
+
+//----------------------------------------
+// Macros
+//----------------------------------------
+#define RETURN_STATUS_ON_FAILURE( STATUS ) if ( ! (STATUS) ) return (STATUS)
+#define RETURN_FALSE_ON_FAILURE( STATUS ) if ( ! (STATUS) ) return false
+
+//These are used when dealing with plugs.
+#define AS_DEST true, false
+#define AS_SOURCE false, true
+#define AS_BOTH true, true
+//----------------------------------------
+// Constants, Typedefs and Statics
+//----------------------------------------
+
+
+
+namespace MExt
+{
+ namespace Attr
+ {
+ void GetScaled( MPoint*, const MObject& node, const MObject& attr );
+
+ void SetScaled( const MPoint&, MObject& node, MObject& attr );
+
+ void SetScaled( const MPoint&, MObject& node, const MString& attr );
+
+ } // namespace Attr
+
+ namespace OptionVar
+ {
+ bool Get( char* buffer, unsigned int buffer_size, const char* symbol );
+
+ void Set( const char* buffer, const char* symbol );
+
+ } // namespace OptionVar
+
+
+ class OptionParser
+ {
+ public:
+
+ OptionParser( const char* command, const MArgList& args );
+ ~OptionParser();
+
+ void setOptions( const char* optionSpec );
+ int nextOption();
+ MString getArg();
+
+ private:
+
+ int m_argc;
+ char** m_argv;
+ char* m_opt;
+
+ };
+
+
+ void AddChild( MObject& parentLocatorNode, MObject& childLocatorNode );
+
+ void Connect( MObject& node,
+ MObject& attr,
+ MObject& otherNode,
+ MObject& otherAttr
+ );
+
+ void Connect( MObject& node,
+ const char* attr,
+ MObject& otherNode,
+ const char* otherAttr
+ );
+
+
+ void CreateNode( MObject* node,
+ MObject* transform,
+ const MString& type,
+ const MString* name = 0,
+ const MObject& parent = MObject::kNullObj
+ );
+
+ void CreateNode( MObject& node,
+ MObject& transform,
+ const MString& type,
+ const MString* name = 0,
+ const MObject& parent = MObject::kNullObj
+ );
+
+
+ void CreateVertexAttribute( MObject* attr,
+ const char* name,
+ const char* brief_name
+ );
+
+ void DeleteNode( MObject& node, bool deleteParent );
+
+ void DisconnectAll( MObject& node, MObject& attr );
+ void DisconnectAll( MObject& node, const char* attrName );
+
+ int DisplayError( const char* fmt, ... );
+
+ int DisplayWarning( const char* fmt, ... );
+
+ int DisplayInfo( const char* fmt, ... );
+
+ void FilterSelectionList( MSelectionList* filteredList,
+ const MString& typeName,
+ const MSelectionList& sourceList
+ );
+
+ bool FindAllSkeletonRoots( MObjectArray* objects );
+
+ bool FindAllTransforms( MObjectArray* transforms, const MObject& root );
+
+
+ bool FindDagNodeByName( MDagPath* path,
+ const MString& node,
+ const MObject& root = MObject::kNullObj
+ );
+
+ bool FindDagNodeByName( MDagPath* path,
+ const MString& node,
+ const MString& root
+ );
+
+ void GetWorldPosition( MPoint*, const MObject& node );
+
+ MPoint GetWorldPositionBetween( MObject& node1, MObject& node2 );
+
+ MMatrix GetWorldMatrix( MObject& node );
+
+ bool IsConnected( MObject& node, const char* attr );
+ bool IsConnected( MObject& node, MObject& attr );
+ bool IsConnected( MPlug& plug1, MPlug& plug2 );
+
+ void MakeNameUnique( MString* unique,
+ const MString& name,
+ const MObject& root = MObject::kNullObj
+ );
+
+ void MakeNameUnique( MString* unique,
+ const MString& name,
+ const MString& root
+ );
+
+ bool MeshClickIntersect( short xClick, short yClick, MPoint& intersect, bool closest = true );
+
+ bool MeshIntersectAlongVector( MPoint from, MPoint direction, MPoint& intersect, bool closest = true );
+
+ bool PlugHasConnection( MObject* connectedNode,
+ MPlug& plug,
+ bool asDst = true,
+ bool asSrc = true,
+ const char* type = 0
+ );
+
+ bool PlugHasConnection( MPlug* connectedPlug,
+ MPlug& plug,
+ bool asDst = true,
+ bool asSrc = true,
+ const char* type = 0
+ );
+
+
+ void ResolveConnections( MPlugArray* sources,
+ MPlugArray* targets,
+ MPlug& plug,
+ bool asDst = true,
+ bool asSrc = true
+ );
+
+
+ void SelectNodesBelowRoot( MSelectionList* list,
+ const MString& typeName,
+ const MObject& root = MObject::kNullObj,
+ MSelectionList* intersectionList = 0
+ );
+
+ void SetWorldPosition( const MPoint&, const MObject& node );
+
+ void ViewToWorldAtY( MPoint* world, MPoint& view, double y = 0.0 );
+
+} // namespace MExt
+
+#endif
diff --git a/tools/globalcode/utility/MExt_template.cpp b/tools/globalcode/utility/MExt_template.cpp
new file mode 100644
index 0000000..c01fee2
--- /dev/null
+++ b/tools/globalcode/utility/MExt_template.cpp
@@ -0,0 +1,273 @@
+#include "precompiled/PCH.h"
+
+//-----------------------------------------------------------------------------
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// MExt_template.cpp
+//
+// Description:
+//
+// Modification History:
+// + Created Dec 19, 2001 -- bkusy
+//-----------------------------------------------------------------------------
+
+//----------------------------------------
+// System Includes
+//----------------------------------------
+
+//----------------------------------------
+// Project Includes
+//----------------------------------------
+#include "MExt_template.h"
+
+//----------------------------------------
+// Forward References
+//----------------------------------------
+
+//----------------------------------------
+// Constants, Typedefs and Statics
+//----------------------------------------
+
+//-----------------------------------------------------------------------------
+// G e t < MDoubleArray >
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+template < >
+void MExt::Attr::Get< MDoubleArray >( MDoubleArray* array, const MPlug& plug )
+{
+ assert( array );
+
+ MStatus status;
+
+ MObject data;
+ status = plug.getValue( data );
+ assert( status );
+
+ MFnDoubleArrayData fnArray( data, &status );
+ assert( status );
+
+ MDoubleArray myArray = fnArray.array( &status );
+ assert( status );
+
+ array->clear();
+ unsigned int i;
+ for ( i = 0; i < myArray.length(); i++ )
+ {
+ array->append( myArray[i] );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// G e t < MIntArray >
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+template < >
+void MExt::Attr::Get< MIntArray >( MIntArray* array, const MPlug& plug )
+{
+ assert( array );
+
+ MStatus status;
+
+ MObject data;
+ status = plug.getValue( data );
+ assert( status );
+
+ MFnIntArrayData fnArray( data, &status );
+ assert( status );
+
+ MIntArray myArray = fnArray.array( &status );
+ assert( status );
+
+ array->clear();
+ unsigned int i;
+ for ( i = 0; i < myArray.length(); i++ )
+ {
+ array->append( myArray[i] );
+ }
+}
+//-----------------------------------------------------------------------------
+// G e t < MPoint >
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+template < >
+void MExt::Attr::Get< MPoint >( MPoint* vertex, const MPlug& plug )
+{
+ assert( vertex );
+
+ MDoubleArray coordinates;
+ Get( &coordinates, plug );
+
+ if ( coordinates.length() > 0 )
+ {
+ assert( coordinates.length() == 3 );
+ vertex->x = coordinates[0];
+ vertex->y = coordinates[1];
+ vertex->z = coordinates[2];
+ }
+ else
+ {
+ *vertex = MPoint::origin;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// G e t < MStringArray >
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+template < >
+void MExt::Attr::Get< MStringArray >( MStringArray* array, const MPlug& plug )
+{
+ assert( array );
+
+ MStatus status;
+
+ MObject data;
+ status = plug.getValue( data );
+ assert( status );
+
+ MFnStringArrayData fnArray( data, &status );
+ assert( status );
+
+ MStringArray myArray = fnArray.array( &status );
+ assert( status );
+
+ array->clear();
+ unsigned int i;
+ for ( i = 0; i < myArray.length(); i++ )
+ {
+ array->append( myArray[i] );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// S e t < MDoubleArray >
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+template < >
+void MExt::Attr::Set< MDoubleArray >( const MDoubleArray& array, MPlug& plug )
+{
+ MStatus status;
+
+ MFnDoubleArrayData fnArray;
+ MObject object = fnArray.create( array, &status );
+ assert( status );
+
+ status = plug.setValue( object );
+ assert( status );
+}
+
+//-----------------------------------------------------------------------------
+// S e t < MIntArray >
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+template < >
+void MExt::Attr::Set< MIntArray >( const MIntArray& array, MPlug& plug )
+{
+ MStatus status;
+
+ MFnIntArrayData fnArray;
+ MObject object = fnArray.create( array, &status );
+ assert( status );
+
+ status = plug.setValue( object );
+ assert( status );
+}
+
+//-----------------------------------------------------------------------------
+// S e t < MPoint >
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+template < >
+void MExt::Attr::Set< MPoint >( const MPoint& vertex, MPlug& plug )
+{
+ MStatus status;
+
+ MDoubleArray coordinates;
+ coordinates.append( vertex.x );
+ coordinates.append( vertex.y );
+ coordinates.append( vertex.z );
+
+ Set( coordinates, plug );
+}
+
+//-----------------------------------------------------------------------------
+// S e t < MStringArray >
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+template < >
+void MExt::Attr::Set< MStringArray >( const MStringArray& array, MPlug& plug )
+{
+ MStatus status;
+
+ MFnStringArrayData fnArray;
+ MObject object = fnArray.create( array, &status );
+ assert( status );
+
+ status = plug.setValue( object );
+ assert( status );
+}
+
diff --git a/tools/globalcode/utility/MExt_template.h b/tools/globalcode/utility/MExt_template.h
new file mode 100644
index 0000000..5714e95
--- /dev/null
+++ b/tools/globalcode/utility/MExt_template.h
@@ -0,0 +1,146 @@
+#include "precompiled/PCH.h"
+
+#ifndef _MEXT_TEMPLATE_H
+#define _MEXT_TEMPLATE_H
+//-----------------------------------------------------------------------------
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// MExt_template.h
+//
+// Description:
+//
+// Modification History:
+// + Created Dec 19, 2001 -- bkusy
+//-----------------------------------------------------------------------------
+
+//This is a warning provided by the STL... It seems that toollib gets whacky when there
+//is other templates made... Sigh...
+#pragma warning(disable:4786)
+
+//----------------------------------------
+// System Includes
+//----------------------------------------
+//#include <assert.h>
+
+/* Using precompiled headers
+#include <maya/MDoubleArray.h>
+#include <maya/MFnDependencyNode.h>
+#include <maya/MFnDoubleArrayData.h>
+#include <maya/MFnIntArrayData.h>
+#include <maya/MFnStringArrayData.h>
+#include <maya/MIntArray.h>
+#include <maya/MObject.h>
+#include <maya/MPlug.h>
+#include <maya/MPoint.h>
+#include <maya/MString.h>
+#include <maya/MStringArray.h>
+*/
+
+//----------------------------------------
+// Project Includes
+//----------------------------------------
+
+//----------------------------------------
+// Forward References
+//----------------------------------------
+
+//----------------------------------------
+// Constants, Typedefs and Statics
+//----------------------------------------
+
+namespace MExt
+{
+ namespace Attr
+ {
+
+ template < class T >
+ void Get( T* value, const MPlug& plug )
+ {
+ assert( value );
+
+ MStatus status;
+
+ status = plug.getValue( *value );
+ assert( status );
+ }
+
+ template < >
+ void Get< MDoubleArray >( MDoubleArray*, const MPlug& );
+
+ template < >
+ void Get< MIntArray >( MIntArray*, const MPlug& );
+
+ template < >
+ void Get< MPoint >( MPoint*, const MPlug& );
+
+ template < >
+ void Get< MStringArray >( MStringArray*, const MPlug& );
+
+ template < class T >
+ void Get( T* value, const MObject& node, const MObject& attr )
+ {
+ MPlug plug( node, attr );
+ Get( value, plug );
+ }
+
+ template < class T >
+ void Get( T* value, const MObject& node, const MString& attr )
+ {
+ MStatus status;
+
+ MFnDependencyNode fnNode( node, &status );
+ assert( status );
+
+ MPlug plug = fnNode.findPlug( attr, &status );
+ assert( status );
+
+ Get( value, plug );
+ }
+
+ template < class T >
+ void Set( const T& value, MPlug& plug )
+ {
+ MStatus status;
+
+ status = plug.setValue( const_cast<T&>(value) );
+ assert( status );
+ }
+
+ template < >
+ void Set< MDoubleArray >( const MDoubleArray& array, MPlug& plug );
+
+ template < >
+ void Set< MIntArray >( const MIntArray& array, MPlug& plug );
+
+ template < >
+ void Set< MPoint >( const MPoint& vertex, MPlug& plug );
+
+ template < >
+ void Set< MStringArray >( const MStringArray& array, MPlug& plug );
+
+ template < class T >
+ void Set( const T& value, MObject& node, MObject& attr )
+ {
+ MPlug plug( node, attr );
+ Set( value, plug );
+ }
+
+ template < class T >
+ void Set( const T& value, MObject& node, const MString& attr )
+ {
+ MStatus status;
+
+ MFnDependencyNode fnNode( node, &status );
+ assert( status );
+
+ MPlug plug = fnNode.findPlug( attr, &status );
+ assert( status );
+
+ Set( value, plug );
+ }
+
+ } // namespace Attr
+
+} // namespace MExt
+
+#endif
diff --git a/tools/globalcode/utility/MUI.cpp b/tools/globalcode/utility/MUI.cpp
new file mode 100644
index 0000000..4cd4a8d
--- /dev/null
+++ b/tools/globalcode/utility/MUI.cpp
@@ -0,0 +1,220 @@
+//-----------------------------------------------------------------------------
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// MUI.cpp
+//
+// Description: Container class for custom UI windows for use in Maya.
+//
+// Modification History:
+// + Created Sep 30, 2001 -- bkusy
+//-----------------------------------------------------------------------------
+
+//----------------------------------------
+// System Includes
+//----------------------------------------
+#include <assert.h>
+
+//----------------------------------------
+// Project Includes
+//----------------------------------------
+#include "stdafx.h"
+#include "MUI.h"
+#include "util.h"
+#include "mayahandles.h"
+
+//----------------------------------------
+// Forward References
+//----------------------------------------
+
+//----------------------------------------
+// Constants, Typedefs and Statics
+//----------------------------------------
+
+
+//-----------------------------------------------------------------------------
+// c o n f i r m
+//
+// Synopsis: Present a modal confirmation box to the user.
+//
+// Parameters: message - the message to display in the box.
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+int MUI::ConfirmDialog( const char* message )
+{
+ UINT style = MB_YESNOCANCEL | MB_ICONQUESTION | MB_DEFBUTTON1 | MB_TASKMODAL ;
+ int button = MessageBox( 0, message, "MUI Confirmation", style );
+
+ int result = MUI::YES;
+ if ( IDNO == button ) result = MUI::NO;
+ if ( IDCANCEL == button ) result = MUI::CANCEL;
+
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+// E r r o r D i a l o g
+//
+// Synopsis: Present a modal error dialog box to the user.
+//
+// Parameters: message - the message to display in the box.
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void MUI::ErrorDialog( const char* message )
+{
+ UINT style = MB_OK | MB_ICONERROR | MB_TASKMODAL;
+ MessageBox( 0, message, "MUI Error", style );
+}
+
+//-----------------------------------------------------------------------------
+// E r r o r D i a l o g
+//
+// Synopsis: Present a modal error dialog box to the user.
+//
+// Parameters: message - the message to display in the box.
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void MUI::InfoDialog( const char* message )
+{
+ UINT style = MB_OK | MB_ICONINFORMATION | MB_TASKMODAL;
+ MessageBox( 0, message, "MUI Info", style );
+}
+
+//-----------------------------------------------------------------------------
+// F i l e D i a l o g
+//
+// Synopsis: Present the user with a file browser window to select a file for
+// open or save.
+//
+// Parameters: filePath - a reference parameter to receive the full
+// file path from the dialog. If not NULL on
+// input, the initial value is used as the
+// starting location for the dialog.
+// filePathSize - the maximum length of the filePath buffer.
+// dialogTitle - the caption to appear in the dialog title
+// bar.
+// extensionFilter - A filter specifiying the types of files that
+// are eligilble for selection. It must end
+// in "||" with all entries separated by "|".
+// Generally entries will be in pairs; the
+// first is a type description and the second
+// is the actual filter. e.g./
+// "Raddle Data(*.rdl)|*.rdl|All Files(*.*)|*.*||".
+// defaultExtension - if not NULL, then the given extension will
+// automatically appended to an extensionless
+// entry in the Filename box.
+// broserType - OPEN | SAVE. Default is OPEN.
+//
+// Returns: true, if a filePath is set; false if the dialog is cancelled.
+//
+// Notes: The filePath will have "/" slashes and not "\" slashes on return.
+//
+//-----------------------------------------------------------------------------
+bool MUI::FileDialog( char* filePath, int filePathSize,
+ const char* windowTitle,
+ const char* extensionFilter,
+ const char* defaultExtension,
+ int browserType
+ )
+{
+ //
+ // We do need the file path to have windows backslashes.
+ //
+ util_replaceCharacters('/', '\\', filePath );
+
+ bool isOk = false;
+
+ BOOL doOpen;
+ DWORD flags = 0;
+
+ switch ( browserType )
+ {
+ case MUI::SET:
+ {
+ doOpen = TRUE;
+ flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
+ break;
+ }
+
+ case MUI::SAVE:
+ {
+ doOpen = FALSE;
+ flags = OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
+ break;
+ }
+
+ default: // MUI::OPEN
+ {
+ doOpen = TRUE;
+ flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
+ break;
+
+ }
+ }
+
+ //
+ // Set the AFX handle to maya's application instance handle.
+ //
+ HINSTANCE handle = static_cast<HINSTANCE>(MayaHandles::GetHInstance());
+ AfxSetResourceHandle( handle );
+
+ //
+ // Create the dialog
+ //
+ CFileDialog fileDialog( doOpen,
+ defaultExtension,
+ filePath,
+ flags,
+ extensionFilter,
+ NULL
+ );
+
+ if ( windowTitle ) fileDialog.m_ofn.lpstrTitle = windowTitle;
+
+ //
+ // Show the dialog and wait for a response.
+ //
+ int result = fileDialog.DoModal();
+ if ( IDOK == result )
+ {
+ const char* filename = LPCSTR( fileDialog.GetPathName() );
+ strncpy( filePath, LPCSTR( fileDialog.GetPathName() ), filePathSize );
+ util_replaceCharacters('\\', '/', filePath );
+ isOk = true;
+ }
+
+ return isOk;
+}
+
+//=============================================================================
+// MUI::PopupDialogue
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( int id, DLGPROC callBack )
+//
+// Return: void
+//
+//=============================================================================
+void MUI::PopupDialogue( int id, DLGPROC callBack )
+{
+ HINSTANCE handle = static_cast<HINSTANCE>(MayaHandles::GetHInstance());
+ AfxSetResourceHandle( handle );
+
+ HWND hWnd = static_cast<HWND>(MayaHandles::GetHWND());
+
+ DialogBox( handle, MAKEINTRESOURCE(id), hWnd, callBack );
+}
+
+
diff --git a/tools/globalcode/utility/MUI.h b/tools/globalcode/utility/MUI.h
new file mode 100644
index 0000000..e991cf7
--- /dev/null
+++ b/tools/globalcode/utility/MUI.h
@@ -0,0 +1,82 @@
+#ifndef _MUI_HPP
+#define _MUI_HPP
+//-----------------------------------------------------------------------------
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// MUI.hpp
+//
+// Description: Container class for custom UI windows for use in Maya.
+//
+// Modification History:
+// + Created Sep 30, 2001 -- bkusy
+//-----------------------------------------------------------------------------
+
+//----------------------------------------
+// System Includes
+//----------------------------------------
+
+//----------------------------------------
+// Project Includes
+//----------------------------------------
+
+//----------------------------------------
+// Forward References
+//----------------------------------------
+
+//----------------------------------------
+// Constants, Typedefs and Statics
+//----------------------------------------
+
+//This is an example callback.
+inline BOOL CALLBACK PopupCallBack( HWND hWnd, UINT uMsg, UINT wParam, long lParam )
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ return true;
+ }
+ break;
+ default:
+ {
+// EndDialog( hWnd, 0); //this is how you close the window.
+ return false;
+ }
+ break;
+ }
+}
+
+
+class MUI
+{
+ public:
+
+ enum {
+ YES,
+ NO,
+ CANCEL,
+ SAVE,
+ SET,
+ NEW,
+ OPEN
+ };
+
+ static int ConfirmDialog( const char* message );
+
+ static bool FileDialog( char* filePath, int filePathSize,
+ const char* windowTitle = 0,
+ const char* extensionFilter = 0,
+ const char* defaultExtension = 0,
+ int browserType = MUI::OPEN
+ );
+
+ static void ErrorDialog( const char* message );
+
+ static void InfoDialog( const char* message );
+
+ static void PopupDialogue( int id, DLGPROC callBack );
+
+ private:
+};
+
+#endif
diff --git a/tools/globalcode/utility/mayahandles.cpp b/tools/globalcode/utility/mayahandles.cpp
new file mode 100644
index 0000000..e0cb824
--- /dev/null
+++ b/tools/globalcode/utility/mayahandles.cpp
@@ -0,0 +1,105 @@
+//-----------------------------------------------------------------------------
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// mayahandles.cpp
+//
+// Description: Class to store and retrieve maya handles as generic pointers.
+//
+// Modification History:
+// + Created Oct 15, 2001 -- bkusy
+// + More MFC goodness -- Cary Brisebois
+//-----------------------------------------------------------------------------
+
+//----------------------------------------
+// System Includes
+//----------------------------------------
+
+//----------------------------------------
+// Project Includes
+//----------------------------------------
+#include "mayahandles.h"
+#include "stdafx.h"
+#include "maya/mglobal.h"
+
+//----------------------------------------
+// Forward References
+//----------------------------------------
+
+//----------------------------------------
+// Constants, Typedefs and Statics
+//----------------------------------------
+void* MayaHandles::m_hInstance = 0;
+void* MayaHandles::m_HWND = 0;
+
+BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam)
+{
+ char str[1024];
+ ::GetWindowText(hwnd, str, 1024);
+
+ MString mayaVersion = MGlobal::mayaVersion();
+
+ char version[256];
+ sprintf( version, "Maya %s", mayaVersion.asChar() );
+
+ if(strncmp(str, version, strlen(version)) == 0) //This is silly.
+ {
+ *(HWND*)lParam = hwnd;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+//-----------------------------------------------------------------------------
+// S e t H I n s t a n c e
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void MayaHandles::SetHInstance( void* hInstance )
+{
+ m_hInstance = hInstance;
+}
+
+//-----------------------------------------------------------------------------
+// G e t H I n s t a n c e
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void* MayaHandles::GetHInstance()
+{
+ return m_hInstance;
+}
+
+void* MayaHandles::GetHWND()
+{
+ if ( m_HWND == 0 )
+ {
+ HWND hWnd = NULL;
+ EnumChildWindows(::GetDesktopWindow(), EnumChildProc, (long)&hWnd);
+ if(hWnd == NULL)
+ {
+ // houston we have a problem
+ MGlobal::displayError("can't find Maya window");
+ }
+ else
+ {
+ m_HWND = hWnd;
+ }
+ }
+
+ return m_HWND;
+} \ No newline at end of file
diff --git a/tools/globalcode/utility/mayahandles.h b/tools/globalcode/utility/mayahandles.h
new file mode 100644
index 0000000..9e530ba
--- /dev/null
+++ b/tools/globalcode/utility/mayahandles.h
@@ -0,0 +1,42 @@
+//-----------------------------------------------------------------------------
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// mayahandles.h
+//
+// Description: Class to store and retrieve maya handles as generic pointers.
+//
+// Modification History:
+// + Created Oct 15, 2001 -- bkusy
+//-----------------------------------------------------------------------------
+
+//----------------------------------------
+// System Includes
+//----------------------------------------
+
+//----------------------------------------
+// Project Includes
+//----------------------------------------
+
+//----------------------------------------
+// Forward References
+//----------------------------------------
+
+//----------------------------------------
+// Constants, Typedefs and Statics
+//----------------------------------------
+
+class MayaHandles
+{
+ public:
+
+ static void SetHInstance( void* hInstance );
+ static void* GetHInstance();
+
+ static void* GetHWND();
+
+ private:
+
+ static void* m_hInstance;
+ static void* m_HWND;
+};
+
diff --git a/tools/globalcode/utility/nodehelper.h b/tools/globalcode/utility/nodehelper.h
new file mode 100644
index 0000000..ef0842a
--- /dev/null
+++ b/tools/globalcode/utility/nodehelper.h
@@ -0,0 +1,37 @@
+#ifndef NODE_HELPERS
+
+#include "precompiled/PCH.h"
+
+namespace NodeHelper
+{
+
+inline int OverrideNodeColour( MObject& node, int defaultColour )
+{
+ int colour = defaultColour;
+
+ MStatus status;
+ MFnDagNode fnDag( node );
+ MPlug overColour = fnDag.findPlug( MString( "overrideColor" ), &status );
+ if ( status )
+ {
+ overColour.getValue( colour );
+ if ( colour != 0 ) //The override is Active...
+ {
+ colour--;
+ if ( colour < 0 )
+ {
+ colour = 0;
+ }
+ }
+ else
+ {
+ colour = defaultColour;
+ }
+ }
+
+ return colour;
+}
+
+};
+
+#endif \ No newline at end of file
diff --git a/tools/globalcode/utility/overlaymarquee.cpp b/tools/globalcode/utility/overlaymarquee.cpp
new file mode 100644
index 0000000..7d97b77
--- /dev/null
+++ b/tools/globalcode/utility/overlaymarquee.cpp
@@ -0,0 +1,222 @@
+//-----------------------------------------------------------------------------
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// marquee.cpp
+//
+// Description:
+//
+// Modification History:
+// + Created Jun 14, 2001 -- bkusy
+//-----------------------------------------------------------------------------
+
+//----------------------------------------
+// System Includes
+//----------------------------------------
+#include <windows.h>
+#include <assert.h>
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <GL/glaux.h>
+
+//----------------------------------------
+// Project Includes
+//----------------------------------------
+#include "overlaymarquee.h"
+
+//----------------------------------------
+// Forward References
+//----------------------------------------
+
+//----------------------------------------
+// Define Owning Namespace
+//----------------------------------------
+namespace GLObj {
+
+//----------------------------------------
+// Constants, Typedefs and Statics
+//----------------------------------------
+
+//-----------------------------------------------------------------------------
+// M a r q u e e
+//
+// Synopsis: Constructor
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+OverlayMarquee::OverlayMarquee() :
+ m_xStart( 0 ),
+ m_yStart( 0 ),
+ m_xEnd( 0 ),
+ m_yEnd( 0 )
+{
+}
+
+//-----------------------------------------------------------------------------
+// ~ M a r q u e e
+//
+// Synopsis: Destructor
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+OverlayMarquee::~OverlayMarquee()
+{
+}
+
+//-----------------------------------------------------------------------------
+// B e g i n
+//
+// Synopsis:
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void OverlayMarquee::Begin( M3dView& view, short xStart, short yStart )
+{
+ m_View = view;
+ m_xStart = xStart;
+ m_yStart = yStart;
+ m_View.beginGL();
+ m_View.beginOverlayDrawing();
+}
+
+//-----------------------------------------------------------------------------
+// D r a w
+//
+// Synopsis: Draw a marquee with the given coordinates.
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void OverlayMarquee::Draw( short xEnd, short yEnd )
+{
+ glPushAttrib( GL_CURRENT_BIT | GL_LINE_BIT | GL_POLYGON_BIT );
+ m_xEnd = xEnd;
+ m_yEnd = yEnd;
+
+ //
+ // Clearing the overlay plane doesn't seem to work, but swapping buffers does
+ // so we'll use that instead. You've gotta luv Maya bugs -- embrace them
+ // don't squash them.
+ //
+ m_View.clearOverlayPlane();
+ SwapBuffers( m_View.deviceContext() );
+
+ //
+ // Setup the orthographic projection matrix.
+ //
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity();
+ gluOrtho2D( 0.0, (GLdouble)m_View.portWidth(), 0.0, (GLdouble)m_View.portHeight() );
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+ glTranslatef( 0.375, 0.375, 0.0 );
+
+ //
+ // Retrieve GL State.
+ //
+ float lineWidth;
+ unsigned char lineSmoothedFlag;
+ glGetFloatv( GL_LINE_WIDTH, &lineWidth );
+ glGetBooleanv( GL_LINE_SMOOTH, &lineSmoothedFlag );
+
+ //
+ // Set line style.
+ //
+ glLineStipple( 1, 0x5555 );
+ glLineWidth( 1.0 );
+ glEnable( GL_LINE_STIPPLE );
+ glEnable( GL_LINE_SMOOTH );
+ glIndexi( 2 );
+
+ //
+ // Draw marquee.
+ //
+ glBegin( GL_LINES );
+
+ glVertex2i( m_xStart, m_yEnd ); // Left Side.
+ glVertex2i( m_xStart, m_yStart );
+
+ glVertex2i( m_xStart, m_yStart );// Top
+ glVertex2i( m_xEnd, m_yStart );
+
+ glVertex2i( m_xEnd, m_yStart ); // Right Side.
+ glVertex2i( m_xEnd, m_yEnd );
+
+ glVertex2i( m_xEnd, m_yEnd ); // Bottom.
+ glVertex2i( m_xStart, m_yEnd );
+
+ glEnd();
+
+ //
+ // Don't swap the display buffers. A bug in Maya causes the display to be
+ // cleared -- making the flicker worse.
+ //
+ //SwapBuffers( m_View.deviceContext() );
+
+ //
+ // Instead just flush the GL buffers.
+ //
+ glFlush();
+
+
+ //
+ // Restore GL state.
+ glLineWidth( lineWidth );
+ if ( !lineSmoothedFlag ) glDisable( GL_LINE_SMOOTH );
+ glDisable( GL_LINE_STIPPLE );
+
+ glPopAttrib();
+}
+
+//-----------------------------------------------------------------------------
+// R e d r a w
+//
+// Synopsis: Draw a marquee with the last given coordinates.
+//
+// Parameters: NONE
+//
+// Returns: NOTHING
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+void OverlayMarquee::Redraw()
+{
+ Draw( m_xEnd, m_yEnd );
+}
+
+void OverlayMarquee::End()
+{
+ m_View.endOverlayDrawing();
+ m_View.endGL();
+
+ //
+ // Use the Maya bug to get rid of any drawing we have done.
+ //
+ SwapBuffers( m_View.deviceContext() );
+}
+
+} // namespace GLObj
+
+
+
+
diff --git a/tools/globalcode/utility/overlaymarquee.h b/tools/globalcode/utility/overlaymarquee.h
new file mode 100644
index 0000000..b900083
--- /dev/null
+++ b/tools/globalcode/utility/overlaymarquee.h
@@ -0,0 +1,55 @@
+#include "precompiled/PCH.h"
+
+#ifndef _GLOBJ_OVERLAYMARQUEE_H
+#define _GLOBJ_OVERLAYMARQUEE_H
+//-----------------------------------------------------------------------------
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// overlaymarquee.h
+//
+// Description: Draw a marquee using openGL.
+//
+// Modification History:
+// + Created Jun 14, 2001 -- bkusy
+//-----------------------------------------------------------------------------
+
+//----------------------------------------
+// System Includes
+//----------------------------------------
+
+//----------------------------------------
+// Project Includes
+//----------------------------------------
+//#include <maya/M3dView.h>
+
+//----------------------------------------
+// Forward References
+//----------------------------------------
+//----------------------------------------
+// Define Owning Namespace
+//----------------------------------------
+namespace GLObj {
+
+class OverlayMarquee
+{
+ public:
+
+ OverlayMarquee();
+ ~OverlayMarquee();
+
+ void Begin( M3dView& view, short xStart, short yStart );
+ void Draw( short xEnd, short yEnd );
+ void Redraw();
+ void End();
+
+ private:
+ OverlayMarquee(OverlayMarquee &);
+ OverlayMarquee &operator=(OverlayMarquee &);
+
+ M3dView m_View;
+ short m_xStart, m_yStart, m_xEnd, m_yEnd;
+};
+
+} // GLObj namespace.
+
+#endif
diff --git a/tools/globalcode/utility/stdafx.h b/tools/globalcode/utility/stdafx.h
new file mode 100644
index 0000000..3152a3f
--- /dev/null
+++ b/tools/globalcode/utility/stdafx.h
@@ -0,0 +1,19 @@
+#ifndef STDAFX
+#define STDAFX
+
+//-----------------------------------------------------------------------------
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// stdafx.h
+//
+// Description: Header wrapper for using MFC.
+//
+// Modification History:
+// + Created Oct 12, 2001 -- bkusy
+//-----------------------------------------------------------------------------
+#define VC_EXTRALEAN
+#include <afxwin.h>
+#include <afxdlgs.h>
+
+
+#endif \ No newline at end of file
diff --git a/tools/globalcode/utility/transformmatrix.cpp b/tools/globalcode/utility/transformmatrix.cpp
new file mode 100644
index 0000000..1264fff
--- /dev/null
+++ b/tools/globalcode/utility/transformmatrix.cpp
@@ -0,0 +1,904 @@
+/*===========================================================================
+ transformmatrix.cpp
+ Created: October 16, 2000
+ Auuthor: Bryan Brandt
+
+ Copyright (c) 2000 Radical Entertainment, Inc.
+ All rights reserved.
+===========================================================================*/
+
+//#include <maya/MFnTransform.h>
+//#include <maya/MPoint.h>
+//#include <maya/MQuaternion.h>
+//#include <maya/MEulerRotation.h>
+//#include <maya/MVector.h>
+//#include <maya/MDagPath.h>
+//#include <maya/MFnIkJoint.h>
+//#include <maya/MPlug.h>
+
+#include "transformmatrix.h"
+
+
+TransformMatrix::TransformMatrix():
+ rotateOrder(ORDER_XYZ)
+{
+ SetIdentity();
+}
+
+
+TransformMatrix::TransformMatrix(const MDagPath& dagPath):
+ rotateOrder(ORDER_XYZ)
+{
+ SetIdentity();
+ Assign(dagPath);
+}
+
+
+TransformMatrix::TransformMatrix(const MTransformationMatrix& xform):
+ rotateOrder(ORDER_XYZ)
+{
+ SetIdentity();
+ Assign(xform);
+}
+
+
+bool TransformMatrix::Assign(const MDagPath& dagPath)
+{
+ MStatus status;
+
+ MObject node = dagPath.node(&status);
+ if (!status)
+ return false;
+
+ if (node.hasFn(MFn::kJoint))
+ {
+ MDagPath tmpDagPath = dagPath;
+ return AssignJoint(tmpDagPath, node);
+ }
+ else if (node.hasFn(MFn::kTransform))
+ {
+ MFnTransform xformNode(dagPath, &status);
+ if (!status)
+ return false;
+
+ MTransformationMatrix xform = xformNode.transformation(&status);
+ if (!status)
+ return false;
+
+ return Assign(xform);
+ }
+
+ return false;
+}
+
+
+bool TransformMatrix::AssignJoint(MDagPath& dagPath, MObject& node)
+{
+ MStatus status;
+
+ MFnIkJoint jointNode(node, &status);
+ if (!status)
+ return false;
+
+ double tmp[3];
+ MQuaternion tmpQuat;
+ MEulerRotation tmpEuler;
+ MVector tmpVector;
+
+ scalePivot.x = 0.0f;
+ scalePivot.y = 0.0f;
+ scalePivot.z = 0.0f;
+
+ status = jointNode.getScale(tmp);
+ if (!status)
+ return false;
+ scaleX = (float)tmp[0];
+ scaleY = (float)tmp[1];
+ scaleZ = (float)tmp[2];
+
+ // we've officially updated a scale dependency,
+ // so set the scale matrix dirty flag
+ scaleDirty = true;
+
+ shearXY = 0.0f;
+ shearXZ = 0.0f;
+ shearYZ = 0.0f;
+
+ scalePivotTranslate.x = 0.0f;
+ scalePivotTranslate.y = 0.0f;
+ scalePivotTranslate.z = 0.0f;
+
+ rotatePivot.x = 0.0f;
+ rotatePivot.y = 0.0f;
+ rotatePivot.z = 0.0f;
+
+ // we've officially updated a hierarchy dependency,
+ // so set the hierarchy matrix dirty flag
+ hierarchyDirty = true;
+
+ status = jointNode.getScaleOrientation(tmpQuat);
+ if (!status)
+ return false;
+ tmpEuler = tmpQuat.asEulerRotation();
+ tmpEuler.reorderIt(MEulerRotation::kXYZ);
+ rotateAxisX = (float)tmpEuler.x;
+ rotateAxisY = (float)tmpEuler.y;
+ rotateAxisZ = (float)tmpEuler.z;
+
+ MTransformationMatrix::RotationOrder ro;
+ jointNode.getRotation(tmp, ro);
+ switch (ro)
+ {
+ case MTransformationMatrix::kXYZ:
+ rotateOrder = ORDER_XYZ;
+ break;
+ case MTransformationMatrix::kYZX:
+ rotateOrder = ORDER_YZX;
+ break;
+ case MTransformationMatrix::kZXY:
+ rotateOrder = ORDER_ZXY;
+ break;
+ case MTransformationMatrix::kXZY:
+ rotateOrder = ORDER_XZY;
+ break;
+ case MTransformationMatrix::kYXZ:
+ rotateOrder = ORDER_YXZ;
+ break;
+ case MTransformationMatrix::kZYX:
+ rotateOrder = ORDER_ZYX;
+ break;
+
+ default:
+ return false;
+ }
+
+ rotateX = (float)tmp[0];
+ rotateY = (float)tmp[1];
+ rotateZ = (float)tmp[2];
+
+ rotatePivotTranslate.x = 0.0f;
+ rotatePivotTranslate.y = 0.0f;
+ rotatePivotTranslate.z = 0.0f;
+
+ status = jointNode.getOrientation(tmpEuler);
+ tmpEuler.reorderIt(MEulerRotation::kXYZ);
+ jointOrientX = (float)tmpEuler.x;
+ jointOrientY = (float)tmpEuler.y;
+ jointOrientZ = (float)tmpEuler.z;
+
+ // default inverseScale to identity
+ inverseScaleX = 1.0f;
+ inverseScaleY = 1.0f;
+ inverseScaleZ = 1.0f;
+
+ // retrieve the segment scale compensate attribute
+ MFnDependencyNode depNode(node, &status);
+ if (!status)
+ return false;
+
+ MPlug plug = depNode.findPlug("segmentScaleCompensate", &status);
+ if (!status)
+ return false;
+
+ bool segmentScaleCompensate;
+ status = plug.getValue(segmentScaleCompensate);
+ if (!status)
+ return false;
+
+ // if we are compensating for parent scale, do so
+ if (segmentScaleCompensate)
+ {
+ plug = depNode.findPlug("inverseScaleX", &status);
+ if (!status)
+ return false;
+ status = plug.getValue(inverseScaleX);
+ if (!status)
+ return false;
+ if (inverseScaleX != 0.0f)
+ inverseScaleX = (1.0f / inverseScaleX);
+
+ plug = depNode.findPlug("inverseScaleY", &status);
+ if (!status)
+ return false;
+ status = plug.getValue(inverseScaleY);
+ if (!status)
+ return false;
+ if (inverseScaleY != 0.0f)
+ inverseScaleY = (1.0f / inverseScaleY);
+
+ plug = depNode.findPlug("inverseScaleZ", &status);
+ if (!status)
+ return false;
+ status = plug.getValue(inverseScaleZ);
+ if (!status)
+ return false;
+ if (inverseScaleZ != 0.0f)
+ inverseScaleZ = (1.0f / inverseScaleZ);
+ }
+
+ tmpVector = jointNode.translation(MSpace::kWorld, &status);
+ if (!status)
+ return false;
+ translate.x = (float)tmpVector.x;
+ translate.y = (float)tmpVector.y;
+ translate.z = (float)tmpVector.z;
+
+ return true;
+}
+
+
+bool TransformMatrix::Assign(const MTransformationMatrix& xform)
+{
+ MStatus status;
+ MPoint tmpPoint;
+ double tmpArray[3];
+ MQuaternion tmpQuat;
+ MEulerRotation tmpEuler;
+ MVector tmpVector;
+
+ tmpPoint = xform.scalePivot(MSpace::kWorld, &status);
+ if (!status)
+ return false;
+ scalePivot.x = (float)tmpPoint.x;
+ scalePivot.y = (float)tmpPoint.y;
+ scalePivot.z = (float)tmpPoint.z;
+
+ // we've officially updated a scale dependency,
+ // so set the scale matrix dirty flag
+ scaleDirty = true;
+
+ status = xform.getScale(tmpArray, MSpace::kWorld);
+ if (!status)
+ return false;
+ scaleX = (float)tmpArray[0];
+ scaleY = (float)tmpArray[1];
+ scaleZ = (float)tmpArray[2];
+
+ status = xform.getShear(tmpArray, MSpace::kWorld);
+ if (!status)
+ return false;
+ shearXY = (float)tmpArray[0];
+ shearXZ = (float)tmpArray[1];
+ shearYZ = (float)tmpArray[2];
+
+ tmpPoint = xform.scalePivotTranslation(MSpace::kWorld, &status);
+ if (!status)
+ return false;
+ scalePivotTranslate.x = (float)tmpPoint.x;
+ scalePivotTranslate.y = (float)tmpPoint.y;
+ scalePivotTranslate.z = (float)tmpPoint.z;
+
+ tmpPoint = xform.rotatePivot(MSpace::kWorld, &status);
+ if (!status)
+ return false;
+ rotatePivot.x = (float)tmpPoint.x;
+ rotatePivot.y = (float)tmpPoint.y;
+ rotatePivot.z = (float)tmpPoint.z;
+
+ // we've officially updated a hierarchy dependency,
+ // so set the hierarchy matrix dirty flag
+ hierarchyDirty = true;
+
+ tmpQuat = xform.rotationOrientation();
+ tmpEuler = tmpQuat.asEulerRotation();
+ tmpEuler.reorderIt(MEulerRotation::kXYZ);
+ rotateAxisX = (float)tmpEuler.x;
+ rotateAxisY = (float)tmpEuler.y;
+ rotateAxisZ = (float)tmpEuler.z;
+
+ MTransformationMatrix::RotationOrder ro = xform.rotationOrder();
+ switch (ro)
+ {
+ case MTransformationMatrix::kXYZ:
+ rotateOrder = ORDER_XYZ;
+ break;
+ case MTransformationMatrix::kYZX:
+ rotateOrder = ORDER_YZX;
+ break;
+ case MTransformationMatrix::kZXY:
+ rotateOrder = ORDER_ZXY;
+ break;
+ case MTransformationMatrix::kXZY:
+ rotateOrder = ORDER_XZY;
+ break;
+ case MTransformationMatrix::kYXZ:
+ rotateOrder = ORDER_YXZ;
+ break;
+ case MTransformationMatrix::kZYX:
+ rotateOrder = ORDER_ZYX;
+ break;
+
+ default:
+ return false;
+ }
+
+ tmpQuat = xform.rotation();
+ tmpEuler = tmpQuat.asEulerRotation();
+ switch (rotateOrder)
+ {
+ case ORDER_XYZ:
+ tmpEuler.reorderIt(MEulerRotation::kXYZ);
+ break;
+ case ORDER_YZX:
+ tmpEuler.reorderIt(MEulerRotation::kYZX);
+ break;
+ case ORDER_ZXY:
+ tmpEuler.reorderIt(MEulerRotation::kZXY);
+ break;
+ case ORDER_XZY:
+ tmpEuler.reorderIt(MEulerRotation::kXZY);
+ break;
+ case ORDER_YXZ:
+ tmpEuler.reorderIt(MEulerRotation::kYXZ);
+ break;
+ case ORDER_ZYX:
+ tmpEuler.reorderIt(MEulerRotation::kZYX);
+ break;
+
+ default:
+ return false;
+ }
+ rotateX = (float)tmpEuler.x;
+ rotateY = (float)tmpEuler.y;
+ rotateZ = (float)tmpEuler.z;
+
+ tmpVector = xform.rotatePivotTranslation(MSpace::kWorld, &status);
+ if (!status)
+ return false;
+ rotatePivotTranslate.x = (float)tmpVector.x;
+ rotatePivotTranslate.y = (float)tmpVector.y;
+ rotatePivotTranslate.z = (float)tmpVector.z;
+
+ // only used in joints
+ jointOrientX = 0.0f;
+ jointOrientY = 0.0f;
+ jointOrientZ = 0.0f;
+
+ // only used in joints
+ inverseScaleX = 1.0f;
+ inverseScaleY = 1.0f;
+ inverseScaleZ = 1.0f;
+
+ tmpVector = xform.translation(MSpace::kWorld, &status);
+ if (!status)
+ return false;
+ translate.x = (float)tmpVector.x;
+ translate.y = (float)tmpVector.y;
+ translate.z = (float)tmpVector.z;
+
+ return true;
+}
+
+
+void TransformMatrix::SetScalePivot(const tlPoint& sp)
+{
+ scalePivot = sp;
+ scaleDirty = true;
+}
+
+
+void TransformMatrix::SetScale(float x, float y, float z)
+{
+ scaleX = x;
+ scaleY = y;
+ scaleZ = z;
+ scaleDirty = true;
+}
+
+
+void TransformMatrix::SetScaleX(float x)
+{
+ scaleX = x;
+ scaleDirty = true;
+}
+
+
+void TransformMatrix::SetScaleY(float y)
+{
+ scaleY = y;
+ scaleDirty = true;
+}
+
+
+void TransformMatrix::SetScaleZ(float z)
+{
+ scaleZ = z;
+ scaleDirty = true;
+}
+
+
+void TransformMatrix::SetShear(float xy, float xz, float yz)
+{
+ shearXY = xy;
+ shearXZ = xz;
+ shearYZ = yz;
+ scaleDirty = true;
+}
+
+
+void TransformMatrix::SetShearXY(float xy)
+{
+ shearXY = xy;
+ scaleDirty = true;
+}
+
+
+void TransformMatrix::SetShearXZ(float xz)
+{
+ shearXZ = xz;
+ scaleDirty = true;
+}
+
+
+void TransformMatrix::SetShearYZ(float yz)
+{
+ shearYZ = yz;
+ scaleDirty = true;
+}
+
+
+void TransformMatrix::SetScalePivotTranslate(float x, float y, float z)
+{
+ scalePivotTranslate.x = x;
+ scalePivotTranslate.y = y;
+ scalePivotTranslate.z = z;
+ scaleDirty = true;
+}
+
+
+void TransformMatrix::SetScalePivotTranslate(const tlPoint& spt)
+{
+ scalePivotTranslate = spt;
+ scaleDirty = true;
+}
+
+
+void TransformMatrix::SetScalePivotX(float x)
+{
+ scalePivotTranslate.x = x;
+ scaleDirty = true;
+}
+
+
+void TransformMatrix::SetScalePivotY(float y)
+{
+ scalePivotTranslate.y = y;
+ scaleDirty = true;
+}
+
+
+void TransformMatrix::SetScalePivotZ(float z)
+{
+ scalePivotTranslate.z = z;
+ scaleDirty = true;
+}
+
+
+void TransformMatrix::SetRotatePivot(float x, float y, float z)
+{
+ rotatePivot.x = x;
+ rotatePivot.y = y;
+ rotatePivot.z = z;
+ hierarchyDirty = true;
+}
+
+
+void TransformMatrix::SetRotatePivot(const tlPoint& rp)
+{
+ rotatePivot = rp;
+ hierarchyDirty = true;
+}
+
+
+void TransformMatrix::SetRotatePivotX(float x)
+{
+ rotatePivot.x = x;
+ hierarchyDirty = true;
+}
+
+
+void TransformMatrix::SetRotatePivotY(float y)
+{
+ rotatePivot.y = y;
+ hierarchyDirty = true;
+}
+
+
+void TransformMatrix::SetRotatePivotZ(float z)
+{
+ rotatePivot.z = z;
+ hierarchyDirty = true;
+}
+
+
+void TransformMatrix::SetRotateAxis(float x, float y, float z)
+{
+ rotateAxisX = x;
+ rotateAxisY = y;
+ rotateAxisZ = z;
+ hierarchyDirty = true;
+}
+
+
+void TransformMatrix::SetRotateAxisX(float rax)
+{
+ rotateAxisX = rax;
+ hierarchyDirty = true;
+}
+
+
+void TransformMatrix::SetRotateAxisY(float ray)
+{
+ rotateAxisY = ray;
+ hierarchyDirty = true;
+}
+
+
+void TransformMatrix::SetRotateAxisZ(float raz)
+{
+ rotateAxisZ = raz;
+ hierarchyDirty = true;
+}
+
+
+void TransformMatrix::SetRotate(float x, float y, float z)
+{
+ rotateX = x;
+ rotateY = y;
+ rotateZ = z;
+ hierarchyDirty = true;
+}
+
+
+void TransformMatrix::SetRotateX(float x)
+{
+ rotateX = x;
+ hierarchyDirty = true;
+}
+
+
+void TransformMatrix::SetRotateY(float y)
+{
+ rotateY = y;
+ hierarchyDirty = true;
+}
+
+
+void TransformMatrix::SetRotateZ(float z)
+{
+ rotateZ = z;
+ hierarchyDirty = true;
+}
+
+
+void TransformMatrix::SetRotateOrder(RotateOrder ro)
+{
+ rotateOrder = ro;
+ hierarchyDirty = true;
+}
+
+
+void TransformMatrix::SetRotatePivotTranslate(float x, float y, float z)
+{
+ rotatePivotTranslate.x = x;
+ rotatePivotTranslate.y = y;
+ rotatePivotTranslate.z = z;
+ hierarchyDirty = true;
+}
+
+
+void TransformMatrix::SetRotatePivotTranslate(const tlPoint& rpt)
+{
+ rotatePivotTranslate = rpt;
+ hierarchyDirty = true;
+}
+
+
+void TransformMatrix::SetRotatePivotTranslateX(float x)
+{
+ rotatePivotTranslate.x = x;
+ hierarchyDirty = true;
+}
+
+
+void TransformMatrix::SetRotatePivotTranslateY(float y)
+{
+ rotatePivotTranslate.y = y;
+ hierarchyDirty = true;
+}
+
+
+void TransformMatrix::SetRotatePivotTranslateZ(float z)
+{
+ rotatePivotTranslate.z = z;
+ hierarchyDirty = true;
+}
+
+
+void TransformMatrix::SetJointOrient(float x, float y, float z)
+{
+ jointOrientX = x;
+ jointOrientY = y;
+ jointOrientZ = z;
+ hierarchyDirty = true;
+}
+
+
+void TransformMatrix::SetJointOrientX(float x)
+{
+ jointOrientX = x;
+ hierarchyDirty = true;
+}
+
+
+void TransformMatrix::SetJointOrientY(float y)
+{
+ jointOrientY = y;
+ hierarchyDirty = true;
+}
+
+
+void TransformMatrix::SetJointOrientZ(float z)
+{
+ jointOrientZ = z;
+ hierarchyDirty = true;
+}
+
+
+void TransformMatrix::SetInverseScale(float x, float y, float z)
+{
+ inverseScaleX = x;
+ inverseScaleY = y;
+ inverseScaleZ = z;
+ hierarchyDirty = true;
+}
+
+
+void TransformMatrix::SetInverseScaleX(float x)
+{
+ inverseScaleX = x;
+ hierarchyDirty = true;
+}
+
+
+void TransformMatrix::SetInverseScaleY(float y)
+{
+ inverseScaleY = y;
+ hierarchyDirty = true;
+}
+
+
+void TransformMatrix::SetInverseScaleZ(float z)
+{
+ inverseScaleZ = z;
+ hierarchyDirty = true;
+}
+
+
+void TransformMatrix::SetTranslate(float x, float y, float z)
+{
+ translate.x = x;
+ translate.y = y;
+ translate.z = z;
+ hierarchyDirty = true;
+}
+
+
+void TransformMatrix::SetTranslate(const tlPoint& t)
+{
+ translate = t;
+ hierarchyDirty = true;
+}
+
+
+void TransformMatrix::SetTranslateX(float x)
+{
+ translate.x = x;
+ hierarchyDirty = true;
+}
+
+
+void TransformMatrix::SetTranslateY(float y)
+{
+ translate.y = y;
+ hierarchyDirty = true;
+}
+
+
+void TransformMatrix::SetTranslateZ(float z)
+{
+ translate.z = z;
+ hierarchyDirty = true;
+}
+
+
+void TransformMatrix::SetScaleMatrixIdentity()
+{
+ scalePivot.x = 0.0f;
+ scalePivot.y = 0.0f;
+ scalePivot.z = 0.0f;
+
+ scaleX = 1.0f;
+ scaleY = 1.0f;
+ scaleZ = 1.0f;
+
+ shearXY = 0.0f;
+ shearXZ = 0.0f;
+ shearYZ = 0.0f;
+
+ scalePivotTranslate.x = 0.0f;
+ scalePivotTranslate.y = 0.0f;
+ scalePivotTranslate.z = 0.0f;
+
+ scaleMatrix.IdentityMatrix();
+ scaleDirty = false;
+}
+
+
+void TransformMatrix::SetHierarchyMatrixIdentity()
+{
+ rotatePivot.x = 0.0f;
+ rotatePivot.y = 0.0f;
+ rotatePivot.z = 0.0f;
+
+ rotateAxisX = 0.0f;
+ rotateAxisY = 0.0f;
+ rotateAxisZ = 0.0f;
+
+ rotateX = 0.0f;
+ rotateY = 0.0f;
+ rotateZ = 0.0f;
+
+ rotatePivotTranslate.x = 0.0f;
+ rotatePivotTranslate.y = 0.0f;
+ rotatePivotTranslate.z = 0.0f;
+
+ jointOrientX = 0.0f;
+ jointOrientY = 0.0f;
+ jointOrientZ = 0.0f;
+
+ inverseScaleX = 1.0f;
+ inverseScaleY = 1.0f;
+ inverseScaleZ = 1.0f;
+
+ translate.x = 0.0f;
+ translate.y = 0.0f;
+ translate.z = 0.0f;
+
+ hierarchyMatrix.IdentityMatrix();
+ hierarchyDirty = false;
+}
+
+
+void TransformMatrix::SetIdentity()
+{
+ SetScaleMatrixIdentity();
+ SetHierarchyMatrixIdentity();
+}
+
+
+void TransformMatrix::ComputeScaleMatrix()
+{
+ if (!scaleDirty)
+ return;
+
+ scaleMatrix.IdentityMatrix();
+ scaleMatrix.Translate(-scalePivot);
+ scaleMatrix.Scale(scaleX, scaleY, scaleZ, true);
+ scaleMatrix.Shear(shearXY, shearXZ, shearYZ);
+ scaleMatrix.Translate(scalePivot);
+ scaleMatrix.Translate(scalePivotTranslate);
+
+ scaleMatrix.Scale(inverseScaleX, inverseScaleY, inverseScaleZ, true);
+
+ scaleDirty = false;
+}
+
+
+void TransformMatrix::ComputeHierarchyMatrix()
+{
+ if (!hierarchyDirty)
+ return;
+
+ hierarchyMatrix.IdentityMatrix();
+ hierarchyMatrix.Translate(-rotatePivot);
+
+ hierarchyMatrix.RotateX(rotateAxisX);
+ hierarchyMatrix.RotateY(rotateAxisY);
+ hierarchyMatrix.RotateZ(rotateAxisZ);
+
+ switch (rotateOrder)
+ {
+ case ORDER_XYZ:
+ hierarchyMatrix.RotateX(rotateX);
+ hierarchyMatrix.RotateY(rotateY);
+ hierarchyMatrix.RotateZ(rotateZ);
+ break;
+
+ case ORDER_YZX:
+ hierarchyMatrix.RotateY(rotateY);
+ hierarchyMatrix.RotateZ(rotateZ);
+ hierarchyMatrix.RotateX(rotateX);
+ break;
+
+ case ORDER_ZXY:
+ hierarchyMatrix.RotateZ(rotateZ);
+ hierarchyMatrix.RotateX(rotateX);
+ hierarchyMatrix.RotateY(rotateY);
+ break;
+
+ case ORDER_XZY:
+ hierarchyMatrix.RotateX(rotateX);
+ hierarchyMatrix.RotateZ(rotateZ);
+ hierarchyMatrix.RotateY(rotateY);
+ break;
+
+ case ORDER_YXZ:
+ hierarchyMatrix.RotateY(rotateY);
+ hierarchyMatrix.RotateX(rotateX);
+ hierarchyMatrix.RotateZ(rotateZ);
+ break;
+
+ case ORDER_ZYX:
+ hierarchyMatrix.RotateZ(rotateZ);
+ hierarchyMatrix.RotateY(rotateY);
+ hierarchyMatrix.RotateX(rotateX);
+ break;
+ }
+
+ hierarchyMatrix.Translate(rotatePivot);
+ hierarchyMatrix.Translate(rotatePivotTranslate);
+ hierarchyMatrix.RotateX(jointOrientX);
+ hierarchyMatrix.RotateY(jointOrientY);
+ hierarchyMatrix.RotateZ(jointOrientZ);
+ //hierarchyMatrix.Scale(inverseScaleX, inverseScaleY, inverseScaleZ, true);
+ hierarchyMatrix.Translate(translate);
+
+ hierarchyDirty = false;
+}
+
+
+const tlMatrix& TransformMatrix::GetScaleMatrix() const
+{
+ const_cast<TransformMatrix*>(this)->ComputeScaleMatrix();
+ return scaleMatrix;
+}
+
+
+const tlMatrix& TransformMatrix::GetHierarchyMatrix() const
+{
+ const_cast<TransformMatrix*>(this)->ComputeHierarchyMatrix();
+ return hierarchyMatrix;
+}
+
+
+void TransformMatrix::GetScaleMatrixLHS(tlMatrix& matrix) const
+{
+ GetScaleMatrixRHS(matrix);
+ matrix.RHSToLHS();
+}
+
+
+void TransformMatrix::GetHierarchyMatrixLHS(tlMatrix& matrix) const
+{
+ GetHierarchyMatrixRHS(matrix);
+ matrix.RHSToLHS();
+}
+
+
+void TransformMatrix::GetScaleMatrixRHS(tlMatrix& matrix) const
+{
+ const_cast<TransformMatrix*>(this)->ComputeScaleMatrix();
+ matrix = scaleMatrix;
+}
+
+
+void TransformMatrix::GetHierarchyMatrixRHS(tlMatrix& matrix) const
+{
+ const_cast<TransformMatrix*>(this)->ComputeHierarchyMatrix();
+ matrix = hierarchyMatrix;
+}
+
+
+// End of file.
+
diff --git a/tools/globalcode/utility/transformmatrix.h b/tools/globalcode/utility/transformmatrix.h
new file mode 100644
index 0000000..4d0e175
--- /dev/null
+++ b/tools/globalcode/utility/transformmatrix.h
@@ -0,0 +1,247 @@
+#include "precompiled/PCH.h"
+
+/*===========================================================================
+ transformmatrix.hpp
+ Created: October 16, 2000
+ Auuthor: Bryan Brandt
+
+ Copyright (c) 2000 Radical Entertainment, Inc.
+ All rights reserved.
+===========================================================================*/
+#ifndef _TRANSFORMMATRIX_HPP
+#define _TRANSFORMMATRIX_HPP
+
+#ifdef WORLD_BUILDER
+#include "main/toolhack.h"
+#endif
+#include <toollib.hpp>
+
+
+class MObject;
+class MDagPath;
+class MFnTransform;
+class MFnIkJoint;
+class MTransformationMatrix;
+
+
+class TransformMatrix
+{
+public:
+
+ enum RotateOrder
+ {
+ ORDER_XYZ = 0,
+ ORDER_YZX,
+ ORDER_ZXY,
+ ORDER_XZY,
+ ORDER_YXZ,
+ ORDER_ZYX
+ };
+
+ TransformMatrix();
+ TransformMatrix(const MDagPath& dagPath);
+ TransformMatrix(const MTransformationMatrix& xform);
+
+ bool Assign(const MDagPath& dagPath);
+ bool Assign(const MTransformationMatrix& xform);
+
+ void SetScalePivot(float x, float y, float z);
+ void SetScalePivot(const tlPoint& sp);
+ void SetScalePivotX(float x);
+ void SetScalePivotY(float y);
+ void SetScalePivotZ(float z);
+ const tlPoint& GetScalePivot() const
+ { return scalePivot; }
+ float GetScalePivotX() const
+ { return scalePivot.x; }
+ float GetScalePivotY() const
+ { return scalePivot.y; }
+ float GetScalePivotZ() const
+ { return scalePivot.z; }
+
+ void SetScale(float x, float y, float z);
+ void SetScaleX(float x);
+ void SetScaleY(float y);
+ void SetScaleZ(float z);
+ float GetScaleX() const
+ { return scaleX; }
+ float GetScaleY() const
+ { return scaleY; }
+ float GetScaleZ() const
+ { return scaleZ; }
+
+ void SetShear(float xy, float xz, float yz);
+ void SetShearXY(float xy);
+ void SetShearXZ(float xz);
+ void SetShearYZ(float yz);
+ float GetShearXY() const
+ { return shearXY; }
+ float GetShearXZ() const
+ { return shearXZ; }
+ float GetShearYZ() const
+ { return shearYZ; }
+
+ void SetScalePivotTranslate(float x, float y, float z);
+ void SetScalePivotTranslate(const tlPoint& spt);
+ void SetScalePivotTranslateX(float x);
+ void SetScalePivotTranslateY(float y);
+ void SetScalePivotTranslateZ(float z);
+ const tlPoint& GetScalePivotTranslate() const
+ { return scalePivotTranslate; }
+ float GetScalePivotTranslateX() const
+ { return scalePivotTranslate.x; }
+ float GetScalePivotTranslateY() const
+ { return scalePivotTranslate.y; }
+ float GetScalePivotTranslateZ() const
+ { return scalePivotTranslate.z; }
+
+ void SetRotatePivot(float x, float y, float z);
+ void SetRotatePivot(const tlPoint& rp);
+ void SetRotatePivotX(float x);
+ void SetRotatePivotY(float y);
+ void SetRotatePivotZ(float z);
+ const tlPoint& GetRotatePivot() const
+ { return rotatePivot; }
+ float GetRotatePivotX() const
+ { return rotatePivot.x; }
+ float GetRotatePivotY() const
+ { return rotatePivot.y; }
+ float GetRotatePivotZ() const
+ { return rotatePivot.z; }
+
+ void SetRotateAxis(float x, float y, float z);
+ void SetRotateAxisX(float rax);
+ void SetRotateAxisY(float ray);
+ void SetRotateAxisZ(float raz);
+ float GetRotateAxisX() const
+ { return rotateAxisX; }
+ float GetRotateAxisY() const
+ { return rotateAxisY; }
+ float GetRotateAxisZ() const
+ { return rotateAxisZ; }
+
+ void SetRotateOrder(RotateOrder ro);
+ RotateOrder GetRotateOrder() const
+ { return rotateOrder; }
+
+ void SetRotate(float x, float y, float z);
+ void SetRotateX(float x);
+ void SetRotateY(float y);
+ void SetRotateZ(float z);
+ float GetRotateX() const
+ { return rotateX; }
+ float GetRotateY() const
+ { return rotateY; }
+ float GetRotateZ() const
+ { return rotateZ; }
+
+ void SetRotatePivotTranslate(float x, float y, float z);
+ void SetRotatePivotTranslate(const tlPoint& rpt);
+ void SetRotatePivotTranslateX(float x);
+ void SetRotatePivotTranslateY(float y);
+ void SetRotatePivotTranslateZ(float z);
+ const tlPoint& GetRotatePivotTranslate() const
+ { return rotatePivotTranslate; }
+ float GetRotatePivotTranslateX() const
+ { return rotatePivotTranslate.x; }
+ float GetRotatePivotTranslateY() const
+ { return rotatePivotTranslate.y; }
+ float GetRotatePivotTranslateZ() const
+ { return rotatePivotTranslate.z; }
+
+ void SetJointOrient(float x, float y, float z);
+ void SetJointOrientX(float x);
+ void SetJointOrientY(float y);
+ void SetJointOrientZ(float z);
+ float GetJointOrientX() const
+ { return jointOrientX; }
+ float GetJointOrientY() const
+ { return jointOrientY; }
+ float GetJointOrientZ() const
+ { return jointOrientZ; }
+
+ void SetInverseScale(float x, float y, float z);
+ void SetInverseScaleX(float x);
+ void SetInverseScaleY(float y);
+ void SetInverseScaleZ(float z);
+ float GetInverseScaleX() const
+ { return inverseScaleX; }
+ float GetInverseScaleY() const
+ { return inverseScaleY; }
+ float GetInverseScaleZ() const
+ { return inverseScaleZ; }
+
+ void SetTranslate(float x, float y, float z);
+ void SetTranslate(const tlPoint& t);
+ void SetTranslateX(float x);
+ void SetTranslateY(float y);
+ void SetTranslateZ(float z);
+ const tlPoint& GetTranslate() const
+ { return translate; }
+ float GetTranslateX() const
+ { return translate.x; }
+ float GetTranslateY() const
+ { return translate.y; }
+ float GetTranslateZ() const
+ { return translate.z; }
+
+ void SetScaleMatrixIdentity();
+ void SetHierarchyMatrixIdentity();
+ void SetIdentity();
+
+ // these are the outputs of this class:
+ // scale matrix - to be baked into the mesh
+ // hierarchy matrix - stored in the skeleton
+ const tlMatrix& GetScaleMatrix() const;
+ const tlMatrix& GetHierarchyMatrix() const;
+
+ // routines for extracting the above matrices,
+ // except with an option to change coordinate systems
+ //
+ void GetScaleMatrixLHS(tlMatrix& matrix) const;
+ void GetHierarchyMatrixLHS(tlMatrix& matrix) const;
+ void GetScaleMatrixRHS(tlMatrix& matrix) const;
+ void GetHierarchyMatrixRHS(tlMatrix& matrix) const;
+
+private:
+
+ bool AssignJoint(MDagPath& dagPath, MObject& jointNode);
+
+ void ComputeScaleMatrix();
+ void ComputeHierarchyMatrix();
+
+ tlPoint scalePivot;
+ float scaleX;
+ float scaleY;
+ float scaleZ;
+ float shearXY;
+ float shearXZ;
+ float shearYZ;
+ tlPoint scalePivotTranslate;
+ tlPoint rotatePivot;
+ float rotateAxisX;
+ float rotateAxisY;
+ float rotateAxisZ;
+ RotateOrder rotateOrder;
+ float rotateX;
+ float rotateY;
+ float rotateZ;
+ tlPoint rotatePivotTranslate;
+ float jointOrientX;
+ float jointOrientY;
+ float jointOrientZ;
+ float inverseScaleX;
+ float inverseScaleY;
+ float inverseScaleZ;
+ tlPoint translate;
+
+ bool scaleDirty;
+ bool hierarchyDirty;
+
+ tlMatrix scaleMatrix;
+ tlMatrix hierarchyMatrix;
+};
+
+
+#endif // _TRANSFORMMATRIX_HPP
+
diff --git a/tools/globalcode/utility/util.c b/tools/globalcode/utility/util.c
new file mode 100644
index 0000000..79764df
--- /dev/null
+++ b/tools/globalcode/utility/util.c
@@ -0,0 +1,724 @@
+/*-----------------------------------------------------------------------------
+** Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+**
+** winutil.h
+**
+** Description: A set of utilities which are specific to the windows development
+** environment.
+**
+** Modification History:
+** + Created Aug 03, 2001 -- bkusy
+**---------------------------------------------------------------------------*/
+
+/*----------------------------------------
+** System Includes
+**--------------------------------------*/
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+
+/*----------------------------------------
+** Project Includes
+**--------------------------------------*/
+#include "util.h"
+
+/*----------------------------------------
+** Constants
+**--------------------------------------*/
+#define BUFFER_SIZE 512
+
+/*----------------------------------------
+** Globals
+**--------------------------------------*/
+char* util_optarg;
+int util_optind;
+int util_opterr = 1;
+int util_optopt;
+
+
+/*-----------------------------------------------------------------------------
+** u t i l _ b a s e n a m e
+**
+** Synopsis: Determine the basename in a file path. ( eg/ would return
+** "newfile.c" from the path "/usr/home/newfile.c".
+**
+** Parameters: buffer - buffer to receive basename.
+** size - size of buffer.
+** path - path to determine basename from.
+**
+** Returns: non-zero if successful, 0 if buffer is too small.
+**
+** Constraints: path must use '/' and not '\' as directory separators.
+**
+**---------------------------------------------------------------------------*/
+int util_basename( char* buffer, int size, const char* path )
+{
+ char* d;
+ char* n;
+ char* e;
+ int length;
+ int result = 0;
+
+ assert( buffer );
+
+ util_decomposeFilePath( path, &d, &n, &e );
+
+ length = strlen( n ) + strlen( e ) + 1;
+
+ if ( length < size )
+ {
+ strcpy( buffer, n );
+ strcat( buffer, "." );
+ strcat( buffer, e );
+
+ result = 1;
+ }
+
+ return result;
+}
+/*-----------------------------------------------------------------------------
+** u t i l _ c h a n g e F i l e E x t e n s i o n
+**
+** Synopsis: Changes the file extension in the given buffer to the given
+** given extension.
+**
+** Parameters: buffer - the file path to be modified.
+** ext - the new file extension.
+**
+** Returns: NOTHING
+**
+** Constraints: If the original file path does not have an extension, as
+** identified by the presence of a "." character, no change will
+** take place.
+** If the new extension is longer than the old extension, no
+** change will take place.
+**
+**---------------------------------------------------------------------------*/
+void util_changeFileExtension( char* buffer, const char* ext )
+{
+ char* oldExt = 0;
+
+ assert( buffer );
+ assert( ext );
+
+ oldExt = (char*)(util_rindex( buffer, '.' ));
+
+ if ( oldExt )
+ {
+ oldExt++;
+
+ if ( strlen( oldExt ) <= strlen( ext ) )
+ {
+ strcpy( oldExt, ext );
+ }
+ }
+}
+
+/*-----------------------------------------------------------------------------
+** u t i l _ d e c o m p o s e F i l e P a t h
+**
+** Synopsis: Decompose a file path into its directory, filename and extension.
+**
+** Parameters: path - the path to decompose.
+** dir - a pointer which will be set to the start of the directory.
+** name - a pointer which will be set to the start of the name.
+** ext - a pointer which will be set to the start of the extension.
+**
+** Returns: NOTHING
+**
+** Constraints: path must use '/' and not '\' as directory separators. The pointers
+** returned in dir, name, and ext are only valid until the next call
+** to util_DecomposePath().
+**
+**---------------------------------------------------------------------------*/
+void util_decomposeFilePath( const char* path, char** dir, char** name, char** ext )
+{
+ static char buffer[ BUFFER_SIZE + 1 ];
+ strncpy( buffer, path, BUFFER_SIZE );
+
+ *ext = strrchr( buffer, '.' );
+ if ( *ext )
+ {
+ /*
+ * Remove the extension by replacing '.' with a NULL character.
+ */
+ **ext = '\0';
+
+ /*
+ * The extension will be in the next position.
+ */
+ (*ext)++;
+ }
+
+ *name = strrchr( buffer, '/' );
+ if ( *name )
+ {
+ /*
+ * Remove the name by replacing the last '/' with a NULL character.
+ */
+ **name = '\0';
+
+ /*
+ * The name will be in the next position.
+ */
+ (*name)++;
+
+ /*
+ * Set dir to the start of the string and we are done.
+ */
+ *dir = buffer;
+ }
+ else
+ {
+ /*
+ * Name must extend to the beginning of the path. Set the name pointer
+ * accordingly and set dir to null.
+ */
+ *name = buffer;
+ *dir = 0;
+ }
+}
+
+/*-----------------------------------------------------------------------------
+** u t i l _ d i r n a m e
+**
+** Synopsis: Determine the directory in a file path.
+**
+** Parameters: buffer - buffer to recieve directory.
+** size - size of buffer.
+** path - the path to retrieve the directory from.
+**
+** Returns: non-zero if successful, zero if buffer is too small to receive
+** the directory.
+**
+** Constraints: path must use '/' and not '\' as directory separators.
+**
+**---------------------------------------------------------------------------*/
+int util_dirname( char* buffer, int size, const char* path )
+{
+ char* d;
+ char* n;
+ char* e;
+ int length;
+ int result = 0;
+
+ util_decomposeFilePath( path, &d, &n, &e );
+
+ length = strlen( d );
+ if ( length < size )
+ {
+ strcpy( buffer, d );
+ result = 1;
+ }
+
+ return result;
+}
+
+/*-----------------------------------------------------------------------------
+** u t i l _ f i l e E x i s t s
+**
+** Synopsis: Determines if the give file exists.
+**
+** Parameters: filename - the name of the file to check for existence.
+**
+** Returns: 0 if file does not exist, non-zero otherwise.
+**
+** Constraints:
+**
+**---------------------------------------------------------------------------*/
+int util_fileExists( const char* filename )
+{
+ FILE *fp;
+
+ assert( filename );
+
+ fp = fopen( filename, "r" );
+
+ if ( fp )
+ {
+ fclose( fp );
+ return 1;
+ }
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------------------
+** u t i l _ g e t o p t _ i n i t
+**
+** Synopsis: Initializes the getopt parser.
+**
+** Parameters: NONE
+**
+** Returns: NOTHING
+**
+** Constraints: NONE
+**
+** Author: Angus Mackay
+**
+**---------------------------------------------------------------------------*/
+void util_getopt_init()
+{
+ util_optind = 1;
+}
+
+/*-----------------------------------------------------------------------------
+** u t i l _ g e t o p t
+**
+** Synopsis: Used to parse command line arguments based on a specified
+** syntax. The argument for the current option is stored in
+** the global variable "util_optarg".
+**
+** Parameters: argc - the number of arguments in the array.
+** argv - the argumnet array.
+** opts - option specifier string. Options can be of two forms:
+** boolean flags ( its either there or it isn't ) and
+** flag value pairs in which a flag is always followed
+** by some value. Options which require an argument
+** must be followed by a ":" in the option specifier
+** string. So for a command which can have two boolean
+** flags, "h" and "i", and two argument flags, "t" and
+** "u", the following option specifier string would be
+** used: "hit:u:".
+**
+** Returns: the option character found, or -1 if no more option
+** characters.
+**
+** Constraints: NONE
+**
+** Author: Angus Mackay
+**
+**---------------------------------------------------------------------------*/
+int util_getopt( int argc, char* const* argv, const char* opts )
+{
+ static int init_done = 0;
+ static int suboptionpos = 1;
+
+ if(!init_done) { util_getopt_init(); init_done = 1; }
+
+ util_optarg = NULL;
+
+ if(util_optind == argc)
+ {
+ /* we are done */
+ return(-1);
+ }
+
+ if(argv[util_optind][0] == '-')
+ {
+ char *argp;
+
+ /* test for end of arg marker */
+ if(argv[util_optind][1] == '-' && argv[util_optind][2] == '\0')
+ {
+ suboptionpos = 1;
+ util_optind++;
+ return(-1);
+ }
+
+ for(argp=&(argv[util_optind][suboptionpos]); *argp != '\0'; argp++)
+ {
+ char *optp;
+ int numcolon = 0;
+ char *p;
+
+ if((optp=strchr(opts, *argp)) == NULL)
+ {
+ if(util_opterr != 0)
+ {
+ fprintf(stderr, "%s: illegal option -- %c\n", argv[0], *argp);
+ }
+ util_optopt = *argp;
+ suboptionpos++;
+ if(argv[util_optind][suboptionpos] == '\0')
+ {
+ suboptionpos = 1;
+ util_optind++;
+ }
+ return('?');
+ }
+
+ /* zero, one or two colons? */
+ for(p=(optp+1); *p == ':'; p++) { numcolon++; }
+ switch(numcolon)
+ {
+ /* no argument */
+ case 0:
+ suboptionpos++;
+ if(argv[util_optind][suboptionpos] == '\0')
+ {
+ suboptionpos = 1;
+ util_optind++;
+ }
+ return(*optp);
+ break;
+
+ /* manditory argument */
+ case 1:
+ /* the argument is seperated by a space */
+ if(argp[1] == '\0')
+ {
+ /* ther are more args */
+ if(util_optind+1 == argc)
+ {
+ suboptionpos++;
+ if(argv[util_optind][suboptionpos] == '\0')
+ {
+ suboptionpos = 1;
+ util_optind++;
+ }
+ if(util_opterr != 0)
+ {
+ fprintf(stderr, "%s: option requires an argument -- %c\n",
+ argv[0], *argp);
+ }
+ util_optopt = *argp;
+ return('?');
+ }
+
+ util_optind++;
+ suboptionpos = 1;
+ util_optarg = argv[util_optind];
+ util_optind++;
+ return(*optp);
+ }
+
+ /* the argument is attached */
+ util_optarg = argp+1;
+ suboptionpos = 1;
+ util_optind++;
+ return(*optp);
+ break;
+
+ /* optional argument */
+ case 2:
+ /* the argument is seperated by a space */
+ if(argp[1] == '\0')
+ {
+ util_optind++;
+ suboptionpos = 1;
+ util_optarg = NULL;
+ return(*optp);
+ }
+
+ /* the argument is attached */
+ suboptionpos = 1;
+ util_optarg = argp+1;
+ util_optind++;
+ return(*optp);
+ break;
+
+ /* a case of too many colons */
+ default:
+ suboptionpos++;
+ if(argv[util_optind][suboptionpos] == '\0')
+ {
+ suboptionpos = 1;
+ util_optind++;
+ }
+ util_optopt = '?';
+ return('?');
+ break;
+ }
+ }
+ suboptionpos = 1;
+ }
+ else
+ {
+ /* we are done */
+ return(-1);
+ }
+
+ /* we shouldn't get here */
+ return(-1);
+}
+
+/*-----------------------------------------------------------------------------
+** u t i l _ i n d e x
+**
+** Synopsis: returns a pointer to the first occurrence of the character
+** "c" in the string "s".
+**
+** Parameters: s - the string to search.
+** c - the character to search for.
+**
+** Returns: a pointer to the matched character, or NULL if the character
+** is not found.
+**
+** Constraints: NONE
+**
+**---------------------------------------------------------------------------*/
+const char* util_index( const char* s, int c )
+{
+ const char* result = 0;
+ const char* sp = 0;
+
+ assert( s );
+
+ sp = s;
+
+ while ( *sp != '\0' )
+ {
+ if ( *sp == c )
+ {
+ result = sp;
+ break;
+ }
+
+ sp++;
+ }
+
+ return result;
+}
+
+/*-----------------------------------------------------------------------------
+** u t i l _ p o s i x F i l e P a t h
+**
+** Synopsis: Ensures the given path uses POSIX style slashes.
+**
+** Parameters: path - the path to "posixfy".
+**
+** Returns: NOTHING
+**
+** Constraints: NONE
+**
+**---------------------------------------------------------------------------*/
+void util_posixFilePath( char* path )
+{
+ char* pp = path;
+ while ( *pp )
+ {
+ if ( '\\' == *pp ) *pp = '/';
+ pp++;
+ }
+}
+
+/*-----------------------------------------------------------------------------
+** u t i l _ r e p l a c e C h a r a c t e r s
+**
+** Synopsis: Replace characters in a string.
+**
+** Parameters: find - the character to find.
+** replace - the charcter to replace the found character with.
+** string - the string within which to do the find/replace.
+**
+** Returns: NOTHING
+**
+** Constraints: NONE
+**
+**---------------------------------------------------------------------------*/
+void util_replaceCharacters( char find, char replace, char* string )
+{
+ char* p = 0;
+
+ if ( string )
+ {
+ while ( p = strchr( string, find ) )
+ {
+ *p = replace;
+ }
+ }
+}
+
+/*-----------------------------------------------------------------------------
+** u t i l _ r e v e r s e S p a n
+**
+** Synopsis: Finds the suffix which is composed completely of characters in
+** in the spanSet in the specified string.
+**
+** Example: end = util_ReverseSpan( "name123", "312" );
+** *
+** * end now points to "123".
+** *
+** end = util_ReverseSpan( "name123", "21" );
+** *
+** * end would point to NULL because the character "3" is not
+** * in the spanSet.
+**
+** Parameters: string - the string to be searched.
+** spanSet - a string of characters that can be in the suffix.
+**
+** Returns: a pointer to the suffix string, or NULL if there is no
+** suffix.
+**
+** Constraints: NONE
+**
+**---------------------------------------------------------------------------*/
+const char* util_reverseSpan( const char* string, const char* spanSet )
+{
+ const char* sp = 0;
+ const char* next_sp = 0;
+ int isEndSpan = 0;
+
+ /*
+ * Set a pointer to the end of the string to be searched.
+ */
+ sp = string + strlen( string );
+
+ /*
+ * If the string passed in is empty, we are done.
+ */
+ if ( sp == string ) return sp;
+
+ while( sp > string && !isEndSpan )
+ {
+ next_sp = sp - 1;
+
+ if ( strchr( spanSet, *next_sp ) )
+ {
+ sp--;
+ }
+ else
+ {
+ isEndSpan = 1;
+ }
+ }
+
+ return sp;
+}
+
+/*-----------------------------------------------------------------------------
+** u t i l _ r i n d e x
+**
+** Synopsis: returns a pointer to the last occurrence of the character
+** "c" in the string "s".
+**
+** Parameters: s - the string to search.
+** c - the character to search for.
+**
+** Returns: a pointer to the matched character, or NULL if the character
+** is not found.
+**
+** Constraints: NONE
+**
+**---------------------------------------------------------------------------*/
+const char* util_rindex( const char* s, int c )
+{
+ const char* result = 0;
+ const char* sp = 0;
+ int length;
+
+ assert( s );
+
+ length = strlen(s);
+ sp = s + length;
+
+ if ( length > 0 )
+ {
+ while ( sp != s )
+ {
+ sp--;
+
+ if ( *sp == c )
+ {
+ result = sp;
+ break;
+ }
+ }
+ }
+
+ return result;
+}
+
+/*-----------------------------------------------------------------------------
+** u t i l _ s u b s t i t u t e
+**
+** Synopsis: Substitue strings matchin "find" with "replace" in "string".
+** If this cannot be done without exceeding the size of "string"
+** An error will be returned and "string" will be as it was
+** when util_substitute was originally called.
+**
+** Parameters: find - the substring to find.
+** replace - the substring to insert in place of found strings.
+** string - the string to operate on.
+** stringSize - the maximum size the string can grow to.
+** firstOnly - flag. If non-zero only the first occurence of
+** "find" will be replaced. If zero, all occurences
+** will be replaced.
+**
+** Returns: 0 on error, the new size of the string on success.
+**
+** Constraints: NONE
+**
+**---------------------------------------------------------------------------*/
+int util_substitute( const char* find,
+ const char* replace,
+ char* string,
+ int stringSize,
+ int firstOnly
+ )
+{
+ char buffer[ BUFFER_SIZE + 1 ];
+ char* sp;
+ char* bp;
+ char* p;
+ int findLength = strlen( find );
+ int replaceLength = strlen( replace );
+ int count = 0;
+ int total = 0;
+ int tooBig = 0;
+ int status = 0;
+
+ assert( stringSize <= BUFFER_SIZE );
+
+ bp = buffer;
+ sp = string;
+ while( !tooBig && (p = strstr( sp, find )) )
+ {
+ /*
+ * Determine the number of characters since last find.
+ * Add to total characters.
+ * If total characters exceeds "stringSize" then break and return
+ * error. Otherwise copy characters since last find to buffer.
+ */
+ count = p - sp;
+ total += count;
+ if ( total >= stringSize )
+ {
+ tooBig = 1;
+ continue;
+ }
+ strncpy( bp, sp, count );
+ bp += count;
+ *bp = '\0';
+
+ /*
+ * If adding the replace string causes buffer to exceed "stringSize"
+ * break and return error. Otherwise copy the replace string into
+ * buffer.
+ */
+ total += replaceLength;
+ if ( total >= stringSize )
+ {
+ tooBig = 1;
+ continue;
+ }
+ strcpy( bp, replace );
+ bp += replaceLength;
+
+ /*
+ * Update the position of sp so that it points to next character
+ * after the last found "find" string.
+ */
+ sp += count + findLength;
+ }
+
+ if ( !tooBig )
+ {
+ /*
+ * Attempt to copy the remaining portion of string into buffer.
+ * If successful, copy buffer into string and return success.
+ * Otherwise return error.
+ */
+ total += strlen( sp );
+ if ( total < stringSize )
+ {
+ strcpy( bp, sp );
+ strcpy( string, buffer );
+ status = strlen( string );
+ }
+ }
+
+ return status;
+}
+
diff --git a/tools/globalcode/utility/util.h b/tools/globalcode/utility/util.h
new file mode 100644
index 0000000..33a6d84
--- /dev/null
+++ b/tools/globalcode/utility/util.h
@@ -0,0 +1,88 @@
+#ifndef _UTIL_H
+#define _UTIL_H
+/*-----------------------------------------------------------------------------
+** Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+**
+** util.h
+**
+** Description: A set of utilities for various things.
+**
+** Modification History:
+** + Created Aug 03, 2001 -- bkusy
+**---------------------------------------------------------------------------*/
+
+/*----------------------------------------
+** System Includes
+**--------------------------------------*/
+
+/*----------------------------------------
+** Project Includes
+**--------------------------------------*/
+
+/*----------------------------------------
+** Forward References
+**--------------------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*----------------------------------------
+** Globals
+**--------------------------------------*/
+extern char* util_optarg;
+extern int util_optind;
+extern int util_opterr;
+extern int util_optopt;
+
+/*----------------------------------------
+** Macros
+**--------------------------------------*/
+
+
+/*----------------------------------------
+** Functions
+**--------------------------------------*/
+
+extern int util_basename( char* buffer, int size, const char* path );
+
+extern void util_changeFileExtension( char* buffer, const char* ext );
+
+extern void util_decomposeFilePath( const char* path,
+ char** dir,
+ char** name,
+ char** ext
+ );
+
+extern int util_dirname( char* buffer, int size, const char* path );
+
+extern int util_fileExists( const char* filename );
+
+extern void util_getopt_init();
+
+extern int util_getopt( int argc, char* const* argv, const char *opts );
+
+extern const char* util_index( const char* s, int c );
+
+extern void util_posixFilePath( char* path );
+
+extern void util_replaceCharacters( char find,
+ char replace,
+ char* string
+ );
+
+extern const char* util_reverseSpan( const char* string, const char* spanSet );
+
+extern const char* util_rindex( const char* s, int c );
+
+extern int util_substitute( const char* find,
+ const char* replace,
+ char* string,
+ int stringSize,
+ int firstOnly
+ );
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/tools/globalcode/utility/winutil.c b/tools/globalcode/utility/winutil.c
new file mode 100644
index 0000000..9493c8b
--- /dev/null
+++ b/tools/globalcode/utility/winutil.c
@@ -0,0 +1,69 @@
+//-----------------------------------------------------------------------------
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// winutil.h
+//
+// Description: A set of utilities which are specific to the windows development
+// environment.
+//
+// Modification History:
+// + Created Aug 03, 2001 -- bkusy
+//-----------------------------------------------------------------------------
+
+//----------------------------------------
+// System Includes
+//----------------------------------------
+#include <windows.h>
+#include <stdio.h>
+#include <assert.h>
+
+//----------------------------------------
+// Project Includes
+//----------------------------------------
+#include "winutil.h"
+
+//----------------------------------------
+// Constants
+//----------------------------------------
+#define BUFFER_SIZE 256
+
+
+//-----------------------------------------------------------------------------
+// w i n u t i l _ V e r s i o n I n f o
+//
+// Synopsis: Retrieve a version info string for the specified module.
+//
+// Parameters: name - the module to retrieve the information for.
+// info - a reference parameter to receive the info string.
+// info_size - the size of the buffer pointed to by info.
+//
+// Returns: the length of the string returned in info.
+//
+// Constraints: NONE
+//
+//-----------------------------------------------------------------------------
+int winutil_VersionInfo( const char* name, char* info, int info_size )
+{
+ char buffer[ BUFFER_SIZE + 1 ];
+ char* data = 0;
+ DWORD data_length, unused;
+ VS_FIXEDFILEINFO* fixed_file_info;
+ UINT fixed_file_info_length;
+ int major, minor;
+ int result;
+
+ GetModuleFileName( GetModuleHandle( name ), buffer, BUFFER_SIZE );
+ data_length = GetFileVersionInfoSize( buffer, &unused );
+ data = calloc( data_length, sizeof( char ) );
+ assert( data );
+ GetFileVersionInfo( buffer, unused, data_length, data );
+ VerQueryValue( data, "\\", (void**)(&fixed_file_info), &fixed_file_info_length );
+
+ major = fixed_file_info->dwFileVersionMS >> 16;
+ minor = fixed_file_info->dwFileVersionMS & 0x0ffff;
+ result = _snprintf( info, info_size, "%d.%d", major, minor );
+ return result;
+}
+
+
+
diff --git a/tools/globalcode/utility/winutil.h b/tools/globalcode/utility/winutil.h
new file mode 100644
index 0000000..bfe19ec
--- /dev/null
+++ b/tools/globalcode/utility/winutil.h
@@ -0,0 +1,37 @@
+#ifndef _WINUTIL_H
+#define _WINUTIL_H
+//-----------------------------------------------------------------------------
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// winutil.h
+//
+// Description: A set of utilities which are specific to the windows development
+// environment.
+//
+// Modification History:
+// + Created Aug 03, 2001 -- bkusy
+//-----------------------------------------------------------------------------
+
+//----------------------------------------
+// System Includes
+//----------------------------------------
+
+//----------------------------------------
+// Project Includes
+//----------------------------------------
+
+//----------------------------------------
+// Forward References
+//----------------------------------------
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int winutil_VersionInfo( const char* name, char* info, int info_size );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif