Python-Integration

Ab Dragonframe 2027 (derzeit in Entwicklung) unterstützt Dragonframe Python + PySide (bis Qt 6.11).

Nach der Installation 2027.01 Entwicklerversion, Erstellen Sie eine Python-Initialisierungsdatei unter ~/Dragonframe/scripts/__init__.py
Alternativ können Sie eine Umgebungsvariable, DRAGONFRAME_PATH, auf eine durch Doppelpunkte getrennte Liste von Pfaden zu Python-Modulverzeichnissen setzen.

Die Benutzeroberfläche befindet sich derzeit noch im Aufbau. Sie kann sich bis zur endgültigen Veröffentlichung noch ändern.
Beachten Sie, dass alle Funktionen nur vom Hauptthread aus aufgerufen werden sollten, mit Ausnahme von util.executeInMainThread und util.executeInMainThreadWithResult.

Hier sind die verfügbaren Module und Methoden:

=== dragonframe.ui ===

Menu:
Members:

  FileMenu : The File menu.

  EditMenu : The Edit menu.

  ViewMenu : The View menu.

  SceneMenu : The Scene menu.

  CaptureMenu : The Capture menu.

  PlaybackMenu : The Playback menu.

  WindowMenu : The Window menu.

  HelpMenu : The Help menu.

  UserTopLevel1 : A top-level user menu.

  UserTopLevel2 : A top-level user menu.

  UserTopLevel3 : A top-level user menu.

  CinematographyImageContextMenu : The right-click context menu on the cinematography image.

addMenuOption:
addMenuOption(location: dragonframe.ui.Menu, label: str, callback: object, kwargs: dict = {}) -> None

Add a menu item to the specified menu.

    location -- Menu value indicating which menu to add the item to
    label    -- display text for the menu item
    callback -- callable invoked with no arguments when the item is selected
    kwargs -- dictionary with additional arguments - 'checked' = True/False, 'shortcut' = shortcut


addMenuSeparator:
addMenuSeparator(location: dragonframe.ui.Menu) -> None

Add a separator line to the specified menu.

    location -- Menu value indicating which menu to add the separator to


isMenuOptionChecked:
isMenuOptionChecked(location: dragonframe.ui.Menu, label: str) -> bool

Returns if a menu item is checked.

    location -- Menu value indicating which menu to add the item to
    label    -- display text for the menu item


setMenuOptionChecked:
setMenuOptionChecked(location: dragonframe.ui.Menu, label: str, checked: bool) -> None

Sets a menu item to be checkable and sets the current value.

    location -- Menu value indicating which menu to add the item to
    label    -- display text for the menu item
    checked  -- whether the menu item is checked


setTopLevelMenuName:
setTopLevelMenuName(location: dragonframe.ui.Menu, label: str) -> None

Set the name of a user-defined top level menu.

    location -- UserTopLevel1, UserTopLevel2, or UserTopLevel3
    label    -- display text for the menu



=== dragonframe.events ===

EventType:
Members:

  Shoot : A capture (shoot) has been initiated.

  Delete : A frame has been deleted.

  Position : The playhead position has changed.

  CaptureComplete : A single exposure capture has completed.

  FrameComplete : All exposures for the current frame have been captured.

  TestComplete : A test shot capture has completed.

  Edit : An edit operation has occurred.

  AfterAssist : An assist operation has finished.

  Exposure : The active exposure (pass) has changed.

  Bash : A bash/shell script event has fired.

  Save : The scene has been saved.

  NewTake : A new take has been created.

  TakeOpened : A take has been opened.

  CaptureFailed : A capture attempt failed.

  MocoDisconnected : The motion control rig has disconnected.

  CameraDisconnected : The camera has disconnected.

registerInterest:
registerInterest(types: list[dragonframe.events.EventType], callback: object) -> None

Register a callback to be invoked when any of the given EventType values occur.

    types    -- list of EventType values to listen for
    callback -- callable invoked with the EventType when the event fires

