diff --git a/.gitignore b/.gitignore index 0322dae9..68e3ef73 100644 --- a/.gitignore +++ b/.gitignore @@ -79,4 +79,5 @@ node_modules output # Copilot instruction files -copilot-instructions.md \ No newline at end of file +copilot-instructions.md +DEBUG.txt diff --git a/src/GDTFManager.cpp b/src/GDTFManager.cpp index ca94fc8d..998828ae 100644 --- a/src/GDTFManager.cpp +++ b/src/GDTFManager.cpp @@ -6156,6 +6156,60 @@ void GdtfDmxChannelFunction::OnReadFromNode(const IXMLFileNodePtr& pNode) if( ! channelSet->IsValid()) { delete channelSet; return; } + // For old virtual channels with recalculated DMX values(32->16), ensure unique DMXFrom values + if (this->GetParentDMXChannel()->IsVirtual()) + { + DmxValue maxDmxValue = this->GetParentDMXChannel()->GetChannelMaxDmx(); + + if (fChannelSets.size() >= maxDmxValue) + { + GdtfParsingError error (GdtfDefines::EGdtfParsingError::eValueError_DmxValueHasWrongValue, objNode); + SceneData::GdtfFixture::AddError(error); + delete channelSet; + return; + } + + DmxValue currentValue = channelSet->GetDmxStart(); + + bool hasDuplicate = true; + + while (hasDuplicate && currentValue < maxDmxValue) + { + hasDuplicate = false; + for (size_t i = 0; i < fChannelSets.size(); i++) + { + if (fChannelSets[i]->GetDmxStart() == currentValue) + { + hasDuplicate = true; + currentValue++; + break; + } + } + } + + // If we reached the maximum and still have a duplicate, use cascading backward decrement + if (hasDuplicate && currentValue >= maxDmxValue) + { + for (int i = fChannelSets.size() - 1; i >= 0; i--) + { + DmxValue nextValue = (i == (int)fChannelSets.size() - 1) ? maxDmxValue : fChannelSets[i + 1]->GetDmxStart(); + DmxValue currentElem = fChannelSets[i]->GetDmxStart(); + DmxValue maxAllowed = (nextValue > 0) ? (nextValue - 1) : 0; + + if (currentElem >= nextValue && maxAllowed >= 0) + { + fChannelSets[i]->SetDmxStart(maxAllowed); + } + } + + currentValue = maxDmxValue; + } + + if (currentValue != channelSet->GetDmxStart()) + { + channelSet->SetDmxStart(currentValue); + } + } // Link with next if(!fChannelSets.empty()) diff --git a/src/XmlFileHelper.cpp b/src/XmlFileHelper.cpp index fb01ce2f..d46eeec5 100644 --- a/src/XmlFileHelper.cpp +++ b/src/XmlFileHelper.cpp @@ -745,25 +745,13 @@ bool SceneData::GdtfConverter::ConvertDMXValue(const TXString& strValue, const I DmxValue maxChannelUnit = GetChannelMaxDmx(chanlReso); double percentage = (dmxValueRaw / maxResolution); - double result = percentage * maxChannelUnit; - // Clamp to avoid floating-point precision errors when converting from higher to lower resolution - if (result > maxChannelUnit) { + intValue = static_cast(result + 0.5); + + if (intValue > maxChannelUnit) { intValue = maxChannelUnit; - } else { - // Preserve ordering: ensure non-zero inputs stay non-zero - if (dmxValueRaw > 0 && result < 1.0) { - intValue = 1; - } else { - intValue = static_cast(result + 0.5); - } - - if (intValue > maxChannelUnit) { - intValue = maxChannelUnit; - } } - } else {