#include "PerFrameContext.hpp" #include "MilkdropPresetExceptions.hpp" #ifdef MILKDROP_PRESET_DEBUG #include #endif #define REG_VAR(var) \ var = projectm_eval_context_register_variable(perFrameCodeContext, #var); namespace libprojectM { namespace MilkdropPreset { PerFrameContext::PerFrameContext(projectm_eval_mem_buffer gmegabuf, PRJM_EVAL_F (*globalRegisters)[100]) : perFrameCodeContext(projectm_eval_context_create(gmegabuf, globalRegisters)) { } PerFrameContext::~PerFrameContext() { if (perFrameCodeHandle != nullptr) { projectm_eval_code_destroy(perFrameCodeHandle); } if (perFrameCodeContext != nullptr) { projectm_eval_context_destroy(perFrameCodeContext); } } void PerFrameContext::RegisterBuiltinVariables() { projectm_eval_context_reset_variables(perFrameCodeContext); REG_VAR(zoom); REG_VAR(zoomexp); REG_VAR(rot); REG_VAR(warp); REG_VAR(cx); REG_VAR(cy); REG_VAR(dx); REG_VAR(dy); REG_VAR(sx); REG_VAR(sy); REG_VAR(time); REG_VAR(fps); REG_VAR(bass); REG_VAR(mid); REG_VAR(treb); REG_VAR(bass_att); REG_VAR(mid_att); REG_VAR(treb_att); REG_VAR(frame); REG_VAR(decay); REG_VAR(wave_a); REG_VAR(wave_r); REG_VAR(wave_g); REG_VAR(wave_b); REG_VAR(wave_x); REG_VAR(wave_y); REG_VAR(wave_mystery); REG_VAR(wave_mode); for (int q = 0; q < QVarCount; q++) { std::string qvar = "q" + std::to_string(q + 1); q_vars[q] = projectm_eval_context_register_variable(perFrameCodeContext, qvar.c_str()); } REG_VAR(progress); REG_VAR(ob_size); REG_VAR(ob_r); REG_VAR(ob_g); REG_VAR(ob_b); REG_VAR(ob_a); REG_VAR(ib_size); REG_VAR(ib_r); REG_VAR(ib_g); REG_VAR(ib_b); REG_VAR(ib_a); REG_VAR(mv_x); REG_VAR(mv_y); REG_VAR(mv_dx); REG_VAR(mv_dy); REG_VAR(mv_l); REG_VAR(mv_r); REG_VAR(mv_g); REG_VAR(mv_b); REG_VAR(mv_a); REG_VAR(echo_zoom); REG_VAR(echo_alpha); REG_VAR(echo_orient); REG_VAR(wave_usedots); REG_VAR(wave_thick); REG_VAR(wave_additive); REG_VAR(wave_brighten); REG_VAR(darken_center); REG_VAR(gamma); REG_VAR(wrap); REG_VAR(invert); REG_VAR(brighten); REG_VAR(darken); REG_VAR(solarize); REG_VAR(meshx); REG_VAR(meshy); REG_VAR(pixelsx); REG_VAR(pixelsy); REG_VAR(aspectx); REG_VAR(aspecty); REG_VAR(blur1_min); REG_VAR(blur2_min); REG_VAR(blur3_min); REG_VAR(blur1_max); REG_VAR(blur2_max); REG_VAR(blur3_max); REG_VAR(blur1_edge_darken); } void PerFrameContext::EvaluateInitCode(PresetState& state) { if (state.perFrameInitCode.empty()) { return; } auto* initCode = projectm_eval_code_compile(perFrameCodeContext, state.perFrameInitCode.c_str()); if (initCode == nullptr) { #ifdef MILKDROP_PRESET_DEBUG int line; int col; auto* errmsg = projectm_eval_get_error(perFrameCodeContext, &line, &col); if (errmsg) { std::cerr << "[Preset] Could not compile per-frame INIT code: " << errmsg << "(L" << line << " C" << col << ")" << std::endl; } #endif throw MilkdropCompileException("Could not compile per-frame init code"); } projectm_eval_code_execute(initCode); projectm_eval_code_destroy(initCode); for (int q = 0; q < QVarCount; q++) { q_values_after_init_code[q] = *q_vars[q]; state.frameQVariables[q] = *q_vars[q]; } } void PerFrameContext::LoadStateVariables(PresetState& state) { *zoom = static_cast(state.zoom); *zoomexp = static_cast(state.zoomExponent); *rot = static_cast(state.rot); *warp = static_cast(state.warpAmount); *cx = static_cast(state.rotCX); *cy = static_cast(state.rotCY); *dx = static_cast(state.xPush); *dy = static_cast(state.yPush); *sx = static_cast(state.stretchX); *sy = static_cast(state.stretchY); *time = static_cast(state.renderContext.time); *fps = static_cast(state.renderContext.fps); *bass = static_cast(state.audioData.bass); *mid = static_cast(state.audioData.mid); *treb = static_cast(state.audioData.treb); *bass_att = static_cast(state.audioData.bassAtt); *mid_att = static_cast(state.audioData.midAtt); *treb_att = static_cast(state.audioData.trebAtt); *frame = static_cast(state.renderContext.frame); for (int q = 0; q < QVarCount; q++) { *q_vars[q] = q_values_after_init_code[q]; } *progress = static_cast(state.renderContext.progress); *decay = static_cast(state.decay); *wave_a = static_cast(state.waveAlpha); *wave_r = static_cast(state.waveR); *wave_g = static_cast(state.waveG); *wave_b = static_cast(state.waveB); *wave_x = static_cast(state.waveX); *wave_y = static_cast(state.waveY); *wave_mystery = static_cast(state.waveParam); *wave_mode = static_cast(state.waveMode); *ob_size = static_cast(state.outerBorderSize); *ob_r = static_cast(state.outerBorderR); *ob_g = static_cast(state.outerBorderG); *ob_b = static_cast(state.outerBorderB); *ob_a = static_cast(state.outerBorderA); *ib_size = static_cast(state.innerBorderSize); *ib_r = static_cast(state.innerBorderR); *ib_g = static_cast(state.innerBorderG); *ib_b = static_cast(state.innerBorderB); *ib_a = static_cast(state.innerBorderA); *mv_x = static_cast(state.mvX); *mv_y = static_cast(state.mvY); *mv_dx = static_cast(state.mvDX); *mv_dy = static_cast(state.mvDY); *mv_l = static_cast(state.mvL); *mv_r = static_cast(state.mvR); *mv_g = static_cast(state.mvG); *mv_b = static_cast(state.mvB); *mv_a = static_cast(state.mvA); *echo_zoom = static_cast(state.videoEchoZoom); *echo_alpha = static_cast(state.videoEchoAlpha); *echo_orient = static_cast(state.videoEchoOrientation); *wave_usedots = static_cast(state.waveDots); *wave_thick = static_cast(state.waveThick); *wave_additive = static_cast(state.additiveWaves); *wave_brighten = static_cast(state.maximizeWaveColor); *darken_center = static_cast(state.darkenCenter); *gamma = static_cast(state.gammaAdj); *wrap = static_cast(state.texWrap); *invert = static_cast(state.invert); *brighten = static_cast(state.brighten); *darken = static_cast(state.darken); *solarize = static_cast(state.solarize); *meshx = static_cast(state.renderContext.perPixelMeshX); *meshy = static_cast(state.renderContext.perPixelMeshY); *pixelsx = static_cast(state.renderContext.viewportSizeX); *pixelsy = static_cast(state.renderContext.viewportSizeY); *aspectx = static_cast(state.renderContext.invAspectX); *aspecty = static_cast(state.renderContext.invAspectY); *blur1_min = static_cast(state.blur1Min); *blur2_min = static_cast(state.blur2Min); *blur3_min = static_cast(state.blur3Min); *blur1_max = static_cast(state.blur1Max); *blur2_max = static_cast(state.blur2Max); *blur3_max = static_cast(state.blur3Max); *blur1_edge_darken = static_cast(state.blur1EdgeDarken); } void PerFrameContext::CompilePerFrameCode(const std::string& perFrameCode) { if (perFrameCode.empty()) { return; } perFrameCodeHandle = projectm_eval_code_compile(perFrameCodeContext, perFrameCode.c_str()); if (perFrameCodeHandle == nullptr) { #ifdef MILKDROP_PRESET_DEBUG int line; int col; auto* errmsg = projectm_eval_get_error(perFrameCodeContext, &line, &col); if (errmsg) { std::cerr << "[Preset] Could not compile per-frame code: " << errmsg << "(L" << line << " C" << col << ")" << std::endl; } #endif throw MilkdropCompileException("Could not compile per-frame code"); } } void PerFrameContext::ExecutePerFrameCode() { if (perFrameCodeHandle != nullptr) { projectm_eval_code_execute(perFrameCodeHandle); } } } // namespace MilkdropPreset } // namespace libprojectM