Python Plugin
The designer-plugin library lets you execute Python code remotely on Disguise Designer. Define your plugin methods locally, connect to a Designer instance, and call those methods as if they were running on your machine. The library handles all the HTTP communication, sending your code to Designer’s Python API and returning the results.
Since Designer’s runtime uses Python 2.7, the library also converts your Python 3 code automatically, transforming f-strings, type hints, and other modern syntax so you can write clean, modern Python without worrying about compatibility.
Code executed on Designer runs under Python 2.7. While the library converts common Python 3 syntax automatically, some features may not be supported. Write and test your plugin code with this in mind.
Installation
Install the designer-plugin package before running any examples.
pip install designer-plugin
Requires Python 3.11 or later on the client (local) machine.
Python Stub for Designer Object (Optional)
To enable IDE autocomplete and type checking for Designer’s Python API, install the stub file package:
pip install designer-plugin-pystub
Once installed, import the stubs in your local (client-side) code:
from designer_plugin.pystub import *
The wildcard import makes all Designer type hints available at once, which is the intended usage for a stub package.
This provides type hints for Designer objects like resourceManager, Screen2, Path, and more. See the Python API for the full list of available classes and methods.
The pystub package provides type hints only. These objects are client-side proxies that hold no data. They only exist in Designer’s runtime. See Limitation for details.
How It Works
Here’s a simple example that prints “Hello World!” to the Designer console:
Using the Client API, you define a class that inherits from D3PluginClient:
from designer_plugin.d3sdk import D3PluginClient
class MyPlugin(D3PluginClient):
def hello_world(self):
print("Hello World!")
plugin = MyPlugin()
with plugin.session('localhost'):
plugin.hello_world()
When you call a method on your plugin, the library sends your code to Designer via HTTP. Designer executes the code using its Python API and returns any output or return values back to your local session.
From your perspective, you’re just calling Python methods. The HTTP communication, serialisation, and response handling are all managed behind the scenes.
Two Ways to Write Plugins
| API | Description | Best For |
|---|---|---|
| Client API | Class-based approach. Inherit from D3PluginClient and all methods become remotely executable. Supports function chaining. | Related methods that share state, OOP-style plugins |
| Functional API | Decorator-based approach using @d3function and @d3pythonscript. Explicit control over what gets sent and when. | Standalone scripts, mixing plugin code with other logic |
Both approaches support synchronous and asynchronous execution.
Limitation
Object types imported from designer_plugin.pystub (such as Screen2, Camera, Path) only live in Designer’s runtime. They cannot be used directly on the client side. You cannot receive one of these objects as a return value and call methods on it in your local Python script.
with my_plugin.session('localhost'):
surface = my_plugin.get_surface("surface 1") # Returns a Screen2 on Designer
surface.rename(...) # This will fail. Surface is not a real object on the client
To work around this, use function chaining: define a method that calls another method within the same D3PluginClient class. Because all chained methods execute on the Designer side, Designer objects can be passed between them freely.
class MyPlugin(D3PluginClient):
def get_surface(self, surface_name: str) -> Screen2:
return resourceManager.load(Path(f'objects/screen2/{surface_name}.apx'), Screen2)
def rename_surface(self, surface_name: str, new_name: str) -> None:
surface: Screen2 = self.get_surface(surface_name) # Chained. Runs on Designer
surface.rename(surface.path.replaceFilename(new_name))
If you need data from a Designer object on the client side, return a serializable value (e.g. a string or number) instead of the object itself:
def get_surface_uid(self, surface_name: str) -> str:
surface: Screen2 = resourceManager.load(...)
return str(surface.uid) # Returns a plain string to the client
Enable Logging
By default, designer_plugin logging is disabled. To enable it:
import logging
logging.basicConfig(level=logging.INFO)
logging.getLogger('designer_plugin').setLevel(logging.DEBUG)
Next Steps
When you need detailed API information, the Client API, Functional API, and Reference pages cover everything in depth. For worked examples, see the Examples in the Client API reference.