Zrythm v2.0.0-alpha.1
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
resize_arranger_objects_command.h
1// SPDX-FileCopyrightText: © 2025 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3
4#pragma once
5
6#include <algorithm>
7#include <optional>
8#include <ranges>
9#include <vector>
10
11#include "structure/arrangement/arranger_object_all.h"
12
13#include <QUndoCommand>
14
15namespace zrythm::commands
16{
17Q_NAMESPACE
18
20enum class ResizeType : int
21{
22 Bounds = 0,
23 LoopPoints = 1,
24 Fades = 2
25};
26Q_ENUM_NS (ResizeType)
27
28
29enum class ResizeDirection : int
30{
31 FromStart = 0,
32 FromEnd = 1
33};
34Q_ENUM_NS (ResizeDirection)
35
36class ResizeArrangerObjectsCommand : public QUndoCommand
37{
38 static constexpr int ID = 1762503480;
39
40public:
43 {
44 units::precise_tick_t position = units::ticks (0);
45 units::precise_tick_t length = units::ticks (0);
46 units::precise_tick_t clipStart = units::ticks (0);
47 units::precise_tick_t loopStart = units::ticks (0);
48 units::precise_tick_t loopEnd = units::ticks (0);
49 bool boundsTracked{};
50 units::precise_tick_t fadeInOffset = units::ticks (0);
51 units::precise_tick_t fadeOutOffset = units::ticks (0);
52 // First child's original position (nullopt when the object has no
53 // children). Used to restore child positions on undo.
54 std::optional<units::precise_tick_t> firstChildTicks;
55 };
56
57 ResizeArrangerObjectsCommand (
58 std::vector<structure::arrangement::ArrangerObjectUuidReference> objects,
59 ResizeType type,
60 ResizeDirection direction,
61 double delta);
62
63 int id () const override { return ID; }
64
65 bool mergeWith (const QUndoCommand * other) override
66 {
67 if (other->id () != id ())
68 return false;
69
70 // Only merge if other command was made in quick succession of this
71 // command's redo() and operates on the same objects
72 const auto * other_cmd =
73 dynamic_cast<const ResizeArrangerObjectsCommand *> (other);
74 const auto cur_time = std::chrono::steady_clock::now ();
75 const auto duration = cur_time - last_redo_timestamp_;
76 if (
77 std::chrono::duration_cast<std::chrono::milliseconds> (duration).count ()
78 > 1'000)
79 {
80 return false;
81 }
82
83 // Check if we're operating on the same set of objects, type, and direction
84 if (type_ != other_cmd->type_ || direction_ != other_cmd->direction_)
85 return false;
86
87 if (objects_.size () != other_cmd->objects_.size ())
88 return false;
89
90 if (
91 !std::ranges::equal (
92 objects_, other_cmd->objects_, {},
93 &structure::arrangement::ArrangerObjectUuidReference::id,
94 &structure::arrangement::ArrangerObjectUuidReference::id))
95 {
96 return false;
97 }
98
99 last_redo_timestamp_ = cur_time;
100 delta_ += other_cmd->delta_;
101 return true;
102 }
103
104 void undo () override;
105 void redo () override;
106
107private:
108 std::vector<structure::arrangement::ArrangerObjectUuidReference> objects_;
109 ResizeType type_;
110 ResizeDirection direction_;
111 double delta_;
112
113 // Original state storage for undo
114 std::vector<OriginalState> original_states_;
115
116 std::chrono::time_point<std::chrono::steady_clock> last_redo_timestamp_;
117};
118
119} // namespace zrythm::commands
Structure to hold original state of an arranger object for undo.