Single mechanical restructure commit: - root Cargo.toml = oakapp bin + workspace; one cargo build produces oakapp, oak-cli, oak-worker, liboakengine.dylib - app/rust/src -> src/ (app at repo root, no rust/ nesting) - src/<mod>/rust -> crates/oak<mod>; src/oakcore-rs -> crates/oakcore; src/bindings/oakotio -> crates/oakotio; src/engine/rust -> crates/oakengine (keeps cdylib+staticlib+rlib) - public C headers include/<mod>/ -> crates/oakengine/include/<mod>/ - OFX SDK headers vendored into crates/oakplugin/ofx/ (HostSupport gone) - legacy deleted: old src/ C++ modules, engine/, core/, ffmpeg_bridge/, app/ (Qt), cli/worker C++, root CMakeLists, third_party/KDDockWidgets submodule, otio-install, all build-* output (~40GB) - oakstorage kept but excluded from the workspace (skeleton w/ todos); gpui excluded (own workspace) - verified: cargo build green, cargo test --workspace 1845/0 (with the documented OCIO_RS_* env override for the homebrew OCIO)
337 lines
11 KiB
Rust
337 lines
11 KiB
Rust
// Oak Video Editor - Non-Linear Video Editor
|
|
// Copyright (C) 2026 Oak Team
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
//! Gizmo data types (C++ `src/node/src/gizmo/{gizmo,draggable,point,line,
|
|
//! path,polygon,screen,text}.h`; the C++ classes are `olive::NodeGizmo`,
|
|
//! `DraggableGizmo`, `PointGizmo`, `LineGizmo`, `PathGizmo`,
|
|
//! `PolygonGizmo`, `ScreenGizmo`, `TextGizmo`, plus the `PointF`/`LineF`/
|
|
//! `RectF` carriers from `mathtypes.h`/`line.h`/`text.h`).
|
|
//!
|
|
//! Data only — drawing, hit testing, and mouse handling live in the
|
|
//! facade/app layer, so the C++ drag callbacks (`drag_start`/`drag_move`/
|
|
//! `drag_end`) and `TextGizmo::update_input_html` have no Rust counterpart
|
|
//! here.
|
|
//!
|
|
//! Note: the rough `crate::node::Gizmo` sketch in `node.rs` should
|
|
//! eventually be replaced by the types in this module.
|
|
//!
|
|
//! C++ uses single inheritance (`NodeGizmo` <- `DraggableGizmo` <-
|
|
//! `PointGizmo`/`PathGizmo`/`PolygonGizmo`/`ScreenGizmo`); Rust models
|
|
//! this by flattening the base-class fields into each concrete struct
|
|
//! (the base fields are documented as such on each).
|
|
|
|
use oakcore_rs::{Rational, TimeRange};
|
|
|
|
use crate::value::{AudioParams, NodeValue, VideoParams};
|
|
|
|
/// 2D point (C++ `olive::PointF` in `src/node/src/mathtypes.h`, a de-Qt
|
|
/// replacement for `QPointF`).
|
|
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
|
pub struct PointF {
|
|
/// X coordinate.
|
|
pub x: f64,
|
|
/// Y coordinate.
|
|
pub y: f64,
|
|
}
|
|
|
|
impl PointF {
|
|
/// Construct a point (C++ `PointF(x, y)`).
|
|
pub fn new(x: f64, y: f64) -> Self {
|
|
Self { x, y }
|
|
}
|
|
|
|
/// Whether both coordinates are zero (C++ `is_null()`).
|
|
pub fn is_null(&self) -> bool {
|
|
self.x == 0.0 && self.y == 0.0
|
|
}
|
|
|
|
/// `|x| + |y|` (C++ `manhattan_length()`).
|
|
pub fn manhattan_length(&self) -> f64 {
|
|
self.x.abs() + self.y.abs()
|
|
}
|
|
}
|
|
|
|
/// Line segment (C++ `olive::LineF` in `src/node/src/gizmo/line.h`, a
|
|
/// de-Qt replacement for `QLineF`; data carrier only).
|
|
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
|
pub struct LineF {
|
|
/// Start point (C++ `p1_`).
|
|
pub p1: PointF,
|
|
/// End point (C++ `p2_`).
|
|
pub p2: PointF,
|
|
}
|
|
|
|
/// Rectangle (C++ `olive::RectF` in `src/node/src/gizmo/text.h`, a de-Qt
|
|
/// replacement for `QRectF`; text gizmo rect).
|
|
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
|
pub struct RectF {
|
|
/// Left edge (C++ `x_`).
|
|
pub x: f64,
|
|
/// Top edge (C++ `y_`).
|
|
pub y: f64,
|
|
/// Width (C++ `width_`).
|
|
pub width: f64,
|
|
/// Height (C++ `height_`).
|
|
pub height: f64,
|
|
}
|
|
|
|
/// Loop mode (C++ `enum class LoopMode` in
|
|
/// `src/common/src/loopmode.h`).
|
|
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
|
pub enum LoopMode {
|
|
/// Play once (C++ `k_loop_mode_off`).
|
|
#[default]
|
|
Off,
|
|
/// Repeat the clip (C++ `k_loop_mode_loop`).
|
|
Loop,
|
|
/// Hold first/last frame (C++ `k_loop_mode_clamp`).
|
|
Clamp,
|
|
}
|
|
|
|
/// Sequence/render globals a gizmo draws against (C++ `NodeGlobals` in
|
|
/// `src/node/src/globals.h`).
|
|
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
|
pub struct NodeGlobals {
|
|
/// Video parameters (C++ `video_params_`).
|
|
pub video_params: VideoParams,
|
|
/// Audio parameters (C++ `audio_params_`).
|
|
pub audio_params: AudioParams,
|
|
/// Current time range (C++ `time_`).
|
|
pub time: TimeRange,
|
|
/// Loop mode (C++ `loop_mode_`).
|
|
pub loop_mode: LoopMode,
|
|
}
|
|
|
|
/// Reference to one keyframe track of a node input (C++
|
|
/// `NodeKeyframeTrackReference` in `src/node/src/param.h`). Invalid when
|
|
/// `track` < 0 (C++ default constructs `track_ = -1`).
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct KeyframeTrackReference {
|
|
/// Input id (C++ `NodeInput`'s input string).
|
|
pub input_id: String,
|
|
/// Array element (C++ `NodeInput`'s element; -1 = none).
|
|
pub element: i32,
|
|
/// Track index (C++ `track_`; -1 = invalid).
|
|
pub track: i32,
|
|
}
|
|
|
|
impl Default for KeyframeTrackReference {
|
|
/// C++ default constructor: empty input, `track = -1`.
|
|
fn default() -> Self {
|
|
Self {
|
|
input_id: String::new(),
|
|
element: -1,
|
|
track: -1,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl KeyframeTrackReference {
|
|
/// Whether the reference is usable (C++ `is_valid()`).
|
|
pub fn is_valid(&self) -> bool {
|
|
self.track >= 0
|
|
}
|
|
}
|
|
|
|
/// Drag state for one input (C++ `NodeInputDragger` in
|
|
/// `src/node/src/inputdragger.h`). Data only: the C++ `start`/`drag`/
|
|
/// `end` methods write keyframes and push undo commands — that behavior
|
|
/// belongs to the facade/app layer; the C++ static
|
|
/// `input_being_dragged` flag is global UI state and is not modeled
|
|
/// here.
|
|
#[derive(Clone, Debug)]
|
|
pub struct InputDragger {
|
|
/// Target input/track (C++ `input_`).
|
|
pub input: KeyframeTrackReference,
|
|
/// Time at drag start (C++ `time_`).
|
|
pub time: Rational,
|
|
/// Value at drag start (C++ `start_value_`).
|
|
pub start_value: NodeValue,
|
|
/// Current/last dragged value (C++ `end_value_`).
|
|
pub end_value: NodeValue,
|
|
/// Whether a drag is in progress (C++ `is_started()`).
|
|
pub started: bool,
|
|
}
|
|
|
|
impl Default for InputDragger {
|
|
/// C++ default constructor: no drag in progress, values unset.
|
|
fn default() -> Self {
|
|
Self {
|
|
input: KeyframeTrackReference::default(),
|
|
time: Rational::default(),
|
|
start_value: NodeValue::None,
|
|
end_value: NodeValue::None,
|
|
started: false,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// What the X/Y coordinates emitted during a drag mean (C++
|
|
/// `DraggableGizmo::DragValueBehavior` in
|
|
/// `src/node/src/gizmo/draggable.h`).
|
|
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
|
pub enum DragValueBehavior {
|
|
/// Exact mouse coordinates in sequence pixels (C++ `k_absolute`;
|
|
/// the C++ default).
|
|
#[default]
|
|
Absolute,
|
|
/// Movement since the last move event (C++
|
|
/// `k_delta_from_previous`).
|
|
DeltaFromPrevious,
|
|
/// Movement from the start of the drag (C++ `k_delta_from_start`).
|
|
DeltaFromStart,
|
|
}
|
|
|
|
/// Base gizmo data (C++ `olive::NodeGizmo` private members in
|
|
/// `src/node/src/gizmo/gizmo.h`).
|
|
///
|
|
/// The C++ `parent_` node pointer is omitted: ownership and
|
|
/// registration run through `NodeCore::gizmos` (mirroring
|
|
/// `Node::add_gizmo()`/`remove_gizmo()`), so a back-pointer has no Rust
|
|
/// equivalent here.
|
|
#[derive(Clone, Debug, Default)]
|
|
pub struct GizmoBase {
|
|
/// Sequence globals the gizmo draws against (C++ `globals_`).
|
|
pub globals: NodeGlobals,
|
|
/// Visibility flag (C++ `visible_`).
|
|
pub visible: bool,
|
|
}
|
|
|
|
/// Draggable base data (C++ `olive::DraggableGizmo` in
|
|
/// `src/node/src/gizmo/draggable.h`).
|
|
#[derive(Clone, Debug, Default)]
|
|
pub struct DraggableGizmo {
|
|
/// Base gizmo data (C++ `NodeGizmo` base-class members).
|
|
pub base: GizmoBase,
|
|
/// Keyframed inputs this gizmo drags (C++ `inputs_`; appended by
|
|
/// `add_input()`).
|
|
pub inputs: Vec<KeyframeTrackReference>,
|
|
/// Per-input drag state, parallel to `inputs` (C++ `draggers_`).
|
|
pub draggers: Vec<InputDragger>,
|
|
/// Drag coordinate semantics (C++ `drag_value_behavior_`).
|
|
pub drag_value_behavior: DragValueBehavior,
|
|
}
|
|
|
|
/// Point gizmo shape (C++ `PointGizmo::Shape` in
|
|
/// `src/node/src/gizmo/point.h`).
|
|
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
|
pub enum PointShape {
|
|
/// Square handle (C++ `k_square`; the C++ default constructor's
|
|
/// shape).
|
|
#[default]
|
|
Square,
|
|
/// Circle handle (C++ `k_circle`).
|
|
Circle,
|
|
/// Anchor-point handle (C++ `k_anchor_point`).
|
|
AnchorPoint,
|
|
}
|
|
|
|
/// Point gizmo (C++ `olive::PointGizmo` in
|
|
/// `src/node/src/gizmo/point.h`; base `DraggableGizmo`).
|
|
#[derive(Clone, Debug, Default)]
|
|
pub struct PointGizmo {
|
|
/// Draggable base data (C++ `DraggableGizmo` base-class members).
|
|
pub draggable: DraggableGizmo,
|
|
/// Handle shape (C++ `shape_`).
|
|
pub shape: PointShape,
|
|
/// Handle position in sequence pixels (C++ `point_`).
|
|
pub point: PointF,
|
|
/// Render the handle smaller (C++ `smaller_`).
|
|
pub smaller: bool,
|
|
}
|
|
|
|
/// Line gizmo (C++ `olive::LineGizmo` in `src/node/src/gizmo/line.h`;
|
|
/// base `NodeGizmo`, not draggable).
|
|
#[derive(Clone, Debug, Default)]
|
|
pub struct LineGizmo {
|
|
/// Base gizmo data (C++ `NodeGizmo` base-class members).
|
|
pub base: GizmoBase,
|
|
/// The line in sequence pixels (C++ `line_`).
|
|
pub line: LineF,
|
|
}
|
|
|
|
/// Path gizmo (C++ `olive::PathGizmo` in `src/node/src/gizmo/path.h`;
|
|
/// base `DraggableGizmo`).
|
|
///
|
|
/// The C++ class has no own members — its former `QPainterPath` (a
|
|
/// drawing/hit-test primitive) was removed; path storage and drawing
|
|
/// belong to the app layer. The type is kept so the gizmo hierarchy
|
|
/// remains distinguishable.
|
|
#[derive(Clone, Debug, Default)]
|
|
pub struct PathGizmo {
|
|
/// Draggable base data (C++ `DraggableGizmo` base-class members).
|
|
pub draggable: DraggableGizmo,
|
|
}
|
|
|
|
/// Polygon gizmo (C++ `olive::PolygonGizmo` in
|
|
/// `src/node/src/gizmo/polygon.h`; base `DraggableGizmo`).
|
|
///
|
|
/// Point-in-polygon testing (formerly `QPolygonF::containsPoint`)
|
|
/// belongs to the app layer.
|
|
#[derive(Clone, Debug, Default)]
|
|
pub struct PolygonGizmo {
|
|
/// Draggable base data (C++ `DraggableGizmo` base-class members).
|
|
pub draggable: DraggableGizmo,
|
|
/// Polygon vertices (C++ `polygon_`, de-Qt'd from `QPolygonF` to a
|
|
/// plain vector of points).
|
|
pub polygon: Vec<PointF>,
|
|
}
|
|
|
|
/// Screen gizmo (C++ `olive::ScreenGizmo` in
|
|
/// `src/node/src/gizmo/screen.h`; base `DraggableGizmo`).
|
|
///
|
|
/// The C++ class has no own members; it exists only to distinguish the
|
|
/// whole-screen drag target in the gizmo hierarchy.
|
|
#[derive(Clone, Debug, Default)]
|
|
pub struct ScreenGizmo {
|
|
/// Draggable base data (C++ `DraggableGizmo` base-class members).
|
|
pub draggable: DraggableGizmo,
|
|
}
|
|
|
|
/// Text gizmo vertical alignment (C++ `TextGizmo::VerticalAlignment` in
|
|
/// `src/node/src/gizmo/text.h`, formerly `Qt::Alignment`; values match
|
|
/// the oakengine facade).
|
|
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
|
pub enum VerticalAlignment {
|
|
/// Align to the top (C++ `k_align_top` = 0).
|
|
#[default]
|
|
Top,
|
|
/// Align to the bottom (C++ `k_align_bottom` = 1).
|
|
Bottom,
|
|
/// Align vertically centered (C++ `k_align_vcenter` = 2).
|
|
VCenter,
|
|
}
|
|
|
|
/// Text gizmo (C++ `olive::TextGizmo` in `src/node/src/gizmo/text.h`;
|
|
/// base `NodeGizmo`, not draggable).
|
|
///
|
|
/// `TextGizmo::update_input_html()` (pushing edited HTML back into the
|
|
/// connected input at a time) is behavioral and belongs to the
|
|
/// facade/app layer, so it is not declared here.
|
|
#[derive(Clone, Debug, Default)]
|
|
pub struct TextGizmo {
|
|
/// Base gizmo data (C++ `NodeGizmo` base-class members).
|
|
pub base: GizmoBase,
|
|
/// Text bounds in sequence pixels (C++ `rect_`).
|
|
pub rect: RectF,
|
|
/// HTML content (C++ `text_`).
|
|
pub html: String,
|
|
/// Input track this gizmo edits (C++ `input_`).
|
|
pub input: KeyframeTrackReference,
|
|
/// Vertical alignment (C++ `valign_`).
|
|
pub vertical_alignment: VerticalAlignment,
|
|
}
|