0

i'd like to know how to apply color and shading to an object in c++ (using maya-api map a 2D texture), Here is my code:

MString MNEUT_FILE("G:/repos_cpp/data/eye_base.obj");
MGlobal::executeCommand(MString("file -import -namespace \"EYETemp\" -mergeNamespacesOnClash true") + "\"" + MNEUT_FILE + "\"");
MGlobal::executeCommand(MString("select \"EYETemp:*\""));
MGlobal::executeCommand(MString("rename ") + "eyeNeutral");

stat = MGlobal::executeCommand(MString("shadingNode -asShader lambert -name eyeball"));
stat = MGlobal::executeCommand(MString("sets -renderable true -noSurfaceShader true -empty -name lambert3SG"));
//stat = MGlobal::executeCommand(MString("defaultNavigation -connectToExisting -source eyeball -destination lambert3SG"));
stat = MGlobal::executeCommand(MString("connectAttr -f eyeball.outColor lambert3SG.surfaceShader"));
stat = MGlobal::executeCommand(MString("shadingNode -asTexture file -name eyeball_TGA"));
stat = MGlobal::executeCommand(MString("connectAttr -f eyeball_TGA.outColor eyeball.color"));
stat = MGlobal::executeCommand(MString("setAttr -type \"string\" eyeball_TGA.fileTextureName \"G:/repos_cpp/data/eyeball.TGA\""));
MGlobal::executeCommand(MString("select -r eyeNeutralShape"));
stat = MGlobal::executeCommand(MString("hyperShade -assign lambert3SG"));
if (!stat)
{
    cout << "error::8\n";
}
stat = MGlobal::executeCommand(MString("sets -e -fe lambert3SG eyeNeutralShape"));
if (!stat)
{
    cout << "error::9\n";
}

when i run this code the "error::8" always exist! would you like to tell me how to solve it. Thanks very much!

jituan
  • 1
  • 1
  • Using hard coded node names is a really bad idea especially with maya which renames nodes if needed. So even if you rename something you can never be sure that the new name is exactly what you want. And I suggest not to split the whole process into a lot of lines but create one mel or python function and call that, this way it is easier to maintain and to debug. – haggi krey Dec 15 '20 at 12:32
  • Try to remove the "select -r..." and the "hyperShade..." commands, they should be not needed if you have the very last command "sets -e ...". – haggi krey Dec 17 '20 at 10:27

1 Answers1

0

You only check the status of the last MGlobal::executeCommand so you can't know that's where it actually fails. You also do not check the error text to get an explanation for the error.

Consider making a wrapper that you use to check all calls:

#include <stdexcept>

MCommandResult MayaCmd(MString cmd) {
    MCommandResult retval;
    std::cout << "Executing MayaCmd: " << cmd << '\n';
    auto stat = MGlobal::executeCommand(cmd, retval);
    if(!stat) throw std::runtime_error(stat.errorString().asChar()); // or asUTF8()
    return retval;
}

You should then be able to execute your commands with little care and get an exception with an explanation as soon as something exceptional happens.

Example:

try {
    MayaCmd(MString("file -import -namespace \"EYETemp\" -mergeNamespacesOnClash true") + "\"" + MNEUT_FILE + "\"");
    MayaCmd("select \"EYETemp:*\"");
    MayaCmd("rename eyeNeutral");

    MayaCmd("shadingNode -asShader lambert -name eyeball");
    MayaCmd("sets -renderable true -noSurfaceShader true -empty -name lambert3SG");
    //MayaCmd("defaultNavigation -connectToExisting -source eyeball -destination lambert3SG");
    MayaCmd("connectAttr -f eyeball.outColor lambert3SG.surfaceShader");
    MayaCmd("shadingNode -asTexture file -name eyeball_TGA");
    MayaCmd("connectAttr -f eyeball_TGA.outColor eyeball.color");
    MayaCmd("setAttr -type \"string\" eyeball_TGA.fileTextureName \"G:/repos_cpp/data/eyeball.TGA\"");
    MayaCmd("select -r eyeNeutralShape");
    MayaCmd("hyperShade -assign lambert3SG");
    MayaCmd("sets -e -fe lambert3SG eyeNeutralShape");
}
catch(const std::exception& ex) {
    std::cout << "Exception: " << ex.what() << '\n';
}

I also suspect that the name you should use with hyperShade -assign is a name returned by one of the previous commands, perhaps shadingNode. Example:

auto ShaderNode = MayaCmd("shadingNode ...").stringResult();
...
MayaCmd("hyperShade -assign " + ShaderNode);
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
  • Hi, Thanks very much for your help! And i get this information when i tried it, Only the "hyperShade -assign lambert3SG" run into error; i would like to know if i used the commands in a wrong way? '''Executing MayaCmd: hyperShade -assign lambert3SG Exception: (kFailure):''' – jituan Dec 16 '20 at 01:39
  • @jituan You're welcome! Oh, that was a disappointing exception. I don't know if you're using `hyperShade` correctly and I was hoping that you'd get more information out of the exception string than `kFailure`. :-( Anyway, doesn't `shadingNode` return the name of the shader that should be used with `hypderShade`? If it does, that could be the cause of the problem. – Ted Lyngmo Dec 16 '20 at 06:37
  • @jituan Were you able to try out my suggestion in the updated answer? – Ted Lyngmo Dec 17 '20 at 06:27
  • 1
    It is possible that the hypershade command only works if the hypershade window has been initialized. I recommend to use the _sets()_ command to assign shaders to objects. – haggi krey Dec 17 '20 at 09:36
  • @haggikrey Ok, I have actually no idea how this framework works. :-) If OP:s usage is fundamentally "broken", my suggested changes won't help I guess. I'll remove the answer if you think it's the wrong way to fix the problem. ... or if it's not totally bad, please feel free to update it. I'm good with both. – Ted Lyngmo Dec 17 '20 at 09:47
  • 1
    I just realized that the commands already use the _sets()_ command. So in theory the commands "select -r..." and the one below "hyperShade..." are not needed because that's exact the same as the last command "sets -e -fe..." – haggi krey Dec 17 '20 at 10:26
  • @haggikrey Ok, nice! ... but should the argument to `hyperShade -assign` be what was previously returned by `shadingNode` for example - or is hardcoding `-assign lambert3SG` fine? – Ted Lyngmo Dec 17 '20 at 10:32
  • 1
    As mentioned above, you can never be sure that the hardcoded name is the correct one, so the name should be the one returned by teh _shadingNode()_ command. That's one of the reasons why I suggested to encapsulate all these mel commands into a single mel function or better a phyton function what is very much easier to control and maintain. – haggi krey Dec 17 '20 at 12:08
  • 1
    @TedLyngmo Hi, First of all, thanks! i have tried your suggestion, but it didn't help. maybe just like haggi krey said the hypershade window should be inited. Filanlly, i just use command "sets -e -fe..." , with no error, but i export .mesh model's material name is empty, and i solve it through specify the material when i use it. Thanks both of you any way! – jituan Dec 21 '20 at 04:43