3ds Max Programming Materials Category() - c++

it is a bit strange but no matter how many times I tried all materials and maps that I create will appear in the General category material.
That’s my code for the material category.
const TCHAR* Category() { return NULL; }//_T(""); }//GetString(IDS_CATEGORY); }
const MCHAR* GetEntryName() const { return LuxMixMapFriendlyClassName; } //NULL; }
const MCHAR* GetEntryCategory() const {
HINSTANCE hInst = GetModuleHandle(_T("sme.gup"));
if (hInst) {
//Extract a resource from the calling module's string table.
static MSTR category(MaxSDK::GetResourceStringAsMSTR(hInst,
IDS_3DSMAX_SME_MATERIALS_CATLABEL).Append(_T("\\Lux")));
return category.data();
}
else
{
return _T("Maps\\Lux");
}
}
enter code here

Finally, I fix the problem, honestly, 3dsmax needs better documentation.
Just writing the solution if this is the case for someone else.
All the code is perfectly correct but in order to apply there is one class that should be called that is optional but not work without it. Also, no error if you not calling it. ( a bit funny )
first, in public classDesc2 i add the "public IMaterialBrowserEntryInfo"
class Lux_AddClassDesc : public ClassDesc2, public IMaterialBrowserEntryInfo
hen inside the class add.
FPInterface* GetInterface(Interface_ID id) {
if (IMATERIAL_BROWSER_ENTRY_INFO_INTERFACE == id) {
return static_cast<IMaterialBrowserEntryInfo*>(this);
}
return ClassDesc2::GetInterface(id);
}
All other part is exactly the same.

Related

Antlr4 c++ visitor API

