Files
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

4047 lines
135 KiB
C++

//
// rageShaderMaya65/rageShaderMaya65.cpp
//
// Copyright (C) 1999-2006 Rockstar Games. All Rights Reserved.
//
#ifdef WIN32
#pragma warning( disable : 4786 ) // Disable stupid STL warnings.
#endif
#define REQUIRE_IOSTREAM
#pragma warning(push)
#pragma warning(disable : 4668)
#include <windows.h>
#include <math.h>
#include <maya/MString.h>
#include <maya/MPlug.h>
#include <maya/MPlugArray.h>
#include <maya/MDataBlock.h>
#include <maya/MDataHandle.h>
#include <maya/MArrayDataHandle.h>
#include <maya/MFnNumericAttribute.h>
#include <maya/MFnTypedAttribute.h>
#include <maya/MFnCompoundAttribute.h>
#include <maya/MFnLightDataAttribute.h>
#include <maya/MFloatVector.h>
#include <maya/MFloatMatrix.h>
#include <maya/MFnStringData.h>
#include <maya/MItDependencyNodes.h>
#include <maya/MGlobal.h>
#include <maya/M3dView.h>
#include <maya/MRenderUtil.h>
#include <maya/MHardwareRenderer.h>
#include <maya/MGeometryData.h>
#include <maya/MHWShaderSwatchGenerator.h>
#include <maya/MPoint.h>
#include <maya/MMatrix.h>
#include <maya/MVector.h>
#include <maya/MFnMesh.h>
#include <maya/MEulerRotation.h>
#include <maya/MDagPath.h>
#include <maya/MFnDependencyNode.h>
#include <maya/MNodeMessage.h>
#include <maya/MFnEnumAttribute.h>
#include <maya/MItSelectionList.h>
#include <maya/MFloatPointArray.h>
#include <maya/MDGMessage.h>
#include <maya/MPolyMessage.h>
#include <maya/MUiMessage.h>
#include <maya/MSceneMessage.h>
#include <maya/MDGModifier.h>
#include <maya/MItDependencyGraph.h>
#pragma warning(error: 4668)
#include <GL/gl.h>
#include <GL/glu.h>
#include "system/param.h"
#include "parser/manager.h"
#include "file/asset.h"
#include "file/stream.h"
#include "file/token.h"
#include "file/device.h"
#include "vector/matrix34.h"
#include "rageShaderMaterial/rageShaderMaterialTemplate.h"
#include "shaderMaterial/shaderMaterialGeoParamValueBool.h"
#include "shaderMaterial/shaderMaterialGeoParamValueMatrix34.h"
#include "shaderMaterial/shaderMaterialGeoParamValueMatrix44.h"
#include "shaderMaterial/shaderMaterialGeoParamValueString.h"
#include "shaderMaterial/shaderMaterialGeoParamValueTexture.h"
#include "shaderMaterial/shaderMaterialGeoParamValueVector4.h"
#include "shaderMaterial/shaderMaterialGeoParamValueVector3.h"
#include "shaderMaterial/shaderMaterialGeoParamValueVector2.h"
#include "shaderMaterial/shaderMaterialGeoParamValueFloat.h"
#include "shaderMaterial/shaderMaterialGeoParamValueInt.h"
#include "rageShaderMaterialViewer/rageShaderMaterialViewer.h"
#include "rageShaderViewer/ModelMaterialPairManager.h"
#include "rageShaderViewer/rageShaderViewer.h"
#include "rageShaderMaterialMayaParam.h"
#include "rageShaderMaterialMaya.h"
#include "rageShaderUpdateManager.h"
#include "rageShaderTexture.h"
#include "rageShaderTextureCache.h"
#include "rageShaderMaya65.h"
#include "UserSettings.h"
// #include "rageShaderMayaNodeToMaterialRelationshipDB.h"
// If set to 1, UV sets will be fixed up on load (i.e. duplicated,
// reassigned, and the original deleted). This resolves
// a weird Maya crash that has plagued MC4 for a while, although it
// slows down the load a bit and adds information to the file's history.
#define FIX_UP_UV_SETS_ON_LOAD 0
#define BUFFER_SIZE 1024
#define DEBUG_LOG_Start \
{ \
FILE* pobFile = fopen("C:/DOCUME~1/krose/LOCALS~1/Temp/ShaderLog.txt", "a"); \
fprintf(pobFile,
#define DEBUG_LOG_End \
); \
fclose(pobFile); \
} \
#if __OPTIMIZED
bool g_bDisplayMGlobalExecuteCommands = false;
#else
bool g_bDisplayMGlobalExecuteCommands = true;
#endif
using namespace rage;
// Plug-in ID and Attributes.
// This ID needs to be unique to prevent clashes.
//
MTypeId rageShaderMaya::id( 0x7017 );
MObject rageShaderMaya::aColor;
MObject rageShaderMaya::aColorR;
MObject rageShaderMaya::aColorG;
MObject rageShaderMaya::aColorB;
MObject rageShaderMaya::aTextureOverride;
MObject rageShaderMaya::aTextureToDisplayInMaya;
MObject rageShaderMaya::aDisplayTransparency;
MObject rageShaderMaya::aIgnoreCreateUVsOnMeshConnection;
MObject rageShaderMaya::aMtlFile;
MObject rageShaderMaya::aCommand;
MObject rageShaderMaya::aPointlessAttributeThatShouldBeDeletedButCantBecauseItIsSavedIntoExistingFiles ;
MObject rageShaderMaya::aPointlessAttributeThatShouldBeDeletedButCantBecauseItIsSavedIntoExistingFiles2;
MObject rageShaderMaya::aPointlessAttributeThatShouldBeDeletedButCantBecauseItIsSavedIntoExistingFiles3;
MObject rageShaderMaya::aPointlessAttributeThatShouldBeDeletedButCantBecauseItIsSavedIntoExistingFiles4;
MObject rageShaderMaya::aPointlessAttributeThatShouldBeDeletedButCantBecauseItIsSavedIntoExistingFiles5;
MObject rageShaderMaya::aPointlessAttributeThatShouldBeDeletedButCantBecauseItIsSavedIntoExistingFiles6;
MObject rageShaderMaya::aPointlessAttributeThatShouldBeDeletedButCantBecauseItIsSavedIntoExistingFiles7;
MString rageShaderMaya::m_strPathToLastLoadedMtlFile = "";
MString rageShaderMaya::m_strPathToLastLoadedTemplateFile = "";
MString rageShaderMaya::m_strPathToLastLoadedTypeFile = "";
MCallbackId rageShaderMaya::sm_MayaExitingCallback;
MCallbackId rageShaderMaya::m_AttribChange;
MCallbackId rageShaderMaya::m_GlobalAfterMayaNewCallbackId;
MCallbackId rageShaderMaya::m_GlobalAfterMayaOpenCallbackId;
MCallbackId rageShaderMaya::m_GlobalAfterMayaImportCallbackId;
MCallbackId rageShaderMaya::m_GlobalAfterMayaReferenceCallbackId;
MCallbackId rageShaderMaya::m_GlobalBeforeMayaNewCallbackId;
MCallbackId rageShaderMaya::m_GlobalBeforeMayaOpenCallbackId;
MCallbackId rageShaderMaya::m_GlobalAfterMayaSaveCallbackId;
MCallbackId rageShaderMaya::m_GlobalBeforeMayaSaveCallbackId;
bool rageShaderMaya::m_GlobalIgnoreConnectionBreaks = false;
bool rageShaderMaya::m_IgnoreReferencedNodesDuringWireUpTextures = false;
MTimer rageShaderMaya::sm_Timer;
rageShaderTextureCache * rageShaderMaya::sm_pTextureCache = NULL;
rageShaderUpdateManager * rageShaderMaya::sm_pRageShaderUpdateManager = NULL;
vector <rageShaderMaya *> rageShaderMaya::sm_apRSMNodes;
#define CHECK_STATUS(x) \
{ \
MStatus _maya_status = (x); \
if ( MStatus::kSuccess != _maya_status ) \
{ \
MString obStrErrorMessage(__FILE__); \
obStrErrorMessage += ":"; \
obStrErrorMessage += __LINE__; \
obStrErrorMessage += ":"; \
_maya_status.perror (obStrErrorMessage); \
} \
} \
void DebugOutputOpenGlState()
{
GLboolean bValue = true;
glGetBooleanv( GL_ACCUM_ALPHA_BITS , &bValue); Displayf(" GL_ACCUM_ALPHA_BITS = %d", bValue);
glGetBooleanv( GL_ACCUM_BLUE_BITS , &bValue); Displayf(" GL_ACCUM_BLUE_BITS = %d", bValue);
glGetBooleanv( GL_ACCUM_CLEAR_VALUE , &bValue); Displayf(" GL_ACCUM_CLEAR_VALUE = %d", bValue);
glGetBooleanv( GL_ACCUM_GREEN_BITS , &bValue); Displayf(" GL_ACCUM_GREEN_BITS = %d", bValue);
glGetBooleanv( GL_ACCUM_RED_BITS , &bValue); Displayf(" GL_ACCUM_RED_BITS = %d", bValue);
glGetBooleanv( GL_ALPHA_BIAS , &bValue); Displayf(" GL_ALPHA_BIAS = %d", bValue);
glGetBooleanv( GL_ALPHA_BITS , &bValue); Displayf(" GL_ALPHA_BITS = %d", bValue);
glGetBooleanv( GL_ALPHA_SCALE , &bValue); Displayf(" GL_ALPHA_SCALE = %d", bValue);
glGetBooleanv( GL_ALPHA_TEST , &bValue); Displayf(" GL_ALPHA_TEST = %d", bValue);
glGetBooleanv( GL_ALPHA_TEST_FUNC , &bValue); Displayf(" GL_ALPHA_TEST_FUNC = %d", bValue);
glGetBooleanv( GL_ALPHA_TEST_REF , &bValue); Displayf(" GL_ALPHA_TEST_REF = %d", bValue);
glGetBooleanv( GL_ATTRIB_STACK_DEPTH , &bValue); Displayf(" GL_ATTRIB_STACK_DEPTH = %d", bValue);
glGetBooleanv( GL_AUTO_NORMAL , &bValue); Displayf(" GL_AUTO_NORMAL = %d", bValue);
glGetBooleanv( GL_AUX_BUFFERS , &bValue); Displayf(" GL_AUX_BUFFERS = %d", bValue);
glGetBooleanv( GL_BLEND , &bValue); Displayf(" GL_BLEND = %d", bValue);
glGetBooleanv( GL_BLEND_DST , &bValue); Displayf(" GL_BLEND_DST = %d", bValue);
glGetBooleanv( GL_BLEND_SRC , &bValue); Displayf(" GL_BLEND_SRC = %d", bValue);
glGetBooleanv( GL_BLUE_BIAS , &bValue); Displayf(" GL_BLUE_BIAS = %d", bValue);
glGetBooleanv( GL_BLUE_BITS , &bValue); Displayf(" GL_BLUE_BITS = %d", bValue);
glGetBooleanv( GL_BLUE_SCALE , &bValue); Displayf(" GL_BLUE_SCALE = %d", bValue);
glGetBooleanv( GL_CLIENT_ATTRIB_STACK_DEPTH , &bValue); Displayf(" GL_CLIENT_ATTRIB_STACK_DEPTH = %d", bValue);
// glGetBooleanv( GL_CLIP_PLANEi , &bValue); Displayf(" GL_CLIP_PLANEi = %d", bValue);
glGetBooleanv( GL_COLOR_ARRAY , &bValue); Displayf(" GL_COLOR_ARRAY = %d", bValue);
glGetBooleanv( GL_COLOR_ARRAY_SIZE , &bValue); Displayf(" GL_COLOR_ARRAY_SIZE = %d", bValue);
glGetBooleanv( GL_COLOR_ARRAY_STRIDE , &bValue); Displayf(" GL_COLOR_ARRAY_STRIDE = %d", bValue);
glGetBooleanv( GL_COLOR_ARRAY_TYPE , &bValue); Displayf(" GL_COLOR_ARRAY_TYPE = %d", bValue);
glGetBooleanv( GL_COLOR_CLEAR_VALUE , &bValue); Displayf(" GL_COLOR_CLEAR_VALUE = %d", bValue);
glGetBooleanv( GL_COLOR_LOGIC_OP , &bValue); Displayf(" GL_COLOR_LOGIC_OP = %d", bValue);
glGetBooleanv( GL_COLOR_MATERIAL , &bValue); Displayf(" GL_COLOR_MATERIAL = %d", bValue);
glGetBooleanv( GL_COLOR_MATERIAL_FACE , &bValue); Displayf(" GL_COLOR_MATERIAL_FACE = %d", bValue);
glGetBooleanv( GL_COLOR_MATERIAL_PARAMETER , &bValue); Displayf(" GL_COLOR_MATERIAL_PARAMETER = %d", bValue);
glGetBooleanv( GL_COLOR_WRITEMASK , &bValue); Displayf(" GL_COLOR_WRITEMASK = %d", bValue);
glGetBooleanv( GL_CULL_FACE , &bValue); Displayf(" GL_CULL_FACE = %d", bValue);
glGetBooleanv( GL_CULL_FACE_MODE , &bValue); Displayf(" GL_CULL_FACE_MODE = %d", bValue);
glGetBooleanv( GL_CURRENT_COLOR , &bValue); Displayf(" GL_CURRENT_COLOR = %d", bValue);
glGetBooleanv( GL_CURRENT_INDEX , &bValue); Displayf(" GL_CURRENT_INDEX = %d", bValue);
glGetBooleanv( GL_CURRENT_NORMAL , &bValue); Displayf(" GL_CURRENT_NORMAL = %d", bValue);
glGetBooleanv( GL_CURRENT_RASTER_COLOR , &bValue); Displayf(" GL_CURRENT_RASTER_COLOR = %d", bValue);
glGetBooleanv( GL_CURRENT_RASTER_DISTANCE , &bValue); Displayf(" GL_CURRENT_RASTER_DISTANCE = %d", bValue);
glGetBooleanv( GL_CURRENT_RASTER_INDEX , &bValue); Displayf(" GL_CURRENT_RASTER_INDEX = %d", bValue);
glGetBooleanv( GL_CURRENT_RASTER_POSITION , &bValue); Displayf(" GL_CURRENT_RASTER_POSITION = %d", bValue);
glGetBooleanv( GL_CURRENT_RASTER_POSITION_VALID , &bValue); Displayf(" GL_CURRENT_RASTER_POSITION_VALID = %d", bValue);
glGetBooleanv( GL_CURRENT_RASTER_TEXTURE_COORDS , &bValue); Displayf(" GL_CURRENT_RASTER_TEXTURE_COORDS = %d", bValue);
glGetBooleanv( GL_CURRENT_TEXTURE_COORDS , &bValue); Displayf(" GL_CURRENT_TEXTURE_COORDS = %d", bValue);
glGetBooleanv( GL_DEPTH_BIAS , &bValue); Displayf(" GL_DEPTH_BIAS = %d", bValue);
glGetBooleanv( GL_DEPTH_BITS , &bValue); Displayf(" GL_DEPTH_BITS = %d", bValue);
glGetBooleanv( GL_DEPTH_CLEAR_VALUE , &bValue); Displayf(" GL_DEPTH_CLEAR_VALUE = %d", bValue);
glGetBooleanv( GL_DEPTH_FUNC , &bValue); Displayf(" GL_DEPTH_FUNC = %d", bValue);
glGetBooleanv( GL_DEPTH_RANGE , &bValue); Displayf(" GL_DEPTH_RANGE = %d", bValue);
glGetBooleanv( GL_DEPTH_SCALE , &bValue); Displayf(" GL_DEPTH_SCALE = %d", bValue);
glGetBooleanv( GL_DEPTH_TEST , &bValue); Displayf(" GL_DEPTH_TEST = %d", bValue);
glGetBooleanv( GL_DEPTH_WRITEMASK , &bValue); Displayf(" GL_DEPTH_WRITEMASK = %d", bValue);
glGetBooleanv( GL_DITHER , &bValue); Displayf(" GL_DITHER = %d", bValue);
glGetBooleanv( GL_DOUBLEBUFFER , &bValue); Displayf(" GL_DOUBLEBUFFER = %d", bValue);
glGetBooleanv( GL_DRAW_BUFFER , &bValue); Displayf(" GL_DRAW_BUFFER = %d", bValue);
glGetBooleanv( GL_EDGE_FLAG , &bValue); Displayf(" GL_EDGE_FLAG = %d", bValue);
glGetBooleanv( GL_EDGE_FLAG_ARRAY , &bValue); Displayf(" GL_EDGE_FLAG_ARRAY = %d", bValue);
glGetBooleanv( GL_EDGE_FLAG_ARRAY_STRIDE , &bValue); Displayf(" GL_EDGE_FLAG_ARRAY_STRIDE = %d", bValue);
glGetBooleanv( GL_FOG , &bValue); Displayf(" GL_FOG = %d", bValue);
glGetBooleanv( GL_FOG_COLOR , &bValue); Displayf(" GL_FOG_COLOR = %d", bValue);
glGetBooleanv( GL_FOG_DENSITY , &bValue); Displayf(" GL_FOG_DENSITY = %d", bValue);
glGetBooleanv( GL_FOG_END , &bValue); Displayf(" GL_FOG_END = %d", bValue);
glGetBooleanv( GL_FOG_HINT , &bValue); Displayf(" GL_FOG_HINT = %d", bValue);
glGetBooleanv( GL_FOG_INDEX , &bValue); Displayf(" GL_FOG_INDEX = %d", bValue);
glGetBooleanv( GL_FOG_MODE , &bValue); Displayf(" GL_FOG_MODE = %d", bValue);
glGetBooleanv( GL_FOG_START , &bValue); Displayf(" GL_FOG_START = %d", bValue);
glGetBooleanv( GL_FRONT_FACE , &bValue); Displayf(" GL_FRONT_FACE = %d", bValue);
glGetBooleanv( GL_GREEN_BIAS , &bValue); Displayf(" GL_GREEN_BIAS = %d", bValue);
glGetBooleanv( GL_GREEN_BITS , &bValue); Displayf(" GL_GREEN_BITS = %d", bValue);
glGetBooleanv( GL_GREEN_SCALE , &bValue); Displayf(" GL_GREEN_SCALE = %d", bValue);
glGetBooleanv( GL_INDEX_ARRAY , &bValue); Displayf(" GL_INDEX_ARRAY = %d", bValue);
glGetBooleanv( GL_INDEX_ARRAY_STRIDE , &bValue); Displayf(" GL_INDEX_ARRAY_STRIDE = %d", bValue);
glGetBooleanv( GL_INDEX_ARRAY_TYPE , &bValue); Displayf(" GL_INDEX_ARRAY_TYPE = %d", bValue);
glGetBooleanv( GL_INDEX_BITS , &bValue); Displayf(" GL_INDEX_BITS = %d", bValue);
glGetBooleanv( GL_INDEX_CLEAR_VALUE , &bValue); Displayf(" GL_INDEX_CLEAR_VALUE = %d", bValue);
glGetBooleanv( GL_INDEX_LOGIC_OP , &bValue); Displayf(" GL_INDEX_LOGIC_OP = %d", bValue);
glGetBooleanv( GL_INDEX_MODE , &bValue); Displayf(" GL_INDEX_MODE = %d", bValue);
glGetBooleanv( GL_INDEX_OFFSET , &bValue); Displayf(" GL_INDEX_OFFSET = %d", bValue);
glGetBooleanv( GL_INDEX_SHIFT , &bValue); Displayf(" GL_INDEX_SHIFT = %d", bValue);
glGetBooleanv( GL_INDEX_WRITEMASK , &bValue); Displayf(" GL_INDEX_WRITEMASK = %d", bValue);
// glGetBooleanv( GL_LIGHTi , &bValue); Displayf(" GL_LIGHTi = %d", bValue);
glGetBooleanv( GL_LIGHTING , &bValue); Displayf(" GL_LIGHTING = %d", bValue);
glGetBooleanv( GL_LIGHT_MODEL_AMBIENT , &bValue); Displayf(" GL_LIGHT_MODEL_AMBIENT = %d", bValue);
glGetBooleanv( GL_LIGHT_MODEL_LOCAL_VIEWER , &bValue); Displayf(" GL_LIGHT_MODEL_LOCAL_VIEWER = %d", bValue);
glGetBooleanv( GL_LIGHT_MODEL_TWO_SIDE , &bValue); Displayf(" GL_LIGHT_MODEL_TWO_SIDE = %d", bValue);
glGetBooleanv( GL_LINE_SMOOTH , &bValue); Displayf(" GL_LINE_SMOOTH = %d", bValue);
glGetBooleanv( GL_LINE_SMOOTH_HINT , &bValue); Displayf(" GL_LINE_SMOOTH_HINT = %d", bValue);
glGetBooleanv( GL_LINE_STIPPLE , &bValue); Displayf(" GL_LINE_STIPPLE = %d", bValue);
glGetBooleanv( GL_LINE_STIPPLE_PATTERN , &bValue); Displayf(" GL_LINE_STIPPLE_PATTERN = %d", bValue);
glGetBooleanv( GL_LINE_STIPPLE_REPEAT , &bValue); Displayf(" GL_LINE_STIPPLE_REPEAT = %d", bValue);
glGetBooleanv( GL_LINE_WIDTH , &bValue); Displayf(" GL_LINE_WIDTH = %d", bValue);
glGetBooleanv( GL_LINE_WIDTH_GRANULARITY , &bValue); Displayf(" GL_LINE_WIDTH_GRANULARITY = %d", bValue);
glGetBooleanv( GL_LINE_WIDTH_RANGE , &bValue); Displayf(" GL_LINE_WIDTH_RANGE = %d", bValue);
glGetBooleanv( GL_LIST_BASE , &bValue); Displayf(" GL_LIST_BASE = %d", bValue);
glGetBooleanv( GL_LIST_INDEX , &bValue); Displayf(" GL_LIST_INDEX = %d", bValue);
glGetBooleanv( GL_LIST_MODE , &bValue); Displayf(" GL_LIST_MODE = %d", bValue);
glGetBooleanv( GL_LOGIC_OP , &bValue); Displayf(" GL_LOGIC_OP = %d", bValue);
glGetBooleanv( GL_LOGIC_OP_MODE , &bValue); Displayf(" GL_LOGIC_OP_MODE = %d", bValue);
glGetBooleanv( GL_MAP1_COLOR_4 , &bValue); Displayf(" GL_MAP1_COLOR_4 = %d", bValue);
glGetBooleanv( GL_MAP1_GRID_DOMAIN , &bValue); Displayf(" GL_MAP1_GRID_DOMAIN = %d", bValue);
glGetBooleanv( GL_MAP1_GRID_SEGMENTS , &bValue); Displayf(" GL_MAP1_GRID_SEGMENTS = %d", bValue);
glGetBooleanv( GL_MAP1_INDEX , &bValue); Displayf(" GL_MAP1_INDEX = %d", bValue);
glGetBooleanv( GL_MAP1_NORMAL , &bValue); Displayf(" GL_MAP1_NORMAL = %d", bValue);
glGetBooleanv( GL_MAP1_TEXTURE_COORD_1 , &bValue); Displayf(" GL_MAP1_TEXTURE_COORD_1 = %d", bValue);
glGetBooleanv( GL_MAP1_TEXTURE_COORD_2 , &bValue); Displayf(" GL_MAP1_TEXTURE_COORD_2 = %d", bValue);
glGetBooleanv( GL_MAP1_TEXTURE_COORD_3 , &bValue); Displayf(" GL_MAP1_TEXTURE_COORD_3 = %d", bValue);
glGetBooleanv( GL_MAP1_TEXTURE_COORD_4 , &bValue); Displayf(" GL_MAP1_TEXTURE_COORD_4 = %d", bValue);
glGetBooleanv( GL_MAP1_VERTEX_3 , &bValue); Displayf(" GL_MAP1_VERTEX_3 = %d", bValue);
glGetBooleanv( GL_MAP1_VERTEX_4 , &bValue); Displayf(" GL_MAP1_VERTEX_4 = %d", bValue);
glGetBooleanv( GL_MAP2_COLOR_4 , &bValue); Displayf(" GL_MAP2_COLOR_4 = %d", bValue);
glGetBooleanv( GL_MAP2_GRID_DOMAIN , &bValue); Displayf(" GL_MAP2_GRID_DOMAIN = %d", bValue);
glGetBooleanv( GL_MAP2_GRID_SEGMENTS , &bValue); Displayf(" GL_MAP2_GRID_SEGMENTS = %d", bValue);
glGetBooleanv( GL_MAP2_INDEX , &bValue); Displayf(" GL_MAP2_INDEX = %d", bValue);
glGetBooleanv( GL_MAP2_NORMAL , &bValue); Displayf(" GL_MAP2_NORMAL = %d", bValue);
glGetBooleanv( GL_MAP2_TEXTURE_COORD_1 , &bValue); Displayf(" GL_MAP2_TEXTURE_COORD_1 = %d", bValue);
glGetBooleanv( GL_MAP2_TEXTURE_COORD_2 , &bValue); Displayf(" GL_MAP2_TEXTURE_COORD_2 = %d", bValue);
glGetBooleanv( GL_MAP2_TEXTURE_COORD_3 , &bValue); Displayf(" GL_MAP2_TEXTURE_COORD_3 = %d", bValue);
glGetBooleanv( GL_MAP2_TEXTURE_COORD_4 , &bValue); Displayf(" GL_MAP2_TEXTURE_COORD_4 = %d", bValue);
glGetBooleanv( GL_MAP2_VERTEX_3 , &bValue); Displayf(" GL_MAP2_VERTEX_3 = %d", bValue);
glGetBooleanv( GL_MAP2_VERTEX_4 , &bValue); Displayf(" GL_MAP2_VERTEX_4 = %d", bValue);
glGetBooleanv( GL_MAP_COLOR , &bValue); Displayf(" GL_MAP_COLOR = %d", bValue);
glGetBooleanv( GL_MAP_STENCIL , &bValue); Displayf(" GL_MAP_STENCIL = %d", bValue);
glGetBooleanv( GL_MATRIX_MODE , &bValue); Displayf(" GL_MATRIX_MODE = %d", bValue);
glGetBooleanv( GL_MAX_CLIENT_ATTRIB_STACK_DEPTH , &bValue); Displayf(" GL_MAX_CLIENT_ATTRIB_STACK_DEPTH = %d", bValue);
glGetBooleanv( GL_MAX_ATTRIB_STACK_DEPTH , &bValue); Displayf(" GL_MAX_ATTRIB_STACK_DEPTH = %d", bValue);
glGetBooleanv( GL_MAX_CLIP_PLANES , &bValue); Displayf(" GL_MAX_CLIP_PLANES = %d", bValue);
glGetBooleanv( GL_MAX_EVAL_ORDER , &bValue); Displayf(" GL_MAX_EVAL_ORDER = %d", bValue);
glGetBooleanv( GL_MAX_LIGHTS , &bValue); Displayf(" GL_MAX_LIGHTS = %d", bValue);
glGetBooleanv( GL_MAX_LIST_NESTING , &bValue); Displayf(" GL_MAX_LIST_NESTING = %d", bValue);
glGetBooleanv( GL_MAX_MODELVIEW_STACK_DEPTH , &bValue); Displayf(" GL_MAX_MODELVIEW_STACK_DEPTH = %d", bValue);
glGetBooleanv( GL_MAX_NAME_STACK_DEPTH , &bValue); Displayf(" GL_MAX_NAME_STACK_DEPTH = %d", bValue);
glGetBooleanv( GL_MAX_PIXEL_MAP_TABLE , &bValue); Displayf(" GL_MAX_PIXEL_MAP_TABLE = %d", bValue);
glGetBooleanv( GL_MAX_PROJECTION_STACK_DEPTH , &bValue); Displayf(" GL_MAX_PROJECTION_STACK_DEPTH = %d", bValue);
glGetBooleanv( GL_MAX_TEXTURE_SIZE , &bValue); Displayf(" GL_MAX_TEXTURE_SIZE = %d", bValue);
glGetBooleanv( GL_MAX_TEXTURE_STACK_DEPTH , &bValue); Displayf(" GL_MAX_TEXTURE_STACK_DEPTH = %d", bValue);
glGetBooleanv( GL_MAX_VIEWPORT_DIMS , &bValue); Displayf(" GL_MAX_VIEWPORT_DIMS = %d", bValue);
glGetBooleanv( GL_MODELVIEW_MATRIX , &bValue); Displayf(" GL_MODELVIEW_MATRIX = %d", bValue);
glGetBooleanv( GL_MODELVIEW_STACK_DEPTH , &bValue); Displayf(" GL_MODELVIEW_STACK_DEPTH = %d", bValue);
glGetBooleanv( GL_NAME_STACK_DEPTH , &bValue); Displayf(" GL_NAME_STACK_DEPTH = %d", bValue);
glGetBooleanv( GL_NORMAL_ARRAY , &bValue); Displayf(" GL_NORMAL_ARRAY = %d", bValue);
glGetBooleanv( GL_NORMAL_ARRAY_STRIDE , &bValue); Displayf(" GL_NORMAL_ARRAY_STRIDE = %d", bValue);
glGetBooleanv( GL_NORMAL_ARRAY_TYPE , &bValue); Displayf(" GL_NORMAL_ARRAY_TYPE = %d", bValue);
glGetBooleanv( GL_NORMALIZE , &bValue); Displayf(" GL_NORMALIZE = %d", bValue);
glGetBooleanv( GL_PACK_ALIGNMENT , &bValue); Displayf(" GL_PACK_ALIGNMENT = %d", bValue);
glGetBooleanv( GL_PACK_LSB_FIRST , &bValue); Displayf(" GL_PACK_LSB_FIRST = %d", bValue);
glGetBooleanv( GL_PACK_ROW_LENGTH , &bValue); Displayf(" GL_PACK_ROW_LENGTH = %d", bValue);
glGetBooleanv( GL_PACK_SKIP_PIXELS , &bValue); Displayf(" GL_PACK_SKIP_PIXELS = %d", bValue);
glGetBooleanv( GL_PACK_SKIP_ROWS , &bValue); Displayf(" GL_PACK_SKIP_ROWS = %d", bValue);
glGetBooleanv( GL_PACK_SWAP_BYTES , &bValue); Displayf(" GL_PACK_SWAP_BYTES = %d", bValue);
glGetBooleanv( GL_PERSPECTIVE_CORRECTION_HINT , &bValue); Displayf(" GL_PERSPECTIVE_CORRECTION_HINT = %d", bValue);
glGetBooleanv( GL_PIXEL_MAP_A_TO_A_SIZE , &bValue); Displayf(" GL_PIXEL_MAP_A_TO_A_SIZE = %d", bValue);
glGetBooleanv( GL_PIXEL_MAP_B_TO_B_SIZE , &bValue); Displayf(" GL_PIXEL_MAP_B_TO_B_SIZE = %d", bValue);
glGetBooleanv( GL_PIXEL_MAP_G_TO_G_SIZE , &bValue); Displayf(" GL_PIXEL_MAP_G_TO_G_SIZE = %d", bValue);
glGetBooleanv( GL_PIXEL_MAP_I_TO_A_SIZE , &bValue); Displayf(" GL_PIXEL_MAP_I_TO_A_SIZE = %d", bValue);
glGetBooleanv( GL_PIXEL_MAP_I_TO_B_SIZE , &bValue); Displayf(" GL_PIXEL_MAP_I_TO_B_SIZE = %d", bValue);
glGetBooleanv( GL_PIXEL_MAP_I_TO_G_SIZE , &bValue); Displayf(" GL_PIXEL_MAP_I_TO_G_SIZE = %d", bValue);
glGetBooleanv( GL_PIXEL_MAP_I_TO_I_SIZE , &bValue); Displayf(" GL_PIXEL_MAP_I_TO_I_SIZE = %d", bValue);
glGetBooleanv( GL_PIXEL_MAP_I_TO_R_SIZE , &bValue); Displayf(" GL_PIXEL_MAP_I_TO_R_SIZE = %d", bValue);
glGetBooleanv( GL_PIXEL_MAP_R_TO_R_SIZE , &bValue); Displayf(" GL_PIXEL_MAP_R_TO_R_SIZE = %d", bValue);
glGetBooleanv( GL_PIXEL_MAP_S_TO_S_SIZE , &bValue); Displayf(" GL_PIXEL_MAP_S_TO_S_SIZE = %d", bValue);
glGetBooleanv( GL_POINT_SIZE , &bValue); Displayf(" GL_POINT_SIZE = %d", bValue);
glGetBooleanv( GL_POINT_SIZE_GRANULARITY , &bValue); Displayf(" GL_POINT_SIZE_GRANULARITY = %d", bValue);
glGetBooleanv( GL_POINT_SIZE_RANGE , &bValue); Displayf(" GL_POINT_SIZE_RANGE = %d", bValue);
glGetBooleanv( GL_POINT_SMOOTH , &bValue); Displayf(" GL_POINT_SMOOTH = %d", bValue);
glGetBooleanv( GL_POINT_SMOOTH_HINT , &bValue); Displayf(" GL_POINT_SMOOTH_HINT = %d", bValue);
glGetBooleanv( GL_POLYGON_MODE , &bValue); Displayf(" GL_POLYGON_MODE = %d", bValue);
glGetBooleanv( GL_POLYGON_OFFSET_FACTOR , &bValue); Displayf(" GL_POLYGON_OFFSET_FACTOR = %d", bValue);
glGetBooleanv( GL_POLYGON_OFFSET_UNITS , &bValue); Displayf(" GL_POLYGON_OFFSET_UNITS = %d", bValue);
glGetBooleanv( GL_POLYGON_OFFSET_FILL , &bValue); Displayf(" GL_POLYGON_OFFSET_FILL = %d", bValue);
glGetBooleanv( GL_POLYGON_OFFSET_LINE , &bValue); Displayf(" GL_POLYGON_OFFSET_LINE = %d", bValue);
glGetBooleanv( GL_POLYGON_OFFSET_POINT , &bValue); Displayf(" GL_POLYGON_OFFSET_POINT = %d", bValue);
glGetBooleanv( GL_POLYGON_SMOOTH , &bValue); Displayf(" GL_POLYGON_SMOOTH = %d", bValue);
glGetBooleanv( GL_POLYGON_SMOOTH_HINT , &bValue); Displayf(" GL_POLYGON_SMOOTH_HINT = %d", bValue);
glGetBooleanv( GL_POLYGON_STIPPLE , &bValue); Displayf(" GL_POLYGON_STIPPLE = %d", bValue);
glGetBooleanv( GL_PROJECTION_MATRIX , &bValue); Displayf(" GL_PROJECTION_MATRIX = %d", bValue);
glGetBooleanv( GL_PROJECTION_STACK_DEPTH , &bValue); Displayf(" GL_PROJECTION_STACK_DEPTH = %d", bValue);
glGetBooleanv( GL_READ_BUFFER , &bValue); Displayf(" GL_READ_BUFFER = %d", bValue);
glGetBooleanv( GL_RED_BIAS , &bValue); Displayf(" GL_RED_BIAS = %d", bValue);
glGetBooleanv( GL_RED_BITS , &bValue); Displayf(" GL_RED_BITS = %d", bValue);
glGetBooleanv( GL_RED_SCALE , &bValue); Displayf(" GL_RED_SCALE = %d", bValue);
glGetBooleanv( GL_RENDER_MODE , &bValue); Displayf(" GL_RENDER_MODE = %d", bValue);
glGetBooleanv( GL_RGBA_MODE , &bValue); Displayf(" GL_RGBA_MODE = %d", bValue);
glGetBooleanv( GL_SCISSOR_BOX , &bValue); Displayf(" GL_SCISSOR_BOX = %d", bValue);
glGetBooleanv( GL_SCISSOR_TEST , &bValue); Displayf(" GL_SCISSOR_TEST = %d", bValue);
glGetBooleanv( GL_SHADE_MODEL , &bValue); Displayf(" GL_SHADE_MODEL = %d", bValue);
glGetBooleanv( GL_STENCIL_BITS , &bValue); Displayf(" GL_STENCIL_BITS = %d", bValue);
glGetBooleanv( GL_STENCIL_CLEAR_VALUE , &bValue); Displayf(" GL_STENCIL_CLEAR_VALUE = %d", bValue);
glGetBooleanv( GL_STENCIL_FAIL , &bValue); Displayf(" GL_STENCIL_FAIL = %d", bValue);
glGetBooleanv( GL_STENCIL_FUNC , &bValue); Displayf(" GL_STENCIL_FUNC = %d", bValue);
glGetBooleanv( GL_STENCIL_PASS_DEPTH_FAIL , &bValue); Displayf(" GL_STENCIL_PASS_DEPTH_FAIL = %d", bValue);
glGetBooleanv( GL_STENCIL_PASS_DEPTH_PASS , &bValue); Displayf(" GL_STENCIL_PASS_DEPTH_PASS = %d", bValue);
glGetBooleanv( GL_STENCIL_REF , &bValue); Displayf(" GL_STENCIL_REF = %d", bValue);
glGetBooleanv( GL_STENCIL_TEST , &bValue); Displayf(" GL_STENCIL_TEST = %d", bValue);
glGetBooleanv( GL_STENCIL_VALUE_MASK , &bValue); Displayf(" GL_STENCIL_VALUE_MASK = %d", bValue);
glGetBooleanv( GL_STENCIL_WRITEMASK , &bValue); Displayf(" GL_STENCIL_WRITEMASK = %d", bValue);
glGetBooleanv( GL_STEREO , &bValue); Displayf(" GL_STEREO = %d", bValue);
glGetBooleanv( GL_SUBPIXEL_BITS , &bValue); Displayf(" GL_SUBPIXEL_BITS = %d", bValue);
glGetBooleanv( GL_TEXTURE_1D , &bValue); Displayf(" GL_TEXTURE_1D = %d", bValue);
glGetBooleanv( GL_TEXTURE_2D , &bValue); Displayf(" GL_TEXTURE_2D = %d", bValue);
glGetBooleanv( GL_TEXTURE_COORD_ARRAY , &bValue); Displayf(" GL_TEXTURE_COORD_ARRAY = %d", bValue);
glGetBooleanv( GL_TEXTURE_COORD_ARRAY_SIZE , &bValue); Displayf(" GL_TEXTURE_COORD_ARRAY_SIZE = %d", bValue);
glGetBooleanv( GL_TEXTURE_COORD_ARRAY_STRIDE , &bValue); Displayf(" GL_TEXTURE_COORD_ARRAY_STRIDE = %d", bValue);
glGetBooleanv( GL_TEXTURE_COORD_ARRAY_TYPE , &bValue); Displayf(" GL_TEXTURE_COORD_ARRAY_TYPE = %d", bValue);
glGetBooleanv( GL_TEXTURE_ENV_COLOR , &bValue); Displayf(" GL_TEXTURE_ENV_COLOR = %d", bValue);
glGetBooleanv( GL_TEXTURE_ENV_MODE , &bValue); Displayf(" GL_TEXTURE_ENV_MODE = %d", bValue);
glGetBooleanv( GL_TEXTURE_GEN_Q , &bValue); Displayf(" GL_TEXTURE_GEN_Q = %d", bValue);
glGetBooleanv( GL_TEXTURE_GEN_R , &bValue); Displayf(" GL_TEXTURE_GEN_R = %d", bValue);
glGetBooleanv( GL_TEXTURE_GEN_S , &bValue); Displayf(" GL_TEXTURE_GEN_S = %d", bValue);
glGetBooleanv( GL_TEXTURE_GEN_T , &bValue); Displayf(" GL_TEXTURE_GEN_T = %d", bValue);
glGetBooleanv( GL_TEXTURE_MATRIX , &bValue); Displayf(" GL_TEXTURE_MATRIX = %d", bValue);
glGetBooleanv( GL_TEXTURE_STACK_DEPTH , &bValue); Displayf(" GL_TEXTURE_STACK_DEPTH = %d", bValue);
glGetBooleanv( GL_UNPACK_ALIGNMENT , &bValue); Displayf(" GL_UNPACK_ALIGNMENT = %d", bValue);
glGetBooleanv( GL_UNPACK_LSB_FIRST , &bValue); Displayf(" GL_UNPACK_LSB_FIRST = %d", bValue);
glGetBooleanv( GL_UNPACK_ROW_LENGTH , &bValue); Displayf(" GL_UNPACK_ROW_LENGTH = %d", bValue);
glGetBooleanv( GL_UNPACK_SKIP_PIXELS , &bValue); Displayf(" GL_UNPACK_SKIP_PIXELS = %d", bValue);
glGetBooleanv( GL_UNPACK_SKIP_ROWS , &bValue); Displayf(" GL_UNPACK_SKIP_ROWS = %d", bValue);
glGetBooleanv( GL_UNPACK_SWAP_BYTES , &bValue); Displayf(" GL_UNPACK_SWAP_BYTES = %d", bValue);
glGetBooleanv( GL_VERTEX_ARRAY , &bValue); Displayf(" GL_VERTEX_ARRAY = %d", bValue);
glGetBooleanv( GL_VERTEX_ARRAY_SIZE , &bValue); Displayf(" GL_VERTEX_ARRAY_SIZE = %d", bValue);
glGetBooleanv( GL_VERTEX_ARRAY_STRIDE , &bValue); Displayf(" GL_VERTEX_ARRAY_STRIDE = %d", bValue);
glGetBooleanv( GL_VERTEX_ARRAY_TYPE , &bValue); Displayf(" GL_VERTEX_ARRAY_TYPE = %d", bValue);
glGetBooleanv( GL_VIEWPORT , &bValue); Displayf(" GL_VIEWPORT = %d", bValue);
glGetBooleanv( GL_ZOOM_X , &bValue); Displayf(" GL_ZOOM_X = %d", bValue);
glGetBooleanv( GL_ZOOM_Y , &bValue); Displayf(" GL_ZOOM_Y = %d", bValue);
}
rageShaderMaya::rageShaderMaya()
{
m_pobUpdateData = NULL;
m_pobRageMaterial = NULL;
m_pCurrentTextureParam = NULL;
m_pCurrentTexture = NULL;
m_strCurrentTextureOverrideFilename = "";
m_bMaterialChangedSinceLastSaved = false; // We don't need to save a material that has not been loaded or newed
m_iUVSetIndexToUseInGeometeryFunctions = 0;
skipSetInternalValueInContext(false);
m_bNodeIsCopy = false;
m_DeletedExistingDataDuringCreation = false;
}
rageShaderMaya::~rageShaderMaya()
{
// rageShaderMayaNodeToMaterialRelationshipDB::RemoveRelationship(thisMObject());
removeThisNode();
for (unsigned i=0; i<sm_apRSMNodes.size(); i++)
{
if (sm_apRSMNodes[i] == this)
{
sm_apRSMNodes.erase(sm_apRSMNodes.begin() + i);
break;
}
}
rageShaderUpdateManager::ReleaseUpdateData(m_pobUpdateData);
m_pobUpdateData = NULL;
delete m_pobRageMaterial;
m_pobRageMaterial = NULL;
}
void * rageShaderMaya::creator()
{
rageShaderMaya * node = new rageShaderMaya();
sm_apRSMNodes.push_back(node);
return node;
}
void rageShaderMaya::initalizePlugin()
{
//if (MGlobal::mayaState() == MGlobal::kBatch)
// return;
// allocate the shader database
#if __OPTIMIZED
static const int s_sysParamCount = 2;
static char *s_sysParams[s_sysParamCount] = {" ", "-noquits"};
#else
static const int s_sysParamCount = 1;
static char *s_sysParams[s_sysParamCount] = {" "};
#endif
sysParam::Init(s_sysParamCount,s_sysParams);
INIT_PARSER;
rageShaderMaterialTemplate::InitShaderMaterialLibrary();
// Start the timer
sm_Timer.beginTimer();
sm_pTextureCache = new rageShaderTextureCache;
sm_pRageShaderUpdateManager = new rageShaderUpdateManager;
sm_pRageShaderUpdateManager->RunThread();
RegisterGlobalCallbacks();
}
void rageShaderMaya::uninitalizePlugin(void * )
{
// Make sure we have deleted all the RSM nodes
for (unsigned i=0; i<sm_apRSMNodes.size(); i++)
{
Assert(sm_apRSMNodes[i]);
delete sm_apRSMNodes[i];
i--;
}
sm_apRSMNodes.clear();
// Delete the shader viewer
if (sm_pRageShaderUpdateManager)
{
sm_pRageShaderUpdateManager->SetExit(true);
// Make sure the thread has stopped before we delete
static int count = 0;
while(!sm_pRageShaderUpdateManager->IsDone() && count < 200)
{
// wait for 10 milli seconds
Sleep(100);
count++;
}
delete sm_pRageShaderUpdateManager;
sm_pRageShaderUpdateManager = NULL;
}
// Delete the texture cache
delete sm_pTextureCache;
sm_pTextureCache = NULL;
sm_Timer.endTimer();
rageShaderMaterialTemplate::ShutdownShaderMaterialLibrary();
UnregisterGlobalCallbacks();
SHUTDOWN_PARSER;
}
MStatus rageShaderMaya::initialize()
{
MFnNumericAttribute nAttr;
MFnTypedAttribute tAttr;
MStatus obStatus;
// Attributes
// Create color input attributes
aColorR = nAttr.create( "colorR", "cr",MFnNumericData::kFloat, 0, &obStatus );
CHECK_STATUS( obStatus );
aColorG = nAttr.create( "colorG", "cg", MFnNumericData::kFloat, 0, &obStatus );
CHECK_STATUS( obStatus );
aColorB = nAttr.create( "colorB", "cb",MFnNumericData::kFloat, 0, &obStatus );
CHECK_STATUS( obStatus );
aColor = nAttr.create( "color", "c", aColorR, aColorG, aColorB, &obStatus );
CHECK_STATUS( obStatus );
CHECK_STATUS( nAttr.setKeyable( false ) );
CHECK_STATUS( nAttr.setStorable( true ) );
CHECK_STATUS( nAttr.setHidden( true ) );
CHECK_STATUS( nAttr.setDefault( 0.4f, 0.4f, 0.4f ) );
CHECK_STATUS( nAttr.setUsedAsColor( true ) );
aTextureToDisplayInMaya = tAttr.create( "TextureToDisplayInMaya", "TTDIM", MFnData::kString, MObject::kNullObj , &obStatus );
CHECK_STATUS( obStatus );
CHECK_STATUS( tAttr.setHidden( true ) );
CHECK_STATUS( tAttr.setReadable( true ) );
CHECK_STATUS( tAttr.setWritable( true ) );
CHECK_STATUS( tAttr.setInternal( true ) );
aMtlFile = tAttr.create( "MtlFilename", "MtlFile", MFnData::kString, MObject::kNullObj , &obStatus );
CHECK_STATUS( obStatus );
CHECK_STATUS( tAttr.setHidden( true ) );
CHECK_STATUS( tAttr.setInternal( true ) );
aCommand = tAttr.create( "Command", "Com", MFnData::kString, MObject::kNullObj , &obStatus );
CHECK_STATUS( obStatus );
CHECK_STATUS( tAttr.setStorable( false ) );
CHECK_STATUS( tAttr.setHidden( true ) );
CHECK_STATUS( tAttr.setReadable( true ) );
CHECK_STATUS( tAttr.setWritable( false ) );
CHECK_STATUS( tAttr.setInternal( true ) );
aDisplayTransparency = nAttr.create( "DisplayTransparency", "DisplayTrans", MFnNumericData::kBoolean, 0, &obStatus );
CHECK_STATUS( obStatus );
CHECK_STATUS( nAttr.setStorable( true ) );
CHECK_STATUS( nAttr.setHidden( true ) );
CHECK_STATUS( nAttr.setReadable( true ) );
CHECK_STATUS( nAttr.setWritable( true ) );
CHECK_STATUS( nAttr.setInternal( false ) );
aIgnoreCreateUVsOnMeshConnection = nAttr.create( "IgnoreCreateUVsOnMeshConnection", "IgnoreCreateUVs", MFnNumericData::kBoolean, 0, &obStatus );
CHECK_STATUS( obStatus );
CHECK_STATUS( nAttr.setStorable( false ) );
CHECK_STATUS( nAttr.setHidden( true ) );
CHECK_STATUS( nAttr.setReadable( true ) );
CHECK_STATUS( nAttr.setWritable( true ) );
CHECK_STATUS( nAttr.setInternal( false ) );
aTextureOverride = nAttr.create( "TextureOveride", "TO", MFnNumericData::kBoolean, 0, &obStatus );
CHECK_STATUS( obStatus );
CHECK_STATUS( nAttr.setStorable( true ) );
CHECK_STATUS( nAttr.setHidden( true ) );
CHECK_STATUS( nAttr.setReadable( true ) );
CHECK_STATUS( nAttr.setWritable( true ) );
CHECK_STATUS( nAttr.setInternal( false ) );
aPointlessAttributeThatShouldBeDeletedButCantBecauseItIsSavedIntoExistingFiles = nAttr.create( "PointlessAttributeThatShouldBeDeletedButCantBecauseItIsSavedIntoExistingFiles", "DisplayComp", MFnNumericData::kBoolean, 1, &obStatus );
CHECK_STATUS( obStatus );
CHECK_STATUS( nAttr.setStorable( false ) );
CHECK_STATUS( nAttr.setHidden( true ) );
CHECK_STATUS( nAttr.setReadable( true ) );
CHECK_STATUS( nAttr.setWritable( false ) );
CHECK_STATUS( nAttr.setInternal( false ) );
aPointlessAttributeThatShouldBeDeletedButCantBecauseItIsSavedIntoExistingFiles5 = tAttr.create( "NewMtlFilename", "NewMtlFile", MFnData::kString, MObject::kNullObj , &obStatus );
CHECK_STATUS( obStatus );
CHECK_STATUS( tAttr.setStorable( false ) );
CHECK_STATUS( tAttr.setHidden( true ) );
CHECK_STATUS( tAttr.setReadable( true ) );
CHECK_STATUS( tAttr.setWritable( false ) );
CHECK_STATUS( tAttr.setInternal( true ) );
aPointlessAttributeThatShouldBeDeletedButCantBecauseItIsSavedIntoExistingFiles3 = tAttr.create( "LoadMtlFilename", "LoadMtlFile", MFnData::kString, MObject::kNullObj , &obStatus );
CHECK_STATUS( obStatus );
CHECK_STATUS( tAttr.setStorable( false ) );
CHECK_STATUS( tAttr.setHidden( true ) );
CHECK_STATUS( tAttr.setReadable( true ) );
CHECK_STATUS( tAttr.setWritable( false ) );
CHECK_STATUS( tAttr.setInternal( true ) );
aPointlessAttributeThatShouldBeDeletedButCantBecauseItIsSavedIntoExistingFiles6 = tAttr.create( "SaveMtlFilename", "SaveMtlFile", MFnData::kString, MObject::kNullObj , &obStatus );
CHECK_STATUS( obStatus );
CHECK_STATUS( tAttr.setStorable( false ) );
CHECK_STATUS( tAttr.setHidden( true ) );
CHECK_STATUS( tAttr.setReadable( true ) );
CHECK_STATUS( tAttr.setWritable( false ) );
CHECK_STATUS( tAttr.setInternal( true ) );
aPointlessAttributeThatShouldBeDeletedButCantBecauseItIsSavedIntoExistingFiles4 = tAttr.create( "TemplateFilename", "TemplateFile", MFnData::kString, MObject::kNullObj , &obStatus );
CHECK_STATUS( obStatus );
CHECK_STATUS( tAttr.setHidden( true ) );
CHECK_STATUS( tAttr.setStorable( false ) );
aPointlessAttributeThatShouldBeDeletedButCantBecauseItIsSavedIntoExistingFiles2 = nAttr.create( "PointlessAttributeThatShouldBeDeletedButCantBecauseItIsSavedIntoExistingFiles2", "DisplayVertCol", MFnNumericData::kBoolean, 0, &obStatus );
CHECK_STATUS( obStatus );
CHECK_STATUS( nAttr.setStorable( false ) );
CHECK_STATUS( nAttr.setHidden( true ) );
CHECK_STATUS( nAttr.setReadable( true ) );
CHECK_STATUS( nAttr.setWritable( true ) );
CHECK_STATUS( nAttr.setInternal( false ) );
aPointlessAttributeThatShouldBeDeletedButCantBecauseItIsSavedIntoExistingFiles7 = tAttr.create( "MaterialUIMelScriptFilename", "MaterialUIMelScript", MFnData::kString, MObject::kNullObj , &obStatus );
CHECK_STATUS( obStatus );
CHECK_STATUS( tAttr.setStorable( false ) );
CHECK_STATUS( tAttr.setHidden( true ) );
CHECK_STATUS( tAttr.setReadable( true ) );
CHECK_STATUS( tAttr.setWritable( false ) );
// Next we will add the attributes we have defined to the node
CHECK_STATUS( addAttribute( aColor ) );
CHECK_STATUS( addAttribute( aTextureToDisplayInMaya ) );
CHECK_STATUS( addAttribute( aTextureOverride ) );
CHECK_STATUS( addAttribute( aMtlFile ) );
CHECK_STATUS( addAttribute( aCommand ) );
CHECK_STATUS( addAttribute( aDisplayTransparency ) );
CHECK_STATUS( addAttribute( aIgnoreCreateUVsOnMeshConnection ) );
//hopefully can remove these at some point
CHECK_STATUS( addAttribute( aPointlessAttributeThatShouldBeDeletedButCantBecauseItIsSavedIntoExistingFiles ) );
CHECK_STATUS( addAttribute( aPointlessAttributeThatShouldBeDeletedButCantBecauseItIsSavedIntoExistingFiles2 ) );
CHECK_STATUS( addAttribute( aPointlessAttributeThatShouldBeDeletedButCantBecauseItIsSavedIntoExistingFiles3 ) );
CHECK_STATUS( addAttribute( aPointlessAttributeThatShouldBeDeletedButCantBecauseItIsSavedIntoExistingFiles4 ) );
CHECK_STATUS( addAttribute( aPointlessAttributeThatShouldBeDeletedButCantBecauseItIsSavedIntoExistingFiles5 ) );
CHECK_STATUS( addAttribute( aPointlessAttributeThatShouldBeDeletedButCantBecauseItIsSavedIntoExistingFiles6 ) );
CHECK_STATUS( addAttribute( aPointlessAttributeThatShouldBeDeletedButCantBecauseItIsSavedIntoExistingFiles7 ) );
CHECK_STATUS( attributeAffects( aColor, outColor ) );
return MS::kSuccess;
}
void rageShaderMaya::postConstructor( )
{
static int s_nUniqueIndex = 0;
m_nUniqueIndex = s_nUniqueIndex;
s_nUniqueIndex++;
// Lets reset the name of the UI Script
setThisStringAttr("MaterialUIMelScript", "");
m_pobUpdateData = rageShaderUpdateManager::CreateUpdateData(this);
}
///////////////////////////////////////////////////////
// DESCRIPTION:
// This function gets called by Maya to evaluate the shader.
//
// Get color from the input block.
// Compute the color/alpha of our bump for a given UV coordinate.
// Put the result into the output plug.
///////////////////////////////////////////////////////
MStatus rageShaderMaya::compute(const MPlug & plug,
MDataBlock & block)
{
// Displayf("%d %s", __LINE__, plug.name().asChar());
if (plug == outColor)
{
MStatus obStatus;
MDataHandle obInColorHandle = block.inputValue( aColor, &obStatus );
CHECK_STATUS( obStatus );
// Get the handle to the attribute
MDataHandle outColorHandle = block.outputValue( outColor, &obStatus );
CHECK_STATUS( obStatus );
outColorHandle.asFloatVector() = obInColorHandle.asFloatVector(); // Set the output value
outColorHandle.setClean();
block.setClean(plug);
}
else
{
return( MS::kUnknownParameter ); // We got an unexpected plug
}
return MS::kSuccess;
}
void rageShaderMaya::bind(bool bEnableLighting)
{
// white, opaque.
float diffuseColor[4] = {1.0f,1.0f,1.0f,1.0f};
if (!m_pCurrentTextureParam)
{
MFnDependencyNode thisNode(thisMObject());
MPlug plug = thisNode.findPlug(aColorR);
if (!plug.isNull())
{
plug.getValue(diffuseColor[0]);
}
plug = thisNode.findPlug(aColorG);
if (!plug.isNull())
{
plug.getValue(diffuseColor[1]);
}
plug = thisNode.findPlug(aColorB);
if (!plug.isNull())
{
plug.getValue(diffuseColor[2]);
}
}
glPushAttrib( GL_ALL_ATTRIB_BITS );
glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
// Set the standard OpenGL blending mode.
if (getThisBoolAttr(aDisplayTransparency))
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_ALWAYS, 0);
}
else
{
glDisable(GL_BLEND);
glDisable(GL_ALPHA_TEST);
}
// Turn on lighting
if (bEnableLighting)
{
// glEnable(GL_LIGHTING);
float ambientColor[4] = { 0.1f, 0.1f, 0.1f, 1.0f };
float specularColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
float emissionColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambientColor);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuseColor );
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specularColor);
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, emissionColor);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 50.0f);
glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
}
else
{
glDisable(GL_LIGHTING);
glDisable(GL_COLOR_MATERIAL);
}
glColor4fv(diffuseColor);
glColorMask(true, true, true, false); // Disable the alpha write
// If the shader is textured or has a color
if (m_pCurrentTextureParam)
{
if (m_pCurrentTextureParam->GetType()==grcEffect::VT_TEXTURE)
{
// Enable 2D texturing.
glEnable(GL_TEXTURE_2D);
// Bind the texture
if (!m_pCurrentTexture)
{
const char * textureFileName = NULL;
if (m_strCurrentTextureOverrideFilename.length())
{
textureFileName = m_strCurrentTextureOverrideFilename.asChar();
}
else
{
// Get the texture file name
textureFileName = ((shaderMaterialGeoParamValueTexture *)m_pCurrentTextureParam)->GetValue();
}
// Bind the texture
m_pCurrentTexture = sm_pTextureCache->bind(textureFileName);
}
else
{
m_pCurrentTexture->bind();
}
}
}
if (!m_pCurrentTexture)
{
if (m_pCurrentTextureParam)
{
switch (m_pCurrentTextureParam->GetType())
{
case grcEffect::VT_VECTOR4:
{
const Vector4 & vData = ((shaderMaterialGeoParamValueVector4 *)m_pCurrentTextureParam)->GetValue();
diffuseColor[0] = vData.x;
diffuseColor[1] = vData.y;
diffuseColor[2] = vData.z;
diffuseColor[3] = vData.w;
break;
}
case grcEffect::VT_VECTOR3:
{
const Vector3 & vData = ((shaderMaterialGeoParamValueVector3 *)m_pCurrentTextureParam)->GetValue();
diffuseColor[0] = vData.x;
diffuseColor[1] = vData.y;
diffuseColor[2] = vData.z;
diffuseColor[3] = 1.0f;
break;
}
case grcEffect::VT_VECTOR2:
{
const Vector2 & vData = ((shaderMaterialGeoParamValueVector2 *)m_pCurrentTextureParam)->GetValue();
diffuseColor[0] = vData.x;
diffuseColor[1] = vData.y;
diffuseColor[2] = 0.0f;
diffuseColor[3] = 1.0f;
break;
}
case grcEffect::VT_FLOAT:
{
float fData = ((shaderMaterialGeoParamValueFloat *)m_pCurrentTextureParam)->GetValue();
diffuseColor[0] = fData;
diffuseColor[1] = fData;
diffuseColor[2] = fData;
diffuseColor[3] = 1.0f;
break;
}
/* case grcEffect::VT_INT:
{
float fData = (float)((shaderMaterialGeoParamValueInt *)m_pCurrentTextureParam)->GetValue() / 255.0f;
diffuseColor[0] = fData;
diffuseColor[1] = fData;
diffuseColor[2] = fData;
diffuseColor[3] = 1.0f;
break;
} */
}
}
// Disable 2D texturing.
glDisable(GL_TEXTURE_2D);
}
}
///////////////////////////////////////////////////////
// DESCRIPTION:
// This function gets called by Maya to bind anything like textures we need.
//
//
//
//
///////////////////////////////////////////////////////
MStatus rageShaderMaya::bind(const MDrawRequest& ,
M3dView& view)
{
MStatus obStatus;
view.beginGL();
bind(true);
view.endGL();
return MS::kSuccess;
}
MStatus rageShaderMaya::glBind(const MDagPath&)
{
bind(true);
return MS::kSuccess;
}
void rageShaderMaya::unbind()
{
glPopClientAttrib();
glPopAttrib();
}
///////////////////////////////////////////////////////
// DESCRIPTION:
// This function gets called by Maya to unbind anything that was bound
//
//
//
//
///////////////////////////////////////////////////////
MStatus rageShaderMaya::unbind(const MDrawRequest& ,
M3dView& view)
{
view.beginGL();
unbind();
view.endGL();
return MS::kSuccess;
}
MStatus rageShaderMaya::glUnbind(const MDagPath&)
{
unbind();
return MS::kSuccess;
}
///////////////////////////////////////////////////////
// DESCRIPTION:
// This function gets called by Maya to do the actual drawing
//
//
//
//
///////////////////////////////////////////////////////
void rageShaderMaya::geometry(const MDagPath & path,
int prim,
int indexCount,
const unsigned int * indexArray,
int /*vertexCount*/,
const int * /*vertexIDs*/,
const float * vertexArray,
int normalCount,
const float ** normalArrays,
int colorCount,
const float ** colorArrays,
int texCoordCount,
const float ** texCoordArrays)
{
//Displayf("%d rageShaderMaya::geometry(%s)", __LINE__, path.fullPathName().asChar());
if (!vertexArray)
{
return;
}
glVertexPointer(3, GL_FLOAT, 0, vertexArray);
glEnableClientState(GL_VERTEX_ARRAY);
if (normalCount > 0 && normalArrays[0])
{
glNormalPointer(GL_FLOAT, 0, normalArrays[0]);
glEnableClientState(GL_NORMAL_ARRAY);
}
else
{
glDisableClientState(GL_NORMAL_ARRAY);
}
if (texCoordCount > m_iUVSetIndexToUseInGeometeryFunctions && texCoordArrays[m_iUVSetIndexToUseInGeometeryFunctions])
{
glTexCoordPointer(2, GL_FLOAT, 0, texCoordArrays[m_iUVSetIndexToUseInGeometeryFunctions]);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
else
{
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
// It sucks that I can't tell if the user has turned on vertex colours the usual CustomPolyDisply way, but there doesn't seem any
// way to detect this :(
//Displayf("getThisBoolAttr(aPointlessAttributeThatShouldBeDeletedButCantBecauseItIsSavedIntoExistingFiles2) = %d", getThisBoolAttr(aPointlessAttributeThatShouldBeDeletedButCantBecauseItIsSavedIntoExistingFiles2));
//Displayf("(colorCount > 0) = %d", (colorCount > 0));
//Displayf("colorArrays[0] = %d", colorArrays[0]);
//Displayf("===========================================================");
//DebugOutputOpenGlState();
if(UserSettings::ViewVertexColoursInMaya())
{
// Get the index of the vert colour set
MStatus obStatus;
MFnMesh obFnMesh(path, &obStatus);
MString strVertexColorSetNameForWithinMaya = "colorSet1";
if(obStatus == MS::kSuccess)
{
obFnMesh.getCurrentColorSetName(strVertexColorSetNameForWithinMaya);
}
int iVertexColourIndex = 0;
MStringArray astrRequiredVertexColorSetNames = GetRequiredVertexColorSetNames();
for(;iVertexColourIndex<colorCount; iVertexColourIndex++)
{
if(astrRequiredVertexColorSetNames[iVertexColourIndex] == strVertexColorSetNameForWithinMaya)
{
break;
}
}
if((iVertexColourIndex < colorCount) && (colorArrays[iVertexColourIndex] != NULL))
{
glColorPointer(4, GL_FLOAT, 0, colorArrays[iVertexColourIndex]);
glEnableClientState(GL_COLOR_ARRAY);
}
else
{
glDisableClientState(GL_COLOR_ARRAY);
}
}
else
{
glDisableClientState(GL_COLOR_ARRAY);
}
MMatrix mm = path.inclusiveMatrix();
if (mm.det3x3() < 0.0)
{
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
}
else
{
glCullFace(GL_BACK);
}
glDrawElements(prim, indexCount, GL_UNSIGNED_INT, indexArray);
}
MStatus rageShaderMaya::geometry(const MDrawRequest& request,
M3dView& view,
int prim,
unsigned int ,
int indexCount,
const unsigned int * indexArray,
int vertexCount,
const int * vertexIDs,
const float * vertexArray,
int normalCount,
const float ** normalArrays,
int colorCount,
const float ** colorArrays,
int texCoordCount,
const float ** texCoordArrays)
{
//Displayf("%d rageShaderMaya::geometry()", __LINE__);
view.beginGL();
geometry(request.multiPath(),
prim,
indexCount,
indexArray,
vertexCount,
vertexIDs,
vertexArray,
normalCount,
normalArrays,
colorCount,
colorArrays,
texCoordCount,
texCoordArrays);
view.endGL();
return MS::kSuccess;
}
MStatus rageShaderMaya::glGeometry(const MDagPath & shapePath,
int prim,
unsigned int ,
int indexCount,
const unsigned int * indexArray,
int vertexCount,
const int * vertexIDs,
const float * vertexArray,
int normalCount,
const float ** normalArrays,
int colorCount,
const float ** colorArrays,
int texCoordCount,
const float ** texCoordArrays)
{
//Displayf("%d rageShaderMaya::glGeometry(%s)", __LINE__, shapePath.fullPathName().asChar());
geometry(shapePath,
prim,
indexCount,
indexArray,
vertexCount,
vertexIDs,
vertexArray,
normalCount,
normalArrays,
colorCount,
colorArrays,
texCoordCount,
texCoordArrays);
return MS::kSuccess;
}
///////////////////////////////////////////////////////
// DESCRIPTION:
// This function gets called by Maya to do the rendering for the uv texture editor
//
//
//
//
///////////////////////////////////////////////////////
MStatus rageShaderMaya::renderImage ( const MString & , const float region[2][2], int& , int& )
{
// Bind the current texture
bind(false);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glBegin( GL_QUADS);
glTexCoord2f(region[0][0], region[0][1]);
glVertex2f(region[0][0], region[0][1]);
glTexCoord2f(region[0][0], region[1][1]);
glVertex2f(region[0][0], region[1][1]);
glTexCoord2f(region[1][0], region[1][1]);
glVertex2f(region[1][0], region[1][1]);
glTexCoord2f(region[1][0], region[0][1]);
glVertex2f(region[1][0], region[0][1]);
glEnd();
// Unbind the material
unbind();
return MStatus::kSuccess;
}
///////////////////////////////////////////////////////
// DESCRIPTION:
// This function gets called by Maya to do the drawing of the swatch
//
//
//
//
///////////////////////////////////////////////////////
MStatus rageShaderMaya::renderSwatchImage( MImage& outImage )
{
MStatus obStatus = MStatus::kFailure;
// Get the hardware renderer utility class
MHardwareRenderer *pRenderer = MHardwareRenderer::theRenderer();
if (pRenderer)
{
const MString& backEndStr = pRenderer->backEndString();
// Get geometry
// ============
unsigned int* pIndexing = 0;
unsigned int numberOfData = 0;
unsigned int indexCount = 0;
// Make the swatch context current
// ===============================
//
unsigned int width, height;
outImage.getSize( width, height );
unsigned int origWidth = width;
unsigned int origHeight = height;
MStatus obStatus2 = pRenderer->makeSwatchContextCurrent( backEndStr, width, height );
if( obStatus2 != MS::kSuccess )
{
return MStatus::kFailure;
}
// Get camera
// ==========
// Get the camera frustum from the API
double l, r, b, t, n, f;
pRenderer->getSwatchOrthoCameraSetting( l, r, b, t, n, f );
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho( l, r, b, t, n, f );
// Draw The Swatch
// ===============
// Set the default background color
if (!getThisBoolAttr(aDisplayTransparency))
{
glClearColor( 0.4f, 0.4f, 0.4f, 1.0f );
}
else
{
glClearColor( 1.0f, 0.0f, 1.0f, 1.0f );
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColorMask(true, true, true, false); // Disable the alpha write
// Scale the plane to fit
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glScalef(2.0f, 1.0f, 1.0f);
MHardwareRenderer::GeometricShape gshape = MHardwareRenderer::kDefaultSphere;
MGeometryData* pGeomData = pRenderer->referenceDefaultGeometry( gshape, numberOfData, pIndexing, indexCount );
if( !pGeomData )
{
return MStatus::kFailure;
}
if (pGeomData)
{
bind(false);
float *vertexData = (float *)( pGeomData[0].data() );
if (vertexData)
{
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer ( 3, GL_FLOAT, 0, vertexData );
}
float *uvData = (float *)(pGeomData[2].data());
if (uvData)
{
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glTexCoordPointer( 2, GL_FLOAT, 0, uvData );
}
if (vertexData && pIndexing )
glDrawElements ( GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, pIndexing );
unbind();
// Release data references
pRenderer->dereferenceGeometry( pGeomData, numberOfData );
}
// Read pixels back from swatch context to MImage
// ==============================================
pRenderer->readSwatchContextPixels( backEndStr, outImage );
// Double check the outing going image size as image resizing
// was required to properly read from the swatch context
outImage.getSize( width, height );
if (width != origWidth || height != origHeight)
{
obStatus = MStatus::kFailure;
}
else
{
obStatus = MStatus::kSuccess;
}
}
return obStatus;
}
int rageShaderMaya::getTexCoordSetNamesThatThisMaterialNeeds( MStringArray & names )
{
ValidateAndGetRageMaterial();
// Displayf("-> rageShaderMaya::getTexCoordSetNames");
names.clear();
// Get the parameter of the texture to display
Assertf(ValidateAndGetRageMaterial(), "Trying to the number of parameters of an uninitialized Material on Maya node %s", MFnDependencyNode(thisMObject()).name().asChar());
for (int i=0; i<ValidateAndGetRageMaterial()->GetParamCount(); i++)
{
shaderMaterialGeoParamValue * pobParam = ValidateAndGetRageMaterial()->GetParam(i);
if ((pobParam->GetSourceOfParamValue() & shaderMaterialGeoParamDescription::GeoInstance) && pobParam->GetType() == grcEffect::VT_TEXTURE)
{
// Get UV set for this texture param
MString strUVSet = pobParam->GetParamDescription()->GetUvSetName();
// Do I already have it?
bool bAddMe = true;
for(unsigned j=0; j<names.length(); j++)
{
if(names[j] == strUVSet)
{
bAddMe = false;
break;
}
}
if(bAddMe)
{
if(m_pCurrentTextureParam == pobParam)
{
m_iUVSetIndexToUseInGeometeryFunctions = names.length();
}
names.append(strUVSet);
}
}
}
//for(unsigned i=0; i<names.length(); i++)
//{
// Displayf("names[%d] = %s", i, names[i].asChar());
//}
// Displayf("<- rageShaderMaya::getTexCoordSetNames");
//names.clear();
//names.append("map1");
//names.append("grime");
//names.append("decal");
//names.append("window");
return names.length();
}
int rageShaderMaya::getTexCoordSetNamesThatEveryMeshUsingThisNodeHas( MStringArray & names )
{
// Displayf("-> rageShaderMaya::getTexCoordSetNames");
names.clear();
// Working out m_astrUVSetsUsedInGeometeryFunctions is slow, so only do it if I need to
if(m_astrUVSetsUsedInGeometeryFunctions.length() == 0)
{
ValidateAndGetRageMaterial();
// For all the meshes I'm on
MFnDependencyNode obFnShadingEngineNode(GetShaderEngineNode());
MStatus obStatus;
MPlugArray plugs;
obFnShadingEngineNode.getConnections(plugs);
for (u32 k=0; k<plugs.length(); k++)
{
// DEBUG_LOG_Start "%s %d %s %d/%d\n", __FILE__, __LINE__, plugs[k].name().asChar(), k, plugs.length() DEBUG_LOG_End;
MPlugArray otherPlugs;
plugs[k].connectedTo(otherPlugs, true, false);
for (u32 l=0; l<otherPlugs.length(); l++)
{
// DEBUG_LOG_Start "%s %d %s %d/%d\n", __FILE__, __LINE__, otherPlugs[l].name().asChar(), l, otherPlugs.length() DEBUG_LOG_End;
if (otherPlugs[l].node().hasFn(MFn::kMesh))
{
// DEBUG_LOG_Start "%s %d Found a mesh %s\n", __FILE__, __LINE__, otherPlugs[l].name().asChar() DEBUG_LOG_End;
// Found a mesh obFnNode, so render it, maybe
MObject obMeshNode(otherPlugs[l].node());
MFnMesh obFnMeshNode(obMeshNode, &obStatus);
if (obStatus == MStatus::kSuccess)
{
// Is it an intermediate ("history") mesh?
if(!obFnMeshNode.isIntermediateObject())
{
// Not history, so include it!
MStringArray astrMeshesUVSetNames;
obFnMeshNode.getUVSetNames(astrMeshesUVSetNames);
for(unsigned j=0; j<astrMeshesUVSetNames.length(); j++)
{
bool bAddMe = true;
for(unsigned k=0; k<m_astrUVSetsUsedInGeometeryFunctions.length(); k++)
{
if(m_astrUVSetsUsedInGeometeryFunctions[k] == astrMeshesUVSetNames[j])
{
bAddMe = false;
break;
}
}
if(bAddMe)
{
m_astrUVSetsUsedInGeometeryFunctions.append(astrMeshesUVSetNames[j]);
}
}
}
}
// DEBUG_LOG_Start "%s %d Made a mesh %s\n", __FILE__, __LINE__, otherPlugs[l].name().asChar() DEBUG_LOG_End;
}
}
}
}
m_iUVSetIndexToUseInGeometeryFunctions = 0;
if(m_pCurrentTextureParam && (m_astrUVSetsUsedInGeometeryFunctions[m_iUVSetIndexToUseInGeometeryFunctions] != m_pCurrentTextureParam->GetParamDescription()->GetUvSetName()))
{
for(unsigned i=0; i<m_astrUVSetsUsedInGeometeryFunctions.length(); i++)
{
if(m_astrUVSetsUsedInGeometeryFunctions[i] == m_pCurrentTextureParam->GetParamDescription()->GetUvSetName())
{
m_iUVSetIndexToUseInGeometeryFunctions = i;
}
}
}
names = m_astrUVSetsUsedInGeometeryFunctions;
//for(unsigned i=0; i<names.length(); i++)
//{
// Displayf("names[%d] = %s", i, names[i].asChar());
//}
//Displayf("<- rageShaderMaya::getTexCoordSetNames");
//names.clear();
//names.append("map1");
//names.append("grime");
//names.append("decal");
//names.append("grime");
//names.append("window");
//names.append("channelmap");
return names.length();
}
// ************************************* WARNING!!!!! *************************************
// getTexCoordSetNames is called by Maya and is supposed to return a list of the UV sets
// that this node needs to render correctly. If you define USE_SENSIBLE_BUT_CRASHY_getTexCoordSetNames_FUNCTION
// this is exactly what it does.
//
// However, if you do this, bad random things happen. For example moving verts on "some"
// meshes will case Maya to crash, you'll be unable to duplicate "some" meshes, etc....
//
// So instead, if you do not define USE_SENSIBLE_BUT_CRASHY_getTexCoordSetNames_FUNCTION
// an insane version is used with just returns the name of every UV set on every mesh
// attached to this node.
// ************************************* WARNING!!!!! *************************************
// #define USE_SENSIBLE_BUT_CRASHY_getTexCoordSetNames_FUNCTION
int rageShaderMaya::getTexCoordSetNames( MStringArray & names )
{
#ifdef USE_SENSIBLE_BUT_CRASHY_getTexCoordSetNames_FUNCTION
return getTexCoordSetNamesThatThisMaterialNeeds(names);
#else
return getTexCoordSetNamesThatEveryMeshUsingThisNodeHas(names);
#endif
}
int rageShaderMaya::getColorSetNames( MStringArray & names )
{
ValidateAndGetRageMaterial();
// Displayf("-> rageShaderMaya::getTexCoordSetNames");
names.clear();
for(unsigned i=0; i<GetRequiredVertexColorSetNames().length(); i++)
{
names.append(GetRequiredVertexColorSetNames()[i]);
}
return names.length();
}
///////////////////////////////////////////////////////
// DESCRIPTION:
// This function gets called by Maya return the names of all
// the available images given the uvset name.
//
//
//
///////////////////////////////////////////////////////
MStatus rageShaderMaya::getAvailableImages ( const MString & , MStringArray & imageNames)
{
u32 nCurrentTextureIndex = 0;
// Add the name of the texture
imageNames.clear();
imageNames.append("Maya Default Color");
if(!ValidateAndGetRageMaterial())
{
// If no material and I can't create one, then bail
return MS::kSuccess;
}
for (int i=0; i<ValidateAndGetRageMaterial()->GetParamCount(); i++)
{
shaderMaterialGeoParamValue * pobParam = ValidateAndGetRageMaterial()->GetParam(i);
if ((pobParam->GetSourceOfParamValue() & shaderMaterialGeoParamDescription::GeoInstance) && pobParam->GetType() == grcEffect::VT_TEXTURE)
{
shaderMaterialGeoParamValueTexture * param = (shaderMaterialGeoParamValueTexture *)ValidateAndGetRageMaterial()->GetParam(i);
imageNames.append(param->GetValue());
if (param == m_pCurrentTextureParam)
{
nCurrentTextureIndex = imageNames.length();
}
}
}
// First I don't like what I'm doing if this function worked correctly I would not be doing this
// Maya does not return the uvSetName that it is suppose to. Then on top of that it initializes
// the UV texture window with the first element which is just black.
// lets stop the timer and get a reading
sm_Timer.endTimer();
// Keep track of the time in seconds / Do this at most once a second
static double s_dTimeStamp = 1.0;
// Increment the time
s_dTimeStamp += sm_Timer.elapsedTime();
if (s_dTimeStamp >= 1.0)
{
// Get the panel name of the uv editor
MStringArray panelName;
MGlobal::executeCommand("getPanel -sty polyTexturePlacementPanel", panelName, g_bDisplayMGlobalExecuteCommands);
static int s_imageNumber = -1;
int imageNumber = -1;
char buffer[256];
formatf(buffer, sizeof(buffer), "textureWindow -q -imageNumber %s;", panelName[0].asChar());
MGlobal::executeCommand(buffer, imageNumber, g_bDisplayMGlobalExecuteCommands);
if (s_imageNumber != (int)nCurrentTextureIndex)
{
// formatf(buffer, sizeof(buffer), "textureWindow -e -setUvSet %d %s;", m_nCurrentTextureCoordSet, panelName[0].asChar());
// MGlobal::executeCommandOnIdle(buffer, g_bDisplayMGlobalExecuteCommands);
// For all the meshes I'm on
MFnDependencyNode obFnShadingEngineNode(GetShaderEngineNode());
MStatus obStatus;
MPlugArray plugs;
obFnShadingEngineNode.getConnections(plugs);
for (u32 k=0; k<plugs.length(); k++)
{
// DEBUG_LOG_Start "%s %d %s %d/%d\n", __FILE__, __LINE__, plugs[k].name().asChar(), k, plugs.length() DEBUG_LOG_End;
MPlugArray otherPlugs;
plugs[k].connectedTo(otherPlugs, true, false);
for (u32 l=0; l<otherPlugs.length(); l++)
{
// DEBUG_LOG_Start "%s %d %s %d/%d\n", __FILE__, __LINE__, otherPlugs[l].name().asChar(), l, otherPlugs.length() DEBUG_LOG_End;
if (otherPlugs[l].node().hasFn(MFn::kMesh))
{
// DEBUG_LOG_Start "%s %d Found a mesh %s\n", __FILE__, __LINE__, otherPlugs[l].name().asChar() DEBUG_LOG_End;
// Found a mesh obFnNode, so render it, maybe
MObject obMeshNode(otherPlugs[l].node());
MFnMesh obFnMeshNode(obMeshNode, &obStatus);
if (obStatus == MStatus::kSuccess)
{
// Is it an intermediate ("history") mesh?
if(!obFnMeshNode.isIntermediateObject() && m_pCurrentTextureParam)
{
// Not history, so render it!
// DEBUG_LOG_Start "%s %d About to do something to it %s\n", __FILE__, __LINE__, otherPlugs[l].name().asChar() DEBUG_LOG_End;
formatf(buffer, sizeof(buffer), "polyUVSet -currentUVSet -uvSet \"%s\" \"%s\"", m_pCurrentTextureParam->GetParamDescription()->GetUvSetName(), obFnMeshNode.fullPathName().asChar());
MGlobal::executeCommandOnIdle(buffer, g_bDisplayMGlobalExecuteCommands);
}
}
else
{
// Badness has happened, obMeshNode hasFn(MFn::kMesh) but it can't be used to create a obFnMeshNode
// This should be impossible
//Errorf("%s %d", __FILE__, __LINE__);
//Errorf("Badness has happened, obMeshNode hasFn(MFn::kMesh) but it can't be used to create a obFnMeshNode.");
//Errorf("This should be impossible.");
//Errorf("This might give you a clue what has happened : %s", otherPlugs[l].name().asChar());
//Errorf("%s", obStatus.errorString().asChar());
}
// DEBUG_LOG_Start "%s %d Made a mesh %s\n", __FILE__, __LINE__, otherPlugs[l].name().asChar() DEBUG_LOG_End;
}
}
}
}
if (imageNumber == 0)
{
// Make sure we set the current texture in the uv editor
formatf(buffer, sizeof(buffer), "textureWindow -e -imageNumber %d %s;", nCurrentTextureIndex, panelName[0].asChar());
MGlobal::executeCommandOnIdle(buffer, g_bDisplayMGlobalExecuteCommands);
}
s_imageNumber = nCurrentTextureIndex;
s_dTimeStamp = 0.0;
}
// Start the timer again
sm_Timer.beginTimer();
return MStatus::kSuccess;
}
///////////////////////////////////////////////////////
// DESCRIPTION:
// This function gets called by Maya to return the number of
// of normals per vertex.
//
//
///////////////////////////////////////////////////////
int rageShaderMaya::normalsPerVertex()
{
return 1;
}
///////////////////////////////////////////////////////
// DESCRIPTION:
// This function gets called by Maya to return the number of
// of colors per vertex.
//
//
///////////////////////////////////////////////////////
int rageShaderMaya::colorsPerVertex()
{
return 1;
}
///////////////////////////////////////////////////////
// DESCRIPTION:
// This function gets called by Maya to return the number of
// of texture coords per vertex.
//
//
///////////////////////////////////////////////////////
//int rageShaderMaya::texCoordsPerVertex()
//{
// // There is no way to know what the correct amount of UV sets is.
// // The shader doesn't know because the meshes might have other, unrelated, uv sets.
// // The meshes don't know because they might not have all the sets they need
// // So just return a magic number that is probably good enough
// return 16;
//}
///////////////////////////////////////////////////////
// DESCRIPTION:
// This function gets called by Maya to return if this
// shader has alpha.
//
///////////////////////////////////////////////////////
bool rageShaderMaya::hasTransparency()
{
return getThisBoolAttr(aDisplayTransparency);
}
///////////////////////////////////////////////////////
// DESCRIPTION:
// This function gets called by the save mtl file.
//
// The function returns the default mtl file name.
//
///////////////////////////////////////////////////////
MString rageShaderMaya::getDefaultMtlFileName()
{
Assertf(ValidateAndGetRageMaterial(), "Trying to get the name of an uninitialized Material on Maya node %s", MFnDependencyNode(thisMObject()).name().asChar());
MString mtlName = ValidateAndGetRageMaterial()->GetShaderName();
for (int i=0; i<ValidateAndGetRageMaterial()->GetParamCount(); i++)
{
shaderMaterialGeoParamValue * pobParam = ValidateAndGetRageMaterial()->GetParam(i);
if ((pobParam->GetSourceOfParamValue() & shaderMaterialGeoParamDescription::GeoInstance) && pobParam->GetType() == grcEffect::VT_TEXTURE)
{
char buffer[256];
fiAssetManager::BaseName(buffer, sizeof(buffer), fiAssetManager::FileName(((shaderMaterialGeoParamValueTexture *)pobParam)->GetValue()));
mtlName = MString(buffer) ;
formatf(buffer, sizeof(buffer), "getDefaultMtlName(\"%s\", \"%s\")", mtlName.asChar(), ValidateAndGetRageMaterial()->GetShaderName());
MGlobal::executeCommand(buffer, mtlName, g_bDisplayMGlobalExecuteCommands);
break;
}
}
if(mtlName == "")
{
return "";
}
return mtlName + ".mtlgeo";
}
///////////////////////////////////////////////////////
// DESCRIPTION:
// This function gets called by Maya when a value is set
//
// The function calls the appropriate function to handle
// creating, loading, and saving RAGE materials.
//
///////////////////////////////////////////////////////
bool rageShaderMaya::setInternalValueInContext (const MPlug & plug,
const MDataHandle & handle,
MDGContext & context)
{
// If name() == "", then just forget it, I've not been made yet
if(name().length() == 0) return MPxNode::setInternalValueInContext(plug, handle, context);
//if we have copied and pasted this is to catch the .MTL filename setting
// The format for this is ("pasted_:" + name of node + ".MTtlFilename")
// IE (pasted_:rageShaderMaya1.MtlFilename)
MString sPlugName = plug.name();
if (strstr(sPlugName.asChar(), "pasted_:"))
{
bool retval = false;
if (plug == aMtlFile)
{
MString strMaterialPathAndFilename = handle.asString();
// Get the current mtl file name
if (strMaterialPathAndFilename.length() != 0)
{
SetMaterialPathAndFilename(strMaterialPathAndFilename);
m_bNodeIsCopy = true;//tells the save we need to be different
}
//Let the value be set in the MPxNode
retval = MPxNode::setInternalValueInContext(plug, handle, context);
}
else if (plug == aTextureToDisplayInMaya)
{
MString strMtlFileName;
getThisStringAttr("MtlFilename", strMtlFileName);
if (strMtlFileName.length() != 0)
{
SetTextureToDisplayInMaya(handle.asString());
}
retval = MPxNode::setInternalValueInContext(plug, handle, context);
}
return retval;
}
// If I am loading, then bail
if(skipSetInternalValueInContext()) return MPxNode::setInternalValueInContext(plug, handle, context);
//char acNodeName[BUFFER_SIZE];
//strcpy(acNodeName, name().asChar());
//char acPlugName[BUFFER_SIZE];
//strcpy(acPlugName, plug.name().asChar());
//MString strOldPlugValue;
//plug.getValue(strOldPlugValue);
//char acOldPlugValue[BUFFER_SIZE];
//strcpy(acOldPlugValue, strOldPlugValue.asChar());
//char acNewPlugValue[BUFFER_SIZE];
//strcpy(acNewPlugValue, handle.asString().asChar());
//Displayf("%s%s is being set from %s to %s", acNodeName, acPlugName, acOldPlugValue, acNewPlugValue);
if(plug == aMtlFile)
{
// Displayf("isReadingFile() = %d", MFileIO::isReadingFile());
// New material FILE, if it isn't blank, load it
MString strMaterialPathAndFilename = handle.asString();
// Get the current mtl file name
if (strMaterialPathAndFilename.length() != 0)
{
loadFromMTLFile(strMaterialPathAndFilename);
}
}
else if (plug == aTextureToDisplayInMaya)
{
if (GetRageMaterial())
{
SetTextureToDisplayInMaya(handle.asString());
}
}
else if (plug == aCommand)
{
// Save the material to the given file name
MString sAttrValue = handle.asString();
// Get the current mtl file name
if (!sAttrValue.length())
{
return MPxNode::setInternalValueInContext(plug, handle, context);
}
IssueCommand(sAttrValue.asChar());
setThisStringAttr("Command", "");
}
else
{
if (GetRageMaterial())
{
ParametersAttributeValueChanged(plug, handle);
}
}
return MPxNode::setInternalValueInContext(plug, handle, context);
}
MStringArray rageShaderMaya::IssueCommand(const char* pcCommand)
{
MStringArray obAStrReturnMe;
MStringArray obAStrCommandParts; MString(pcCommand).split(' ', obAStrCommandParts);
MString strCommand = obAStrCommandParts[0];
if (strCommand == "reload")
{
// Save the mtl name
if (GetMaterialPathAndFilename().length() > 0)
{
loadFromMTLFile(GetMaterialPathAndFilename());
}
}
else if (strCommand == "expandTextureNodes")
{
// Should I wire up textures?
if (!getThisBoolAttr(aTextureOverride))
{
Assertf(ValidateAndGetRageMaterial(), "Trying to wire up the textures of an uninitialized Material on Maya node %s", MFnDependencyNode(thisMObject()).name().asChar());
rageShaderMaterialMaya::ExpandTextureNodes(thisMObject(), *ValidateAndGetRageMaterial());
}
}
else if (strCommand == "addToViewer")
{
addToViewer();
}
else if (strCommand == "removeFromViewer")
{
removeFromViewer();
}
else if (strCommand == "save")
{
SaveMaterialFile();
}
else if (strCommand == "saveAs")
{
BrowseForMaterialFileAndSaveToIt();
}
else if (strCommand == "saveTo")
{
MString strMtlPathAndFilename = obAStrCommandParts[obAStrCommandParts.length() - 1];
m_bMaterialChangedSinceLastSaved = true;
saveMaterialAndSetMaterialFilenameAttribute(strMtlPathAndFilename);
}
else if (strCommand == "forceSave")
{
m_bMaterialChangedSinceLastSaved = true;
SaveMaterialFile();
}
else if (strCommand == "mtlFileName")
{
if (GetRageMaterial())
{
char command[128];
formatf(command, sizeof(command), "print \"%s\"", GetMaterialPathAndFilename().asChar());
MGlobal::executeCommand(command, g_bDisplayMGlobalExecuteCommands);
}
}
else if (strCommand == "templateFileName")
{
if (GetRageMaterial())
{
char command[256];
formatf(command, sizeof(command), "print \"%s\"", GetRageMaterial()->GetTemplate()->GetTemplatePathAndFilename());
MGlobal::executeCommand(command, g_bDisplayMGlobalExecuteCommands);
}
}
else if (strCommand == "validateInternalMaterial")
{
ValidateAndGetRageMaterial();
}
else if (strCommand == "getRequiredVertexColorSetNames")
{
return GetRequiredVertexColorSetNames();
}
else if (strCommand == "getTemplate")
{
if(ValidateAndGetRageMaterial())
{
obAStrReturnMe.append(ValidateAndGetRageMaterial()->GetTemplate()->GetTemplatePathAndFilename());
}
}
else if (strCommand == "getType")
{
if(ValidateAndGetRageMaterial())
{
obAStrReturnMe.append(ValidateAndGetRageMaterial()->GetParentTypePathAndFilename());
}
}
else if (strCommand == "newMtl")
{
MString strGeoTypeOrTemplatePathAndFileName = obAStrCommandParts[obAStrCommandParts.length() - 1];
// Is it a type or a template?
if (strstr(strGeoTypeOrTemplatePathAndFileName.asChar(), ".geotype") != 0)
{
// Given a geotype, so all good
loadFromTypeFile(strGeoTypeOrTemplatePathAndFileName.asChar());
}
else if (strstr(strGeoTypeOrTemplatePathAndFileName.asChar(), ".geotemplate") != 0)
{
// Given a geotemplate, so get matching default geotype
loadFromTemplateFile(strGeoTypeOrTemplatePathAndFileName.asChar());
}
else
{
if (!UserSettings::SilentRunning())
{
MString filename = getFileToOpen("RAGE Shader Material Type (*.geotype)\0*.geotype\0", GetPathToLastLoadedTypeFile());
if (filename.length())
{
// Set the modified flag to flag a save at close
m_bMaterialChangedSinceLastSaved = true;
loadFromTypeFile(filename.asChar());
}
}
}
}
else if (strCommand == "loadMtl")
{
// pcCommand contains "loadMtl <filename>", so the filename is everything past the first ' '
const char* pcFilenamePos = strchr(pcCommand, ' ');
if(pcFilenamePos == NULL)
{
MString filename = getFileToOpen("RAGE Shader Material (*.mtlgeo)\0*.mtlgeo;\0", GetPathToLastLoadedMtlFile());
if (filename.length())
{
MPlug obMtlFilenamePlug = MFnDependencyNode(thisMObject()).findPlug(aMtlFile);
obMtlFilenamePlug.setValue(filename.asChar());
}
}
else
{
pcFilenamePos++;
MPlug obMtlFilenamePlug = MFnDependencyNode(thisMObject()).findPlug(aMtlFile);
obMtlFilenamePlug.setValue(pcFilenamePos);
}
}
else if (strCommand == "saveAsNewType")
{
saveAsNewType();
}
else if (strCommand == "saveType")
{
saveType();
}
else if (strCommand == "reloadType")
{
reloadType();
}
else
{
MGlobal::executeCommand(("rageUserError(\"Attempting to issue command [" + strCommand + "] but it is no longer supported\")"), g_bDisplayMGlobalExecuteCommands);
}
return obAStrReturnMe;
}
///////////////////////////////////////////////////////
// DESCRIPTION:
// This function gets called when the node is duplicated or when a maya file is being loaded
//
// The function copies all the internal data to the new node
//
///////////////////////////////////////////////////////
void rageShaderMaya::copyInternalData (MPxNode *node)
{
// If I am loading, then bail (copyInternalData is called sometimes when loading references)
if(skipSetInternalValueInContext()) return;
// Copy all the data we need
rageShaderMaya * shader = (rageShaderMaya *)node;
SetMaterialPathAndFilename(shader->GetMaterialPathAndFilename());
m_bNodeIsCopy = true;
}
void rageShaderMaya::loadFromTemplateFile(const MString& strTemplateFilename)
{
//standardize this file name
MString strTemplateFilenameLC = strTemplateFilename;
strTemplateFilenameLC.toLowerCase();
//Does material file exist?
WIN32_FIND_DATA FindFileData;
HANDLE hFind = FindFirstFile(strTemplateFilenameLC.asChar(), &FindFileData);
//Does material file exist?
if (hFind != INVALID_HANDLE_VALUE)
{
FindClose(hFind);
// File exists, so load it
delete m_pobRageMaterial;
m_pobRageMaterial = new rageShaderMaterial();
if (!createFromTemplateFile(strTemplateFilename, m_pobRageMaterial))
{
delete m_pobRageMaterial;
m_pobRageMaterial = NULL;
}
else
{
SetPathToLastLoadedTemplateFile(strTemplateFilename.asChar());
}
}
else
{
//disable so we dont spew so much
//MGlobal::displayError("Unable to find geoTemplate file "+ strTemplateFilenameLC);
}
}
void rageShaderMaya::loadFromTypeFile(const MString& strTypeFilename)
{
//standardize this file name
MString strTypeFilenameLC = strTypeFilename;
strTypeFilenameLC.toLowerCase();
//Does material file exist?
WIN32_FIND_DATA FindFileData;
HANDLE hFind = FindFirstFile(strTypeFilenameLC.asChar(), &FindFileData);
//Does material file exist?
if (hFind != INVALID_HANDLE_VALUE)
{
FindClose(hFind);
// File exists, so load it
delete m_pobRageMaterial;
m_pobRageMaterial = new rageShaderMaterial();
if (!createFromTypeFile(strTypeFilename, m_pobRageMaterial))
{
delete m_pobRageMaterial;
m_pobRageMaterial = NULL;
}
else
{
SetPathToLastLoadedTypeFile(strTypeFilename.asChar());
}
}
else
{
//disable so we dont spew so much
//MGlobal::displayError("Unable to find geotype file "+ strTypeFilenameLC);
}
}
void rageShaderMaya::loadFromMTLFile(const MString& strMaterialFilename)
{
//standardize this file name
MString strMaterialFilenameLC = strMaterialFilename;
strMaterialFilenameLC.toLowerCase();
//Does material file exist?
WIN32_FIND_DATA FindFileData;
HANDLE hFind = FindFirstFile(strMaterialFilenameLC.asChar(), &FindFileData);
//Does material file exist?
if (hFind != INVALID_HANDLE_VALUE)
{
FindClose(hFind);
// File exists, so load it
delete m_pobRageMaterial;
m_pobRageMaterial = new rageShaderMaterial();
if (!createFromMTLFile(strMaterialFilenameLC, m_pobRageMaterial))
{
delete m_pobRageMaterial;
m_pobRageMaterial = NULL;
}
else
{
SetPathToLastLoadedMtlFile(strMaterialFilenameLC.asChar());
}
}
else
{
//disable so we dont spew so much
//MGlobal::displayError("Unable to find mtl file "+ strMaterialFilenameLC);
}
}
void rageShaderMaya::saveAsNewType()
{
if (!UserSettings::SilentRunning())
{
char typeFileName[256];
OPENFILENAME ofn;
memset(&ofn, 0, sizeof(ofn));
memset(typeFileName, 0, sizeof(typeFileName));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = M3dView::applicationShell();
ofn.lpstrFilter = "RAGE Shader Material Type (*.geotype)\0*.geotype\0";
ofn.lpstrInitialDir = GetPathToLastLoadedTypeFile();
ofn.nMaxFile = sizeof(typeFileName);
ofn.lpstrFile = typeFileName;
if (GetSaveFileName(&ofn))
{
// Set the modified flag to flag a save at close
m_bMaterialChangedSinceLastSaved = true;
// Lets make sure it is the one we want stupid maya problem
for (int i=0; i<StringLength(typeFileName); i++)
{
if (typeFileName[i]=='\\')
{
typeFileName[i] = '/';
}
}
rageShaderMaterial* pobRageMaterial = ValidateAndGetRageMaterial();
if (pobRageMaterial)
{
shaderMaterialGeoInstance* pobShaderMaterialGeoInstance = SHADER_MATERIAL_GEO_MANAGER.GetShaderMaterialGeoInstanceFromUID(pobRageMaterial->GetInstanceGUID());
Assertf(pobShaderMaterialGeoInstance, "Trying to get geoinstance [%s] on to an uninitialized Material on Maya node %s", pobRageMaterial->GetInstancePathAndFilename(), MFnDependencyNode(thisMObject()).name().asChar());
shaderMaterialGeoType* pobShaderMaterialGeoType = SHADER_MATERIAL_GEO_MANAGER.GetShaderMaterialGeoType(pobRageMaterial->GetParentTypePathAndFilename());
Assertf(pobShaderMaterialGeoType, "Trying to get geotype [%s] on to an uninitialized Material on Maya node %s", pobRageMaterial->GetParentTypePathAndFilename(), MFnDependencyNode(thisMObject()).name().asChar());
//copy over any changes
pobShaderMaterialGeoType->CopyParamValuesSelectively((*pobShaderMaterialGeoInstance));
if(pobShaderMaterialGeoType->SaveTo(typeFileName))
{
Displayf("success saving file [%s]", typeFileName);
}
}
}
}
}
void rageShaderMaya::saveType()
{
if (!UserSettings::SilentRunning())
{
rageShaderMaterial* pobRageMaterial = ValidateAndGetRageMaterial();
if (pobRageMaterial)
{
shaderMaterialGeoInstance* pobShaderMaterialGeoInstance = SHADER_MATERIAL_GEO_MANAGER.GetShaderMaterialGeoInstanceFromUID(pobRageMaterial->GetInstanceGUID());
Assertf(pobShaderMaterialGeoInstance, "Trying to get geoinstance [%s] on to an uninitialized Material on Maya node %s", pobRageMaterial->GetInstancePathAndFilename(), MFnDependencyNode(thisMObject()).name().asChar());
shaderMaterialGeoType* pobShaderMaterialGeoType = SHADER_MATERIAL_GEO_MANAGER.GetShaderMaterialGeoType(pobRageMaterial->GetParentTypePathAndFilename());
Assertf(pobShaderMaterialGeoType, "Trying to get geotype [%s] on to an uninitialized Material on Maya node %s", pobRageMaterial->GetParentTypePathAndFilename(), MFnDependencyNode(thisMObject()).name().asChar());
//copy over any changes
pobShaderMaterialGeoType->CopyParamValuesSelectively((*pobShaderMaterialGeoInstance));
if(pobShaderMaterialGeoType->SaveTo(pobRageMaterial->GetParentTypePathAndFilename()))
{
Displayf("success saving file [%s]", pobRageMaterial->GetParentTypePathAndFilename());
}
}
}
}
void rageShaderMaya::reloadType()
{
if (!UserSettings::SilentRunning())
{
// FAKED OUT FOR NOW FIX THIS.
//if (GetMaterialPathAndFilename().length() > 0)
//{
// loadFromMTLFile(GetMaterialPathAndFilename());
//}
}
}
bool rageShaderMaya::createFromTemplateFile(const MString& strTemplateFilename, rageShaderMaterial* pobRageMaterial)
{
Assertf(pobRageMaterial, "Trying to load geotemplate [%s] on to an uninitialized Material on Maya node %s", strTemplateFilename.asChar(), MFnDependencyNode(thisMObject()).name().asChar());
bool retval = false;
if (pobRageMaterial->LoadFromTemplate(strTemplateFilename.asChar()))
{
postCreate(pobRageMaterial);
retval = true;
}
else
{
MGlobal::executeCommand("rageUserError(\"Errors occurred loading "+ strTemplateFilename +" see the output window for more information.\")", g_bDisplayMGlobalExecuteCommands);
}
//reset the MtlFile name so we don't override an existing MTL
setThisStringAttr("MtlFilename", "");
// Set that it has not changed
m_bMaterialChangedSinceLastSaved = false;
return retval;
}
bool rageShaderMaya::createFromTypeFile(const MString& strTypeFilename, rageShaderMaterial* pobRageMaterial)
{
Assertf(pobRageMaterial, "Trying to load geotype [%s] on to an uninitialized Material on Maya node %s", strTypeFilename.asChar(), MFnDependencyNode(thisMObject()).name().asChar());
bool retval = false;
if (pobRageMaterial->LoadFromType(strTypeFilename.asChar()))
{
postCreate(pobRageMaterial);
retval = true;
}
else
{
MGlobal::executeCommand("rageUserError(\"Errors occurred loading "+ strTypeFilename +" see the output window for more information.\")", g_bDisplayMGlobalExecuteCommands);
}
//reset the MtlFile name so we don't override an existing MTL
setThisStringAttr("MtlFilename", "");
// Set that it has not changed
m_bMaterialChangedSinceLastSaved = false;
return retval;
}
bool rageShaderMaya::createFromMTLFile(const MString& strMaterialFilename, rageShaderMaterial* pobRageMaterial)
{
Assertf(pobRageMaterial, "Trying to load mtl [%s] on to an uninitialized Material on Maya node %s", strMaterialFilename.asChar(), MFnDependencyNode(thisMObject()).name().asChar());
bool retval = false;
if (pobRageMaterial->LoadFromMTL(strMaterialFilename.asChar()))
{
postCreate(pobRageMaterial);
retval = true;
}
else
{
MGlobal::executeCommand("rageUserError(\"Errors occurred loading "+ strMaterialFilename +" see the output window for more information.\")", g_bDisplayMGlobalExecuteCommands);
}
if (m_bNodeIsCopy)
{
//reset the MtlFile name so we don't override an existing MTL
setThisStringAttr("MtlFilename", "");
//it is nolonger a copy
m_bNodeIsCopy = false;
}
// Set that it has not changed
m_bMaterialChangedSinceLastSaved = false;
return retval;
}
void rageShaderMaya::postCreate(rageShaderMaterial* pobRageMaterial)
{
UpdateTextureOverrides();
if(!isLocked())
{
//Add attributes to maya node
skipSetInternalValueInContext(true);
rageShaderMaterialMaya::AddToMayaNode(thisMObject(), (*pobRageMaterial), &m_DeletedExistingDataDuringCreation);
// This is such a hack and will probably slow down the load time of
// a scene, but doing it so attribute relationships can be evaluated.
// Created to allow attributes to manipulate the maya default color for an RSM
if (!rageShaderMaya::getIgnoreReferencedNodesDuringWireUpTextures())
{
for (int i=0; i<pobRageMaterial->GetShaderParamCount(); i++)
{
Assert(pobRageMaterial->GetShaderParam(i));
Assert(pobRageMaterial->GetShaderParam(i)->GetParamDescription());
MString attribute = pobRageMaterial->GetShaderParam(i)->GetParamDescription()->GetUIName();
CallAttributeWatchScriptFunction(this->name(), attribute);
}
}
skipSetInternalValueInContext(false);
// Setup user options
if(UserSettings::ExpandTexturesOnFileLoad() && !getThisBoolAttr(aTextureOverride))
{
rageShaderMaterialMaya::ExpandTextureNodes(thisMObject(), (*pobRageMaterial));
}
// Set the texture to display in maya
MPlug obTextureToDisplayInMayaPlug(thisMObject(), aTextureToDisplayInMaya);
MString strTextureToDisplayInMaya = "Maya Default Color";
obTextureToDisplayInMayaPlug.getValue(strTextureToDisplayInMaya);
if(
(strTextureToDisplayInMaya.length() == 0) || //no texture to display in maya
(strTextureToDisplayInMaya == "Composite Render") // set to composite render
)
{
strTextureToDisplayInMaya = "Maya Default Color";
}
obTextureToDisplayInMayaPlug.setValue(strTextureToDisplayInMaya);
}
}
///////////////////////////////////////////////////////
// DESCRIPTION:
// This function gets called by setInternalValue()
//
// The function saves the current loaded material data to
// the given .mtl file.
//
///////////////////////////////////////////////////////
bool rageShaderMaya::saveMaterialAndSetMaterialFilenameAttribute(const MString& strMaterialFilename)
{
if(!m_bMaterialChangedSinceLastSaved || !ValidateAndGetRageMaterial())
{
// Nothing to save
return false;
}
if(getThisBoolAttr(aTextureOverride))
{
// Nothing to save
return false;
}
MFnDependencyNode obFnShaderNode(thisMObject());
if (obFnShaderNode.isFromReferencedFile())
{
//object is from a referenced file don't save it.
return false;
}
if (!strstr(strMaterialFilename.asChar(), ".mtl"))
{
MGlobal::executeCommand("rageUserError(\"Invalid file name "+ strMaterialFilename +"\")", g_bDisplayMGlobalExecuteCommands);
return false;
}
// Does the file already exist?
int eFileAttributes = GetFileAttributes(strMaterialFilename.asChar());
if (eFileAttributes != INVALID_FILE_ATTRIBUTES)
{
// File already exists, is the file readonly?
if(eFileAttributes & FILE_ATTRIBUTE_READONLY)
{
// File is read only, so bail (we can not modify read only files so why ask to save)
MGlobal::executeCommand(MString("rageError(\"Current material is read only : ")+ GetMaterialPathAndFilename() +"\")");
return false;
}
}
// I need here to "get" the value of every plug that represents a shader parameter.
// I don't actually care what the value is, but by "getting" it I force Maya to call
// rageShaderMaya::setInternalValueInContext with the attribute, which is the only way
// I can make sure the current value has been written back into my m_RageMaterial
MFnDependencyNode obFnThis(thisMObject());
float fSomeThingToGrabInto;
for (int i=0; i<ValidateAndGetRageMaterial()->GetParamCount(); i++)
{
shaderMaterialGeoParamValue * pobParam = ValidateAndGetRageMaterial()->GetParam(i);
MPlug plug = obFnThis.findPlug(rageShaderMaterialMayaParam::GetCleanVersionOfString(pobParam->GetParamDescription()->GetUIName()).asChar());
if (!plug.isNull())
{
plug.getValue(fSomeThingToGrabInto);
}
}
// Save the material
if (getThisBoolAttr(aTextureOverride) && (eFileAttributes != INVALID_FILE_ATTRIBUTES))
{
// They are using the evil texture override option, so load the file, modify the textures
// to use what the file has in it.
rageShaderMaterial obRageMaterialCurrrent;
obRageMaterialCurrrent.Copy(*ValidateAndGetRageMaterial());
rageShaderMaterial obRageMaterialFile;
obRageMaterialFile.LoadFromMTL(strMaterialFilename.asChar());
// Copy over all the texture parameters to save to the .mtl file
for (int i=0; i<obRageMaterialCurrrent.GetParamCount(); i++)
{
shaderMaterialGeoParamValue * param = obRageMaterialCurrrent.GetParam(i);
if (param->GetType() == grcEffect::VT_TEXTURE)
{
for (int j=0; j<obRageMaterialFile.GetParamCount(); j++)
{
shaderMaterialGeoParamValue * paramFile = obRageMaterialFile.GetParam(j);
if (paramFile->GetType() == grcEffect::VT_TEXTURE &&
stricmp(param->GetParamDescription()->GetUIName(), paramFile->GetParamDescription()->GetUIName())==0)
{
param->Copy(paramFile);
break;
}
}
}
}
// Save the hacked copy
bool bSuccess = obRageMaterialCurrrent.SaveTo(strMaterialFilename.asChar());
if(!bSuccess)
{
// Unable to save file, so bail
MGlobal::executeCommand("rageUserError(\"Could not save file "+ strMaterialFilename +"\")", g_bDisplayMGlobalExecuteCommands);
return false;
}
}
else
{
if (!ValidateAndGetRageMaterial()->SaveTo(strMaterialFilename.asChar()))
{
// Unable to save file, so bail
MGlobal::executeCommand("rageUserError(\"Could not save file "+ strMaterialFilename +"\")", g_bDisplayMGlobalExecuteCommands);
return false;
}
}
SetMaterialPathAndFilename(strMaterialFilename);
// Set the modified flag to not prompt a save because we just saved the material
m_bMaterialChangedSinceLastSaved = false;
return true;
}
bool rageShaderMaya::BrowseForMaterialFileAndSaveToIt()
{
if (!UserSettings::SilentRunning())
{
char mtlPathName[256];
char mtlFileName[256];
OPENFILENAME ofn;
memset(&ofn, 0, sizeof(ofn));
memset(mtlPathName, 0, sizeof(mtlPathName));
memset(mtlFileName, 0, sizeof(mtlFileName));
MString fileName = getDefaultMtlFileName();
//const char* pcNodeName = MFnDependencyNode(thisMObject()).name().asChar();
//const char* pcFileName = fileName.asChar();
//Displayf("rageShaderMaya::BrowseForMaterialFileAndSaveToIt() Node = %s Mtl = %s", pcNodeName, pcFileName);
if((fileName == "error") || (fileName == ".mtl"))
{
// Can't save the file, there is no material specified
// Unable to save file, so bail
MGlobal::executeCommand("rageUserError(\"Could not save file material for node "+ MFnDependencyNode(thisMObject()).name() +" as no material has been set.\"); select "+ MFnDependencyNode(thisMObject()).name(), g_bDisplayMGlobalExecuteCommands);
return false;
}
// If we don't have a file name then insert the node name as the file name
if (fileName == "")
{
fileName = MFnDependencyNode(thisMObject()).name();
fileName += ".mtlgeo";
}
strcpy(mtlFileName, fileName.asChar());
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = M3dView::applicationShell();
ofn.lpstrFilter = "RAGE Shader Material (*.mtlgeo)\0*.mtlgeo;\0";
ofn.lpstrInitialDir = GetPathToLastLoadedMtlFile();
ofn.nMaxFile = sizeof(mtlFileName);
ofn.lpstrFile = mtlFileName;
ofn.Flags = OFN_OVERWRITEPROMPT;
if (ValidateAndGetRageMaterial())
{
MString strTemplateFileName = ValidateAndGetRageMaterial()->GetTemplateFileName();
MString strTrueTemplateName = MString(fiAssetManager::FileName(strTemplateFileName.asChar()));
MString strNodeName = MFnDependencyNode(thisMObject()).name();
char title[BUFFER_SIZE];
sprintf(title, "Save MTL using template %s on node %s", strTrueTemplateName.asChar(), strNodeName.asChar());
ofn.lpstrTitle = title;
}
if (GetSaveFileName(&ofn))
{
// Lets make sure it is the one we want stupid maya problem
for (int i=0; i<StringLength(mtlFileName); i++)
{
if (mtlFileName[i]=='\\')
{
mtlFileName[i] = '/';
}
}
// Make sure the extension is on it
if (!strstr(mtlFileName, ".mtlgeo"))
{
strcat(mtlFileName, ".mtlgeo");
}
m_bMaterialChangedSinceLastSaved = true;
bool retval = saveMaterialAndSetMaterialFilenameAttribute(mtlFileName);
if (retval)
{
//refresh the locking and MTL file name
MGlobal::executeCommandOnIdle("rageShaderMaya_RefreshAEWindow()", g_bDisplayMGlobalExecuteCommands);
}
return retval;
}
else
{
// Uh-oh an error occurred, but what was it?
DWORD ErrorCode = CommDlgExtendedError();
switch(ErrorCode)
{
case FNERR_BUFFERTOOSMALL:
{
// // Displayf("The buffer pointed to by the lpstrFile member of the OPENFILENAME structure is too small for the file name specified by the user. The first two bytes of the lpstrFile buffer contain an integer value specifying the size, in TCHARs, required to receive the full name.");
break;
}
case FNERR_INVALIDFILENAME:
{
// // Displayf("A file name is invalid.");
break;
}
case FNERR_SUBCLASSFAILURE:
{
// // Displayf("An attempt to subclass a list box failed because sufficient memory was not available.");
break;
}
}
}
}
return false;
}
void rageShaderMaya::releaseConnectedMesh(const MObject & obMeshNode, const MString & sMeshNodeName)
{
m_pobUpdateData->ReleaseConnectedMesh(obMeshNode, sMeshNodeName);
}
void rageShaderMaya::NodeAboutToDeleteCallback(MObject& /*node*/, MDGModifier& /*modifier*/, void* thisPtr)
{
rageShaderMaya * pobShader = ((rageShaderMaya *)thisPtr);
pobShader->removeThisNode();
for (unsigned i=0; i<sm_apRSMNodes.size(); i++)
{
if (sm_apRSMNodes[i] == pobShader)
{
sm_apRSMNodes.erase(sm_apRSMNodes.begin() + i);
break;
}
}
}
void rageShaderMaya::MeshConnected(MObject obMeshNode, bool bConnectionMade )
{
MStatus obStatus;
MFnMesh obFnMeshNode(obMeshNode, &obStatus);
if (obFnMeshNode.isLocked() || obFnMeshNode.isFromReferencedFile())
{
return;
}
// A new mesh has been connected, so I need to reset my m_astrUVSetsUsedInGeometeryFunctions
m_astrUVSetsUsedInGeometeryFunctions.clear();
if (bConnectionMade)
{
if (obStatus == MStatus::kSuccess)
{
// Is it an intermediate ("history") mesh?
if(!obFnMeshNode.isIntermediateObject())
{
if (!getThisBoolAttr(aIgnoreCreateUVsOnMeshConnection))
{
CreateUVSets(obMeshNode);
}
if (IsShaderInViewer())
{
AddModelMaterialPair(obFnMeshNode.fullPathName());
}
}
}
else
{
// Badness has happened, obMeshNode hasFn(MFn::kMesh) but it can't be used to create a obFnMeshNode
// This should be impossible
Errorf("%s %d", __FILE__, __LINE__);
Errorf("Badness has happened, obMeshNode hasFn(MFn::kMesh) but it can't be used to create a obFnMeshNode.");
Errorf("This should be impossible.");
// Errorf("This might give you a clue what has happened : %s", srcPlug.name().asChar());
Errorf("%s", obStatus.errorString().asChar());
// Try and see if I can work out what it really is
MFnDependencyNode obFnMeshNodeAsDN(obMeshNode, &obStatus);
if(obStatus == MStatus::kSuccess)
{
Errorf("The node in question is called %s and is of type %s", obFnMeshNodeAsDN.name().asChar(), obFnMeshNodeAsDN.typeName().asChar());
}
}
}
else
{
if (IsShaderInViewer())
{
releaseConnectedMesh(obMeshNode, obFnMeshNode.fullPathName());
}
}
}
void rageShaderMaya::DeleteParamAttributesBeforeSave()
{
if (ValidateAndGetRageMaterial()/* && m_DeletedExistingDataDuringCreation*/)
{
rageShaderMaterialMaya::RemoveFromMayaNode(thisMObject(), *ValidateAndGetRageMaterial());
}
}
void rageShaderMaya::CreateParamAttributesAfterSave()
{
if (/*!m_DeletedExistingDataDuringCreation && */ValidateAndGetRageMaterial())
{
rageShaderMaterialMaya::AddToMayaNode(thisMObject(), *ValidateAndGetRageMaterial(), &m_DeletedExistingDataDuringCreation);
// Setup user options
if(UserSettings::ExpandTexturesOnFileLoad() && !getThisBoolAttr(aTextureOverride))
{
rageShaderMaterialMaya::ExpandTextureNodes(thisMObject(), *ValidateAndGetRageMaterial());
}
}
}
void rageShaderMaya::NodeAttribDirtyCallback( MObject & node, MPlug & plug, void* clientData)
{
//char acNodeName[BUFFER_SIZE];
//strcpy(acNodeName, MFnDependencyNode(node).name().asChar());
//char acPlugName[BUFFER_SIZE];
//strcpy(acPlugName, plug.name().asChar());
//Displayf("Plug: %s Node: %s", acPlugName, acNodeName);
MFnDependencyNode obFnDagNode(node);
if (!obFnDagNode.isFromReferencedFile() && !obFnDagNode.isLocked())
{
char acPlugName[BUFFER_SIZE];
strcpy(acPlugName, plug.name().asChar());
char* subString = strstr(acPlugName, ".");
if (strlen((subString+1))) //if we have chars after the "."
{
rageShaderMaya * pobShader = ((rageShaderMaya *)clientData);
pobShader->handleDirtyAttribute((subString+1));
}
}
}
void rageShaderMaya::connectionCallback(MPlug & srcPlug, MPlug & destPlug, bool bConnectionMade, void * thisPtr)
{
rageShaderMaya * pobShader = ((rageShaderMaya *)thisPtr);
// If I am loading, then bail
if(pobShader->skipSetInternalValueInContext()) return;
MFnDependencyNode obFnDagNode(pobShader->thisMObject());
if (obFnDagNode.isFromReferencedFile() || obFnDagNode.isLocked())
{
return;
}
//char acNodeName[BUFFER_SIZE];
//strcpy(acNodeName, srcPlug.name().asChar());
//char acPlugName[BUFFER_SIZE];
//strcpy(acPlugName, destPlug.name().asChar());
//char name[BUFFER_SIZE];
//strcpy(name, MFnDependencyNode(pobShader->thisMObject()).name().asChar());
//Displayf("Source: %s Dest: %s Name: %s", acNodeName, acPlugName, name);
// Is the destination plug my shader engine?
if (pobShader->GetShaderEngineNode() == destPlug.node())
{
// Do I have a valid material, if not, I just as well bail now
rageShaderMaterial* pobMaterial = pobShader->ValidateAndGetRageMaterial();
if(pobMaterial == NULL)
{
// No valid material, so bail
return;
}
// Something has been connected to my shader engine, is it a mesh?
MStatus obStatus;
MObject obMeshNode = srcPlug.node(&obStatus);
if (obStatus == MStatus::kSuccess && obMeshNode.hasFn(MFn::kMesh))
{
pobShader->MeshConnected(obMeshNode, bConnectionMade );
}
}
else
{
/* DOES NO WORK SO TAKING OUT....
char destString[BUFFER_SIZE];
strcpy(destString, destPlug.name().asChar());
//if the broken connection is affecting an attribute of my node then the RSM node has changed
if (!bConnectionMade && //the connection is being broken
strstr(destString, ".")) //it is an attribute
{
char name[BUFFER_SIZE];
strcpy(name, MFnDependencyNode(pobShader->thisMObject()).name().asChar());
strcat(name, ".");
if (strstr(destPlug.name().asChar(), name)) //it is an attrib of mine
{
char* subString = strstr(destString, ".");
if (strlen((subString+1))) //if we have chars after the "."
{
//pobShader->breakConnectionToAttrib((subString+1));
}
}
}
*/
}
}
void rageShaderMaya::SaveMaterialFile()
{
// Do I even have a material to save?
if (ValidateAndGetRageMaterial())
{
if(GetMaterialPathAndFilename().length() == 0)
{
BrowseForMaterialFileAndSaveToIt();
}
else
{
saveMaterialAndSetMaterialFilenameAttribute(GetMaterialPathAndFilename());
}
}
}
void rageShaderMaya::removeThisNode()
{
// I never setup a material, then don't bother trying to clean it up
if(GetRageMaterial() && !UserSettings::SilentRunning())
{
// Check to see if we should prompt to save the material
if(m_bMaterialChangedSinceLastSaved && (!getThisBoolAttr(aTextureOverride)))
{
MString strMaterialPathAndFilename = GetMaterialPathAndFilename();
// Get the mtl file name
bool isReadOnly = false;
MString result = "No";
if (strMaterialPathAndFilename.length() == 0)
{
MString strTemplateFileName = ValidateAndGetRageMaterial()->GetTemplate()->GetTemplatePathAndFilename();
result = " the unsaved material using the " + MString(fiAssetManager::FileName(strTemplateFileName.asChar())) + " template";
}
else
{
result = strMaterialPathAndFilename + "\\nthe unsaved RAGE material";
// Does the file already exist?
int eFileAttributes = GetFileAttributes(strMaterialPathAndFilename.asChar());
if (eFileAttributes != INVALID_FILE_ATTRIBUTES)
{
// File already exists, is the file readonly?
if(eFileAttributes & FILE_ATTRIBUTE_READONLY)
{
isReadOnly = true;
}
}
}
if(!isReadOnly)
{
char command[BUFFER_SIZE];
formatf(command, sizeof(command), "confirmDialog -title \"Unsaved RAGE Material\" -message \"Do you wish to save %s on node %s?\" -button \"Yes\" -button \"No\" -defaultButton \"Yes\" -cancelButton \"No\" -dismissString \"No\";", result.asChar(), name().asChar());
CHECK_STATUS (MGlobal::executeCommand(command, result, g_bDisplayMGlobalExecuteCommands));
}
if (result=="Yes")
{
char mtlFileName[256];
OPENFILENAME ofn;
memset(&ofn, 0, sizeof(ofn));
memset(mtlFileName, 0, sizeof(mtlFileName));
if (strMaterialPathAndFilename.length() == 0)
{
BrowseForMaterialFileAndSaveToIt();
}
else
{
saveMaterialAndSetMaterialFilenameAttribute(strMaterialPathAndFilename);
}
}
}
// Clean up callbacks
MMessage::removeCallback(m_ConnectionCallbackId);
MMessage::removeCallback(m_NodeAboutToDeleteCallbackId);
MMessage::removeCallback(m_AttribChange);
}
rageShaderUpdateManager::ReleaseUpdateData(m_pobUpdateData);
m_pobUpdateData = NULL;
delete m_pobRageMaterial;
m_pobRageMaterial = NULL;
// // Displayf("%s %s %d m_TextureCoordSetNames.clear();", MFnDependencyNode(thisMObject()).name().asChar(), __FILE__, __LINE__);
}
bool rageShaderMaya::IsShaderInViewer() const
{
return m_pobUpdateData && m_pobUpdateData->IsShaderInViewer();
}
bool rageShaderMaya::skipSetInternalValueInContext() const
{
return (isLocked() || MFileIO::isReadingFile() || m_bSkipSetInternalValueInContext);
}
void rageShaderMaya::skipSetInternalValueInContext(bool bSkip)
{
m_bSkipSetInternalValueInContext = bSkip;
}
void rageShaderMaya::addToViewer()
{
if(!ValidateAndGetRageMaterial())
{
// No point adding me to the viewer, I have no materials!
return;
}
// Set user option
rageShaderViewer::GetInstance()->SetAcceptInput(UserSettings::ViewerAcceptInput());
rageShaderViewer::GetInstance()->SetAlwaysOnTop(UserSettings::ViewerAlwaysOnTop());
// I have a valid material, so add me
static int iNoOfAddToViewerCalls = 0;
iNoOfAddToViewerCalls++;
// DEBUG_LOG_Start "%s %d Entered rageShaderMaya::addToViewer() %d\n", __FILE__, __LINE__, iNoOfAddToViewerCalls DEBUG_LOG_End;
MFnDependencyNode obFnShadingEngineNode(GetShaderEngineNode());
MStatus obStatus;
MPlugArray plugs;
obFnShadingEngineNode.getConnections(plugs);
for (u32 k=0; k<plugs.length(); k++)
{
// DEBUG_LOG_Start "%s %d %s %d/%d\n", __FILE__, __LINE__, plugs[k].name().asChar(), k, plugs.length() DEBUG_LOG_End;
MPlugArray otherPlugs;
plugs[k].connectedTo(otherPlugs, true, false);
for (u32 l=0; l<otherPlugs.length(); l++)
{
// DEBUG_LOG_Start "%s %d %s %d/%d\n", __FILE__, __LINE__, otherPlugs[l].name().asChar(), l, otherPlugs.length() DEBUG_LOG_End;
if (otherPlugs[l].node().hasFn(MFn::kMesh))
{
// DEBUG_LOG_Start "%s %d Found a mesh %s\n", __FILE__, __LINE__, otherPlugs[l].name().asChar() DEBUG_LOG_End;
// Found a mesh obFnNode, so render it, maybe
MObject obMeshNode(otherPlugs[l].node());
MFnMesh obFnMeshNode(obMeshNode, &obStatus);
if (obStatus == MStatus::kSuccess)
{
// Is it an intermediate ("history") mesh?
if(!obFnMeshNode.isIntermediateObject())
{
// Not history, so render it!
// DEBUG_LOG_Start "%s %d About to do something to it %s\n", __FILE__, __LINE__, otherPlugs[l].name().asChar() DEBUG_LOG_End;
AddModelMaterialPair(obFnMeshNode.fullPathName());
}
}
// DEBUG_LOG_Start "%s %d Made a mesh %s\n", __FILE__, __LINE__, otherPlugs[l].name().asChar() DEBUG_LOG_End;
}
}
}
// DEBUG_LOG_Start "%s %d Leaving rageShaderMaya::addToViewer() %d\n", __FILE__, __LINE__, iNoOfAddToViewerCalls DEBUG_LOG_End;
}
void rageShaderMaya::AddModelMaterialPair(const MString & sMeshNodeName)
{
m_pobUpdateData->AddModelMaterialPair(sMeshNodeName);
}
void rageShaderMaya::removeFromViewer()
{
MFnDependencyNode obFnShadingEngineNode(GetShaderEngineNode());
MStatus obStatus;
MPlugArray plugs;
obFnShadingEngineNode.getConnections(plugs);
for (u32 k=0; k<plugs.length(); k++)
{
MPlugArray otherPlugs;
plugs[k].connectedTo(otherPlugs, true, false);
for (u32 l=0; l<otherPlugs.length(); l++)
{
if (otherPlugs[l].node().hasFn(MFn::kMesh))
{
MObject obMeshNode(otherPlugs[l].node());
MFnMesh obFnMeshNode(obMeshNode, &obStatus);
if (obStatus == MStatus::kSuccess)
{
if(!obFnMeshNode.isIntermediateObject())
{
DeleteModelMaterialPair(obFnMeshNode.fullPathName());
}
}
}
}
}
}
void rageShaderMaya::DeleteModelMaterialPair(const MString & sMeshNodeName)
{
m_pobUpdateData->DeleteModelMaterialPair(sMeshNodeName);
}
void rageShaderMaya::setThisStringAttr(const char * attrName, const char * value)
{
// // Displayf("Setting string attribute \"%s\" on \"%s\" to \"%s\"", attrName, name().asChar(), value);
MFnDependencyNode node(thisMObject());
MPlug plug = node.findPlug(attrName);
if (!plug.isNull())
{
MStatus obStatus = plug.setValue(value);
if(obStatus != MS::kSuccess)
{
Errorf("Unable to set attribute %s on %s to \"%s\" as an error occurred : %s", attrName, name().asChar(), value, obStatus.errorString().asChar());
}
}
else
{
Errorf("Unable to set attribute %s on %s to \"%s\" as attribute does not exist", attrName, name().asChar(), value);
}
}
void rageShaderMaya::setThisIntAttr(const char * attrName, const int value)
{
MFnDependencyNode node(thisMObject());
MPlug plug = node.findPlug(attrName);
if (!plug.isNull())
{
plug.setValue(value);
}
}
void rageShaderMaya::setThisBoolAttr(const char * attrName, const bool value)
{
MFnDependencyNode node(thisMObject());
MPlug plug = node.findPlug(attrName);
if (!plug.isNull())
{
plug.setValue(value);
}
}
bool rageShaderMaya::getThisBoolAttr(const MObject & bObject) const
{
bool value = false;
MFnDependencyNode node(thisMObject());
MPlug plug = node.findPlug(bObject);
if (!plug.isNull())
{
plug.getValue(value);
}
return value;
}
void rageShaderMaya::getThisStringAttr(const char * attrName, MString & value) const
{
MFnDependencyNode node(thisMObject());
MPlug plug = node.findPlug(attrName);
if (!plug.isNull())
{
plug.getValue(value);
}
else
{
Errorf("Unable to get attribute %s on %s as attribute does not exist", attrName, name().asChar());
}
// // Displayf("Got string attribute \"%s\" on \"%s\" as \"%s\"", attrName, name().asChar(), value);
}
void rageShaderMaya::getThisIntAttr(const char * attrName, int & value)
{
MFnDependencyNode node(thisMObject());
MPlug plug = node.findPlug(attrName);
if (!plug.isNull())
{
plug.getValue(value);
}
}
void rageShaderMaya::getThisBoolAttr(const char * attrName, bool & value)
{
MFnDependencyNode node(thisMObject());
MPlug plug = node.findPlug(attrName);
if (!plug.isNull())
{
plug.getValue(value);
}
}
void rageShaderMaya::SetTextureToDisplayInMaya(const MString & strTextureToDisplayInMaya)
{
m_pCurrentTextureParam = NULL;
m_pCurrentTexture = NULL; // Reset the texture to force a clean load
m_strCurrentTextureOverrideFilename = "";
if(strTextureToDisplayInMaya == "Maya Default Color")
{
// Use the first texture I find for UVs
// so just bail
return;
}
// Work out which texture to use
Assertf(ValidateAndGetRageMaterial(), "Trying to the number of parameters of an uninitialized Material on Maya node %s", MFnDependencyNode(thisMObject()).name().asChar());
for (int i=0; i<ValidateAndGetRageMaterial()->GetParamCount(); i++)
{
shaderMaterialGeoParamValue * p = ValidateAndGetRageMaterial()->GetParam(i);
if (MString(p->GetParamDescription()->GetUIName()) == strTextureToDisplayInMaya)
{
// Bingo!
m_pCurrentTextureParam = (shaderMaterialGeoParamValueTexture *)p;
break;
}
}
if (getThisBoolAttr(aTextureOverride) && m_pCurrentTextureParam)
{
MFnDependencyNode obFnThis(thisMObject());
MPlug obInTexturePlug = obFnThis.findPlug(rageShaderMaterialMayaParam::GetCleanVersionOfString(m_pCurrentTextureParam->GetParamDescription()->GetUIName()));
if (!obInTexturePlug.isNull())
{
// Get the file node on the other end of the plug
if(obInTexturePlug.isConnected())
{
// It is connected, so get the other end of the connection
MStatus obStatus;
MPlugArray aobPlugsConnectedToParam;
obInTexturePlug.connectedTo(aobPlugsConnectedToParam, true, true, &obStatus);
CHECK_STATUS( obStatus )
if(aobPlugsConnectedToParam.length() > 0)
{
// Update the parameter to match the connected pieces
MFnDependencyNode obFnFileNode(aobPlugsConnectedToParam[0].node());
MPlug filenamePlug = obFnFileNode.findPlug("fileTextureName");
filenamePlug.getValue(m_strCurrentTextureOverrideFilename);
}
}
}
}
}
bool rageShaderMaya::ParametersAttributeValueChanged(const MPlug &obPlugBeingDirtied, const MDataHandle & obDataHandle)
{
Assertf(ValidateAndGetRageMaterial(), "Trying to update a parameter value an uninitialized Material on Maya node %s", MFnDependencyNode(thisMObject()).name().asChar());
// Lets extract the name of the parameter without the shader node
MString strPlugName = obPlugBeingDirtied.partialName(false, false, false, false, true, true);
// There is a rather troublesome problem here, as if you delete a rageShaderMaya node, and then undo the deletion, the first I get to know about
// it is when I come in here. Only m_pRageMaterial is no longer valid so bad things happen.
// So......
shaderMaterialGeoParamValue * param = ValidateAndGetRageMaterial()->GetParamByUIName(strPlugName.asChar());
if (!param)
{
//check for vector types which have added (xyzw) chars appended to the name
atString temp(strPlugName.asChar());
temp.Truncate(temp.length() - 1);
param = ValidateAndGetRageMaterial()->GetParamByUIName(temp.c_str());
if (!param)
{
return false;
}
}
// Set the new value
switch (param->GetType())
{
case grcEffect::VT_STRING:
{
MString value;
MObject obj = obPlugBeingDirtied.attribute();
if (obj.hasFn(MFn::kEnumAttribute))
{
MFnEnumAttribute attr(obj);
value = attr.fieldName((u8)obDataHandle.asInt());
}
else
{
value = obDataHandle.asString();
}
if (param->Update(value.asChar()))
{
// Make sure I know to save the file
// Displayf("Material will need saving because parameter %s has changed", strPlugName.asChar());
m_bMaterialChangedSinceLastSaved = true;
// Update shader in viewer, if needed
if(IsShaderInViewer())
{
m_pobUpdateData->UpdateShader();
}
}
break;
}
/* case grcEffect::VT_BOOL:
{
if (param->Update(obDataHandle.asBool()))
{
// Make sure I know to save the file
// Displayf("Material will need saving because parameter %s has changed", strPlugName.asChar());
m_bMaterialChangedSinceLastSaved = true;
// Update shader in viewer, if needed
if(IsShaderInViewer())
{
m_pobUpdateData->UpdateShader();
}
}
break;
}
case grcEffect::VT_INT:
{
int value = obDataHandle.asInt();
MObject obj = obPlugBeingDirtied.attribute();
if (obj.hasFn(MFn::kEnumAttribute))
{
value = (u8)obDataHandle.asInt();
}
if (param->Update(value))
{
// Make sure I know to save the file
// Displayf("Material will need saving because parameter %s has changed", strPlugName.asChar());
m_bMaterialChangedSinceLastSaved = true;
// Update shader in viewer, if needed
if(IsShaderInViewer())
{
m_pobUpdateData->UpdateShader();
}
}
break;
} */
case grcEffect::VT_FLOAT:
{
if (param->Update(obDataHandle.asFloat()))
{
// Make sure I know to save the file
// Displayf("Material will need saving because parameter %s has changed", strPlugName.asChar());
m_bMaterialChangedSinceLastSaved = true;
// Update shader in viewer, if needed
if(IsShaderInViewer())
{
m_pobUpdateData->UpdateShader();
}
}
break;
}
case grcEffect::VT_VECTOR2:
case grcEffect::VT_MATRIX34:
case grcEffect::VT_MATRIX44:
{
if (param->Update(strPlugName.asChar(), obDataHandle.asFloat()))
{
// Make sure I know to save the file
// Displayf("Material will need saving because parameter %s has changed", strPlugName.asChar());
m_bMaterialChangedSinceLastSaved = true;
// Update shader in viewer, if needed
if(IsShaderInViewer())
{
m_pobUpdateData->UpdateShader();
}
}
break;
}
case grcEffect::VT_VECTOR3:
case grcEffect::VT_VECTOR4:
{
if (param->Update(strPlugName.asChar(), obDataHandle.asFloat3()[0], obDataHandle.asFloat3()[1], obDataHandle.asFloat3()[2]))
{
// Make sure I know to save the file
// Displayf("Material will need saving because parameter %s has changed", strPlugName.asChar());
m_bMaterialChangedSinceLastSaved = true;
// Update shader in viewer, if needed
if(IsShaderInViewer())
{
m_pobUpdateData->UpdateShader();
}
}
break;
}
case grcEffect::VT_TEXTURE:
{
MPlugArray plugArray;
obPlugBeingDirtied.connectedTo(plugArray, true, false);
//for(unsigned p=0; p<plugArray.length(); p++)
//{
// const char* pcPlugName = plugArray[p].name().asChar();
// const char* pcNodeTypeName = plugArray[p].node().apiTypeStr();
// // Displayf("%s is connected to %s %s", obPlugBeingDirtied.name().asChar(), pcPlugName, pcNodeTypeName);
//}
MString value = "none";
if (plugArray.length() == 1)
{
if ((plugArray[0].node().apiType() == MFn::kFileTexture) || (plugArray[0].node().apiType() == MFn::kPsdFileTexture))
{
MFnDependencyNode obFnFileNode(plugArray[0].node());
MPlug filenamePlug = obFnFileNode.findPlug("fileTextureName");
filenamePlug.getValue(value);
//////////////////////////////////////////////////////////////////////////
MString translator = "";
const char* str = value.asChar();
char helper[2];
helper[1] = '\0';
// Lets make sure it is the one we want stupid maya problem
for (unsigned int i=0; i<value.length(); i++)
{
if (str[i]=='\\')
{
helper[0] = '/';
}
else
{
helper[0] = str[i];
}
translator += helper;
}
value = translator;
//////////////////////////////////////////////////////////////////////////
}
if(param->Update(value.asChar()))
{
// Make sure I know to save the file
// Displayf("Material will need saving because parameter %s has changed", strPlugName.asChar());
bool bUseExistingTextureNodes = getThisBoolAttr(aTextureOverride);
if(!bUseExistingTextureNodes)
{
// If texture override was on, then I'd ignore the change, but it isn't
// so take note so I remember to save the material later
m_bMaterialChangedSinceLastSaved = true;
}
// Update shader in viewer, if needed
if(IsShaderInViewer())
{
m_pobUpdateData->UpdateShader();
}
}
// Kick the Attribute editor, if it is open
//MGlobal::executeCommandOnIdle("rageShaderMaya_RefreshAEWindow()", g_bDisplayMGlobalExecuteCommands);
}
break;
}
default:
Assert(0 && "Invalid param type");
}
//an attribute has changed so we need to call our attribute watch script command
if (!rageShaderMaya::getIgnoreReferencedNodesDuringWireUpTextures())
{
CallAttributeWatchScriptFunction(this->name(), strPlugName);
}
return false;
}
void rageShaderMaya::CallAttributeWatchScriptFunction(const MString& nodeName, const MString& attribute)
{
// this is used for linking the default maya color to attributes of the RSM
// and could be used for other things as desired, but is only project specific
// at the moment.
static atString melAttributeWatch("");
static int checked = false;
if (!checked)
{
//initModuleSettings::GetModuleSetting(("MTLAttributeWatchScriptFunction"), melAttributeWatch);
checked = true;
}
//build the MEL command
if (melAttributeWatch != "")
{
MString command;
command = MString(melAttributeWatch.c_str()) +
"(\"" +
nodeName +
"\", \"" +
attribute +
"\");";
//Displayf("%s", command.asChar());
MGlobal::executeCommandOnIdle(command);
}
}
// Function to validate the material member pointer
rageShaderMaterial* rageShaderMaya::ValidateAndGetRageMaterial()
{
// Quick out
if (m_pobRageMaterial)
{
return m_pobRageMaterial;
}
// Get the current mtl file name
MString strMaterialPathAndFilename = GetMaterialPathAndFilename();
// Load it
if (strMaterialPathAndFilename.length() != 0)
{
loadFromMTLFile(strMaterialPathAndFilename);
}
// Another callback for when it is about to die
MObject obNode = thisMObject();
MFnDependencyNode obFnThis(obNode);
m_NodeAboutToDeleteCallbackId = MNodeMessage::addNodeAboutToDeleteCallback(obNode, NodeAboutToDeleteCallback, this );
// Create the call back for when this object has something connected to it.
m_ConnectionCallbackId = MDGMessage::addConnectionCallback (&rageShaderMaya::connectionCallback, this);
m_AttribChange = MNodeMessage::addNodeDirtyCallback(obNode, &rageShaderMaya::NodeAttribDirtyCallback, this);
return m_pobRageMaterial;
}
const rageShaderMaterial* rageShaderMaya::GetRageMaterial() const
{
return m_pobRageMaterial;
}
void rageShaderMaya::SetPathToLastLoadedMtlFile(const char* pcPathToLastLoadedMtlFile)
{
// Make sure all the slashes are \\ and not /
m_strPathToLastLoadedMtlFile = "";
const char* pcPosOfSlash = strrchr(pcPathToLastLoadedMtlFile, '/');
if(pcPosOfSlash == NULL)
{
pcPosOfSlash = strrchr(pcPathToLastLoadedMtlFile, '\\');
}
// Replace any bad chars with "_"
unsigned iStrLen = strlen(pcPathToLastLoadedMtlFile);
for(unsigned i=0; i<iStrLen; i++)
{
char c = pcPathToLastLoadedMtlFile[i];
if(c == '/')
{
// Bad character, so replace with an better slash
m_strPathToLastLoadedMtlFile += "\\";
}
else
{
// The character is valid, so do nothing
m_strPathToLastLoadedMtlFile += MString(&c, 1);
}
if (pcPosOfSlash == &(pcPathToLastLoadedMtlFile[i]))
{
break;
}
}
}
void rageShaderMaya::SetPathToLastLoadedTemplateFile(const char* pcPathToLastLoadedTemplateFile)
{
// Make sure all the slashes are \\ and not /
m_strPathToLastLoadedTemplateFile = "";
const char* pcPosOfSlash = strrchr(pcPathToLastLoadedTemplateFile, '/');
if(pcPosOfSlash == NULL)
{
pcPosOfSlash = strrchr(pcPathToLastLoadedTemplateFile, '\\');
}
// Replace any bad chars with "_"
unsigned iStrLen = strlen(pcPathToLastLoadedTemplateFile);
for(unsigned i=0; i<iStrLen; i++)
{
char c = pcPathToLastLoadedTemplateFile[i];
if(c == '/')
{
// Bad character, so replace with an better slash
m_strPathToLastLoadedTemplateFile += "\\";
}
else
{
// The character is valid, so do nothing
m_strPathToLastLoadedTemplateFile += MString(&c, 1);
}
if (pcPosOfSlash == &(pcPathToLastLoadedTemplateFile[i]))
{
break;
}
}
}
const char* rageShaderMaya::GetPathToLastLoadedTemplateFile()
{
if (!m_strPathToLastLoadedTemplateFile.length())
{
MString temp = SHADER_MATERIAL_GEO_MANAGER.GetPathToTemplates();
const char* tempStr = temp.asChar();
unsigned iStrLen = strlen(tempStr);
for(unsigned i=0; i<iStrLen; i++)
{
char c = tempStr[i];
if(c == '/')
{
// Bad character, so replace with an better slash
m_strPathToLastLoadedTemplateFile += "\\";
}
else
{
// The character is valid, so do nothing
m_strPathToLastLoadedTemplateFile += MString(&c, 1);
}
}
}
return m_strPathToLastLoadedTemplateFile.asChar();
}
void rageShaderMaya::SetPathToLastLoadedTypeFile(const char* pcPathToLastLoadedTypeFile)
{
// Make sure all the slashes are \\ and not /
m_strPathToLastLoadedTypeFile = "";
const char* pcPosOfSlash = strrchr(pcPathToLastLoadedTypeFile, '/');
if(pcPosOfSlash == NULL)
{
pcPosOfSlash = strrchr(pcPathToLastLoadedTypeFile, '\\');
}
// Replace any bad chars with "_"
unsigned iStrLen = strlen(pcPathToLastLoadedTypeFile);
for(unsigned i=0; i<iStrLen; i++)
{
char c = pcPathToLastLoadedTypeFile[i];
if(c == '/')
{
// Bad character, so replace with an better slash
m_strPathToLastLoadedTypeFile += "\\";
}
else
{
// The character is valid, so do nothing
m_strPathToLastLoadedTypeFile += MString(&c, 1);
}
if (pcPosOfSlash == &(pcPathToLastLoadedTypeFile[i]))
{
break;
}
}
}
const char* rageShaderMaya::GetPathToLastLoadedTypeFile()
{
if (!m_strPathToLastLoadedTypeFile.length())
{
MString temp = SHADER_MATERIAL_GEO_MANAGER.GetPathToTypes();
const char* tempStr = temp.asChar();
unsigned iStrLen = strlen(tempStr);
for(unsigned i=0; i<iStrLen; i++)
{
char c = tempStr[i];
if(c == '/')
{
// Bad character, so replace with an better slash
m_strPathToLastLoadedTypeFile += "\\";
}
else
{
// The character is valid, so do nothing
m_strPathToLastLoadedTypeFile += MString(&c, 1);
}
}
}
return m_strPathToLastLoadedTypeFile.asChar();
}
void rageShaderMaya::CreateUVSets(MObject obMeshNode)
{
// Check to make sure that this mesh has the appropriate uvsets created.
MStatus obStatus;
MStringArray aUvSetNames;
MFnMesh meshNode(obMeshNode, &obStatus);
if((obStatus == MStatus::kSuccess) && (!meshNode.isLocked()) && (!meshNode.isFromReferencedFile()))
{
// If no polys then have to skip
if(meshNode.numPolygons() != 0)
{
// Valid mesh, so work with it
meshNode.getUVSetNames(aUvSetNames);
MStringArray astrTextureCoordSetNames;
getTexCoordSetNamesThatThisMaterialNeeds(astrTextureCoordSetNames);
bool bAutoCreateAllNew = false;
// If we don't have any uv sets then we must be applying a MTL for the first time.
// Dont want to prompt for renaming as everything should be new
if (!aUvSetNames.length()) {
bAutoCreateAllNew = true;
}
MStringArray aCulledUvSetNames;
//Cull down the list of names to only the ones that are unassigned
bool bAutoCreateUnFoundNew = false;
if (!bAutoCreateAllNew)
{
GetUnusedUVSetNames(astrTextureCoordSetNames, aUvSetNames, aCulledUvSetNames);
// Dont want to prompt for renaming as nothing can be renamed
if (!aCulledUvSetNames.length())
{
bAutoCreateUnFoundNew = true;
}
}
//Dont prompt if we are in silent mode
if (UserSettings::SilentRunning())
{
bAutoCreateUnFoundNew = true;
}
for (u32 i=0; i<astrTextureCoordSetNames.length(); i++)
{
bool bCreateNew = false;
if (!bAutoCreateAllNew)
{
//does the uv set already exist
bool bFoundUvSetName = StringArrayHasString(astrTextureCoordSetNames[i], aUvSetNames);
//UV set not found
if (!bFoundUvSetName && !bAutoCreateUnFoundNew)
{
//Build array string
MString arrayString = "{";
for (u32 unusedIndex=0; unusedIndex<aCulledUvSetNames.length(); ++unusedIndex )
{
arrayString += "\"" + aCulledUvSetNames[unusedIndex] + "\"";
if (unusedIndex+1 != aCulledUvSetNames.length())
{
arrayString += ", ";
}
}
arrayString += "}";
MString templateFilename = "";
GetTemplateFileName(templateFilename);
//build the MEL command
MString command;
command = "rageUVUtilities.PromptForUVsetNaming(\"" +
meshNode.fullPathName() +
"\", \"" +
astrTextureCoordSetNames[i] +
"\", \"" +
templateFilename +
"\", " +
arrayString +
");";
MString result = "";
bool bContinue = true;
do
{
//do our prompting
MGlobal::executeCommand(command, result);
if (result != "")
{
bContinue = false;
MString renameUVSetCommand;
renameUVSetCommand = "polyUVSet -rename -uvSet \"" + result + "\" -newUVSet \"" + astrTextureCoordSetNames[i] + "\" " + meshNode.fullPathName() + ";";
MGlobal::executeCommandOnIdle(renameUVSetCommand);
//find the index
int foundIndex = -1;
for (u32 mtluv=0; mtluv<aCulledUvSetNames.length(); mtluv++)
{
if (aCulledUvSetNames[mtluv] == result)
{
foundIndex = mtluv;
break;
}
}
//remove the string from the list of unused
if (foundIndex != -1)
{
aCulledUvSetNames.remove(foundIndex);
}
}
else
{
bCreateNew = true;
bContinue = false;
}
} while(bContinue);
}
else if (!bFoundUvSetName && bAutoCreateUnFoundNew)
{
bCreateNew = true;
}
}
else
{
bCreateNew = true;
}
if (bCreateNew)
{
//Make a new UVset
MString command;
command = "polyUVSet -copy -uvSet \"map1\" -nuv \"" + astrTextureCoordSetNames[i] + "\" " + meshNode.fullPathName() + ";";
MGlobal::executeCommandOnIdle(command);
}
}
}
}
}
void rageShaderMaya::GetUnusedUVSetNames (const MStringArray &usedTextureCoordSetNames, const MStringArray &aObjectUvSetNames, MStringArray &out_CulledUvSetNames)
{
for (u32 objectUvSet=0; objectUvSet < aObjectUvSetNames.length(); objectUvSet++)
{
//dont delete map1 it is the default UVSet and Maya does not like if it is deleted
if (aObjectUvSetNames[objectUvSet] != "map1")
{
//is the uv set used by the shader
bool bUvSetUsed = StringArrayHasString(aObjectUvSetNames[objectUvSet], usedTextureCoordSetNames);
//UV set not used
if (!bUvSetUsed)
{
out_CulledUvSetNames.append(aObjectUvSetNames[objectUvSet]);
}
}
}
}
void rageShaderMaya::GetTemplateFileName (MString &out_TemplateFilename)
{
MString templateFilenameWithPath = GetGeoTemplatePathAndFileName();
out_TemplateFilename = templateFilenameWithPath;
if (templateFilenameWithPath.length())
{
//find the last "\"
int subStart = templateFilenameWithPath.rindex('\\');
if (subStart == -1)
{
//um ... maybe it is "/"
subStart = templateFilenameWithPath.rindex('/');
}
if (subStart != -1)
{
out_TemplateFilename = templateFilenameWithPath.substring(subStart, templateFilenameWithPath.length()-1);
}
}
}
bool rageShaderMaya::StringArrayHasString (const MString &strFindString, const MStringArray &aStrings)
{
bool bReturnValue = false;
for (u32 stringIndex=0; stringIndex < aStrings.length(); stringIndex++)
{
if (strFindString == aStrings[stringIndex])
{
bReturnValue = true;
break;
}
}
return bReturnValue;
}
void rageShaderMaya::DeleteUVSetFromNode (const MString &strUVSetName, const MString& strMeshNodeName)
{
//dont delete map1 it is the default UVSet and Maya does not like if it is deleted
if (strUVSetName != "map1")
{
MString command;
command = "polyUVSet -delete -uvSet \"" + strUVSetName + "\" " + strMeshNodeName + ";";
MGlobal::executeCommandOnIdle(command);
command = "print \"Deleting unused UVSet: " + strUVSetName + " from node: " + strMeshNodeName + "\\n\"";
MGlobal::executeCommandOnIdle(command);
}
}
rageShaderMaya* rageShaderMaya::GetRageShaderMayaNodeGivenNodeName(const char* pcNodeName)
{
MString strNodeName(pcNodeName);
for (unsigned i=0; i<sm_apRSMNodes.size(); i++)
{
if(sm_apRSMNodes[i]->name() == strNodeName)
{
return sm_apRSMNodes[i];
}
}
return NULL;
}
MObject rageShaderMaya::GetShaderEngineNode() const
{
MStatus obStatus = MStatus::kSuccess;
MObject obThisNode = thisMObject();
MItDependencyGraph it(obThisNode,
MFn::kShadingEngine,
MItDependencyGraph::kDownstream,
MItDependencyGraph::kBreadthFirst,
MItDependencyGraph::kNodeLevel, &obStatus);
MObject obMyShadingEngine = ((obStatus == MStatus::kSuccess ? it.thisNode() : MObject::kNullObj));
return obMyShadingEngine;
}
MString rageShaderMaya::GetGeoTypePathAndFileName() const
{
if (GetRageMaterial())
{
return GetRageMaterial()->GetParentTypePathAndFilename();
}
return "";
}
MString rageShaderMaya::GetGeoTemplatePathAndFileName() const
{
if (GetRageMaterial())
{
return GetRageMaterial()->GetTemplate()->GetTemplatePathAndFilename();
}
return "";
}
MString rageShaderMaya::getFileToOpen(const char* fileFilter, const char* lastLoadPath) const
{
MString retval = "";
char tempStrBuffer[256];
OPENFILENAME ofn;
memset(&ofn, 0, sizeof(ofn));
memset(tempStrBuffer, 0, sizeof(tempStrBuffer));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = M3dView::applicationShell();
ofn.lpstrFilter = fileFilter;
ofn.lpstrInitialDir = lastLoadPath;
ofn.nMaxFile = sizeof(tempStrBuffer);
ofn.lpstrFile = tempStrBuffer;
if (GetOpenFileName(&ofn))
{
// Lets make sure it is the one we want stupid maya problem
for (int i=0; i<StringLength(tempStrBuffer); i++)
{
if (tempStrBuffer[i]=='\\')
{
tempStrBuffer[i] = '/';
}
}
retval = tempStrBuffer;
}
return retval;
}
MString rageShaderMaya::GetMaterialPathAndFilename() const
{
MString strMaterialFilename;
getThisStringAttr("MtlFilename", strMaterialFilename);
return strMaterialFilename;
}
void rageShaderMaya::SetMaterialPathAndFilename(const MString& strMaterialFilename)
{
setThisStringAttr("MtlFilename", strMaterialFilename.asChar());
}
void rageShaderMaya::RegisterGlobalCallbacks()
{
// Add a callback to initialize the materials when the maya scene is opened
m_GlobalAfterMayaNewCallbackId = MSceneMessage::addCallback(MSceneMessage::kAfterNew, GlobalAfterMayaOpenCallback );
m_GlobalAfterMayaOpenCallbackId = MSceneMessage::addCallback(MSceneMessage::kAfterOpen, GlobalAfterMayaOpenCallback );
m_GlobalAfterMayaImportCallbackId = MSceneMessage::addCallback(MSceneMessage::kAfterImport, GlobalAfterMayaOpenCallback);
m_GlobalAfterMayaReferenceCallbackId = MSceneMessage::addCallback(MSceneMessage::kAfterReference, GlobalAfterMayaOpenCallback);
m_GlobalBeforeMayaNewCallbackId = MSceneMessage::addCallback(MSceneMessage::kBeforeNew, GlobalBeforeMayaOpenCallback );
m_GlobalBeforeMayaOpenCallbackId = MSceneMessage::addCallback(MSceneMessage::kBeforeOpen, GlobalBeforeMayaOpenCallback );
sm_MayaExitingCallback = MSceneMessage::addCallback(MSceneMessage::kMayaExiting , &uninitalizePlugin);
m_GlobalBeforeMayaSaveCallbackId = MSceneMessage::addCallback(MSceneMessage::kBeforeSave, GlobalBeforeMayaSaveCallback );
m_GlobalAfterMayaSaveCallbackId = MSceneMessage::addCallback(MSceneMessage::kAfterSave, GlobalAfterMayaSaveCallback );
}
void rageShaderMaya::UnregisterGlobalCallbacks()
{
// Clean up callbacks
MMessage::removeCallback(m_GlobalAfterMayaNewCallbackId);
MMessage::removeCallback(m_GlobalAfterMayaOpenCallbackId);
MMessage::removeCallback(m_GlobalAfterMayaImportCallbackId);
MMessage::removeCallback(m_GlobalAfterMayaReferenceCallbackId);
MMessage::removeCallback(m_GlobalBeforeMayaNewCallbackId);
MMessage::removeCallback(m_GlobalBeforeMayaOpenCallbackId);
MMessage::removeCallback(m_GlobalBeforeMayaSaveCallbackId);
MMessage::removeCallback(m_GlobalAfterMayaSaveCallbackId);
MMessage::removeCallback(sm_MayaExitingCallback);
}
void rageShaderMaya::GlobalBeforeMayaSaveCallback(void * /*clientData*/)
{
//Delete all parameter attributes
for (unsigned i=0; i<sm_apRSMNodes.size(); i++)
{
Assert(sm_apRSMNodes[i]);
// Force the saving of the material file
sm_apRSMNodes[i]->SaveMaterialFile();
sm_apRSMNodes[i]->DeleteParamAttributesBeforeSave();
}
}
void rageShaderMaya::GlobalAfterMayaSaveCallback(void * /*clientData*/)
{
//Re add all the attributes
for (unsigned i=0; i<sm_apRSMNodes.size(); i++)
{
Assert(sm_apRSMNodes[i]);
// Get the current mtl file name
sm_apRSMNodes[i]->CreateParamAttributesAfterSave();
}
}
void rageShaderMaya::GlobalBeforeMayaOpenCallback(void * /*clientData*/)
{
//Maya breaks the connections to the node when it is attempting to load/create a
// different scene. This triggered the "breakConnectionToAttrib" code causing
// MTLGEOs to be considered as changed when they were not.
rageShaderMaya::m_GlobalIgnoreConnectionBreaks = true;
}
void rageShaderMaya::GlobalAfterMayaOpenCallback(void * /*clientData*/)
{
rageShaderMaya::m_GlobalIgnoreConnectionBreaks = false;
// I need to nuke any loaded textures, to force them to be reloaded
for (unsigned i=0; i<sm_apRSMNodes.size(); i++)
{
// Get the current mtl file name
sm_apRSMNodes[i]->ReleaseTextures();
}
// Make sure all the data that we need destroyed is destroyed
delete sm_pTextureCache;// ->reset();
sm_pTextureCache = new rageShaderTextureCache();
//Displayf("Initializing shader after opening file");
if(!MFileIO::isReadingFile())
{
// Refresh the texture to display in Maya and
// Go through each node to generate a list of missing MTL files
MStringArray astrMissingMtlFiles;
for (unsigned i=0; i<sm_apRSMNodes.size(); i++)
{
//////////////////////////////////////////////////////////////////////////
// Get aTextureToDisplayInMaya plug
MFnDependencyNode obFnShaderNode(sm_apRSMNodes[i]->thisMObject());
MPlug plug = obFnShaderNode.findPlug(aTextureToDisplayInMaya);
if(!plug.isNull())
{
MString strValue;
plug.getValue(strValue);
plug.setValue(strValue);
}
//////////////////////////////////////////////////////////////////////////
// Get the current mtl file name
MString strMaterialPathAndFilename = sm_apRSMNodes[i]->GetMaterialPathAndFilename();
if (strMaterialPathAndFilename.length() != 0)
{
// I have an MTL, so does it exist?
if(!ASSET.Exists(strMaterialPathAndFilename.asChar(), ""))
{
// File is missing!
// Log it to all the output windows I can
Displayf("Mtl File missing : %s used on node %s", strMaterialPathAndFilename.asChar(), sm_apRSMNodes[i]->name().asChar());
MGlobal::displayError("Mtl File missing : "+ strMaterialPathAndFilename +" used on node "+ sm_apRSMNodes[i]->name());
// Have I already logged it?
bool bAlreadyLogged = false;
for(unsigned j=0; j<astrMissingMtlFiles.length(); j++)
{
if(astrMissingMtlFiles[j] == strMaterialPathAndFilename)
{
// Already logged
bAlreadyLogged = true;
break;
}
}
if(!bAlreadyLogged)
{
astrMissingMtlFiles.append(strMaterialPathAndFilename);
}
}
}
}
// Display summary
if(astrMissingMtlFiles.length() > 0)
{
// Missing MTLs
MString strErrorMessage = "rageUserError(\"The following MTL files are missing:\\\\n";
for(unsigned j=0; j<astrMissingMtlFiles.length(); j++)
{
strErrorMessage += astrMissingMtlFiles[j];
strErrorMessage += "\\\\n";
}
strErrorMessage += "\")";
MGlobal::executeCommand(strErrorMessage, g_bDisplayMGlobalExecuteCommands);
}
}
}
MStringArray rageShaderMaya::GetParamNames(shaderMaterialGeoParamDescription::ValueSource _SourceFlags) const
{
MStringArray obAStrReturnMe;
const rageShaderMaterial* pobRageMaterial = GetRageMaterial();
if(pobRageMaterial)
{
for (int i=0; i<pobRageMaterial->GetParamCount(); i++)
{
const shaderMaterialGeoParamValue * pobParam = pobRageMaterial->GetParam(i);
if(pobParam->GetSourceOfParamValue() & _SourceFlags)
{
obAStrReturnMe.append(pobParam->GetParamDescription()->GetUIName());
}
}
}
return obAStrReturnMe;
}
MStringArray rageShaderMaya::GetRequiredVertexColorSetNames() const
{
MStringArray obAStrReturnMe;
if (GetRageMaterial())
{
const shaderMaterialGeoTemplate* pTemplate = GetRageMaterial()->GetTemplate();
if (pTemplate)
{
const rsmSourceVertexColourDescriptions& obSourceVertexColourDescriptions = pTemplate->GetSourceVertexColourDescriptions();
for(int i=0; i<obSourceVertexColourDescriptions.GetNumberOfDescriptions(); i++)
{
const rsmSourceVertexColourDescription* pobSourceVertexColourDescription = obSourceVertexColourDescriptions.GetDescription(i);
const char* pcColourSetName = pobSourceVertexColourDescription->GetName();
obAStrReturnMe.append(pcColourSetName);
}
}
if(obAStrReturnMe.length() == 1)
{
obAStrReturnMe.append("colorSet1");
}
}
return obAStrReturnMe;
}
void rageShaderMaya::breakConnectionToAttrib(const char* attribName)
{
Assert(attribName);
if (rageShaderMaya::m_GlobalIgnoreConnectionBreaks)
{
return;
}
rageShaderMaterial* pobRageMaterial = ValidateAndGetRageMaterial();
if(pobRageMaterial)
{
shaderMaterialGeoParamValue* param = pobRageMaterial->GetParamByUIName(attribName);
//TODO: add more evaluations here for other param types
if (param && param->GetType() == grcEffect::VT_TEXTURE)
{
shaderMaterialGeoParamValueTexture* textureParam = (shaderMaterialGeoParamValueTexture*)param;
m_bMaterialChangedSinceLastSaved = true;
textureParam->SetValue("none");
}
}
}
void rageShaderMaya::handleDirtyAttribute(const char* attribName)
{
Assert(attribName);
if(ValidateAndGetRageMaterial())
{
shaderMaterialGeoParamValue* param = ValidateAndGetRageMaterial()->GetParamByUIName(attribName);
//TODO: add more evaluations here for other param types as needed
if (param && param->GetType() == grcEffect::VT_TEXTURE)
{
//refresh the value by getting a setting it. Kindof a hack
MFnDependencyNode obFnShaderNode(thisMObject());
MPlug plug = obFnShaderNode.findPlug(aTextureToDisplayInMaya);
if(!plug.isNull())
{
MString strValue;
plug.getValue(strValue);
plug.setValue(strValue);
}
// Update shader in viewer, if needed
if(IsShaderInViewer())
{
m_pobUpdateData->UpdateShader();
}
}
}
}
void rageShaderMaya::UpdateTextureOverrides(void)
{
rageShaderMaterial* pobRageMaterial = ValidateAndGetRageMaterial();
Assertf(pobRageMaterial, "Trying to update texture overrides of an uninitialized Material on Maya node %s", MFnDependencyNode(thisMObject()).name().asChar());
MFnDependencyNode obFnThis(thisMObject());
for (int i=0; i<pobRageMaterial->GetParamCount(); i++)
{
// Set the values
shaderMaterialGeoParamValue * pobParam =pobRageMaterial->GetParam(i);
if ((pobParam->GetSourceOfParamValue() & shaderMaterialGeoParamDescription::GeoInstance) && pobParam->GetType() == grcEffect::VT_TEXTURE)
{
MPlug obInTexturePlug = obFnThis.findPlug(rageShaderMaterialMayaParam::GetCleanVersionOfString(pobParam->GetParamDescription()->GetUIName()));
if (!obInTexturePlug.isNull())
{
// Get the file node on the other end of the plug
if(obInTexturePlug.isConnected())
{
// It is connected, so get the other end of the connection
MStatus obStatus;
MPlugArray aobPlugsConnectedToParam;
obInTexturePlug.connectedTo(aobPlugsConnectedToParam, true, true, &obStatus);
CHECK_STATUS( obStatus )
if(aobPlugsConnectedToParam.length() > 0)
{
// Update the parameter to match the connected pieces
MString value;
MFnDependencyNode obFnFileNode(aobPlugsConnectedToParam[0].node());
MPlug filenamePlug = obFnFileNode.findPlug("fileTextureName");
filenamePlug.getValue(value);
pobParam->Update(value.asChar());
}
}
}
}
}
}