Wie erstelle ich eine benutzerdefinierte Benutzeroberfläche?

Ich habe dieses -Video zum Erstellen einer benutzerdefinierten Benutzeroberfläche mit Python und in angesehen In der Zeile from bpy.types import Menu, Panel, UIList werden die Namen von Objekten angezeigt, die so aussehen, als könnten sie alle zum Erstellen verschiedener UI-Elemente verwendet werden. Enthält bpy.types alle Objekte, die Benutzer verwenden, wenn sie benutzerdefinierte Benutzeroberflächenelemente erstellen möchten?

Kommentare

  • Ein Typ ist eine Klasse, die als Vorlage für zusätzliche Klassen durch Vererbung verwendet werden kann, z class MyPanel(bpy.types.Panel): blender.org/api/blender_python_api_current/bpy.types.html . Mein Vorschlag ist, die “ Texteditor > Vorlagen > Python > Ui * “ Beispiele, die mit einem Mixer geliefert werden.

Antwort

Das Entwerfen einer Benutzeroberfläche oder eines Add-Ons ist im Grunde eine Kombination aus der Bereitstellung von Eigenschaften und der Vererbung integrierter Typklassen (Bedienfeld, Operator) , Menü usw.).


Eigenschaften

Definieren Sie zunächst Ihre Eigenschaften . Eigenschaften sind im Grunde „Datentypen“ und können in der Benutzeroberfläche für die grundlegende Benutzerinteraktion angezeigt werden. Beachten Sie, dass Sie von fast überall auf den Wert jeder Eigenschaft zugreifen können. Verwenden Sie zum Auffüllen einer vollständigen Liste in der Konsole die dir() -Methode von Python für bpy.props :

Geben Sie hier die Bildbeschreibung ein. Zum Vergrößern klicken

Aussehen der Eigenschaft

Eigenschaftsdefinition

from bpy.props import (StringProperty, BoolProperty, IntProperty, FloatProperty, EnumProperty, ) my_bool : BoolProperty( name="Enable or Disable", description="A bool property", default = False ) my_int : IntProperty( name = "Set a value", description="A integer property", default = 23, min = 10, max = 100 ) ... 

Beachten Sie, dass ab Blender 2.8x Eigenschaften sollte den Variablen u zugewiesen werden Singen Sie einen einzelnen Doppelpunkt : anstelle des üblichen Zuweisungsoperators = wie in Blender 2.7x oder älteren Versionen von Mixer.


Typen

Der Inhalt von bpy.types sind Klassenvorlagen, die für die Vererbung erstellt wurden.

Bedienfeld

Bedienfelder befinden sich überall in Blender, daher ist es das grundlegendste Element der Benutzeroberfläche Das Panel, das verwendet werden soll, wird durch bl_space_type definiert. Die Blender-Oberfläche ist „kontextsensitiv“, sodass Sie definieren können bl_context , um das Bedienfeld in einen entsprechenden Modus zu versetzen (Objektmodus, Bearbeitungsmodus usw.) .

Geben Sie hier die Bildbeschreibung ein.

class HelloWorldPanel(bpy.types.Panel): bl_idname = "OBJECT_PT_hello_world" bl_label = "Hello World" bl_space_type = "PROPERTIES" bl_region_type = "WINDOW" bl_context = "object" def draw(self, context): self.layout.label(text="Hello World") bpy.utils.register_class(HelloWorldPanel) 

Unterfenster

Geben Sie hier die Bildbeschreibung ein.

Ab Blender 2.8x können wir Unterfenster durch Zuweisen eines bestimmten Felds (übergeordnetes Element) zu bl_parent_id :

import bpy class HelloWorldPanel: bl_space_type = "VIEW_3D" bl_region_type = "UI" bl_category = "Tools" bl_options = {"DEFAULT_CLOSED"} class HELLO_PT_World1(HelloWorldPanel, bpy.types.Panel): bl_idname = "HELLO_PT_World1" bl_label = "Panel 1" def draw(self, context): layout = self.layout layout.label(text="This is the main panel.") class HELLO_PT_World2(HelloWorldPanel, bpy.types.Panel): bl_parent_id = "HELLO_PT_World1" bl_label = "Panel 2" def draw(self, context): layout = self.layout layout.label(text="First Sub Panel of Panel 1.") class HELLO_PT_World3(HelloWorldPanel, bpy.types.Panel): bl_parent_id = "HELLO_PT_World1" bl_label = "Panel 3" def draw(self, context): layout = self.layout layout.label(text="Second Sub Panel of Panel 1.") classes = ( HELLO_PT_World1, HELLO_PT_World2, HELLO_PT_World3 ) def register(): for cls in classes: bpy.utils.register_class(cls) def unregister(): for cls in classes: bpy.utils.unregister_class(cls) if __name__ == "__main__": register() 

