void MusicEffect::RenderMorph(RenderBuffer &buffer, int x, int bars, int startNote, int endNote, std::list<MusicEvent*>& events, int colourTreatment, bool bounce, bool fade) { bool up = true; int event = -1; for (auto it = events.begin(); it != events.end(); ++it) { event++; up = !up; if ((*it)->IsEventActive(buffer.curPeriod)) { float progress = (*it)->OffsetInDuration(buffer.curPeriod); int length = buffer.BufferHt; int start = -1 * length + progress * 2 * length + 1; int end = start + length; for (int y = std::max(0, start); y < std::min(end, buffer.BufferHt); y++) { xlColor c = xlWHITE; float proportion = ((float)end - (float)y) / (float)length; if (colourTreatment == 1) { // distinct float percolour = 1.0 / (float)buffer.GetColorCount(); for (int i = 0; i < buffer.GetColorCount(); i++) { if (proportion <= ((float)i + 1.0)*percolour) { buffer.palette.GetColor(i, c); break; } } } else if (colourTreatment == 2) { // blend buffer.GetMultiColorBlend(proportion, false, c); } else if (colourTreatment == 3) { buffer.palette.GetColor(event % buffer.GetColorCount(), c); } if (fade) { c.alpha = (1.0 -proportion) * 255; } if (up || !bounce) { buffer.SetPixel(x, y, c); } else { buffer.SetPixel(x, buffer.BufferHt - y - 1, c); } } } } }
void MusicEffect::RenderOn(RenderBuffer &buffer, int x, int bars, int startNote, int endNote, std::list<MusicEvent*>& events, int colourTreatment, bool fade) { int event = -1; for (auto it = events.begin(); it != events.end(); ++it) { event++; if ((*it)->IsEventActive(buffer.curPeriod)) { float progress = (*it)->OffsetInDuration(buffer.curPeriod); for (int y = 0; y < buffer.BufferHt; y++) { xlColor c = xlWHITE; float proportion = (float)y / (float)buffer.BufferHt; if (colourTreatment == 1) { // distinct float percolour = 1.0 / (float)buffer.GetColorCount(); for (int i = 0; i < buffer.GetColorCount(); i++) { if (proportion <= ((float)i + 1.0)*percolour) { buffer.palette.GetColor(i, c); break; } } } else if (colourTreatment == 2) { // blend buffer.GetMultiColorBlend(proportion, false, c); } else if (colourTreatment == 3) { buffer.palette.GetColor(event % buffer.GetColorCount(), c); } if (fade) { c.alpha = (1.0 - progress) * 255; } buffer.SetPixel(x, y, c); } } } }
void MusicEffect::RenderCollide(RenderBuffer &buffer, int x, int bars, int startNote, int endNote, bool in, std::list<MusicEvent*>& events, int colourTreatment, bool fade) { int event = -1; for (auto it = events.begin(); it != events.end(); ++it) { event++; if ((*it)->IsEventActive(buffer.curPeriod)) { float progress = (*it)->OffsetInDuration(buffer.curPeriod); int mid = buffer.BufferHt / 2; int length = buffer.BufferHt; int leftstart, leftend; if (!in) { progress = 1.0 - progress; } leftstart = 0 - mid - 1 + progress * length; leftend = leftstart + mid; if (leftend > mid) { leftend = mid; } int loopstart = leftstart; if (loopstart < 0) { loopstart = 0; } for (int y = loopstart; y < leftend; y++) { xlColor c = xlWHITE; float proportion = ((float)y - (float)leftstart) / (float)mid; if (colourTreatment == 1) { // distinct float percolour = 1.0 / (float)buffer.GetColorCount(); for (int i = 0; i < buffer.GetColorCount(); i++) { if (proportion <= ((float)i + 1.0)*percolour) { buffer.palette.GetColor(i, c); break; } } } else if (colourTreatment == 2) { // blend buffer.GetMultiColorBlend(proportion, false, c); } else if (colourTreatment == 3) { buffer.palette.GetColor(event % buffer.GetColorCount(), c); } if (fade) { c.alpha = progress * 255; } buffer.SetPixel(x, y, c); buffer.SetPixel(x, mid - y + mid - 1, c); } } } }
void GarlandsEffect::Render(Effect *effect, const SettingsMap &SettingsMap, RenderBuffer &buffer) { int GarlandType = SettingsMap.GetInt("SLIDER_Garlands_Type", 0); int Spacing = SettingsMap.GetInt("SLIDER_Garlands_Spacing", 0); float cycles = SettingsMap.GetDouble("TEXTCTRL_Garlands_Cycles", 1.0); if (Spacing < 1) { Spacing = 1; } int x,y,yadj,ylimit,ring; double ratio; xlColor color; int dir = GetDirection(SettingsMap.Get("CHOICE_Garlands_Direction", "Up")); double position = buffer.GetEffectTimeIntervalPosition(cycles); if (dir > 3) { dir -= 4; if (position > 0.5) { position = (1.0 - position) * 2.0; } else { position *= 2.0; } } int buffMax = buffer.BufferHt; int garlandWid = buffer.BufferWi; if (dir > 1) { buffMax = buffer.BufferWi; garlandWid = buffer.BufferHt; } double PixelSpacing=Spacing*buffMax/100.0; if (PixelSpacing < 2.0) PixelSpacing=2.0; double total = buffMax * PixelSpacing - buffMax + 1; double positionOffset = total * position; for (ring = 0; ring < buffMax; ring++) { ratio=double(buffMax-ring-1)/double(buffMax); buffer.GetMultiColorBlend(ratio, false, color); y = 1.0 + ring*PixelSpacing - positionOffset; ylimit=ring; for (x=0; x<garlandWid; x++) { yadj=y; switch (GarlandType) { case 1: switch (x%5) { case 2: yadj-=2; break; case 1: case 3: yadj-=1; break; } break; case 2: switch (x%5) { case 2: yadj-=4; break; case 1: case 3: yadj-=2; break; } break; case 3: switch (x%6) { case 3: yadj-=6; break; case 2: case 4: yadj-=4; break; case 1: case 5: yadj-=2; break; } break; case 4: switch (x%5) { case 1: case 3: yadj-=2; break; } break; } if (yadj < ylimit) yadj=ylimit; if (yadj < buffMax) { if (dir == 1 || dir == 2) { yadj = buffMax - yadj - 1; } if (dir > 1) { buffer.SetPixel(yadj,x,color); } else { buffer.SetPixel(x,yadj,color); } } } } }
void StateEffect::RenderState(RenderBuffer &buffer, SequenceElements *elements, const std::string &faceDefinition, const std::string& Phoneme, const std::string &trackName, const std::string& mode, const std::string& colourmode) { if (buffer.needToInit) { buffer.needToInit = false; elements->AddRenderDependency(trackName, buffer.cur_model); if (buffer.isTransformed) { log4cpp::Category &logger_base = log4cpp::Category::getInstance(std::string("log_base")); logger_base.warn("State effect starting at %dms until %dms on model %s has a transformed buffer. This may not work as expected.", buffer.curEffStartPer * buffer.frameTimeInMs, buffer.curEffEndPer * buffer.frameTimeInMs, (const char *)buffer.cur_model.c_str()); } } Element *track = elements->GetElement(trackName); std::recursive_mutex tmpLock; std::recursive_mutex *lock = &tmpLock; if (track != nullptr) { lock = &track->GetChangeLock(); } std::unique_lock<std::recursive_mutex> locker(*lock); if (buffer.cur_model == "") { return; } Model* model_info = buffer.frame->AllModels[buffer.cur_model]; if (model_info == nullptr) { return; } std::string definition = faceDefinition; bool found = true; std::map<std::string, std::map<std::string, std::string> >::iterator it = model_info->stateInfo.find(definition); if (it == model_info->stateInfo.end()) { //not found found = false; } if (!found) { if ("Coro" == definition && model_info->stateInfo.find("SingleNode") != model_info->stateInfo.end()) { definition = "SingleNode"; found = true; } else if ("SingleNode" == definition && model_info->stateInfo.find("Coro") != model_info->stateInfo.end()) { definition = "Coro"; found = true; } } if (definition == "") { return; } std::string modelType = found ? model_info->stateInfo[definition]["Type"] : definition; if (modelType == "") { modelType = definition; } int type = 1; if ("SingleNode" == modelType) { type = 0; } else if ("NodeRange" == modelType) { type = 1; } std::string tstates = Phoneme; int intervalnumber = 0; //GET label from timing track int startms = -1; int endms = -1; int posms = -1; if (tstates == "") { // if we dont have a track then exit if (track == NULL) { return; } EffectLayer *layer = track->GetEffectLayer(0); std::unique_lock<std::recursive_mutex> locker(layer->GetLock()); int time = buffer.curPeriod * buffer.frameTimeInMs + 1; posms = buffer.curPeriod * buffer.frameTimeInMs; Effect *ef = layer->GetEffectByTime(time); if (ef == nullptr) { tstates = ""; } else { startms = ef->GetStartTimeMS(); endms = ef->GetEndTimeMS(); tstates = ef->GetEffectName(); } ef = layer->GetEffectByTime(buffer.curEffStartPer * buffer.frameTimeInMs + 1); while (ef != NULL && ef->GetStartTimeMS() <= time) { intervalnumber++; int endtime = ef->GetEndTimeMS(); ef = layer->GetEffectByTime(endtime + 1); if (ef == NULL) { ef = layer->GetEffectAfterTime(endtime + 1); } } } std::vector<std::string> sstates; if (mode == "Default" || startms == -1) { wxString ss = wxString(tstates); wxStringTokenizer tkz(ss, wxT(" ,;:")); while (tkz.HasMoreTokens()) { wxString token = tkz.GetNextToken(); sstates.push_back(token.Lower().ToStdString()); } } else if (mode == "Countdown") { // tstates should contain the starting number int val = wxAtoi(tstates); val = val * 1000; int subtracttime = (posms - startms); val = val - subtracttime; val = val / 1000; int v = val; bool force = false; if ((v / 1000) * 1000 > 0) { sstates.push_back(wxString::Format("%d", (v / 1000) * 1000).ToStdString()); force = true; } v = v - (v / 1000) * 1000; if ((v / 100) * 100 > 0) { sstates.push_back(wxString::Format("%d", (v / 100) * 100).ToStdString()); force = true; } else { if (force) { sstates.push_back("000"); } } v = v - (v / 100) * 100; if ((v / 10) * 10 > 0) { sstates.push_back(wxString::Format("%d", (v / 10) * 10).ToStdString()); } else { if (force) { sstates.push_back("00"); } } v = v - (v / 10) * 10; sstates.push_back(wxString::Format("%d", v).ToStdString()); } else if (mode == "Time Countdown") { wxDateTime dt; dt.ParseFormat(tstates.c_str(), "%H:%M:%S"); if (!dt.IsValid()) { dt.ParseFormat(tstates.c_str(), "%M:%S"); } if (dt.IsValid()) { dt.Subtract(wxTimeSpan(0, 0, 0, (buffer.curPeriod - buffer.curEffStartPer) * buffer.frameTimeInMs)); int m = dt.GetMinute(); if ((m / 10) * 1000 > 0) { sstates.push_back(wxString::Format("%d", (m / 10) * 1000).ToStdString()); } else { sstates.push_back("0000"); } m = m - (m / 10) * 10; if (m * 100 > 0) { sstates.push_back(wxString::Format("%d", m * 100).ToStdString()); } else { sstates.push_back("000"); } int s = dt.GetSecond(); if ((s / 10) * 10 > 0) { sstates.push_back(wxString::Format("%d", (s / 10) * 10).ToStdString()); } else { sstates.push_back("00"); } s = s - (s / 10) * 10; sstates.push_back(wxString::Format("%d", s).ToStdString()); } sstates.push_back("colon"); } else if (mode == "Number") // used for FM frequencies { double f = wxAtof(tstates); sstates.push_back("dot"); double f2 = f - int(f); f2 = (int)(f2 * 10 + 0.5); sstates.push_back(wxString::Format("%d", (int)f2).ToStdString()); int v = f; bool force = false; if ((v / 100) * 1000 > 0) { sstates.push_back(wxString::Format("%d", (v / 100) * 1000).ToStdString()); force = true; } v = v - (v / 100) * 100; if ((v / 10) * 100 > 0) { sstates.push_back(wxString::Format("%d", (v / 10) * 100).ToStdString()); } else { if (force) { sstates.push_back("000"); } } v = v - (v / 10) * 10; if (v * 10 > 0) { sstates.push_back(wxString::Format("%d", v * 10).ToStdString()); } else { sstates.push_back("00"); } } else if (mode == "Iterate") { float progressthroughtimeinterval = ((float)posms - (float)startms) / ((float)endms - (float)startms); std::vector<std::string> tmpstates; wxString ss = wxString(tstates); wxStringTokenizer tkz(ss, wxT(" ,;:")); while (tkz.HasMoreTokens()) { wxString token = tkz.GetNextToken(); tmpstates.push_back(token.Lower().ToStdString()); } int which = tmpstates.size() * progressthroughtimeinterval; if (which < sstates.size()) { sstates.push_back(tmpstates[which]); } } bool customColor = found ? model_info->stateInfo[definition]["CustomColors"] == "1" : false; // process each token for (size_t i = 0; i < sstates.size(); i++) { // get the channels std::string statename = FindState(model_info->stateInfo[definition], sstates[i]); std::string channels = model_info->stateInfo[definition][statename]; if (statename != "" && channels != "") { xlColor color; if (colourmode == "Graduate") { buffer.GetMultiColorBlend(buffer.GetEffectTimeIntervalPosition(), false, color); } else if (colourmode == "Cycle") { buffer.palette.GetColor((intervalnumber - 1) % buffer.GetColorCount(), color); } else { // allocate int statenum = wxAtoi(statename.substr(1)); buffer.palette.GetColor((statenum - 1) % buffer.GetColorCount(), color); } if (customColor) { std::string cname = model_info->stateInfo[definition][statename + "-Color"]; if (cname == "") { color = xlWHITE; } else { color = xlColor(cname); } } wxStringTokenizer wtkz(channels, ","); while (wtkz.HasMoreTokens()) { wxString valstr = wtkz.GetNextToken(); if (type == 0) { for (size_t n = 0; n < model_info->GetNodeCount(); n++) { wxString nn = model_info->GetNodeName(n, true); if (nn == valstr) { for (auto a = buffer.Nodes[n]->Coords.begin() ; a != buffer.Nodes[n]->Coords.end(); a++) { buffer.SetPixel(a->bufX, a->bufY, color); } } } } else if (type == 1) { int start, end; if (valstr.Contains("-")) { int idx = valstr.Index('-'); start = wxAtoi(valstr.Left(idx)); end = wxAtoi(valstr.Right(valstr.size() - idx - 1)); } else { start = end = wxAtoi(valstr); } if (start > end) { start = end; } start--; end--; for (int n = start; n <= end; n++) { if (n < buffer.Nodes.size()) { for (auto a = buffer.Nodes[n]->Coords.begin() ; a != buffer.Nodes[n]->Coords.end(); a++) { buffer.SetPixel(a->bufX, a->bufY, color); } } } } } } } }
void ColorWashEffect::Render(Effect *effect, const SettingsMap &SettingsMap, RenderBuffer &buffer) { bool HorizFade = SettingsMap.GetBool(CHECKBOX_ColorWash_HFade); bool VertFade = SettingsMap.GetBool(CHECKBOX_ColorWash_VFade); float cycles = SettingsMap.GetDouble(TEXTCTRL_ColorWash_Cycles, 1.0); bool EntireModel = SettingsMap.GetInt(CHECKBOX_ColorWash_EntireModel, 1); int x1 = SettingsMap.GetInt(SLIDER_ColorWash_X1, -50); int y1 = SettingsMap.GetInt(SLIDER_ColorWash_Y1, -50); int x2 = SettingsMap.GetInt(SLIDER_ColorWash_X2, 50); int y2 = SettingsMap.GetInt(SLIDER_ColorWash_Y2, 50); bool shimmer = SettingsMap.GetInt(CHECKBOX_ColorWash_Shimmer, 0); bool circularPalette = SettingsMap.GetInt(CHECKBOX_ColorWash_CircularPalette, 0); int x,y; xlColor color, orig; double position = buffer.GetEffectTimeIntervalPosition(cycles); buffer.GetMultiColorBlend(position, circularPalette, color); int startX = 0; int startY = 0; int endX = buffer.BufferWi - 1; int endY = buffer.BufferHt - 1; if (!EntireModel) { startX = std::min(x1, x2); endX = std::max(x1, x2); startY = std::min(y1, y2); endY = std::max(y1, y2); startX = std::round(double(buffer.BufferWi - 0.5) * (double)startX / 100.0); endX = std::round(double(buffer.BufferWi - 0.5) * (double)endX / 100.0); startY = std::round(double(buffer.BufferHt - 0.5) * (double)startY / 100.0); endY = std::round(double(buffer.BufferHt - 0.5) * (double)endY / 100.0); startX = std::max(startX, 0); endX = std::min(endX, buffer.BufferWi - 1); startY = std::max(startY, 0); endY = std::min(endY, buffer.BufferHt - 1); } int tot = buffer.curPeriod - buffer.curEffStartPer; if (!shimmer || (tot % 2) == 0) { double HalfHt=double(endY - startY)/2.0; double HalfWi=double(endX - startX)/2.0; orig = color; HSVValue hsvOrig = color.asHSV(); xlColor color2 = color; for (x=startX; x <= endX; x++) { HSVValue hsv = hsvOrig; if (HorizFade) { if (buffer.allowAlpha) { color.alpha = (double)orig.alpha*(1.0-std::abs(HalfWi-x-startX)/HalfWi); } else { hsv.value*=1.0-std::abs(HalfWi-x-startX)/HalfWi; color = hsv; } } color2.alpha = color.alpha; for (y=startY; y<=endY; y++) { if (VertFade) { if (buffer.allowAlpha) { color.alpha = (double)color2.alpha*(1.0-std::abs(HalfHt-(y-startY))/HalfHt); } else { HSVValue hsv2 = hsv; hsv2.value*=1.0-std::abs(HalfHt-(y-startY))/HalfHt; color = hsv2; } } buffer.SetPixel(x, y, color); } } } else { orig = xlBLACK; } wxMutexLocker lock(effect->GetBackgroundDisplayList().lock); if (VertFade || HorizFade) { effect->GetBackgroundDisplayList().resize((buffer.curEffEndPer - buffer.curEffStartPer + 1) * 4 * 2); int total = buffer.curEffEndPer - buffer.curEffStartPer + 1; double x1 = double(buffer.curPeriod - buffer.curEffStartPer) / double(total); double x2 = (buffer.curPeriod - buffer.curEffStartPer + 1.0) / double(total); int idx = (buffer.curPeriod - buffer.curEffStartPer) * 8; buffer.SetDisplayListVRect(effect, idx, x1, 0.0, x2, 0.5, xlBLACK, orig); buffer.SetDisplayListVRect(effect, idx + 4, x1, 0.5, x2, 1.0, orig, xlBLACK); } else { effect->GetBackgroundDisplayList().resize((buffer.curEffEndPer - buffer.curEffStartPer + 1) * 4); int midX = (startX + endX) / 2; int midY = (startY + endY) / 2; buffer.CopyPixelsToDisplayListX(effect, midY, midX, midX); } }