Group Details Private

Global Moderators

Forum wide moderators

  • RE: Cannot write specific values to UVWTag

    It's actually due to a lower number of bits used to store the floating value.

    posted in Cinema 4D Development
  • RE: Custom FIELDLAYER_CHANNELFLAG

    @mikeudin said in Custom FIELDLAYER_CHANNELFLAG:

    We need use different values, which user can disable/enable as color, value, direction and rotation native field flags.
    In other words, we need to change several plugin parameters using only one FieldList. So instead color, value, direction and rotation flags we need something like value1, value2, value3 flags.

    Hi @mikeudin
    Unfortunately, there is no way to add additional channels to the overall field system, only the pre-build one can be used.
    So if you have 3 values, you will need 3 fieldList.

    posted in Cinema 4D Development
  • RE: Python NODES - Shouldn't really they can change the scene?

    @SolarPH said in Python NODES - Shouldn't really they can change the scene?:

    Also, Anyone know how to extract Thread Name? Or if possible, a list of Thread ID with their thread name would be useful.

    The Cinema 4d SDK offers no way to retrieve a list of all running threads, and thread doesn't have a name.

    Also, I wonder if procesisng the threads can have a delay using a timer thing...

    I'm not sure to understand what do you mean. In Python and in general, the SDK offers no means to interact with other threads.

    In the end, the only proper way is to create a MessageData plugin to react to a Core Event and do the stuff within this MessageData plugin.

    Cheers,
    Maxime.

    posted in Cinema 4D Development
  • RE: unresolved external symbol "void __cdecl maxon::_ConsoleOutputC4D when compiling under R19.

    Looking at the doc in R19:

    5fdf5fb0-1327-4589-b6b6-d68af8869c11-image.png
    821d97fa-e103-4cca-84b1-85f0f50304f0-image.png

    So I'm afraid there is no simple solution that will work on each version maxon::String being introduced in R20, you will need to adapt your code.

    Cheers,
    Maxime.

    posted in Cinema 4D Development
  • RE: Need Help Debugging EXC_BAD_ACCESS error during render

    Hi @JuicyJuggles , I apologize for coming late here but luckly you've been already provided in the meanwhile of some good guidance from @PluginStudent and @zipit .

    Rest assured that the API documentation is, by far, the best place where to look for answers although I can see that, due to huge number of covered topics, it could take time to get used to browse it effectively.

    Last but not least, if the issue is addressed, don't forget to mark the right post as correct answer or if it's not possible to identify a specific one, to set the whole topic as Solved

    Cheers, Riccardo

    posted in Cinema 4D Development
  • RE: Python NODES - Shouldn't really they can change the scene?

    An express tag is a tag, and it evaluation takes place as any other tag, meaning it has the same limitation as a Python Scripting Tag.

    @SolarPH said in Python NODES - Shouldn't really they can change the scene?:

    I've set all of those outside Execute method to ensure that it wouldn't loop infinitely. I often connect it to an if/else statement (connected to a boolean/integer switch that switches itself off after the first cycle) to ensure that it wouldn't make Cinema4D crash.

    I'm not sure to follow you here but since you modify the scene content while the scene execution (aka xpresso execution) then it can affect the stability, and it does not matter if it's executed once or 100 times, so you may run into a conflict with another part of the scene while this other part is accessed by something else, and you have a crash.

    make sure to call StopAllThread, but you can even call EventAdd

    I actually haven't tested StopAllThread line yet, but I can already use EventAdd() after any commands that changes the scene in terms of heirarchy and inserted objects. I haven't really tested doing a delete command, but I have some ways to let the code know what to delete after the cycle. Utilizng ports as a way to actually pass the correct object data on the code makes it easier for me to execute this kinds of codes on my python tags.

    I was speaking if you are in the main thread, which is not the case here because you are in a tag execution, so if you call StopAllThread within your thread, your thread will be canceled (due to the nature of python, your python code may execute completely but not the other part of the xpresso evaluation)

    Also, According to the online manual about python codes for cinema4d (official documentation), for example, I do

    c4d.documents.MergeDocument(doc,Path,c4d.SCENEFILTER_OBJECTS|c4d.SCENEFILTER_MATERIALS,None)
    

    will make it run on Main C4D Thread (i don't actually know if not putting the None at the end of the code makes it run on another thread, but when I tried, it doesn't actually crash C4D since the line only runs once because of the nature of the switch I used)

    Passing None in the MergeDocument will not make it run into the main thread, you just pass the thread you are currently in, and it will be this thread that will be tested if you should leave or not, but it does not modify where the code is executed. So calling MergeDocument is not fine because, in the end, you modify the current document especially if there are some materials. And this could make Cinema 4D Crash since a lot of stuff happens during a merge.

    Cheers,
    Maxime.

    posted in Cinema 4D Development
  • RE: Set Track Data Method?

    Hi, I can confirm there is no way exposed to 3rd party developers to set manually the 2D/3D track Data.

    Cheers,
    Maxime.

    posted in Cinema 4D Development
  • RE: Cannot write specific values to UVWTag

    Hi @C4DS, thanks for reaching out us.

    With regard to your issue, I confirm that, by design, the values stored in UVWTag are rounded to 8 significant digits.

    Best, R

    posted in Cinema 4D Development
  • RE: Avoid: IsActive()

    This does not solve your initial issue since it requires the use of GetItemDim and it was introduced in R18 but here is how to avoid your second issue:

    import c4d
    
    class Dialog(c4d.gui.GeDialog):
        
        def CreateLayout(self):
            bc = c4d.BaseContainer()
            bc.SetBool(c4d.BITMAPBUTTON_BUTTON, True)
            bc.SetInt32(c4d.BITMAPBUTTON_ICONID1, c4d.Ocube)
            bc.SetInt32(c4d.BITMAPBUTTON_FORCE_SIZE, 32)
            button = self.AddCustomGui(10003, c4d.CUSTOMGUI_BITMAPBUTTON, "but", c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 40, 40, bc)
            button.SetCommandDragId(c4d.Ocube)
            self.AddStaticText(10001, 0, 0, name="test")
            return True
    
        def IsPositionOnGadget(self, gadgetId, x, y):
            # Be sure that the windows is opened,
            # in our case since we call it in BFM_INTERACTSTART it's ok
            buttonData = self.GetItemDim(gadgetId)
            
            if not buttonData["x"] < x < buttonData["x"] + buttonData["w"]:
                return False
    
            if not buttonData["y"] < y < buttonData["y"] + buttonData["h"]:
                return False
    
            return True
    
        def Message(self, msg, result):
            # Main thread
            if msg.GetId() == c4d.BFM_INTERACTSTART:
                c4d.StopAllThreads()
    
                # Check the mouse is clicked
                state = c4d.BaseContainer()
                self.GetInputState(c4d.BFM_INPUT_MOUSE, c4d.BFM_INPUT_MOUSERIGHT, state)
    
                if state.GetInt32(c4d.BFM_INPUT_CHANNEL) != 0:
    
                    # Get coordinates
                    x = state.GetInt32(c4d.BFM_INPUT_X)
                    y = state.GetInt32(c4d.BFM_INPUT_Y)
                    g2l  = self.Global2Local() 
                    x += g2l['x']  
                    y += g2l['y']
    
                    # Checks the coordinate is within the range of the BitmapButton
                    if self.IsPositionOnGadget(10003, x, y):
                        print 'Icon clicked in the GeDialog.'
    
                        # Stop others event to be processed
                        self.KillEvents()
                        return True
                    
            return c4d.gui.GeDialog.Message(self, msg, result)
    
    # Main function
    def main():
        global dlg
        dlg = Dialog()
        dlg.Open(c4d.DLG_TYPE_ASYNC)
    
    # Execute main()
    if __name__=='__main__':
        main()
    

    Note that there is a very similar problem Disable default Right-Click Menu that you may found interesting about how to handle popup in your dialog.

    And adding this constraint in mind, I'm afraid I don't see any solution to make it work before R18.
    Cheers,
    Maxime.

    posted in Cinema 4D Development
  • RE: Update button

    Hi @pyxelrigger thanks for reaching us, the main issue is to properly update you need to send the message MSG_DESCRIPTION_COMMAND and this is what the UI, it set the parameter then call this message.

    But adding this call in the execute method of the python tag is not enough.
    This message is processed by the constraint tag and add an Undo, and as said multiple time, this is not possible to add an undo in a threaded environment(see Python Tags - Shouldn't really they can change the scene? so this fail.

    So the workaround is to not call the message during the scene execution of the scene but when the value is set in the user Data, so you react to a GUI interaction (main thread) so you are free to do what you want.

    import c4d
    #Welcome to the world of Python
    
    def message(msgId, msgData):
        # React to the change within the UI, since it came from the UI, this is executed in the Main Thread, so you can add Undo or Add Event
        if msgId == c4d.MSG_DESCRIPTION_POSTSETPARAMETER:
            # Check if its an User Data ID
            if msgData['descid'].IsPartOf(c4d.DESCID_DYNAMICSUB):
                # Checks if its the User Data ID 1 that changed
                if msgData['descid'][-1].id == 1:
                    constraintTag = op.GetObject().GetTag(1019364)
    
                    # This will update the stuff and create an Undo
                    constraintTag.Message(c4d.MSG_DESCRIPTION_COMMAND, {"id": c4d.ID_CA_CONSTRAINT_TAG_PARENT_LOCALTRANFORM_UPDATEBUTTON})
                    c4d.EventAdd()
            return True
    
    def main():
        option = op[c4d.ID_USERDATA,1]
        constraintTag = op.GetObject().GetTag(1019364)
        # Defines the new value (We could do it as well in the message method, but just to show you that Execute is called before)
        constraintTag[c4d.ID_CA_CONSTRAINT_TAG_PARENT_LOCALTRANFORM_UPDATEBUTTON] = option + 1
    

    test_scene.c4d
    Cheers,
    Maxime.

    posted in Cinema 4D Development