Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "tofflinegl.h"
Toshihiro Shimizu 890ddd
#include "tstroke.h"
Toshihiro Shimizu 890ddd
#include "tpalette.h"
Toshihiro Shimizu 890ddd
#include "tvectorimage.h"
Toshihiro Shimizu 890ddd
#include "tvectorrenderdata.h"
Toshihiro Shimizu 890ddd
#include "tflash.h"
Toshihiro Shimizu 890ddd
#include "texception.h"
Toshihiro Shimizu 890ddd
#include "trasterimage.h"
Toshihiro Shimizu 890ddd
#include "drawutil.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzBase includes
Toshihiro Shimizu 890ddd
#include "trasterfx.h"
Toshihiro Shimizu 890ddd
#include "tparamuiconcept.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzLib includes
Toshihiro Shimizu 890ddd
#include "toonz/toonzimageutils.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzStdfx includes
Toshihiro Shimizu 890ddd
#include "particlesengine.h"
Toshihiro Shimizu 890ddd
#include "particlesmanager.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "particlesfx.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**************************************************************************
Toshihiro Shimizu 890ddd
//    Particles Fx  implementation
Toshihiro Shimizu 890ddd
//**************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
ParticlesFx::ParticlesFx()
Toshihiro Shimizu 890ddd
	: m_source("Texture"), m_control("Control"), source_ctrl_val(0), bright_thres_val(25), multi_source_val(false), center_val(TPointD(0.0, 0.0)), length_val(5.0), height_val(4.0), maxnum_val(10.0), lifetime_val(DoublePair(100., 100.)), lifetime_ctrl_val(0), column_lifetime_val(false), startpos_val(1), randseed_val(1), gravity_val(0.0), g_angle_val(0.0), gravity_ctrl_val(0)
Toshihiro Shimizu 890ddd
	  //, gravity_radius_val (4)
Toshihiro Shimizu 890ddd
	  ,
Toshihiro Shimizu 890ddd
	  friction_val(0.0), friction_ctrl_val(0), windint_val(0.0), windangle_val(0.0), swingmode_val(new TIntEnumParam(SWING_RANDOM, "Random")), randomx_val(DoublePair(0., 0.)), randomy_val(DoublePair(0., 0.)), randomx_ctrl_val(0), randomy_ctrl_val(0), swing_val(DoublePair(0., 0.)), speed_val(DoublePair(0., 10.)), speed_ctrl_val(0), speeda_val(DoublePair(0., 0.)), speeda_ctrl_val(0), speeda_use_gradient_val(false), speedscale_val(false), toplayer_val(new TIntEnumParam(TOP_YOUNGER, "Younger")), mass_val(DoublePair(1., 1.)), scale_val(DoublePair(100., 100.)), scale_ctrl_val(0), scale_ctrl_all_val(false), rot_val(DoublePair(0., 0.)), rot_ctrl_val(0), trail_val(DoublePair(0., 0.)), trailstep_val(0.0), rotswingmode_val(new TIntEnumParam(SWING_RANDOM, "Random")), rotspeed_val(0.0), rotsca_val(DoublePair(0., 0.)), rotswing_val(DoublePair(0., 0.)), pathaim_val(false), opacity_val(DoublePair(0., 100.)), opacity_ctrl_val(0), trailopacity_val(DoublePair(0., 100.)), scalestep_val(DoublePair(0., 0.)), scalestep_ctrl_val(0), fadein_val(0.0), fadeout_val(0.0), animation_val(new TIntEnumParam(ANIM_HOLD, "Hold Frame")), step_val(1), gencol_ctrl_val(0), gencol_spread_val(0.0), genfadecol_val(0.0), fincol_ctrl_val(0), fincol_spread_val(0.0), finrangecol_val(0.0), finfadecol_val(0.0), foutcol_ctrl_val(0), foutcol_spread_val(0.0), foutrangecol_val(0.0), foutfadecol_val(0.0), source_gradation_val(false), pick_color_for_every_frame_val(false), perspective_distribution_val(false)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	addInputPort("Texture1", new TRasterFxPort, 0);