Siehe auch: Texteditor> Vorlagen> Python > UI-Panel .

Operator

Der Operator ist das wichtigste zu verstehende Element. Sie können „Operatoren“ als Schaltflächen anzeigen und einmal registriert und von überall über bpy.ops.IDNAME() aufrufen. So ist auch der Mixer aufgebaut. Alle echten Schaltflächen sind „Operatoren“ unter der Haube, meistens in C geschrieben, dann aber Python ausgesetzt. Siehe auch: Texteditor> Vorlagen> Python > Operator … .

Geben Sie hier die Bildbeschreibung ein

class HelloWorldMinimal(bpy.types.Operator): bl_idname = "wm.hello_world" bl_label = "Minimal Operator" def execute(self, context): # Report "Hello World" to the Info Area self.report({"INFO"}, "Hello World") return {"FINISHED"} bpy.utils.register_class(HelloWorldMinimal) # test call the operator bpy.ops.wm.hello_world() 

Die Operator-Klassenvorlage enthält vordefinierte Methoden . Tatsächlich poll, invoke, execute, draw, modal und cancel, die zusammen mit benutzerdefinierten Eigenschaften für alle Arten von Vorgängen und auch zur Bereitstellung von Benutzerinteraktion verwendet werden können. Vollständigeres Beispiel eines Operators :

class HelloWorld(bpy.types.Operator): bl_idname = "wm.hello_world" bl_label = "Minimal Operator" bl_options = {"REGISTER"} # Operator user properties, should be assigned using a single colon : # instead of using an equal sign = in Blender 2.8 report_flag: bpy.props.BoolProperty( name = "Report", default = True) @classmethod # Will never run when poll returns false def poll(cls, context): return context.object def invoke(self, context, event): # Used for user interaction wm = context.window_manager return wm.invoke_props_dialog(self) def draw(self, context): # Draw options (typically displayed in the tool-bar) row = self.layout row.prop(self, "report_flag", text="Report Hello World") def execute(self, context): # Runs by default if self.report_flag: self.report({"INFO"}, "Hello World") else: print ("Hello World") return {"FINISHED"} bpy.utils.register_class(HelloWorld) # For interaction, pass "INVOKE_DEFAULT" when calling # the operator, this way invoke runs before execute method bpy.ops.wm.hello_world("INVOKE_DEFAULT") 

Weiterführende Literatur: Gewusst wie Rufen Sie ein Bestätigungsdialogfeld auf? (für enorm gefährliche Bediener ).

Menü

Für ein benutzerdefiniertes Menü definieren / erben Sie eine Menüklasse . Fügen Sie Ihre Operatoren und Eigenschaften der Funktion draw() ordnungsgemäß hinzu (siehe auch: Texteditor> Vorlagen> Python> UI-Menüvorlagen) .

Geben Sie hier die Bildbeschreibung ein.

class SimpleCustomMenu(bpy.types.Menu): bl_label = "Simple Custom Menu" bl_idname = "OBJECT_MT_simple_custom_menu" def draw(self, context): layout = self.layout layout.operator("wm.open_mainfile") layout.operator("wm.save_as_mainfile") # The menu can also be called from scripts bpy.ops.wm.call_menu(name=SimpleCustomMenu.bl_idname) 

Sie können auch eine Schaltfläche zeichnen, um das Menü aufzurufen, ohne einen zusätzlichen Operator zu deklarieren. layout.operator("wm.call_menu").name="bl_idname"

Untermenü

Um ein Untermenü zu erhalten, rufen Sie das zweite im übergeordneten Menü über layout.menu(bl_idname) .

Geben Sie hier die Bildbeschreibung ein.

