Problems with R16 [SOLVED]
-
On 10/10/2014 at 04:45, xxxxxxxx wrote:
Ah, if you are under Windows, could you provide me with a plugin compiled in debug mode? This may be faster, than me having to set something up first. Just the binary should be fine for a first shot.
By the way, are you porting to R16 changing the code or are you trying to go with __LEGACY_API define? -
On 10/10/2014 at 04:57, xxxxxxxx wrote:
Calling GetInputState() from any other but the main thread causes a breakpoint to be triggered.
The BaseContainer getter methods trigger breakpoints, for instance, if you call GetVector(id) but the
data at the specified id is not a vector.This is one reason why it is important to properly initialize the node's container in Init().
-
On 10/10/2014 at 05:13, xxxxxxxx wrote:
Andreas:
Sure, where can I send it? And yep, I have changed the code and am not running with __LEGACY_API (though I do have some typedefs and #defines used myself).Niklas: Shouldn't bt be the main thread here? It's not explicitly stated but I may want to check this myself. How do I get a pointer to the C4D main thread or is it the main thread if bt is nullptr?
Thanks for the tip about GetVector(id) as well but I have this element intialised correctly and the id is also correct and it is definetly a VECTOR element (and if it wasn't shouldn't that break point also be triggered in R13?)
-
On 10/10/2014 at 05:24, xxxxxxxx wrote:
We mailed already, that address would be fine.
-
On 10/10/2014 at 05:58, xxxxxxxx wrote:
Ok, at least I could find the culprit for the vector and Niklas was right. Although in the Init() of my object the vector was correctly initialised, I have a macro command where that element was set as a float! When I generated my object without the macro...no trigger
Thanks for that Niklas! Worth an entry in the docs I'd say..
Still the problem with GetInputState persists. Why is it triggering a break in R16 but not in R13 (during debugging). Hope you find a clue Andreas. Thanks for the effort!
-
On 10/10/2014 at 06:21, xxxxxxxx wrote:
Glad it helped.
Afaik, Execute() is not called from the main thread. The main thread would not have pointer (the OS
thread ID is 0 for the main thread). You can use GeIsMainThread() to check if you're in the main thread
at any time.Afaik (again), the BaseThread pointer is only passed so you can call TestBreak(). For instance, you
can tell the RenderDocument() function by returning True from your own C4DThread::TestDBreak()
implementation and passing the C4DThread's BaseThread pointer to the RenderDocument()
function.I've never tried to use BaseThread::TestBreak() from Execute(), maybe that returns True already
if ESC is pressed or something like that.Best,
-Niklas -
On 10/10/2014 at 06:45, xxxxxxxx wrote:
Thanks Niklas. And again right, it's definetly not the main thread (just checked with GeIsMainThread). Also I found the threading information in the docs stating that SceneHookData::Execute is indeed called in a threaded context and probably that's not necessarily the main thread. Makes sense.
Furthermore it seems the TestBreak call does not crash now anymore! Re-run several times now without a crash triggering so I guess that solved that issue already (so glad!).
In my own threads (executed within Execute of the scene hook) I override TestDBreak and that's also where I am calling GetInputState checking for a the ESC key (always triggering a break...very annoying! :). I guess I could pass the bt to the thread class and simply check for a break with it as bt->TestBreak does indeed work when the user hits ESC (if I remember correctly).
At the beginning of the Execute however I also need the left mouse button so I kind of don't get around using GetInputState. Is there an alternative to it? (though I surely can outcomment it for debugging purposes with a preprocessor directive)
-
On 10/10/2014 at 06:45, xxxxxxxx wrote:
Niklas is right (of course I might add).
The first breakpoint is triggered, because GetInputState() is called from a thread. -
On 10/10/2014 at 06:49, xxxxxxxx wrote:
Thanks Andreas for confirming. I guess if there is no alternative I will go with my _DEBUG preprocessor solution to avoid the break points.
-
On 10/10/2014 at 06:51, xxxxxxxx wrote:
I've noted two things for SDK Docs:
- a hint on internal breakpoint for using wrong datatype functions for a certain ID
- some more explanation on threading, the dos and don'ts, plus info on the threadcontext PluginStart gets called inKatachi, do you mind, marking this as solved?
-
On 10/10/2014 at 06:55, xxxxxxxx wrote:
Thanks both of you and yep, consider it solved!
-
On 10/10/2014 at 09:45, xxxxxxxx wrote:
Glad I could help.
@Andreas: good to read you're taking notes on things to be added to the documentation!
Originally posted by xxxxxxxx
so I kind of don't get around using GetInputState. Is there an alternative to it? (though I surely can outcomment it for debugging purposes with a preprocessor directive)
Maybe you can get this data from the main thread (eg. in a MessageData plugin) and request it
from a scene hook.I did not try to compile this code, it is completely from scratch! Just to give you an idea of
what I'm talking about. It might need to a bit of performance adjusting, like "only re-get the
input state if at least 200 milliseconds passed since the last time the state was retreived".Edit : AAAAaaaand you should probably add a lock/semaphore to the InputStateData structure, or
return a copy of the data from GetRecentInputState().>
> /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> /// RecentInputState.h
> /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>
> #include "c4d.h"
> #pragma once
>
> struct InputStateData
> {
> Int32 timestamp; // current timestamp returned by GeGetMilliSeconds();
> BaseContainer bc; // filled by GetInputState();
> InputStateData() : timestamp(-1), bc() { }
> };
>
> const InputStateData* GetRecentInputState(Int32 pluginid);
> Bool RegisterRecentInputStateHook(Int32 pluginid, Int32 askdevice, Int32 askchannel);
>
> /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> /// RecentInputState.cpp
> /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>
> #include "RecentInputState.h"
>
> #include "c4d.h"
> #include "HashMap.h"
>
> class InputStateHook;
> static maxon::HashMap<Int32, InputStateHook*> g_map;
>
> class InputStateHook : public MessageData
> {
> public:
> InputStateHook(Int32 askdevice, Int32 askchannel);
> virtual const InputStateData* GetData() const;
> virtual Bool CoreMessage(Int32 id, const BaseContainer& msg) override;
> private:
> Int32 _askdevice, _askchannel;
> InputStateData _data;
> };
>
> InputStateHook::InputStateHook(Int32 askdevice, Int32 askchannel)
> : _askdevice(askdevice), _askchannel(askchannel)
> {
> }
>
> Bool InputStateHook::CoreMessage(Int32 id, const BaseContainer& msg)
> {
> if (GetInputState(_askdevice, _askchannel, _data.bc))
> {
> _data.timestamp = GeGetMilliSeconds();
> }
> return true;
> }
>
> const InputStateData* InputStateHook::GetData() const
> {
> if (_data.timestamp > 0)
> return &_data;
> else
> return nullptr;
> }
>
> static const InputStateHook* GetRecentInputState(Int32 pluginid)
> {
> maxon::HashMap<Int32, InputStateHook*>::Entry* entry = g_map.FindEntry(pluginid);
> if (entry && entry->GetValue())
> {
> InputStateHook* hook = entry->GetValue();
> return hook->GetData();
> }
> return nullptr;
> }
>
> Bool RegisterRecentInputStateHook(Int32 pluginid, Int32 askdevice, Int32 askchannel)
> {
> InputStateHook* hook = NewObj(InputStateHook, askdevice, askchannel);
> if (hook)
> {
> String name = "InputStateHook:" + String::IntToString(askdevice) +
> String::IntToString(askchannel);
> Bool success = RegisterMessagePlugin(pluginid, name, 0, hook);
> if (success)
> g_map.Put(pluginid, hook);
> return success;
> }
> return false;
> }Best,
-Niklas -
On 10/10/2014 at 10:02, xxxxxxxx wrote:
Hey Niklas, thanks. That's quite a clever workaround idea!