I am using Antlr4's C++ visitor api to traverse a parse tree. However, I'm struggling to get it functioning correctly. Namely, I'm not sure how to use the visitChildren(ParseTree *tree) call.
I'm given the context for each rule that I have defined. And I can traverse the tree using the contexts: context->accept[RuleContext]([RuleContext]* rule)
However, when I use those I continually visit the same node multiple times.
For instance:
program:
: nameRule
dateRule
( statements )*
EOF
;
nameRule
: NAME IDENTIFIER ;
dateRule
: DATE IDENTIFIER ;
statements:
: statementX
| statementY
| statementZ
;
statementX:
: // do something here
statementY:
: // do something here
statementZ:
: // do something here
IDENTIFIER, DATE, and NAME are terminals.
I build the Antlr parsing structure by the following:
void Parser::parse() {
ifstream file(FLAGS_c, ifstream::binary);
// Convert the file into ANTLR's format.
ANTLRInputStream stream = ANTLRInputStream(file);
// Give the input to the lexer.
MyLexer lexer = new MyLexer(&stream);
// Generate the tokens.
CommonTokenStream tokens(lexer);
file.close();
tokens.fill();
// Create the translation that will parse the input.
MyParser parser = new MyParser(&tokens);
parser->setBuildParseTree(true);
MyParser::ProgramContext *tree = parser->program();
auto *visitor = new MyVisitor();
visitor->visitProgram(tree);
}
So when I try to traverse this it looks similar to this, the class MyVisitor extends MyParserVisitor. MyVisitor is the visitor class I use to traverse the generated tree.
Any MyVisitor::visitProgram(ParserVisitor::ProgramContext *context) {
this->visitNameRule(context->nameRule());
this->visitDateRule(context->dateRule());
if (!this->statements.empty()) {
for (auto &it : this->statements) {
this->visitStatements(it);
}
}
return Any(context);
}
// Omitting name and date rules.
Any MyVisitor::visitStatements(ParserVisitor::StatementContext *context) {
this->visitStatementX(context->statementX());
this->visitStatementY(context->statementY());
this->visitStatementZ(context->statementZ());
return Any(context);
}
In this case, statements X, Y, and Z will be visited every time statements is visited. Even if they aren't present in the input program.
Is this the correct way to use this? If it isn't, then I assume the visitChildren(ParseTree *tree) is the correct api to use at each visitor function. But I don't understand how to get access to the ParseTree data structure from the *Context.
This question is not directly related to the C++ visitor, but a general visitor problem in ANTLR4. What you are doing is to shortcut the visitor walk in a way you are not intended to do. Don't explicitly visit the certain sub trees manually, but instead call the super implementation to let it do for you and collect the result in individual visitStatementXXX functions. Look at this implementation of a (very simple) expression evaluator, used in a unit test (written in C++). Here's a partial copy to demonstrate the principle:
class EvalParseVisitor : public MySQLParserBaseVisitor {
public:
std::vector<EvalValue> results; // One entry for each select item.
bool asBool(EvalValue in) {
if (!in.isNullType() && in.number != 0)
return true;
return false;
};
virtual Any visitSelectItem(MySQLParser::SelectItemContext *context) override {
Any result = visitChildren(context);
results.push_back(result.as<EvalValue>());
return result;
}
virtual Any visitExprNot(MySQLParser::ExprNotContext *context) override {
EvalValue value = visit(context->expr());
switch (value.type) {
case EvalValue::Null:
return EvalValue::fromNotNull();
case EvalValue::NotNull:
return EvalValue::fromNull();
default:
return EvalValue::fromBool(!asBool(value));
}
}
virtual Any visitExprAnd(MySQLParser::ExprAndContext *context) override {
EvalValue left = visit(context->expr(0));
EvalValue right = visit(context->expr(1));
if (left.isNullType() || right.isNullType())
return EvalValue::fromNull();
return EvalValue::fromBool(asBool(left) && asBool(right));
return visitChildren(context);
}
...
The essential part is the call to visit() which in turn iterates over the child nodes of the given context tree and triggers only visitor functions for elements that actually exist.

C++ Using a Class return function in another Class if statement

Alright, I have been having this problem for a while and I believe I have pin-pointed where the problem is, but I am not sure how to fix it.
void Unit::AddStatusEffect(StatusEffect effect)
{
// Add status effect and if it effects what actions a unit can do, do it here.
myEffects.push_back(effect);
if( effect.GetEffect == effect.STUN)
{
myCanMove = false;
myCanAttack = false;
myCanCast = false;
}
else if (effect.GetEffect == effect.MUTE)
{
myCanCast = false;
}
else if (effect.GetEffect == effect.BLIND)
{
myCanHit = false;
}
else
{}
}
My problem seems to be with the effect.GetEffect return function within the StatusEffect class. If I ask if(effect.STUN == effect.STUN) I get no errors which is why I believe the function is the problem. The error I get seems to be:
function call missing argument list; use '&StatusEffect::GetEffect' to create a pointer to member
(Here is the class in case there is something in there that may be the problem)
class StatusEffect
{
public:
enum Effect { POISON, BURN, BLEED, FREEZE, MUTE, STUN, BLIND, ATKBOOST, HPREGEN, MANAREGEN, MATKBOOST, DEFENSEBOOST, MAGICDEFENSEBOOST };
private:
Effect myEffect;
public:
////////////////////////////////////////////////////////////////
// Data Retrievers
////////////////////////////////////////////////////////////////
Effect const GetEffect() { return myEffect; }
StatusEffect(void);
~StatusEffect(void);
};
I hope I explained my problem well enough. Everything I read up on didn't seem to help me solve this problem.
In Unit::AddStatusEffect, replace effect.GetEffect by effect.GetEffect()
The difference between effect.GetEffect and effect.GetEffect() is that the first evaluates to a pointer to a member function (the function does not get called) while the second evaluates to the returned value of the function call.
You have to call a method or function by adding parentheses, even if there is no argument.
effect.GetEffect()

C++ Function signature that returns a PPL task?

I am a total noob when it comes to using PPL tasks within the C++ environment, so I am having a hard time to figure out what would be the C++ syntax of the following C# code:
private static async Task<RandomAccessStreamReference> GetImageStreamRef()
{
return RandomAccessStreamReference.CreateFromStream(await GetImageStream());
}
private static async Task<IRandomAccessStream> GetImageStream()
{
var stream = new InMemoryRandomAccessStream();
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.BmpEncoderId, stream);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, width, height, 96, 96, imageBytes);
await encoder.FlushAsync();
return stream;
}
This C# code was taken from the Windows Store reversi Microsoft sample code. The best I could get so far is this:
Concurrency::task<IRandomAccessStream^> GetImageStream()
{
auto stream = ref new InMemoryRandomAccessStream();
task<BitmapEncoder^>(BitmapEncoder::CreateAsync(BitmapEncoder::JpegEncoderId, Stream)).then([this, stream, width, height, imageBytes](BitmapEncoder^ encoder)
{
encoder->SetPixelData(BitmapPixelFormat::Rgba8, BitmapAlphaMode::Ignore, width, height, 96.0, 96.0, imageBytes);
return encoder->FlushAsync();
}).then([this, stream]()
{
return stream; //Does this even make sense?
});
//return stream; //Not sure if I should have this here?
}
But it generates the following compile error:
error C4716: 'GetImageStream' : must return a value
I understand why this error happens, but I have no clue how I can have a function that returns a task without having a return value at two different locations? I haven't even tackled GetImageStream yet.
I am not even sure I took the right path into this...
Thank you!
You're real close. A key point you might be missing is that then returns you a new task. So the last then in the chain determines the type of your task.
auto t = task<int>([] { return 0; });
// t is task<int>
auto t = task<int>([] { return 0; })
.then([](int i) { return 3.14; });
// t is task<double>
auto t = task<int>([] { return 0; })
.then([](int i) { return 3.14; })
.then([](double d) { return "foo"; });
// t is task<const char*>
If you just glance at the first line, it looks like you've always got a task<int>, but as you can see that's not necessarily the case if you immediately call then on it.
Secondly, keep in mind that your function is returning a task, not the stream itself.
Usually you'd have the last then in your chain return you the task that you'll return from your function, and rather than store the task in a local variable, you just return it. For example:
task<const char*>
get_foo()
{
return task<int>([] { return 0; })
.then([](int i) { return 3.14; })
.then([](double d) { return "foo"; });
}
Again, it looks a tad strange because a quick glance makes you think that you're returning a task<int>. This is nicely handled by using create_task rather than calling the task constructor explicitly. It frees you from having to explicitly specify the task's type at all. Additionally, it's easily changed to create_async if you instead want to return an IAsyncInfo derivative.
I'm not at all familiar with BitmapEncoder, but here's a tweaked version of your code that might do the trick:
Concurrency::task<IRandomAccessStream^> GetImageStream()
{
auto stream = ref new InMemoryRandomAccessStream();
return create_task(BitmapEncoder::CreateAsync(BitmapEncoder::JpegEncoderId, stream))
.then([this, width, height, imageBytes](BitmapEncoder^ encoder)
{
// are width, height, and imageBytes member variables?
// if so, you should only need to capture them OR "this", not both
encoder->SetPixelData(BitmapPixelFormat::Rgba8, BitmapAlphaMode::Ignore, width, height, 96.0, 96.0, imageBytes);
return encoder->FlushAsync();
}).then([stream]()
{
// this should work fine since "stream" is a ref-counted variable
// this lambda will keep a reference alive until it uses it
return stream;
});
}
The only real change is using create_task and immediately returning its result.
I'm still learning PPL myself, but one thing I've learned that's held up so far is that you should pretty much always be doing something with any task you create. The usual thing to do is use then to turn it into a new/different task, but you still need to do something with the task returned by the last then. Oftentimes you just return it, as above. Sometimes you'll add it to a container of tasks which are then grouped together with when_all or when_any. Sometimes you'll just call get() on it yourself to wait for its result. But the point is that if you create a task and don't do anything with it, then there's probably something wrong.
Also if anyone cares, here is how to implement the GetImageStreamRef mentioned above, in C++ version:
task<RandomAccessStreamReference^> GetImageStreamRef()
{
return GetImageStream().then([](IRandomAccessStream^ pStream)
{
return RandomAccessStreamReference::CreateFromStream(pStream);
});
}
Also, make sure to NEVER use .get() on any of those tasks, otherwise you will get an exception thrown saying "Illegal to wait on a task in a Windows Runtime STA". The proper way to get the value of this image stream reference is, for example on a DataRequestHandler that sets a bitmap data on the DataRequest:
void OnBitmapRequested(DataProviderRequest^ request)
{
auto Deferral = request->GetDeferral();
GetImageStreamRef().then([Deferral, request](RandomAccessStreamReference^ pStreamRef)
{
try
{
request->SetData(pStreamRef);
Deferral->Complete();
}
catch( std::exception ex )
{
Deferral->Complete();
throw ex; //Propagate the exception up again
}
});
}

