mirror of
https://github.com/projectM-visualizer/projectm.git
synced 2026-03-03 14:05:17 +00:00
first step of rehashing Preset definition
git-svn-id: https://projectm.svn.sourceforge.net/svnroot/projectm/personal/carm/represet@1127 6778bc44-b910-0410-a7a0-be141de4315d
This commit is contained in:
530
src/libprojectM/MilkdropPreset.cpp
Executable file
530
src/libprojectM/MilkdropPreset.cpp
Executable file
@ -0,0 +1,530 @@
|
||||
/**
|
||||
* projectM -- Milkdrop-esque visualisation SDK
|
||||
* Copyright (C)2003-2004 projectM Team
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* See 'LICENSE.txt' included within this release
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef WIN32
|
||||
#include "win32-dirent.h"
|
||||
#else
|
||||
#include <dirent.h>
|
||||
#endif /** WIN32 */
|
||||
#include <time.h>
|
||||
|
||||
#include "MilkdropPreset.hpp"
|
||||
#include "Parser.hpp"
|
||||
#include "ParamUtils.hpp"
|
||||
#include "InitCondUtils.hpp"
|
||||
#include "fatal.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
|
||||
MilkdropPreset::MilkdropPreset(std::istream & in, const std::string & presetName, PresetInputs & presetInputs, PresetOutputs & presetOutputs):
|
||||
builtinParams(presetInputs, presetOutputs),
|
||||
m_presetName(presetName),
|
||||
m_presetOutputs(presetOutputs),
|
||||
m_presetInputs(presetInputs)
|
||||
{
|
||||
|
||||
m_presetOutputs.customWaves.clear();
|
||||
m_presetOutputs.customShapes.clear();
|
||||
|
||||
initialize(in);
|
||||
|
||||
}
|
||||
|
||||
|
||||
MilkdropPreset::MilkdropPreset(const std::string & absoluteFilePath, const std::string & presetName, PresetInputs & presetInputs, PresetOutputs & presetOutputs):
|
||||
builtinParams(presetInputs, presetOutputs),
|
||||
m_absoluteFilePath(absoluteFilePath),
|
||||
m_presetName(presetName),
|
||||
m_presetOutputs(presetOutputs),
|
||||
m_presetInputs(presetInputs)
|
||||
{
|
||||
|
||||
m_presetOutputs.customWaves.clear();
|
||||
m_presetOutputs.customShapes.clear();
|
||||
|
||||
initialize(absoluteFilePath);
|
||||
|
||||
}
|
||||
|
||||
Preset::~MilkdropPreset()
|
||||
{
|
||||
|
||||
Algorithms::traverse<Algorithms::TraverseFunctors::DeleteFunctor<InitCond> >(init_cond_tree);
|
||||
|
||||
Algorithms::traverse<Algorithms::TraverseFunctors::DeleteFunctor<InitCond> >(per_frame_init_eqn_tree);
|
||||
|
||||
Algorithms::traverse<Algorithms::TraverseFunctors::DeleteFunctor<PerPixelEqn> >(per_pixel_eqn_tree);
|
||||
|
||||
Algorithms::traverseVector<Algorithms::TraverseFunctors::DeleteFunctor<PerFrameEqn> >(per_frame_eqn_tree);
|
||||
|
||||
Algorithms::traverse<Algorithms::TraverseFunctors::DeleteFunctor<Param> >(user_param_tree);
|
||||
|
||||
for (PresetOutputs::cwave_container::iterator pos = customWaves.begin(); pos != customWaves.end(); ++pos)
|
||||
{
|
||||
delete(*pos);
|
||||
}
|
||||
|
||||
for (PresetOutputs::cshape_container::iterator pos = customShapes.begin(); pos != customShapes.end(); ++pos)
|
||||
{
|
||||
delete(*pos);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Adds a per pixel equation according to its string name. This
|
||||
will be used only by the parser */
|
||||
|
||||
int MilkdropPreset::add_per_pixel_eqn(char * name, GenExpr * gen_expr)
|
||||
{
|
||||
|
||||
PerPixelEqn * per_pixel_eqn = NULL;
|
||||
int index;
|
||||
Param * param = NULL;
|
||||
|
||||
assert(gen_expr);
|
||||
assert(name);
|
||||
|
||||
if (PER_PIXEL_EQN_DEBUG) printf("add_per_pixel_eqn: per pixel equation (name = \"%s\")\n", name);
|
||||
|
||||
|
||||
/* Search for the parameter so we know what matrix the per pixel equation is referencing */
|
||||
|
||||
param = ParamUtils::find(name, &this->builtinParams, &this->user_param_tree);
|
||||
if ( !param )
|
||||
{
|
||||
if (PER_PIXEL_EQN_DEBUG) printf("add_per_pixel_eqn: failed to allocate a new parameter!\n");
|
||||
return PROJECTM_FAILURE;
|
||||
}
|
||||
|
||||
index = per_pixel_eqn_tree.size();
|
||||
|
||||
/* Create the per pixel equation given the index, parameter, and general expression */
|
||||
if ((per_pixel_eqn = new PerPixelEqn(index, param, gen_expr)) == NULL)
|
||||
{
|
||||
if (PER_PIXEL_EQN_DEBUG) printf("add_per_pixel_eqn: failed to create new per pixel equation!\n");
|
||||
return PROJECTM_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Insert the per pixel equation into the preset per pixel database */
|
||||
std::pair<std::map<int, PerPixelEqn*>::iterator, bool> inserteeOption = per_pixel_eqn_tree.insert
|
||||
(std::make_pair(per_pixel_eqn->index, per_pixel_eqn));
|
||||
|
||||
if (!inserteeOption.second)
|
||||
{
|
||||
printf("failed to add per pixel eqn!\n");
|
||||
delete(per_pixel_eqn);
|
||||
return PROJECTM_FAILURE;
|
||||
}
|
||||
|
||||
/* Done */
|
||||
return PROJECTM_SUCCESS;
|
||||
}
|
||||
|
||||
void MilkdropPreset::evalCustomShapeInitConditions()
|
||||
{
|
||||
|
||||
for (PresetOutputs::cshape_container::iterator pos = customShapes.begin(); pos != customShapes.end(); ++pos) {
|
||||
assert(*pos);
|
||||
(*pos)->evalInitConds();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MilkdropPreset::evalCustomWaveInitConditions()
|
||||
{
|
||||
|
||||
for (PresetOutputs::cwave_container::iterator pos = customWaves.begin(); pos != customWaves.end(); ++pos) {
|
||||
assert(*pos);
|
||||
(*pos)->evalInitConds();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MilkdropPreset::evalCustomWavePerFrameEquations()
|
||||
{
|
||||
|
||||
for (PresetOutputs::cwave_container::iterator pos = customWaves.begin(); pos != customWaves.end(); ++pos)
|
||||
{
|
||||
|
||||
std::map<std::string, InitCond*> & init_cond_tree = (*pos)->init_cond_tree;
|
||||
for (std::map<std::string, InitCond*>::iterator _pos = init_cond_tree.begin(); _pos != init_cond_tree.end(); ++_pos)
|
||||
{
|
||||
assert(_pos->second);
|
||||
_pos->second->evaluate();
|
||||
}
|
||||
|
||||
std::vector<PerFrameEqn*> & per_frame_eqn_tree = (*pos)->per_frame_eqn_tree;
|
||||
for (std::vector<PerFrameEqn*>::iterator _pos = per_frame_eqn_tree.begin(); _pos != per_frame_eqn_tree.end(); ++_pos)
|
||||
{
|
||||
(*_pos)->evaluate();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MilkdropPreset::evalCustomShapePerFrameEquations()
|
||||
{
|
||||
|
||||
for (PresetOutputs::cshape_container::iterator pos = customShapes.begin(); pos != customShapes.end(); ++pos)
|
||||
{
|
||||
|
||||
std::map<std::string, InitCond*> & init_cond_tree = (*pos)->init_cond_tree;
|
||||
for (std::map<std::string, InitCond*>::iterator _pos = init_cond_tree.begin(); _pos != init_cond_tree.end(); ++_pos)
|
||||
{
|
||||
assert(_pos->second);
|
||||
_pos->second->evaluate();
|
||||
}
|
||||
|
||||
std::vector<PerFrameEqn*> & per_frame_eqn_tree = (*pos)->per_frame_eqn_tree;
|
||||
for (std::vector<PerFrameEqn*>::iterator _pos = per_frame_eqn_tree.begin(); _pos != per_frame_eqn_tree.end(); ++_pos)
|
||||
{
|
||||
(*_pos)->evaluate();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MilkdropPreset::evalPerFrameInitEquations()
|
||||
{
|
||||
|
||||
for (std::map<std::string, InitCond*>::iterator pos = per_frame_init_eqn_tree.begin(); pos != per_frame_init_eqn_tree.end(); ++pos)
|
||||
{
|
||||
assert(pos->second);
|
||||
pos->second->evaluate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MilkdropPreset::evalPerFrameEquations()
|
||||
{
|
||||
|
||||
for (std::map<std::string, InitCond*>::iterator pos = init_cond_tree.begin(); pos != init_cond_tree.end(); ++pos)
|
||||
{
|
||||
assert(pos->second);
|
||||
pos->second->evaluate();
|
||||
}
|
||||
|
||||
for (std::vector<PerFrameEqn*>::iterator pos = per_frame_eqn_tree.begin(); pos != per_frame_eqn_tree.end(); ++pos)
|
||||
{
|
||||
(*pos)->evaluate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MilkdropPreset::preloadInitialize() {
|
||||
|
||||
/// @note commented this out because it should be unnecessary
|
||||
// Clear equation trees
|
||||
//init_cond_tree.clear();
|
||||
//user_param_tree.clear();
|
||||
//per_frame_eqn_tree.clear();
|
||||
//per_pixel_eqn_tree.clear();
|
||||
//per_frame_init_eqn_tree.clear();
|
||||
|
||||
|
||||
}
|
||||
|
||||
void MilkdropPreset::postloadInitialize() {
|
||||
|
||||
/* It's kind of ugly to reset these values here. Should definitely be placed in the parser somewhere */
|
||||
this->per_frame_eqn_count = 0;
|
||||
this->per_frame_init_eqn_count = 0;
|
||||
|
||||
this->loadBuiltinParamsUnspecInitConds();
|
||||
this->loadCustomWaveUnspecInitConds();
|
||||
this->loadCustomShapeUnspecInitConds();
|
||||
|
||||
|
||||
/// @bug are you handling all the q variables conditions? in particular, the un-init case?
|
||||
//m_presetOutputs.q1 = 0;
|
||||
//m_presetOutputs.q2 = 0;
|
||||
//m_presetOutputs.q3 = 0;
|
||||
//m_presetOutputs.q4 = 0;
|
||||
//m_presetOutputs.q5 = 0;
|
||||
//m_presetOutputs.q6 = 0;
|
||||
//m_presetOutputs.q7 = 0;
|
||||
//m_presetOutputs.q8 = 0;
|
||||
|
||||
}
|
||||
|
||||
void MilkdropPreset::initialize(const std::string & pathname)
|
||||
{
|
||||
int retval;
|
||||
|
||||
preloadInitialize();
|
||||
|
||||
if (PRESET_DEBUG)
|
||||
std::cerr << "[Preset] loading file \"" << pathname << "\"..." << std::endl;
|
||||
|
||||
if ((retval = loadPresetFile(pathname)) < 0)
|
||||
{
|
||||
if (PRESET_DEBUG)
|
||||
std::cerr << "[Preset] failed to load file \"" <<
|
||||
pathname << "\"!" << std::endl;
|
||||
|
||||
/// @bug how should we handle this problem? a well define exception?
|
||||
throw retval;
|
||||
}
|
||||
|
||||
postloadInitialize();
|
||||
}
|
||||
|
||||
void MilkdropPreset::initialize(std::istream & in)
|
||||
{
|
||||
int retval;
|
||||
|
||||
preloadInitialize();
|
||||
|
||||
if ((retval = readIn(in)) < 0)
|
||||
{
|
||||
|
||||
if (PRESET_DEBUG)
|
||||
std::cerr << "[Preset] failed to load from stream " << std::endl;
|
||||
|
||||
/// @bug how should we handle this problem? a well define exception?
|
||||
throw retval;
|
||||
}
|
||||
|
||||
postloadInitialize();
|
||||
}
|
||||
|
||||
void MilkdropPreset::loadBuiltinParamsUnspecInitConds() {
|
||||
|
||||
InitCondUtils::LoadUnspecInitCond loadUnspecInitCond(this->init_cond_tree, this->per_frame_init_eqn_tree);
|
||||
|
||||
this->builtinParams.traverse(loadUnspecInitCond);
|
||||
Algorithms::traverse(user_param_tree, loadUnspecInitCond);
|
||||
|
||||
}
|
||||
|
||||
void MilkdropPreset::loadCustomWaveUnspecInitConds()
|
||||
{
|
||||
|
||||
|
||||
for (PresetOutputs::cwave_container::iterator pos = customWaves.begin(); pos != customWaves.end(); ++pos)
|
||||
{
|
||||
assert(*pos);
|
||||
(*pos)->loadUnspecInitConds();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MilkdropPreset::loadCustomShapeUnspecInitConds()
|
||||
{
|
||||
|
||||
for (PresetOutputs::cshape_container::iterator pos = customShapes.begin(); pos != customShapes.end(); ++pos)
|
||||
{
|
||||
assert(*pos);
|
||||
(*pos)->loadUnspecInitConds();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MilkdropPreset::evaluateFrame()
|
||||
{
|
||||
|
||||
// Evaluate all equation objects according to milkdrop flow diagram
|
||||
|
||||
evalPerFrameInitEquations();
|
||||
evalPerFrameEquations();
|
||||
|
||||
// Important step to ensure custom shapes and waves don't stamp on the q variable values
|
||||
// calculated by the per frame (init) and per pixel equations.
|
||||
transfer_q_variables(customWaves);
|
||||
transfer_q_variables(customShapes);
|
||||
|
||||
initialize_PerPixelMeshes();
|
||||
|
||||
evalPerPixelEqns();
|
||||
|
||||
evalCustomWaveInitConditions();
|
||||
evalCustomWavePerFrameEquations();
|
||||
|
||||
evalCustomShapeInitConditions();
|
||||
evalCustomShapePerFrameEquations();
|
||||
|
||||
// Setup pointers of the custom waves and shapes to the preset outputs instance
|
||||
/// @slow an extra O(N) per frame, could do this during eval
|
||||
m_presetOutputs.customWaves = PresetOutputs::cwave_container(customWaves);
|
||||
m_presetOutputs.customShapes = PresetOutputs::cshape_container(customShapes);
|
||||
|
||||
}
|
||||
|
||||
void MilkdropPreset::initialize_PerPixelMeshes()
|
||||
{
|
||||
|
||||
int x,y;
|
||||
for (x=0;x<m_presetInputs.gx;x++){
|
||||
for(y=0;y<m_presetInputs.gy;y++){
|
||||
m_presetOutputs.cx_mesh[x][y]=m_presetOutputs.cx;
|
||||
}}
|
||||
|
||||
|
||||
|
||||
|
||||
for (x=0;x<m_presetInputs.gx;x++){
|
||||
for(y=0;y<m_presetInputs.gy;y++){
|
||||
m_presetOutputs.cy_mesh[x][y]=m_presetOutputs.cy;
|
||||
}}
|
||||
|
||||
|
||||
|
||||
for (x=0;x<m_presetInputs.gx;x++){
|
||||
for(y=0;y<m_presetInputs.gy;y++){
|
||||
m_presetOutputs.sx_mesh[x][y]=m_presetOutputs.sx;
|
||||
}}
|
||||
|
||||
|
||||
|
||||
|
||||
for (x=0;x<m_presetInputs.gx;x++){
|
||||
for(y=0;y<m_presetInputs.gy;y++){
|
||||
m_presetOutputs.sy_mesh[x][y]=m_presetOutputs.sy;
|
||||
}}
|
||||
|
||||
|
||||
|
||||
for (x=0;x<m_presetInputs.gx;x++){
|
||||
for(y=0;y<m_presetInputs.gy;y++){
|
||||
m_presetOutputs.dx_mesh[x][y]=m_presetOutputs.dx;
|
||||
}}
|
||||
|
||||
|
||||
|
||||
for (x=0;x<m_presetInputs.gx;x++){
|
||||
for(y=0;y<m_presetInputs.gy;y++){
|
||||
m_presetOutputs.dy_mesh[x][y]=m_presetOutputs.dy;
|
||||
}}
|
||||
|
||||
|
||||
|
||||
for (x=0;x<m_presetInputs.gx;x++){
|
||||
for(y=0;y<m_presetInputs.gy;y++){
|
||||
m_presetOutputs.zoom_mesh[x][y]=m_presetOutputs.zoom;
|
||||
}}
|
||||
|
||||
|
||||
|
||||
|
||||
for (x=0;x<m_presetInputs.gx;x++){
|
||||
for(y=0;y<m_presetInputs.gy;y++){
|
||||
m_presetOutputs.zoomexp_mesh[x][y]=m_presetOutputs.zoomexp;
|
||||
}}
|
||||
|
||||
|
||||
|
||||
for (x=0;x<m_presetInputs.gx;x++){
|
||||
for(y=0;y<m_presetInputs.gy;y++){
|
||||
m_presetOutputs.rot_mesh[x][y]=m_presetOutputs.rot;
|
||||
}}
|
||||
|
||||
|
||||
for (x=0;x<m_presetInputs.gx;x++){
|
||||
for(y=0;y<m_presetInputs.gy;y++){
|
||||
m_presetOutputs.warp_mesh[x][y]=m_presetOutputs.warp;
|
||||
}}
|
||||
|
||||
|
||||
|
||||
}
|
||||
// Evaluates all per-pixel equations
|
||||
void MilkdropPreset::evalPerPixelEqns()
|
||||
{
|
||||
|
||||
/* Evaluate all per pixel equations in the tree datastructure */
|
||||
for (int mesh_x = 0; mesh_x < m_presetInputs.gx; mesh_x++)
|
||||
for (int mesh_y = 0; mesh_y < m_presetInputs.gy; mesh_y++)
|
||||
for (std::map<int, PerPixelEqn*>::iterator pos = per_pixel_eqn_tree.begin();
|
||||
pos != per_pixel_eqn_tree.end(); ++pos)
|
||||
pos->second->evaluate(mesh_x, mesh_y);
|
||||
|
||||
}
|
||||
|
||||
int MilkdropPreset::readIn(std::istream & fs) {
|
||||
|
||||
line_mode_t line_mode;
|
||||
presetOutputs().compositeShader.programSource.clear();
|
||||
presetOutputs().warpShader.programSource.clear();
|
||||
|
||||
/* Parse any comments */
|
||||
if (Parser::parse_top_comment(fs) < 0)
|
||||
{
|
||||
if (PRESET_DEBUG)
|
||||
std::cerr << "[Preset::readIn] no left bracket found..." << std::endl;
|
||||
return PROJECTM_FAILURE;
|
||||
}
|
||||
|
||||
/* Parse the preset name and a left bracket */
|
||||
char tmp_name[MAX_TOKEN_SIZE];
|
||||
|
||||
if (Parser::parse_preset_name(fs, tmp_name) < 0)
|
||||
{
|
||||
std::cerr << "[Preset::readIn] loading of preset name failed" << std::endl;
|
||||
return PROJECTM_ERROR;
|
||||
}
|
||||
|
||||
/// @note We ignore the preset name because [preset00] is just not so useful
|
||||
|
||||
// Loop through each line in file, trying to succesfully parse the file.
|
||||
// If a line does not parse correctly, keep trucking along to next line.
|
||||
int retval;
|
||||
while ((retval = Parser::parse_line(fs, this)) != EOF)
|
||||
{
|
||||
if (retval == PROJECTM_PARSE_ERROR)
|
||||
{
|
||||
line_mode = UNSET_LINE_MODE;
|
||||
// std::cerr << "[Preset::readIn()] parse error in file \"" << this->absoluteFilePath() << "\"" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// std::cerr << "loadPresetFile: finished line parsing successfully" << std::endl;
|
||||
|
||||
/* Now the preset has been loaded.
|
||||
Evaluation calls can be made at appropiate
|
||||
times in the frame loop */
|
||||
|
||||
return PROJECTM_SUCCESS;
|
||||
}
|
||||
|
||||
/* loadPresetFile: private function that loads a specific preset denoted
|
||||
by the given pathname */
|
||||
int MilkdropPreset::loadPresetFile(const std::string & pathname)
|
||||
{
|
||||
|
||||
|
||||
/* Open the file corresponding to pathname */
|
||||
std::ifstream fs(pathname.c_str());
|
||||
if (!fs || fs.eof()) {
|
||||
if (PRESET_DEBUG)
|
||||
std::cerr << "loadPresetFile: loading of file \"" << pathname << "\" failed!\n";
|
||||
return PROJECTM_ERROR;
|
||||
}
|
||||
|
||||
return readIn(fs);
|
||||
|
||||
}
|
||||
|
||||
246
src/libprojectM/MilkdropPreset.hpp
Normal file
246
src/libprojectM/MilkdropPreset.hpp
Normal file
@ -0,0 +1,246 @@
|
||||
|
||||
/**
|
||||
* projectM -- Milkdrop-esque visualisation SDK
|
||||
* Copyright (C)2003-2007 projectM Team
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* See 'LICENSE.txt' included within this release
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* $Id$
|
||||
*
|
||||
* MilkdropPreset
|
||||
*
|
||||
* $Log$
|
||||
*/
|
||||
|
||||
#ifndef _MilkdropPreset_HPP
|
||||
#define _MilkdropPreset_HPP
|
||||
|
||||
#include "Common.hpp"
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include <map>
|
||||
|
||||
#define MilkdropPreset_DEBUG 0 /* 0 for no debugging, 1 for normal, 2 for insane */
|
||||
|
||||
#include "CustomShape.hpp"
|
||||
#include "CustomWave.hpp"
|
||||
#include "Expr.hpp"
|
||||
#include "PerPixelEqn.hpp"
|
||||
#include "PerFrameEqn.hpp"
|
||||
#include "BuiltinParams.hpp"
|
||||
#include "PresetFrameIO.hpp"
|
||||
#include "InitCond.hpp"
|
||||
|
||||
class CustomWave;
|
||||
class CustomShape;
|
||||
class InitCond;
|
||||
|
||||
|
||||
class MilkdropPreset : public Preset
|
||||
{
|
||||
protected:
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/// Load a MilkdropPreset by filename with input and output buffers specified.
|
||||
/// \param absoluteFilePath the absolute file path of a MilkdropPreset to load from the file system
|
||||
/// \param MilkdropPresetName a descriptive name for the MilkdropPreset. Usually just the file name
|
||||
/// \param MilkdropPresetInputs a reference to read only projectM engine variables
|
||||
/// \param MilkdropPresetOutputs initialized and filled with data parsed from a MilkdropPreset
|
||||
MilkdropPreset(const std::string & absoluteFilePath, const std::string & MilkdropPresetName, MilkdropPresetInputs & MilkdropPresetInputs, MilkdropPresetOutputs & MilkdropPresetOutputs);
|
||||
|
||||
/// Load a MilkdropPreset from an input stream with input and output buffers specified.
|
||||
/// \param in an already initialized input stream to read the MilkdropPreset file from
|
||||
/// \param MilkdropPresetName a descriptive name for the MilkdropPreset. Usually just the file name
|
||||
/// \param MilkdropPresetInputs a reference to read only projectM engine variables
|
||||
/// \param MilkdropPresetOutputs initialized and filled with data parsed from a MilkdropPreset
|
||||
MilkdropPreset(std::istream & in, const std::string & MilkdropPresetName, MilkdropPresetInputs & MilkdropPresetInputs, MilkdropPresetOutputs & MilkdropPresetOutputs);
|
||||
|
||||
~MilkdropPreset();
|
||||
|
||||
/// Evaluates the MilkdropPreset for a frame given the current values of MilkdropPreset inputs / outputs
|
||||
/// All calculated values are stored in the associated MilkdropPreset outputs instance
|
||||
void evaluateFrame();
|
||||
|
||||
/// All "builtin" parameters for this MilkdropPreset. Anything *but* user defined parameters and
|
||||
/// custom waves / shapes objects go here.
|
||||
/// @bug encapsulate
|
||||
BuiltinParams builtinParams;
|
||||
|
||||
|
||||
/// Used by parser to find/create custom waves and shapes. May be refactored
|
||||
template <class CustomObject>
|
||||
static CustomObject * find_custom_object(int id, std::vector<CustomObject*> & customObjects);
|
||||
|
||||
|
||||
int per_pixel_eqn_string_index;
|
||||
int per_frame_eqn_string_index;
|
||||
int per_frame_init_eqn_string_index;
|
||||
|
||||
int per_frame_eqn_count,
|
||||
per_frame_init_eqn_count;
|
||||
|
||||
|
||||
/// Used by parser
|
||||
/// @bug refactor
|
||||
int add_per_pixel_eqn( char *name, GenExpr *gen_expr );
|
||||
|
||||
/// Accessor method to retrieve the absolute file path of the loaded MilkdropPreset
|
||||
/// \returns a file path string
|
||||
std::string absoluteFilePath() const
|
||||
{
|
||||
return m_absoluteFilePath;
|
||||
}
|
||||
|
||||
|
||||
/// Accessor method for the MilkdropPreset outputs instance associated with this MilkdropPreset
|
||||
/// \returns A MilkdropPreset output instance with values computed from most recent evaluateFrame()
|
||||
MilkdropPresetOutputs & MilkdropPresetOutputs() const
|
||||
{
|
||||
|
||||
return m_MilkdropPresetOutputs;
|
||||
}
|
||||
|
||||
MilkdropPresetInputs & MilkdropPresetInputs() const
|
||||
{
|
||||
|
||||
return m_PresetInputs;
|
||||
}
|
||||
/// Sets the descriptive name for this MilkdropPreset (typically the file name)
|
||||
/// \param theValue the new MilkdropPreset name to assign to the MilkdropPreset
|
||||
void setPresetName ( const std::string& theValue )
|
||||
{
|
||||
m_PresetName = theValue;
|
||||
}
|
||||
|
||||
/// Gets the descriptive name for this MilkdropPreset (typically the file name)
|
||||
/// \returns the name of the MilkdropPreset
|
||||
std::string MilkPresetName() const
|
||||
{
|
||||
return m_PresetName;
|
||||
}
|
||||
|
||||
/// @bug encapsulate
|
||||
|
||||
PresetOutputs::cwave_container customWaves;
|
||||
PresetOutputs::cshape_container customShapes;
|
||||
|
||||
/// @bug encapsulate
|
||||
/* Data structures that contain equation and initial condition information */
|
||||
std::vector<PerFrameEqn*> per_frame_eqn_tree; /* per frame equations */
|
||||
std::map<int, PerPixelEqn*> per_pixel_eqn_tree; /* per pixel equation tree */
|
||||
std::map<std::string,InitCond*> per_frame_init_eqn_tree; /* per frame initial equations */
|
||||
std::map<std::string,InitCond*> init_cond_tree; /* initial conditions */
|
||||
std::map<std::string,Param*> user_param_tree; /* user parameter splay tree */
|
||||
|
||||
private:
|
||||
|
||||
// The absolute file path of the MilkdropPreset
|
||||
std::string m_absoluteFilePath;
|
||||
|
||||
// The absolute path of the MilkdropPreset
|
||||
std::string m_absolutePath;
|
||||
|
||||
// The name for the MilkdropPreset. Usually the file name, but in theory anything goes
|
||||
std::string m_MilkdropPresetName;
|
||||
|
||||
void initialize(const std::string & pathname);
|
||||
void initialize(std::istream & in);
|
||||
|
||||
int loadPresetFile(const std::string & pathname);
|
||||
|
||||
void loadBuiltinParamsUnspecInitConds();
|
||||
void loadCustomWaveUnspecInitConds();
|
||||
void loadCustomShapeUnspecInitConds();
|
||||
|
||||
void evalCustomWavePerFrameEquations();
|
||||
void evalCustomShapePerFrameEquations();
|
||||
void evalPerFrameInitEquations();
|
||||
void evalCustomWaveInitConditions();
|
||||
void evalCustomShapeInitConditions();
|
||||
void evalPerPixelEqns();
|
||||
void evalPerFrameEquations();
|
||||
void initialize_PerPixelMeshes();
|
||||
int readIn(std::istream & fs);
|
||||
|
||||
void preloadInitialize();
|
||||
void postloadInitialize();
|
||||
|
||||
PresetOutputs & m_PresetOutputs;
|
||||
PresetInputs & m_PresetInputs; // added for gx, gy reference.
|
||||
|
||||
template <class CustomObject>
|
||||
void transfer_q_variables(std::vector<CustomObject*> & customObjects);
|
||||
};
|
||||
|
||||
|
||||
template <class CustomObject>
|
||||
void MilkdropPreset::transfer_q_variables(std::vector<CustomObject*> & customObjects)
|
||||
{
|
||||
CustomObject * custom_object;
|
||||
|
||||
for (typename std::vector<CustomObject*>::iterator pos = customObjects.begin(); pos != customObjects.end();++pos) {
|
||||
|
||||
custom_object = *pos;
|
||||
custom_object->q1 = m_MilkdropPresetOutputs.q[0];
|
||||
custom_object->q2 = m_MilkdropPresetOutputs.q[1];
|
||||
custom_object->q3 = m_MilkdropPresetOutputs.q[2];
|
||||
custom_object->q4 = m_MilkdropPresetOutputs.q[3];
|
||||
custom_object->q5 = m_MilkdropPresetOutputs.q[4];
|
||||
custom_object->q6 = m_MilkdropPresetOutputs.q[5];
|
||||
custom_object->q7 = m_MilkdropPresetOutputs.q[6];
|
||||
custom_object->q8 = m_MilkdropPresetOutputs.q[7];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
template <class CustomObject>
|
||||
CustomObject * MilkdropPreset::find_custom_object(int id, std::vector<CustomObject*> & customObjects)
|
||||
{
|
||||
|
||||
CustomObject * custom_object = NULL;
|
||||
|
||||
|
||||
for (typename std::vector<CustomObject*>::iterator pos = customObjects.begin(); pos != customObjects.end();++pos) {
|
||||
if ((*pos)->id == id) {
|
||||
custom_object = *pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (custom_object == NULL)
|
||||
{
|
||||
|
||||
if ((custom_object = new CustomObject(id)) == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
customObjects.push_back(custom_object);
|
||||
|
||||
}
|
||||
|
||||
assert(custom_object);
|
||||
return custom_object;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /** !_MilkdropPreset_HPP */
|
||||
@ -1,530 +1,25 @@
|
||||
/**
|
||||
* projectM -- Milkdrop-esque visualisation SDK
|
||||
* Copyright (C)2003-2004 projectM Team
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* See 'LICENSE.txt' included within this release
|
||||
/*
|
||||
* Preset.cpp
|
||||
*
|
||||
* Created on: Aug 5, 2008
|
||||
* Author: carm
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef WIN32
|
||||
#include "win32-dirent.h"
|
||||
#else
|
||||
#include <dirent.h>
|
||||
#endif /** WIN32 */
|
||||
#include <time.h>
|
||||
|
||||
#include "Preset.hpp"
|
||||
#include "Parser.hpp"
|
||||
#include "ParamUtils.hpp"
|
||||
#include "InitCondUtils.hpp"
|
||||
#include "fatal.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
Preset::Preset() {}
|
||||
|
||||
Preset::Preset(std::istream & in, const std::string & presetName, PresetInputs & presetInputs, PresetOutputs & presetOutputs):
|
||||
builtinParams(presetInputs, presetOutputs),
|
||||
m_presetName(presetName),
|
||||
m_presetOutputs(presetOutputs),
|
||||
m_presetInputs(presetInputs)
|
||||
{
|
||||
Preset::~Preset() {}
|
||||
|
||||
m_presetOutputs.customWaves.clear();
|
||||
m_presetOutputs.customShapes.clear();
|
||||
Preset::Preset(const std::string & presetName, const std::string & presetAuthor):
|
||||
_name(presetName), _author(presetAuthor) {}
|
||||
|
||||
initialize(in);
|
||||
void Preset::setName(const std::string & value) { _name = value; }
|
||||
|
||||
}
|
||||
const std::string & Preset::name() const { return _name; }
|
||||
|
||||
void setAuthor(const std::string & value) { _author = value; }
|
||||
|
||||
Preset::Preset(const std::string & absoluteFilePath, const std::string & presetName, PresetInputs & presetInputs, PresetOutputs & presetOutputs):
|
||||
builtinParams(presetInputs, presetOutputs),
|
||||
m_absoluteFilePath(absoluteFilePath),
|
||||
m_presetName(presetName),
|
||||
m_presetOutputs(presetOutputs),
|
||||
m_presetInputs(presetInputs)
|
||||
{
|
||||
const std::string & author() const { return _author; }
|
||||
|
||||
m_presetOutputs.customWaves.clear();
|
||||
m_presetOutputs.customShapes.clear();
|
||||
|
||||
initialize(absoluteFilePath);
|
||||
|
||||
}
|
||||
|
||||
Preset::~Preset()
|
||||
{
|
||||
|
||||
Algorithms::traverse<Algorithms::TraverseFunctors::DeleteFunctor<InitCond> >(init_cond_tree);
|
||||
|
||||
Algorithms::traverse<Algorithms::TraverseFunctors::DeleteFunctor<InitCond> >(per_frame_init_eqn_tree);
|
||||
|
||||
Algorithms::traverse<Algorithms::TraverseFunctors::DeleteFunctor<PerPixelEqn> >(per_pixel_eqn_tree);
|
||||
|
||||
Algorithms::traverseVector<Algorithms::TraverseFunctors::DeleteFunctor<PerFrameEqn> >(per_frame_eqn_tree);
|
||||
|
||||
Algorithms::traverse<Algorithms::TraverseFunctors::DeleteFunctor<Param> >(user_param_tree);
|
||||
|
||||
for (PresetOutputs::cwave_container::iterator pos = customWaves.begin(); pos != customWaves.end(); ++pos)
|
||||
{
|
||||
delete(*pos);
|
||||
}
|
||||
|
||||
for (PresetOutputs::cshape_container::iterator pos = customShapes.begin(); pos != customShapes.end(); ++pos)
|
||||
{
|
||||
delete(*pos);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Adds a per pixel equation according to its string name. This
|
||||
will be used only by the parser */
|
||||
|
||||
int Preset::add_per_pixel_eqn(char * name, GenExpr * gen_expr)
|
||||
{
|
||||
|
||||
PerPixelEqn * per_pixel_eqn = NULL;
|
||||
int index;
|
||||
Param * param = NULL;
|
||||
|
||||
assert(gen_expr);
|
||||
assert(name);
|
||||
|
||||
if (PER_PIXEL_EQN_DEBUG) printf("add_per_pixel_eqn: per pixel equation (name = \"%s\")\n", name);
|
||||
|
||||
|
||||
/* Search for the parameter so we know what matrix the per pixel equation is referencing */
|
||||
|
||||
param = ParamUtils::find(name, &this->builtinParams, &this->user_param_tree);
|
||||
if ( !param )
|
||||
{
|
||||
if (PER_PIXEL_EQN_DEBUG) printf("add_per_pixel_eqn: failed to allocate a new parameter!\n");
|
||||
return PROJECTM_FAILURE;
|
||||
}
|
||||
|
||||
index = per_pixel_eqn_tree.size();
|
||||
|
||||
/* Create the per pixel equation given the index, parameter, and general expression */
|
||||
if ((per_pixel_eqn = new PerPixelEqn(index, param, gen_expr)) == NULL)
|
||||
{
|
||||
if (PER_PIXEL_EQN_DEBUG) printf("add_per_pixel_eqn: failed to create new per pixel equation!\n");
|
||||
return PROJECTM_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Insert the per pixel equation into the preset per pixel database */
|
||||
std::pair<std::map<int, PerPixelEqn*>::iterator, bool> inserteeOption = per_pixel_eqn_tree.insert
|
||||
(std::make_pair(per_pixel_eqn->index, per_pixel_eqn));
|
||||
|
||||
if (!inserteeOption.second)
|
||||
{
|
||||
printf("failed to add per pixel eqn!\n");
|
||||
delete(per_pixel_eqn);
|
||||
return PROJECTM_FAILURE;
|
||||
}
|
||||
|
||||
/* Done */
|
||||
return PROJECTM_SUCCESS;
|
||||
}
|
||||
|
||||
void Preset::evalCustomShapeInitConditions()
|
||||
{
|
||||
|
||||
for (PresetOutputs::cshape_container::iterator pos = customShapes.begin(); pos != customShapes.end(); ++pos) {
|
||||
assert(*pos);
|
||||
(*pos)->evalInitConds();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Preset::evalCustomWaveInitConditions()
|
||||
{
|
||||
|
||||
for (PresetOutputs::cwave_container::iterator pos = customWaves.begin(); pos != customWaves.end(); ++pos) {
|
||||
assert(*pos);
|
||||
(*pos)->evalInitConds();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Preset::evalCustomWavePerFrameEquations()
|
||||
{
|
||||
|
||||
for (PresetOutputs::cwave_container::iterator pos = customWaves.begin(); pos != customWaves.end(); ++pos)
|
||||
{
|
||||
|
||||
std::map<std::string, InitCond*> & init_cond_tree = (*pos)->init_cond_tree;
|
||||
for (std::map<std::string, InitCond*>::iterator _pos = init_cond_tree.begin(); _pos != init_cond_tree.end(); ++_pos)
|
||||
{
|
||||
assert(_pos->second);
|
||||
_pos->second->evaluate();
|
||||
}
|
||||
|
||||
std::vector<PerFrameEqn*> & per_frame_eqn_tree = (*pos)->per_frame_eqn_tree;
|
||||
for (std::vector<PerFrameEqn*>::iterator _pos = per_frame_eqn_tree.begin(); _pos != per_frame_eqn_tree.end(); ++_pos)
|
||||
{
|
||||
(*_pos)->evaluate();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Preset::evalCustomShapePerFrameEquations()
|
||||
{
|
||||
|
||||
for (PresetOutputs::cshape_container::iterator pos = customShapes.begin(); pos != customShapes.end(); ++pos)
|
||||
{
|
||||
|
||||
std::map<std::string, InitCond*> & init_cond_tree = (*pos)->init_cond_tree;
|
||||
for (std::map<std::string, InitCond*>::iterator _pos = init_cond_tree.begin(); _pos != init_cond_tree.end(); ++_pos)
|
||||
{
|
||||
assert(_pos->second);
|
||||
_pos->second->evaluate();
|
||||
}
|
||||
|
||||
std::vector<PerFrameEqn*> & per_frame_eqn_tree = (*pos)->per_frame_eqn_tree;
|
||||
for (std::vector<PerFrameEqn*>::iterator _pos = per_frame_eqn_tree.begin(); _pos != per_frame_eqn_tree.end(); ++_pos)
|
||||
{
|
||||
(*_pos)->evaluate();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Preset::evalPerFrameInitEquations()
|
||||
{
|
||||
|
||||
for (std::map<std::string, InitCond*>::iterator pos = per_frame_init_eqn_tree.begin(); pos != per_frame_init_eqn_tree.end(); ++pos)
|
||||
{
|
||||
assert(pos->second);
|
||||
pos->second->evaluate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Preset::evalPerFrameEquations()
|
||||
{
|
||||
|
||||
for (std::map<std::string, InitCond*>::iterator pos = init_cond_tree.begin(); pos != init_cond_tree.end(); ++pos)
|
||||
{
|
||||
assert(pos->second);
|
||||
pos->second->evaluate();
|
||||
}
|
||||
|
||||
for (std::vector<PerFrameEqn*>::iterator pos = per_frame_eqn_tree.begin(); pos != per_frame_eqn_tree.end(); ++pos)
|
||||
{
|
||||
(*pos)->evaluate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Preset::preloadInitialize() {
|
||||
|
||||
/// @note commented this out because it should be unnecessary
|
||||
// Clear equation trees
|
||||
//init_cond_tree.clear();
|
||||
//user_param_tree.clear();
|
||||
//per_frame_eqn_tree.clear();
|
||||
//per_pixel_eqn_tree.clear();
|
||||
//per_frame_init_eqn_tree.clear();
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Preset::postloadInitialize() {
|
||||
|
||||
/* It's kind of ugly to reset these values here. Should definitely be placed in the parser somewhere */
|
||||
this->per_frame_eqn_count = 0;
|
||||
this->per_frame_init_eqn_count = 0;
|
||||
|
||||
this->loadBuiltinParamsUnspecInitConds();
|
||||
this->loadCustomWaveUnspecInitConds();
|
||||
this->loadCustomShapeUnspecInitConds();
|
||||
|
||||
|
||||
/// @bug are you handling all the q variables conditions? in particular, the un-init case?
|
||||
//m_presetOutputs.q1 = 0;
|
||||
//m_presetOutputs.q2 = 0;
|
||||
//m_presetOutputs.q3 = 0;
|
||||
//m_presetOutputs.q4 = 0;
|
||||
//m_presetOutputs.q5 = 0;
|
||||
//m_presetOutputs.q6 = 0;
|
||||
//m_presetOutputs.q7 = 0;
|
||||
//m_presetOutputs.q8 = 0;
|
||||
|
||||
}
|
||||
|
||||
void Preset::initialize(const std::string & pathname)
|
||||
{
|
||||
int retval;
|
||||
|
||||
preloadInitialize();
|
||||
|
||||
if (PRESET_DEBUG)
|
||||
std::cerr << "[Preset] loading file \"" << pathname << "\"..." << std::endl;
|
||||
|
||||
if ((retval = loadPresetFile(pathname)) < 0)
|
||||
{
|
||||
if (PRESET_DEBUG)
|
||||
std::cerr << "[Preset] failed to load file \"" <<
|
||||
pathname << "\"!" << std::endl;
|
||||
|
||||
/// @bug how should we handle this problem? a well define exception?
|
||||
throw retval;
|
||||
}
|
||||
|
||||
postloadInitialize();
|
||||
}
|
||||
|
||||
void Preset::initialize(std::istream & in)
|
||||
{
|
||||
int retval;
|
||||
|
||||
preloadInitialize();
|
||||
|
||||
if ((retval = readIn(in)) < 0)
|
||||
{
|
||||
|
||||
if (PRESET_DEBUG)
|
||||
std::cerr << "[Preset] failed to load from stream " << std::endl;
|
||||
|
||||
/// @bug how should we handle this problem? a well define exception?
|
||||
throw retval;
|
||||
}
|
||||
|
||||
postloadInitialize();
|
||||
}
|
||||
|
||||
void Preset::loadBuiltinParamsUnspecInitConds() {
|
||||
|
||||
InitCondUtils::LoadUnspecInitCond loadUnspecInitCond(this->init_cond_tree, this->per_frame_init_eqn_tree);
|
||||
|
||||
this->builtinParams.traverse(loadUnspecInitCond);
|
||||
Algorithms::traverse(user_param_tree, loadUnspecInitCond);
|
||||
|
||||
}
|
||||
|
||||
void Preset::loadCustomWaveUnspecInitConds()
|
||||
{
|
||||
|
||||
|
||||
for (PresetOutputs::cwave_container::iterator pos = customWaves.begin(); pos != customWaves.end(); ++pos)
|
||||
{
|
||||
assert(*pos);
|
||||
(*pos)->loadUnspecInitConds();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Preset::loadCustomShapeUnspecInitConds()
|
||||
{
|
||||
|
||||
for (PresetOutputs::cshape_container::iterator pos = customShapes.begin(); pos != customShapes.end(); ++pos)
|
||||
{
|
||||
assert(*pos);
|
||||
(*pos)->loadUnspecInitConds();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Preset::evaluateFrame()
|
||||
{
|
||||
|
||||
// Evaluate all equation objects according to milkdrop flow diagram
|
||||
|
||||
evalPerFrameInitEquations();
|
||||
evalPerFrameEquations();
|
||||
|
||||
// Important step to ensure custom shapes and waves don't stamp on the q variable values
|
||||
// calculated by the per frame (init) and per pixel equations.
|
||||
transfer_q_variables(customWaves);
|
||||
transfer_q_variables(customShapes);
|
||||
|
||||
initialize_PerPixelMeshes();
|
||||
|
||||
evalPerPixelEqns();
|
||||
|
||||
evalCustomWaveInitConditions();
|
||||
evalCustomWavePerFrameEquations();
|
||||
|
||||
evalCustomShapeInitConditions();
|
||||
evalCustomShapePerFrameEquations();
|
||||
|
||||
// Setup pointers of the custom waves and shapes to the preset outputs instance
|
||||
/// @slow an extra O(N) per frame, could do this during eval
|
||||
m_presetOutputs.customWaves = PresetOutputs::cwave_container(customWaves);
|
||||
m_presetOutputs.customShapes = PresetOutputs::cshape_container(customShapes);
|
||||
|
||||
}
|
||||
|
||||
void Preset::initialize_PerPixelMeshes()
|
||||
{
|
||||
|
||||
int x,y;
|
||||
for (x=0;x<m_presetInputs.gx;x++){
|
||||
for(y=0;y<m_presetInputs.gy;y++){
|
||||
m_presetOutputs.cx_mesh[x][y]=m_presetOutputs.cx;
|
||||
}}
|
||||
|
||||
|
||||
|
||||
|
||||
for (x=0;x<m_presetInputs.gx;x++){
|
||||
for(y=0;y<m_presetInputs.gy;y++){
|
||||
m_presetOutputs.cy_mesh[x][y]=m_presetOutputs.cy;
|
||||
}}
|
||||
|
||||
|
||||
|
||||
for (x=0;x<m_presetInputs.gx;x++){
|
||||
for(y=0;y<m_presetInputs.gy;y++){
|
||||
m_presetOutputs.sx_mesh[x][y]=m_presetOutputs.sx;
|
||||
}}
|
||||
|
||||
|
||||
|
||||
|
||||
for (x=0;x<m_presetInputs.gx;x++){
|
||||
for(y=0;y<m_presetInputs.gy;y++){
|
||||
m_presetOutputs.sy_mesh[x][y]=m_presetOutputs.sy;
|
||||
}}
|
||||
|
||||
|
||||
|
||||
for (x=0;x<m_presetInputs.gx;x++){
|
||||
for(y=0;y<m_presetInputs.gy;y++){
|
||||
m_presetOutputs.dx_mesh[x][y]=m_presetOutputs.dx;
|
||||
}}
|
||||
|
||||
|
||||
|
||||
for (x=0;x<m_presetInputs.gx;x++){
|
||||
for(y=0;y<m_presetInputs.gy;y++){
|
||||
m_presetOutputs.dy_mesh[x][y]=m_presetOutputs.dy;
|
||||
}}
|
||||
|
||||
|
||||
|
||||
for (x=0;x<m_presetInputs.gx;x++){
|
||||
for(y=0;y<m_presetInputs.gy;y++){
|
||||
m_presetOutputs.zoom_mesh[x][y]=m_presetOutputs.zoom;
|
||||
}}
|
||||
|
||||
|
||||
|
||||
|
||||
for (x=0;x<m_presetInputs.gx;x++){
|
||||
for(y=0;y<m_presetInputs.gy;y++){
|
||||
m_presetOutputs.zoomexp_mesh[x][y]=m_presetOutputs.zoomexp;
|
||||
}}
|
||||
|
||||
|
||||
|
||||
for (x=0;x<m_presetInputs.gx;x++){
|
||||
for(y=0;y<m_presetInputs.gy;y++){
|
||||
m_presetOutputs.rot_mesh[x][y]=m_presetOutputs.rot;
|
||||
}}
|
||||
|
||||
|
||||
for (x=0;x<m_presetInputs.gx;x++){
|
||||
for(y=0;y<m_presetInputs.gy;y++){
|
||||
m_presetOutputs.warp_mesh[x][y]=m_presetOutputs.warp;
|
||||
}}
|
||||
|
||||
|
||||
|
||||
}
|
||||
// Evaluates all per-pixel equations
|
||||
void Preset::evalPerPixelEqns()
|
||||
{
|
||||
|
||||
/* Evaluate all per pixel equations in the tree datastructure */
|
||||
for (int mesh_x = 0; mesh_x < m_presetInputs.gx; mesh_x++)
|
||||
for (int mesh_y = 0; mesh_y < m_presetInputs.gy; mesh_y++)
|
||||
for (std::map<int, PerPixelEqn*>::iterator pos = per_pixel_eqn_tree.begin();
|
||||
pos != per_pixel_eqn_tree.end(); ++pos)
|
||||
pos->second->evaluate(mesh_x, mesh_y);
|
||||
|
||||
}
|
||||
|
||||
int Preset::readIn(std::istream & fs) {
|
||||
|
||||
line_mode_t line_mode;
|
||||
presetOutputs().compositeShader.programSource.clear();
|
||||
presetOutputs().warpShader.programSource.clear();
|
||||
|
||||
/* Parse any comments */
|
||||
if (Parser::parse_top_comment(fs) < 0)
|
||||
{
|
||||
if (PRESET_DEBUG)
|
||||
std::cerr << "[Preset::readIn] no left bracket found..." << std::endl;
|
||||
return PROJECTM_FAILURE;
|
||||
}
|
||||
|
||||
/* Parse the preset name and a left bracket */
|
||||
char tmp_name[MAX_TOKEN_SIZE];
|
||||
|
||||
if (Parser::parse_preset_name(fs, tmp_name) < 0)
|
||||
{
|
||||
std::cerr << "[Preset::readIn] loading of preset name failed" << std::endl;
|
||||
return PROJECTM_ERROR;
|
||||
}
|
||||
|
||||
/// @note We ignore the preset name because [preset00] is just not so useful
|
||||
|
||||
// Loop through each line in file, trying to succesfully parse the file.
|
||||
// If a line does not parse correctly, keep trucking along to next line.
|
||||
int retval;
|
||||
while ((retval = Parser::parse_line(fs, this)) != EOF)
|
||||
{
|
||||
if (retval == PROJECTM_PARSE_ERROR)
|
||||
{
|
||||
line_mode = UNSET_LINE_MODE;
|
||||
// std::cerr << "[Preset::readIn()] parse error in file \"" << this->absoluteFilePath() << "\"" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// std::cerr << "loadPresetFile: finished line parsing successfully" << std::endl;
|
||||
|
||||
/* Now the preset has been loaded.
|
||||
Evaluation calls can be made at appropiate
|
||||
times in the frame loop */
|
||||
|
||||
return PROJECTM_SUCCESS;
|
||||
}
|
||||
|
||||
/* loadPresetFile: private function that loads a specific preset denoted
|
||||
by the given pathname */
|
||||
int Preset::loadPresetFile(const std::string & pathname)
|
||||
{
|
||||
|
||||
|
||||
/* Open the file corresponding to pathname */
|
||||
std::ifstream fs(pathname.c_str());
|
||||
if (!fs || fs.eof()) {
|
||||
if (PRESET_DEBUG)
|
||||
std::cerr << "loadPresetFile: loading of file \"" << pathname << "\" failed!\n";
|
||||
return PROJECTM_ERROR;
|
||||
}
|
||||
|
||||
return readIn(fs);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -1,248 +1,38 @@
|
||||
|
||||
/**
|
||||
* projectM -- Milkdrop-esque visualisation SDK
|
||||
* Copyright (C)2003-2007 projectM Team
|
||||
/*
|
||||
* Preset.hpp
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* See 'LICENSE.txt' included within this release
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* $Id$
|
||||
*
|
||||
* Preset
|
||||
*
|
||||
* $Log$
|
||||
* Created on: Aug 5, 2008
|
||||
* Author: carm
|
||||
*/
|
||||
|
||||
#ifndef _PRESET_HPP
|
||||
#define _PRESET_HPP
|
||||
#ifndef PRESET_HPP_
|
||||
#define PRESET_HPP_
|
||||
|
||||
#include "Common.hpp"
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include <map>
|
||||
|
||||
#define PRESET_DEBUG 0 /* 0 for no debugging, 1 for normal, 2 for insane */
|
||||
|
||||
#include "CustomShape.hpp"
|
||||
#include "CustomWave.hpp"
|
||||
#include "Expr.hpp"
|
||||
#include "PerPixelEqn.hpp"
|
||||
#include "PerFrameEqn.hpp"
|
||||
#include "BuiltinParams.hpp"
|
||||
#include "PresetFrameIO.hpp"
|
||||
#include "InitCond.hpp"
|
||||
|
||||
class CustomWave;
|
||||
class CustomShape;
|
||||
class InitCond;
|
||||
|
||||
|
||||
class Preset
|
||||
{
|
||||
protected:
|
||||
#include "BeatDetect.hpp"
|
||||
#include "Pipeline.hpp"
|
||||
#include "PipelineContext.hpp"
|
||||
|
||||
class Preset {
|
||||
public:
|
||||
|
||||
Preset();
|
||||
Preset(const std::string & name, const std::string & author);
|
||||
virtual ~Preset();
|
||||
|
||||
/// Load a preset by filename with input and output buffers specified.
|
||||
/// \param absoluteFilePath the absolute file path of a preset to load from the file system
|
||||
/// \param presetName a descriptive name for the preset. Usually just the file name
|
||||
/// \param presetInputs a reference to read only projectM engine variables
|
||||
/// \param presetOutputs initialized and filled with data parsed from a preset
|
||||
Preset(const std::string & absoluteFilePath, const std::string & presetName, PresetInputs & presetInputs, PresetOutputs & presetOutputs);
|
||||
void setName(const std::string & value);
|
||||
const std::string & name() const;
|
||||
|
||||
/// Load a preset from an input stream with input and output buffers specified.
|
||||
/// \param in an already initialized input stream to read the preset file from
|
||||
/// \param presetName a descriptive name for the preset. Usually just the file name
|
||||
/// \param presetInputs a reference to read only projectM engine variables
|
||||
/// \param presetOutputs initialized and filled with data parsed from a preset
|
||||
Preset(std::istream & in, const std::string & presetName, PresetInputs & presetInputs, PresetOutputs & presetOutputs);
|
||||
void setAuthor(const std::string & value);
|
||||
const std::string & author() const;
|
||||
|
||||
~Preset();
|
||||
|
||||
/// Evaluates the preset for a frame given the current values of preset inputs / outputs
|
||||
/// All calculated values are stored in the associated preset outputs instance
|
||||
void evaluateFrame();
|
||||
|
||||
/// All "builtin" parameters for this preset. Anything *but* user defined parameters and
|
||||
/// custom waves / shapes objects go here.
|
||||
/// @bug encapsulate
|
||||
BuiltinParams builtinParams;
|
||||
|
||||
|
||||
/// Used by parser to find/create custom waves and shapes. May be refactored
|
||||
template <class CustomObject>
|
||||
static CustomObject * find_custom_object(int id, std::vector<CustomObject*> & customObjects);
|
||||
|
||||
|
||||
int per_pixel_eqn_string_index;
|
||||
int per_frame_eqn_string_index;
|
||||
int per_frame_init_eqn_string_index;
|
||||
|
||||
int per_frame_eqn_count,
|
||||
per_frame_init_eqn_count;
|
||||
|
||||
|
||||
/// Used by parser
|
||||
/// @bug refactor
|
||||
int add_per_pixel_eqn( char *name, GenExpr *gen_expr );
|
||||
|
||||
/// Accessor method to retrieve the absolute file path of the loaded preset
|
||||
/// \returns a file path string
|
||||
std::string absoluteFilePath() const
|
||||
{
|
||||
return m_absoluteFilePath;
|
||||
}
|
||||
|
||||
|
||||
/// Accessor method for the preset outputs instance associated with this preset
|
||||
/// \returns A preset output instance with values computed from most recent evaluateFrame()
|
||||
PresetOutputs & presetOutputs() const
|
||||
{
|
||||
|
||||
return m_presetOutputs;
|
||||
}
|
||||
|
||||
PresetInputs & presetInputs() const
|
||||
{
|
||||
|
||||
return m_presetInputs;
|
||||
}
|
||||
/// Sets the descriptive name for this preset (typically the file name)
|
||||
/// \param theValue the new preset name to assign to the preset
|
||||
void setPresetName ( const std::string& theValue )
|
||||
{
|
||||
m_presetName = theValue;
|
||||
}
|
||||
|
||||
|
||||
/// Gets the descriptive name for this preset (typically the file name)
|
||||
/// \returns the name of the preset
|
||||
std::string presetName() const
|
||||
{
|
||||
return m_presetName;
|
||||
}
|
||||
|
||||
|
||||
/// @bug encapsulate
|
||||
|
||||
PresetOutputs::cwave_container customWaves;
|
||||
PresetOutputs::cshape_container customShapes;
|
||||
|
||||
/// @bug encapsulate
|
||||
/* Data structures that contain equation and initial condition information */
|
||||
std::vector<PerFrameEqn*> per_frame_eqn_tree; /* per frame equations */
|
||||
std::map<int, PerPixelEqn*> per_pixel_eqn_tree; /* per pixel equation tree */
|
||||
std::map<std::string,InitCond*> per_frame_init_eqn_tree; /* per frame initial equations */
|
||||
std::map<std::string,InitCond*> init_cond_tree; /* initial conditions */
|
||||
std::map<std::string,Param*> user_param_tree; /* user parameter splay tree */
|
||||
virtual const Pipeline & pipeline() const = 0;
|
||||
virtual void Render(const BeatDetect &music, const PipelineContext &context) = 0;
|
||||
|
||||
private:
|
||||
|
||||
// The absolute file path of the preset
|
||||
std::string m_absoluteFilePath;
|
||||
|
||||
// The absolute path of the preset
|
||||
std::string m_absolutePath;
|
||||
|
||||
// The name for the preset. Usually the file name, but in theory anything goes
|
||||
std::string m_presetName;
|
||||
|
||||
void initialize(const std::string & pathname);
|
||||
void initialize(std::istream & in);
|
||||
|
||||
int loadPresetFile(const std::string & pathname);
|
||||
|
||||
void loadBuiltinParamsUnspecInitConds();
|
||||
void loadCustomWaveUnspecInitConds();
|
||||
void loadCustomShapeUnspecInitConds();
|
||||
|
||||
void evalCustomWavePerFrameEquations();
|
||||
void evalCustomShapePerFrameEquations();
|
||||
void evalPerFrameInitEquations();
|
||||
void evalCustomWaveInitConditions();
|
||||
void evalCustomShapeInitConditions();
|
||||
void evalPerPixelEqns();
|
||||
void evalPerFrameEquations();
|
||||
void initialize_PerPixelMeshes();
|
||||
int readIn(std::istream & fs);
|
||||
|
||||
void preloadInitialize();
|
||||
void postloadInitialize();
|
||||
|
||||
PresetOutputs & m_presetOutputs;
|
||||
PresetInputs & m_presetInputs; // added for gx, gy reference.
|
||||
|
||||
template <class CustomObject>
|
||||
void transfer_q_variables(std::vector<CustomObject*> & customObjects);
|
||||
std::string _name;
|
||||
std::string _author;
|
||||
};
|
||||
|
||||
|
||||
template <class CustomObject>
|
||||
void Preset::transfer_q_variables(std::vector<CustomObject*> & customObjects)
|
||||
{
|
||||
CustomObject * custom_object;
|
||||
|
||||
for (typename std::vector<CustomObject*>::iterator pos = customObjects.begin(); pos != customObjects.end();++pos) {
|
||||
|
||||
custom_object = *pos;
|
||||
custom_object->q1 = m_presetOutputs.q[0];
|
||||
custom_object->q2 = m_presetOutputs.q[1];
|
||||
custom_object->q3 = m_presetOutputs.q[2];
|
||||
custom_object->q4 = m_presetOutputs.q[3];
|
||||
custom_object->q5 = m_presetOutputs.q[4];
|
||||
custom_object->q6 = m_presetOutputs.q[5];
|
||||
custom_object->q7 = m_presetOutputs.q[6];
|
||||
custom_object->q8 = m_presetOutputs.q[7];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
template <class CustomObject>
|
||||
CustomObject * Preset::find_custom_object(int id, std::vector<CustomObject*> & customObjects)
|
||||
{
|
||||
|
||||
CustomObject * custom_object = NULL;
|
||||
|
||||
|
||||
for (typename std::vector<CustomObject*>::iterator pos = customObjects.begin(); pos != customObjects.end();++pos) {
|
||||
if ((*pos)->id == id) {
|
||||
custom_object = *pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (custom_object == NULL)
|
||||
{
|
||||
|
||||
if ((custom_object = new CustomObject(id)) == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
customObjects.push_back(custom_object);
|
||||
|
||||
}
|
||||
|
||||
assert(custom_object);
|
||||
return custom_object;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /** !_PRESET_HPP */
|
||||
#endif /* PRESET_HPP_ */
|
||||
|
||||
Reference in New Issue
Block a user