mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-10-23 14:01:37 +00:00
Track both parent and children on instances
This commit is contained in:
parent
1137584cd3
commit
ee108e414f
3 changed files with 112 additions and 20 deletions
|
|
@ -19,4 +19,6 @@ pub struct RbxInstance {
|
|||
|
||||
/// All of the children of this instance. Order is relevant to preserve!
|
||||
pub children: Vec<Id>,
|
||||
|
||||
pub parent: Option<Id>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,12 @@ use session::SessionConfig;
|
|||
use vfs_session::{VfsSession, FileItem, FileChange};
|
||||
use message_session::{Message, MessageSession};
|
||||
|
||||
fn insert_if_missing<T: PartialEq>(vec: &mut Vec<T>, value: T) {
|
||||
if !vec.contains(&value) {
|
||||
vec.push(value);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Rethink data structure and insertion/update behavior. Maybe break some
|
||||
// pieces off into a new object?
|
||||
fn file_to_instances(
|
||||
|
|
@ -16,6 +22,7 @@ fn file_to_instances(
|
|||
partition: &Partition,
|
||||
output: &mut HashMap<Id, RbxInstance>,
|
||||
instances_by_route: &mut HashMap<FileRoute, Id>,
|
||||
parent_id: Option<Id>,
|
||||
) -> (Id, Vec<Id>) {
|
||||
match file_item {
|
||||
FileItem::File { contents, route } => {
|
||||
|
|
@ -37,6 +44,7 @@ fn file_to_instances(
|
|||
class_name: "StringValue".to_string(),
|
||||
properties,
|
||||
children: Vec::new(),
|
||||
parent: parent_id,
|
||||
});
|
||||
|
||||
(primary_id, vec![primary_id])
|
||||
|
|
@ -57,7 +65,7 @@ fn file_to_instances(
|
|||
let mut changed_ids = vec![primary_id];
|
||||
|
||||
for child_file_item in children.values() {
|
||||
let (child_id, mut child_changed_ids) = file_to_instances(child_file_item, partition, output, instances_by_route);
|
||||
let (child_id, mut child_changed_ids) = file_to_instances(child_file_item, partition, output, instances_by_route, Some(primary_id));
|
||||
|
||||
child_ids.push(child_id);
|
||||
changed_ids.push(child_id);
|
||||
|
|
@ -73,6 +81,7 @@ fn file_to_instances(
|
|||
class_name: "Folder".to_string(),
|
||||
properties: HashMap::new(),
|
||||
children: child_ids,
|
||||
parent: parent_id,
|
||||
});
|
||||
|
||||
(primary_id, changed_ids)
|
||||
|
|
@ -110,16 +119,56 @@ impl RbxSession {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn retrieve_instance<'a, 'b>(&'a self, id: Id, output: &'b mut HashMap<Id, &'a RbxInstance>) {
|
||||
let requested_instance = match self.instances.get(&id) {
|
||||
Some(instance) => instance,
|
||||
None => return,
|
||||
};
|
||||
pub fn delete_instance(&mut self, id: Id) -> Vec<Id> {
|
||||
let mut ids_to_visit = vec![id];
|
||||
let mut ids_deleted = Vec::new();
|
||||
|
||||
output.insert(id, requested_instance);
|
||||
for instance in self.instances.values_mut() {
|
||||
match instance.children.iter().position(|&v| v == id) {
|
||||
Some(index) => {
|
||||
instance.children.remove(index);
|
||||
},
|
||||
None => {},
|
||||
}
|
||||
}
|
||||
|
||||
for child_id in &requested_instance.children {
|
||||
self.retrieve_instance(*child_id, output);
|
||||
loop {
|
||||
let id = match ids_to_visit.pop() {
|
||||
Some(id) => id,
|
||||
None => break,
|
||||
};
|
||||
|
||||
match self.instances.get(&id) {
|
||||
Some(instance) => ids_to_visit.extend_from_slice(&instance.children),
|
||||
None => continue,
|
||||
}
|
||||
|
||||
self.instances.remove(&id);
|
||||
ids_deleted.push(id);
|
||||
}
|
||||
|
||||
ids_deleted
|
||||
}
|
||||
|
||||
pub fn get_instance<'a, 'b>(&'a self, id: Id, output: &'b mut HashMap<Id, &'a RbxInstance>) {
|
||||
let mut ids_to_visit = vec![id];
|
||||
|
||||
loop {
|
||||
let id = match ids_to_visit.pop() {
|
||||
Some(id) => id,
|
||||
None => break,
|
||||
};
|
||||
|
||||
match self.instances.get(&id) {
|
||||
Some(instance) => {
|
||||
output.insert(id, instance);
|
||||
|
||||
for child_id in &instance.children {
|
||||
ids_to_visit.push(*child_id);
|
||||
}
|
||||
},
|
||||
None => continue,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -133,7 +182,21 @@ impl RbxSession {
|
|||
route: Vec::new(),
|
||||
};
|
||||
let file_item = vfs_session.get_by_route(&route).unwrap();
|
||||
let (root_id, _) = file_to_instances(file_item, partition, &mut self.instances, &mut self.instances_by_route);
|
||||
|
||||
let parent_id = match route.parent() {
|
||||
Some(parent_route) => match self.instances_by_route.get(&parent_route) {
|
||||
Some(&parent_id) => Some(parent_id),
|
||||
None => None,
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
|
||||
let (root_id, _) = file_to_instances(file_item, partition, &mut self.instances, &mut self.instances_by_route, parent_id);
|
||||
|
||||
if let Some(parent_id) = parent_id {
|
||||
insert_if_missing(&mut self.instances.get_mut(&parent_id).unwrap().children, root_id);
|
||||
}
|
||||
|
||||
self.partition_instances.insert(partition.name.clone(), root_id);
|
||||
}
|
||||
}
|
||||
|
|
@ -146,7 +209,20 @@ impl RbxSession {
|
|||
FileChange::Created(route) | FileChange::Updated(route) => {
|
||||
let file_item = vfs_session.get_by_route(route).unwrap();
|
||||
let partition = self.config.partitions.get(&route.partition).unwrap();
|
||||
let (_, changed_ids) = file_to_instances(file_item, partition, &mut self.instances, &mut self.instances_by_route);
|
||||
|
||||
let parent_id = match route.parent() {
|
||||
Some(parent_route) => match self.instances_by_route.get(&parent_route) {
|
||||
Some(&parent_id) => Some(parent_id),
|
||||
None => None,
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
|
||||
let (root_id, changed_ids) = file_to_instances(file_item, partition, &mut self.instances, &mut self.instances_by_route, parent_id);
|
||||
|
||||
if let Some(parent_id) = parent_id {
|
||||
insert_if_missing(&mut self.instances.get_mut(&parent_id).unwrap().children, root_id);
|
||||
}
|
||||
|
||||
let messages = changed_ids
|
||||
.iter()
|
||||
|
|
@ -156,11 +232,11 @@ impl RbxSession {
|
|||
self.message_session.push_messages(&messages);
|
||||
},
|
||||
FileChange::Deleted(route) => {
|
||||
// TODO: Handle deletion of children here and in Moved case.
|
||||
match self.instances_by_route.get(route) {
|
||||
Some(id) => {
|
||||
self.instances.remove(id);
|
||||
self.message_session.push_messages(&[Message::InstanceChanged { id: *id }]);
|
||||
Some(&id) => {
|
||||
self.delete_instance(id);
|
||||
self.instances_by_route.remove(route);
|
||||
self.message_session.push_messages(&[Message::InstanceChanged { id }]);
|
||||
},
|
||||
None => (),
|
||||
}
|
||||
|
|
@ -169,16 +245,30 @@ impl RbxSession {
|
|||
let mut messages = Vec::new();
|
||||
|
||||
match self.instances_by_route.get(from_route) {
|
||||
Some(id) => {
|
||||
self.instances.remove(id);
|
||||
messages.push(Message::InstanceChanged { id: *id });
|
||||
Some(&id) => {
|
||||
self.delete_instance(id);
|
||||
self.instances_by_route.remove(from_route);
|
||||
messages.push(Message::InstanceChanged { id });
|
||||
},
|
||||
None => (),
|
||||
}
|
||||
|
||||
let file_item = vfs_session.get_by_route(to_route).unwrap();
|
||||
let partition = self.config.partitions.get(&to_route.partition).unwrap();
|
||||
let (_, changed_ids) = file_to_instances(file_item, partition, &mut self.instances, &mut self.instances_by_route);
|
||||
|
||||
let parent_id = match to_route.parent() {
|
||||
Some(parent_route) => match self.instances_by_route.get(&parent_route) {
|
||||
Some(&parent_id) => Some(parent_id),
|
||||
None => None,
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
|
||||
let (root_id, changed_ids) = file_to_instances(file_item, partition, &mut self.instances, &mut self.instances_by_route, parent_id);
|
||||
|
||||
if let Some(parent_id) = parent_id {
|
||||
insert_if_missing(&mut self.instances.get_mut(&parent_id).unwrap().children, root_id);
|
||||
}
|
||||
|
||||
for id in changed_ids {
|
||||
messages.push(Message::InstanceChanged { id });
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ pub fn start(config: WebConfig) {
|
|||
let mut instances = HashMap::new();
|
||||
|
||||
for requested_id in &requested_ids {
|
||||
rbx_session.retrieve_instance(*requested_id, &mut instances);
|
||||
rbx_session.get_instance(*requested_id, &mut instances);
|
||||
}
|
||||
|
||||
Response::json(&ReadResponse {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue