Up until now Module
s were rendered by simple rectangles with text on top of them to signal what they consume and produce.
I improved the rendering to also show all Structures
within the Module
.
There’s now also a slight overlay to indicate that this is a Module
and not multiple Structure
s.
Production and consumption are now also shown at the respective Source
or Sink
, while these are rendered slightly differently to better indicate that they are the ‘edges’ of a Module
and not freely placed Source
s or Sink
s.
Since the internals of Module
s aren’t animated, the render Node
of a Module
will ‘never’ change (unless specific render settings are altered).
This makes it possible to cache their render Node
s.
For this I first wrapped the Node
type:
pub enum RcNode {
Node(Node),
Rc(Rc<Node>),
}
An RcNode
is either a simple Node
(just as before), or an Rc<Node>
. Rc is a reference counting pointer and in this use case allows for very cheap copies.
I then changed BranchNode
to hold RcNode
s as children:
pub struct BranchNode {
...
pub children: Vec<RcNode>,
}
This way it’s now possible to create render trees with cheap-to-copy Node
s.
I also added:
pub struct ModuleNodeStore {
cache: RefCell<BTreeMap<ModuleDefinitionID, Rc<Node>>>,
}
to take care of the caching of Module
render Node
s.
It either returns an already generated Node
, or generates one, then caches and returns it:
impl ModuleNodeStore {
pub fn get(&self, module_store: &dyn ModuleStore, i: ModuleDefinitionID) -> Option<Rc<Node>> {
if i.0 >= module_store.len() {
return None;
}
if let Some(node) = self.cache.borrow().get(&i).cloned() {
return Some(node);
}
let new_node = self.new_node(module_store, &*module_store.get(i).unwrap_condition());
self.cache.borrow_mut().insert(i, new_node.clone());
Some(new_node)
}
...
}
By using ModuleNodeStore
the render Node
of every Module
is only generated once.