美文网首页CgTd
C4D 插件结构

C4D 插件结构

作者: N景波 | 来源:发表于2017-03-22 18:00 被阅读0次

    插件结构

    插件放在用户目录下的plugins目录。插件后缀该为.pyd, .pypv(加密文件)。 C4D 启动后,寻找并执行此目录下所有以.pyp 或 .pypv结尾的插件。一个简单的插件如下:

    def main():
        print "Hello World!"
    
    main()
    

    这个插件不好玩,就能输出个hello world! 但是,我们可以在程序的各个部分注册插件钩子。

    Hook 钩子

    所有插件的钩子都从BaseData继承而来, 这些类包含能被C4D调用的方法。 MessageData的例子:

    class SampleData(plugins.MessageData):
    
        def CoreMessage(self, id, bc):
            pass
    

    Registration 注册

    向C4D注册插件需使用Register() 。 注册函数可接收实例也能接收类,在内部自己创建对象:
    plugins.RegisterCommandPlugin(id=PLUGIN_ID, str="TestBase-Plugin", info=0, dat=SampleData())

    NodeData的注册方法需要一个类名:

    class SampleData(plugins.ObjectData):
        def GetVirtualObjects(self, op, hierarchyhelp):
            pass
    
    plugins.RegisterObjectPlugin(id=PLUGIN_ID, str="TestNode-Plugin",
                                g=SampleData, description="", icon=None,
                                info=c4d.OBJECT_GENERATOR)
    

    Lifetime 生命周期

    数据类的声明周期还有点说道,上面的例子中将新的实例传给了注册函数,在C4D的session周期内此实例都存在。其构造和析构函数正常调用,不用多想多做。需要将名字传给注册函数的数据类在C4D的节点上游对应的1:1标志,其生命周期和node一样,分配和删除都由C4D控制。其构造和析构也如常调用,但C4D会额外调用NodeData.Init()

    Directory Structure 目录结构

    .pyp 或.pypv 可以放在插件目录,将其组织成层次会更好。 插件的标准层次结构如下:

    myPlugin/
        myPlugin.pyp
        ...
        res/
            c4d_symbols.h
            description/
                myDescription.h
                myDescription.res
                ...
            dialogs/
                myDialog.res
                ...
    
            strings_us/
                c4d_strings.str
                description/
                    myDescription.str
                    ...
                dialogs/
                    myDialog.str
                    ...
                strings_de/
                strings_jp/
                ...
        myIcon.tif
        myWhatever.any
        ...
    

    主文件myPlugin.pyp 注册了钩子。 res目录包含插件资源,现指dialogs,description, strings。

    每个description都会有一个.h文件,枚举了description用到的常量。 查看Descriptions in cinema4D。 每个dialog包含自己的 .res文件。 c4d_symbols.h包含了.res使用的常量。

    可能会有个string_xx的目录来做国际化,xx是两个目录,代表一种语言,依据是iso 639,iso3361-1. 当前C4D有一下编码:

    us - American English
    de - German
    fr - French
    it - Italian
    jp - Japanese
    

    每种语言的目录应该包含dialog的.str文件。 c4d_string.str是给其他资源用的。 推荐的做法是先做一种语言,翻译前拷贝一份。最后你可以有很多文件,例如插件的icon和logo,这些可以方便地通过file访问

    dir, file= os.path.split(__file__)
    

    Plugin Messages 插件信息

    PluginMessage(id, data)
    定义此函数可以接收插件信息。 可以从C4D或者从其他插件调用GetPluginMessage()

    Paste_Image.png

    Command Line Arguments 命令行参数

    随时接收C4D的命令行参数,实现PluginMessage() 填入C4DPL_COMMANDLINEARGS 信息:

    import c4d
    import sys
    def PluginMessage(id, data):
            if id == c4d.C4DPL_COMMANDLINEARGS:
                print sys.argv 
    
    • 代码保存到.pyp 文件中,放在插件目录下。
    • 带参启动 C4D,比如Cinema 4D.exe -hello
    • 打开终端,其应该包含传入的参数。

    警告
    C4D模块维护的参数被移除了。 例如,”Cinema 4D.exe -hello -paralle" 打开终端,paralle不在打印的参数列表中。

    重载python插件

    C4D的函数重载,重编译.pyp文件。 被pyp文件import的库不会reload. python首先检查模块是否导入, 已导入就跳过,并建立引用.

    当PluginMessage()接收到C4DPL_RELOADPYTHONPLUGINS , 可以用reload()来强制重载python模块. 此处可以关闭以前打开的资源(socket,file等)

    增强主菜单

    添加自己的菜单, 在PluginMessage()中拦截C4DPL_BUILDMENU, 并调用GetMenuResource()来接收主菜单容器,下面是一个完整的例子。

    def EnhanceMainMenu():
        mainMenu = gui.GetMenuResource("M_EDITOR")  # Get main menu resource
        pluginsMenu = gui.SearchPluginMenuResource()  # Get 'Plugins' main menu resource
    
        menu = c4d.BaseContainer()  # Create a container to hold a new menu information
    
        menu.InsData(c4d.MENURESOURCE_SUBTITLE, "Py-Test")  # Set the name of the menu
        menu.InsData(c4d.MENURESOURCE_COMMAND, "IDM_NEU")  # Add registered default command 'New Scene' to the menu
        menu.InsData(c4d.MENURESOURCE_SEPERATOR, True);  # Add a separator
        menu.InsData(c4d.MENURESOURCE_COMMAND, "PLUGIN_CMD_5159")  # Add command 'Cube' with ID 5159 to the menu
    
        submenu = c4d.BaseContainer()  # Create a new submenu container
        submenu.InsData(c4d.MENURESOURCE_SUBTITLE, "Submenu")  # This is a submenu
        submenu.InsData(c4d.MENURESOURCE_COMMAND, "IDM_SPEICHERN")  # Add registered default command 'Save' to the menu
    
        menu.InsData(c4d.MENURESOURCE_SUBMENU, submenu)  # Add the submenu
        if pluginsMenu:
            # Insert menu after 'Plugins' menu
            mainMenu.InsDataAfter(c4d.MENURESOURCE_STRING, menu, pluginsMenu)
        else:
        # Insert menu after the last existing menu ('Plugins' menu was not found)
            mainMenu.InsData(c4d.MENURESOURCE_STRING, menu)
    
    def PluginMessage(id, data):
        if id == c4d.C4DPL_BUILDMENU:
            EnhanceMainMenu()
    

    注意
    如果在“C4DPL_BUILDMENU” 消息之外修改了菜单,记得调用gui.UpdateMenus()

    相关文章

      网友评论

        本文标题:C4D 插件结构

        本文链接:https://www.haomeiwen.com/subject/xwjenttx.html