Toshihiro Shimizu 890ddd
#ifdef _MSC_VER
Toshihiro Shimizu 890ddd
#define NOMINMAX
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
#include <sstream></sstream>
Toshihiro Shimizu 890ddd
#include <string></string>
Toshihiro Shimizu 890ddd
#include <utility></utility>
Toshihiro Shimizu 890ddd
#include <stdexcept></stdexcept>
Toshihiro Shimizu 890ddd
#include <stdint.h></stdint.h>
Toshihiro Shimizu 890ddd
#if defined(_WIN32) || defined(_CYGWIN_)
Toshihiro Shimizu 890ddd
#define UUID UUID_
Toshihiro Shimizu 890ddd
#include <windows.h></windows.h>
Toshihiro Shimizu 890ddd
#undef UUID
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
#include <dlfcn.h></dlfcn.h>
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
#include <string.h></string.h>
Toshihiro Shimizu 890ddd
#include <map></map>
Toshihiro Shimizu 890ddd
#include <type_traits></type_traits>
Toshihiro Shimizu 890ddd
#include <functional></functional>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// #include "tfxparam.h"
Toshihiro Shimizu 890ddd
#include <toonzqt addfxcontextmenu.h=""> // as receiver</toonzqt>
Toshihiro Shimizu 890ddd
#include "tenv.h"
Toshihiro Shimizu 890ddd
#include "../include/toonzqt/fxsettings.h"
Toshihiro Shimizu 890ddd
#include "toonz/tcolumnfx.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "pluginhost.h"
Toshihiro Shimizu 890ddd
#include "toonz_plugin.h"
Toshihiro Shimizu 890ddd
#include "toonz_hostif.h"
Toshihiro Shimizu 890ddd
#include "toonz_params.h"
Toshihiro Shimizu 890ddd
#include "plugin_tile_interface.h"
Toshihiro Shimizu 890ddd
#include "plugin_port_interface.h"
Toshihiro Shimizu 890ddd
#include "plugin_fxnode_interface.h"
Toshihiro Shimizu 890ddd
#include "plugin_param_interface.h"
Toshihiro Shimizu 890ddd
#include "plugin_param_view_interface.h"
Toshihiro Shimizu 890ddd
#include "plugin_ui_page_interface.h"
Toshihiro Shimizu 890ddd
#include "plugin_utilities.h"
Toshihiro Shimizu 890ddd
#include "toonz_params.h"
Toshihiro Shimizu 890ddd
#include <qfileinfo></qfileinfo>
Toshihiro Shimizu 890ddd
#include <qdir></qdir>
Toshihiro Shimizu 890ddd
#include <qlabel></qlabel>
Toshihiro Shimizu 890ddd
#include <qhboxlayout></qhboxlayout>
Toshihiro Shimizu 890ddd
#include <qformlayout></qformlayout>
Toshihiro Shimizu 890ddd
//#include <qtconcurrent></qtconcurrent>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "plugin_param_traits.h"
Toshihiro Shimizu 890ddd
#include "../include/toonzqt/pluginloader.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace toonz; // plugin namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
extern std::map<std::string, *="" plugininformation=""> plugin_dict_;</std::string,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
  PluginLoadController が main thread queue を使うことと, 
Toshihiro Shimizu 890ddd
  QThread で他スレッドの待ち合わせがしにくい(sendor thread が QThread::wait() でブロックしていると emit signal が処理できずデッドロックする)ので、
Toshihiro Shimizu 890ddd
  大人しく polling にした.
Toshihiro Shimizu 890ddd
 */