class MyCustomMenu(bpy.types.Menu): bl_label = "First Menu" bl_idname = "OBJECT_MT_custom_menu" def draw(self, context): layout = self.layout layout.label(text="Hello First Menu!", icon="WORLD_DATA") # call the second custom menu layout.menu("OBJECT_MT_sub_menu", icon="COLLAPSEMENU") class MyCustomSubMenu(bpy.types.Menu): bl_label = "Sub Menu" bl_idname = "OBJECT_MT_sub_menu" def draw(self, context): layout = self.layout layout.label(text="Hello Second Menu!", icon="WORLD_DATA") # call another predefined menu layout.operator("wm.call_menu", text="Unwrap").name = "VIEW3D_MT_uv_map" # draw a button within the panel to call the first menu class OBJECT_PT_my_panel(bpy.types.Panel): ... def draw(self, context): layout.operator("wm.call_menu", text="Call My Menu").name = "OBJECT_MT_custom_menu" ... 

Alles in einem

Beim Erstellen eines Add-Ons werden normalerweise viele Eigenschaften benötigt. Für eine bessere Organisation können Sie eine „Einstellungsklasse“ erstellen, indem Sie eine PropertyGroup verwenden. Beachten Sie dies ab Blender 2.8x , Eigenschaften sollten mit einem einzelnen Doppelpunkt : anstelle des üblichen Zuweisungsoperators = zugewiesen werden.

2.7x

class MySettings(PropertyGroup): my_bool = BoolProperty() my_int = IntProperty() my_float = FloatProperty() ... 

2.8x

class MySettings(PropertyGroup): my_bool: BoolProperty() my_int: IntProperty() my_float: FloatProperty() ... 

Ab Blender 2.8x-Modul / Die Klassenregistrierung wurde geändert , um Namenskonflikte zu vermeiden. bpy.utils.register_module(__name__) ist nicht mehr verfügbar, sodass Sie grundsätzlich jede Klasse einzeln oder innerhalb einer Schleife registrieren / abmelden müssen (Best Practice):

classes = ( WM_OT_HelloWorld, OBJECT_PT_CustomPanel, ) def register(): from bpy.utils import register_class for cls in classes: register_class(cls) def unregister(): from bpy.utils import unregister_class for cls in reversed(classes): unregister_class(cls) 

Beachten Sie , dass zusätzlich zur alten Benennung Konventionen Sie müssen auch einen Separator hinzufügen wie _OT_, _MT_ oder _PT_ zum Namen Ihrer Klasse basierend auf dem geerbten Klassentyp (Operator, , Panel).


Add-On-Vorlage

Das folgende Add-On hängt ein benutzerdefiniertes Bedienfeld an in das Werkzeugregal der 3D-Ansicht und druckt die aktuellen „Benutzerwerte“ aller benutzerdefinierten Eigenschaften auf die Konsole:

Geben Sie hier die Bildbeschreibung ein.

