Skip to content

Commit

Permalink
Basic duplciate, copy, and paste of zone (#1486)
Browse files Browse the repository at this point in the history
All in the sidebar control, still no cut, menu state not
there, no keybinding.

But addresses #1483
  • Loading branch information
baconpaul authored Jan 25, 2025
1 parent 3a9f958 commit cb034b4
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 0 deletions.
28 changes: 28 additions & 0 deletions src-ui/app/edit-screen/components/GroupZoneTreeControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,12 +250,34 @@ template <typename SidebarParent, bool fz> struct GroupZoneListBoxModel : juce::
return;
w->doZoneRename();
});

p.addItem("Copy", [w = juce::Component::SafePointer(this)]() {
if (!w)
return;
auto za = w->getZoneAddress();
w->gsb->sendToSerialization(cmsg::CopyZone(za));
});

p.addItem("Paste", [w = juce::Component::SafePointer(this)]() {
if (!w)
return;
auto za = w->getZoneAddress();
w->gsb->sendToSerialization(cmsg::PasteZone(za));
});

p.addItem("Duplicate", [w = juce::Component::SafePointer(this)]() {
if (!w)
return;
auto za = w->getZoneAddress();
w->gsb->sendToSerialization(cmsg::DuplicateZone(za));
});
p.addItem("Delete", [w = juce::Component::SafePointer(this)]() {
if (!w)
return;
auto za = w->getZoneAddress();
w->gsb->sendToSerialization(cmsg::DeleteZone(za));
});
p.addSeparator();
p.addItem("Delete All Selected Zones",
[w = juce::Component::SafePointer(this)]() {
if (!w)
Expand All @@ -279,6 +301,12 @@ template <typename SidebarParent, bool fz> struct GroupZoneListBoxModel : juce::
return;
w->doGroupRename();
});
p.addItem("Paste Zone", [w = juce::Component::SafePointer(this)]() {
if (!w)
return;
auto za = w->getZoneAddress();
w->gsb->sendToSerialization(cmsg::PasteZone(za));
});
p.addItem("Delete", [w = juce::Component::SafePointer(this)]() {
if (!w)
return;
Expand Down
81 changes: 81 additions & 0 deletions src/engine/engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,87 @@ void Engine::createEmptyZone(scxt::engine::KeyboardRange krange, scxt::engine::V
});
}

void Engine::copyZone(const selection::SelectionManager::ZoneAddress &s)
{
auto &zoneO = getPatch()->getPart(s.part)->getGroup(s.group)->getZone(s.zone);
auto v = json::scxt_value(*zoneO);
zoneClipboard = tao::json::msgpack::to_string(v);
}

void Engine::pasteZone(const selection::SelectionManager::ZoneAddress &a)
{
if (zoneClipboard.empty())
return;
tao::json::events::transformer<tao::json::events::to_basic_value<json::scxt_traits>> consumer;
tao::json::msgpack::events::from_string(consumer, zoneClipboard);
auto v = std::move(consumer.value);
auto zptr = std::make_unique<Zone>();
v.to(*zptr);

zptr->setupOnUnstream(*this);

auto sp = a.part;
;
auto sg = a.group;
;

// 3. Send a message to the audio thread saying to add that zone and
messageController->scheduleAudioThreadCallbackUnderStructureLock(
[sp = sp, sg = sg, zone = zptr.release()](auto &e) {
std::unique_ptr<Zone> zptr;
zptr.reset(zone);
e.getPatch()->getPart(sp)->guaranteeGroupCount(sg + 1);
e.getPatch()->getPart(sp)->getGroup(sg)->addZone(zptr);

// 4. have the audio thread message back here to refresh the ui
messaging::audio::sendStructureRefresh(*(e.getMessageController()));
},
[sp = sp, sg = sg](auto &e) {
auto &g = e.getPatch()->getPart(sp)->getGroup(sg);
int32_t zi = g->getZones().size() - 1;
e.getSelectionManager()->selectAction({sp, sg, zi, true, true, true});
});
}

void Engine::duplicateZone(const selection::SelectionManager::ZoneAddress &s)
{
assert(messageController->threadingChecker.isSerialThread());

// 2. Create a zone object on this thread but don't add it
auto &zoneO = getPatch()->getPart(s.part)->getGroup(s.group)->getZone(s.zone);
auto v = json::scxt_value(*zoneO);
auto zptr = std::make_unique<Zone>();
v.to(*zptr);

zptr->setupOnUnstream(*this);

// give it a name
zptr->givenName = zoneO->getName() + " (copy)";

// Drop into selected group logic goes here
auto sp = s.part;
;
auto sg = s.group;
;

// 3. Send a message to the audio thread saying to add that zone and
messageController->scheduleAudioThreadCallbackUnderStructureLock(
[sp = sp, sg = sg, zone = zptr.release()](auto &e) {
std::unique_ptr<Zone> zptr;
zptr.reset(zone);
e.getPatch()->getPart(sp)->guaranteeGroupCount(sg + 1);
e.getPatch()->getPart(sp)->getGroup(sg)->addZone(zptr);

// 4. have the audio thread message back here to refresh the ui
messaging::audio::sendStructureRefresh(*(e.getMessageController()));
},
[sp = sp, sg = sg](auto &e) {
auto &g = e.getPatch()->getPart(sp)->getGroup(sg);
int32_t zi = g->getZones().size() - 1;
e.getSelectionManager()->selectAction({sp, sg, zi, true, true, true});
});
}

void Engine::sendMetadataToClient() const
{
// On register send metadata
Expand Down
4 changes: 4 additions & 0 deletions src/engine/engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,10 @@ struct Engine : MoveableOnly<Engine>, SampleRateSupport
VelocityRange vrange = {0, 127});

void createEmptyZone(KeyboardRange krange = {48, 72}, VelocityRange vrange = {0, 127});
void duplicateZone(const selection::SelectionManager::ZoneAddress &);
void copyZone(const selection::SelectionManager::ZoneAddress &);
void pasteZone(const selection::SelectionManager::ZoneAddress &);
std::string zoneClipboard;

void loadSf2MultiSampleIntoSelectedPart(const fs::path &);

Expand Down
3 changes: 3 additions & 0 deletions src/messaging/client/client_serial.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ enum ClientToSerializationMessagesIds
c2s_create_group,
c2s_move_zone,
c2s_delete_zone,
c2s_duplicate_zone,
c2s_copy_zone,
c2s_paste_zone,
c2s_add_blank_zone,
c2s_delete_selected_zones,
c2s_delete_group,
Expand Down
7 changes: 7 additions & 0 deletions src/messaging/client/structure_messages.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,13 @@ inline void removeZone(const selection::SelectionManager::ZoneAddress &a, engine
CLIENT_TO_SERIAL(DeleteZone, c2s_delete_zone, selection::SelectionManager::ZoneAddress,
removeZone(payload, engine, cont));

CLIENT_TO_SERIAL(DuplicateZone, c2s_duplicate_zone, selection::SelectionManager::ZoneAddress,
engine.duplicateZone(payload));
CLIENT_TO_SERIAL(CopyZone, c2s_copy_zone, selection::SelectionManager::ZoneAddress,
engine.copyZone(payload));
CLIENT_TO_SERIAL(PasteZone, c2s_paste_zone, selection::SelectionManager::ZoneAddress,
engine.pasteZone(payload));

inline void removeSelectedZones(const bool &, engine::Engine &engine, MessageController &cont)
{
auto part = engine.getSelectionManager()->selectedPart;
Expand Down

0 comments on commit cb034b4

Please sign in to comment.