Toshihiro Shimizu 890ddd
	addInputPort("Control1", new TRasterFxPort, 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	length_val->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
	height_val->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
	center_val->getX()->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
	center_val->getY()->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bindParam(this, "source_ctrl", source_ctrl_val);
Toshihiro Shimizu 890ddd
	bindParam(this, "bright_thres", bright_thres_val);
Toshihiro Shimizu 890ddd
	bright_thres_val->setValueRange(0, 255);
Toshihiro Shimizu 890ddd
	bindParam(this, "multi_source", multi_source_val);
Toshihiro Shimizu 890ddd
	bindParam(this, "center", center_val);
Toshihiro Shimizu 890ddd
	bindParam(this, "length", length_val);
Toshihiro Shimizu 890ddd
	length_val->setValueRange(1.0, (std::numeric_limits<double>::max)());</double>
Toshihiro Shimizu 890ddd
	bindParam(this, "height", height_val);
Toshihiro Shimizu 890ddd
	height_val->setValueRange(1.0, (std::numeric_limits<double>::max)());</double>
Toshihiro Shimizu 890ddd
	bindParam(this, "birth_rate", maxnum_val);
Toshihiro Shimizu 890ddd
	maxnum_val->setValueRange(0.0, (std::numeric_limits<double>::max)());</double>
Toshihiro Shimizu 890ddd
	bindParam(this, "lifetime", lifetime_val);
Toshihiro Shimizu 890ddd
	lifetime_val->getMin()->setValueRange(0., +3000.);
Toshihiro Shimizu 890ddd
	lifetime_val->getMax()->setValueRange(0., +3000.);
Toshihiro Shimizu 890ddd
	bindParam(this, "lifetime_ctrl", lifetime_ctrl_val);
Toshihiro Shimizu 890ddd
	bindParam(this, "column_lifetime", column_lifetime_val);
Toshihiro Shimizu 890ddd
	bindParam(this, "starting_frame", startpos_val);
Toshihiro Shimizu 890ddd
	bindParam(this, "random_seed", randseed_val);
Toshihiro Shimizu 890ddd
	bindParam(this, "gravity", gravity_val);
Toshihiro Shimizu 890ddd
	gravity_val->setValueRange(0.0, (std::numeric_limits<double>::max)());</double>
Toshihiro Shimizu 890ddd
	bindParam(this, "gravity_angle", g_angle_val);
Toshihiro Shimizu 890ddd
	g_angle_val->setMeasureName("angle");
Toshihiro Shimizu 890ddd
	bindParam(this, "gravity_ctrl", gravity_ctrl_val);
Toshihiro Shimizu 890ddd
	//  bindParam(this,"gravity_radius", gravity_radius_val);
Toshihiro Shimizu 890ddd
	//  gravity_radius_val->setValueRange(0,40);
Toshihiro Shimizu 890ddd
	bindParam(this, "friction", friction_val);
Toshihiro Shimizu 890ddd
	bindParam(this, "friction_ctrl", friction_ctrl_val);
Toshihiro Shimizu 890ddd
	bindParam(this, "wind", windint_val);
Toshihiro Shimizu 890ddd
	bindParam(this, "wind_angle", windangle_val);
Toshihiro Shimizu 890ddd
	windangle_val->setMeasureName("angle");
Toshihiro Shimizu 890ddd
	bindParam(this, "swing_mode", swingmode_val);
Toshihiro Shimizu 890ddd
	swingmode_val->addItem(SWING_SMOOTH, "Smooth");
Toshihiro Shimizu 890ddd
	bindParam(this, "scattering_x", randomx_val);
Toshihiro Shimizu 890ddd
	randomx_val->getMin()->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
	randomx_val->getMax()->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
	randomx_val->getMin()->setValueRange(-1000., +1000.);
Toshihiro Shimizu 890ddd
	randomx_val->getMax()->setValueRange(-1000., +1000.);
Toshihiro Shimizu 890ddd
	bindParam(this, "scattering_y", randomy_val);
Toshihiro Shimizu 890ddd
	randomy_val->getMin()->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
	randomy_val->getMax()->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
	randomy_val->getMin()->setValueRange(-1000., +1000.);
Toshihiro Shimizu 890ddd
	randomy_val->getMax()->setValueRange(-1000., +1000.);
Toshihiro Shimizu 890ddd
	bindParam(this, "scattering_x_ctrl", randomx_ctrl_val);
Toshihiro Shimizu 890ddd
	bindParam(this, "scattering_y_ctrl", randomy_ctrl_val);
Toshihiro Shimizu 890ddd
	bindParam(this, "swing", swing_val);
Toshihiro Shimizu 890ddd
	swing_val->getMin()->setValueRange(-1000., +1000.);
Toshihiro Shimizu 890ddd
	swing_val->getMax()->setValueRange(-1000., +1000.);
Toshihiro Shimizu 890ddd
	speed_val->getMin()->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
	speed_val->getMax()->setMeasureName("fxLength");
Toshihiro Shimizu 890ddd
	bindParam(this, "speed", speed_val);
Toshihiro Shimizu 890ddd
	speed_val->getMin()->setValueRange(-1000., +1000.);
Toshihiro Shimizu 890ddd
	speed_val->getMax()->setValueRange(-1000., +1000.);
Toshihiro Shimizu 890ddd
	bindParam(this, "speed_ctrl", speed_ctrl_val);
Toshihiro Shimizu 890ddd
	bindParam(this, "speed_angle", speeda_val);
Toshihiro Shimizu 890ddd
	speeda_val->getMin()->setValueRange(-1000., +1000.);
Toshihiro Shimizu 890ddd
	speeda_val->getMax()->setValueRange(-1000., +1000.);
Toshihiro Shimizu 890ddd
	speeda_val->getMin()->setMeasureName("angle");
Toshihiro Shimizu 890ddd
	speeda_val->getMax()->setMeasureName("angle");
Toshihiro Shimizu 890ddd
	bindParam(this, "speeda_ctrl", speeda_ctrl_val);
Toshihiro Shimizu 890ddd
	bindParam(this, "speeda_use_gradient", speeda_use_gradient_val);
Toshihiro Shimizu 890ddd
	bindParam(this, "speed_size", speedscale_val);
Toshihiro Shimizu 890ddd
	bindParam(this, "top_layer", toplayer_val);
Toshihiro Shimizu 890ddd
	toplayer_val->addItem(TOP_OLDER, "Older");
Toshihiro Shimizu 890ddd
	toplayer_val->addItem(TOP_SMALLER, "Smaller");
Toshihiro Shimizu 890ddd
	toplayer_val->addItem(TOP_BIGGER, "Bigger");
Toshihiro Shimizu 890ddd
	toplayer_val->addItem(TOP_RANDOM, "Random");
Toshihiro Shimizu 890ddd
	bindParam(this, "mass", mass_val);
Toshihiro Shimizu 890ddd
	mass_val->getMin()->setValueRange(0., +1000.);
Toshihiro Shimizu 890ddd
	mass_val->getMax()->setValueRange(0., +1000.);
Toshihiro Shimizu 890ddd
	bindParam(this, "scale", scale_val);
Toshihiro Shimizu 890ddd
	scale_val->getMin()->setValueRange(0., +1000.);
Toshihiro Shimizu 890ddd
	scale_val->getMax()->setValueRange(0., +1000.);
Toshihiro Shimizu 890ddd
	bindParam(this, "scale_ctrl", scale_ctrl_val);
Toshihiro Shimizu 890ddd
	bindParam(this, "scale_ctrl_all", scale_ctrl_all_val);
Toshihiro Shimizu 890ddd
	bindParam(this, "rot", rot_val);
Toshihiro Shimizu 890ddd
	rot_val->getMin()->setValueRange(-1000., +1000.);
Toshihiro Shimizu 890ddd
	rot_val->getMax()->setValueRange(-1000., +1000.);
Toshihiro Shimizu 890ddd
	rot_val->getMin()->setMeasureName("angle");
Toshihiro Shimizu 890ddd
	rot_val->getMax()->setMeasureName("angle");
Toshihiro Shimizu 890ddd
	bindParam(this, "rot_ctrl", rot_ctrl_val);
Toshihiro Shimizu 890ddd
	bindParam(this, "trail", trail_val);
Toshihiro Shimizu 890ddd
	trail_val->getMin()->setValueRange(0., +1000.);
Toshihiro Shimizu 890ddd
	trail_val->getMax()->setValueRange(0., +1000.);
Toshihiro Shimizu 890ddd
	bindParam(this, "trail_step", trailstep_val);
Toshihiro Shimizu 890ddd
	trailstep_val->setValueRange(1.0, (std::numeric_limits<double>::max)());</double>
Toshihiro Shimizu 890ddd
	bindParam(this, "spin_swing_mode", rotswingmode_val);
Toshihiro Shimizu 890ddd
	rotswingmode_val->addItem(SWING_SMOOTH, "Smooth");
Toshihiro Shimizu 890ddd
	bindParam(this, "spin_speed", rotspeed_val);
Toshihiro Shimizu 890ddd
	rotspeed_val->setMeasureName("angle");
Toshihiro Shimizu 890ddd
	bindParam(this, "spin_random", rotsca_val);
Toshihiro Shimizu 890ddd
	rotsca_val->getMin()->setValueRange(-1000., +1000.);
Toshihiro Shimizu 890ddd
	rotsca_val->getMax()->setValueRange(-1000., +1000.);
Toshihiro Shimizu 890ddd
	rotsca_val->getMin()->setMeasureName("angle");
Toshihiro Shimizu 890ddd
	rotsca_val->getMax()->setMeasureName("angle");
Toshihiro Shimizu 890ddd
	bindParam(this, "spin_swing", rotswing_val);
Toshihiro Shimizu 890ddd
	rotswing_val->getMin()->setValueRange(-1000., +1000.);
Toshihiro Shimizu 890ddd
	rotswing_val->getMax()->setValueRange(-1000., +1000.);
Toshihiro Shimizu 890ddd
	rotswing_val->getMin()->setMeasureName("angle");
Toshihiro Shimizu 890ddd
	rotswing_val->getMax()->setMeasureName("angle");
Toshihiro Shimizu 890ddd
	bindParam(this, "path_aim", pathaim_val);
Toshihiro Shimizu 890ddd
	bindParam(this, "opacity", opacity_val);
Toshihiro Shimizu 890ddd
	opacity_val->getMin()->setValueRange(0., +100.);
Toshihiro Shimizu 890ddd
	opacity_val->getMax()->setValueRange(0., +100.);
Toshihiro Shimizu 890ddd
	bindParam(this, "opacity_ctrl", opacity_ctrl_val);
Toshihiro Shimizu 890ddd
	bindParam(this, "trail_opacity", trailopacity_val);
Toshihiro Shimizu 890ddd
	trailopacity_val->getMin()->setValueRange(0., +100.);
Toshihiro Shimizu 890ddd
	trailopacity_val->getMax()->setValueRange(0., +100.);
Toshihiro Shimizu 890ddd
	bindParam(this, "scale_step", scalestep_val);
Toshihiro Shimizu 890ddd
	bindParam(this, "scale_step_ctrl", scalestep_ctrl_val);
Toshihiro Shimizu 890ddd
	scalestep_val->getMin()->setValueRange(-100., +100.);
Toshihiro Shimizu 890ddd
	scalestep_val->getMax()->setValueRange(-100., +100.);
Toshihiro Shimizu 890ddd
	bindParam(this, "fade_in", fadein_val);
Toshihiro Shimizu 890ddd
	bindParam(this, "fade_out", fadeout_val);
Toshihiro Shimizu 890ddd
	bindParam(this, "animation", animation_val);
Toshihiro Shimizu 890ddd
	animation_val->addItem(ANIM_RANDOM, "Random Frame");
Toshihiro Shimizu 890ddd
	animation_val->addItem(ANIM_CYCLE, "Column");
Toshihiro Shimizu 890ddd
	animation_val->addItem(ANIM_R_CYCLE, "Column - Random Start");
Toshihiro Shimizu 890ddd
	animation_val->addItem(ANIM_SR_CYCLE, "Column Swing - Random Start");
Toshihiro Shimizu 890ddd
	bindParam(this, "step", step_val);
Toshihiro Shimizu 890ddd
	step_val->setValueRange(1, (std::numeric_limits<int>::max)());</int>
Toshihiro Shimizu 890ddd
	TSpectrum::ColorKey colors[] = {
Toshihiro Shimizu 890ddd
		TSpectrum::ColorKey(0, TPixel32::Red),
Toshihiro Shimizu 890ddd
		TSpectrum::ColorKey(1, TPixel32::Red)};
Toshihiro Shimizu 890ddd
	gencol_val = TSpectrumParamP(tArrayCount(colors), colors);
Toshihiro Shimizu 890ddd
	bindParam(this, "birth_color", gencol_val);
Toshihiro Shimizu 890ddd
	bindParam(this, "birth_color_ctrl", gencol_ctrl_val);
Toshihiro Shimizu 890ddd
	bindParam(this, "birth_color_spread", gencol_spread_val);
Toshihiro Shimizu 890ddd
	gencol_spread_val->setValueRange(0.0, (std::numeric_limits<int>::max)());</int>
Toshihiro Shimizu 890ddd
	bindParam(this, "birth_color_fade", genfadecol_val);
Toshihiro Shimizu 890ddd
	genfadecol_val->setValueRange(0.0, 100.0);
Toshihiro Shimizu 890ddd
	TSpectrum::ColorKey colors1[] = {
Toshihiro Shimizu 890ddd
		TSpectrum::ColorKey(0, TPixel32::Green),
Toshihiro Shimizu 890ddd
		TSpectrum::ColorKey(1, TPixel32::Green)};
Toshihiro Shimizu 890ddd
	fincol_val = TSpectrumParamP(tArrayCount(colors1), colors1);
Toshihiro Shimizu 890ddd
	bindParam(this, "fadein_color", fincol_val);
Toshihiro Shimizu 890ddd
	bindParam(this, "fadein_color_ctrl", fincol_ctrl_val);
Toshihiro Shimizu 890ddd
	bindParam(this, "fadein_color_spread", fincol_spread_val);
Toshihiro Shimizu 890ddd
	fincol_spread_val->setValueRange(0.0, (std::numeric_limits<int>::max)());</int>
Toshihiro Shimizu 890ddd
	bindParam(this, "fadein_color_range", finrangecol_val);
Toshihiro Shimizu 890ddd
	finrangecol_val->setValueRange(0.0, (std::numeric_limits<double>::max)());</double>
Toshihiro Shimizu 890ddd
	bindParam(this, "fadein_color_fade", finfadecol_val);
Toshihiro Shimizu 890ddd
	finfadecol_val->setValueRange(0.0, 100.0);
Toshihiro Shimizu 890ddd
	TSpectrum::ColorKey colors2[] = {
Toshihiro Shimizu 890ddd
		TSpectrum::ColorKey(0, TPixel32::Blue),
Toshihiro Shimizu 890ddd
		TSpectrum::ColorKey(1, TPixel32::Blue)};
Toshihiro Shimizu 890ddd
	foutcol_val = TSpectrumParamP(tArrayCount(colors2), colors2);
Toshihiro Shimizu 890ddd
	bindParam(this, "fadeout_color", foutcol_val);
Toshihiro Shimizu 890ddd
	bindParam(this, "fadeout_color_ctrl", foutcol_ctrl_val);
Toshihiro Shimizu 890ddd
	bindParam(this, "fadeout_color_spread", foutcol_spread_val);
Toshihiro Shimizu 890ddd
	foutcol_spread_val->setValueRange(0.0, (std::numeric_limits<int>::max)());</int>
Toshihiro Shimizu 890ddd
	bindParam(this, "fadeout_color_range", foutrangecol_val);
Toshihiro Shimizu 890ddd
	foutrangecol_val->setValueRange(0.0, (std::numeric_limits<double>::max)());</double>
Toshihiro Shimizu 890ddd
	bindParam(this, "fadeout_color_fade", foutfadecol_val);
Toshihiro Shimizu 890ddd
	foutfadecol_val->setValueRange(0.0, 100.0);
Toshihiro Shimizu 890ddd
	bindParam(this, "source_gradation", source_gradation_val);
Toshihiro Shimizu 890ddd
	bindParam(this, "pick_color_for_every_frame", pick_color_for_every_frame_val);
Toshihiro Shimizu 890ddd
	bindParam(this, "perspective_distribution", perspective_distribution_val);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
ParticlesFx::~ParticlesFx()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ParticlesFx::getParamUIs(TParamUIConcept *&concepts, int &length)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	concepts = new TParamUIConcept[length = 2];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	concepts[0].m_type = TParamUIConcept::POINT;
Toshihiro Shimizu 890ddd
	concepts[0].m_label = "Center";
Toshihiro Shimizu 890ddd
	concepts[0].m_params.push_back(center_val);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	concepts[1].m_type = TParamUIConcept::RECT;
Toshihiro Shimizu 890ddd
	concepts[1].m_params.push_back(length_val);
Toshihiro Shimizu 890ddd
	concepts[1].m_params.push_back(height_val);
Toshihiro Shimizu 890ddd
	concepts[1].m_params.push_back(center_val);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool ParticlesFx::doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// Returning an infinite rect. This is necessary since building the actual bbox
Toshihiro Shimizu 890ddd
	// is a very complicate task.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bBox = TConsts::infiniteRectD;
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
string ParticlesFx::getAlias(double frame, const TRenderSettings &info) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	string alias = getFxType();
Toshihiro Shimizu 890ddd
	alias += "[";
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// alias degli effetti connessi alle porte di input separati da virgole
Toshihiro Shimizu 890ddd
	// una porta non connessa da luogo a un alias vuoto (stringa vuota)
Toshihiro Shimizu 890ddd
	for (int i = 0; i < getInputPortCount(); ++i) {
Toshihiro Shimizu 890ddd
		TFxPort *port = getInputPort(i);
Toshihiro Shimizu 890ddd
		if (port->isConnected()) {
Toshihiro Shimizu 890ddd
			TRasterFxP ifx = port->getFx();
Toshihiro Shimizu 890ddd
			assert(ifx);
Toshihiro Shimizu 890ddd
			alias += ifx->getAlias(frame, info);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		alias += ",";
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	string paramalias("");
Toshihiro Shimizu 890ddd
	for (int i = 0; i < getParams()->getParamCount(); ++i) {
Toshihiro Shimizu 890ddd
		TParam *param = getParams()->getParam(i);
Toshihiro Shimizu 890ddd
		paramalias += param->getName() + "=" + param->getValueAlias(frame, 3);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return alias + toString(frame) + "," + toString(getIdentifier()) + paramalias + "]";
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool ParticlesFx::allowUserCacheOnPort(int portNum)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// Only control port are currently allowed to cache upon explicit user's request
Toshihiro Shimizu 890ddd
	string tmpName = getInputPortName(portNum);
Toshihiro Shimizu 890ddd
	return tmpName.find("Control") != string::npos;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ParticlesFx::doDryCompute(TRectD &rect, double frame, const TRenderSettings &info)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	ParticlesManager *pc = ParticlesManager::instance();
Toshihiro Shimizu 890ddd
	unsigned long fxId = getIdentifier();
Toshihiro Shimizu 890ddd
	int inputPortCount = getInputPortCount();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int i, j, curr_frame = frame, startframe = startpos_val->getValue();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRenderSettings infoOnInput(info);
Toshihiro Shimizu 890ddd
	infoOnInput.m_affine = TAffine(); // Using the standard reference - indep. from cameras.
Toshihiro Shimizu 890ddd
	infoOnInput.m_bpp = 32;			  // Control ports rendered at 32 bit - since not visible.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (i = startframe - 1; i <= curr_frame; ++i) {
Toshihiro Shimizu 890ddd
		double frame = tmax(0, i);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (j = 0; j < inputPortCount; ++j) {
Toshihiro Shimizu 890ddd
			TFxPort *port = getInputPort(j);
Toshihiro Shimizu 890ddd
			string tmpName = getInputPortName(j);
Toshihiro Shimizu 890ddd
			if (port->isConnected()) {
Toshihiro Shimizu 890ddd
				TRasterFxP fx = port->getFx();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				// Now, consider that source ports work different than control ones
Toshihiro Shimizu 890ddd
				QString portName = QString::fromStdString(tmpName);
Toshihiro Shimizu 890ddd
				if (portName.startsWith("C")) {
Toshihiro Shimizu 890ddd
					// Control ports are calculated from start to current frame, since
Toshihiro Shimizu 890ddd
					// particle mechanics at current frame is influenced by previous ones
Toshihiro Shimizu 890ddd
					// (and therefore by all previous control images).
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					TRectD bbox;
Toshihiro Shimizu 890ddd
					fx->getBBox(frame, bbox, infoOnInput);
Toshihiro Shimizu 890ddd
					if (bbox == TConsts::infiniteRectD)
Toshihiro Shimizu 890ddd
						bbox = info.m_affine.inv() * rect;
Toshihiro Shimizu 890ddd
					fx->dryCompute(bbox, frame, infoOnInput);
Toshihiro Shimizu 890ddd
				} else if (portName.startsWith("T")) {
Toshihiro Shimizu 890ddd
					// Particles handle source ports caching procedures on its own.
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ParticlesFx::doCompute(TTile &tile, double frame, const TRenderSettings &ri)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	vector<int> lastframe;</int>
Toshihiro Shimizu 890ddd
	vector<tlevelp> partLevel;</tlevelp>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TPointD p_offset;
Toshihiro Shimizu 890ddd
	TDimension p_size(0, 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*-- 参照画像ポートの取得 --*/
Toshihiro Shimizu 890ddd
	vector<trasterfxport *=""> part_ports;   /*- テクスチャ素材画像のポート -*/</trasterfxport>
Toshihiro Shimizu 890ddd
	map<int, *="" trasterfxport=""> ctrl_ports; /*- コントロール画像のポート番号/ポート -*/</int,>
Toshihiro Shimizu 890ddd
	int portsCount = this->getInputPortCount();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (int i = 0; i < portsCount; ++i) {
Toshihiro Shimizu 890ddd
		string tmpName = this->getInputPortName(i);
Toshihiro Shimizu 890ddd
		QString portName = QString::fromStdString(tmpName);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (portName.startsWith("T")) {
Toshihiro Shimizu 890ddd
			TRasterFxPort *tmpPart = (TRasterFxPort *)this->getInputPort(tmpName);
Toshihiro Shimizu 890ddd
			if (tmpPart->isConnected())
Toshihiro Shimizu 890ddd
				part_ports.push_back((TRasterFxPort *)this->getInputPort(tmpName));
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			portName.replace(QString("Control"), QString(""));
Toshihiro Shimizu 890ddd
			TRasterFxPort *tmpCtrl = (TRasterFxPort *)this->getInputPort(tmpName);
Toshihiro Shimizu 890ddd
			if (tmpCtrl->isConnected())
Toshihiro Shimizu 890ddd
				ctrl_ports[portName.toInt()] = (TRasterFxPort *)this->getInputPort(tmpName);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	/*-- テクスチャ素材のバウンディングボックスを足し合わせる --*/
Toshihiro Shimizu 890ddd
	if (!part_ports.empty()) {
Toshihiro Shimizu 890ddd
		TRectD outTileBBox(tile.m_pos, TDimensionD(tile.getRaster()->getLx(), tile.getRaster()->getLy()));
Toshihiro Shimizu 890ddd
		TRectD bbox;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (unsigned int i = 0; i < (int)part_ports.size(); ++i) {
Toshihiro Shimizu 890ddd
			const TFxTimeRegion &tr = (*part_ports[i])->getTimeRegion();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			lastframe.push_back(tr.getLastFrame() + 1);
Toshihiro Shimizu 890ddd
			partLevel.push_back(new TLevel());
Toshihiro Shimizu 890ddd
			partLevel[i]->setName((*part_ports[i])->getAlias(0, ri));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// The particles offset must be calculated without considering the affine's translational
Toshihiro Shimizu 890ddd
			// component
Toshihiro Shimizu 890ddd
			TRenderSettings riZero(ri);
Toshihiro Shimizu 890ddd
			riZero.m_affine.a13 = riZero.m_affine.a23 = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// Calculate the bboxes union
Toshihiro Shimizu 890ddd
			for (int t = 0; t <= tr.getLastFrame(); ++t) {
Toshihiro Shimizu 890ddd
				TRectD inputBox;
Toshihiro Shimizu 890ddd
				(*part_ports[i])->getBBox(t, inputBox, riZero);
Toshihiro Shimizu 890ddd
				bbox += inputBox;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (bbox == TConsts::infiniteRectD)
Toshihiro Shimizu 890ddd
			bbox *= outTileBBox;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		p_size.lx = (int)bbox.getLx() + 1;
Toshihiro Shimizu 890ddd
		p_size.ly = (int)bbox.getLy() + 1;
Toshihiro Shimizu 890ddd
		p_offset = TPointD(0.5 * (bbox.x0 + bbox.x1), 0.5 * (bbox.y0 + bbox.y1));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	/*- テクスチャ素材が無い場合、丸を描く -*/
Toshihiro Shimizu 890ddd
	else {
Toshihiro Shimizu 890ddd
		partLevel.push_back(new TLevel());
Toshihiro Shimizu 890ddd
		partLevel[0]->setName("particles");
Toshihiro Shimizu 890ddd
		TDimension vecsize(10, 10);
Toshihiro Shimizu 890ddd
		TOfflineGL *offlineGlContext = new TOfflineGL(vecsize);
Toshihiro Shimizu 890ddd
		offlineGlContext->clear(TPixel32(0, 0, 0, 0));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TStroke *stroke;
Toshihiro Shimizu 890ddd
		stroke = makeEllipticStroke(0.07, TPointD((vecsize.lx - 1) * .5, (vecsize.ly - 1) * .5), 2.0, 2.0);
Toshihiro Shimizu 890ddd
		TVectorImageP vectmp = new TVectorImage();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TPalette *plt = new TPalette();
Toshihiro Shimizu 890ddd
		vectmp->setPalette(plt);
Toshihiro Shimizu 890ddd
		vectmp->addStroke(stroke);
Toshihiro Shimizu 890ddd
		TVectorRenderData rd(AffI, TRect(vecsize), plt, 0, true, true);
Toshihiro Shimizu 890ddd
		offlineGlContext->makeCurrent();
Toshihiro Shimizu 890ddd
		offlineGlContext->draw(vectmp, rd);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		partLevel[0]->setFrame(0, TRasterImageP(offlineGlContext->getRaster()->clone()));
Toshihiro Shimizu 890ddd
		p_size.lx = vecsize.lx + 1;
Toshihiro Shimizu 890ddd
		p_size.ly = vecsize.ly + 1;
Toshihiro Shimizu 890ddd
		lastframe.push_back(1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		delete offlineGlContext;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	Particles_Engine myEngine(this, frame);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Retrieving the dpi multiplier from the accumulated affine (which is isotropic). That is,
Toshihiro Shimizu 890ddd
	// the affine will be applied *before* this effect - and we'll multiply geometrical parameters
Toshihiro Shimizu 890ddd
	// by this dpi mult. in order to compensate.
Toshihiro Shimizu 890ddd
	float dpi = sqrt(fabs(ri.m_affine.det())) * 100;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TTile tileIn;
Toshihiro Shimizu 890ddd
	if (TRaster32P raster32 = tile.getRaster()) {
Toshihiro Shimizu 890ddd
		TFlash *flash = 0;
Toshihiro Shimizu 890ddd
		myEngine.render_particles(flash, &tile, part_ports, ri, p_size, p_offset, ctrl_ports, partLevel,
Toshihiro Shimizu 890ddd
								  1, (int)frame, 1, 0, 0, 0, 0, lastframe, getIdentifier());
Toshihiro Shimizu 890ddd
	} else if (TRaster64P raster64 = tile.getRaster()) {
Toshihiro Shimizu 890ddd
		TFlash *flash = 0;
Toshihiro Shimizu 890ddd
		myEngine.render_particles(flash, &tile, part_ports, ri, p_size, p_offset, ctrl_ports, partLevel,
Toshihiro Shimizu 890ddd
								  1, (int)frame, 1, 0, 0, 0, 0, lastframe, getIdentifier());
Toshihiro Shimizu 890ddd
	} else
Toshihiro Shimizu 890ddd
		throw TException("ParticlesFx: unsupported Pixel Type");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ParticlesFx::compute(TFlash &flash, int frame)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// Particles is currently disabled in Flash...
Toshihiro Shimizu 890ddd
	return;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ParticlesFx::compatibilityTranslatePort(int major, int minor, std::string &portName)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	VersionNumber version(major, minor);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (version < VersionNumber(1, 16)) {
Toshihiro Shimizu 890ddd
		if (portName == "Texture")
Toshihiro Shimizu 890ddd
			portName = "Texture1";
Toshihiro Shimizu 890ddd
	} else if (version < VersionNumber(1, 20)) {
Toshihiro Shimizu 890ddd
		int idx;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		bool chop =
Toshihiro Shimizu 890ddd
			((idx = portName.find("Texture")) != std::string::npos && idx > 0) ||
Toshihiro Shimizu 890ddd
			((idx = portName.find("Control")) != std::string::npos && idx > 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (chop)
Toshihiro Shimizu 890ddd
			portName.erase(portName.begin(), portName.begin() + idx);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
FX_PLUGIN_IDENTIFIER(ParticlesFx, "particlesFx");