Skip to content

Python Library

Ready-to-use Python snippets for the Custom Code action node. Click the copy icon on any code block, paste it into the matching field on your Custom Code node, and you're set. Requires the Python Editor Script Plugin enabled.

12 scripts ready
Each card tells you which field to paste into — Execute (runs on click), Display (sets the wedge label), or Visible (shows/hides the wedge).

All 0 #selection 0 #transform 0 #spawn 0 #camera 0 #workflow 0 #shortcut 0 #debug 0 #dynamic 0 #graph 0

No scripts yet in this category — more are on the way.

S

Toggle Wireframe

Flips the wireframe display on the first selected static mesh actor. Useful for inspecting geometry without leaving the viewport.

Execute

actors = unreal.EditorLevelLibrary.get_selected_level_actors()
if actors:
    a = actors[0]
    comp = a.get_component_by_class(unreal.StaticMeshComponent)
    if comp:
        comp.set_editor_property('bWireframe', not comp.get_editor_property('bWireframe'))

#selection #render #toggle

T

Randomize Rotation

Gives every selected actor a random Yaw — instantly breaks up grid-aligned props, foliage, or debris.

Execute

import random
for actor in unreal.EditorLevelLibrary.get_selected_level_actors():
    rot = unreal.Rotator(0, random.uniform(0, 360), 0)
    actor.set_actor_rotation(rot, False)

#selection #transform #random #foliage

T

Scatter in a Radius

Nudges each selected actor by ±500 units on X and Y. Quick way to break up perfect grids before tweaking by hand.

Execute

import random
actors = unreal.EditorLevelLibrary.get_selected_level_actors()
for a in actors:
    loc = a.get_actor_location()
    loc.x += random.uniform(-500, 500)
    loc.y += random.uniform(-500, 500)
    a.set_actor_location(loc, False, False)

#selection #transform #random #scatter

S

Select Same Class

Picks the first selected actor's class and re-selects every actor of that class in the level. Handy before a bulk operation.

Execute

actors = unreal.EditorLevelLibrary.get_selected_level_actors()
if actors:
    cls = actors[0].get_class()
    all_actors = unreal.EditorLevelLibrary.get_all_level_actors()
    same = [a for a in all_actors if a.get_class() == cls]
    unreal.EditorLevelLibrary.set_selected_level_actors(same)

#selection #class #batch

D

Log Selected Actor Properties

Dumps name, class, location and scale of the first selected actor to the Output Log. Handy when something looks off and you want a quick sanity check.

Execute

actors = unreal.EditorLevelLibrary.get_selected_level_actors()
if actors:
    a = actors[0]
    unreal.log(f"Name: {a.get_name()}")
    unreal.log(f"Class: {a.get_class().get_name()}")
    unreal.log(f"Location: {a.get_actor_location()}")
    unreal.log(f"Scale: {a.get_actor_scale3d()}")

#selection #debug #log

T

Align to Same Z Height

Snaps every selected actor to the Z height of the first one in the selection. Great for lining up props on a shared floor.

Execute

actors = unreal.EditorLevelLibrary.get_selected_level_actors()
if len(actors) > 1:
    target_z = actors[0].get_actor_location().z
    for a in actors[1:]:
        loc = a.get_actor_location()
        loc.z = target_z
        a.set_actor_location(loc, False, False)

#selection #transform #align

S

Rename Sequentially

Relabels every selected actor as Prop_000, Prop_001, etc. Useful before exporting or referencing them by name.

Execute

actors = unreal.EditorLevelLibrary.get_selected_level_actors()
for i, a in enumerate(actors):
    a.set_actor_label(f"Prop_{i:03d}")

#selection #rename #batch

Sp

Ring of Actors

Spawns 8 empty Static Mesh actors in a 500-unit ring around the first selected actor. Drop in your own mesh and you have a procedural circle.

Execute

