#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(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(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(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(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; } }