Skip to content

Core Classes

The main methods - start, update and done - all receive the core object. This holds references to most of OmniStep's systems: inputs, player, scene, and overlay. Below are the most relevant properties and methods for each.

core.scene.state

The Scene has a state dataclass that holds the most relevant scene-related variables.
Access pattern: core.scene.state.target_timestep

timer: bpy.types.Timer = None       # main modal timer

target_timestep: float = 0.0        # what it should be 
current_timestep: float = 0.0       # actual viewport timestep
scene_timestep: float = 0.0         # 1.0 / scene_framerate
physics_timestep: float = 0.0       # defaults to 1.0 / 120
use_fixed_timestep: bool = False    # Animation Option
max_timestep: float = 0.0           # upper limit to avoid glitching through walls

collision_samples: int = 0

IDLE = "Idle"
PREROLL = "Preroll"
RECORDING = "Recording"
END = "End"

record_state: str = IDLE

current_frame: int = 0              # Which frame the scene is on when playback is active, or recording playhead if not active
scene_framerate: float = 0          # set framerate of the scene (can be fractional because of base)
write_frame: bool = False           # True for one loop, iteration when recording should happen

modal_frame_count: int = 0          # internal frame counter (modal frames)

camera: bpy.types.Object = None     # Current camera or None

enable_animation: bool = False      # Master Switch
record_camera: bool = False         # Are we recording? only if camera is valid and enable_animation

scale: float = 0.0                  # from settings, scene scale
gravity: float = 0.0                # from settings, scene gravity (with scale applied)

core.scene.bvh

The scene BVH provides spatial queries against OmniStep's collision system. All methods query both static and animated geometry, returning the closest result. Collections excluded in the Collision settings are automatically ignored.

core.scene.bvh.find_nearest(pos, distance=1.84467e+19)

Finds the closest point on any collision surface to the given position. Queries both the static BVH and all animated objects, returning whichever is closer. :::params pos (Vector) - Query position in world space. distance (float) - (Optional) maximum search distance. :::return location, normal, index, distance (Vector, Vector, int, float) - Values will all be None if nothing is found within range.

core.scene.bvh.ray_cast(pos, vec, distance=1.84467e+19)

Casts a ray into the scene. This is magnitudes faster than the Blender scene raycast, as it uses only the internal BVH-tree. It respects only objects that are part of OmniStep's collision system, both dynamic and static. :::params pos (Vector) - Ray origin. vec (Vector) - Ray direction. distance (float) - (Optional) maximum distance. :::return location, normal, index, distance (Vector, Vector, int, float) - Values will all be None if no hit is found.

core.scene.bvh.ray_cast_delta(pos, vec, distance=1.84467e+19)

Casts a ray and returns a delta matrix representing the frame-to-frame movement of the hit object. Only works against animated objects — returns None if the ray hits static geometry or nothing. The delta rotation is constrained to the Z-axis to keep the player upright. Useful for platform movement and moving elevators. :::params pos (Vector) - Ray origin. vec (Vector) - Ray direction. distance (float) - (Optional) maximum distance. :::return delta (Matrix) - 4x4 matrix with Z-rotation and translation, or None.

core.scene.bvh.get_last_hit_object()

Returns the animated object from the last find_nearest or ray_cast query. Returns None if the closest hit was static geometry or if no hit occurred. Call this immediately after a query — the result is cleared each frame. :::return obj (Object) - The Blender object that was hit, or None.

core.scene.bvh.add_animated(obj)

Adds an object to the animated collision cache. The object will be included in all subsequent ray_cast, find_nearest, and ray_cast_delta queries. Has no effect if the object is already in the cache. :::params obj (Object) - Mesh object to add.

core.scene.bvh.remove_animated(name)

Removes an object from the animated collision cache by name. Uses name instead of a direct reference because the object may already have been deleted. :::params name (string) - Name of the object to remove.

core.overlay

core.overlay.message(text, time=None)

Displays a temporary message at the bottom center of the viewport. The message fades out automatically. Style and default duration can be set in the add-on preferences. :::params text (string) - Text to display. time (float) - (Optional) display duration in seconds. Defaults to the value set in add-on preferences.

core.overlay.log(text)

Prints a line to the on-screen console. Repeated identical messages are collapsed into a single line with a count. Long messages are automatically wrapped. The console displays up to 15 lines. :::params text (string) - Text to print.

core.input.state

All inputs are accessed through core.input.state using bracket notation. Each entry is an InputItem with a phase and a pressed state:

core.input.state['forward'].phase      # InputItem.IDLE / DOWN / HOLD / UP
core.input.state['forward'].pressed    # bool (raw held state)

Phases follow this lifecycle:

InputItem.IDLE      # No input (continuous)
InputItem.DOWN      # Just pressed (true for one frame)
InputItem.HOLD      # Being held (continuous)
InputItem.UP        # Just released (true for one frame)

Example usage:

1
2
3
4
5
6
7
def update(self, context, core):
    if core.input.state['action1'].phase == InputItem.DOWN:
        # Fire once on press
        pass
    if core.input.state['action1'].phase == InputItem.HOLD:
        # Continuous while held
        pass

Available Keys

All key bindings are defined in the add-on preferences.

# Actions (used by modules and scripts)
core.input.state['action1']         # InputItem
core.input.state['action2']         # InputItem
core.input.state['action3']         # InputItem
core.input.state['action4']         # InputItem
core.input.state['action5']         # InputItem
core.input.state['action6']         # InputItem

# Movement
core.input.state['forward']         # InputItem
core.input.state['back']            # InputItem
core.input.state['left']            # InputItem
core.input.state['right']           # InputItem
core.input.state['up']              # InputItem
core.input.state['down']            # InputItem
core.input.state['jump']            # InputItem
core.input.state['crouch']          # InputItem
core.input.state['speed']           # InputItem
core.input.state['speed_up']        # InputItem
core.input.state['speed_down']      # InputItem
core.input.state['speed_reset']     # InputItem

# System
core.input.state['toggle']          # InputItem
core.input.state['respawn']         # InputItem
core.input.state['teleport']        # InputItem
core.input.state['restart']         # InputItem
core.input.state['pause']           # InputItem
core.input.state['alt_done']        # InputItem

Analog Inputs

Mouse and gamepad analog data are accessed directly on core.input.state:

core.input.state.mouse_move         # Vector — mouse delta (respects input smoothing)
core.input.state.mouse_pos          # Vector — smoothed mouse position
core.input.state.direction          # Vector — combined movement input (keyboard + gamepad, normalized)
core.input.state.roll               # float  — roll input (gamepad only, fly mode)
core.input.state.pad_raw_move       # Vector — raw gamepad left stick
core.input.state.pad_raw_look       # Vector — raw gamepad right stick

Input Overrides

core.input.override_move_input(input_x=None, input_y=None, input_z=None)

Overrides the movement direction vector for this frame. Pass None for any axis to keep its current value. Values are not normalized — set -1 to 1 for normal range. :::params input_x (float) - (Optional) strafe axis. input_y (float) - (Optional) forward/back axis. input_z (float) - (Optional) up/down axis.

core.input.override_look_input(delta_pitch=None, delta_yaw=None, delta_roll=None)

Overrides the look input for this frame. Adds rotational deltas as if they came from the mouse or gamepad. Pass None for any axis to leave it unchanged. :::params delta_pitch (float) - (Optional) vertical look delta. delta_yaw (float) - (Optional) horizontal look delta. delta_roll (float) - (Optional) roll delta.

core.player.state

The Player has a state dataclass that holds position, orientation, movement, and grounding data.
Access pattern: core.player.state.velocity

Helpers

Where possible, use the derived helpers like view_pos, view_vec, etc. They are easier to work with than the raw transform hierarchy.

# Transform Hierarchy (TransformNodes, documented below)
root: TransformNode         # player root position
base: TransformNode         # yaw (+ pitch/roll in trackball mode)
head: TransformNode         # pitch + vertical offset from base
cam: TransformNode          # eye/neck offset only
aim: TransformNode          # root @ base @ head @ cam (no effects)
view: TransformNode         # full chain including inertia + effects
effect: TransformNode       # module-driven effects (bob, lean, etc.)
inertia: TransformNode      # camera motion inertia effect

override: bpy.types.Object  # if set, the view matrix is NOT written by Player — script is responsible

# Derived Helpers
view_pos: Vector            # final camera world position
view_vec: Vector            # final camera forward direction
view_mat: Matrix            # final camera 4x4 world matrix
aim_pos: Vector             # aim position (without effects)
aim_vec: Vector             # aim forward direction (without effects)
aim_mat: Matrix             # aim 4x4 world matrix
root_pos: Vector            # root world position
root_mat: Matrix            # root 4x4 world matrix

# Movement
velocity: Vector            # current movement velocity
real_velocity: Vector       # measured velocity (position delta)
real_accel: Vector          # measured acceleration
platform_velocity: Vector   # inherited from animated platforms

# Orientation
pitch: float                # current pitch angle
yaw: float                  # current yaw angle
bank: float                 # current banking angle
roll_delta: float           # trackball roll input

# Grounding
ground_distance: float      # distance to ground surface
ground_normal: Vector       # surface normal at ground contact
ground_slope: float         # slope angle at ground contact
is_grounded: bool           # standing on valid ground
is_contact: bool            # touching any surface below
is_top_contact: bool        # touching surface above (head)
is_stair: bool              # on a stair step

# State Flags
is_teleport: bool           # currently teleporting
wish_jump: bool             # jump requested

# View
current_focal: float        # current focal length in mm

core.player

core.player.set_position(pos, clear_velocity=False)

Sets the player root position. Has no effect during a teleport. :::params pos (Vector) - New world position. clear_velocity (bool) - (Optional) reset velocity to zero.

core.player.apply_impulse(vec, clear_velocity=False)

