#include <maya/MFnPlugin.h>
#include <maya/MPxNode.h>
#include <maya/MIOStream.h>
#include <maya/MString.h>
#include <maya/MTypeId.h>
#include <maya/MPlug.h>
#include <maya/MDataBlock.h>
#include <maya/MDataHandle.h>
#include <maya/MFnNumericAttribute.h>
#include <maya/MFnTypedAttribute.h>
#include <maya/MFnStringData.h>
#include <maya/MRenderUtil.h>
#include <maya/MImage.h>
#include <maya/MFloatVector.h>
#include <maya/MFnDependencyNode.h>
#include <maya/MDrawRegistry.h>
#include <maya/MPxShadingNodeOverride.h>
#include <maya/MViewport2Renderer.h>
#include <maya/MFragmentManager.h>
#include <maya/MShaderManager.h>
#include <maya/MTextureManager.h>
#include <maya/MStateManager.h>
{
public:
static void* creator();
FileNode();
~FileNode() override;
SchedulingType
schedulingType()
const override {
return SchedulingType::kParallel; }
private:
size_t fWidth;
size_t fHeight;
friend class FileNodeOverride;
};
{
public:
~FileNodeOverride() override;
private:
FileNodeOverride(
const MObject& obj);
mutable MString fResolvedSamplerName;
};
const MTypeId FileNode::id(0x00081057);
void* FileNode::creator()
{
return new FileNode();
}
FileNode::FileNode()
: fWidth(0)
, fHeight(0)
{
}
FileNode::~FileNode()
{
}
MStatus FileNode::setDependentsDirty(
{
if (plug == aFileName)
{
fImage.release();
fWidth = fHeight = 0;
}
}
{
if ((plug != aOutColor) &&
(plug.
parent() != aOutColor) &&
(plug != aOutAlpha))
{
return MS::kUnknownParameter;
}
float resultAlpha = 1.0f;
if (!fImage.pixels())
{
{
unsigned int width = 0;
unsigned int height = 0;
if (fImage.readFromFile(exactName) &&
fImage.getSize(width, height))
{
fWidth = width;
fHeight = height;
}
}
}
unsigned char* data = fImage.pixels();
if (data && fWidth > 0 && fHeight > 0)
{
float u = uv[0]; if (u<0.0f) u=0.0f; if (u>1.0f) u=1.0f;
float v = uv[1]; if (v<0.0f) v=0.0f; if (v>1.0f) v=1.0f;
static const size_t pixelSize = 4;
size_t rowOffset = (size_t)(v*(fHeight-1)) * fWidth;
size_t colOffset = (size_t)(u*(fWidth-1));
const unsigned char* pixel = data +
((rowOffset + colOffset) * pixelSize);
resultColor[0] = ((float)pixel[0])/255.0f;
resultColor[1] = ((float)pixel[1])/255.0f;
resultColor[2] = ((float)pixel[2])/255.0f;
resultAlpha = ((float)pixel[3])/255.0f;
}
outColor = resultColor;
float& outAlpha = outAlphaHandle.
asFloat();
outAlpha = resultAlpha;
return MS::kSuccess;
}
#define MAKE_INPUT(attr) \
CHECK_MSTATUS(attr.setKeyable(true)); \
CHECK_MSTATUS(attr.setStorable(true)); \
CHECK_MSTATUS(attr.setReadable(true)); \
CHECK_MSTATUS(attr.setWritable(true));
#define MAKE_OUTPUT(attr) \
CHECK_MSTATUS(attr.setKeyable(false)); \
CHECK_MSTATUS(attr.setStorable(false)); \
CHECK_MSTATUS(attr.setReadable(true)); \
CHECK_MSTATUS(attr.setWritable(false));
MObject FileNode::aCMConfigEnabled;
{
MAKE_INPUT(tAttr);
MObject theStringCMConfigPath = stringDataCMConfigPath.create();
aCMConfigPath = tAttr.
create(
"colorManagementConfigFilePath",
"cmcfp",
MFnData::kString, theStringCMConfigPath);
MObject theStringCMWorkingSpace = stringDataCMWorkingSpace.
create();
MAKE_INPUT(tAttr);
MAKE_INPUT(tAttr);
MAKE_INPUT(nAttr);
MAKE_INPUT(nAttr);
aUVCoord = nAttr.
create(
"uvCoord",
"uv", child1, child2);
MAKE_INPUT(nAttr);
MAKE_OUTPUT(nAttr);
MAKE_OUTPUT(nAttr);
return MS::kSuccess;
}
{
return new FileNodeOverride(obj);
}
FileNodeOverride::FileNodeOverride(
const MObject& obj)
: MPxShadingNodeOverride(obj)
, fObject(obj)
, fFragmentName("")
, fFileName("")
, fSamplerState(NULL)
, fResolvedMapName("")
, fResolvedSamplerName("")
{
static const MString sFragmentOutputName(
"fileTexturePluginFragmentOutput");
static const char* sFragmentOutputBody =
"<fragment uiName=\"fileTexturePluginFragmentOutput\" name=\"fileTexturePluginFragmentOutput\" type=\"structure\" class=\"ShadeFragment\" version=\"1.0\">"
" <description><![CDATA[Struct output for simple file texture fragment]]></description>"
" <properties>"
" <struct name=\"fileTexturePluginFragmentOutput\" struct_name=\"fileTexturePluginFragmentOutput\" />"
" </properties>"
" <values>"
" </values>"
" <outputs>"
" <alias name=\"fileTexturePluginFragmentOutput\" struct_name=\"fileTexturePluginFragmentOutput\" />"
" <float3 name=\"outColor\" semantic=\"mayaCMSemantic\" />"
" <float name=\"outAlpha\" />"
" </outputs>"
" <implementation>"
" <implementation render=\"OGSRenderer\" language=\"Cg\" lang_version=\"2.1\">"
" <function_name val=\"\" />"
" <declaration name=\"fileTexturePluginFragmentOutput\"><![CDATA["
"struct fileTexturePluginFragmentOutput \n"
"{ \n"
" float3 outColor; \n"
" float outAlpha; \n"
"}; \n]]>"
" </declaration>"
" </implementation>"
" <implementation render=\"OGSRenderer\" language=\"HLSL\" lang_version=\"11.0\">"
" <function_name val=\"\" />"
" <declaration name=\"fileTexturePluginFragmentOutput\"><![CDATA["
"struct fileTexturePluginFragmentOutput \n"
"{ \n"
" float3 outColor; \n"
" float outAlpha; \n"
"}; \n]]>"
" </declaration>"
" </implementation>"
" <implementation render=\"OGSRenderer\" language=\"GLSL\" lang_version=\"3.0\">"
" <function_name val=\"\" />"
" <declaration name=\"fileTexturePluginFragmentOutput\"><![CDATA["
"struct fileTexturePluginFragmentOutput \n"
"{ \n"
" vec3 outColor; \n"
" float outAlpha; \n"
"}; \n]]>"
" </declaration>"
" </implementation>"
" </implementation>"
"</fragment>";
static const MString sFragmentName(
"fileTexturePluginFragment");
static const char* sFragmentBody =
"<fragment uiName=\"fileTexturePluginFragment\" name=\"fileTexturePluginFragment\" type=\"plumbing\" class=\"ShadeFragment\" version=\"1.0\">"
" <description><![CDATA[Simple file texture fragment]]></description>"
" <properties>"
" <float2 name=\"uvCoord\" semantic=\"mayaUvCoordSemantic\" flags=\"varyingInputParam\" />"
" <texture2 name=\"map\" />"
" <sampler name=\"textureSampler\" />"
" </properties>"
" <values>"
" </values>"
" <outputs>"
" <struct name=\"output\" struct_name=\"fileTexturePluginFragmentOutput\" />"
" </outputs>"
" <implementation>"
" <implementation render=\"OGSRenderer\" language=\"Cg\" lang_version=\"2.100000\">"
" <function_name val=\"fileTexturePluginFragment\" />"
" <source><![CDATA["
"fileTexturePluginFragmentOutput fileTexturePluginFragment(float2 uv, texture2D map, sampler2D mapSampler) \n"
"{ \n"
" fileTexturePluginFragmentOutput result; \n"
" uv -= floor(uv); \n"
" uv.y = 1.0f - uv.y; \n"
" float4 color = tex2D(mapSampler, uv); \n"
" result.outColor = color.rgb; \n"
" result.outAlpha = color.a; \n"
" return result; \n"
"} \n]]>"
" </source>"
" </implementation>"
" <implementation render=\"OGSRenderer\" language=\"HLSL\" lang_version=\"11.000000\">"
" <function_name val=\"fileTexturePluginFragment\" />"
" <source><![CDATA["
"fileTexturePluginFragmentOutput fileTexturePluginFragment(float2 uv, Texture2D map, sampler mapSampler) \n"
"{ \n"
" fileTexturePluginFragmentOutput result; \n"
" uv -= floor(uv); \n"
" uv.y = 1.0f - uv.y; \n"
" float4 color = map.Sample(mapSampler, uv); \n"
" result.outColor = color.rgb; \n"
" result.outAlpha = color.a; \n"
" return result; \n"
"} \n]]>"
" </source>"
" </implementation>"
" <implementation render=\"OGSRenderer\" language=\"GLSL\" lang_version=\"3.0\">"
" <function_name val=\"fileTexturePluginFragment\" />"
" <source><![CDATA["
"fileTexturePluginFragmentOutput fileTexturePluginFragment(vec2 uv, sampler2D mapSampler) \n"
"{ \n"
" fileTexturePluginFragmentOutput result; \n"
" uv -= floor(uv); \n"
" uv.y = 1.0f - uv.y; \n"
" vec4 color = texture(mapSampler, uv); \n"
" result.outColor = color.rgb; \n"
" result.outAlpha = color.a; \n"
" return result; \n"
"} \n]]>"
" </source>"
" </implementation>"
" </implementation>"
"</fragment>";
static const MString sFragmentGraphName(
"fileTexturePluginGraph");
static const char* sFragmentGraphBody =
"<fragment_graph name=\"fileTexturePluginGraph\" ref=\"fileTexturePluginGraph\" class=\"FragmentGraph\" version=\"1.0\">"
" <fragments>"
" <fragment_ref name=\"fileTexturePluginFragment\" ref=\"fileTexturePluginFragment\" />"
" <fragment_ref name=\"fileTexturePluginFragmentOutput\" ref=\"fileTexturePluginFragmentOutput\" />"
" </fragments>"
" <connections>"
" <connect from=\"fileTexturePluginFragment.output\" to=\"fileTexturePluginFragmentOutput.fileTexturePluginFragmentOutput\" />"
" </connections>"
" <properties>"
" <float2 name=\"uvCoord\" ref=\"fileTexturePluginFragment.uvCoord\" semantic=\"mayaUvCoordSemantic\" flags=\"varyingInputParam\" />"
" <texture2 name=\"map\" ref=\"fileTexturePluginFragment.map\" />"
" <sampler name=\"textureSampler\" ref=\"fileTexturePluginFragment.textureSampler\" />"
" </properties>"
" <values>"
" </values>"
" <outputs>"
" <struct name=\"output\" ref=\"fileTexturePluginFragmentOutput.fileTexturePluginFragmentOutput\" />"
" </outputs>"
"</fragment_graph>";
if (theRenderer)
{
if (fragmentMgr)
{
bool fragAdded = fragmentMgr->
hasFragment(sFragmentName);
bool structAdded = fragmentMgr->
hasFragment(sFragmentOutputName);
bool graphAdded = fragmentMgr->
hasFragment(sFragmentGraphName);
if (!fragAdded)
{
}
if (!structAdded)
{
}
if (!graphAdded)
{
}
if (fragAdded && structAdded && graphAdded)
{
fFragmentName = sFragmentGraphName;
}
}
}
}
FileNodeOverride::~FileNodeOverride()
{
fSamplerState = NULL;
}
MHWRender::DrawAPI FileNodeOverride::supportedDrawAPIs() const
{
return MHWRender::kOpenGL | MHWRender::kDirectX11 | MHWRender::kOpenGLCoreProfile;
}
MString FileNodeOverride::fragmentName()
const
{
fResolvedMapName = "";
fResolvedSamplerName = "";
return fFragmentName;
}
void FileNodeOverride::getCustomMappings(
{
"map", "", false, true);
"textureSampler", "", false, true);
mappings.
append(textureSamplerMapping);
}
void FileNodeOverride::updateDG()
{
if (status)
{
node.findPlug("fileName", true).getValue(name);
}
}
void FileNodeOverride::updateShader(
{
if (fResolvedMapName.length() == 0)
{
if (mapping)
{
}
}
if (fResolvedSamplerName.length() == 0)
{
if (mapping)
{
}
}
if (fResolvedMapName.length() > 0 && fResolvedSamplerName.length() > 0)
{
if (!fSamplerState)
{
}
if (fSamplerState)
{
}
if (renderer)
{
if (textureManager)
{
if (texture)
{
textureAssignment.
texture = texture;
}
}
}
}
}
bool FileNodeOverride::valueChangeRequiresFragmentRebuild(
const MPlug* plug)
const
{
if(*plug == FileNode::aColorSpace)
return true;
}
static const MString sRegistrantId(
"fileTexturePlugin");
{
const MString UserClassify(
"texture/2d:drawdb/shader/texture/2d/fileTexture");
MFnPlugin plugin(obj, PLUGIN_COMPANY,
"1.0",
"Any");
"fileTexture",
FileNode::id,
FileNode::creator,
FileNode::initialize,
&UserClassify));
"drawdb/shader/texture/2d/fileTexture",
sRegistrantId,
FileNodeOverride::creator));
return MS::kSuccess;
}
{
"drawdb/shader/texture/2d/fileTexture",
sRegistrantId));
return MS::kSuccess;
}