Navigation

    • Register
    • Login
    • Search
    1. Home
    2. fwilleke80
    fwilleke80

    Frank Willeke

    @fwilleke80

    Software Engineer

    32
    Reputation
    433
    Posts
    344
    Profile views
    0
    Followers
    0
    Following
    Joined Last Online
    Website www.frankwilleke.de Location Berlin Age 43

    • Profile
    • More
      • Following
      • Followers
      • Topics
      • Posts
      • Best
      • Groups
    fwilleke80 Follow

    Best posts made by fwilleke80

    RE: Best way to update objects after preference change?

    Oh wait, I think I found a way. In case anybody else wants to know, here it is...

    In the PrefsDialogObject:

    Bool MyPrefsDialog::SetDParameter(GeListNode *node, const DescID &id,const GeData &t_data,DESCFLAGS_SET &flags)
    {
    	BaseContainer* bc = MyPlugin::GetPreferences();
    	if (!bc)
    		SUPER::SetDParameter(node, id, t_data, flags);
    	
    	switch (id[0].id)
    	{
    		// If PREFS_MYPLUGIN_SOMEVALUE was changed, store value and notify plugin objects in all open documents.
    		case PREFS_MYPLUGIN_SOMEVALUE:
    			bc->SetInt32(PREFS_MYPLUGIN_SOMEVALUE, t_data.GetInt32());
    			flags |= DESCFLAGS_SET::PARAM_SET;
    			
    			// Iterate open documents
    			for (BaseDocument *doc = GetFirstDocument(); doc; doc = doc->GetNext())
    			{
    				// Send broadcast message to each document, use unique ID
    				doc->MultiMessage(MULTIMSG_ROUTE::BROADCAST, MyPlugin::UNIQUE_ID_PREFS, nullptr);
    			}
    			
    			GeUpdateUI();
    			return true;
    	}
    	
    	return SUPER::SetDParameter(node, id, t_data, flags);
    }
    

    And then, in the plugin object:

    Bool MyPluginObject::Message(GeListNode *node, Int32 type, void *data)
    {
    	if (type == MyPlugin::UNIQUE_ID_PREFS)
    	{
    		GePrint("Aha! My prefs have changed!"_s);
    		return true;
    	}
    	return SUPER::Message(node, type, data);
    }
    
    posted in Cinema 4D SDK •
    RE: Python Source Protector: Can it be called via CLI?

    And in deed, having the option of executing the source protector using a command line argument for Cinema 4D, or using c4dpy would be great for integration in a plugin build pipeline.

    posted in Cinema 4D SDK •
    RE: Custom Tokens with Team Render Server

    Hi,
    I'll just chime in here, as I'm involved in that project, too.

    So the token hook needs to access certain elements of the scene to get their values, and the problem (thankfully) is easily reproducible.

    I wrote a sample plugin that recreates the behaviour by simply returning data from the first object in the scene. Download it from our dropbox: tokenhookbug.zip

    Here is the code:
    tokenhookbug_code.png

    This is the render setting in my example scene (which just contains a Cube):
    tokenhookbug_rendersetting.png

    Here is the render result in the Picture Viewer, notice the correct file name:
    tokenhookbug_result_pv.png

    Uploading and rendering the file on TeamRender produces this:
    tokenhookbug_result_tr.png

    The debugger clearly shows that doc->GetFirstObject() returns nullptr.

    Cheers,
    Frank

    posted in Cinema 4D SDK •
    RE: Shader that gets data from an object: Refresh

    It works like a charm!
    Thank you again!

    I was surprised at how little code was required.

    Sharing is caring. In case anyone needs it, here's the code:

    #include "ge_prepass.h"
    #include "c4d_general.h"
    #include "c4d_baselinkarray.h"
    #include "c4d_basedocument.h"
    
    ///
    /// \brief Registers observers and sends messages to them.
    ///
    class Observable
    {
    public:
    	///
    	/// \brief Subscribes a new observer.
    	///
    	/// \param[in] observer Pointer to an AtomGoal
    	/// \param[in] doc The document that owns the AtomGoal
    	///
    	/// \return A maxon error object if anything went wrong, otherwise maxon::OK
    	///
    	maxon::Result<void> Subscribe(C4DAtomGoal *observer, BaseDocument *doc);
    		
    	///
    	/// \brief Unsubscribes an observer
    	///
    	/// \param[in] observer Pointer to an AtomGoal that has previously been subscribed
    	/// \param[in] doc The document that owns the AtomGoal
    	///
    	void Unsubscribe(C4DAtomGoal *observer, BaseDocument *doc);
    		
    	///
    	/// \brief Sends a messages to all subscribed observers
    	///
    	/// \param[in] type Message type
    	/// \param[in] doc The document that owns the subscribed observers
    	/// \param[in] data Optional message data
    	///
    	void Message(Int32 type, BaseDocument *doc, void *data = nullptr) const;
    
    private:
    	BaseLinkArray _observers;
    };
    
    maxon::Result<void> Observable::Subscribe(C4DAtomGoal *observer, BaseDocument *doc)
    {
    	if (!observer)
    		return maxon::NullptrError(MAXON_SOURCE_LOCATION, "Observer must not be nullptr!"_s);
    
    	// Check if this observer is already registered
    	const Int32 observerIndex = _observers.Find(observer, doc);
    	if (observerIndex != NOTOK)
    		return maxon::OK;
    
    	// Register new observer
    	if (!_observers.Append(observer))
    	{
    		return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION, "Failed to add observer to the list!"_s);
    	}
    
    	return maxon::OK;
    }
    
    void Observable::Unsubscribe(C4DAtomGoal *observer, BaseDocument *doc)
    {
    	if (observer && doc)
    	{
    		const Int32 observerIndex = _observers.Find(observer, doc);
    		if (observerIndex != NOTOK)
    		{
    			_observers.Remove(observerIndex);
    		}
    	}
    }
    
    void Observable::Message(Int32 type, BaseDocument *doc, void *data) const
    {
    	for (Int32 i = 0; i < _observers.GetCount(); ++i)
    	{
    		C4DAtomGoal *atom = _observers.GetIndex(i, doc);
    		if (atom)
    		{
    			atom->Message(type, data);
    		}
    	}
    }
    
    posted in Cinema 4D SDK •
    RE: Dynamic elements in a CYCLE, CYCLE empty after loading document?

    Hi Adam, happy new year to you, too!

    Since it works now, for some reason, I am pretty happy with what I have. However, since it might interest other plugin developers, I'll share more code. Maybe you have some tipps about improvements or potentially dangerous stuff, too.

    The idea is that the shader has a LINK field where the user can link an object (which is also part of my plugin). The object can (but doesn't have to) provide a list of "custom outputs" that will be added to the shader's CYCLE. In the screenshot below it's the "Difference Map".

    When a rendering is started, the shader will request the according data from the linked object during InitRender(). But that's not part of this thread ;-)

    Screenshot 2021-01-26 at 11.42.45.png

    The shader's GetDDescription():

    Bool TerrainOperatorShader::GetDDescription(GeListNode *node, Description *description, DESCFLAGS_DESC &flags)
    {
    	iferr_scope_handler
    	{
    		GePrint(err.GetMessage());
    		return false;
    	};
    
    	if (!description->LoadDescription(node->GetType()))
    		return false;
    	flags |= DESCFLAGS_DESC::LOADED;
    
    	BaseDocument* doc = node->GetDocument();
    	const BaseContainer& dataRef = static_cast<BaseShader*>(node)->GetDataInstanceRef();
    	
    	// Hide or show attributes, depending on shader mode
    	const Bool slopeMode = dataRef.GetInt32(XTERRAINOPERATORSHADER_DATA) == XTERRAINOPERATORSHADER_DATA_SLOPE;
    	TF4D::GUI::ShowDescription(node, description, XTERRAINOPERATORSHADER_SLOPE_DIRECTION_ENABLE, slopeMode);
    	TF4D::GUI::ShowDescription(node, description, XTERRAINOPERATORSHADER_SLOPE_DIRECTION, slopeMode);
    
    	// Get linked object
    	BaseObject *linkedObject = dataRef.GetObjectLink(XTERRAINOPERATORSHADER_OPERATORLINK, doc);
    	if (linkedObject)
    	{
    		// Get linked object's NodeData
    		TF4D::BaseTerrainOperatorData* linkedOperator = linkedObject->GetNodeData<TF4D::BaseTerrainOperatorData>();
    
    		// Get list of custom outputs (these are the elements to add to the CYCLE)
    		maxon::BaseArray<TF4D::GUI::CycleElementData> customOutputs;
    		if (linkedOperator->GetCustomOperatorOutputs(customOutputs))
    		{
    			if (!TF4D::GUI::AddCycleElements(node, description, XTERRAINOPERATORSHADER_DATA, customOutputs, true))
    				iferr_throw(maxon::UnexpectedError(MAXON_SOURCE_LOCATION, "Could not add LONG CYCLE elements!"_s));
    		}
    	}
    
    	return SUPER::GetDDescription(node, description, flags);
    }
    

    The linked object's NodeData's GetCustomOperatorOutputs():

    Bool ErosionOperator::GetCustomOperatorOutputs(maxon::BaseArray<TF4D::GUI::CycleElementData>& customOperatorOutputs) const
    {
    	iferr_scope_handler
    	{
    		GePrint(err.GetMessage());
    		return false;
    	};
    
    	customOperatorOutputs.Reset();
    
    	// GetCustomOutputName() simply returns a maxon::String
    	customOperatorOutputs.Append(TF4D::GUI::CycleElementData(TF4D_CUSTOMOUTPUT_EROSION_DIFFERENCE, GetCustomOutputName(TF4D_CUSTOMOUTPUT_EROSION_DIFFERENCE))) iferr_return;
    
    	return true;
    }
    

    Cheers,
    Frank

    Ah, damn. Now I've spoiled that I'm working on erosion for Terraform4D :D

    posted in Cinema 4D SDK •
    RE: PySide2 Integration

    Why don't you avoid all those difficulties and simply implement that dialog using the C4D UI?

    posted in General Talk •
    RE: Save node data in Read and Write

    If you're storing data in the tag's BaseContainer, you don't need to override Write() and Read(). That's meant for private class member whose data would be lost otherwise.

    Also, you can remove the "return true" at the end of the functions. As you already return in the previous line, it will never be called.

    posted in Cinema 4D SDK •
    RE: Type Viewer not working in Visual Studio 2015

    I did today, including it in projectdefinition.txt worked smoothly, thank you!
    If I ever find out why copying it do the folders does not work, I'll post it here.

    posted in Cinema 4D SDK •
    RE: Threading & job questions

    Oh my god. the stupidest error.... :dizzy_face:
    OK, question 1 solved already, thanks :grin:

    posted in Cinema 4D SDK •
    RE: Creating and saving a 32bit grayscale bitmap

    Ah, great, thank for checking!
    Then I don't need to worry about my bmp code :-)

    Cheers,
    Frank

    posted in Cinema 4D SDK •

    Latest posts made by fwilleke80

    RE: Can't debug C4D 2023 and 2024 on macOS

    @ferdinand said in Can't debug C4D 2023 and 2024 on macOS:

    first, thank you very much for investing more time into this and with that saving time for me, truly appreciated.

    You're welcome. If any of this get any of us further it's worth the time.

    @ferdinand said in Can't debug C4D 2023 and 2024 on macOS:

    But let us discuss the details per mail.

    Okay!

    Cheers,
    Frank

    posted in Cinema 4D SDK •
    RE: Can't debug C4D 2023 and 2024 on macOS

    Well, well, well, there we have it. It's a Redshift issue! After removing the Redshift .xlib files from /corelibs and /Redshift, most of the error messages are gone, and so is the crash. Tested in C4D 2023.2.

    Screenshot 2023-09-22 at 11.18.36.jpg

    posted in Cinema 4D SDK •
    RE: How to get OutLine of Polygon object

    Another idea: You could also use some primitive way to render an object mask (e.g. white object on black background), and then run an edge recognition kernel on the resulting image.

    posted in General Talk •
    RE: Can't debug C4D 2023 and 2024 on macOS

    Redshift sure complains a lot in the debug console.

    Should I try and remove redshift.xlib from C4D 2023 and see if that changes anything?

    posted in Cinema 4D SDK •
    RE: Can't debug C4D 2023 and 2024 on macOS

    Follow-up: C4D 2024 (latest release, just downloaded from Maxon website)

    Tried on the same system as before: 2019 MacBook Pro, Xcode 13.2.1 using legacy build system, macOS Monterey 12.6.8.

    Screenshot 2023-09-22 at 11.06.40.jpg

    posted in Cinema 4D SDK •
    RE: Can't debug C4D 2023 and 2024 on macOS

    Thank you :-)

    posted in Cinema 4D SDK •
    RE: Can't debug C4D 2023 and 2024 on macOS

    That made no difference at all :-(
    Exactly the same error with legacy build system.

    I also tried in both versions of C4D 2023: 2023.1.3 and 2023.2. Both exactly the same.

    The release build freezes from time to time, too, in about the same moment that the debug build always crashes.

    Built with Xcode 13.2.1 on macOS Monterey 12.6.8 on my 2019 MacBook Pro.

    posted in Cinema 4D SDK •
    RE: Can't debug C4D 2023 and 2024 on macOS

    It is mysterious.

    @ferdinand said in Can't debug C4D 2023 on macOS:

    But you are running things with the so-called legacy build system, right? I know that you are an experienced developer, but if you have somehow managed to get the SDK with the new build system going, all sorts of weird errors are to be expected.

    Ah, that could be it. Because I did manage to get it to build with the new system. Hang on, I'll try with the legacy system.

    posted in Cinema 4D SDK •
    RE: R23 Monterey SDK compile errors

    Which exact Code version is it? I remember I couldn't use any Xcode version later than 13.2.1. Any more recent version would throw countless errors.

    posted in Cinema 4D SDK •
    Can't debug C4D 2023 and 2024 on macOS

    Hi,

    here's a problem that occurs on both my Mac machines (2019 MacBook Pro, 2019 iMac), on macOS Big Sur and Monterey, and in Xcode 12 and 13 alike. It also happens with C4D 2024 (though the error message might look different, if necessary I can add a screenshot of that, too).

    Screenshot 2023-09-22 at 08.06.53.jpg

    It happens early on in the debug session, before the C4D GUI even shows up. And it also happens with the cinema4dsdk project, without any of my plugins being present. Running Cinema 4D without attaching a debugger works as expected. Running a Release build without the debugger attached works as expected, however, running a Debug build without the debugger freezes after the GUI has appeared.

    It never happens on Windows (not even in Boot Camp on the iMac), and it also doesn't happen with R25 and earlier versions.

    What could it be?

    Cheers,
    Frank

    posted in Cinema 4D SDK •