diff options
author | Svxy <aidan61605@gmail.com> | 2023-05-31 23:31:32 +0200 |
---|---|---|
committer | Svxy <aidan61605@gmail.com> | 2023-05-31 23:31:32 +0200 |
commit | eb4b3404aa00220d659e532151dab13d642c17a3 (patch) | |
tree | 7e1107c4995489a26c4007e41b53ea8d00ab2134 /tools/globalcode/utility | |
download | The-Simpsons-Hit-and-Run-TSH&R-PC.tar The-Simpsons-Hit-and-Run-TSH&R-PC.tar.gz The-Simpsons-Hit-and-Run-TSH&R-PC.tar.bz2 The-Simpsons-Hit-and-Run-TSH&R-PC.tar.lz The-Simpsons-Hit-and-Run-TSH&R-PC.tar.xz The-Simpsons-Hit-and-Run-TSH&R-PC.tar.zst The-Simpsons-Hit-and-Run-TSH&R-PC.zip |
Diffstat (limited to 'tools/globalcode/utility')
-rw-r--r-- | tools/globalcode/utility/GLExt.cpp | 1129 | ||||
-rw-r--r-- | tools/globalcode/utility/GLExt.h | 191 | ||||
-rw-r--r-- | tools/globalcode/utility/MExt.cpp | 2030 | ||||
-rw-r--r-- | tools/globalcode/utility/MExt.h | 226 | ||||
-rw-r--r-- | tools/globalcode/utility/MExt_template.cpp | 273 | ||||
-rw-r--r-- | tools/globalcode/utility/MExt_template.h | 146 | ||||
-rw-r--r-- | tools/globalcode/utility/MUI.cpp | 220 | ||||
-rw-r--r-- | tools/globalcode/utility/MUI.h | 82 | ||||
-rw-r--r-- | tools/globalcode/utility/mayahandles.cpp | 105 | ||||
-rw-r--r-- | tools/globalcode/utility/mayahandles.h | 42 | ||||
-rw-r--r-- | tools/globalcode/utility/nodehelper.h | 37 | ||||
-rw-r--r-- | tools/globalcode/utility/overlaymarquee.cpp | 222 | ||||
-rw-r--r-- | tools/globalcode/utility/overlaymarquee.h | 55 | ||||
-rw-r--r-- | tools/globalcode/utility/stdafx.h | 19 | ||||
-rw-r--r-- | tools/globalcode/utility/transformmatrix.cpp | 904 | ||||
-rw-r--r-- | tools/globalcode/utility/transformmatrix.h | 247 | ||||
-rw-r--r-- | tools/globalcode/utility/util.c | 724 | ||||
-rw-r--r-- | tools/globalcode/utility/util.h | 88 | ||||
-rw-r--r-- | tools/globalcode/utility/winutil.c | 69 | ||||
-rw-r--r-- | tools/globalcode/utility/winutil.h | 37 |
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 |