Example::

    def on_event(event_type):
        print('event:', event_type)
    dragonframe.events.registerInterest(
        [dragonframe.events.EventType.FrameComplete], on_event)


=== dragonframe.scene ===

currentExposure:
currentExposure() -> int

Return the 1-based index of the currently active exposure (pass), or 0 if no scene is open.


currentFrame:
currentFrame() -> int

Return the 1-based index of the currently selected frame, or 0 if no scene is open.


exposureCount:
exposureCount() -> int

Return the number of exposures (passes) defined in the current scene, or 0 if no scene is open.


exposureFolder:
exposureFolder(exp: int) -> str

Return the absolute path to the capture folder for the given exposure.

    exposure -- 1-based exposure (pass) index

Returns an empty string if no scene is open.


exposureFramePrefix:
exposureFramePrefix(exp: int) -> str

Return the file name prefix used for captured frames of the given exposure.

    exp -- 1-based exposure index

Returns an empty string if no scene is open.


exposureName:
exposureName(exp: int) -> str

Return the display name of the given exposure (pass).

    exp -- 1-based exposure index

Returns an empty string if no scene is open.


feedFolder:
feedFolder() -> str

Return the absolute path to the live-view feed folder, or an empty string if no scene is open.


highResFile:
highResFile(vframe: int, exposure: int, raw: bool) -> str

Return the file path of the captured image for a given frame and exposure.

    vframe   -- 1-based virtual frame number
    exposure -- 1-based exposure (pass) index
    raw      -- if True, return the path to the raw file instead of the processed image


importAxisSetup:
importAxisSetup(fileName: str) -> None

Import a motion control axis setup file.

    fileName -- absolute path to the .dfscene file


loadMediaIntoReferences:
loadMediaIntoReferences(fileNames: list[str]) -> None

Load images into the references folder.




loadMediaIntoTestShots:
loadMediaIntoTestShots(fileNames: list[str]) -> None

Load images into the test shots folder.




loadReferenceLayerImage:
loadReferenceLayerImage(fileName: str) -> bool

Load a still image as the active reference layer.

    fileName -- absolute path to the image file


loadReferenceLayerImageSequence:
loadReferenceLayerImageSequence(fileName: str) -> bool

Load an image sequence as the active reference layer.

    fileName -- absolute path to the first frame of the image sequence


loadReferenceLayerMovie:
loadReferenceLayerMovie(fileName: str) -> bool

Load a movie file as the active reference layer.

    fileName -- absolute path to the movie file


loadReferenceLayerScene:
loadReferenceLayerScene(fileName: str) -> bool

Load another Dragonframe scene as the active reference layer.

    fileName -- absolute path to the .dfscene file


name:
name() -> str

Return the full name of the open scene, or an empty string if no scene is open.


namePrefix:
namePrefix() -> str

Return the name prefix used when constructing frame file names, or an empty string if no scene is open.


openFile:
openFile(fileName: str) -> bool

Load a scene or take. If you provide a .dgn folder, the Choose Take dialog will appear.

    fileName -- path to scene.dgn or take folder


save:
save() -> None

Save the current scene to disk. Has no effect if no scene is open.


sceneFolder:
sceneFolder() -> str

Return the absolute path to the scene folder, or an empty string if no scene is open.


sceneName:
sceneName() -> str

Return the scene number/identifier portion of the scene name, or an empty string if no scene is open.


setCurrentExposure:
setCurrentExposure(exp: int) -> None

Set the currently active exposure (pass).

    exp -- 1-based exposure index

Has no effect if no scene is open.


setCurrentFrame:
setCurrentFrame(frame: int) -> None

Set the currently selected frame.

    frame -- 1-based frame index

Has no effect if no scene is open.


takeFile:
takeFile() -> str

Return the absolute path to the scene data file (.dfscene), or an empty string if no scene is open.


takeFolder:
takeFolder() -> str

Return the absolute path to the current take folder, or an empty string if no scene is open.