Blender 2.7x

 bl_info = { "name": "Add-on Template", "description": "", "author": "", "version": (0, 0, 2), "blender": (2, 70, 0), "location": "3D View > Tools", "warning": "", # used for warning icon and text in addons panel "wiki_url": "", "tracker_url": "", "category": "Development" } import bpy from bpy.props import (StringProperty, BoolProperty, IntProperty, FloatProperty, EnumProperty, PointerProperty, ) from bpy.types import (Panel, Operator, PropertyGroup, ) # ------------------------------------------------------------------------ # Scene Properties # ------------------------------------------------------------------------ class MySettings(PropertyGroup): my_bool = BoolProperty( name="Enable or Disable", description="A bool property", default = False ) my_int = IntProperty( name = "Int Value", description="A integer property", default = 23, min = 10, max = 100 ) my_float = FloatProperty( name = "Float Value", description = "A float property", default = 23.7, min = 0.01, max = 30.0 ) my_string = StringProperty( name="User Input", description=":", default="", maxlen=1024, ) my_enum = EnumProperty( name="Dropdown:", description="Apply Data to attribute.", items=[ ("OP1", "Option 1", ""), ("OP2", "Option 2", ""), ("OP3", "Option 3", ""), ] ) # ------------------------------------------------------------------------ # Operators # ------------------------------------------------------------------------ class WM_OT_HelloWorld(bpy.types.Operator): bl_idname = "wm.hello_world" bl_label = "Print Values Operator" def execute(self, context): scene = context.scene mytool = scene.my_tool # print the values to the console print("Hello World") print("bool state:", mytool.my_bool) print("int value:", mytool.my_int) print("float value:", mytool.my_float) print("string value:", mytool.my_string) print("enum state:", mytool.my_enum) return {"FINISHED"} # ------------------------------------------------------------------------ # Menus # ------------------------------------------------------------------------ class OBJECT_MT_CustomMenu(bpy.types.Menu): bl_idname = "object.custom_menu" bl_label = "Select" def draw(self, context): layout = self.layout # Built-in example operators layout.operator("object.select_all", text="Select/Deselect All").action = "TOGGLE" layout.operator("object.select_all", text="Inverse").action = "INVERT" layout.operator("object.select_random", text="Random") # ------------------------------------------------------------------------ # Panel in Object Mode # ------------------------------------------------------------------------ class OBJECT_PT_CustomPanel(Panel): bl_idname = "object.custom_panel" bl_label = "My Panel" bl_space_type = "VIEW_3D" bl_region_type = "TOOLS" bl_category = "Tools" bl_context = "objectmode" @classmethod def poll(self,context): return context.object is not None def draw(self, context): layout = self.layout scene = context.scene mytool = scene.my_tool layout.prop(mytool, "my_bool") layout.prop(mytool, "my_enum", text="") layout.prop(mytool, "my_int") layout.prop(mytool, "my_float") layout.prop(mytool, "my_string") layout.operator("wm.hello_world") layout.menu(OBJECT_MT_CustomMenu.bl_idname, text="Presets", icon="SCENE") layout.separator() # ------------------------------------------------------------------------ # Registration # ------------------------------------------------------------------------ def register(): bpy.utils.register_module(__name__) bpy.types.Scene.my_tool = PointerProperty(type=MySettings) def unregister(): bpy.utils.unregister_module(__name__) del bpy.types.Scene.my_tool if __name__ == "__main__": register() 

Kern:

https://gist.github.com/p2or/a00bdde9f2751940717a404cf977dd01

Blender 2.8x

bl_info = { "name": "Add-on Template", "description": "", "author": "p2or", "version": (0, 0, 3), "blender": (2, 80, 0), "location": "3D View > Tools", "warning": "", # used for warning icon and text in addons panel "wiki_url": "", "tracker_url": "", "category": "Development" } import bpy from bpy.props import (StringProperty, BoolProperty, IntProperty, FloatProperty, FloatVectorProperty, EnumProperty, PointerProperty, ) from bpy.types import (Panel, Menu, Operator, PropertyGroup, ) # ------------------------------------------------------------------------ # Scene Properties # ------------------------------------------------------------------------ class MyProperties(PropertyGroup): my_bool: BoolProperty( name="Enable or Disable", description="A bool property", default = False ) my_int: IntProperty( name = "Int Value", description="A integer property", default = 23, min = 10, max = 100 ) my_float: FloatProperty( name = "Float Value", description = "A float property", default = 23.7, min = 0.01, max = 30.0 ) my_float_vector: FloatVectorProperty( name = "Float Vector Value", description="Something", default=(0.0, 0.0, 0.0), min= 0.0, # float max = 0.1 ) my_string: StringProperty( name="User Input", description=":", default="", maxlen=1024, ) my_path: StringProperty( name = "Directory", description="Choose a directory:", default="", maxlen=1024, subtype="DIR_PATH" ) my_enum: EnumProperty( name="Dropdown:", description="Apply Data to attribute.", items=[ ("OP1", "Option 1", ""), ("OP2", "Option 2", ""), ("OP3", "Option 3", ""), ] ) # ------------------------------------------------------------------------ # Operators # ------------------------------------------------------------------------ class WM_OT_HelloWorld(Operator): bl_label = "Print Values Operator" bl_idname = "wm.hello_world" def execute(self, context): scene = context.scene mytool = scene.my_tool # print the values to the console print("Hello World") print("bool state:", mytool.my_bool) print("int value:", mytool.my_int) print("float value:", mytool.my_float) print("string value:", mytool.my_string) print("enum state:", mytool.my_enum) return {"FINISHED"} # ------------------------------------------------------------------------ # Menus # ------------------------------------------------------------------------ class OBJECT_MT_CustomMenu(bpy.types.Menu): bl_label = "Select" bl_idname = "OBJECT_MT_custom_menu" def draw(self, context): layout = self.layout # Built-in operators layout.operator("object.select_all", text="Select/Deselect All").action = "TOGGLE" layout.operator("object.select_all", text="Inverse").action = "INVERT" layout.operator("object.select_random", text="Random") # ------------------------------------------------------------------------ # Panel in Object Mode # ------------------------------------------------------------------------ class OBJECT_PT_CustomPanel(Panel): bl_label = "My Panel" bl_idname = "OBJECT_PT_custom_panel" bl_space_type = "VIEW_3D" bl_region_type = "UI" bl_category = "Tools" bl_context = "objectmode" @classmethod def poll(self,context): return context.object is not None def draw(self, context): layout = self.layout scene = context.scene mytool = scene.my_tool layout.prop(mytool, "my_bool") layout.prop(mytool, "my_enum", text="") layout.prop(mytool, "my_int") layout.prop(mytool, "my_float") layout.prop(mytool, "my_float_vector", text="") layout.prop(mytool, "my_string") layout.prop(mytool, "my_path") layout.operator("wm.hello_world") layout.menu(OBJECT_MT_CustomMenu.bl_idname, text="Presets", icon="SCENE") layout.separator() # ------------------------------------------------------------------------ # Registration # ------------------------------------------------------------------------ classes = ( MyProperties, WM_OT_HelloWorld, OBJECT_MT_CustomMenu, OBJECT_PT_CustomPanel ) def register(): from bpy.utils import register_class for cls in classes: register_class(cls) bpy.types.Scene.my_tool = PointerProperty(type=MyProperties) def unregister(): from bpy.utils import unregister_class for cls in reversed(classes): unregister_class(cls) del bpy.types.Scene.my_tool if __name__ == "__main__": register() 

Inhalt: https://gist.github.com/p2or/2947b1aa89141caae182526a8fc2bc5a


Komplexere Beispiele

Kommentare

  • Meine Güte, das war wirklich gründlich! ‚ bietet mehr Möglichkeiten für die Python-Benutzeroberfläche als nur bpy.types und dann haha. Vielen Dank!
  • Dies ist eine erstaunlich präzise und klare Übersicht, die als Teil der Dokumentation großartig wäre. Ich habe Wochen gebraucht, um dies anhand vieler, vieler Beispiele herauszufinden.
  • Viel besser als ein offizielles Dokument. Du hast meinen Tag gerettet!

Antwort

modifizierte Version – für Blender 2.80 !!!

 # https://blender.stackexchange.com/q/57306/3710 # https://blender.stackexchange.com/q/79779/3710 # # modified for blender 2.80 # last modification: 2019-09-12 -- add custom-preferences panel -- Emanuel Rumpf -- bl_info = { "name": "Add-on Template", "description": "", "author": "", "version": (0, 0, 2), "blender": (2, 80, 0), "location": "3D View > Tools", "warning": "", # used for warning icon and text in addons panel "wiki_url": "", "tracker_url": "", "category": "Development" } """ This is an addon - template for blender 2.80 Use it as base for new addons. -- Some changes made for blender 2.80 version (from 2.79): - Properties are annotations now, assigned with : not = - bl_region_type now is "UI" not "TOOLS" - Registration procedure changed: Use bpy.utils.register_class() not register_module() More information see: python api blender 2.80 """ import bpy #import collections #import importlib #import mathutils #import math from bpy.utils import ( register_class, unregister_class ) from bpy.props import ( StringProperty, BoolProperty, IntProperty, FloatProperty, FloatVectorProperty, EnumProperty, PointerProperty, ) from bpy.types import ( Panel, AddonPreferences, Operator, PropertyGroup, ) # this must match the addon name, use "__package__" # when defining this in a submodule of a python package. addon_name = __name__ # when single file #addon_name = __package__ # when file in package # ------------------------------------------------------------------------ # settings in addon-preferences panel # ------------------------------------------------------------------------ # panel update function for PREFS_PT_MyPrefs panel def _update_panel_fnc (self, context): # # load addon custom-preferences print( addon_name, ": update pref.panel function called" ) # main_panel = OBJECT_PT_my_panel # main_panel .bl_category = context .preferences.addons[addon_name] .preferences.tab_label # re-register for update unregister_class( main_panel ) register_class( main_panel ) class PREFS_PT_MyPrefs( AddonPreferences ): """ Custom Addon Preferences Panel - in addon activation panel - menu / edit / preferences / add-ons """ bl_idname = addon_name tab_label: StringProperty( name="Tab Label", description="Choose a label-name for the panel tab", default="New Addon", update=_update_panel_fnc ) def draw(self, context): layout = self.layout row = layout.row() col = row.column() col.label(text="Tab Label:") col.prop(self, "tab_label", text="") # ------------------------------------------------------------------------ # properties visible in the addon-panel # ------------------------------------------------------------------------ class PG_MyProperties (PropertyGroup): my_bool : BoolProperty( name="Enable or Disable", description="A bool property", default = False ) my_int : IntProperty( name = "Int Value", description="A integer property", default = 23, min = 10, max = 100 ) my_float : FloatProperty( name = "Float Value", description = "A float property", default = 23.7, min = 0.01, max = 30.0 ) my_float_vector : FloatVectorProperty( name = "Float Vector Value", description="Something", default=(0.0, 0.0, 0.0), min= 0.0, # float max = 0.1 ) my_string : StringProperty( name="User Input", description=":", default="", maxlen=1024, ) my_enum : EnumProperty( name="Dropdown:", description="Apply Data to attribute.", items=[ ("OP1", "Option 1", ""), ("OP2", "Option 2", ""), ("OP3", "Option 3", ""), ] ) # ------------------------------------------------------------------------ # operators # ------------------------------------------------------------------------ class OT_HelloWorldOperator (bpy.types.Operator): bl_idname = "wm.hello_world" bl_label = "Print Values Operator" def execute(self, context): scene = context.scene mytool = scene.my_tool # print the values to the console print("Hello World") print("bool state:", mytool.my_bool) print("int value:", mytool.my_int) print("float value:", mytool.my_float) print("string value:", mytool.my_string) print("enum state:", mytool.my_enum) return {"FINISHED"} # ------------------------------------------------------------------------ # menus # ------------------------------------------------------------------------ class MT_BasicMenu (bpy.types.Menu): bl_idname = "OBJECT_MT_select_test" bl_label = "Select" def draw(self, context): layout = self.layout # built-in example operators layout.operator("object.select_all", text="Select/Deselect All").action = "TOGGLE" layout.operator("object.select_all", text="Inverse").action = "INVERT" layout.operator("object.select_random", text="Random") # ------------------------------------------------------------------------ # addon - panel -- visible in objectmode # ------------------------------------------------------------------------ class OBJECT_PT_my_panel (Panel): bl_idname = "OBJECT_PT_my_panel" bl_label = "My Panel" bl_space_type = "VIEW_3D" bl_region_type = "UI" bl_category = "Tool" # note: replaced by preferences-setting in register function bl_context = "objectmode" # def __init(self): # super( self, Panel ).__init__() # bl_category = bpy.context.preferences.addons[__name__].preferences.category @classmethod def poll(self,context): return context.object is not None def draw(self, context): layout = self.layout scene = context.scene mytool = scene.my_tool layout.prop( mytool, "my_bool") layout.prop( mytool, "my_enum", text="") layout.prop( mytool, "my_int") layout.prop( mytool, "my_float") layout.prop( mytool, "my_float_vector", text="") layout.prop( mytool, "my_string") layout.operator( "wm.hello_world") layout.menu( "OBJECT_MT_select_test", text="Presets", icon="SCENE") # ------------------------------------------------------------------------ # register and unregister # ------------------------------------------------------------------------ classes = ( PG_MyProperties, # OT_HelloWorldOperator, MT_BasicMenu, OBJECT_PT_my_panel, # PREFS_PT_MyPrefs, ) def register(): # for cls in classes: register_class(cls) # bpy.types.Scene.my_tool = PointerProperty(type=PG_MyProperties) # def unregister(): # for cls in reversed(classes): unregister_class(cls) # del bpy.types.Scene.my_tool # remove PG_MyProperties if __name__ == "__main__": pass #register() 

Einige Änderungen für Blender 2.80:

  • Eigenschaften sind jetzt Anmerkungen, denen : nicht =
  • bl_region_type ist jetzt „UI“ nicht „TOOLS“
  • Registrierungsverfahren geändert:
    • Verwenden Sie bpy.utils.register_class() nicht register_module()

Weitere Informationen: Python-API-Mixer 2.80

Kommentare

  • OMG. Ich danke dir sehr. Ich lerne Python im Mixer. Ich codiere viel in VB.net & C #. Ich hatte Probleme mit der Benutzeroberfläche. Dies erklärte es sehr gut und
  • Hallo, ich würde gerne wissen, worauf sich scene.my_tool bezog? weil ich nicht gesehen habe, wo es zuerst definiert wurde?
  • Oh, jetzt verstehe ich es, also muss ich eine Zeiger-Eigenschaft registrieren, um einige andere Eigenschaften zu speichern?

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.