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