1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// src/editor/hook/duplicate.rs
//
// EditorHook: duplicate the selection in place (Ctrl+D, /dup). Each selected
// authored entry is cloned with all its args -- position included, so the copy
// sits exactly on the original until it is dragged away -- under a unique
// name. The copies become the new selection (ready to move), and the whole
// batch commits as ONE undo step.
use super::*;
impl EditorHook {
// Duplicate every eligible selection member; the number of copies made.
// Skipped: generated assets (no authored entry to clone) and singleton
// types (a second instance is a cook error).
pub(super) fn duplicate_selection(&mut self) -> usize {
let names: Vec<String> = self.selection.iter().map(String::from).collect();
let mut copies = Vec::new();
for name in &names {
let Some(idx) = self
.entries
.iter()
.position(|e| entry_name(e) == Some(name))
else {
continue;
};
let Some(ty) = entry_type(&self.entries[idx]) else {
continue;
};
if panel::is_singleton(ty) {
continue;
}
let mut clone = self.entries[idx].clone();
let new_name = self.unique_from(name);
if let Some(obj) = clone.as_object_mut() {
obj.insert(
"name".to_string(),
serde_json::Value::String(new_name.clone()),
);
}
self.entries.push(clone);
copies.push(new_name);
}
if copies.is_empty() {
return 0;
}
self.mark_changed();
let made = copies.len();
self.selection.set(copies);
made
}
}