Hi Ilia,
Thank you very much, I was not aware of that!
Cheers!
Hi Ilia,
Thank you very much, I was not aware of that!
Cheers!
Hello,
I am running the following code to create a vertex map tag on an object (targetObject is a sphere BaseObject every time I call the function):
# Make object editable
res = c4d.utils.SendModelingCommand(
command = c4d.MCOMMAND_MAKEEDITABLE,
list = [targetObject],
mode = c4d.MODELINGCOMMANDMODE_ALL,
doc = doc )
if res is False or res is True:
raise TypeError()
elif isinstance( res, list ):
doc.InsertObject( res[0] )
vertexMapTag = res[0].GetTag( c4d.Tvertexmap )
if vertexMapTag is None:
vertexMapTag = c4d.BaseTag( c4d.Tvertexmap )
vertexMapTag[c4d.ID_TAGFIELD_ENABLE] = True
vertexMapTag[c4d.ID_TAGFIELD_INVERT] = False
vertexMapTag[c4d.ID_TAGFIELD_DEFORMED] = False
res[0].InsertTag( vertexMapTag )
c4d.EventAdd()
After running this I get a sphere with a UVW tag and a vertex map tag, as intended. However, when I select the sphere and select the paint tool, I get the following error:
What is causing the tag to not be in sync?
Thank you for your help,
Daniel
Hey Ferdinand, thanks again for the quick reply.
What we're going to do is basically have a "cache" location, as you said, where we will save the users' textures when they bake the stack. I would also prefer the approach you showed using the document's asset repository, but since the textures might be very heavy, it would probably lead to very large document sizes for a lot of users, especially if they use several textures/have several stacks with textures. I'm working on implementing solution 1.1, using the Message system to move things around. However, thank you very much for the code example, I will probably use something similar with other assets that are not as large as textures.
Cheers,
Daniel
Hi Ferdinand and Maxime,
I think I was unclear when asking the last question, my bad. I get that the issue would be that we would essentially have a Filename
that does not resolve if the image was in working memory (using a RamDisk
or a MemoryFileStruct
) and then shut down and re-launched Cinema 4D. I was originally wondering if we could trigger a function (probably using the modifier Message
function) when saving the scene to save the image on the physical disk at that point, and change the Filename
in the shader accordingly. However we've decided not to try putting the image in memory at all, and directly save it to the disk. I'll try to explain what we're trying to achieve so the situation is a bit clearer, I would love your input on this.
We currently have an object consisting of a stack that performs computations. We are implementing functionality so that the entire stack can be baked into a single object, which helps speed up computations. The collapse is reversible, so we want the user to be able to "unbake" the object. We also want the user to be able to save the stack to the physical disk as a "baked" object. If one of the objects in the stack (let's call it object A) uses a texture, we save the texture as an image with the baked object. We essentially serialize the image and use it in the calculations, then save it to the physical disk. However, if the user "unbakes" the object, we need to take the serialized image and generate a texture for object A to use. The texture could be an image found on the disk, a gradient created in C4D, some procedurally generated image, etc.
What we are currently considering is to simply save the texture as an image at the moment that the stack is baked, and use a Filename
pointing to it if the stack is unbaked. However, if the scene had not been saved before, we would have to create the image as a temp file and copy it to wherever the scene is saved on the disk afterwards. Is there something I might be missing in the Cinema 4D SDK that could improve this approach, or even be a better way to handle the situation?
Thanks a lot for the help,
Daniel
Hi Ferdinand,
Thank you very much for the answer! Don't worry about it, I was also dealing with other tasks in the interim. The volatility might be an issue, we might have to write manual code to save scenes if necessary. That would just involve saving the image file somewhere on the actual disk and changing the where the shader points to, right?
Thank you for the example, I'll work on implementing something similar in our code and get back to you if anything comes up.
Cheers,
Daniel
Hi @m_adam,
I've been trying to use a RamDiskInterface
to store the images I need in memory, but I can't see a way to create a file using it. I can see the CreateLazyFile method, but that's not available before C4D 2024, and I need support back to R25. I am looking into MemoryFileStruct and it seems promising, I was just wondering if the RamDiskInterface
is preferred when creating multiple files in memory.
Cheers,
Daniel Bauer
Hi Maxime,
Thank you very much for the answer! Sorry I haven't responded in a while, some other issues came up. I'll try using the method you mentioned, the image structure should not be a problem because we save images already generated in Cinema 4D. I'll get back to you once I get a chance to implement it.
Thanks again,
Daniel
Hi,
In our plugin we generate images which we would like to use as texture maps in our modifiers. I've been following the BaseShader
manual and can see that I can create a Bitmap Shader and populate the bitmap with a file:
// configure the bitmap shader and the material
bitmapShader>SetParameter(ConstDescID(DescLevel(BITMAPSHADER_FILENAME)), imageFile, DESCFLAGS_SET::NONE);
(This is from the C4D documentation). I was wondering if it's possible to populate the BaseShader
bitmap without saving the image to the disk.
Thank you very much,
Daniel
Hi Maxime, thank you very much for your answer! I wasn't sure if storing things in the global document BaseContainer was a good approach, but it's working well.
Cheers,
Daniel
Hello,
I have a command plugin that inherits from CommandData, defined and registered in C++. I am trying to create a Python script which calls this command plugin, but I want to pass data to it so it can use that data in its Execute()
function. I can modify the class in C++ if necessary. Can I do this in Python? I know I can pass data using the Message()
function, but have not found a way to use that from Python.
Thank you for the help,
Daniel
Hi @ferdinand,
Thank you so much for the comprehensive reply! Given all this I don't think it would make sense to keep trying to unit test this particular part of our code with Python. The last approach you highlighted with testing directly on the C++ side seems like the best option, so I'll give that a try. I'll have to see how to integrate this test with the rest of the unit tests (we have a lot and they're all in Python) but hopefully that won't be too much of a problem.
Thanks again for all the help,
Daniel
Hi Ferdinand, thank you for the answer.
The reason we are trying to simulate mouse input is to create some unit tests in Python for our tool, which inherits from DescriptionToolData
(the tool itself is implemented in C++). We override MouseInput() and manipulate geometry within that function, and that is exactly what we need to create a few unit tests for. If we cannot set the position of the mouse cursor or control drag events I will have to think of another way.
The other approach that occurred to me is to create a special case within Message() only for debugging, and run the necessary functions with pre-set mouse positions. Is there any way to get the tool using the Python API in such a way that we can call the Message() override?
Have a great day,
Daniel
Hi,
I am currently trying to simulate mouse movement using the Python SDK. I can select the tool I want to use, but I have not found a way to simulate the mouse clicking on a screen position, dragging to a different position and letting go of the click. Is this at all possible using the Python API? I have tried calling the ToolData
MouseInput() function, but I can only get the tool as a BasePlugin
.
Thank you for the help,
Daniel
Hi @ferdinand and @Cairyn, thanks for the answers.
There may be a simpler way to achieve an effect similar to what we want (for example, by caching the world matrix at the time t
) but I'm still thinking of alternate ways to be able to access the full mesh information at time t
. Caching the full mesh is probably not a good option since we would have to update that cache every time the mesh is changed at any time before t
(since this might change the mesh at t
). A possible option is to restrict the usability a bit and always evaluate the mesh at time 0, I'm checking if this is something we can do.
Feedback loops could be an issue, but it should never happen that (using the example @ferdinand wrote) P relies on T and T also relies on P in this specific plugin. Also, t
should always be a time before the current time, although that might not alleviate this particular problem.
In any case, I'm going to go ahead and mark this as solved, I think I got all the information I need to find a solution.
Thank you both very much for helping me out,
Daniel
I might not have been clear in my previous post. The parameter is a BaseLink to a mesh, and that parameter is not animated. It should always be a link to the same BaseObject. The mesh itself has animated parameters, and I need to access the mesh object at a specified time t
. At the very least, I need to know its position, rotation and scale values at t
.
I have tried using CCurve.FindKey()
and CKey.GetGeData()
/CKey.GetValue()
to get the mesh position at t
, but the parameters in obase.h don't have tracks themselves. What I was wondering is if there is a way to get the world matrix of an object at time t
without using ExecutePasses()
.
Hi @ferdinand, thanks a lot for the answer.
The parameter I am trying to evaluate is actually a BaseLink
to a BaseObject
representing a mesh. As such, I cannot use the CCurve::GetValue
approach directly on the parameter. However, if possible I want to avoid running ExecutePass
, since this would probably be quite slow.
I realized I can solve my issue if I can get access to the world matrix of the mesh at the given time. Is there a way to get the interpolated world matrix at a specific time from a BaseObject
? If not, can I get the CTrack
associated with that world matrix? I could then interpolate the values between keys and use the resulting matrix. If neither of those is possible I will probably end up using ExecutePasses
.
Thanks again for the reply,
Daniel
Dear community,
What is a good way to evaluate a parameter value at a given frame from a threaded context?
I need to get the value of a parameter at a given time within the ModifyObject()
function of a class derived from ObjectData
. I need to do this when using bucket rendering. The required time is stored in a BaseTime
member. The solution I've found so far is to use ExecutePasses(bt, true, true, true, BUILDFLAGS::EXTERNALRENDERER)
. However, this causes issues because the ModifyObject()
function is called again. Additionally, I would like to avoid calculating the entire scene again. Is there a better way to do this?
On a related note, I get a debugbreak when calling ExecutePasses
, is this due to the way I'm calling it?
Thank you for your attention,
danniccs