Toshihiro Shimizu 890ddd
bool PluginLoader::load_entries(const std::string &basepath)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	static PluginLoadController *aw = NULL; /* main() から一度だけ呼ばれる */
Toshihiro Shimizu 890ddd
	if (!aw) {
Toshihiro Shimizu 890ddd
		aw = new PluginLoadController(basepath, NULL);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	bool ret = aw->wait(16 /* ms */);
Toshihiro Shimizu 890ddd
	if (ret)
Toshihiro Shimizu 890ddd
		aw = NULL; /* deleteLater で消えるはず */
Toshihiro Shimizu 890ddd
	return ret;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TFx *PluginLoader::create_host(const std::string &fxId)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::string id = fxId.substr(5);
Toshihiro Shimizu 890ddd
	auto it = plugin_dict_.find(id);
Toshihiro Shimizu 890ddd
	if (it != plugin_dict_.end()) {
Toshihiro Shimizu 890ddd
		auto plugin = new RasterFxPluginHost(it->second);
Toshihiro Shimizu 890ddd
		plugin->notify();
Toshihiro Shimizu 890ddd
		return plugin;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return NULL;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
std::map<std::string, *="" qtreewidgetitem=""> PluginLoader::create_menu_items(std::function<void(qtreewidgetitem *)=""> &&l1_handler, std::function<void(qtreewidgetitem *)=""> &&l2_handler)</void(qtreewidgetitem></void(qtreewidgetitem></std::string,>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::map<std::string, *="" qtreewidgetitem=""> vendors;</std::string,>
Toshihiro Shimizu 890ddd
	for (auto plugin : plugin_dict_) {
Toshihiro Shimizu 890ddd
		PluginDescription *desc = plugin.second->desc_;
Toshihiro Shimizu 890ddd
		if (vendors.count(desc->vendor_) == 0) {
Toshihiro Shimizu 890ddd
			auto vendor = new QTreeWidgetItem((QTreeWidget *)NULL, QStringList(QString::fromStdString(desc->vendor_)));
Toshihiro Shimizu 890ddd
			vendors.insert(std::make_pair(desc->vendor_, vendor));
Toshihiro Shimizu 890ddd
			l1_handler(vendor);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		auto vendor = vendors[desc->vendor_];
Toshihiro Shimizu 890ddd
		auto item = new QTreeWidgetItem((QTreeWidget *)NULL, QStringList(QString::fromStdString(desc->name_)));
Toshihiro Shimizu 890ddd
		item->setData(0, Qt::UserRole, QVariant("_plg_" + QString::fromStdString(desc->id_)));
Toshihiro Shimizu 890ddd
		l2_handler(item);
Toshihiro Shimizu 890ddd
		vendor->addChild(item);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return vendors;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static bool copy_rendering_setting(toonz_rendering_setting_t *dst, const TRenderSettings &src);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class PluginSetupMessage : public TThread::Message
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	PluginInformation *pi_;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	PluginSetupMessage(PluginInformation *pi) : pi_(pi) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void onDeliver()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		RasterFxPluginHost *fx = new RasterFxPluginHost(pi_);
Toshihiro Shimizu 890ddd
		if (pi_ && pi_->handler_) {
Toshihiro Shimizu 890ddd
			pi_->handler_->setup(fx);
Toshihiro Shimizu 890ddd
			/* fx は pi のラッパーとしてのみ構築されており、即座に削除される. 実 instance に引き継がれないので ここで createParam() 等を呼び出しても意味がない.
Toshihiro Shimizu 890ddd
			   ここで createParamsByDesc() などを呼び出しても、 instance の parameter は 0 になる.  */
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		delete fx;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TThread::Message *clone() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return new PluginSetupMessage(*this);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PluginInformation::~PluginInformation()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (library_) {
Toshihiro Shimizu 890ddd
		if (library_.use_count() == 1 && fin_) {
Toshihiro Shimizu 890ddd
			fin_();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	delete[] param_pages_;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PluginInformation::add_ref()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	++ref_count_;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PluginInformation::release()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (--ref_count_ == 0) {
Toshihiro Shimizu 890ddd
		delete this;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PluginDescription::PluginDescription(const plugin_probe_t *const probe)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	name_ = probe->name ? probe->name : "unnamed-plugin";
Toshihiro Shimizu 890ddd
	vendor_ = probe->vendor ? probe->vendor : "";
Toshihiro Shimizu 890ddd
	id_ = probe->id ? probe->id : "unnamed-plugin.plugin";
Toshihiro Shimizu 890ddd
	note_ = probe->note ? probe->note : "";
Toshihiro Shimizu 890ddd
	url_ = probe->helpurl ? probe->helpurl : "";
Toshihiro Shimizu 890ddd
	clss_ = probe->clss;
Toshihiro Shimizu 890ddd
	fullname_ = id_ + "$" + name_ + "$" + vendor_;
Toshihiro Shimizu 890ddd
	plugin_ver_ = probe->plugin_ver;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
RasterFxPluginHost::RasterFxPluginHost(PluginInformation *pinfo)
Toshihiro Shimizu 890ddd
	: TZeraryFx(), pi_(pinfo), user_data_(nullptr)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	pi_->add_ref();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static int create_param_view(toonz_node_handle_t node, toonz_param_view_handle_t *view)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	ParamView *p = NULL;
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		RasterFxPluginHost *fx = reinterpret_cast<rasterfxpluginhost *="">(node);</rasterfxpluginhost>
Toshihiro Shimizu 890ddd
		if (!fx) {
Toshihiro Shimizu 890ddd
			printf("create_param_view: invalid toonz_node_handle_t\n");
Toshihiro Shimizu 890ddd
			return TOONZ_ERROR_INVALID_HANDLE;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (p = fx->createParamView()) {
Toshihiro Shimizu 890ddd
			*view = p;
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			printf("create_param_view: invalid param name");
Toshihiro Shimizu 890ddd
			return TOONZ_ERROR_FAILED_TO_CREATE;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} catch (const std::exception &e) {
Toshihiro Shimizu 890ddd
		printf("create_param_view: exception: %s\n", e.what());
Toshihiro Shimizu 890ddd
		delete p;
Toshihiro Shimizu 890ddd
		return TOONZ_ERROR_UNKNOWN;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return TOONZ_OK;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static int setup_input_port(toonz_node_handle_t node, const char *name, int type)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		RasterFxPluginHost *fx = reinterpret_cast<rasterfxpluginhost *="">(node);</rasterfxpluginhost>
Toshihiro Shimizu 890ddd
		if (!fx)
Toshihiro Shimizu 890ddd
			return TOONZ_ERROR_INVALID_HANDLE;
Toshihiro Shimizu 890ddd
		if (!fx->addPortDesc({true, name, type})) {
Toshihiro Shimizu 890ddd
			printf("add_input_port: failed to add: already have\n");
Toshihiro Shimizu 890ddd
			return TOONZ_ERROR_BUSY;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} catch (const std::exception &e) {
Toshihiro Shimizu 890ddd
		printf("setup_putput_port: exception: %s\n", e.what());
Toshihiro Shimizu 890ddd
		return TOONZ_ERROR_UNKNOWN;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return TOONZ_OK;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static int setup_output_port(toonz_node_handle_t node, const char *name, int type)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		RasterFxPluginHost *fx = reinterpret_cast<rasterfxpluginhost *="">(node);</rasterfxpluginhost>
Toshihiro Shimizu 890ddd
		if (!fx)
Toshihiro Shimizu 890ddd
			return TOONZ_ERROR_INVALID_HANDLE;
Toshihiro Shimizu 890ddd
		if (!fx->addPortDesc({false, name, type})) {
Toshihiro Shimizu 890ddd
			printf("add_input_port: failed to add: already have\n");
Toshihiro Shimizu 890ddd
			return TOONZ_ERROR_BUSY;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} catch (const std::exception &e) {
Toshihiro Shimizu 890ddd
		printf("setup_putput_port: exception: %s\n", e.what());
Toshihiro Shimizu 890ddd
		return TOONZ_ERROR_UNKNOWN;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return TOONZ_OK;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static int add_input_port(toonz_node_handle_t node, const char *name, int type, toonz_port_handle_t *port)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		RasterFxPluginHost *fx = reinterpret_cast<rasterfxpluginhost *="">(node);</rasterfxpluginhost>
Toshihiro Shimizu 890ddd
		if (!fx)
Toshihiro Shimizu 890ddd
			return TOONZ_ERROR_INVALID_HANDLE;
Toshihiro Shimizu 890ddd
		auto p = std::make_shared<trasterfxport>();</trasterfxport>
Toshihiro Shimizu 890ddd
		/* TRasterFxPort は non-copyable なスマートポインタなのでポインタで引き回す */
Toshihiro Shimizu 890ddd
		if (!fx->addInputPort(name, p)) { // overloaded version
Toshihiro Shimizu 890ddd
			printf("add_input_port: failed to add: already have\n");
Toshihiro Shimizu 890ddd
			return TOONZ_ERROR_BUSY;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		*port = p.get();
Toshihiro Shimizu 890ddd
	} catch (const std::exception &e) {
Toshihiro Shimizu 890ddd
		printf("add_input_port: exception: %s\n", e.what());
Toshihiro Shimizu 890ddd
		return TOONZ_ERROR_UNKNOWN;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return TOONZ_OK;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static int get_input_port(toonz_node_handle_t node, const char *name, toonz_port_handle_t *port)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!(node && port)) {
Toshihiro Shimizu 890ddd
		return TOONZ_ERROR_NULL;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	RasterFxPluginHost *fx = reinterpret_cast<rasterfxpluginhost *="">(node);</rasterfxpluginhost>
Toshihiro Shimizu 890ddd
	std::string portName(name);
Toshihiro Shimizu 890ddd
	TFxPort *tfxport = fx->getInputPort(portName);
Toshihiro Shimizu 890ddd
	if (!tfxport) {
Toshihiro Shimizu 890ddd
		return TOONZ_ERROR_NOT_FOUND;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	*port = tfxport;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return TOONZ_OK;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static int add_output_port(toonz_node_handle_t node, const char *name, int type, toonz_port_handle_t *port)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TRasterFxPort *p = NULL;
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		RasterFxPluginHost *fx = reinterpret_cast<rasterfxpluginhost *="">(node);</rasterfxpluginhost>
Toshihiro Shimizu 890ddd
		if (!fx)
Toshihiro Shimizu 890ddd
			return TOONZ_ERROR_INVALID_HANDLE;
Toshihiro Shimizu 890ddd
		p = new TRasterFxPort();
Toshihiro Shimizu 890ddd
		/* TRasterFxPort は non-copyable なスマートポインタなのでポインタで引き回す */
Toshihiro Shimizu 890ddd
		if (fx->addOutputPort(name, p)) { // overloaded version
Toshihiro Shimizu 890ddd
			delete p;
Toshihiro Shimizu 890ddd
			return TOONZ_ERROR_BUSY;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		*port = p;
Toshihiro Shimizu 890ddd
	} catch (const std::exception &) {
Toshihiro Shimizu 890ddd
		delete p;
Toshihiro Shimizu 890ddd
		return TOONZ_ERROR_UNKNOWN;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return TOONZ_OK;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static int get_rect(toonz_rect_t *rect, double *x0, double *y0, double *x1, double *y1)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!(rect && x0 && y0 && x1 && y1)) {
Toshihiro Shimizu 890ddd
		return -2;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	*x0 = rect->x0;
Toshihiro Shimizu 890ddd
	*y0 = rect->y0;
Toshihiro Shimizu 890ddd
	*x1 = rect->x1;
Toshihiro Shimizu 890ddd
	*y1 = rect->y1;
Toshihiro Shimizu 890ddd
	return 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static int set_rect(toonz_rect_t *rect, double x0, double y0, double x1, double y1)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!rect) {
Toshihiro Shimizu 890ddd
		return -2;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	rect->x0 = x0;
Toshihiro Shimizu 890ddd
	rect->y0 = y0;
Toshihiro Shimizu 890ddd
	rect->x1 = x1;
Toshihiro Shimizu 890ddd
	rect->y1 = y1;
Toshihiro Shimizu 890ddd
	return 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static int add_preference(toonz_node_handle_t node, const char *name, toonz_ui_page_handle_t *ui)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	UIPage *p = NULL;
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		RasterFxPluginHost *fx = reinterpret_cast<rasterfxpluginhost *="">(node);</rasterfxpluginhost>
Toshihiro Shimizu 890ddd
		if (!fx) {
Toshihiro Shimizu 890ddd
			printf("add_preference: invalid toonz_node_handle_t\n");
Toshihiro Shimizu 890ddd
			return TOONZ_ERROR_INVALID_HANDLE;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (p = fx->createUIPage(name)) {
Toshihiro Shimizu 890ddd
			*ui = p;
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			printf("add_preference: failed to get UIPage\n");
Toshihiro Shimizu 890ddd
			return TOONZ_ERROR_FAILED_TO_CREATE;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} catch (const std::exception &e) {
Toshihiro Shimizu 890ddd
		printf("add_preference: exception: %s\n", e.what());
Toshihiro Shimizu 890ddd
		delete p;
Toshihiro Shimizu 890ddd
		return TOONZ_ERROR_UNKNOWN;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return TOONZ_OK;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static int add_param(toonz_node_handle_t node, const char *name, int type, toonz_param_handle_t *param)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	Param *p = NULL;
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		RasterFxPluginHost *fx = reinterpret_cast<rasterfxpluginhost *="">(node);</rasterfxpluginhost>
Toshihiro Shimizu 890ddd
		if (!fx) {
Toshihiro Shimizu 890ddd
			printf("add_param: invalid toonz_node_handle_t\n");
Toshihiro Shimizu 890ddd
			return TOONZ_ERROR_INVALID_HANDLE;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (p = fx->createParam(name, toonz_param_type_enum(type))) {
Toshihiro Shimizu 890ddd
			*param = p;
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			printf("add_param: invalid type");
Toshihiro Shimizu 890ddd
			return TOONZ_ERROR_FAILED_TO_CREATE;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} catch (const std::exception &e) {
Toshihiro Shimizu 890ddd
		printf("add_param: exception: %s\n", e.what());
Toshihiro Shimizu 890ddd
		delete p;
Toshihiro Shimizu 890ddd
		return TOONZ_ERROR_UNKNOWN;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return TOONZ_OK;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static int get_param(toonz_node_handle_t node, const char *name, toonz_param_handle_t *param)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		RasterFxPluginHost *fx = reinterpret_cast<rasterfxpluginhost *="">(node);</rasterfxpluginhost>
Toshihiro Shimizu 890ddd
		if (!fx) {
Toshihiro Shimizu 890ddd
			printf("get_param: invalid toonz_node_handle_t\n");
Toshihiro Shimizu 890ddd
			return TOONZ_ERROR_INVALID_HANDLE;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (Param *p = fx->getParam(name)) {
Toshihiro Shimizu 890ddd
			*param = p;
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			printf("get_param: invalid type");
Toshihiro Shimizu 890ddd
			return TOONZ_ERROR_NOT_FOUND;
Toshihiro Shimizu 890ddd
		}
Adric Worley f63c1a
	} catch (const std::exception&) {
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return TOONZ_OK;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static int set_user_data(toonz_node_handle_t node, void *user_data)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!node) {
Toshihiro Shimizu 890ddd
		return TOONZ_ERROR_NULL;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	RasterFxPluginHost *fx = reinterpret_cast<rasterfxpluginhost *="">(node);</rasterfxpluginhost>
Toshihiro Shimizu 890ddd
	fx->setUserData(user_data);
Toshihiro Shimizu 890ddd
	return TOONZ_OK;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static int get_user_data(toonz_node_handle_t node, void **user_data)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!node || !user_data) {
Toshihiro Shimizu 890ddd
		return TOONZ_ERROR_NULL;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	RasterFxPluginHost *fx = reinterpret_cast<rasterfxpluginhost *="">(node);</rasterfxpluginhost>
Toshihiro Shimizu 890ddd
	*user_data = fx->getUserData();
Toshihiro Shimizu 890ddd
	return TOONZ_OK;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool RasterFxPluginHost::addPortDesc(port_description_t &&desc)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	printf("addPortDesc: name:%s dir:%d type:%d\n", desc.name_.c_str(), desc.input_, desc.type_);
Toshihiro Shimizu 890ddd
	auto ret = pi_->port_mapper_.insert(std::make_pair(desc.name_, desc));
Toshihiro Shimizu 890ddd
	return ret.second;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void RasterFxPluginHost::notify()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	/* 最低限必要な setup をしてから通知する */
Toshihiro Shimizu 890ddd
	QString nm = QString::fromStdString(pi_->desc_->name_.c_str());
Toshihiro Shimizu 890ddd
	setName(nm.toStdWString());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	createParamsByDesc();
Toshihiro Shimizu 890ddd
	createPortsByDesc();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (pi_ && pi_->handler_->create)
Toshihiro Shimizu 890ddd
		pi_->handler_->create(this);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
RasterFxPluginHost::~RasterFxPluginHost()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (pi_ && pi_->handler_->destroy) {
Toshihiro Shimizu 890ddd
		pi_->handler_->destroy(this);
Toshihiro Shimizu 890ddd
		pi_->release();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	inputs_.clear();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
 node を click するなどの要因で頻繁に呼ばれる.
Toshihiro Shimizu 890ddd
 click した場合は FxsData::setFxs から呼ばれ、新しいインスタンスは FxsData::m_fxs に入れられ、 FxsData のインスタンスと同時に(大抵の場合は)即座に消される.
Toshihiro Shimizu 890ddd
 */
Toshihiro Shimizu 890ddd
TFx *RasterFxPluginHost::clone(bool recursive) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	RasterFxPluginHost *plugin = newInstance(pi_);
Toshihiro Shimizu 890ddd
	plugin->user_data_ = user_data_;
Toshihiro Shimizu 890ddd
	// clone ports before TFx::clone().
Toshihiro Shimizu 890ddd
	for (auto &ip : pi_->port_mapper_) {
Toshihiro Shimizu 890ddd
		if (ip.second.input_) {
Toshihiro Shimizu 890ddd
#if 0
Toshihiro Shimizu 890ddd
			/* addInputPort() 内で行われる port owner の更新は後勝ちだが,
Toshihiro Shimizu 890ddd
			   clone された新しいインスタンスのほうが先に消えてしまう場合に, 無効なポインタを示す owner が port に残ってしまう. この問題が解決したら共有できるようにしたい.
Toshihiro Shimizu 890ddd
			   (このため、 plugin 空間に通知される全ての handle には一貫性がない. ただし、後から一貫性がなくなるよりは遥かにいいだろう)
Toshihiro Shimizu 890ddd
			*/
Toshihiro Shimizu 890ddd
			plugin->addInputPort(getInputPortName(i), ip);
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
			plugin->addInputPort(ip.first, std::shared_ptr<tfxport>(new TRasterFxPort));</tfxport>
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 0b19cb
	printf("recursive:%d params:%d\n", recursive, params_.size());
Toshihiro Shimizu 890ddd
	// clone params before TFx::clone().
Toshihiro Shimizu 890ddd
	/* ui_pages_, param_views_ は pi に移ったが createParam の呼び出しだけはしておかないと Fx Settings 構築時に assert failed になる */
Shinya Kitaoka 0b19cb
	for (auto const ¶m : params_) {
Toshihiro Shimizu 890ddd
		/* 古い createParam() は desc をとらず、コンストラクト時にデフォルト値を持つタイプの T*Param を再作成できない */
Shinya Kitaoka f91c5a
		plugin->createParam(param->desc());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return TFx::clone(plugin, recursive);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
RasterFxPluginHost *RasterFxPluginHost::newInstance(PluginInformation *pi) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return new RasterFxPluginHost(pi);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
const TPersistDeclaration *RasterFxPluginHost::getDeclaration() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	printf("RasterFxPluginHost::getDeclaration()\n");
Toshihiro Shimizu 890ddd
	return pi_->decl_;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PluginDeclaration::PluginDeclaration(PluginInformation *pi)
Toshihiro Shimizu 890ddd
	: TFxDeclaration(TFxInfo(pi->desc_->id_, false)), pi_(pi)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TPersist *PluginDeclaration::create() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	RasterFxPluginHost *fx = new RasterFxPluginHost(pi_);
Toshihiro Shimizu 890ddd
	fx->notify();
Toshihiro Shimizu 890ddd
	return fx;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
std::string RasterFxPluginHost::getPluginId() const { return pi_->desc_->id_; };
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void *RasterFxPluginHost::getUserData()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return user_data_;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void RasterFxPluginHost::setUserData(void *user_data)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	user_data_ = user_data;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool RasterFxPluginHost::doGetBBox(double frame, TRectD &bbox, const TRenderSettings &info)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	using namespace plugin::utils;
Toshihiro Shimizu 890ddd
	bool ret = true; /* 負論理 */
Toshihiro Shimizu 890ddd
	if (pi_ && pi_->handler_->do_get_bbox) {
Toshihiro Shimizu 890ddd
		rendering_setting_t info_;
Toshihiro Shimizu 890ddd
		copy_rendering_setting(&info_, info);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		rect_t rc;
Toshihiro Shimizu 890ddd
		copy_rect(&rc, bbox);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		ret = ret && pi_->handler_->do_get_bbox(this, &info_, frame, &rc);
Toshihiro Shimizu 890ddd
		bbox = restore_rect(&rc);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return !ret;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void RasterFxPluginHost::doCompute(TTile &tile, double frame, const TRenderSettings &info)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (pi_ && pi_->handler_->do_compute) {
Toshihiro Shimizu 890ddd
		rendering_setting_t info_;
Toshihiro Shimizu 890ddd
		copy_rendering_setting(&info_, info);
Toshihiro Shimizu 890ddd
		pi_->handler_->do_compute(this, &info_, frame, &tile);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int RasterFxPluginHost::getMemoryRequirement(const TRectD &rect, double frame, const TRenderSettings &info)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	using namespace plugin::utils;
Toshihiro Shimizu 890ddd
	if (pi_ && pi_->handler_->get_memory_requirement) {
Toshihiro Shimizu 890ddd
		rendering_setting_t rs;
Toshihiro Shimizu 890ddd
		copy_rendering_setting(&rs, info);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		rect_t rc;
Toshihiro Shimizu 890ddd
		copy_rect(&rc, rect);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		size_t ignore = pi_->handler_->get_memory_requirement(this, &rs, frame, &rc);
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool RasterFxPluginHost::canHandle(const TRenderSettings &info, double frame)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (pi_ && pi_->handler_->can_handle) {
Toshihiro Shimizu 890ddd
		rendering_setting_t rs;
Toshihiro Shimizu 890ddd
		copy_rendering_setting(&rs, info);
Toshihiro Shimizu 890ddd
		return pi_->handler_->can_handle(this, &rs, frame);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	/* 適切なデフォルト値は 'geometric' の場合とそうでない場合で異なる */
Toshihiro Shimizu 890ddd
	return isPluginZerary(); /* better-default depends on that is 'geometric' or not */
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool RasterFxPluginHost::addInputPort(const std::string &nm, std::shared_ptr<tfxport> port)</tfxport>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	/* setOwnFx は addInputPort 内で行われている. setFx() は接続なので自分自身に呼んではダメ */
Toshihiro Shimizu 890ddd
	//port->setFx(this);
Toshihiro Shimizu 890ddd
	bool ret = TFx::addInputPort(nm, *port.get());
Toshihiro Shimizu 890ddd
	if (ret) {
Toshihiro Shimizu 890ddd
		inputs_.push_back(port);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return ret;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool RasterFxPluginHost::addOutputPort(const std::string &nm, TRasterFxPort *port)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	port->setFx(this);
Toshihiro Shimizu 890ddd
	return TFx::addOutputConnection(port);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void RasterFxPluginHost::callStartRenderHandler()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (pi_ && pi_->handler_ && pi_->handler_->start_render) {
Toshihiro Shimizu 890ddd
		pi_->handler_->start_render(this);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void RasterFxPluginHost::callEndRenderHandler()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (pi_ && pi_->handler_ && pi_->handler_->end_render) {
Toshihiro Shimizu 890ddd
		pi_->handler_->end_render(this);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void RasterFxPluginHost::callStartRenderFrameHandler(const TRenderSettings *rs, double frame)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	toonz_rendering_setting_t trs;
Toshihiro Shimizu 890ddd
	copy_rendering_setting(&trs, *rs);
Toshihiro Shimizu 890ddd
	if (pi_ && pi_->handler_ && pi_->handler_->on_new_frame) {
Toshihiro Shimizu 890ddd
		pi_->handler_->on_new_frame(this, &trs, frame);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void RasterFxPluginHost::callEndRenderFrameHandler(const TRenderSettings *rs, double frame)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	toonz_rendering_setting_t trs;
Toshihiro Shimizu 890ddd
	copy_rendering_setting(&trs, *rs);
Toshihiro Shimizu 890ddd
	if (pi_ && pi_->handler_ && pi_->handler_->on_end_frame) {
Toshihiro Shimizu 890ddd
		pi_->handler_->on_end_frame(this, &trs, frame);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
std::string RasterFxPluginHost::getUrl() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return pi_->desc_->url_;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
UIPage *RasterFxPluginHost::createUIPage(const char *name)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	pi_->ui_pages_.push_back(NULL);
Toshihiro Shimizu 890ddd
	pi_->ui_pages_.back() = new UIPage(name);
Toshihiro Shimizu 890ddd
	return pi_->ui_pages_.back();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// deprecated. for migration.
Shinya Kitaoka f91c5a
Param *RasterFxPluginHost::createParam(const char *name, toonz_param_type_enum e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	toonz_param_desc_t *desc = new toonz_param_desc_t;
Toshihiro Shimizu 890ddd
	memset(desc, 0, sizeof(toonz_param_desc_t));
Toshihiro Shimizu 890ddd
	desc->base.ver = {1, 0};
Toshihiro Shimizu 890ddd
	desc->key = name;
Toshihiro Shimizu 890ddd
	desc->traits_tag = e;
Shinya Kitaoka f91c5a
	return createParam(desc);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka f91c5a
Param *RasterFxPluginHost::createParam(const toonz_param_desc_t *desc)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TParamP p = parameter_factory(desc);
Toshihiro Shimizu 890ddd
	if (!p)
Toshihiro Shimizu 890ddd
		return nullptr;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	p->setDescription(desc->note);
Toshihiro Shimizu 890ddd
	p->setUILabel(desc->base.label);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bindParam(this, desc->key, p);
Toshihiro Shimizu 890ddd
Shinya Kitaoka f91c5a
	params_.push_back(std::make_shared<param>(this, desc->key, toonz_param_type_enum(desc->traits_tag), desc));
Shinya Kitaoka f91c5a
	return params_.back().get();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Param *RasterFxPluginHost::getParam(const char *name) const
Toshihiro Shimizu 890ddd
{
Shinya Kitaoka 0b19cb
	for (auto ¶m : params_) {
Toshihiro Shimizu 890ddd
		if (param->name() == name) {
Shinya Kitaoka 0b19cb
			return param.get();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return nullptr;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
ParamView *RasterFxPluginHost::createParamView()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	pi_->param_views_.push_back(NULL);
Toshihiro Shimizu 890ddd
	pi_->param_views_.back() = new ParamView();
Toshihiro Shimizu 890ddd
	return pi_->param_views_.back();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/* build で構築された GUI は plugin のインスタンスには紐づかない. 通常一度だけ呼ばれ使い回される.  */
Toshihiro Shimizu 890ddd
void RasterFxPluginHost::build(ParamsPageSet *pages)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	printf(">>>> RasterFxPluginHost::build: ui_pages:%d\n", pi_->ui_pages_.size());
Toshihiro Shimizu 890ddd
	for (std::size_t i = 0, size = pi_->ui_pages_.size(); i < size; ++i) {
Toshihiro Shimizu 890ddd
		pi_->ui_pages_[i]->build(this, pages);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	auto aboutpage = pages->createParamsPage();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if 1
Toshihiro Shimizu 890ddd
	/* FIXME: fxsettings で大きさの測定のためにいろいろやっているので使える layout/widget に制限がありそう.
Toshihiro Shimizu 890ddd
	   しかしなぜか最後の widget しか出ない */
Toshihiro Shimizu 890ddd
	aboutpage->beginGroup("Name");
Toshihiro Shimizu 890ddd
	aboutpage->addWidget(new QLabel(pi_->desc_->name_.c_str(), aboutpage));
Toshihiro Shimizu 890ddd
	aboutpage->endGroup();
Toshihiro Shimizu 890ddd
	aboutpage->beginGroup("Vendor");
Toshihiro Shimizu 890ddd
	aboutpage->addWidget(new QLabel(pi_->desc_->vendor_.c_str(), aboutpage));
Toshihiro Shimizu 890ddd
	aboutpage->endGroup();
Toshihiro Shimizu 890ddd
	aboutpage->beginGroup("Version");
Toshihiro Shimizu 890ddd
	auto version =
Toshihiro Shimizu 890ddd
		QString::fromStdString(std::to_string(pi_->desc_->plugin_ver_.major)) + "." +
Toshihiro Shimizu 890ddd
		QString::fromStdString(std::to_string(pi_->desc_->plugin_ver_.minor));
Toshihiro Shimizu 890ddd
	aboutpage->addWidget(new QLabel(version, aboutpage));
Toshihiro Shimizu 890ddd
	aboutpage->endGroup();
Toshihiro Shimizu 890ddd
	aboutpage->beginGroup("Note");
Toshihiro Shimizu 890ddd
	aboutpage->addWidget(new QLabel(pi_->desc_->note_.c_str()), aboutpage);
Toshihiro Shimizu 890ddd
	aboutpage->endGroup();
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
	pages->addParamsPage(aboutpage, "Version");
Toshihiro Shimizu 890ddd
	aboutpage->setPageSpace();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename compat_maj,="" compat_min="" t,="" uint32_t=""></typename>
Toshihiro Shimizu 890ddd
static inline bool is_compatible(const T &d)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return d.ver.major == compat_maj && d.ver.minor == compat_min;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <uint32_t compat_maj,="" compat_min="" uint32_t=""></uint32_t>
Toshihiro Shimizu 890ddd
static inline bool is_compatible(const toonz_if_version_t &v)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return v.major == compat_maj && v.minor == compat_min;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int check_base_sanity(const toonz_param_page_t *p)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int err = 0;
Toshihiro Shimizu 890ddd
	if (!is_compatible<toonz_param_base_t_, 0="" 1,="">(p->base))</toonz_param_base_t_,>
Toshihiro Shimizu 890ddd
		err |= TOONZ_PARAM_ERROR_VERSION;
Toshihiro Shimizu 890ddd
	if (p->base.label == NULL)
Toshihiro Shimizu 890ddd
		err |= TOONZ_PARAM_ERROR_LABEL;
Toshihiro Shimizu 890ddd
	if (p->base.type != TOONZ_PARAM_DESC_TYPE_PAGE)
Toshihiro Shimizu 890ddd
		err |= TOONZ_PARAM_ERROR_TYPE;
Toshihiro Shimizu 890ddd
	return err;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int check_base_sanity(const toonz_param_group_t *p)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int err = 0;
Toshihiro Shimizu 890ddd
	if (!is_compatible<toonz_param_base_t_, 0="" 1,="">(p->base))</toonz_param_base_t_,>
Toshihiro Shimizu 890ddd
		err |= TOONZ_PARAM_ERROR_VERSION;
Toshihiro Shimizu 890ddd
	if (p->base.label == NULL)
Toshihiro Shimizu 890ddd
		err |= TOONZ_PARAM_ERROR_LABEL;
Toshihiro Shimizu 890ddd
	if (p->base.type != TOONZ_PARAM_DESC_TYPE_GROUP)
Toshihiro Shimizu 890ddd
		err |= TOONZ_PARAM_ERROR_TYPE;
Toshihiro Shimizu 890ddd
	return err;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int check_base_sanity(const toonz_param_desc_t *p)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int err = 0;
Toshihiro Shimizu 890ddd
	if (!is_compatible<toonz_param_base_t_, 0="" 1,="">(p->base))</toonz_param_base_t_,>
Toshihiro Shimizu 890ddd
		err |= TOONZ_PARAM_ERROR_VERSION;
Toshihiro Shimizu 890ddd
	if (p->base.label == NULL)
Toshihiro Shimizu 890ddd
		err |= TOONZ_PARAM_ERROR_LABEL;
Toshihiro Shimizu 890ddd
	if (p->base.type != TOONZ_PARAM_DESC_TYPE_PARAM)
Toshihiro Shimizu 890ddd
		err |= TOONZ_PARAM_ERROR_TYPE;
Toshihiro Shimizu 890ddd
	return err;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool RasterFxPluginHost::setParamStructure(int n, toonz_param_page_t *p, int &err, void *&pos)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	/* 適当に現実的な最大値: あまりに大きい場合は領域の破壊を疑う */
Toshihiro Shimizu 890ddd
	static const int max_pages_ = 31;
Toshihiro Shimizu 890ddd
	static const int max_groups_ = 32;
Toshihiro Shimizu 890ddd
	static const int max_params_ = 65535;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	pos = p;
Toshihiro Shimizu 890ddd
	if (pi_) {
Toshihiro Shimizu 890ddd
		if (n > max_pages_ || p == NULL) {
Toshihiro Shimizu 890ddd
			/* parameter が null でないことは上位でチェックされているはずで、ここで返せるエラーは定義していない. */
Toshihiro Shimizu 890ddd
			if (p == NULL)
Toshihiro Shimizu 890ddd
				err |= TOONZ_PARAM_ERROR_UNKNOWN;
Toshihiro Shimizu 890ddd
			err |= TOONZ_PARAM_ERROR_PAGE_NUM;
Toshihiro Shimizu 890ddd
			return false;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		/* SAN 値チェック */
Toshihiro Shimizu 890ddd
		for (int k = 0; k < n; k++) {
Toshihiro Shimizu 890ddd
			toonz_param_page_t *pg = &p[k];
Toshihiro Shimizu 890ddd
			pos = pg;
Toshihiro Shimizu 890ddd
			if (int e = check_base_sanity(pg)) {
Toshihiro Shimizu 890ddd
				err = e;
Toshihiro Shimizu 890ddd
				return false;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			if (pg->num > max_groups_) {
Toshihiro Shimizu 890ddd
				err |= TOONZ_PARAM_ERROR_GROUP_NUM;
Toshihiro Shimizu 890ddd
				return false;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			for (int l = 0; l < pg->num; l++) {
Toshihiro Shimizu 890ddd
				toonz_param_group_t *grp = &pg->array[l];
Toshihiro Shimizu 890ddd
				pos = grp;
Toshihiro Shimizu 890ddd
				if (int e = check_base_sanity(grp)) {
Toshihiro Shimizu 890ddd
					err = e;
Toshihiro Shimizu 890ddd
					return false;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
				if (grp->num > max_params_) {
Toshihiro Shimizu 890ddd
					err |= TOONZ_PARAM_ERROR_GROUP_NUM;
Toshihiro Shimizu 890ddd
					return false;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
				for (int i = 0; i < grp->num; i++) {
Toshihiro Shimizu 890ddd
					toonz_param_desc_t *desc = &grp->array[i];
Toshihiro Shimizu 890ddd
					pos = desc;
Toshihiro Shimizu 890ddd
					if (int e = check_base_sanity(desc))
Toshihiro Shimizu 890ddd
						err |= e;
Toshihiro Shimizu 890ddd
					if (desc->key == NULL)
Toshihiro Shimizu 890ddd
						err |= TOONZ_PARAM_ERROR_NO_KEY;
Toshihiro Shimizu 890ddd
					else {
Toshihiro Shimizu 890ddd
						if (!validateKeyName(desc->key))
Toshihiro Shimizu 890ddd
							err |= TOONZ_PARAM_ERROR_KEY_NAME;
Shinya Kitaoka 0b19cb
						for (auto it : params_) {
Toshihiro Shimizu 890ddd
							if (it->name() == desc->key) {
Toshihiro Shimizu 890ddd
								err |= TOONZ_PARAM_ERROR_KEY_DUP;
Toshihiro Shimizu 890ddd
								break;
Toshihiro Shimizu 890ddd
							}
Toshihiro Shimizu 890ddd
						}
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
					if (desc->reserved_[0] || desc->reserved_[1]) // reserved fields must be zero
Toshihiro Shimizu 890ddd
						err |= TOONZ_PARAM_ERROR_POLLUTED;
Toshihiro Shimizu 890ddd
					err |= check_traits_sanity(desc);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					if (err)
Toshihiro Shimizu 890ddd
						return false;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (err)
Toshihiro Shimizu 890ddd
			return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// deep copy param resources
Toshihiro Shimizu 890ddd
		std::vector<std::shared_ptr<void>> ¶m_resources = pi_->param_resources_;</std::shared_ptr<void>
Toshihiro Shimizu 890ddd
		std::vector<std::shared_ptr<std::string>> &strtbl = pi_->param_string_tbl_;</std::shared_ptr<std::string>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		auto patch_string = [&](const char *srcstr) {
Toshihiro Shimizu 890ddd
			strtbl.push_back(std::shared_ptr<std::string>(new std::string("")));</std::string>
Toshihiro Shimizu 890ddd
			if (srcstr)
Toshihiro Shimizu 890ddd
				strtbl.back()->assign(srcstr);
Toshihiro Shimizu 890ddd
			return strtbl.back()->c_str();
Toshihiro Shimizu 890ddd
		};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		auto deep_copy_base = [&](toonz_param_base_t_ &dst, const toonz_param_base_t_ &src) {
Toshihiro Shimizu 890ddd
			dst.ver = src.ver;
Toshihiro Shimizu 890ddd
			dst.type = src.type;
Toshihiro Shimizu 890ddd
			dst.label = patch_string(src.label);
Toshihiro Shimizu 890ddd
		};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		param_resources.clear();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		toonz_param_page_t *origin_pages = new toonz_param_page_t[n];
Toshihiro Shimizu 890ddd
		for (int i = 0; i < n; i++) {
Toshihiro Shimizu 890ddd
			toonz_param_page_t &dst_page = origin_pages[i];
Toshihiro Shimizu 890ddd
			const toonz_param_page_t &src_page = p[i];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			deep_copy_base(dst_page.base, src_page.base);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			const int group_num = dst_page.num = src_page.num;
Toshihiro Shimizu 890ddd
			dst_page.array = new toonz_param_group_t[group_num];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			for (int j = 0; j < group_num; j++) {
Toshihiro Shimizu 890ddd
				toonz_param_group_t &dst_group = dst_page.array[j];
Toshihiro Shimizu 890ddd
				const toonz_param_group_t &src_group = src_page.array[j];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				deep_copy_base(dst_group.base, src_group.base);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				const int desc_num = dst_group.num = src_group.num;
Toshihiro Shimizu 890ddd
				dst_group.array = new toonz_param_desc_t[desc_num];
Toshihiro Shimizu 890ddd
				for (int k = 0; k < desc_num; k++) {
Toshihiro Shimizu 890ddd
					toonz_param_desc_t &dst_desc = dst_group.array[k];
Toshihiro Shimizu 890ddd
					const toonz_param_desc_t &src_desc = src_group.array[k];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					deep_copy_base(dst_desc.base, src_desc.base); // base
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					dst_desc.key = patch_string(src_desc.key);									// key
Toshihiro Shimizu 890ddd
					dst_desc.note = patch_string(src_desc.note);								// note
Toshihiro Shimizu 890ddd
					memcpy(dst_desc.reserved_, src_desc.reserved_, sizeof(src_desc.reserved_)); // reserved fields
Toshihiro Shimizu 890ddd
					dst_desc.traits_tag = src_desc.traits_tag;									// tag
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					// traits
Toshihiro Shimizu 890ddd
					if (dst_desc.traits_tag == TOONZ_PARAM_TYPE_ENUM) {
Toshihiro Shimizu 890ddd
						dst_desc.traits.e.def = src_desc.traits.e.def;
Toshihiro Shimizu 890ddd
						int enums = dst_desc.traits.e.enums = src_desc.traits.e.enums;
Toshihiro Shimizu 890ddd
						auto a = std::shared_ptr<void>(new char *[enums]);</void>
Toshihiro Shimizu 890ddd
						param_resources.push_back(a);
Toshihiro Shimizu 890ddd
						dst_desc.traits.e.array = static_cast<const **="" char="">(a.get());</const>
Toshihiro Shimizu 890ddd
						for (int i = 0; i < enums; i++)
Toshihiro Shimizu 890ddd
							dst_desc.traits.e.array[i] = patch_string(src_desc.traits.e.array[i]);
Toshihiro Shimizu 890ddd
					} else if (dst_desc.traits_tag == TOONZ_PARAM_TYPE_SPECTRUM) {
Toshihiro Shimizu 890ddd
						int points = dst_desc.traits.g.points = src_desc.traits.g.points;
Toshihiro Shimizu 890ddd
						auto ptr = std::shared_ptr<void>(new toonz_param_traits_spectrum_t::valuetype[points]);</void>
Toshihiro Shimizu 890ddd
						param_resources.push_back(ptr);
Toshihiro Shimizu 890ddd
						dst_desc.traits.g.array = static_cast<toonz_param_traits_spectrum_t::valuetype *="">(ptr.get());</toonz_param_traits_spectrum_t::valuetype>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						for (int i = 0; i < dst_desc.traits.g.points; i++)
Toshihiro Shimizu 890ddd
							memcpy(&dst_desc.traits.g.array[i], &src_desc.traits.g.array[i], sizeof(toonz_param_traits_spectrum_t::valuetype));
Toshihiro Shimizu 890ddd
					} else if (dst_desc.traits_tag == TOONZ_PARAM_TYPE_STRING) {
Toshihiro Shimizu 890ddd
						dst_desc.traits.s.def = patch_string(src_desc.traits.s.def);
Toshihiro Shimizu 890ddd
					} else if (dst_desc.traits_tag == TOONZ_PARAM_TYPE_TONECURVE) {
Toshihiro Shimizu 890ddd
						/* has no default values */
Toshihiro Shimizu 890ddd
					} else {
Toshihiro Shimizu 890ddd
						memcpy(&dst_desc.traits, &src_desc.traits, sizeof(src_desc.traits));
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		pi_->param_page_num_ = n;
Toshihiro Shimizu 890ddd
		pi_->param_pages_ = origin_pages;
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void RasterFxPluginHost::createParamsByDesc()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	printf("RasterFxPluginHost::createParamsByDesc: num:%d\n", pi_->param_page_num_);
Toshihiro Shimizu 890ddd
	for (int k = 0; k < pi_->param_page_num_; k++) {
Toshihiro Shimizu 890ddd
		toonz_param_page_t *pg = &pi_->param_pages_[k];
Toshihiro Shimizu 890ddd
		void *page = NULL;
Toshihiro Shimizu 890ddd
		int r = add_preference(this, pg->base.label, &page);
Toshihiro Shimizu 890ddd
		printf("RasterFxPluginHost::createParamsByDesc: add_preference: r:0x%x page:%p\n", r, page);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (int l = 0; l < pg->num; l++) {
Toshihiro Shimizu 890ddd
			toonz_param_group_t *grp = &pg->array[l];
Toshihiro Shimizu 890ddd
			begin_group(page, grp->base.label);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			for (int i = 0; i < grp->num; i++) {
Toshihiro Shimizu 890ddd
				toonz_param_desc_t *desc = &grp->array[i];
Toshihiro Shimizu 890ddd
				Param *p = createParam(desc);
Toshihiro Shimizu 890ddd
				printf("RasterFxPluginHost::createParam: p:%p key:%s tag:%d\n", p, desc->key, desc->traits_tag);
Toshihiro Shimizu 890ddd
				if (p) {
Toshihiro Shimizu 890ddd
					void *v = NULL;
Toshihiro Shimizu 890ddd
					int r = create_param_view(this, &v);
Toshihiro Shimizu 890ddd
					printf("RasterFxPluginHost::createParam: create_param_view: r:0x%x v:%p\n", r, v);
Toshihiro Shimizu 890ddd
					r = add_param_field(v, NULL);
Toshihiro Shimizu 890ddd
					printf("RasterFxPluginHost::createParam: add_param_field: r:0x%x v:%p p:%p\n", r, v, p);
Toshihiro Shimizu 890ddd
					/* set_param_range() の中で型チェックをしているので全型について呼び出してよい */
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					r = bind_param(page, p, v);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					set_param_default<tpbind_dbl_t>(p, desc);</tpbind_dbl_t>
Toshihiro Shimizu 890ddd
					set_param_default<tpbind_int_t>(p, desc);</tpbind_int_t>
Toshihiro Shimizu 890ddd
					set_param_default<tpbind_rng_t>(p, desc);</tpbind_rng_t>
Toshihiro Shimizu 890ddd
					set_param_default<tpbind_pnt_t>(p, desc);</tpbind_pnt_t>
Toshihiro Shimizu 890ddd
					set_param_default<tpbind_enm_t>(p, desc);</tpbind_enm_t>
Toshihiro Shimizu 890ddd
					set_param_default<tpbind_col_t>(p, desc);</tpbind_col_t>
Toshihiro Shimizu 890ddd
					set_param_default<tpbind_bool_t>(p, desc);</tpbind_bool_t>
Toshihiro Shimizu 890ddd
					set_param_default<tpbind_str_t>(p, desc);</tpbind_str_t>
Toshihiro Shimizu 890ddd
					set_param_default<tpbind_spc_t>(p, desc);</tpbind_spc_t>
Toshihiro Shimizu 890ddd
					set_param_default<tpbind_tcv_t>(p, desc);</tpbind_tcv_t>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					set_param_range<tpbind_dbl_t>(p, desc);</tpbind_dbl_t>
Toshihiro Shimizu 890ddd
					set_param_range<tpbind_int_t>(p, desc);</tpbind_int_t>
Toshihiro Shimizu 890ddd
					set_param_range<tpbind_rng_t>(p, desc);</tpbind_rng_t>
Toshihiro Shimizu 890ddd
					set_param_range<tpbind_pnt_t>(p, desc);</tpbind_pnt_t>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					printf("RasterFxPluginHost::createParam: bind_param: r:0x%x\n", r);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			end_group(page, grp->base.label);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
パラメタのキー名として適切か確認
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
bool RasterFxPluginHost::validateKeyName(const char *name)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (name[0] == '\0')
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	if (!isalpha(name[0]) && name[0] != '_')
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (int i = 1; name[i] != '\0'; i++)
Toshihiro Shimizu 890ddd
		if (!isalnum(name[i]) && name[i] != '_')
Toshihiro Shimizu 890ddd
			return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/* XMLの仕様ではXMLから始まるタグ名は認められないので、ここで弾く */
Toshihiro Shimizu 890ddd
	if (strlen(name) >= 3 &&
Toshihiro Shimizu 890ddd
		(name[0] == 'X' || name[0] == 'x') &&
Toshihiro Shimizu 890ddd
		(name[1] == 'M' || name[1] == 'm') &&
Toshihiro Shimizu 890ddd
		(name[2] == 'L' || name[2] == 'l'))
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
 strict sanity check:
Toshihiro Shimizu 890ddd
 未初期化値を受け入れて互換性が崩れないよう厳しくチェックする
Toshihiro Shimizu 890ddd
 */
Toshihiro Shimizu 890ddd
#define VERBOSE
Toshihiro Shimizu 890ddd
static inline bool check(const plugin_probe_t *begin, const plugin_probe_t *end)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	/*
Toshihiro Shimizu 890ddd
	printf("dump toonz_plugin_probe_t: ver:(%d, %d) (%s, %s, %s, %s) resv:[%p, %p, %p, %p, %p] clss:0x%x resv:[%d, %d, %d, %d, %d]\n",
Toshihiro Shimizu 890ddd
		   x->ver.major, x->ver.minor,
Toshihiro Shimizu 890ddd
		   x->name, x->id, x->note, x->url,
Toshihiro Shimizu 890ddd
		   x->reserved_ptr_[0], x->reserved_ptr_[1], x->reserved_ptr_[2], x->reserved_ptr_[3], x->reserved_ptr_[4],
Toshihiro Shimizu 890ddd
		   x->clss,
Toshihiro Shimizu 890ddd
		   x->reserved_int_[0], x->reserved_int_[1], x->reserved_int_[2], x->reserved_int_[3], x->reserved_int_[4], x->reserved_int_[5], x->reserved_int_[6], x->reserved_int_[7]);
Toshihiro Shimizu 890ddd
	*/
Toshihiro Shimizu 890ddd
	int idx = 0;
Toshihiro Shimizu 890ddd
	if (!is_compatible<plugin_probe_t, 0="" 1,="">(*begin)) {</plugin_probe_t,>
Toshihiro Shimizu 890ddd
#if defined(VERBOSE)
Toshihiro Shimizu 890ddd
		printf("sanity check(): first interface version is unknown\n", idx);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	toonz_if_version_t v = begin->ver;
Toshihiro Shimizu 890ddd
	for (auto x = begin; x < end; x++, idx++) {
Toshihiro Shimizu 890ddd
		/* 異なるバージョンの構造体の混在はエラーとする. 
Toshihiro Shimizu 890ddd
		   しかし toonz_plugin_probe_t は reservation filed を持っており、サイズが変わらない限りは混在も対応可能だが、まずは sanity check で落とす.
Toshihiro Shimizu 890ddd
		   
Toshihiro Shimizu 890ddd
		   For now we permit mixed versions. Not that we never support it since size of toonz_plugin_probe_t is constant.
Toshihiro Shimizu 890ddd
		*/
Toshihiro Shimizu 890ddd
		if (!(x->ver.major == v.major && x->ver.minor == v.minor)) {
Toshihiro Shimizu 890ddd
#if defined(VERBOSE)
Toshihiro Shimizu 890ddd
			printf("sanity check(): versions are ambiguous: first:(%d, %d) plugin[%d]:(%d, %d)\n", v.major, v.minor, idx, x->ver.major, x->ver.minor);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
			return false;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (!x->clss) {
Toshihiro Shimizu 890ddd
#if defined(VERBOSE)
Toshihiro Shimizu 890ddd
			printf("sanity check(): plugin[%d] class is zero\n", idx);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
			return false;
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			uint32_t m = x->clss & TOONZ_PLUGIN_CLASS_MODIFIER_MASK;
Toshihiro Shimizu 890ddd
			uint32_t c = x->clss & ~TOONZ_PLUGIN_CLASS_MODIFIER_MASK;
Toshihiro Shimizu 890ddd
			if (!(m == 0 || m == TOONZ_PLUGIN_CLASS_MODIFIER_GEOMETRIC)) {
Toshihiro Shimizu 890ddd
#if defined(VERBOSE)
Toshihiro Shimizu 890ddd
				printf("sanity check(): plugin[%d] unknown modifier: 0x%x\n", idx, m);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
				return false; // we don't know the modifier
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			if (!(c == TOONZ_PLUGIN_CLASS_POSTPROCESS_SLAB)) {
Toshihiro Shimizu 890ddd
#if defined(VERBOSE)
Toshihiro Shimizu 890ddd
				printf("sanity check(): plugin[%d] unknown class: 0x%x\n", idx, c);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
				return false; // we don't know the class
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// reservations are must be zero
Toshihiro Shimizu 890ddd
		for (int i = 0; i < 3; i++)
Toshihiro Shimizu 890ddd
			if (x->reserved_ptr_[i]) {
Toshihiro Shimizu 890ddd
#if defined(VERBOSE)
Toshihiro Shimizu 890ddd
				printf("sanity check(): plugin[%d] reserved_ptr_[%d] is NOT all zero-ed\n", idx, i);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
				return false;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		for (int i = 0; i < 7; i++)
Toshihiro Shimizu 890ddd
			if (x->reserved_int_[i]) {
Toshihiro Shimizu 890ddd
#if defined(VERBOSE)
Toshihiro Shimizu 890ddd
				printf("sanity check(): plugin[%d] reserved_int_[%d] is NOT all zero-ed\n", idx, i);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
				return false;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		for (int i = 0; i < 3; i++)
Toshihiro Shimizu 890ddd
			if (x->reserved_ptr_trail_[i]) {
Toshihiro Shimizu 890ddd
#if defined(VERBOSE)
Toshihiro Shimizu 890ddd
				printf("sanity check(): plugin[%d] reserved_ptr_trail_[%d] is NOT all zero-ed\n", idx, i);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
				return false;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (x->handler == NULL) {
Toshihiro Shimizu 890ddd
#if defined(VERBOSE)
Toshihiro Shimizu 890ddd
			printf("sanity check(): plugin[%d] handler is null\n", idx);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
			return false; // handler must be NOT null
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// check if the end is empty
Toshihiro Shimizu 890ddd
	const char *b = reinterpret_cast<const *="" char="">(end);</const>
Toshihiro Shimizu 890ddd
	for (int i = 0; i < sizeof(plugin_probe_t); i++) {
Toshihiro Shimizu 890ddd
		if (b[i] != 0) {
Toshihiro Shimizu 890ddd
#if defined(VERBOSE)
Toshihiro Shimizu 890ddd
			printf("sanity check(): empty is NOT all zero-ed\n");
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
			return false; // must be zero
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static inline bool check_and_copy(nodal_rasterfx_handler_t *__restrict dst, const nodal_rasterfx_handler_t *__restrict src)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// do we know the version?
Toshihiro Shimizu 890ddd
	if (!(src->ver.major == 1 && src->ver.minor == 0))
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	dst->ver = src->ver;
Toshihiro Shimizu 890ddd
	dst->do_compute = src->do_compute;
Toshihiro Shimizu 890ddd
	dst->do_get_bbox = src->do_get_bbox;
Toshihiro Shimizu 890ddd
	dst->can_handle = src->can_handle;
Toshihiro Shimizu 890ddd
	dst->get_memory_requirement = src->get_memory_requirement;
Toshihiro Shimizu 890ddd
	dst->on_new_frame = src->on_new_frame;
Toshihiro Shimizu 890ddd
	dst->on_end_frame = src->on_end_frame;
Toshihiro Shimizu 890ddd
	dst->create = src->create;
Toshihiro Shimizu 890ddd
	dst->destroy = src->destroy;
Toshihiro Shimizu 890ddd
	dst->setup = src->setup;
Toshihiro Shimizu 890ddd
	dst->start_render = src->start_render;
Toshihiro Shimizu 890ddd
	dst->end_render = src->end_render;
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static inline bool uuid_matches(const UUID *x, const UUID *y)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return x->uid0 == y->uid0 && x->uid1 == y->uid1 && x->uid2 == y->uid2 && x->uid3 == y->uid3 && x->uid4 == y->uid4;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static UUID uuid_nodal_ = {0xCC14EA21, 0x13D8, 0x4A3B, 0x9375, 0xAA4F68C9DDDD};
Toshihiro Shimizu 890ddd
static UUID uuid_port_ = {0x2F89A423, 0x1D2D, 0x433F, 0xB93E, 0xCFFD83745F6F};
Toshihiro Shimizu 890ddd
static UUID uuid_tile_ = {0x882BD525, 0x937E, 0x427C, 0x9D68, 0x4ECA651F6562};
Toshihiro Shimizu 890ddd
//static UUID uuid_ui_page_ = {0xD2EF0310, 0x3414, 0x4753, 0x84CA, 0xD5447C70DD89};
Toshihiro Shimizu 890ddd
static UUID uuid_fx_node_ = {0x26F9FC53, 0x632B, 0x422F, 0x87A0, 0x8A4547F55474};
Toshihiro Shimizu 890ddd
//static UUID uuid_param_view_ = {0x5133A63A, 0xDD92, 0x41BD, 0xA255, 0x6F97BE7292EA};
Toshihiro Shimizu 890ddd
static UUID uuid_param_ = {0x2E3E4A55, 0x8539, 0x4520, 0xA266, 0x15D32189EC4D};
Toshihiro Shimizu 890ddd
static UUID uuid_setup_ = {0xcfde9107, 0xc59d, 0x414c, 0xae4a, 0x3d115ba97933};
Toshihiro Shimizu 890ddd
static UUID uuid_null_ = {0, 0, 0, 0, 0};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename int="" major,="" minor="" t,=""></typename>
Toshihiro Shimizu 890ddd
T *base_interface_factory()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	T *t = new T;
Toshihiro Shimizu 890ddd
	memset(t, 0, sizeof(T));
Toshihiro Shimizu 890ddd
	t->ver.major = major;
Toshihiro Shimizu 890ddd
	t->ver.minor = minor;
Toshihiro Shimizu 890ddd
	return t;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename major,="" minor="" t,="" uint32_t=""></typename>
Toshihiro Shimizu 890ddd
struct interface_t {
Toshihiro Shimizu 890ddd
	static T *factory()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		T *t = base_interface_factory<t, major,="" minor="">();</t,>
Toshihiro Shimizu 890ddd
		return t;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
extern "C" {
Toshihiro Shimizu 890ddd
int set_parameter_pages(toonz_node_handle_t, int num, toonz_param_page_t *params);
Toshihiro Shimizu 890ddd
int set_parameter_pages_with_error(toonz_node_handle_t, int num, toonz_param_page_t *params, int *, void **);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <uint32_t major,="" minor="" uint32_t=""></uint32_t>
Toshihiro Shimizu 890ddd
struct interface_t<setup_interface_t, major,="" minor=""> {</setup_interface_t,>
Toshihiro Shimizu 890ddd
	static setup_interface_t *factory()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		setup_interface_t *t = base_interface_factory<setup_interface_t, major,="" minor="">();</setup_interface_t,>
Toshihiro Shimizu 890ddd
		t->set_parameter_pages = set_parameter_pages;
Toshihiro Shimizu 890ddd
		t->set_parameter_pages_with_error = set_parameter_pages_with_error;
Toshihiro Shimizu 890ddd
		t->add_input_port = setup_input_port;
Toshihiro Shimizu 890ddd
		return t;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
template < uint32_t major, uint32_t minor >
Toshihiro Shimizu 890ddd
struct interface_t < ui_page_interface_t, major, minor > {
Toshihiro Shimizu 890ddd
	static ui_page_interface_t* factory()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		ui_page_interface_t* t = base_interface_factory< ui_page_interface_t, major, minor >();
Toshihiro Shimizu 890ddd
		t->begin_group = begin_group;
Toshihiro Shimizu 890ddd
		t->end_group = end_group;
Toshihiro Shimizu 890ddd
		t->bind_param = bind_param;
Toshihiro Shimizu 890ddd
		return t;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template < uint32_t major, uint32_t minor >
Toshihiro Shimizu 890ddd
struct interface_t < param_view_interface_t, major, minor > {
Toshihiro Shimizu 890ddd
	static param_view_interface_t* factory()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		param_view_interface_t* t = base_interface_factory< param_view_interface_t, major, minor >();
Toshihiro Shimizu 890ddd
		t->add_param_field = add_param_field;
Toshihiro Shimizu 890ddd
		t->add_custom_field = add_custom_field;
Toshihiro Shimizu 890ddd
		t->add_lineedit = add_lineedit;
Toshihiro Shimizu 890ddd
		t->add_slider = add_slider;
Toshihiro Shimizu 890ddd
		t->add_spinbox = add_spinbox;
Toshihiro Shimizu 890ddd
		t->add_checkbox = add_checkbox;
Toshihiro Shimizu 890ddd
		t->add_radiobutton = add_radiobutton;
Toshihiro Shimizu 890ddd
		t->add_combobox = add_combobox;
Toshihiro Shimizu 890ddd
		return t;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <uint32_t major,="" minor="" uint32_t=""></uint32_t>
Toshihiro Shimizu 890ddd
struct interface_t<param_interface_t, major,="" minor=""> {</param_interface_t,>
Toshihiro Shimizu 890ddd
	static param_interface_t *factory()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		param_interface_t *t = base_interface_factory<param_interface_t, major,="" minor="">();</param_interface_t,>
Toshihiro Shimizu 890ddd
		t->get_type = get_type;
Toshihiro Shimizu 890ddd
		//t->hint_default_value = hint_default_value;
Toshihiro Shimizu 890ddd
		//t->hint_value_range = hint_value_range;
Toshihiro Shimizu 890ddd
		//t->hint_unit = hint_unit;
Toshihiro Shimizu 890ddd
		//t->hint_item = hint_item;
Toshihiro Shimizu 890ddd
		//t->get_value_type = get_value_type;
Toshihiro Shimizu 890ddd
		t->get_value = get_value;
Toshihiro Shimizu 890ddd
		//t->set_value = set_value;
Toshihiro Shimizu 890ddd
		t->get_string_value = get_string_value;
Toshihiro Shimizu 890ddd
		t->get_spectrum_value = get_spectrum_value;
Toshihiro Shimizu 890ddd
		return t;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <uint32_t major,="" minor="" uint32_t=""></uint32_t>
Toshihiro Shimizu 890ddd
struct interface_t<node_interface_t, major,="" minor=""> {</node_interface_t,>
Toshihiro Shimizu 890ddd
	static node_interface_t *factory()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		node_interface_t *t = base_interface_factory<node_interface_t, major,="" minor="">();</node_interface_t,>
Toshihiro Shimizu 890ddd
		//t->add_input_port = add_input_port;
Toshihiro Shimizu 890ddd
		//t->add_output_port = add_output_port;
Toshihiro Shimizu 890ddd
		t->get_input_port = get_input_port;
Toshihiro Shimizu 890ddd
		t->get_rect = get_rect;
Toshihiro Shimizu 890ddd
		t->set_rect = set_rect;
Toshihiro Shimizu 890ddd
		//t->add_preference = add_preference;
Toshihiro Shimizu 890ddd
		//t->add_param = add_param;
Toshihiro Shimizu 890ddd
		t->get_param = get_param;
Toshihiro Shimizu 890ddd
		//t->create_param_view = create_param_view;
Toshihiro Shimizu 890ddd
		t->set_user_data = set_user_data;
Toshihiro Shimizu 890ddd
		t->get_user_data = get_user_data;
Toshihiro Shimizu 890ddd
		return t;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <uint32_t major,="" minor="" uint32_t=""></uint32_t>
Toshihiro Shimizu 890ddd
struct interface_t<toonz_tile_interface_t, major,="" minor=""> {</toonz_tile_interface_t,>
Toshihiro Shimizu 890ddd
	static toonz_tile_interface_t *factory()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		toonz_tile_interface_t *t = base_interface_factory<toonz_tile_interface_t, major,="" minor="">();</toonz_tile_interface_t,>
Toshihiro Shimizu 890ddd
		t->get_raw_address_unsafe = tile_interface_get_raw_address_unsafe;
Toshihiro Shimizu 890ddd
		t->get_raw_stride = tile_interface_get_raw_stride;
Toshihiro Shimizu 890ddd
		t->get_element_type = tile_interface_get_element_type;
Toshihiro Shimizu 890ddd
		t->copy_rect = tile_interface_copy_rect;
Toshihiro Shimizu 890ddd
		t->create_from = tile_interface_create_from;
Toshihiro Shimizu 890ddd
		t->create = tile_interface_create;
Toshihiro Shimizu 890ddd
		t->destroy = tile_interface_destroy;
Toshihiro Shimizu 890ddd
		t->get_rectangle = tile_interface_get_rectangle;
Toshihiro Shimizu 890ddd
		t->safen = tile_interface_safen;
Toshihiro Shimizu 890ddd
		return t;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <uint32_t major,="" minor="" uint32_t=""></uint32_t>
Toshihiro Shimizu 890ddd
struct interface_t<port_interface_t, major,="" minor=""> {</port_interface_t,>
Toshihiro Shimizu 890ddd
	static port_interface_t *factory()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		port_interface_t *t = base_interface_factory<port_interface_t, major,="" minor="">();</port_interface_t,>
Toshihiro Shimizu 890ddd
		t->is_connected = is_connected;
Toshihiro Shimizu 890ddd
		t->get_fx = get_fx;
Toshihiro Shimizu 890ddd
		return t;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <uint32_t major,="" minor="" uint32_t=""></uint32_t>
Toshihiro Shimizu 890ddd
struct interface_t<fxnode_interface_t, major,="" minor=""> {</fxnode_interface_t,>
Toshihiro Shimizu 890ddd
	static fxnode_interface_t *factory()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		fxnode_interface_t *t = base_interface_factory<fxnode_interface_t, major,="" minor="">();</fxnode_interface_t,>
Toshihiro Shimizu 890ddd
		t->get_bbox = fxnode_get_bbox;
Toshihiro Shimizu 890ddd
		t->can_handle = fxnode_can_handle;
Toshihiro Shimizu 890ddd
		t->get_input_port_count = fxnode_get_input_port_count;
Toshihiro Shimizu 890ddd
		t->get_input_port = fxnode_get_input_port;
Toshihiro Shimizu 890ddd
		t->compute_to_tile = fxnode_compute_to_tile;
Toshihiro Shimizu 890ddd
		return t;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
template <>
Toshihiro Shimizu 890ddd
template < uint32_t major, uint32_t minor >
Toshihiro Shimizu 890ddd
struct interface_t< toonz_nodal_rasterfx_interface_t >::i_< major, minor > {
Toshihiro Shimizu 890ddd
	static toonz_nodal_rasterfx_interface_t* factory()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		printf("toonz_nodal_rasterfx_interface_t::factory\n");
Toshihiro Shimizu 890ddd
		toonz_nodal_rasterfx_interface_t* t = base_interface_factory< toonz_nodal_rasterfx_interface_t, major, minor >();
Toshihiro Shimizu 890ddd
		return t;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename major,="" minor="" t,="" uint32_t=""></typename>
Toshihiro Shimizu 890ddd
T *interface_factory()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//return interface_t< T >::i_< major, minor >().factory();
Toshihiro Shimizu 890ddd
	return interface_t<t, major,="" minor="">::factory();</t,>
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int query_interface(const UUID *uuid, void **interf)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	typedef std::pair<const *,="" int="" uuid=""> uuid_dict_t;</const>
Toshihiro Shimizu 890ddd
	static const uuid_dict_t dict[] = {
Toshihiro Shimizu 890ddd
		uuid_dict_t(&uuid_nodal_, 1),
Toshihiro Shimizu 890ddd
		uuid_dict_t(&uuid_port_, 2),
Toshihiro Shimizu 890ddd
		uuid_dict_t(&uuid_tile_, 3),
Toshihiro Shimizu 890ddd
		//uuid_dict_t(&uuid_ui_page_, 4),
Toshihiro Shimizu 890ddd
		uuid_dict_t(&uuid_fx_node_, 5),
Toshihiro Shimizu 890ddd
		//uuid_dict_t(&uuid_param_view_, 6),
Toshihiro Shimizu 890ddd
		uuid_dict_t(&uuid_param_, 7),
Toshihiro Shimizu 890ddd
		uuid_dict_t(&uuid_setup_, 8),
Toshihiro Shimizu 890ddd
		uuid_dict_t(&uuid_null_, 0)};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!(uuid && interf))
Toshihiro Shimizu 890ddd
		return TOONZ_ERROR_NULL;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		const uuid_dict_t *it = &dict[0];
Toshihiro Shimizu 890ddd
		while (it->first != &uuid_null_) {
Toshihiro Shimizu 890ddd
			if (uuid_matches(it->first, uuid)) {
Toshihiro Shimizu 890ddd
				switch (it->second) {
Toshihiro Shimizu 890ddd
				case 1:
Toshihiro Shimizu 890ddd
					*interf = interface_factory<toonz_node_interface_t, 0="" 1,="">();</toonz_node_interface_t,>
Toshihiro Shimizu 890ddd
					break;
Toshihiro Shimizu 890ddd
				case 2:
Toshihiro Shimizu 890ddd
					*interf = interface_factory<toonz_port_interface_t, 0="" 1,="">();</toonz_port_interface_t,>
Toshihiro Shimizu 890ddd
					break;
Toshihiro Shimizu 890ddd
				case 3:
Toshihiro Shimizu 890ddd
					*interf = interface_factory<toonz_tile_interface_t, 0="" 1,="">();</toonz_tile_interface_t,>
Toshihiro Shimizu 890ddd
					break;
Toshihiro Shimizu 890ddd
				//case 4:
Toshihiro Shimizu 890ddd
				//	*interf = interface_factory< toonz_ui_page_interface_t, 1, 0 >();
Toshihiro Shimizu 890ddd
				//	break;
Toshihiro Shimizu 890ddd
				case 5:
Toshihiro Shimizu 890ddd
					*interf = interface_factory<toonz_fxnode_interface_t, 0="" 1,="">();</toonz_fxnode_interface_t,>
Toshihiro Shimizu 890ddd
					break;
Toshihiro Shimizu 890ddd
				//case 6:
Toshihiro Shimizu 890ddd
				//*interf = interface_factory< toonz_param_view_interface_t, 1, 0 >();
Toshihiro Shimizu 890ddd
				//break;
Toshihiro Shimizu 890ddd
				case 7:
Toshihiro Shimizu 890ddd
					*interf = interface_factory<toonz_param_interface_t, 0="" 1,="">();</toonz_param_interface_t,>
Toshihiro Shimizu 890ddd
					break;
Toshihiro Shimizu 890ddd
				case 8:
Toshihiro Shimizu 890ddd
					*interf = interface_factory<toonz_setup_interface_t, 0="" 1,="">();</toonz_setup_interface_t,>
Toshihiro Shimizu 890ddd
					break;
Toshihiro Shimizu 890ddd
				default:
Toshihiro Shimizu 890ddd
					return TOONZ_ERROR_NOT_IMPLEMENTED;
Toshihiro Shimizu 890ddd
					break;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			it++;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} catch (const std::bad_alloc &) {
Toshihiro Shimizu 890ddd
		return TOONZ_ERROR_OUT_OF_MEMORY;
Toshihiro Shimizu 890ddd
	} catch (const std::exception &) {
Toshihiro Shimizu 890ddd
		return TOONZ_ERROR_UNKNOWN;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return TOONZ_OK;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void release_interface(void *interf)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (interf)
Toshihiro Shimizu 890ddd
		delete interf;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Loader::Loader()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void Loader::walkDirectory(const QString &path)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	walkDirectory_(path);
Toshihiro Shimizu 890ddd
	emit fixup();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void Loader::walkDictionary(const QString &path)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	/* only for emitting a signal for fixup */
Toshihiro Shimizu 890ddd
	printf("walkDictionary: %s [dry]\n", path.toLocal8Bit().data());
Toshihiro Shimizu 890ddd
	emit fixup();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void Loader::walkDirectory_(const QString &path)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	printf("walkDirectory_: %s\n", path.toLocal8Bit().data());
Toshihiro Shimizu 890ddd
	QDir dir(path, QString::fromStdString("*.plugin"), QDir::Name, QDir::AllDirs | QDir::Files | QDir::NoDot | QDir::NoDotDot);
Toshihiro Shimizu 890ddd
	auto lst = dir.entryInfoList();
Toshihiro Shimizu 890ddd
	for (auto &e : lst) {
Toshihiro Shimizu 890ddd
		if (e.isDir()) {
Toshihiro Shimizu 890ddd
			walkDirectory_(e.filePath());
Toshihiro Shimizu 890ddd
		} else if (e.isFile()) { // file or symlink-to-file
Toshihiro Shimizu 890ddd
			doLoad(e.filePath());
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if defined(_WIN32) || defined(_CYGWIN_)
Toshihiro Shimizu 890ddd
void end_library(HMODULE mod)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	FreeLibrary(mod);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
void end_library(void *mod)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	dlclose(mod);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void Loader::doLoad(const QString &file)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
#if defined(_WIN32) || defined(_CYGWIN_)
Toshihiro Shimizu 890ddd
	HMODULE handle = LoadLibraryA(file.toLocal8Bit().data());
Toshihiro Shimizu 890ddd
	printf("doLoad handle:%p path:%s\n", handle, file.toLocal8Bit().data());
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
	void *handle = dlopen(file.toUtf8().data(), RTLD_LOCAL);
Toshihiro Shimizu 890ddd
	printf("doLoad handle:%p path:%s\n", handle, file.toUtf8().data());
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
	PluginInformation *pi = new PluginInformation;
Toshihiro Shimizu 890ddd
	if (handle) {
Toshihiro Shimizu 890ddd
		pi->library_ = library_t(handle, end_library); // shared_ptr
Toshihiro Shimizu 890ddd
													   /*
Toshihiro Shimizu 890ddd
		  probe に使う plugin 情報を探す.
Toshihiro Shimizu 890ddd
		  テーブルを export したほうが楽だが、開発者はデバッグしにくいので関数フォームも提供する.
Toshihiro Shimizu 890ddd
		  toonz_plugin_info で検索し、なければ toonz_plugin_probe() を呼び出す.
Toshihiro Shimizu 890ddd
		*/
Toshihiro Shimizu 890ddd
#if defined(_WIN32) || defined(_CYGWIN_)
Toshihiro Shimizu 890ddd
		auto ini = (int (*)(host_interface_t *))GetProcAddress(handle, "toonz_plugin_init");
Toshihiro Shimizu 890ddd
		auto fin = (void (*)(void))GetProcAddress(handle, "toonz_plugin_exit"); // optional
Toshihiro Shimizu 890ddd
		const plugin_probe_list_t *problist = reinterpret_cast<const *="" plugin_probe_list_t="">(GetProcAddress(handle, "toonz_plugin_info_list"));</const>
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
		auto ini = (int (*)(host_interface_t *))dlsym(handle, "toonz_plugin_init");
Toshihiro Shimizu 890ddd
		auto fin = (void (*)(void))dlsym(handle, "toonz_plugin_exit"); // optional
Toshihiro Shimizu 890ddd
		const plugin_probe_list_t *problist = reinterpret_cast<const *="" plugin_probe_list_t="">(dlsym(handle, "toonz_plugin_info_list"));</const>
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
		pi->ini_ = ini;
Toshihiro Shimizu 890ddd
		pi->fin_ = fin;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		const plugin_probe_t *probinfo_begin = NULL;
Toshihiro Shimizu 890ddd
		const plugin_probe_t *probinfo_end = NULL;
Toshihiro Shimizu 890ddd
		try {
Toshihiro Shimizu 890ddd
			if (problist) {
Toshihiro Shimizu 890ddd
				if (!is_compatible<plugin_probe_list_t, 0="" 1,="">(*problist))</plugin_probe_list_t,>
Toshihiro Shimizu 890ddd
					throw std::domain_error("invaid toonz_plugin_info_list: version unmatched");
Toshihiro Shimizu 890ddd
				probinfo_begin = problist->begin;
Toshihiro Shimizu 890ddd
				probinfo_end = problist->end;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (!probinfo_begin || !probinfo_end) {
Toshihiro Shimizu 890ddd
				printf("use function-formed prober:toonz_plugin_probe\n");
Toshihiro Shimizu 890ddd
// look at function-formed
Toshihiro Shimizu 890ddd
#if defined(_WIN32) || defined(_CYGWIN_)
Toshihiro Shimizu 890ddd
				void *probe = GetProcAddress(handle, "toonz_plugin_probe");
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
				void *probe = dlsym(handle, "toonz_plugin_probe");
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
				if (probe) {
Toshihiro Shimizu 890ddd
					printf("function-formed prober found\n");
Toshihiro Shimizu 890ddd
					const plugin_probe_list_t *lst = (reinterpret_cast<const *(*)(void)="" plugin_probe_list_t="">(probe))();</const>
Toshihiro Shimizu 890ddd
					if (!lst || !is_compatible<plugin_probe_list_t, 0="" 1,="">(*lst))</plugin_probe_list_t,>
Toshihiro Shimizu 890ddd
						throw std::domain_error("invalid plugin list");
Toshihiro Shimizu 890ddd
					plugin_probe_t *begin = lst->begin;
Toshihiro Shimizu 890ddd
					plugin_probe_t *end = lst->end;
Toshihiro Shimizu 890ddd
					if (!begin || !end)
Toshihiro Shimizu 890ddd
						throw std::domain_error("invalid plugin information address (begin or end is null)");
Toshihiro Shimizu 890ddd
					else if (begin >= end)
Toshihiro Shimizu 890ddd
						throw std::domain_error("invalid plugin information address (begin >= end)");
Toshihiro Shimizu 890ddd
					else if (begin == end - 1)
Toshihiro Shimizu 890ddd
						throw std::domain_error("invalid plugin information address (information is empty)");
Toshihiro Shimizu 890ddd
					probinfo_begin = begin;
Toshihiro Shimizu 890ddd
					probinfo_end = end;
Toshihiro Shimizu 890ddd
				} else {
Toshihiro Shimizu 890ddd
					throw std::domain_error("found toonz_plugin_probe nor toonz_plugin_info");
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			int plugin_num = probinfo_end - probinfo_begin;
Toshihiro Shimizu 890ddd
			printf("plugin count:%d begin:%p end:%p\n", plugin_num, probinfo_begin, probinfo_end);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			/* sanity check に失敗した場合は予期せぬアドレスを参照して toonz 本体ごと落ちる可能性があるので
Toshihiro Shimizu 890ddd
			   致命的エラー扱いで早期に抜ける. */
Toshihiro Shimizu 890ddd
			if (!probinfo_begin || !probinfo_end || !check(probinfo_begin, probinfo_end))
Toshihiro Shimizu 890ddd
				throw std::domain_error("ill-formed plugin information");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			for (const plugin_probe_t *probinfo = probinfo_begin; probinfo < probinfo_end; probinfo++) {
Toshihiro Shimizu 890ddd
				pi->desc_ = new PluginDescription(probinfo);
Toshihiro Shimizu 890ddd
				nodal_rasterfx_handler_t *nodal = probinfo->handler;
Toshihiro Shimizu 890ddd
				/* probinfo は sanity check 通過済みなのでチェック不要. handler は null でないことのみが確認されている */
Toshihiro Shimizu 890ddd
				if (is_compatible<nodal_rasterfx_handler_t, 0="" 1,="">(*nodal)) {</nodal_rasterfx_handler_t,>
Toshihiro Shimizu 890ddd
					uint32_t c = probinfo->clss & ~(TOONZ_PLUGIN_CLASS_MODIFIER_MASK);
Toshihiro Shimizu 890ddd
					uint32_t m = probinfo->clss & (TOONZ_PLUGIN_CLASS_MODIFIER_MASK);
Toshihiro Shimizu 890ddd
					if (c == TOONZ_PLUGIN_CLASS_POSTPROCESS_SLAB) {
Toshihiro Shimizu 890ddd
						pi->handler_ = new nodal_rasterfx_handler_t;
Toshihiro Shimizu 890ddd
						if (!check_and_copy(pi->handler_, nodal))
Toshihiro Shimizu 890ddd
							throw std::domain_error("ill-formed nodal interface");
Toshihiro Shimizu 890ddd
					} else {
Toshihiro Shimizu 890ddd
						// unknown plugin-class : gracefully end
Toshihiro Shimizu 890ddd
						/* sanity check しているので来ないはずだ */
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
				} else {
Toshihiro Shimizu 890ddd
					// unknown version : gracefully end
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				emit load_finished(pi);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if (pi) {
Toshihiro Shimizu 890ddd
					try {
Toshihiro Shimizu 890ddd
						if (pi->ini_) {
Toshihiro Shimizu 890ddd
							/* interface は plugin 内部で破壊されても他に影響させないため plugin instance ごとに割り当てる.  */
Toshihiro Shimizu 890ddd
							host_interface_t *host = new host_interface_t;
Toshihiro Shimizu 890ddd
							host->ver.major = 1;
Toshihiro Shimizu 890ddd
							host->ver.minor = 0;
Toshihiro Shimizu 890ddd
							host->query_interface = query_interface;
Toshihiro Shimizu 890ddd
							host->release_interface = release_interface;
Toshihiro Shimizu 890ddd
							int ret = pi->ini_(host);
Toshihiro Shimizu 890ddd
							if (ret) {
Toshihiro Shimizu 890ddd
								delete host;
Toshihiro Shimizu 890ddd
								std::domain_error("failed initialized: error on _toonz_plugin_init");
Toshihiro Shimizu 890ddd
							}
Toshihiro Shimizu 890ddd
							pi->host_ = host;
Toshihiro Shimizu 890ddd
							pi->decl_ = new PluginDeclaration(pi);
Toshihiro Shimizu 890ddd
						} else {
Toshihiro Shimizu 890ddd
							/* もっと早期にエラーを出して終了することもできるが
Toshihiro Shimizu 890ddd
							   センシティブすぎると見通しが立てにくいのである程度我慢してから出す */
Toshihiro Shimizu 890ddd
							throw std::domain_error("not found _toonz_plugin_init");
Toshihiro Shimizu 890ddd
						}
Toshihiro Shimizu 890ddd
					} catch (const std::exception &e) {
Toshihiro Shimizu 890ddd
						printf("Exception occured after plugin loading: %s\n", e.what());
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					if (pi->handler_ && pi->handler_->setup) {
Toshihiro Shimizu 890ddd
						PluginSetupMessage(pi).sendBlocking();
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					if (probinfo + 1 < probinfo_end) {
Toshihiro Shimizu 890ddd
						/* for a next plugin on the library */
Toshihiro Shimizu 890ddd
						auto prev = pi->library_;
Toshihiro Shimizu 890ddd
						pi = new PluginInformation;
Toshihiro Shimizu 890ddd
						/* instance に依存しない unique なリソースは引き継ぐ必要がある */
Toshihiro Shimizu 890ddd
						pi->library_ = prev;
Toshihiro Shimizu 890ddd
						pi->ini_ = ini;
Toshihiro Shimizu 890ddd
						pi->fin_ = fin;
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		} catch (const std::exception &e) {
Toshihiro Shimizu 890ddd
			printf("Exception occured while plugin loading: %s\n", e.what());
Toshihiro Shimizu 890ddd
			delete pi;
Toshihiro Shimizu 890ddd
			pi = NULL;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void RasterFxPluginHost::createPortsByDesc()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (pi_) {
Toshihiro Shimizu 890ddd
		for (auto pm : pi_->port_mapper_) {
Toshihiro Shimizu 890ddd
			/* TRasterFxPort は non-copyable なスマートポインタなのでポインタで引き回す */
Toshihiro Shimizu 890ddd
			printf("createPortsByDesc: name:%s dir:%d type:%d\n", pm.first.c_str(), pm.second.input_, pm.second.type_);
Toshihiro Shimizu 890ddd
			if (pm.second.input_) {
Toshihiro Shimizu 890ddd
				auto p = std::make_shared<trasterfxport>();</trasterfxport>
Toshihiro Shimizu 890ddd
				if (!addInputPort(pm.first, p)) { // overloaded version
Toshihiro Shimizu 890ddd
					printf("createPortsByDesc: failed to add: already have\n");
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				auto p = new TRasterFxPort();
Toshihiro Shimizu 890ddd
				/* TRasterFxPort は non-copyable なスマートポインタなのでポインタで引き回す */
Toshihiro Shimizu 890ddd
				if (addOutputPort(pm.first, p)) { // overloaded version
Toshihiro Shimizu 890ddd
					delete p;
Toshihiro Shimizu 890ddd
					printf("createPortsByDesc: failed to add: already have\n");
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
 TODO: addfxcontextmenu に移したほうがいい
Toshihiro Shimizu 890ddd
 */
Toshihiro Shimizu 890ddd
PluginLoadController::PluginLoadController(const std::string &basedir, QObject *listener)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	Loader *ld = new Loader;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ld->moveToThread(&work_entity);
Toshihiro Shimizu 890ddd
	connect(&work_entity, &QThread::finished, ld, &QObject::deleteLater);
Toshihiro Shimizu 890ddd
	/* AddFxContextMenu から呼ばれていたが、プラグインの検索が load_entries() を通じて起動時に呼ばれるようにした関係で,
Toshihiro Shimizu 890ddd
	   (あまりよくはないが)listner の有無によって receiver を分けるようにしている.
Toshihiro Shimizu 890ddd
	   listener がいる場合は従来通り context menu の構築のために AddFxContextMenu::fixup() に接続するが 
Toshihiro Shimizu 890ddd
	   それ以外では plugin_dict_ への追加のため PluginLoadController::finished に接続する.
Toshihiro Shimizu 890ddd
	*/
Toshihiro Shimizu 890ddd
	if (listener) {
Toshihiro Shimizu 890ddd
		AddFxContextMenu *a = qobject_cast<addfxcontextmenu *="">(listener);</addfxcontextmenu>
Toshihiro Shimizu 890ddd
		connect(ld, &Loader::fixup, a, &AddFxContextMenu::fixup);
Toshihiro Shimizu 890ddd
		connect(this, &PluginLoadController::start, ld, &Loader::walkDictionary);
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		connect(this, &PluginLoadController::start, ld, &Loader::walkDirectory);
Toshihiro Shimizu 890ddd
		connect(ld, &Loader::load_finished, this, &PluginLoadController::result);
Toshihiro Shimizu 890ddd
		if (!connect(ld, &Loader::fixup, this, &PluginLoadController::finished))
Toshihiro Shimizu 890ddd
			assert(false);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	work_entity.start();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QString pluginbase = (TEnv::getStuffDir() + "plugins").getQString();
Toshihiro Shimizu 890ddd
	printf("plugin search directory:%s\n", pluginbase.toLocal8Bit().data());
Toshihiro Shimizu 890ddd
	emit start(pluginbase);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PluginLoadController::finished()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	printf("===== PluginLoadController::finished() =====\n");
Toshihiro Shimizu 890ddd
	work_entity.exit();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PluginLoadController::result(PluginInformation *pi)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	/* slot receives PluginInformation on the main thread たぶん */
Toshihiro Shimizu 890ddd
	printf("PluginLoadController::result() pi:%p\n", pi);
Toshihiro Shimizu 890ddd
	if (pi) {
Toshihiro Shimizu 890ddd
		/* addfxcontextmenu.cpp の dict に登録する */
Toshihiro Shimizu 890ddd
		plugin_dict_.insert(std::pair<std::string, *="" plugininformation="">(pi->desc_->id_, pi));</std::string,>
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static bool copy_rendering_setting(toonz_rendering_setting_t *dst, const TRenderSettings &src)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	plugin::utils::copy_affine(&dst->affine, src.m_affine);
Toshihiro Shimizu 890ddd
	dst->gamma = src.m_gamma;
Toshihiro Shimizu 890ddd
	dst->time_stretch_from = src.m_timeStretchFrom;
Toshihiro Shimizu 890ddd
	dst->time_stretch_to = src.m_timeStretchTo;
Toshihiro Shimizu 890ddd
	dst->stereo_scopic_shift = src.m_stereoscopicShift;
Toshihiro Shimizu 890ddd
	dst->bpp = src.m_bpp;
Toshihiro Shimizu 890ddd
	dst->max_tile_size = src.m_maxTileSize;
Toshihiro Shimizu 890ddd
	dst->quality = src.m_quality;
Toshihiro Shimizu 890ddd
	dst->field_prevalence = src.m_fieldPrevalence;
Toshihiro Shimizu 890ddd
	dst->stereoscopic = src.m_stereoscopic;
Toshihiro Shimizu 890ddd
	dst->is_swatch = src.m_isSwatch;
Toshihiro Shimizu 890ddd
	dst->user_cachable = src.m_userCachable;
Toshihiro Shimizu 890ddd
	dst->apply_shrink_to_viewer = src.m_applyShrinkToViewer;
Toshihiro Shimizu 890ddd
	dst->context = &src;
Toshihiro Shimizu 890ddd
	dst->is_canceled = src.m_isCanceled;
Toshihiro Shimizu 890ddd
	plugin::utils::copy_rect(&dst->camera_box, src.m_cameraBox);
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//#include "pluginhost.moc"