void ShimmerEffect::Render(Effect *effect, const SettingsMap &SettingsMap, RenderBuffer &buffer) { float oset = buffer.GetEffectTimeIntervalPosition(); int Duty_Factor = GetValueCurveInt("Shimmer_Duty_Factor", 50, SettingsMap, oset); bool Use_All_Colors = SettingsMap.GetBool("CHECKBOX_Shimmer_Use_All_Colors", false); float cycles = GetValueCurveDouble("Shimmer_Cycles", 1.0, SettingsMap, oset); int colorcnt=buffer.GetColorCount(); double position = buffer.GetEffectTimeIntervalPosition(cycles); double ColorIdx = round(position * 0.999 * (double)colorcnt); double pos2 = position * colorcnt; while (pos2 > 1.0) { pos2 -= 1.0; } if (pos2 * 100 > Duty_Factor) { return; } xlColor color; buffer.palette.GetColor(ColorIdx, color); for (int y=0; y<buffer.BufferHt; y++) { for (int x=0; x<buffer.BufferWi; x++) { if(Use_All_Colors) { // Should we randomly assign colors from palette or cycle thru sequentially? ColorIdx=rand() % colorcnt; // Select random numbers from 0 up to number of colors the user has checked. 0-5 if 6 boxes checked buffer.palette.GetColor(ColorIdx, color); // Now go and get the hsv value for this ColorIdx } buffer.SetPixel(x,y,color); // Turn pixel } } }
void MorphEffect::Render(Effect *effect, const SettingsMap &SettingsMap, RenderBuffer &buffer) { int start_x1 = SettingsMap.GetInt("SLIDER_Morph_Start_X1", 0); int start_y1 = SettingsMap.GetInt("SLIDER_Morph_Start_Y1", 0); int start_x2 = SettingsMap.GetInt("SLIDER_Morph_Start_X2", 0); int start_y2 = SettingsMap.GetInt("SLIDER_Morph_Start_Y2", 0); int end_x1 = SettingsMap.GetInt("SLIDER_Morph_End_X1", 0); int end_y1 = SettingsMap.GetInt("SLIDER_Morph_End_Y1", 0); int end_x2 = SettingsMap.GetInt("SLIDER_Morph_End_X2", 0); int end_y2 = SettingsMap.GetInt("SLIDER_Morph_End_Y2", 0); int start_length = SettingsMap.GetInt("SLIDER_MorphStartLength", 0); int end_length = SettingsMap.GetInt("SLIDER_MorphEndLength", 0); bool start_linked = SettingsMap.GetBool("CHECKBOX_Morph_Start_Link"); bool end_linked = SettingsMap.GetBool("CHECKBOX_Morph_End_Link"); int duration = SettingsMap.GetInt("SLIDER_MorphDuration", 0); int acceleration = SettingsMap.GetInt("SLIDER_MorphAccel", 0); bool showEntireHeadAtStart = SettingsMap.GetBool("CHECKBOX_ShowHeadAtStart"); int repeat_count = SettingsMap.GetInt("SLIDER_Morph_Repeat_Count", 0); int repeat_skip = SettingsMap.GetInt("SLIDER_Morph_Repeat_Skip", 0); int stagger = SettingsMap.GetInt("SLIDER_Morph_Stagger", 0); double eff_pos = buffer.GetEffectTimeIntervalPosition(); double step_size = 0.1; int hcols = 0, hcole = 1; int tcols = 2, tcole = 3; int num_tail_colors = 2; switch (buffer.palette.Size()) { case 1: //one color selected, use it for all hcols = hcole = tcols = tcole = 0; break; case 2: //two colors, head/tail hcols = hcole = 0; tcols = tcole = 1; break; case 3: //three colors, head /tail start/end hcols = hcole = 0; tcols = 1; tcole = 2; break; case 4: break; case 5: num_tail_colors = 3; break; case 6: num_tail_colors = 4; break; } int x1a = calcPosition(start_x1, buffer.BufferWi); int y1a = calcPosition(start_y1, buffer.BufferHt); int x2a = calcPosition(end_x1, buffer.BufferWi); int y2a = calcPosition(end_y1, buffer.BufferHt); int x1b, x2b, y1b, y2b; if( start_linked ) { x1b = x1a; y1b = y1a; } else { x1b = calcPosition(start_x2, buffer.BufferWi); y1b = calcPosition(start_y2, buffer.BufferHt); } if( end_linked ) { x2b = x2a; y2b = y2a; } else { x2b = calcPosition(end_x2, buffer.BufferWi); y2b = calcPosition(end_y2, buffer.BufferHt); } xlColor head_color, tail_color, test_color; // compute direction int delta_xa = x2a - x1a; int delta_xb = x2b - x1b; int delta_ya = y2a - y1a; int delta_yb = y2b - y1b; int direction = delta_xa + delta_xb + delta_ya + delta_yb; int repeat_x = 0; int repeat_y = 0; double effect_pct = 1.0; double stagger_pct = 0.0; if( repeat_count > 0 ) { if( (std::abs((float)delta_xa) + std::abs((float)delta_xb)) < (std::abs((float)delta_ya) + std::abs((float)delta_yb)) ) { repeat_x = repeat_skip; } else { repeat_y = repeat_skip; } double stagger_val = (double)(std::abs((double)stagger))/200.0; effect_pct = 1.0 / (1 + stagger_val * repeat_count); stagger_pct = effect_pct * stagger_val; } std::vector<int> v_ax; std::vector<int> v_ay; std::vector<int> v_bx; std::vector<int> v_by; StoreLine(x1a, y1a, x2a, y2a, &v_ax, &v_ay); // store side a StoreLine(x1b, y1b, x2b, y2b, &v_bx, &v_by); // store side b int size_a = v_ax.size(); int size_b = v_bx.size(); std::vector<int> *v_lngx; // pointer to longest vector x std::vector<int> *v_lngy; // pointer to longest vector y std::vector<int> *v_shtx; // pointer to shorter vector x std::vector<int> *v_shty; // pointer to shorter vector y if( size_a > size_b ) { v_lngx = &v_ax; v_lngy = &v_ay; v_shtx = &v_bx; v_shty = &v_by; } else { v_lngx = &v_bx; v_lngy = &v_by; v_shtx = &v_ax; v_shty = &v_ay; } double pos_a, pos_b; double total_tail_length, alpha_pct; double total_length = v_lngx->size(); // total length of longest vector double head_duration = duration/100.0; // time the head is in the frame double head_end_of_head_pos = total_length + 1; double tail_end_of_head_pos = total_length + 1; double head_end_of_tail_pos = -1; double tail_end_of_tail_pos = -1; for( int repeat = 0; repeat <= repeat_count; repeat++ ) { double eff_pos_adj = buffer.calcAccel(eff_pos, acceleration); double eff_start_pct = (stagger >= 0) ? stagger_pct*repeat : stagger_pct*(repeat_count-repeat); double eff_end_pct = eff_start_pct + effect_pct; eff_pos_adj = (eff_pos_adj - eff_start_pct) / (eff_end_pct - eff_start_pct); if( eff_pos_adj < 0.0 ) { head_end_of_head_pos = -1; tail_end_of_head_pos = -1; head_end_of_tail_pos = -1; tail_end_of_tail_pos = -1; total_tail_length = 1.0; if( showEntireHeadAtStart ) { head_end_of_head_pos = start_length; } } else { if( head_duration > 0.0 ) { double head_loc_pct = eff_pos_adj / head_duration; head_end_of_head_pos = total_length * head_loc_pct; double current_total_head_length = end_length * head_loc_pct + start_length * (1.0 - head_loc_pct); // adjusted head length excluding clipping head_end_of_head_pos += current_total_head_length * head_loc_pct * head_duration; total_tail_length = total_length * ( 1 / head_duration - 1.0); if( showEntireHeadAtStart ) { head_end_of_head_pos += current_total_head_length * (1.0 - eff_pos_adj); } tail_end_of_head_pos = head_end_of_head_pos - current_total_head_length; head_end_of_tail_pos = tail_end_of_head_pos - step_size; tail_end_of_tail_pos = head_end_of_tail_pos - total_tail_length; buffer.Get2ColorBlend(hcols, hcole, std::min( head_loc_pct, 1.0), head_color); } else { total_tail_length = total_length; head_end_of_tail_pos = total_length * 2 * eff_pos_adj; tail_end_of_tail_pos = head_end_of_tail_pos - total_tail_length; } } // draw the tail for( double i = std::min(head_end_of_tail_pos, total_length-1); i >= tail_end_of_tail_pos && i >= 0.0; i -= step_size ) { double pct = ((total_length == 0) ? 0.0 : i / total_length); pos_a = i; pos_b = v_shtx->size() * pct; double tail_color_pct = (i-tail_end_of_tail_pos) / total_tail_length; if( num_tail_colors > 2 ) { double color_index = ((double)num_tail_colors - 1.0) * (1.0 - tail_color_pct); tail_color_pct = color_index - (double)((int)color_index); tcols = (int)color_index + 2; tcole = tcols + 1; if( tcole == num_tail_colors+1 ) { alpha_pct = (1.0 - tail_color_pct); } else { alpha_pct = 1.0; } buffer.Get2ColorBlend(tcols, tcole, tail_color_pct, tail_color); } else { if( tail_color_pct > 0.5 ) { alpha_pct = 1.0; } else { alpha_pct = tail_color_pct / 0.5; } buffer.Get2ColorBlend(tcole, tcols, tail_color_pct, tail_color); } if( buffer.allowAlpha ) { tail_color.alpha = 255 * alpha_pct; } buffer.DrawThickLine( (*v_lngx)[pos_a]+(repeat_x*repeat), (*v_lngy)[pos_a]+(repeat_y*repeat), (*v_shtx)[pos_b]+(repeat_x*repeat), (*v_shty)[pos_b]+(repeat_y*repeat), tail_color, direction >= 0); } // draw the head for( double i = std::max(tail_end_of_head_pos, 0.0); i <= head_end_of_head_pos && i < total_length; i += step_size ) { double pct = ((total_length == 0) ? 0.0 : i / total_length); pos_a = i; pos_b = v_shtx->size() * pct; buffer.DrawThickLine( (*v_lngx)[pos_a]+(repeat_x*repeat), (*v_lngy)[pos_a]+(repeat_y*repeat), (*v_shtx)[pos_b]+(repeat_x*repeat), (*v_shty)[pos_b]+(repeat_y*repeat), head_color, direction >= 0); } } }
void GalaxyEffect::Render(Effect *effect, const SettingsMap &SettingsMap, RenderBuffer &buffer) { int center_x = SettingsMap.GetInt("SLIDER_Galaxy_CenterX"); int center_y = SettingsMap.GetInt("SLIDER_Galaxy_CenterY"); int start_radius = SettingsMap.GetInt("SLIDER_Galaxy_Start_Radius"); int end_radius = SettingsMap.GetInt("SLIDER_Galaxy_End_Radius"); int start_angle = SettingsMap.GetInt("SLIDER_Galaxy_Start_Angle"); int revolutions = SettingsMap.GetInt("SLIDER_Galaxy_Revolutions"); int start_width = SettingsMap.GetInt("SLIDER_Galaxy_Start_Width"); int end_width = SettingsMap.GetInt("SLIDER_Galaxy_End_Width"); int duration = SettingsMap.GetInt("SLIDER_Galaxy_Duration"); int acceleration = SettingsMap.GetInt("SLIDER_Galaxy_Accel"); bool reverse_dir = SettingsMap.GetBool("CHECKBOX_Galaxy_Reverse"); bool blend_edges = SettingsMap.GetBool("CHECKBOX_Galaxy_Blend_Edges"); bool inward = SettingsMap.GetBool("CHECKBOX_Galaxy_Inward"); if( revolutions == 0 ) return; std::vector< std::vector<double> > temp_colors_pct(buffer.BufferWi, std::vector<double>(buffer.BufferHt)); std::vector< std::vector<double> > pixel_age(buffer.BufferWi, std::vector<double>(buffer.BufferHt)); double eff_pos = buffer.GetEffectTimeIntervalPosition(); int num_colors = buffer.palette.Size(); xlColor color, c_old, c_new; HSVValue hsv1; double eff_pos_adj = buffer.calcAccel(eff_pos, acceleration); double revs = (double)revolutions; double pos_x = buffer.BufferWi * center_x/100.0; double pos_y = buffer.BufferHt * center_y/100.0; double head_duration = duration/100.0; // time the head is in the frame double tail_length = revs * (1.0 - head_duration); double color_length = tail_length / num_colors; if(color_length < 1.0) color_length = 1.0; double tail_end_of_tail = ((revs + tail_length) * eff_pos_adj) - tail_length; double head_end_of_tail = tail_end_of_tail + tail_length; double radius1 = start_radius; double radius2 = end_radius; double width1 = start_width; double width2 = end_width; double step = buffer.GetStepAngle(radius1, radius2); for( int x = 0; x < buffer.BufferWi; x++ ) { for( int y = 0; y < buffer.BufferHt; y++ ) { temp_colors_pct[x][y] = 0.0; pixel_age[x][y] = 0.0; } } buffer.ClearTempBuf(); double last_check = (inward ? std::min(head_end_of_tail,revs) : std::max(0.0, tail_end_of_tail) ) + (double)start_angle; for( double i = (inward ? std::min(head_end_of_tail,revs) : std::max(0.0, tail_end_of_tail)); (inward ? i >= std::max(0.0, tail_end_of_tail) : i <= std::min(head_end_of_tail,revs)); (inward ? i -= step : i += step) ) { double adj_angle = i + (double)start_angle; if( reverse_dir ) { adj_angle *= -1.0; } double color_val = (head_end_of_tail-i) / color_length; int color_int = (int)color_val; double color_pct = color_val - (double)color_int; int color2 = std::min(color_int+1, num_colors-1); if( color_int < color2 ) { buffer.Get2ColorBlend(color_int, color2, std::min( color_pct, 1.0), color); } else { buffer.palette.GetColor(color2, color); } HSVValue hsv(color); double full_brightness = hsv.value; double pct = i/revs; double current_radius = radius2 * pct + radius1 * (1.0 - pct); double current_width = width2 * pct + width1 * (1.0 - pct); double half_width = current_width / 2.0; double inside_radius = current_radius - half_width; for( double r = inside_radius; ; r += 0.5 ) { if( r > current_radius ) r = current_radius; double x1 = buffer.sin(ToRadians(adj_angle)) * r + (double)pos_x; double y1 = buffer.cos(ToRadians(adj_angle)) * r + (double)pos_y; double outside_radius = current_radius + (current_radius - r); double x2 = buffer.sin(ToRadians(adj_angle)) * outside_radius + (double)pos_x; double y2 = buffer.cos(ToRadians(adj_angle)) * outside_radius + (double)pos_y; double color_pct2 = (r-inside_radius)/(current_radius-inside_radius); if( blend_edges ) { if( hsv.value > 0.0 ) { if ((int)x1 >= 0 && (int)x1 < buffer.BufferWi && (int)y1 >= 0 && (int)y1 < buffer.BufferHt) { buffer.SetTempPixel((int)x1,(int)y1,color); temp_colors_pct[(int)x1][(int)y1] = color_pct2; pixel_age[(int)x1][(int)y1] = adj_angle; } if ((int)x2 >= 0 && (int)x2 < buffer.BufferWi && (int)y2 >= 0 && (int)y2 < buffer.BufferHt) { buffer.SetTempPixel((int)x2,(int)y2,color); temp_colors_pct[(int)x2][(int)y2] = color_pct2; pixel_age[(int)x2][(int)y2] = adj_angle; } } } else { hsv.value = full_brightness * color_pct2; if( hsv.value > 0.0 ) { buffer.SetPixel(x1,y1,hsv); buffer.SetPixel(x2,y2,hsv); } } if( r >= current_radius ) break; } // blend old data down into final buffer if( blend_edges && ( (inward ? (last_check-adj_angle) : (adj_angle-last_check)) >= 90.0) ) { for( int x = 0; x < buffer.BufferWi; x++ ) { for( int y = 0; y < buffer.BufferHt; y++ ) { if( temp_colors_pct[x][y] > 0.0 && ((inward ? (pixel_age[x][y]-adj_angle) : (adj_angle-pixel_age[x][y])) >= 180.0) ) { buffer.GetTempPixel(x,y,c_new); buffer.GetPixel(x,y,c_old); buffer.Get2ColorAlphaBlend(c_old, c_new, temp_colors_pct[x][y], color); buffer.SetPixel(x,y,color); temp_colors_pct[x][y] = 0.0; pixel_age[x][y] = 0.0; } } } last_check = adj_angle; } } // blend remaining data down into final buffer if( blend_edges ) { for( int x = 0; x < buffer.BufferWi; x++ ) { for( int y = 0; y < buffer.BufferHt; y++ ) { if( temp_colors_pct[x][y] > 0.0 ) { buffer.GetTempPixel(x,y,c_new); buffer.GetPixel(x,y,c_old); buffer.Get2ColorAlphaBlend(c_old, c_new, temp_colors_pct[x][y], color); buffer.SetPixel(x,y,color); } } } } }
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); } }
void ShockwaveEffect::Render(Effect *effect, const SettingsMap &SettingsMap, RenderBuffer &buffer) { int center_x = SettingsMap.GetInt("SLIDER_Shockwave_CenterX", 0); int center_y = SettingsMap.GetInt("SLIDER_Shockwave_CenterY", 0); int start_radius = SettingsMap.GetInt("SLIDER_Shockwave_Start_Radius", 0); int end_radius = SettingsMap.GetInt("SLIDER_Shockwave_End_Radius", 0); int start_width = SettingsMap.GetInt("SLIDER_Shockwave_Start_Width", 0); int end_width = SettingsMap.GetInt("SLIDER_Shockwave_End_Width", 0); int acceleration = SettingsMap.GetInt("SLIDER_Shockwave_Accel", 0); bool blend_edges = SettingsMap.GetBool("CHECKBOX_Shockwave_Blend_Edges"); std::vector< std::vector<double> > temp_colors_pct(buffer.BufferWi, std::vector<double>(buffer.BufferHt)); double eff_pos = buffer.GetEffectTimeIntervalPosition(); int num_colors = buffer.palette.Size(); if( num_colors == 0 ) num_colors = 1; xlColor color, c_old, c_new; double eff_pos_adj = buffer.calcAccel(eff_pos, acceleration); double blend_pct = 1.0 / (num_colors-1); double color_pct1 = eff_pos_adj / blend_pct; int color_index = (int)color_pct1; blend_pct = color_pct1 - (double)color_index; buffer.Get2ColorBlend(color_index, std::min(color_index+1,num_colors-1), std::min( blend_pct, 1.0), color); double pos_x = buffer.BufferWi * center_x/100.0; double pos_y = buffer.BufferHt * center_y/100.0; double radius1 = start_radius; double radius2 = end_radius; double radius_center = radius1 + (radius2 - radius1) * eff_pos_adj; double half_width = (start_width + (end_width - start_width) * eff_pos_adj) / 2.0; radius1 = radius_center - half_width; radius2 = radius_center + half_width; double step = buffer.GetStepAngle(radius1, radius2); for( int x = 0; x < buffer.BufferWi; x++ ) { for( int y = 0; y < buffer.BufferHt; y++ ) { temp_colors_pct[x][y] = 0.0; } } buffer.ClearTempBuf(); for( double current_angle = 0.0; current_angle <= 360.0; current_angle += step ) { for( double r = std::max(0.0, radius1); r <= radius2; r += 0.5 ) { double x1 = buffer.sin(ToRadians(current_angle)) * r + (double)pos_x; double y1 = buffer.cos(ToRadians(current_angle)) * r + (double)pos_y; if( blend_edges ) { double color_pct = 1.0 - std::abs(r-radius_center)/half_width; if( color_pct > 0.0 ) { if (x1 >= 0 && x1 < buffer.BufferWi && y1 >= 0 && y1 < buffer.BufferHt) { if (buffer.allowAlpha) { color.alpha = 255.0 * color_pct; buffer.SetPixel((int)x1,(int)y1,color); } else { temp_colors_pct[(int)x1][(int)y1] = color_pct; buffer.SetTempPixel((int)x1,(int)y1,color); } } } } else { buffer.SetPixel((int)x1,(int)y1,color); } } } // blend element data into final buffer if( blend_edges && !buffer.allowAlpha ) { for( int x = 0; x < buffer.BufferWi; x++ ) { for( int y = 0; y < buffer.BufferHt; y++ ) { if( temp_colors_pct[x][y] > 0.0 ) { buffer.GetTempPixel(x,y,c_new); buffer.GetPixel(x,y,c_old); buffer.Get2ColorAlphaBlend(c_old, c_new, temp_colors_pct[x][y], color); buffer.SetPixel(x,y,color); temp_colors_pct[x][y] = 0.0; } } } } }
void PinwheelEffect::Render(Effect *effect, const SettingsMap &SettingsMap, RenderBuffer &buffer) { float oset = buffer.GetEffectTimeIntervalPosition(); int pinwheel_arms = SettingsMap.GetInt("SLIDER_Pinwheel_Arms", 3); int pinwheel_twist = GetValueCurveInt("Pinwheel_Twist", 0, SettingsMap, oset); int pinwheel_thickness = GetValueCurveInt("Pinwheel_Thickness", 0, SettingsMap, oset); bool pinwheel_rotation = SettingsMap.GetBool("CHECKBOX_Pinwheel_Rotation"); const std::string &pinwheel_3d = SettingsMap["CHOICE_Pinwheel_3D"]; int xc_adj = GetValueCurveInt("PinwheelXC", 0, SettingsMap, oset); int yc_adj = GetValueCurveInt("PinwheelYC", 0, SettingsMap, oset); int pinwheel_armsize = GetValueCurveInt("Pinwheel_ArmSize", 100, SettingsMap, oset); int pspeed = GetValueCurveInt("Pinwheel_Speed", 10, SettingsMap, oset); const std::string &pinwheel_style = SettingsMap["CHOICE_Pinwheel_Style"]; int xc; float tmax; HSVValue hsv, hsv1; double pos = (buffer.curPeriod - buffer.curEffStartPer) * pspeed * buffer.frameTimeInMs / 50; int degrees_per_arm = 1; if (pinwheel_arms > 0) degrees_per_arm = 360 / pinwheel_arms; float armsize = (pinwheel_armsize / 100.0); if (pinwheel_style == "New Render Method") { std::vector<size_t> colorarray; colorarray.resize(pinwheel_arms); for (int i = 0; i < pinwheel_arms; i++) { colorarray[i] = i%buffer.GetColorCount(); } xc = (int)(ceil(std::hypot(buffer.BufferWi, buffer.BufferHt) / 2)); xc_adj = xc_adj*buffer.BufferWi / 200; yc_adj = yc_adj*buffer.BufferHt / 200; int max_radius = xc * armsize; if (pinwheel_thickness == 0) pinwheel_thickness = 1; tmax = (pinwheel_thickness / 100.0)*degrees_per_arm; // Force single visible line in case width is narrower than visible float pi_180 = M_PI/180; for(int a=0; a<pinwheel_arms; a++) { int ColorIdx = a%pinwheel_arms; xlColor color; buffer.palette.GetHSV(colorarray[ColorIdx], hsv); color = xlColor(hsv); int angle = (a*degrees_per_arm); if (pinwheel_rotation == 1) // do we have CW rotation { angle = (270 - angle) + pos; } else { angle = angle - 90 - pos; } int x,y, degrees_twist; for (float r=0; r<=max_radius; r+=0.5) { degrees_twist = (r/max_radius) * pinwheel_twist; int t2 = (int)angle%degrees_per_arm; double round = (float)t2 / (float)tmax; x = floor((int)(r * buffer.cos((angle + degrees_twist) * pi_180)) + xc_adj + buffer.BufferWi / 2); y = floor((int)(r * buffer.sin((angle + degrees_twist) * pi_180)) + yc_adj + buffer.BufferHt / 2); if (buffer.palette.IsSpatial(colorarray[ColorIdx])) { buffer.palette.GetSpatialColor(colorarray[ColorIdx], xc_adj + buffer.BufferWi / 2, yc_adj + buffer.BufferHt / 2, x, y, round, max_radius, color); } buffer.SetPixel(x,y,color); } } // Draw actual pinwheel arms for (int x = 0; x < buffer.BufferWi; x++) { int x1 = x - xc_adj - (buffer.BufferWi / 2); for (int y = 0; y < buffer.BufferHt; y++) { int y1 = y - yc_adj - (buffer.BufferHt / 2); double r = std::hypot(x1, y1); if (r <= max_radius) { double degrees_twist = (r / max_radius)*pinwheel_twist; double theta = (std::atan2(x1, y1) * 180 / 3.14159) + degrees_twist; if (pinwheel_rotation == 1) // do we have CW rotation { theta = pos + theta + (tmax/2); } else { theta = pos - theta + (tmax/2); } theta = theta + 540.0; int t2 = (int)theta%degrees_per_arm; if (t2 <= tmax) { double round = (float)t2 / (float)tmax; t2 = std::abs(t2 - (tmax/2)) * 2; xlColor color; int ColorIdx2 = ((int)((theta/degrees_per_arm)))%pinwheel_arms; if (buffer.palette.IsSpatial(colorarray[ColorIdx2])) { buffer.palette.GetSpatialColor(colorarray[ColorIdx2], xc_adj + buffer.BufferWi / 2, yc_adj + buffer.BufferHt / 2, x, y, round, max_radius, color); hsv = color.asHSV(); } else { buffer.palette.GetHSV(colorarray[ColorIdx2], hsv); } hsv1=hsv; color = xlColor(hsv1); if(pinwheel_3d=="3D") { if (buffer.allowAlpha) { color.alpha = 255.0 * ((tmax - t2) / tmax); } else { hsv1.value = hsv.value * ((tmax - t2) / tmax); color = hsv1; } } else if (pinwheel_3d == "3D Inverted") { if (buffer.allowAlpha) { color.alpha = 255.0 * ((t2) / tmax); } else { hsv1.value = hsv.value * ((t2) / tmax); color = hsv1; } } buffer.SetPixel(x, y, color); } } } } } else { // Old Render Method int a,xc,ColorIdx,base_degrees; float t,tmax; float radius; HSVValue hsv,hsv0,hsv1; size_t colorcnt=buffer.GetColorCount(); xc= (int)(std::max(buffer.BufferWi, buffer.BufferHt)/2); radius = xc/100.0; for(a=1; a<=pinwheel_arms; a++) { ColorIdx=a%colorcnt; buffer.palette.GetHSV(ColorIdx, hsv); // Now go and get the hsv value for this ColorIdx if(pinwheel_rotation==1) // do we have CW rotation { base_degrees = (a-1)*degrees_per_arm + pos; // yes } else { base_degrees = (a-1)*degrees_per_arm - pos; // no, we are CCW } Draw_arm(buffer, base_degrees, xc*armsize, pinwheel_twist,hsv,xc_adj,yc_adj); if(pinwheel_thickness>0) { tmax= (pinwheel_thickness/100.0)*degrees_per_arm/2.0; hsv1=hsv; xlColor color(hsv1); for (t=1; t<=tmax; t++) { if(pinwheel_3d=="3D") { if (buffer.allowAlpha) { color.alpha = 255.0 * ((tmax-t)/tmax); } else { hsv1.value = hsv.value * ((tmax-t)/tmax); color = hsv1; } } else if(pinwheel_3d=="3D Inverted") { if (buffer.allowAlpha) { color.alpha = 255.0 * ((t)/tmax); } else { hsv1.value = hsv.value * ((t)/tmax); color = hsv1; } } Draw_arm(buffer, base_degrees-t, xc*armsize, pinwheel_twist,color,xc_adj,yc_adj); Draw_arm(buffer, base_degrees+t, xc*armsize, pinwheel_twist,color,xc_adj,yc_adj); } } } } }
void OnEffect::Render(Effect *eff, const SettingsMap &SettingsMap, RenderBuffer &buffer) { int start = SettingsMap.GetInt(TEXTCTRL_Eff_On_Start, 100); int end = SettingsMap.GetInt(TEXTCTRL_Eff_On_End, 100); bool shimmer = SettingsMap.GetInt(CHECKBOX_On_Shimmer, 0) > 0; float cycles = SettingsMap.GetDouble(TEXTCTRL_On_Cycles, 1.0); int x,y; int cidx = 0; if (shimmer) { int tot = buffer.curPeriod - buffer.curEffStartPer; if (tot % 2) { if (buffer.palette.Size() <= 1) { return; } cidx = 1; } } bool spatialcolour = buffer.palette.IsSpatial(cidx); double adjust = buffer.GetEffectTimeIntervalPosition(cycles); xlColor color; if (start == 100 && end == 100) { buffer.palette.GetColor(cidx, color); } else { HSVValue hsv; buffer.palette.GetHSV(cidx,hsv); double d = adjust; d = start + (end - start) * d; d = d / 100.0; hsv.value = hsv.value * d; color = hsv; } int transparency = GetValueCurveInt("On_Transparency", 0, SettingsMap, adjust); if (transparency) { transparency *= 255; transparency /= 100; color.alpha = 255 - transparency; } ///////////////////////// DMX Support //////////////////////// // if the model is a DMX model this will write the color into // the proper red, green, and blue channels. ////////////////////////////////////////////////////////////// if (buffer.cur_model != "") { Model* model_info = buffer.frame->AllModels[buffer.cur_model]; if (model_info != nullptr) { if( model_info->GetDisplayAs() == "DMX" ) { xlColor c; DmxModel* dmx = (DmxModel*)model_info; int red_channel = dmx->GetRedChannel(); int grn_channel = dmx->GetGreenChannel(); int blu_channel = dmx->GetBlueChannel(); if( red_channel != 0 ) { c.red = color.red; c.green = color.red; c.blue = color.red; buffer.SetPixel(red_channel-1, 0, c); } if( grn_channel != 0 ) { c.red = color.green; c.green = color.green; c.blue = color.green; buffer.SetPixel(grn_channel-1, 0, c); } if( blu_channel != 0 ) { c.red = color.blue; c.green = color.blue; c.blue = color.blue; buffer.SetPixel(blu_channel-1, 0, c); } return; } } } ////////////////////////////////////////////////////////////// ///////////////////// End DMX Support //////////////////////// ////////////////////////////////////////////////////////////// //Every Node set to selected color for (x=0; x<buffer.BufferWi; x++) { for (y=0; y<buffer.BufferHt; y++) { if (spatialcolour) { buffer.palette.GetSpatialColor(cidx, (float)x / (float)buffer.BufferWi, (float)y / (float)buffer.BufferHt, color); if (start == 100 && end == 100) { } else { HSVValue hsv = color.asHSV(); double d = adjust; d = start + (end - start) * d; d = d / 100.0; hsv.value = hsv.value * d; color = hsv; } if (transparency) { color.alpha = 255 - transparency; } } buffer.SetPixel(x,y,color); } } if (shimmer || cycles != 1.0) { std::lock_guard<std::recursive_mutex> lock(eff->GetBackgroundDisplayList().lock); eff->GetBackgroundDisplayList().resize((buffer.curEffEndPer - buffer.curEffStartPer + 1) * 6); buffer.CopyPixelsToDisplayListX(eff, 0, 0, 0); } else if (buffer.needToInit) { std::lock_guard<std::recursive_mutex> lock(eff->GetBackgroundDisplayList().lock); eff->GetBackgroundDisplayList().resize(6); if (start == 100 && end == 100) { buffer.palette.GetColor(0, color); buffer.SetDisplayListHRect(eff, 0, 0.0, 0.0, 1.0, 1.0, color, color); } else { HSVValue hsv; buffer.palette.GetHSV(cidx,hsv); hsv.value = hsv.value * start / 100.0; color = hsv; buffer.palette.GetHSV(cidx,hsv); hsv.value = hsv.value * end / 100.0; buffer.SetDisplayListHRect(eff, 0, 0.0, 0.0, 1.0, 1.0, color, xlColor(hsv)); } buffer.needToInit = false; } }