import math
actors = unreal.EditorLevelLibrary.get_selected_level_actors()
if actors:
    center = actors[0].get_actor_location()
    radius = 500
    count = 8
    for i in range(count):
        angle = (2 * math.pi / count) * i
        loc = unreal.Vector(
            center.x + radius * math.cos(angle),
            center.y + radius * math.sin(angle),
            center.z
        )
        unreal.EditorLevelLibrary.spawn_actor_from_class(unreal.StaticMeshActor, loc)

#spawn #ring #procedural

S

Toggle Collision

Flips bGenerateOverlapEvents on every selected actor's primitive component. Useful when iterating on triggers or interactive props.

Execute

for actor in unreal.EditorLevelLibrary.get_selected_level_actors():
    comp = actor.get_component_by_class(unreal.PrimitiveComponent)
    if comp:
        enabled = comp.get_editor_property('bGenerateOverlapEvents')
        comp.set_editor_property('bGenerateOverlapEvents', not enabled)

#selection #collision #toggle

UI

Show Selection Count

Returns "Selected: N actor(s)" for the wedge label. Paste in the Display Name Code field — the label updates every time the pie menu opens.

Display

count = len(unreal.EditorLevelLibrary.get_selected_level_actors())
result = f"Selected: {count} actor{'s' if count != 1 else ''}"

#dynamic #label #selection

UI

Hide Outside Landscape

Returns True only when an editor world is loaded. Paste in Is Visible Code — the wedge disappears in contexts where this script can't run.

Visible

result = unreal.EditorLevelLibrary.get_editor_world() is not None

#dynamic #visibility #landscape

G

Color Wedges by Label

Calls QuickMenu's exposed UFUNCTION to recolor every wedge whose label matches "Translate". Use as a starting point for building style presets.

Execute

graph = unreal.QuickMenuGraphAsset.get_active_graph()
graph.set_wedge_color_by_label("Translate", unreal.LinearColor(0.2, 0.4, 1.0, 1.0))

#graph #color #wedge

Sh

Save All Dirty Packages

One-shot equivalent of the native Ctrl+Shift+S — saves every modified asset and level. Wire it to a wedge when you want Save All on the radial.

Execute

unreal.EditorLoadingAndSavingUtils.save_dirty_packages(save_map_packages=True, save_content_packages=True)

#shortcut #save #workflow #assets

W

Copy Camera Settings

Recursively serialises every editor property of the selected camera component (filmback, lens, focus, full post-process with its bOverride_ flags) to a JSON clipboard on disk. Pairs with the Paste card below.

Execute

import json
import os

CLIP = os.path.join(unreal.Paths.project_intermediate_dir(), "qm_camera_clipboard.json")

SKIP = {
    "relative_location", "relative_rotation", "relative_scale3d",
    "absolute_location", "absolute_rotation", "absolute_scale",
    "attach_parent", "attach_socket_name", "attach_children",
    "component_to_world", "component_tags", "asset_user_data",
    "mobility", "primary_component_tick",
}

def get_cam(actor):
    return (actor.get_component_by_class(unreal.CineCameraComponent)
            or actor.get_component_by_class(unreal.CameraComponent))

def list_props(obj):
    props = []
    for name in dir(obj):
        if name.startswith("_") or name in SKIP:
            continue
        try:
            if callable(getattr(obj, name)):
                continue
            obj.get_editor_property(name)
            props.append(name)
        except Exception:
            pass
    return props

def serialize(v):
    if v is None or isinstance(v, (bool, int, float, str)):
        return v
    if isinstance(v, unreal.Name):
        return {"__name__": str(v)}
    if isinstance(v, unreal.Text):
        return {"__text__": str(v)}
    if isinstance(v, unreal.StructBase):
        return {"__struct__": type(v).__name__,
                "fields": {p: serialize(v.get_editor_property(p)) for p in list_props(v)}}
    if isinstance(v, unreal.Array):
        return {"__array__": [serialize(x) for x in v]}
    if isinstance(v, unreal.Object):
        try:
            return {"__object__": v.get_path_name()}
        except Exception:
            return None
    try:
        return {"__enum__": type(v).__name__, "value": int(v)}
    except Exception:
        return None

