Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login
    1. Maxon Developers Forum
    2. Havremunken
    3. Posts
    H
    • Profile
    • Following 0
    • Followers 0
    • Topics 8
    • Posts 46
    • Best 6
    • Controversial 0
    • Groups 0

    Posts made by Havremunken

    • RE: Plugin does not appear in Expression on client's Cinema 4D

      One thing you could do is run a utility like procmon: https://learn.microsoft.com/en-us/sysinternals/downloads/procmon

      This will let you see what a process accesses on the file system, among other things. Hopefully it will also show you which paths are searched for these libraries, allowing you to identify how to get them in the right location for your customer. 🙂

      posted in Cinema 4D SDK
      H
      Havremunken
    • RE: Plugin does not appear in Expression on client's Cinema 4D

      I believe what Ferdinand means is that what is typical for dynamic linking means you need to include libcurl.dll and libcrypto-3-x64.dll with the distribution of your plugin. When Cinema 4D tries to initialize your plugin, it will in turn try to open these to use code from them.

      I would assume that you have them on your system, which is why it works there but not for the customer. 🙂

      posted in Cinema 4D SDK
      H
      Havremunken
    • RE: Plugin does not appear in Expression on client's Cinema 4D

      I can relate to the problem, even if I never experienced this in a Cinema 4D context. I don't know of course the technical level of your customer, but something that hopefully they are able to handle is the console inside of C4D. You can print to that using ApplicationOutput("Some string"); - would it be an idea to compile a debug version for the customer, putting ApplicationOutput statements at various init points in the plugin, and see if these messages show up for them? Unfortunately I don't have the knowledge to look deeper at this myself.

      posted in Cinema 4D SDK
      H
      Havremunken
    • RE: Plugin does not appear in Expression on client's Cinema 4D

      I am not qualified to help you, but do you have any logging in your plugin? If not, could you add it? Logging either to Cinema 4D or to your own log file, it would be interesting to see if your main file is started, if your plugin registration is executed etc. The screenshot seems to be from Windows, and as long as you have SDK compatibility with the C4D version the user has, I would think that C4D at least should make an attempt at loading it. Logging would hopefully let you find out.

      Unfortunately I am not near my C4D machine for many hours so I can't test your plugin at the moment.

      posted in Cinema 4D SDK
      H
      Havremunken
    • RE: How to store "cached" data in the document from the scenehook?

      Hi Ferdinand,

      Yes, I remember reading about that, so the IDs for this container data is 5060 and 5061 (I work in IP telephony as my day job so this is surely no coincidence), but I even tried to move them to 50060 and 50061 and the freeze still happens.

      I will pack up the project shortly and email it in. 🙂

      posted in Cinema 4D SDK
      H
      Havremunken
    • RE: How to store "cached" data in the document from the scenehook?

      Hi @ferdinand,

      First, thanks once more! I loved the more general example you made, but since it showed how to store full "Cinema 4D objects" into the branch and not my simplistic data needs (just two strings), I had to make some assumptions about how to do things. Once more you showed me they were bad assumptions to make. 🙂

      About the CopyTo, I do get the reasons, and I had actually implemented it, but it was also implemented based on the bad assumptions, so I am rewriting it as well. And as for the 0xFFF.. thing I realised of course that this "magic" value of all bits set was not happening by accident, I just could not tell how it happened. But since this happened as another consequence of my poor assumptions about how to implement data storage in a branch, I'll ignore it for now. If it is still there after the code is fixed, then perhaps it is relevant to look at again.

      Your new code example above does shed a lot more light and give me an expanded understanding of how this should work, but like the story where you always go 50% of the remaining distance to the goal, I feel like I am SO close but never getting all the way there. I am sure there are only details missing however. 🙂

      I updated my Read and Write as you instructed, and I abandoned creating all the UrlCacheAssetData nodes manually (I don't want to be a bad citizen after all). So I aim for your point number 3 to store my two strings per node. While it would be fun to do like in the second half of your example and store it in a cube, I used the first part to create the BaseList2D, get the data instance, and then set the strings. I am still registering ID_MORPHINETABLE_URLCACHE_ASSETNODE using RegisterNodePlugin - as an experiment I tried not registering it at all, but then BaseList2D::Alloc(ID_MORPHINETABLE_URLCACHE_ASSETNODE) returned a nullptr which I guess is to be expected. When it is registered I get a real object (e.g. not nullptr), and I also get a not-nullptr when I do asset->GetDataInstance(). However, when I then do data->SetString(ID_MORPHINETABLE_URL, task->url); Cinema 4D completely freezes. The only thing I can really do at that point is to Shift-F5 to stop the Visual Studio debugging session. Edit: This happens when I set the data, i.e. when the user changes the URL parameter in my plugin and the scene hook has loaded the URL contents. So this happens before the whole GetBranchInfo / Read / Write process.

      Could this be because RegisterNodePlugin is the wrong registration method for my asset container? And since in this case I only really need the BaseContainer of the thing to store the two things, how elaborate does the UrlCacheAssetData class really need to be? What you are allocating in your (untested and uncompiled) example is just a BaseList2D, but do I need to make a subclass of that in order to give it the ID_MORPHINETABLE_URLCACHE_ASSETNODE id so I can identify it in my branch for reading and writing? Edit: When I step through in the debugger, the BaseList2D::Alloc() does not invoke my UrlCachetAssetData::Alloc static function as I suspected, which is why I am wondering what role the UrlCacheAssetData class REALLY plays in this scenario beyond registering "something" with the ID_MORPHINETABLE_URLCACHE_ASSETNODE node.

      I am of course also open to the SetString freeze happening for an entirely different reason, but since I don't know how much my UrlCacheAssetData (inheriting from NodeData) implementation matters when we are creating a BaseList2D with its' ID like you are showing, it seems likely that this is another thing I screwed up.

      I will happily pack up the project again if this is impossible to solve without seeing full source. Is my project subdirectory enough, or would you like the whole sdk directory to be able to reproduce 100% what I am seeing?

      Thanks again, and have a great weekend when the time comes!

      posted in Cinema 4D SDK
      H
      Havremunken
    • RE: How to store "cached" data in the document from the scenehook?

      Hi Ferdinand,

      I have worked on fitting your example into my project. As you know, there are two major differences that I needed to account for; first, I am doing this in a Scene Hook, and second, I am not keeping Cinema 4D primitives in my BranchInfo, I am keeping URLs and their contents. So I had to adapt.

      First I implemented GetBranchInfo in my scene hook. It is more or less a copy of yours.

      maxon::Result<Bool> GetBranchInfo(const GeListNode* node, const maxon::ValueReceiver<const BranchInfo&>& info, GETBRANCHINFO flags) const override
      {
      	iferr_scope;
      	yield_scope;
      
      	NodeData::GetBranchInfo (node, info, flags) yield_return;
      
      	if (!(flags & GETBRANCHINFO::ONLYWITHCHILDREN) || _assetHead->GetFirst())
      	{
      		info (
      			BranchInfo{
      				MAXON_REMOVE_CONST (this)->_assetHead,
      				"clever.unique.name.changed.to.protect.the.innocent"_s,
      				ID_MORPHINETABLE_URLCACHE_ASSETNODE,
      				BRANCHINFOFLAGS::NONE
      			}) yield_return;
      	}
      
      	return true;
      }
      

      This will come into play a little later.

      In my scenehook I also implemented the Read, Write and CopyTo (I understand how these go together, but will CopyTo ever really be used in a scene hook? I placed a breakpoint in the function and it didn't get called yet).

      First of all; Since I need something to store my data in, I decided on creating a NodeData subclass like this - the simplest implementation I could imagine getting away with:

      class UrlCacheAssetData : public NodeData
      {
      	INSTANCEOF (UrlCacheAssetData, NodeData)
      
      private:
      	maxon::String _url;
      	maxon::String _data;
      
      public:
      	static NodeData* Alloc()
      	{
      		return NewObjClear (UrlCacheAssetData);
      	}
      
      	static Bool RegisterAssetDataPlugin()
      	{
      		return RegisterNodePlugin (ID_MORPHINETABLE_URLCACHE_ASSETNODE, "UrlCacheAssetDataPlugin"_s,
      		                           PLUGINFLAG_SMALLNODE, UrlCacheAssetData::Alloc, nullptr, 0, nullptr);
      	}
      
      	void SetData(String url, String data)
      	{
      		_url = url;
      		_data = data;
      	}
      
      	String GetUrl() const
      	{
      		return _url;
      	}
      
      	String GetData() const
      	{
      		return _data;
      	}
      };
      

      So when the user enters a new URL into my plugin, I have added code to add a new asset as such:

      auto node = AllocSmallListNode (ID_MORPHINETABLE_URLCACHE_ASSETNODE);
      auto const assetData = node->GetNodeData<UrlCacheAssetData>();
      if (assetData != nullptr)
      {
      	assetData->SetData (*task->url, loadedData);
      	_assetHead->InsertLast (node);
      	_currentCacheSize++;
      }
      

      _assetHead is declared the same way you did in your example. _currentCacheSize is a running count of the number of asset nodes we have.

      Ok, time to save a document (with a plugin that has added at least one item in the cache). Here is my Write implementation for the scene hook:

      Bool Write(const GeListNode* node, HyperFile* hf) const override
      {
      	if (!_assetHead || !hf)
      		return false;
      
      	if (!hf->WriteInt32 (_currentCacheSize))
      		return false;
      
      	auto current = _assetHead->GetFirst();
      	while (current)
      	{
      		auto const assetData = current->GetNodeData<UrlCacheAssetData>();
      		if (assetData != nullptr)
      		{
      			if (!hf->WriteString (assetData->GetUrl()))
      				return false;
      			if (!hf->WriteString (assetData->GetData()))
      				return false;
      		}
      		current = current->GetNext();
      	}
      	return SceneHookData::Write (node, hf);
      }
      

      As you see, my thought is that I first write an integer saying how many url/content pairs I have, then I loop through the asset nodes and write them to the file. I couldn't think of another way to do this, as I do not have the luxury of dealing with objects that already have the WriteObject() functions implemented. I am of course expecting that my way is not the optimal way, or even correct. 🙂

      I step through it using the debugger and all seems to work the way I expect. Ok, I close the file and then try to reopen it using C4D.

      Here is my Read implementation:

      Bool Read(GeListNode* node, HyperFile* hf, Int32 level) override
      {
      	SUPER::Read (node, hf, level);
      
      	iferr_scope_handler
      	{
      		return false;
      	};
      
      	if (!hf || !_assetHead)
      		return false;
      	_assetHead->FlushAll();
      
      	if (!hf->ReadInt32 (&_currentCacheSize))
      		return false;
      
      	for (auto i = 0; i < _currentCacheSize; i++)
      	{
      		auto newNode = AllocSmallListNode (ID_MORPHINETABLE_URLCACHE_ASSETNODE);
      		auto const assetData = newNode->GetNodeData<UrlCacheAssetData>();
      		if (assetData != nullptr)
      		{
      			String url;
      			if (!hf->ReadString (&url))
      				return false;
      			String data;
      			if (!hf->ReadString (&data))
      				return false;
      			assetData->SetData (url, data);
      			_assetHead->InsertLast (newNode);
      		}
      	}
      
      	return true;
      }
      

      I step through it using the debugger and again it works as expected; I read the integer specifying the number of cache items, then loop through that amount of times to read the items. The items are read successfully, containing the expected data! Amazing!

      However, at some point after my Read method is exited, I get a crash. This crash happens while Cinema is executing my GetBranchInfo() code above, specifically the info(...) yield return part. At this point it gets a little difficult for me to look into. I understand that a value is pointing to the wrong place, with a very suspicious value (the "opposite" of a null pointer, so to speak), but I can't tell where this value is coming from.

      Exception details:

      Exception thrown at 0x00007FF8E8427C10 (c4d_base.xdl64) in Cinema 4D.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.
      

      This is refering to a location in delegate.h in the SDK where the following code can be seen:

      //----------------------------------------------------------------------------------------
      /// Forwards the call (invokes the stub function for a callable).
      //----------------------------------------------------------------------------------------
      MAXON_ATTRIBUTE_FORCE_INLINE RESULT operator ()(ARGS... args) const
      {
      	StubPtrType stub = StubPtrType(_stubPtr);
      #ifdef PRIVATE_MAXON_MTABLE_PTMF
      	return (reinterpret_cast<Delegate*>(_objectPtr)->*stub)(std::forward<ARGS>(args)...);
      #else
      	return stub(_objectPtr, std::forward<ARGS>(args)...);
      #endif
      }
      

      Line 761-772 in my 2024 SDK. I don't know where exactly the 0xFFF... is coming from but it is not the stub/_stubPtr and the exception happens in the line with the reinterpret_cast.

      The call stack does not tell me a lot apart from this happening while Cinema is running my GetBranchInfo:
      2971ec64-f0ee-4fac-bc0b-9fed1123f3f0-image.png

      I realize of course that debugging this based on a forum post is hopeless - unless the 0xFFFF... value could be caused by only one very well known thing, I expect you would need my complete code for this? It changed quite a bit since last time.

      I am quite sure that there is something that is not properly initialized or something along those lines, since this happens only when I try to open a document saved with my branch info in it. Oh, and for completeness, my asset head is declared as a private instance variable in my scene hook like this:

      AutoAlloc<GeListHead> _assetHead;
      

      And I also borrowed from your init code and put it in the same class.

      Bool Init(GeListNode* node, Bool isCloneInit) override
      {
      	if (!_assetHead)
      		return false;
      
      	_assetHead->SetParent (node);
      
      	return SUPER::Init (node, isCloneInit);
      }
      
      

      If you want me to send you the code, just let me know. If you want me to change or test anything else, the same. And if I am completely off track with my asset implementation, doing something that couldn't possibly work - please don't be afraid to tell me. I'm a big boy, I can take it. 😁

      Thanks again!

      posted in Cinema 4D SDK
      H
      Havremunken
    • RE: How to store "cached" data in the document from the scenehook?

      "Thank you" seems poor and inadequate for that fantastic example, but I don't have the English vocabulary to go beyond that!

      I have read through the example once, and I think I understand it. Since this has been a real Monday (tm), I'm going to let this simmer in the brain for a day or two, and then use the techniques you demonstrate to add GetBranchInfo etc. to my scene hook. Both the example and the video were great at explaining the steps needed to get "extra" information into the document, and are much appreciated!

      So while it does not express the full extent of my gratitude, once again - thank you!

      posted in Cinema 4D SDK
      H
      Havremunken
    • RE: How to store "cached" data in the document from the scenehook?

      Thank you so much, Ferdinand, I look forward to that! And enjoy the well-deserved weekend in the mean time! 🙂

      posted in Cinema 4D SDK
      H
      Havremunken
    • RE: How to store "cached" data in the document from the scenehook?

      This is perhaps not a big deal, but while implementing this, I met some resistance from Visual Studio while overriding GetBranchInfo in my scene hook. It did not match the signature from your example. Ok, so detective time - my scene hook inherits from SceneHookData, which has no GetBranchInfo of its own, this comes from it inheriting from NodeData, and this class does have a GetBranchInfo. However, the signature does not match entirely. I am on 2024 still, just in case this changed for 2025. This is the signature:

      virtual maxon::Result<Bool> GetBranchInfo(const GeListNode* node, const maxon::ValueReceiver<const BranchInfo&>& info, GETBRANCHINFO flags) const;

      Ok, sligtly different, but... It is supposed to return a bool? Ok, that is a bit confusing, in your example you returned the number of elements we filled in. Ok, let me look at the docs in the source file (c4d_nodedata.h):

      /// @return The number of BranchInfo elements filled in the @formatParam{info} array.

      Ok, that is clear as mud. 😏 So I am not supposed to return a number, then, but just true if I actually put something in there? How does it learn the number of items, or doesn't it need to?

      A minor point is that in your code example (in your first post) you write it as FlowTag::GetBranchInfo - I guess I can safely assume this was copied from another source example where a FlowTag class was implemented, so the name "FlowTag" has no meaning in this case?

      From your example I get the sense that the MyAssetData is created in a way where one instance of the class represents one piece of data. In my case, my variant of this asset node would contain one URL and one content string. Then I use the list starting with the AssetHead to store each url+content combo I have in my cache, is this correct? So my version of AddAsset would take these two as params?

      I am also trying to understand the choice to "feed" the asset object by sending it a message, instead of for instance calling Load directly. Is this because when you BaseList2D::Alloc(Tassetnode); you don't actually get direct access to the instance of the MyAssetData class itself, so we're in the Data Layer instead of in the Logic Layer, and have to use this mechanism?

      Hopefully final question in this round (at least I'm not one of the many spammers that keep trying their luck on the forum, huh?): When I create an object that causes some data to be cached using this system, and save the C4D file, then later reopen it - I understand that C4D reads this data from the file, and I imagine that the searching lambda in your GetAssetHead is what locates this again the first time it is called (when _assetHead is not already set). Fairly soon after opening the file, C4D will call GetVirtualObjects on my main plugin, and it will ask the scene hook for the data - am I correct in assuming that this would be when the scene hook calls GetAssetHead(), reads all the MyAssetData (or whatever I end up calling them) nodes, and finally has his cache so he can return data to the generator plugin?

      I hope these questions are not too annoying, I am just trying to understand the code rather than just copy & paste it (or feed it to an AI). 🙂

      Thanks!

      posted in Cinema 4D SDK
      H
      Havremunken
    • RE: How to store "cached" data in the document from the scenehook?

      Hi Ferdinand,

      Thank you again! I see I misunderstood the point of the alloc parameter, as I was also missing the connection between the scene hook (owner of the branch I guess) and the asset nodes making up the branch. I love the explanation of the different layers as an added bonus. 🙂

      posted in Cinema 4D SDK
      H
      Havremunken
    • RE: How to store "cached" data in the document from the scenehook?

      Hi Ferdinand,

      I got sidetracked from implementing this, but back at it now. I think I have it figured out in my head, and my plan is basically in my asset Write method to write an int saying how many "cache items" I have, and then a pair of strings with the URL and the content for each of them.

      But one question I just wanted to clarify - in your code above, in the Scene Hook part of it, you have the AddAsset method, and in it you allocate a new asset object... I presume? You write:

      BaseList2D* asset = BaseList2D::Alloc(Tassetnode);

      Am I correct in assuming that this should have been something like

      BaseList2D* asset = BaseList2D::Alloc(MyAssetData);

      Since I am supposed to allocate a new asset object, and not a new... int? 🙂
      Asking just because I couldn't see the connection where MyAssetData was actually connected to the Tassetnode.

      posted in Cinema 4D SDK
      H
      Havremunken
    • RE: How to get FONT information and use it to create text objects in C++?

      I can confirm that you were right (nothing unexpected there!) - this is the second time in a couple of weeks where casting has bit me in the behind. I guess I was too spoiled by C# and need to keep my head turned on in the future..

      For anyone from the future reading this: The problem with the code above was READING the value, not WRITING it back to the object. That part was ok. Either passing on for instance op as a parameter or using Get() (if you're on the right object) to get at it is the right move.

      Thanks again!

      posted in Cinema 4D SDK
      H
      Havremunken
    • RE: How to get FONT information and use it to create text objects in C++?

      Hi Ferdinand,

      Thanks for getting back to me. I'll change the reinterpret_cast - to be honest that was suggested by ReSharper (an addon for Visual Studio) as an "improvement" to my old C-style (BaseObject*) cast, so I just went with it. This call was in a method on the plugin object called by GetVirtualObjects that didn't have the BaseObject* as a param, that is why I tried a quick and dirty way to access the BaseContainer.

      None of the code above is production code, of course, just an experiment to see if I could set the font. And the BaseContainer for the cellObj was given the PRIM_TEXT_FONT after running this code. And just for completeness, this didn't crash Cinema 4D. But that is perhaps because I am running it in the debugger in the first place. 🙂

      I will rearchitect a bit and clean it up, hopefully that should make the text object accept the new font settings.

      posted in Cinema 4D SDK
      H
      Havremunken
    • RE: How to get FONT information and use it to create text objects in C++?

      Ok, I tested the "better route" one to see if I could do it. I inserted the following code right after cellObj has been created (BaseObject::Alloc(Osplinetext)).

      // Start experiment
      
      auto obj = reinterpret_cast<BaseObject*> (this);
      if (obj != nullptr)
      {
      	GeData copy;
      	if (!obj->GetParameter (ConstDescID (DescLevel(C2T_FONT)), copy, DESCFLAGS_GET::NONE))
      		ApplicationOutput ("Could not GetParameter from 'us' object.@");
      	if (!cellObj->SetParameter (ConstDescID (DescLevel(PRIM_TEXT_FONT)), copy, DESCFLAGS_SET::NONE))
      		ApplicationOutput ("Could not SetParameter to cellObj.@");
      }
      
      GeData numbah;
      numbah.SetFloat (50);
      cellObj->SetParameter (ConstDescID(DescLevel(PRIM_TEXT_HEIGHT)), numbah, DESCFLAGS_SET::NONE);
      
      // End experiment
      

      The thing with setting the smaller height towards the end is to verify that the code is being run. It is (the produced text objects are 1/4 the size of the default 200 height), the ApplicationOutputs don't trigger so both GetParameter and SetParameter succeeds as such (and I have verified in the debugger that the code is going through the "happy path", executing what I want). However the generated text stays in the default font.

      Is PRIM_TEXT_FONT the wrong parameter to set? Or am I misunderstanding some other fundamental thing here?

      I tried looking into the BaseContainer of the created cellObj, and it does contain a parameter with ID 2117, which corresponds to PRIM_TEXT_FONT, so it IS there, leading me to wonder if I am setting the wrong thing.

      Any insights welcome, thanks!

      posted in Cinema 4D SDK
      H
      Havremunken
    • RE: How to get FONT information and use it to create text objects in C++?

      Thanks, Ferdinand! This removes most of my need for depending on references to other text objects to allow the user to customize font properties. I'll dive into this and verify that I can get this to work once I get in front of my C4D computer later today!

      posted in Cinema 4D SDK
      H
      Havremunken
    • RE: How to get FONT information and use it to create text objects in C++?

      Hi Ferdinand, and thanks for your reply. I am 100% sure you hit the nail on the head in point 2. 🙂 But let me reply by points.

      1. Thanks for the input. In the fullness of time all the text splines will be put under an extrude object anyway, but you are of course right that using a text spline object will make it easier to change later. I aim to make it beneficial for a user of my plugin to keep it procedural as long as possible, but of course you have a valid point that you never know when the user will suddenly decide to press C. 🙂

      2. This looks like exactly what I was looking for. Does this mean I can do this in two simple steps like myPluginsBaseContainer->GetData(C2T_FONT) and then newTextSplineObjectsBaseContainer->SetData(PRIM_TEXT_FONT) without doing a roundtrip through the FontData stuff? I.e. it doesn't matter what "shape" the font data is in, using GetData and SetData like this should just copy it correctly across to the new object? Or would I still need to roundtrip with GetFont and SetFont here?

      3. Thanks for the information. This could become useful for me as I need to calculate the "x-height" (literally the height of the lower case x) of fonts for layout purposes and to know where to put the baseline of text. In theory this could mean that the user ends up with many different fonts that needs to be aligned (and by aligned, I mean placed vertically in a manner that gives the least amount of "that looks wrong"). Having to calculate this for what could easily be a hundered or more text object is a waste, so I may want to "cache" that by checking if I already calculated the x-height for this combination of font and size already. In that case getting enough information about the font to uniquely identify it could mean that FontData.GetFont and understanding the data it contains would be useful.

      posted in Cinema 4D SDK
      H
      Havremunken
    • How to get FONT information and use it to create text objects in C++?

      Hi,
      I will try to explain just enough but not too much what I need this time. 🙂
      In my classic API ObjectData generator plugin I have a font setting + height. There are more settings in real life, but they are not relevant for this example.

      CONTAINER Otestobject
      {
      	NAME Otestobject;
      	INCLUDE Obase;
      
      	GROUP ID_OBJECTPROPERTIES
      	{
      		FONT C2T_FONT { OPEN; }
      		REAL C2T_FONT_HEIGHT	{ UNIT METER; }
      	}
      }
      

      C2T_FONT is defined to be 1006, if it matters, and the height one 1007.
      In the GetVirtualObjects method for this generator plugin, I create text objects. Right now I do one of the following:

      1. Clone a Text Spline object.
      2. Clone a MoGraph Text object.
      3. Create a new Osplinetext object in code.

      For this purpose I will focus on #3, as I am moving in that direction. For the future, I am also considering going a bit lower level and deleting 1 and 2, and replacing 3 with using GenerateText() to create the text splines directly instead of cloning an object.

      My question is simply - how can I take the font information that the user has configured in the Attribute Manager for my object and use it in the creation of the text object when

      1. I am creating a new Osplinetext object like BaseObject::Alloc (Osplinetext);
      2. Using the BaseObjects' GenerateText() function.

      I am assuming both these methods of creating a text spline would need the same kind of parameters, but I have had a hard time finding out from the documentation how I am supposed to "feed" them the settings in order to get it right.

      Thanks for any insights!

      posted in Cinema 4D SDK c++
      H
      Havremunken
    • RE: How to store "cached" data in the document from the scenehook?

      Hi Ferdinand, and thanks for all the fish! 🙂

      No worries about the psuedo code, this is precisely what I needed to understand what I need to implement in order to store my data with the document. I am going to try to write this into my project, and will of course return soon if something happens that I can't figure out.

      Again, many thanks!

      posted in Cinema 4D SDK
      H
      Havremunken
    • How to store "cached" data in the document from the scenehook?

      Hey - this is probably most directly directed to Ferdinand, as it is based on something he mentioned in another thread a while ago.
      In a code snippet, the following is explained:

      This is the 'bad' way to solve this, it would be better to store the downloaded assets in the scene graph via NodeData::GetBranchInfo, but that would be another support cases to flesh that out.
      

      This refers to a maxon::HashMap<const maxon::Url, const BaseObject*> data variable used as an in-memory cache of downloaded data. Like we discussed in the thread, perhaps one day it would be good to store the downloaded data with the document. One example could be that the object is created on a machine with Internet access, then needs to be worked on in a machine that doesn't. Or the user just wants to make sure they have the version of the url content that was current when the file was originally made.

      So this is the "another support case to flesh that out" - I have searched, but not found a clear example of what I have to implement in my scene hook to write this cache along with the document file when the user saves, and then automatically load it back in when the document is reopened.

      For what it is worth, my current implementation of the scenehook stores the data in the HashMap as described.

      Is there an example available on how to include this data into the document on disk? The reason the data is stored in a HashMap is that it contains a mapping of URLs to content, where the content is just a string with the data returned from the web server / file system.

      Thanks for any insights!

      posted in Cinema 4D SDK c++
      H
      Havremunken