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, I found the solution.
import urllib2 class Update(c4d.gui.GeDialog): UPDATE_BTN = 1000 PROGRESS = 1001 PROGRESSBAR = 1002 state = "" def CreateLayout(self) : self.AddButton(self.UPDATE_BTN, flags = c4d.BFH_LEFT, inith = 13, name = "Update") self.AddStaticText(self.PROGRESS, flags=c4d.BFH_SCALEFIT, initw=0, inith=0, name=self.state, borderstyle=0) # How to taking the percentage value from the function chunk_report() and apply it to the following CUSTOMGUI_PROGRESSBAR self.GroupBegin(id=0, flags=c4d.BFH_LEFT, cols=1, rows=0) self.GroupBorderNoTitle(c4d.BORDER_THIN_IN) self.AddCustomGui(self.PROGRESSBAR, c4d.CUSTOMGUI_PROGRESSBAR, "", c4d.BFH_SCALEFIT|c4d.BFV_SCALEFIT,200, 8) self.GroupEnd() def chunk_read(self, response, chunk_size=8192): total_size = response.info().getheader('Content-Length').strip() total_size = int(total_size) bytes_so_far = 0 progressMsg = c4d.BaseContainer(c4d.BFM_SETSTATUSBAR) progressMsg[c4d.BFM_STATUSBAR_PROGRESSON] = True while 1: chunk = response.read(chunk_size) bytes_so_far += len(chunk) if not chunk: break percent = float(bytes_so_far) / total_size percent = round(percent*100, 2) progressMsg[c4d.BFM_STATUSBAR_PROGRESS] = percent/100 self.SendMessage(self.PROGRESSBAR, progressMsg) self.SetString(self.PROGRESS, percent) def Command(self, id, msg): if id == self.UPDATE_BTN : filedata = urllib2.urlopen('https://www.domainname.com/file.zip') self.chunk_read(filedata)
@mfersaoui Hi, I found the following solution:
FileMenu = c4d.BaseContainer() resource = c4d.plugins.GeResource() resource.InitAsGlobal() FileMenu.InsData(c4d.MENURESOURCE_SUBTITLE, resource.LoadString(12587))
Hello,
Is it possible that a Dynamics Body Tag added to GVO object can be assigned to all the child virtual objects. like on Fracture Object with Explode Segments mode.
a code example and screenshot below:
import c4d, os from c4d import bitmaps, plugins class Object(plugins.ObjectData): def GetVirtualObjects(self, op, hh): dirty = op.CheckCache(hh) or op.IsDirty(c4d.DIRTY_MATRIX | c4d.DIRTY_DATA) if not dirty: return op.GetCache(hh) cloner = c4d.BaseObject(1018544) if cloner is None: return c4d.BaseObject(c4d.Onull) cube = c4d.BaseObject(c4d.Ocube) if cube is None: return c4d.BaseObject(c4d.Onull) cube[c4d.PRIM_CUBE_LEN] = c4d.Vector(20.0, 20.0, 20.0) cube.InsertUnder(cloner) return cloner if __name__ == "__main__": icon = bitmaps.BaseBitmap() icon.InitWith(os.path.join("res", "icons", "icon.tif")) plugins.RegisterObjectPlugin(1078197, 'Object', Object, 'Object', c4d.OBJECT_GENERATOR, icon)
Thanks.
Hi @m_adam, I found the solution below that allow to inject my custom menu just after the "IDM_SAVEALL" submenu of "File" menu, but the only problem now is with the following line: FileMenu.InsData(c4d.MENURESOURCE_SUBTITLE, "File")
FileMenu.InsData(c4d.MENURESOURCE_SUBTITLE, "File")
Because with this solution I must to rebuild all the "IDS_EDITOR_FILE" menu. and I'm searching how to grab the default sub-title of the "IDS_EDITOR_FILE" menu depending on the user interface language. So is there method to get the default subtitle of "IDS_EDITOR_FILE". Thanks.
import c4d, os, sys def GetMenuContainer(name): mainMenu = c4d.gui.GetMenuResource("M_EDITOR") customMenu = c4d.BaseContainer() for bcMenuId, bcMenu in mainMenu: if bcMenu[c4d.MENURESOURCE_SUBTITLE] == "IDS_EDITOR_FILE": customMenu = mainMenu.GetContainerInstance(bcMenuId) break if customMenu is not None: customMenu.FlushAll() def AddsMenuToC4DMenu(MenuContainer): MainMenu = c4d.gui.GetMenuResource("M_EDITOR") FileMenu = c4d.BaseContainer() FileMenu.InsData(c4d.MENURESOURCE_SUBTITLE, "File") for bcMenuId, bcMenu in MainMenu: if bcMenu[c4d.MENURESOURCE_SUBTITLE] == "IDS_EDITOR_FILE": for _bcMenuId, _bcMenu in bcMenu: if _bcMenu == "IDM_SAVEALL": cs_menu = c4d.BaseContainer() cs_menu.InsData(c4d.MENURESOURCE_SUBTITLE, "My Menu") cs_menu.InsData(c4d.MENURESOURCE_COMMAND, "PLUGIN_CMD_{}".format(menu_id1)) cs_menu.InsData(c4d.MENURESOURCE_COMMAND, "PLUGIN_CMD_{}".format(menu_id2)) cs_menu.InsData(c4d.MENURESOURCE_SEPERATOR, 1) # Append separator cs_menu.InsData(c4d.MENURESOURCE_COMMAND, "PLUGIN_CMD_{}".format(menu_id3)) FileMenu.InsData(1, cs_menu) FileMenu.InsData(c4d.MENURESOURCE_SEPERATOR, 1) FileMenu.InsData(_bcMenuId, _bcMenu) MainMenu.InsDataAfter(c4d.MENURESOURCE_STRING, FileMenu, MenuContainer) def PluginMessage(id, data): if id == c4d.C4DPL_BUILDMENU: MenuContainer = c4d.gui.SearchPluginMenuResource("IDS_EDITOR_FILE") AddsMenuToC4DMenu(MenuContainer) GetMenuContainer("IDS_EDITOR_FILE") c4d.gui.UpdateMenus()
Is it possible to placing a custom menu after specific submenu from the File menu, after the Save submenu for example .
The script bellow insert my custom menu at the bottom of the File menu:
def enhanceMainMenu(): mainMenu = c4d.gui.GetMenuResource("M_EDITOR") menu = c4d.BaseContainer() menu.InsData(c4d.MENURESOURCE_SUBTITLE, "Custom Menu") menu.InsData(c4d.MENURESOURCE_COMMAND, "PLUGIN_CMD_{}".format(ID_MENU_1)) menu.InsData(c4d.MENURESOURCE_COMMAND, "PLUGIN_CMD_{}".format(ID_MENU_2)) #menu.InsData(0, '') # Append separator menu.InsData(c4d.MENURESOURCE_COMMAND, "PLUGIN_CMD_{}".format(ID_MENU_3)) filemenue = mainMenu.GetData(1) filemenue.InsData(c4d.MENURESOURCE_SUBMENU, menu) mainMenu.SetData(1, filemenue) def PluginMessage(id, data): if id == c4d.C4DPL_BUILDMENU: enhanceMainMenu()
I have a plugin that contain multiple subplugins (.pyp files) and want to know how to insert my lib modules to the system path and that affect all the plugin .pyp files. (I have already seen the post: External dependencies: The right way to do and I did not find an answer concerning this point )
lib\n module1.py, module2.py, module3.py,... res\n <resource files> plugin_1.pyp plugin_2.pyp plugin_3.pyp ...
Must I use the "sys.path.inser()" method on each of my subplugins? I noticed that the subplugins is loaded one by one and in alphabetical order. so, for a test I created a new file and I rename it "a.pyp" (to be loaded in the first) and then I put inside it the following code:
import os import sys dirname = os.path.dirname(__file__) lib_path = os.path.join(dirname, 'lib') sys.path.insert(0, lib_path)
This it works, and affect all the .pyp files of my plugin.
Is there a right way to do that?
@mfersaoui said in TreeView Menu:
GroupBegin
For my second question I found this function to interact with the htmlViewer area.
c4d.SpecialEventAdd(ACTION_ID)
Hi @m_adam ,
Thank you so much, I have two questions:
The first is What the right way to rewriting the following code and obtain same result:
class ListView(c4d.gui.TreeViewFunctions): def __init__(self): self.listOfTexture = list() # Store all objects we need to display in this list
def CreateLayout(self): self.GroupBegin(0, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 2, 0) self.GroupBorderSpace(5, 5, 5, 5) self.GroupBegin(0, flags=c4d.BFH_LEFT | c4d.BFV_SCALEFIT, cols=1, rows=1, initw=400, inith=0) # Create the TreeView GUI. customgui = c4d.BaseContainer() customgui.SetBool(c4d.TREEVIEW_BORDER, c4d.BORDER_THIN_IN) customgui.SetBool(c4d.TREEVIEW_HAS_HEADER, False) # True if the tree view may have a header line. customgui.SetBool(c4d.TREEVIEW_HIDE_LINES, False) # True if no lines should be drawn. customgui.SetBool(c4d.TREEVIEW_MOVE_COLUMN, True) # True if the user can move the columns. customgui.SetBool(c4d.TREEVIEW_RESIZE_HEADER, True) # True if the column width can be changed by the user. customgui.SetBool(c4d.TREEVIEW_FIXED_LAYOUT, True) # True if all lines have the same height. customgui.SetBool(c4d.TREEVIEW_ALTERNATE_BG, False) # Alternate background per line. customgui.SetBool(c4d.TREEVIEW_CURSORKEYS, True) # True if cursor keys should be processed. customgui.SetBool(c4d.TREEVIEW_NOENTERRENAME, False) # Suppresses the rename popup when the user presses enter. customgui.SetBool(c4d.TREEVIEW_NO_MULTISELECT, True) self._treegui = self.AddCustomGui( 1000, c4d.CUSTOMGUI_TREEVIEW, "", c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 0, 0, customgui) if not self._treegui: print "[ERROR]: Could not create TreeView" return False self.GroupEnd() self.GroupBegin(0, flags=c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, cols=1, rows=1) html_file = "file.html" htmlViewer = self.AddCustomGui(1000001, c4d.CUSTOMGUI_HTMLVIEWER, "Viewer", c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 0, 0) htmlViewer.SetUrl(html_file, c4d.URL_ENCODING_UTF16) self.GroupEnd() return True def InitValues(self): # Initialize the column layout for the TreeView. layout = c4d.BaseContainer() layout.SetLong(ID_NAME, c4d.LV_TREE) self._treegui.SetLayout(1, layout) mdata = { "Menu 01": { "Item 01": ["sub-item 01", "sub-item 02", "sub-item 03"], "Item 02": ["sub-item 01", "sub-item 02"], "Item 03": [], }, "Menu 02": [], "Menu 03": ["sub-item 01", "sub-item 02"], "Menu 04": ["sub-item 01"] } res = [] for m in m_data: m1 = TextureObject(m) res.append(m1) m1_items = m_data[m] if len(m1_items): for m1_name in m1_items: m1_item = TextureObject(m1_name) m1.AddChild(m1_item) if isinstance(m1_items, dict): m2_items = m1_items[m1_name] if len(m2_items): for m2_name in m2_items: m2_item = TextureObject(m2_name) m1_item.AddChild(m2_item) self._listView.listOfTexture.extend(res) # Set TreeViewFunctions instance used by our CUSTOMGUI_TREEVIEW self._treegui.SetRoot(self._treegui, self._listView, None) return True
Result:
The second question is How to interact with the htmlViewer area at the right of dialog from the my TreeView menu (Changing the htmlViewer file when clicking on a menu items).
def Select(self, root, userdata, obj, mode): """ Called when the user selects an element. """ if mode == c4d.SELECTION_NEW: html_file = "file.html" #TestDialog() for tex in TextureObjectIterator(self.listOfTexture): tex.Deselect() obj.Select()
Thanks
Hello, Is there a TreeView example to create a similar tree view menu like as the Cinema 4D help dialog?
Hi @m_magalhaes,
I used your suggestion and I replaced the +=. Yes is better, but it's always the same problem. I don't know how to explain the problem, and for that reason I have created this plugin object example. So the best way to understand the problem is by testing the example.
+=
I will try to explain roughly the problem: The handle point is pinned on child object of the main object plugin and this child object has a dynamic (position and rotation) that depend on the Pitch & Rotation values. So I must to dynamically adapt the info.direction depending on the position and rotation of the child object. And concerning this thread, this helped me to control the Pitch and Rotation via Handle but not the (Width, Height and Depth) values (of child object).
info.direction
At the moment, I guess I'll just use the SwapPoint() it doesn't have a perfect result but it's acceptable.
SwapPoint()
Hi, @zipit
Yes I'm searching a solution. I tried your solution but this does not work. the problem is with the handle point that not moving correctly (check the screen video above)
I actually using the following method, but is too long and its works at 90%
def GetAxis(self, pitch, rot): pitch = int(math.degrees(pitch)) rot = int(math.degrees(rot)) if -90 <= rot < -45 or 225 <= rot < 270: if -45 <= pitch < 45: axis = 0 # +x elif -225 <= pitch < -135 or 135 <= pitch < 225: axis = 1 # -z elif -135 <= pitch < -45: axis = 3 # -y elif 45 <= pitch < 135 or -270 <= pitch < -225: axis = 2 # +y else: axis = 0 # +x elif -45 <= rot < 45: if -45 <= pitch < 45: axis = 4 # +z elif -225 <= pitch < -135 or 135 <= pitch < 225: axis = 5 # -z elif -135 <= pitch < -45: axis = 13 # -y elif 45 <= pitch < 135 or -270 <= pitch < -225: axis = 12 # +y else: axis = 4 # +z elif 45 <= rot < 135: if -45 <= pitch < 45 or -225 <= pitch < -46: axis = 11 # +x elif -225 <= pitch < -135 or 135 <= pitch < 225: axis = 10 # -z elif 135 <= pitch < -45: axis = 23 # -y elif 45 <= pitch < 135 or -270 <= pitch < -225: axis = 22 # +y else: axis = 1 # +x elif 135 <= rot < 225: if -45 <= pitch < 45: axis = 15 # +x elif -225 <= pitch < -135 or 135 <= pitch < 225: axis = 14 # -z elif -135 <= pitch < -45: axis = 33 # -y elif 45 <= pitch < 135 or -270 <= pitch < -225: axis = 32 # +y else: axis = 5 # +x else: axis = 0 return axis def SwapPoint(self, p, axis): if axis == 0 : return c4d.Vector(-p.z, p.y, p.x) elif axis == 1 : return c4d.Vector(p.z, -p.y, p.x) elif axis == 2 : return c4d.Vector(-p.y, -p.z, p.x) elif axis == 3 : return c4d.Vector(p.y, p.z, p.x) elif axis == 4 : return c4d.Vector(-p.x, p.y, -p.z) elif axis == 5 : return c4d.Vector(-p.x, -p.y, p.z) elif axis == 12 : return c4d.Vector(-p.x, -p.z, -p.y) elif axis == 13 : return c4d.Vector(-p.x, p.z, p.y) elif axis == 10 : return c4d.Vector(-p.z, -p.y, -p.x) elif axis == 11 : return c4d.Vector(p.z, p.y, -p.x) elif axis == 22 : return c4d.Vector(p.y, -p.z, -p.x) elif axis == 23: return c4d.Vector(-p.y, p.z, -p.x) elif axis == 14: return c4d.Vector(p.x, -p.y, -p.z) elif axis == 15: return c4d.Vector(p.x, p.y, p.z) elif axis == 32 : return c4d.Vector(p.x, -p.z, p.y) elif axis == 33 : return c4d.Vector(p.x, p.z, -p.y) return p
axis = self.GetAxis(pitch, rotation) if handle_index == 0: # Width info.position = rot_mx * Vector(-size_x, 0, depth) info.direction = self.SwapPoint(info.direction, axis)