actors = unreal.get_editor_subsystem(unreal.EditorActorSubsystem).get_selected_level_actors()
if not actors:
    unreal.log_warning("[QM] Select a source camera first")
else:
    c = get_cam(actors[0])
    if not c:
        unreal.log_warning(f"[QM] No camera component on '{actors[0].get_actor_label()}'")
    else:
        data = {"class": type(c).__name__,
                "props": {p: serialize(c.get_editor_property(p)) for p in list_props(c)}}
        with open(CLIP, "w") as f:
            json.dump(data, f, indent=2)
        unreal.log(f"[QM] {data['class']} copied from '{actors[0].get_actor_label()}' ({len(data['props'])} props)")

#workflow #camera #clipboard #cinecamera

W

Paste Camera Settings

Applies every saved property from the camera clipboard to the selected camera(s), wrapped in a single editor transaction so Ctrl+Z undoes the whole paste.

Execute

import json
import os

CLIP = os.path.join(unreal.Paths.project_intermediate_dir(), "qm_camera_clipboard.json")

def get_cam(actor):
    return (actor.get_component_by_class(unreal.CineCameraComponent)
            or actor.get_component_by_class(unreal.CameraComponent))

def deserialize(d):
    if d is None or isinstance(d, (bool, int, float, str)):
        return d
    if isinstance(d, dict):
        if "__name__" in d:
            return unreal.Name(d["__name__"])
        if "__text__" in d:
            return unreal.Text(d["__text__"])
        if "__struct__" in d:
            cls = getattr(unreal, d["__struct__"], None)
            if cls is None:
                return None
            s = cls()
            for k, v in d["fields"].items():
                try:
                    s.set_editor_property(k, deserialize(v))
                except Exception:
                    pass
            return s
        if "__array__" in d:
            return [deserialize(x) for x in d["__array__"]]
        if "__enum__" in d:
            cls = getattr(unreal, d["__enum__"], None)
            try:
                return cls(d["value"]) if cls else d["value"]
            except Exception:
                return d["value"]
        if "__object__" in d:
            try:
                return unreal.load_object(None, d["__object__"])
            except Exception:
                return None
    return None

if not os.path.exists(CLIP):
    unreal.log_warning("[QM] Camera clipboard empty — run Copy Camera Settings first")
else:
    with open(CLIP) as f:
        data = json.load(f)
    actors = unreal.get_editor_subsystem(unreal.EditorActorSubsystem).get_selected_level_actors()
    if not actors:
        unreal.log_warning("[QM] Select at least one target camera")
    else:
        ok, skipped, fails = 0, 0, 0
        with unreal.ScopedEditorTransaction("QM Paste Camera Settings"):
            for a in actors:
                c = get_cam(a)
                if not c:
                    skipped += 1
                    continue
                for name, raw in data["props"].items():
                    try:
                        c.set_editor_property(name, deserialize(raw))
                    except Exception:
                        fails += 1
                ok += 1
        unreal.log(f"[QM] Camera pasted: {ok} target(s), {skipped} skipped, {fails} prop(s) failed")

#workflow #camera #paste #cinecamera

UI

Hide Paste Until Clipboard Set

Returns True only when the camera clipboard JSON exists on disk. Paste in Is Visible Code on a Paste-Camera wedge so the action disappears until you've actually copied a camera.

Visible

import os
result = os.path.exists(os.path.join(unreal.Paths.project_intermediate_dir(), "qm_camera_clipboard.json"))

#dynamic #visibility #camera

Writing your own

See Custom Python Actions for the full guide on creating new Custom Code nodes — including the three code fields, dynamic labels, and conditional visibility.