Applies a velocity impulse to the player. The impulse is applied on the next physics step, not immediately. Has no effect during a teleport. :::params vec (Vector) - Impulse vector in world space. clear_velocity (bool) - (Optional) reset existing velocity before applying the impulse.

core.player.spawn_at_obj(obj=None)

Teleports the player to an object's position and orientation. If obj is a Camera, the view aligns to match the camera. If obj is any other type, position and rotation are read from its world matrix. If None, the player respawns at the next spawn point. Has no effect during a teleport. :::params obj (Object) - (Optional) target object. Pass None to use spawn points.

core.player.ray_cast_player(pos, vec)

Casts a ray against the player's collision shape — a sphere in Fly mode, a capsule (three spheres) in Walk mode. Useful for testing if something can see or hit the player. :::params pos (Vector) - Ray origin. vec (Vector) - Ray direction. :::return location, normal, distance (Vector, Vector, float) - Hit data, or all None if no intersection.

core.player.set_fov(fov)

Sets the current focal length. Works in both camera and viewport mode. :::params fov (float) - Focal length in millimeters.

core.player.align_root(normal, limit_deg=None)

Tilts the player root to align with a surface normal, clamped to avoid extreme angles. Only affects the X and Y rotation axes — yaw (Z) is preserved. Useful for walking on curved or angled surfaces. :::params normal (Vector) - Target up direction. limit_deg (float) - (Optional) maximum tilt in degrees. Defaults to 45.


TransformNode

TransformNode is a lightweight transform object that wraps position, rotation, and scale into a single unit with a 4x4 matrix that stays in sync automatically. It can be used freely in scripts and modules to represent any point or object in the scene - spawn points, targets, waypoints, or custom objects. If linked to a Blender object, changes to the node are written to the object's matrix_world automatically. Multiple nodes can be combined by multiplying their matrices to build transform hierarchies - this is how the player's view is assembled from root → base → head → cam. Note that the player's view-related nodes use -Z as forward to match Blender's view matrix convention.

TransformNode(position, rotation, scale, obj=None)

Creates a new TransformNode. If obj is provided, the node initializes from the object's world matrix and keeps it in sync on every change. :::params position (Vector) - Initial position. Defaults to (0, 0, 0). rotation (Euler) - Initial rotation. Defaults to (0, 0, 0). scale (Vector) - Initial scale. Defaults to (1, 1, 1). obj (Object) - (Optional) Blender object to bind to.

Position

node.translate(vector, space='global')

Moves the node by the given vector. In 'local' space, the vector is transformed by the node's current rotation before applying. :::params vector (Vector) - Translation offset. space (string) - (Optional) 'global' or 'local'. Defaults to 'global'.

node.set_position(position)

Sets the node's world position directly. :::params position (Vector) - New position.

node.get_position()

Returns the node's world position extracted from its matrix. :::return position (Vector) - Current world position.

Rotation

node.set_rotation(rotation)

Sets the node's rotation directly. :::params rotation (Euler) - New rotation.

node.get_rotation()

Returns the node's current rotation as Euler angles. :::return rotation (Euler) - Current rotation.

node.get_rotation_quaternion()

Returns the node's current rotation as a quaternion. :::return rotation (Quaternion) - Current rotation.

node.rotate(euler_angles)

Applies an incremental rotation to the node's current rotation. :::params euler_angles (Euler) - Rotation to add.

node.rotate_axis(angle, axis, space='global')

Rotates the node around an arbitrary axis. In 'global' space, the rotation is applied before the current matrix. In 'local' space, it is applied after. :::params angle (float) - Rotation angle in radians. axis (Vector) - Axis to rotate around. space (string) - (Optional) 'global' or 'local'. Defaults to 'global'.

node.look_at(target, up='Z', factor=1.0)

Rotates the node to face a target position. Uses spherical interpolation, so factor can be used for smooth tracking over multiple frames. :::params target (Vector) - World position to look at. up (string) - (Optional) up axis. Defaults to 'Z'. factor (float) - (Optional) interpolation factor, 0 to 1. Use 1.0 for instant alignment.

Scale

node.set_scale(scale)

Sets the node's scale. :::params scale (Vector) - New scale.

node.get_scale()

Returns the node's current scale extracted from its matrix. :::return scale (Vector) - Current scale.

Direction Vectors

node.forward()

Returns the node's local forward direction (Y+) in world space. :::return direction (Vector) - Forward vector.

node.right()

Returns the node's local right direction (X+) in world space. :::return direction (Vector) - Right vector.

node.up()

Returns the node's local up direction (Z+) in world space. :::return direction (Vector) - Up vector.

Matrix

node.set_matrix(matrix)

Sets the node's full 4x4 matrix directly. Position, rotation, and scale are decomposed from the matrix. :::params matrix (Matrix) - 4x4 transformation matrix.

node.align_to(other)

Copies the full transform from another TransformNode. :::params other (TransformNode) - Source node to copy from.