Visual Studio Compiler is highlighting Static variables differently?

I'm programming in C++ and have a method which uses a static variable. The method isn't working as I think it should; upon investigation, I found that my static variable is being highlighted in red in two places and blue in other places. Below is the code:
int GameModeState::changeJob(int number)
{
static int job = 1; //red
if (number == 1)
{
job = (job+1); //First one is red, second one is blue
return job; //blue
} else {
return job; //blue
}
}
I'm calling this method with other methods, one shown for example:
int GameModeState::getJob()
{
int currentJob = (changeJob(2));
return currentJob;
}
I want a method like getJob() to simply return the current value of job, while another method, when calling changeJob(number) is changeJob(1), to increment job's value by one. (Hence the if/else statement in changeJob(number)).
Since the job variables are highlighted differently, I'm thinking the compiler is saying that it views the two separately somehow? I'm getting stuck with job being some even value.
EDIT I also have Awesomium... I believe that is the only addition to the compiler, but I'm not completely sure.
MOAR EDIT In another class, I have a method which should determine the current job's number and do something based on if the number is even or odd (since right now there are only two jobs)
void ZoneMovementState::_changeZone(const String& message, const Awesomium::JSValue& input, Awesomium::JSValue& output)
{
//Awesomium::JSValue::Object object = input.getObject();
//String zoneFilename = Convert::toString(object[L"zoneFilename"].toString());
// If the number from getJob is even, the player is currently a geologist
if (GameModeState::getJob()%2 == 0)
{
ZoneParser::getSingleton().load("../media/zones/geology_zone.xml", false);
} else {
ZoneParser::getSingleton().load("../media/zones/farm_zone.xml", false);
}
transitionHandler->go();
}
Ignore the two commented out lines; they deal with JS, which I'm not working on for now.
In the program, I can access the farm_zone until I increment job's value using the below method in GameModeState:
void GameModeState::_openNotebook(const String& message, const Awesomium::JSValue& input, Awesomium::JSValue& output)
{
mNotebookTransition->go();
static int currentJob = changeJob(1);
}
.... So I figured out my problem. While going through the code to show you guys, I realized that the static for currentJob was probably unneeded... once I removed it, my code works as it should now.
Thanks for the help guys!
Part of the problem here is you're using a static local for what very likely should just be a member variable. A static local maintains it's value across all calls to a function in all threads in a process. It's much more likely that you want it to persist for all calls to changeJob in a particular GameModeState instance (else why make it a member functon to begin with?).
To do this you'll need to define a member variable on GameModeState initialize it in the constructor and then access it in the method. For example
class GameModeState {
int job;
GameModeState() : job(1) {}
int changeJob(int number);
};
int GameModeState::changeJob(int number) {
if (number == 1) {
job = (job+1);
return job;
} else {
return job;
}
}
Note: I'm not entirely sure why you're seeing the color's your are seeing. Visual Studio by default won't color member variables a particular color in C++ so it's very likely another add-in you are using.
Nah, highlighting doesn't mean anything. That is, the editor doesn't call the compiler before deciding how/what/when to highlight. So that is not your problem. Sorry 'bout that :-)
You can prove this to yourself by going to Tools->Options->TextEditor and noticing that you can change the highlighting by choosing a different text-editing model.