takeName:
takeName() -> str

Return the take number/identifier portion of the scene name, or an empty string if no scene is open.


testRefsFolder:
testRefsFolder() -> str

Return the absolute path to the test reference images folder, or an empty string if no scene is open.


testShotsFolder:
testShotsFolder() -> str

Return the absolute path to the test shots folder, or an empty string if no scene is open.


=== dragonframe.util ===

executeInMainThread:
executeInMainThread(call: object, args: object = (), kwargs: dict = {}) -> None

Executes a call on the main thread.


executeInMainThreadWithResult:
executeInMainThreadWithResult(call: object, args: object = (), kwargs: dict = {}) -> object

Executes a call on the main thread, waiting for the result.


executeScript:
executeScript(action: str) -> None

Executes the user-provided bash/bat script (in Preferences|Advanced).

    action -- The action name that will be provided to the script

Und hier ist ein Beispiel für eine __init__.py-Datei:

print("Initializing Dragonframe python")

from dragonframe import ui
from dragonframe import events
from dragonframe import scene

def print_module_docs(mod):
    name = getattr(mod, '__name__', str(mod))
    print(f"\n=== {name} ===")
    for attr in sorted(dir(mod)):
        if attr.startswith('_'):
            continue
        obj = getattr(mod, attr)
        doc = getattr(obj, '__doc__', None)
        if doc:
            print(f"\n{attr}:\n{doc}")

print_module_docs(ui)
print_module_docs(events)
print_module_docs(scene)

from PySide6.QtWidgets import (QFileDialog)

def get_media(user_data: dict):
    print("get_media")
    print(f"Scene Name {scene.name()} {scene.sceneName()} {scene.takeName()}")
    fileNames, _ = QFileDialog.getOpenFileNames(None, "Get Media",
                                              "Test Python",
                                              "All Files (*);;Media Files (*.jpg,*.png,*.tiff,*.crw)", "")
    if fileNames:
        print(f"Chosen files {fileNames}")
        scene.loadMediaIntoReferences(fileNames);

def load_reference_image(user_data: dict):
    print("load_reference_image")
    print(f"Scene Name {scene.name()} {scene.sceneName()} {scene.takeName()}")
    fileName, _ = QFileDialog.getOpenFileName(None, "Load Reference Image",
                                              "Test Python",
                                              "All Files (*);;Image Files (*.jpg,*.png,*.tiff,*.crw)", "")
    if fileName:
        print(f"Chosen file {fileName}")
        scene.loadReferenceLayerImage(fileName);

def launch_image(user_data: dict):
    print("Launch image! ")
    print("Exposure: " + str(user_data["exposure"]))
    frameList = user_data["frames"];
    for frame in frameList:
        fileName = scene.highResFile(frame, user_data["exposure"], False)
        rawFileName = scene.highResFile(frame, user_data["exposure"], True)
        print(f"FRAME: {frame}, File {fileName}, Raw {rawFileName}");

ui.addMenuSeparator(ui.Menu.FileMenu);
ui.addMenuOption(ui.Menu.FileMenu, "Company|Load Reference Image", load_reference_image);

ui.addMenuOption(ui.Menu.CinematographyImageContextMenu, "My Launcher", launch_image, { "shortcut": "Ctrl+G" });
ui.addMenuOption(ui.Menu.CinematographyImageContextMenu, "Import to References", get_media);

def handle_shoot(user_data: dict):
    print("Shooting! " + str(user_data["frame"]) + " " + str(user_data["exposure"]));

def handle_position(user_data: dict):
    print("POSITION: " + str(user_data["frame"]) + " " + str(user_data["exposure"]));

def handle_cc(user_data: dict):
    print("CC: " + str(user_data["frame"]) + " " + str(user_data["exposure"]));


events.registerInterest([events.EventType.Shoot], handle_shoot);
events.registerInterest([events.EventType.Position], handle_position);
events.registerInterest([events.EventType.CaptureComplete], handle_cc);