150 lines
3.8 KiB
C++
150 lines
3.8 KiB
C++
#include "ElectronicCircuitNode.h"
|
|
|
|
#include "TerminalNode.h"
|
|
#include "WireNode.h"
|
|
#include "LogicGateNode.h"
|
|
|
|
#include "LineNode.h"
|
|
|
|
#include "FileLogger.h"
|
|
|
|
ElectronicCircuitNode::ElectronicCircuitNode(const Transform& transform)
|
|
: AbstractVisualNode(transform)
|
|
{
|
|
|
|
}
|
|
|
|
ElectronicCircuitNode::~ElectronicCircuitNode()
|
|
{
|
|
|
|
}
|
|
|
|
void ElectronicCircuitNode::setContent(ElectronicCircuit* content)
|
|
{
|
|
mContent = content;
|
|
mContentDirty = true;
|
|
}
|
|
|
|
void ElectronicCircuitNode::buildWireConnections()
|
|
{
|
|
mWireInputConnections.clear();
|
|
mWireOutputConnections.clear();
|
|
|
|
for (auto terminal : mContent->getInputTerminals())
|
|
{
|
|
mWireOutputConnections[terminal->getConnection()] = terminal;
|
|
}
|
|
|
|
for (auto gate : mContent->getLogicGates())
|
|
{
|
|
for (std::size_t idx = 0; idx < gate->getNumInputs(); idx++)
|
|
{
|
|
mWireInputConnections[gate->getInput(idx)] = gate;
|
|
}
|
|
|
|
for (std::size_t idx = 0; idx < gate->getNumOutputs(); idx++)
|
|
{
|
|
mWireOutputConnections[gate->getOutput(idx)] = gate;
|
|
}
|
|
}
|
|
|
|
for (auto terminal : mContent->getOutputTerminals())
|
|
{
|
|
mWireInputConnections[terminal->getConnection()] = terminal;
|
|
}
|
|
}
|
|
|
|
void ElectronicCircuitNode::createOrUpdateGeometry(SceneInfo*)
|
|
{
|
|
mInputTerminalNodes.clear();
|
|
mWireNodes.clear();
|
|
mLogicGateNodes.clear();
|
|
|
|
buildWireConnections();
|
|
|
|
// Layout terminals
|
|
double terminal_vertical_spacing = 100;
|
|
double terminal_left_margin = 10;
|
|
|
|
double terminal_y = 10;
|
|
for (auto terminal : mContent->getInputTerminals())
|
|
{
|
|
Point loc{ terminal_left_margin, terminal_y };
|
|
auto terminal_node = std::make_unique<TerminalNode>(Transform(loc));
|
|
|
|
terminal_node->setContent(terminal);
|
|
|
|
addChild(terminal_node.get());
|
|
|
|
mNodesForContent[terminal] = terminal_node.get();
|
|
mInputTerminalNodes.push_back(std::move(terminal_node));
|
|
|
|
terminal_y += terminal_vertical_spacing;
|
|
}
|
|
|
|
// Layout logic gates
|
|
double logic_gate_vertical_spacing = 100;
|
|
double logic_gate_horizontal_spacing = 100;
|
|
|
|
double gate_x = logic_gate_vertical_spacing;
|
|
double gate_y = 0;
|
|
for (auto gate : mContent->getLogicGates())
|
|
{
|
|
Point loc{ gate_x, gate_y };
|
|
auto gate_node = std::make_unique<LogicGateNode>(Transform(loc));
|
|
|
|
gate_node->setContent(gate);
|
|
|
|
addChild(gate_node.get());
|
|
|
|
mNodesForContent[gate] = gate_node.get();
|
|
mLogicGateNodes.push_back(std::move(gate_node));
|
|
|
|
gate_x += logic_gate_vertical_spacing;
|
|
gate_y += logic_gate_horizontal_spacing;
|
|
}
|
|
|
|
// Layout output terminals
|
|
terminal_y = 10;
|
|
double terminal_right_margin = 10;
|
|
unsigned width = 500;
|
|
for (auto terminal : mContent->getOutputTerminals())
|
|
{
|
|
Point loc{ width - terminal_right_margin, terminal_y };
|
|
auto node = std::make_unique<TerminalNode>(Transform(loc));
|
|
|
|
node->setContent(terminal);
|
|
|
|
addChild(node.get());
|
|
|
|
mNodesForContent[terminal] = node.get();
|
|
|
|
mOutputTerminalNodes.push_back(std::move(node));
|
|
|
|
terminal_y += terminal_vertical_spacing;
|
|
}
|
|
|
|
// Add wires
|
|
for (auto wire : mContent->getWires())
|
|
{
|
|
auto start_node = mNodesForContent[mWireOutputConnections[wire]];
|
|
auto end_node = mNodesForContent[mWireInputConnections[wire]];
|
|
|
|
auto wire_node = std::make_unique<WireNode>(Transform());
|
|
wire_node->setInputLocation(start_node->getConnectionLocation(wire));
|
|
wire_node->setOutputLocation(end_node->getConnectionLocation(wire));
|
|
|
|
addChild(wire_node.get());
|
|
|
|
mWireNodes.push_back(std::move(wire_node));
|
|
}
|
|
}
|
|
|
|
void ElectronicCircuitNode::update(SceneInfo* sceneInfo)
|
|
{
|
|
if (mContentDirty)
|
|
{
|
|
createOrUpdateGeometry(sceneInfo);
|
|
mContentDirty = false;
|
|
}
|
|
}
|