Your browser does not seem to support JavaScript. As a result, your viewing experience will be diminished, and you have been placed in read-only mode.
Please download a browser that supports JavaScript, or enable it if it's disabled (i.e. NoScript).
Hi,
Not quite directly a revision of your code but this should help you get started.
import c4d from c4d import gui # Main function def main(): cloner = doc.SearchObject("Cloner") # Assuming there is already a Cloner Mograph Object plain_effector = doc.SearchObject("Plain")# Assuming there is already a Plain Effector Object effector_list = c4d.InExcludeData() effector_list.InsertObject(plain_effector, 1) cloner[c4d.ID_MG_MOTIONGENERATOR_EFFECTORLIST] = effector_list c4d.EventAdd() # Execute main() if __name__=='__main__': main()
Cinema4D can accommodate plug-ins written in C++ or Python. However, it only accept scripts written in Python.
Probably not that helpful but there is an existing script for the C4D OBJ Sequence Exporter https://richh.co/c4d-native-obj-sequence-export-no-plugins/
Hi @blieque
You can do is the Basic>Enable Checkbox in every object. If you drag it to the console, the parameter is [c4d.ID_BASEOBJECT_GENERATOR_FLAG]
[c4d.ID_BASEOBJECT_GENERATOR_FLAG]
Thanks Adam for the confirmation. I'll just send it for Maxon Suggestion for now.
Thanks!
Thanks @m_adam. Works as expected. My bad, I was looking at the documentation hierarchy erroneously (i.e c4d > modules > graphview > GvNode)
Just a note: I think the if Multiply: line is supposed to be if isMultiply:.
if Multiply:
if isMultiply:
Thanks again. Have a great day ahead!
Hi @m_adam
Thanks for the patience. Your suggestions and reminders works are greatly appreciated.
I guess the confusion stems mainly on my part because I posted slightly two different codes. You were responding to my initial post but I was thinking with the code from the succeeding post(the one in the rar file). Totally my bad.
Anyhow, here is the working code (using the initial post) which works as I expected:
import c4d class ColorButton(object): def __init__(self): self.width = None self.height = None self.color = None self.color = None self.btn_id = None self.menu_list = None def create(self, dlg, w, h, color, btn_id): self.width = w self.height = h self.color = color self.btn_id = btn_id bmp_color = c4d.bitmaps.BaseBitmap() bmp_color.Init(w, h) for y in xrange(w): for x in xrange(h): bmp_color.SetPixel(x, y, color[0], color[1], color[2]) bcBitmapButton = c4d.BaseContainer() bcBitmapButton[c4d.BITMAPBUTTON_BUTTON] = True bmp_btn = dlg.AddCustomGui(self.btn_id, c4d.CUSTOMGUI_BITMAPBUTTON, "", c4d.BFH_CENTER | c4d.BFV_CENTER, w, h, bcBitmapButton) bmp_btn.SetImage(bmp_color, True) def create_menu(self): self.menu = c4d.BaseContainer() for menu_item in self.menu_list: counter = 0 IDM_MENU = c4d.FIRST_POPUP_ID + counter self.menu.InsData(IDM_MENU, menu_item) counter += 1 class MyDialog(c4d.gui.GeDialog): def __init__(self): self.btn_id_list = [] self.class_btn_id_dict = {} def CreateLayout(self): red_button = ColorButton() red_button.create(self, w=50,h=50,color=(255,0,0), btn_id=6000) red_button.menu_list = ['Menu1', 'Menu2', 'Menu3'] self.btn_id_list.append(red_button.btn_id) self.class_btn_id_dict[6000] = red_button blue_button = ColorButton() blue_button.create(self, w=50,h=50,color=(0,0,255), btn_id=7000) blue_button.menu_list = ['Menu4', 'Menu5', 'Menu6', 'Menu7'] self.btn_id_list.append(blue_button.btn_id) self.class_btn_id_dict[7000] = blue_button green_button = ColorButton() green_button.create(self, w=50,h=50,color=(0,255,0), btn_id=8000) green_button.menu_list = ['Menu8', 'Menu9'] self.btn_id_list.append(green_button.btn_id) self.class_btn_id_dict[8000] = green_button 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 function_to_determine_gadgetId_under_mouse_cursor(self, x, y): for gadgetId in self.btn_id_list: if self.IsPositionOnGadget(gadgetId, x, y): return gadgetId def Message(self, msg, result): if msg.GetId() == c4d.BFM_ADJUSTSIZE: self._x = msg[3] # Retrieve Y size of the GeDialog self._y = msg[4] # Retrieve Y size of the GeDialog # We are on the main thread here elif msg.GetId() == c4d.BFM_INTERACTSTART: c4d.StopAllThreads() state = c4d.BaseContainer() self.GetInputState(c4d.BFM_INPUT_MOUSE, c4d.BFM_INPUT_MOUSERIGHT, state) if state.GetInt32(c4d.BFM_INPUT_VALUE) == True: x = state.GetInt32(c4d.BFM_INPUT_X) y = state.GetInt32(c4d.BFM_INPUT_Y) g2l = self.Global2Local() x += g2l['x'] y += g2l['y'] gadgetId = self.function_to_determine_gadgetId_under_mouse_cursor(x=x,y=y) if gadgetId in self.btn_id_list: if self.IsPositionOnGadget(gadgetId=gadgetId, x=x, y=y): button_class = self.class_btn_id_dict[gadgetId] button_class.create_menu() l2s = self.Local2Screen() print str(x+l2s['x']) + " :: " + str(y+l2s['y']) self.KillEvents() res = c4d.gui.ShowPopupDialog(cd=self, bc=button_class.menu, x=x+l2s['x'], y=y+l2s['y']) return True return c4d.gui.GeDialog.Message(self, msg, result) if __name__ == "__main__": dlg = MyDialog() dlg.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=20304050)
@r_gigante
Thanks for the reference. For anyone trying to achieve the same, here is a sample file. https://www.dropbox.com/sh/z1lzyphp8qnt9kw/AAB2P5gNo16IHafgc6xPEsy4a?dl=0
Thanks again for @zipit for the help.
@m_magalhaes @zipit
I managed to flip the mesh (not necessarily a pose morph target since I'd have to know the API). Anyhow, here is a demo of it working: https://www.dropbox.com/s/bh4p26s4m9qwljw/c4d272_flip_miror_mesh.mp4?dl=0
Here is wip script. It only works if the x-axis is dead set on 0. Also, it is slow since it has to loop within a loop.
import c4d from c4d import gui # Main function def main(): neutral_geo = doc.SearchObject('neutral_geo') posed_geo = doc.SearchObject('posed_geo') neutral_world_matrix = neutral_geo.GetMg() posed_world_matrix = posed_geo.GetMg() neut_lcl_pnts = neutral_geo.GetAllPoints() neut_gbl_pnts = [point * neutral_world_matrix for point in neut_lcl_pnts] posed_lcl_pnts = posed_geo.GetAllPoints() posed_gbl_pnts = [point * posed_world_matrix for point in posed_lcl_pnts] match_pnts = [] left_pnts = [] right_pnts = [] for idx, point in enumerate(neut_gbl_pnts): if point[0] == 0.0: # ignore points at the world x axis continue if point[0] > 0.0: left_pnts.append((idx,point)) if point[0] < 0.0: right_pnts.append((idx,point)) for left in left_pnts: for right in right_pnts: if left[1][1] == right[1][1]: # check if Y pos match if left[1][2] == right[1][2]: # check if Z pos match if left[1][0] == -1 * (right[1][0]):# check if X pos are inverse match_pnts.append((left[0],right[0])) for pnt in match_pnts: reversed_left = posed_lcl_pnts[pnt[1]] reversed_left[0] = reversed_left[0] * -1 reversed_right = posed_lcl_pnts[pnt[0]] reversed_right[0] = reversed_right[0] * -1 posed_geo.SetPoint(pnt[0], reversed_left) posed_geo.SetPoint(pnt[1], reversed_right) posed_geo.Message(c4d.MSG_UPDATE) c4d.EventAdd() # Execute main() if __name__=='__main__': main()
@m_adam
Thanks for the response.
RE: without enabling the Post Deformers option. It seems like so. I initially thought I could reverse engineer it by getting the point's skin influence (its joint and its weight) and in a way factor it with the intended world vector. However, I gave up since I realize point can have several joints and several weight. Haha
Don't get me wrong, enabling the post deformer works as expected. The problem comes because of its inherent nature "calculate the points position of the morph after they are deformed by a Deformer."
It presupposes that the (near) last deformation comes from the pose morph. For example, Squash/Stretch>Bulge>Bend>Twist>Pose Morph. However, there are cases where the intended deformation is Pose Morph>Squash/Stretch>Bulge>Bend>Twist.
So having the post deformer off while still getting the world position desired gives a bit of flexibility.
Anyhow, thanks again for the help. I'll just use the post deformer for now and see where I get stuck.
Have a great day ahead!
Is there a way of getting the panel type under cursor?
My use case is to have a different commands pop up in my plug-in depending on where the cursor is under.
For example, if its on the viewport, create primitive objects if its on the object manager, create light objects.
I know the example is crude but something like that.
Kindly ignore.
Found the solution. It would be doc.GetActiveBaseDraw() Then the related parameters are [c4d.BASEDRAW_DATA_PLANE_LEGACY_MODE] [c4d.BASEDRAW_DATA_SNAP_PLANE_SPACING] [c4d.BASEDRAW_DATA_SNAP_PLANE_SUB]
doc.GetActiveBaseDraw()
[c4d.BASEDRAW_DATA_PLANE_LEGACY_MODE]
[c4d.BASEDRAW_DATA_SNAP_PLANE_SPACING]
[c4d.BASEDRAW_DATA_SNAP_PLANE_SUB]
Is there a way to access the world grid options in R25+?
By default it is not in UI. But I'm guessing it is still there since when I open an old project to R25. It recognizes the world grid options (i.e. the gird does not go infinitely).
See reference below for R21 UI option
Is there a custom drag and drop to viewport functionality in redshift?
For example, by default, if you drag file named, "dragme.txt" to viewport. It will error out (i.e. unknown format).
I was wondering if there is a way to preprocess this. So if I drag a "dragme.txt" in the viewport, I want to create a primitive box, etc.
Is this possible?
Kindly ignore. Adrian from Redshift forum answered it.
You can look into the rslight.h from Plugins\C4D\R26\Redshift\res\description, all the parms are there
I'm trying to use the gr4phos RS Light Lister (https://github.com/gr4ph0s/c4d_redshift_light_lister) but its giving me error such as
AttributeError: module 'c4d' has no attribute 'REDSHIFT_LIGHT_AFFECTS_DIFFUSE'
I'm guessing the attribute is just renamed.
I tried searching in the documentation but it gives me material related redshift.
So I want to list all the attributes in C4D relating to Redshift and just eyeball what is the equivalent of REDSHIFT_LIGHT_AFFECTS_DIFFUSE.
Hi @ferdinand
RE: Please note that this is not a commitment of us to do this regularly . . I understand. Thanks for the detailed explanation and background theory for the answer.
Have a nice ahead! Will close this thread now.
RE: import struct I'm guessing this is the built-in struct library and not the maxon.Struct?
RE: /88 Is there a documentation on the list of parameters? I'm guess 88 is referring the particle number? Would be nice to have a list of them for reference like the PSR.
I understand there is a documentation about particles but there is no sample code so I'm a bit lost on how to use it.
https://developers.maxon.net/docs/Cinema4DPythonSDK/html/modules/c4d.modules/particles/index.html?highlight=emitter
https://developers.maxon.net/docs/Cinema4DPythonSDK/html/modules/c4d.modules/particles/Particle/index.html?highlight=emitter
Is there a way I can retrieve the Emitter's number of particles (with their corresponding PSR) at a given frame using expresso?
I tried dragging the emitter to the xpresso editor but I couldn't see such data but I could be wrong.
Regards, Ben
P.S. I'm referring to the emitter object and not the thinking particles.