What's a better way to store information than by using static ints? C++

I'm keeping track of a player's "job" by setting his job to a number, and incrementing it by one if he changes job, and determining which job he currently is by whether the number is even or odd. (Only two jobs right now). However, I know there are better ways of doing this, and soon I'll need to implement for a third and fourth job, so I cannot keep using the even/odd check.
Here's my code for reference: (Please note that I only include relevant code)
GameModeState.cpp
// If changeJob's parameter number is 1, it increments the job. If number is 2, it only returns the current job
int GameModeState::changeJob(int number)
{
// Default job is even (landman)
static int job = 1;
if (number == 1)
{
job = (job+1);
return job;
}
else
{
return job;
}
}
int GameModeState::getJob()
{
int currentJob = (changeJob(2));
return currentJob;
}
// If the player opens the "stat sheet", it changes their job
void GameModeState::_statSheet(const String& message, const Awesomium::JSValue& input, Awesomium::JSValue& output)
{
changeJob(1);
}
GameModeState.h
class GameModeState : public GameState::State
{
public:
/// Changes the player's job if number is 1, or returns current job if number is 2
static int changeJob(int number);
/// Returns the current job number by calling changeJob appropriately
static int getJob();
private:
// Opening the player sheet will change the player's job
void _statSheet(const String& message, const Awesomium::JSValue& input, Awesomium::JSValue& output);
};
ZoneMovementState.cpp (This is where I check for current job)
#include "GameModeState.h"
#include <EnergyGraphics/ZoneParser.h>
void ZoneMovementState::_changeZone(const String& message, const Awesomium::JSValue& input, Awesomium::JSValue& output)
{
// If the number from getJob is even, the player is currently a geologist
if (GameModeState::getJob()%2 == 0)
{
ZoneParser::getSingleton().load("../media/zones/geology_zone.xml", false);
}
else //otherwise they are a landman
{
ZoneParser::getSingleton().load("../media/zones/landman_zone.xml", false);
}
transitionHandler->go();
}
I'm thinking either arrays or enums of the jobs will be the better way to deal with this, but I'm not sure how to implement this into my code. If you know a better way, please include examples or at least a point in the right direction. I will greatly appreciate it!
Don't use static variables to save anything like that inside a class. Use a member variable instead.
IMO the easiest way to do something like that and make it extensible is using a enum:
enum PlayerJob
JOB_NONE = 0,
JOB_GEOLOGIST,
JOB_LANDMAN,
...
NUM_JOBS // this element is optional but can be useful for range checking.
};
...
PlayerJob job = JOB_NONE;
...
switch(job)
{
case JOB_NONE:
break;
case JOB_GEOLOGIST:
...
break;
...
default:
error("Unhandled palyer job: %d", job);
break;
}
Also I'd think about somehow organizing such "job relevant" stuff into some kind of array or list or whatever to make it easier to call "job specific" things:
std::map<PlayerJob,std::string> jobzones;
jobzones.push_back(JOB_GEOLOGIST, "geozone.xml");
...
transitToZone(jobzones[job]);
Enums are nice, you may also think about using a std::stack or something similar for the GameState, so that you can push/pop etc.
You may want to look at the State pattern.