void MainSequencer::SplitTimingMark() { int x1; int x2; if( mPlayType == PLAY_TYPE_MODEL ) { x1 = PanelTimeLine->GetPlayMarker(); x2 = x1; } else { x1 = PanelTimeLine->GetSelectedPositionStart(); x2 = PanelTimeLine->GetSelectedPositionEnd(); } if( x2 == -1 ) x2 = x1; int selectedTiming = mSequenceElements->GetSelectedTimingRow(); if(selectedTiming >= 0) { Element* e = mSequenceElements->GetVisibleRowInformation(selectedTiming)->element; EffectLayer* el = e->GetEffectLayer(mSequenceElements->GetVisibleRowInformation(selectedTiming)->layerIndex); int index1,index2; int t1 = PanelTimeLine->GetAbsoluteTimeMSfromPosition(x1); int t2 = PanelTimeLine->GetAbsoluteTimeMSfromPosition(x2); if(el->HitTestEffectByTime(t1,index1) && el->HitTestEffectByTime(t2,index2)) { if( index1 == index2 ) { Effect* eff1 = el->GetEffect(index1); int old_end_time = eff1->GetEndTimeMS(); if( t1 != t2 || ((t1 == t2) && t1 != eff1->GetStartTimeMS() && t1 != eff1->GetEndTimeMS()) ) { eff1->SetEndTimeMS(t1); std::string name,settings; el->AddEffect(0,name,settings,"",t2,old_end_time,false,false); PanelEffectGrid->ForceRefresh(); } } else { wxMessageBox("Timing cannot be split across timing marks.","Timing placement error"); } } } }
void MainSequencer::InsertTimingMarkFromRange() { bool is_range = true; int x1; int x2; if( mPlayType == PLAY_TYPE_MODEL ) { x1 = PanelTimeLine->GetPlayMarker(); x2 = x1; } else { x1 = PanelTimeLine->GetSelectedPositionStart(); x2 = PanelTimeLine->GetSelectedPositionEnd(); } if( x2 == -1 ) x2 = x1; if( x1 == x2) is_range = false; int selectedTiming = mSequenceElements->GetSelectedTimingRow(); if(selectedTiming >= 0) { int t1 = PanelTimeLine->GetAbsoluteTimeMSfromPosition(x1); int t2 = PanelTimeLine->GetAbsoluteTimeMSfromPosition(x2); if(is_range) { Element* e = mSequenceElements->GetVisibleRowInformation(selectedTiming)->element; EffectLayer* el = e->GetEffectLayer(mSequenceElements->GetVisibleRowInformation(selectedTiming)->layerIndex); int index; if(!el->HitTestEffectByTime(t1,index) && !el->HitTestEffectByTime(t2,index)) { std::string name,settings; el->AddEffect(0,name,settings,"",t1,t2,false,false); PanelEffectGrid->ForceRefresh(); } else { wxMessageBox("Timing exist already in the selected region","Timing placement error"); } } else { // x1 and x2 are the same. Insert from end time of timing to the left to x2 Element* e = mSequenceElements->GetVisibleRowInformation(selectedTiming)->element; EffectLayer* el = e->GetEffectLayer(mSequenceElements->GetVisibleRowInformation(selectedTiming)->layerIndex); int index; if(!el->HitTestEffectByTime(t2,index)) { // if there is an effect to left std::string name,settings; Effect * effect = nullptr; for (int x = 0; x < el->GetEffectCount(); x++) { Effect * e = el->GetEffect(x); if (e->GetStartTimeMS() > t2 && x > 0) { effect = el->GetEffect(x - 1); break; } } if(effect!=nullptr) { int t1 = effect->GetEndTimeMS(); el->AddEffect(0,name,settings,"",t1,t2,false,false); } // No effect to left start at time = 0 else { int t1 = 0; if (el->GetEffectCount() > 0) { Effect *e = el->GetEffect(el->GetEffectCount() - 1); t1 = e->GetEndTimeMS(); } el->AddEffect(0,name,settings,"",t1,t2,false,false); } PanelEffectGrid->ForceRefresh(); } else { SplitTimingMark(); // inserting a timing mark inside a timing mark same as a split } } } }
bool SequenceElements::LoadSequencerFile(xLightsXmlFile& xml_file) { mFilename = xml_file; wxXmlDocument& seqDocument = xml_file.GetXmlDocument(); wxXmlNode* root=seqDocument.GetRoot(); std::vector<std::string> effectStrings; std::vector<std::string> colorPalettes; Clear(); for(wxXmlNode* e=root->GetChildren(); e!=NULL; e=e->GetNext() ) { if (e->GetName() == "DisplayElements") { for(wxXmlNode* element=e->GetChildren(); element!=NULL; element=element->GetNext() ) { bool active=false; bool selected=false; bool collapsed=false; std::string name = element->GetAttribute(STR_NAME).ToStdString(); std::string type = element->GetAttribute(STR_TYPE).ToStdString(); bool visible = element->GetAttribute("visible")=='1'?true:false; if (type==STR_TIMING) { active = element->GetAttribute("active")=='1'?true:false; } else { collapsed = element->GetAttribute("collapsed")=='1'?true:false; } Element* elem = AddElement(name,type,visible,collapsed,active,selected); if (type==STR_TIMING) { std::string views = element->GetAttribute("views", "").ToStdString(); elem->SetViews(views); } } } else if (e->GetName() == "EffectDB") { effectStrings.clear(); for(wxXmlNode* elementNode=e->GetChildren(); elementNode!=NULL; elementNode=elementNode->GetNext() ) { if(elementNode->GetName()==STR_EFFECT) { effectStrings.push_back(elementNode->GetNodeContent().ToStdString()); } } } else if (e->GetName() == "ColorPalettes") { colorPalettes.clear(); for(wxXmlNode* elementNode=e->GetChildren(); elementNode!=NULL; elementNode=elementNode->GetNext() ) { if(elementNode->GetName() == STR_COLORPALETTE) { colorPalettes.push_back(elementNode->GetNodeContent().ToStdString()); } } } else if (e->GetName() == "ElementEffects") { for(wxXmlNode* elementNode=e->GetChildren(); elementNode!=NULL; elementNode=elementNode->GetNext() ) { if(elementNode->GetName()==STR_ELEMENT) { Element* element = GetElement(elementNode->GetAttribute(STR_NAME).ToStdString()); if (element !=NULL) { // check for fixed timing interval int interval = 0; if( elementNode->GetAttribute(STR_TYPE) == STR_TIMING ) { interval = wxAtoi(elementNode->GetAttribute("fixed")); } if( interval > 0 ) { element->SetFixedTiming(interval); EffectLayer* effectLayer = element->AddEffectLayer(); int time = 0; int end_time = xml_file.GetSequenceDurationMS(); int startTime, endTime, next_time; while( time <= end_time ) { next_time = (time + interval <= end_time) ? time + interval : end_time; startTime = TimeLine::RoundToMultipleOfPeriod(time,mFrequency); endTime = TimeLine::RoundToMultipleOfPeriod(next_time,mFrequency); effectLayer->AddEffect(0,"","","",startTime,endTime,EFFECT_NOT_SELECTED,false); time += interval; } } else { for(wxXmlNode* effectLayerNode=elementNode->GetChildren(); effectLayerNode!=NULL; effectLayerNode=effectLayerNode->GetNext()) { if (effectLayerNode->GetName() == STR_EFFECTLAYER || effectLayerNode->GetName() == STR_STRAND) { EffectLayer* effectLayer = NULL; if (effectLayerNode->GetName() == STR_EFFECTLAYER) { effectLayer = element->AddEffectLayer(); } else { effectLayer = element->GetStrandLayer(wxAtoi(effectLayerNode->GetAttribute(STR_INDEX)), true); if (effectLayerNode->GetAttribute(STR_NAME, STR_EMPTY) != STR_EMPTY) { ((StrandLayer*)effectLayer)->SetName(effectLayerNode->GetAttribute(STR_NAME).ToStdString()); } } LoadEffects(effectLayer, elementNode->GetAttribute(STR_TYPE).ToStdString(), effectLayerNode, effectStrings, colorPalettes); } } } } } } } } // Select view and set current view models as visible int last_view = xml_file.GetLastView(); for(wxXmlNode* view=mViewsNode->GetChildren(); view!=NULL; view=view->GetNext() ) { std::string viewName = view->GetAttribute(STR_NAME).ToStdString(); std::string models = view->GetAttribute("models").ToStdString(); std::vector <Element*> new_view; mAllViews.push_back(new_view); int view_index = mAllViews.size()-1; if( view_index == last_view ) { AddMissingModelsToSequence(models); PopulateView(models, view_index); SetCurrentView(view_index); } } if (mModelsNode != nullptr) { PopulateRowInformation(); } // Set to the first model/view mFirstVisibleModelRow = 0; return true; }