parameterlinks.cpp (4966B)
1 #include "parameterlinks.h" 2 3 #include "controller.h" 4 5 namespace pluginLib 6 { 7 ParameterLinks::ParameterLinks(Controller& _controller) : m_controller(_controller) 8 { 9 } 10 11 bool ParameterLinks::add(Parameter* _source, Parameter* _dest, bool _applyCurrentSourceToTarget) 12 { 13 if(!_source || !_dest) 14 return false; 15 16 if(_source == _dest) 17 return false; 18 19 const auto it = m_parameterLinks.find(_source); 20 21 if(it != m_parameterLinks.end()) 22 return it->second->add(_dest, _applyCurrentSourceToTarget); 23 24 m_parameterLinks.insert({_source, std::make_unique<ParameterLink>(_source, _dest, _applyCurrentSourceToTarget)}); 25 m_destToSource[_dest].insert(_source); 26 27 _dest->setLinkState(Target); 28 29 return true; 30 } 31 32 bool ParameterLinks::remove(const Parameter* _source, Parameter* _dest) 33 { 34 const auto it = m_parameterLinks.find(_source); 35 if(it == m_parameterLinks.end()) 36 return false; 37 if(!it->second->remove(_dest)) 38 return false; 39 if(it->second->empty()) 40 m_parameterLinks.erase(it); 41 42 auto& sources = m_destToSource[_dest]; 43 44 sources.erase(_source); 45 46 if(sources.empty()) 47 { 48 m_destToSource.erase(_dest); 49 _dest->clearLinkState(Target); 50 } 51 52 return true; 53 } 54 55 ParameterLinkType ParameterLinks::getRegionLinkType(const std::string& _regionId, const uint8_t _part) const 56 { 57 const auto& regions = m_controller.getParameterDescriptions().getRegions(); 58 59 const auto itRegion = regions.find(_regionId); 60 61 if(itRegion == regions.end()) 62 return None; 63 64 uint32_t totalCount = 0; 65 uint32_t sourceCount = 0; 66 uint32_t targetCount = 0; 67 68 for (const auto& [name, desc] : itRegion->second.getParams()) 69 { 70 const auto* parameter = m_controller.getParameter(name, _part); 71 72 if(!parameter) 73 continue; 74 75 ++totalCount; 76 77 const auto state = parameter->getLinkState(); 78 79 if(state & ParameterLinkType::Source) ++sourceCount; 80 if(state & ParameterLinkType::Target) ++targetCount; 81 } 82 83 ParameterLinkType result = None; 84 85 if(sourceCount > (totalCount>>1)) 86 result = static_cast<ParameterLinkType>(result | ParameterLinkType::Source); 87 if(targetCount > (totalCount>>1)) 88 result = static_cast<ParameterLinkType>(result | ParameterLinkType::Target); 89 90 return result; 91 } 92 93 bool ParameterLinks::linkRegion(const std::string& _regionId, const uint8_t _partSource, const uint8_t _partDest, bool _applyCurrentSourceToTarget) 94 { 95 const auto& regions = m_controller.getParameterDescriptions().getRegions(); 96 97 const auto itRegion = regions.find(_regionId); 98 99 if(itRegion == regions.end()) 100 return false; 101 102 const RegionLink link{_regionId, _partSource, _partDest}; 103 104 if(!m_linkedRegions.insert(link).second) 105 return false; 106 107 return updateRegionLinks(itRegion->second, _partSource, _partDest, true, _applyCurrentSourceToTarget); 108 } 109 110 bool ParameterLinks::unlinkRegion(const std::string& _regionId, const uint8_t _partSource, const uint8_t _partDest) 111 { 112 const RegionLink link{_regionId, _partSource, _partDest}; 113 114 if(!m_linkedRegions.erase(link)) 115 return false; 116 117 const auto& regions = m_controller.getParameterDescriptions().getRegions(); 118 119 const auto itRegion = regions.find(_regionId); 120 121 if(itRegion == regions.end()) 122 return false; 123 124 return updateRegionLinks(itRegion->second, _partSource, _partDest, false, false); 125 } 126 127 bool ParameterLinks::isRegionLinked(const std::string& _regionId, const uint8_t _partSource, const uint8_t _partDest) const 128 { 129 const RegionLink link{_regionId, _partSource, _partDest}; 130 return m_linkedRegions.find(link) != m_linkedRegions.end(); 131 } 132 133 void ParameterLinks::saveChunkData(baseLib::BinaryStream& s) const 134 { 135 if(m_linkedRegions.empty()) 136 return; 137 138 baseLib::ChunkWriter cw(s, "PLNK", 1); 139 140 s.write(static_cast<uint32_t>(m_linkedRegions.size())); 141 142 for (const auto& linkedRegion : m_linkedRegions) 143 { 144 s.write(linkedRegion.regionId); 145 s.write(linkedRegion.sourcePart); 146 s.write(linkedRegion.destPart); 147 } 148 } 149 150 void ParameterLinks::loadChunkData(baseLib::ChunkReader& _cr) 151 { 152 _cr.add("PLNK", 1, [this](baseLib::BinaryStream& _binaryStream, unsigned _version) 153 { 154 const uint32_t count = _binaryStream.read<uint32_t>(); 155 156 for(uint32_t i=0; i<count; ++i) 157 { 158 const auto regionId = _binaryStream.readString(); 159 const auto sourcePart = _binaryStream.read<uint8_t>(); 160 const auto destPart = _binaryStream.read<uint8_t>(); 161 162 linkRegion(regionId, sourcePart, destPart, false); 163 } 164 }); 165 } 166 167 bool ParameterLinks::updateRegionLinks(const ParameterRegion& _region, const uint8_t _partSource, const uint8_t _partDest, const bool _enableLink, const bool _applyCurrentSourceToTarget) 168 { 169 bool res = false; 170 171 for(const auto& [name, desc] : _region.getParams()) 172 { 173 auto* paramSource = m_controller.getParameter(name, _partSource); 174 auto* paramDest = m_controller.getParameter(name, _partDest); 175 176 if(_enableLink) 177 res |= add(paramSource, paramDest, _applyCurrentSourceToTarget); 178 else 179 res |= remove(paramSource, paramDest); 180 } 181 182 return res; 183 } 184 }