| #include <stdio.h> |
| #include <toonz_plugin.h> |
| #include <toonz_hostif.h> |
| #include <memory> |
| #include <cmath> |
| #include <vector> |
| #include "pixelop.hpp" |
| |
| #include <utils/rect.hpp> |
| #include <utils/interf_holder.hpp> |
| #include <utils/param_traits.hpp> |
| |
| #ifdef _MSC_VER |
| |
| #define RESTRICT |
| #else |
| #define RESTRICT __restrict |
| #endif |
| |
| extern "C" { |
| TOONZ_EXPORT int toonz_plugin_init(toonz::host_interface_t *hostif); |
| TOONZ_EXPORT void toonz_plugin_exit(); |
| } |
| |
| toonz::host_interface_t *ifactory_ = NULL; |
| |
| int toonz_plugin_init(toonz::host_interface_t *hostif) |
| { |
| printf("toonz_plugin_init()\n"); |
| ifactory_ = hostif; |
| return TOONZ_OK; |
| } |
| |
| void toonz_plugin_exit() |
| { |
| printf("toonz_plugin_exit()\n"); |
| } |
| |
| ToonzRect conv2rect(toonz::rect_t &&r) |
| { |
| return ToonzRect(r.x0, r.y0, r.x1, r.y1); |
| } |
| |
| toonz::rect_t conv2rect(ToonzRect &&r) |
| { |
| return toonz::rect_t{r.x0, r.y0, r.x1, r.y1}; |
| } |
| |
| ToonzRect conv2rect(const toonz::rect_t &r) |
| { |
| return ToonzRect(r.x0, r.y0, r.x1, r.y1); |
| } |
| |
| toonz::rect_t conv2rect(const ToonzRect &r) |
| { |
| return toonz::rect_t{r.x0, r.y0, r.x1, r.y1}; |
| } |
| |
| template <typename T> |
| void dump_value(const T &v) |
| { |
| printf("value: type:%s {%d}\n", typeid(T).name(), v); |
| } |
| |
| template <> |
| void dump_value<toonz_param_traits_double_t::iovaluetype>(const toonz_param_traits_double_t::iovaluetype &v) |
| { |
| printf("value: type:%s {%g}\n", typeid(toonz_param_traits_double_t::iovaluetype).name(), v); |
| } |
| |
| template <> |
| void dump_value<toonz_param_traits_range_t::iovaluetype>(const toonz_param_traits_range_t::iovaluetype &v) |
| { |
| printf("value: type:%s {%g, %g}\n", typeid(toonz_param_traits_range_t::iovaluetype).name(), v.a, v.b); |
| } |
| |
| template <> |
| void dump_value<toonz_param_traits_point_t::iovaluetype>(const toonz_param_traits_point_t::iovaluetype &v) |
| { |
| printf("value: type:%s {%g, %g}\n", typeid(toonz_param_traits_point_t::iovaluetype).name(), v.x, v.y); |
| } |
| |
| template <> |
| void dump_value<toonz_param_traits_color_t::iovaluetype>(const toonz_param_traits_color_t::iovaluetype &v) |
| { |
| printf("value: type:%s {%d, %d, %d, %d}\n", typeid(toonz_param_traits_color_t::iovaluetype).name(), v.c0, v.c1, v.c2, v.m); |
| } |
| |
| template <> |
| void dump_value<toonz_param_traits_spectrum_t::iovaluetype>(const toonz_param_traits_spectrum_t::iovaluetype &v) |
| { |
| printf("value: type:%s {%g, %g, %g, %g, %g}\n", typeid(toonz_param_traits_spectrum_t::iovaluetype).name(), v.w, v.c0, v.c1, v.c2, v.m); |
| } |
| |
| template <> |
| void dump_value<toonz_param_traits_tonecurve_t::iovaluetype>(const toonz_param_traits_tonecurve_t::iovaluetype &v) |
| { |
| printf("value: type:%s {%g, %g, %d, %d}\n", typeid(toonz_param_traits_tonecurve_t::iovaluetype).name(), v.x, v.y, v.channel, v.interp); |
| } |
| |
| template <typename T> |
| bool get_and_check(toonz::node_handle_t node, const char *nm, double frame, double opt = 0) |
| { |
| auto nodeif = grab_interf<toonz::node_interface_t>(TOONZ_UUID_NODE); |
| auto pif = grab_interf<toonz::param_interface_t>(TOONZ_UUID_PARAM); |
| toonz_param_handle_t p1; |
| int ret; |
| ret = nodeif->get_param(node, nm, &p1); |
| printf("get_param(%s): ret:%d\n", nm, ret); |
| |
| int type = 0; |
| int cnt = 0; |
| pif->get_type(p1, frame, &type, &cnt); |
| printf("parameter(ret:%d): name:%s (type:%d count:%d) expect:(type:%d) typesize:%ld\n", ret, nm, type, cnt, T::E, sizeof(typename T::iovaluetype)); |
| if (type != T::E) |
| return false; |
| |
| typename T::iovaluetype v; |
| ret = pif->get_value(p1, frame, &cnt, &v); |
| printf("get_value: ret:%d count:%d\n", ret, cnt); |
| dump_value<typename T::iovaluetype>(v); |
| return true; |
| } |
| |
| template <> |
| bool get_and_check<toonz_param_traits_string_t>(toonz::node_handle_t node, const char *nm, double frame, double opt) |
| { |
| auto nodeif = grab_interf<toonz::node_interface_t>(TOONZ_UUID_NODE); |
| auto pif = grab_interf<toonz::param_interface_t>(TOONZ_UUID_PARAM); |
| toonz_param_handle_t p1; |
| int ret; |
| ret = nodeif->get_param(node, nm, &p1); |
| printf("get_param(%s): ret:%d\n", nm, ret); |
| |
| int type = 0; |
| int cnt = 0; |
| ret = pif->get_type(p1, frame, &type, &cnt); |
| printf("parameter(ret:%d): name:%s (type:%d count:%d) expect:(type:%d) typesize:-\n", ret, nm, type, cnt, toonz_param_traits_string_t::E); |
| if (type != toonz_param_traits_string_t::E) |
| return false; |
| |
| std::vector<toonz_param_traits_string_t::iovaluetype> v(cnt); |
| ret = pif->get_value(p1, frame, &cnt, v.data()); |
| printf("get_value: ret:%d count:%d\n", ret, cnt); |
| |
| printf("value: type:%s {%s}\n", typeid(toonz_param_traits_string_t::iovaluetype).name(), v.begin()); |
| return true; |
| } |
| |
| template <> |
| bool get_and_check<toonz_param_traits_spectrum_t>(toonz::node_handle_t node, const char *nm, double frame, double opt) |
| { |
| auto nodeif = grab_interf<toonz::node_interface_t>(TOONZ_UUID_NODE); |
| auto pif = grab_interf<toonz::param_interface_t>(TOONZ_UUID_PARAM); |
| toonz_param_handle_t p1; |
| int ret; |
| ret = nodeif->get_param(node, nm, &p1); |
| printf("get_param(%s): ret:%d\n", nm, ret); |
| int type = 0; |
| int cnt = 0; |
| ret = pif->get_type(p1, frame, &type, &cnt); |
| printf("parameter(ret:%d): name:%s (type:%d count:%d) expect:(type:%d) typesize:-\n", ret, nm, type, cnt, toonz_param_traits_spectrum_t::E); |
| if (type != toonz_param_traits_spectrum_t::E) |
| return false; |
| |
| toonz_param_traits_spectrum_t::iovaluetype v; |
| v.w = opt; |
| ret = pif->get_value(p1, frame, &cnt, &v); |
| printf("get_value: ret:%d count:%d\n", ret, cnt); |
| dump_value<toonz_param_traits_spectrum_t::iovaluetype>(v); |
| return true; |
| } |
| |
| template <> |
| bool get_and_check<toonz_param_traits_tonecurve_t>(toonz::node_handle_t node, const char *nm, double frame, double opt) |
| { |
| auto nodeif = grab_interf<toonz::node_interface_t>(TOONZ_UUID_NODE); |
| auto pif = grab_interf<toonz::param_interface_t>(TOONZ_UUID_PARAM); |
| toonz_param_handle_t p1; |
| int ret; |
| ret = nodeif->get_param(node, nm, &p1); |
| printf("get_param(%s): ret:%d\n", nm, ret); |
| |
| int type = 0; |
| int cnt = 0; |
| ret = pif->get_type(p1, frame, &type, &cnt); |
| printf("parameter)(ret:%d): name:%s (type:%d count:%d) expect:(type:%d) sz:-\n", ret, nm, type, cnt, toonz_param_traits_tonecurve_t::E); |
| if (type != toonz_param_traits_tonecurve_t::E) |
| return false; |
| |
| std::vector<toonz_param_traits_tonecurve_t::iovaluetype> v(cnt); |
| ret = pif->get_value(p1, frame, &cnt, v.data()); |
| printf("get_value: ret:%d count:%d\n", ret, cnt); |
| for (int i = 0; i < cnt; i++) { |
| dump_value<toonz_param_traits_tonecurve_t::iovaluetype>(v[i]); |
| } |
| return true; |
| } |
| |
| void do_compute(toonz::node_handle_t node, const toonz::rendering_setting_t *rs, double frame, toonz::tile_handle_t tile) |
| { |
| printf("do_compute(): node:%p tile:%p frame:%g\n", node, tile, frame); |
| |
| toonz::port_handle_t port = nullptr; |
| { |
| auto nodeif = grab_interf<toonz::node_interface_t>(TOONZ_UUID_NODE); |
| if (nodeif) { |
| int ret = nodeif->get_input_port(node, "IPort", &port); |
| if (ret) |
| printf("do_compute(): get_input_port: ret:%d\n", ret); |
| |
| |
| get_and_check<toonz_param_traits_double_t>(node, "first", frame); |
| get_and_check<toonz_param_traits_range_t>(node, "second", frame); |
| get_and_check<toonz_param_traits_color_t>(node, "third", frame); |
| get_and_check<toonz_param_traits_point_t>(node, "fourth", frame); |
| get_and_check<toonz_param_traits_enum_t>(node, "fifth", frame); |
| get_and_check<toonz_param_traits_int_t>(node, "sixth", frame); |
| get_and_check<toonz_param_traits_bool_t>(node, "seventh", frame); |
| get_and_check<toonz_param_traits_string_t>(node, "eighth", frame); |
| get_and_check<toonz_param_traits_spectrum_t>(node, "ninth", frame, 0.5); |
| get_and_check<toonz_param_traits_tonecurve_t>(node, "tenth", frame); |
| |
| get_and_check<toonz_param_traits_tonecurve_t>(node, "unknown", frame); |
| |
| toonz::param_handle_t str; |
| nodeif->get_param(node, "eighth", &str); |
| toonz::param_handle_t notstr; |
| nodeif->get_param(node, "seventh", ¬str); |
| toonz::param_handle_t spec; |
| nodeif->get_param(node, "ninth", &spec); |
| auto pif = grab_interf<toonz::param_interface_t>(TOONZ_UUID_PARAM); |
| if (pif) { |
| int t, l; |
| pif->get_type(str, frame, &t, &l); |
| int sz; |
| std::vector<char> shortage_buf(l / 2 + 1); |
| int ret = pif->get_string_value(str, &sz, l / 2 + 1, shortage_buf.data()); |
| printf("get_string_value(string): {%s} (length:%d) ret:%d\n", shortage_buf.data(), sz, ret); |
| |
| ret = pif->get_string_value(notstr, &sz, l / 2 + 1, shortage_buf.data()); |
| printf("get_string_value(not string): sz:%d ret:%d\n", sz, ret); |
| |
| pif->get_type(spec, frame, &t, &l); |
| toonz_param_spectrum_t spc; |
| ret = pif->get_spectrum_value(spec, frame, 0, &spc); |
| printf("get_spectrum_value(spec): ret:%d\n", ret); |
| dump_value(spc); |
| ret = pif->get_spectrum_value(str, frame, 0, &spc); |
| printf("get_spectrum_value(str): ret:%d\n", ret); |
| } |
| } |
| } |
| |
| int blur = 1; |
| |
| auto tileif = grab_interf<toonz::tile_interface_t>(TOONZ_UUID_TILE); |
| auto portif = grab_interf<toonz::port_interface_t>(TOONZ_UUID_PORT); |
| if (port && tileif && portif) { |
| toonz::fxnode_handle_t fx; |
| portif->get_fx(port, &fx); |
| auto fxif = grab_interf<toonz::fxnode_interface_t>(TOONZ_UUID_FXNODE); |
| if (fxif) { |
| |
| toonz::rect_t rect; |
| tileif->get_rectangle(tile, &rect); |
| |
| toonz::rect_t inRect = conv2rect(conv2rect(rect).enlarge(blur, blur)); |
| toonz::tile_handle_t result = nullptr; |
| tileif->create(&result); |
| fxif->compute_to_tile(fx, rs, frame, &inRect, tile, result); |
| |
| |
| int x = rect.x0; |
| int y = rect.y0; |
| int lx = rect.x1 - rect.x0; |
| int ly = rect.y1 - rect.y0; |
| |
| int sstride, dstride; |
| tileif->get_raw_stride(result, &sstride); |
| tileif->get_raw_stride(tile, &dstride); |
| int selement_type, delement_type; |
| |
| tileif->get_element_type(result, &delement_type); |
| tileif->get_element_type(tile, &selement_type); |
| uint8_t *saddr, *daddr; |
| |
| tileif->get_raw_address_unsafe(result, reinterpret_cast<void **>(&saddr)); |
| tileif->get_raw_address_unsafe(tile, reinterpret_cast<void **>(&daddr)); |
| |
| printf("%f %f %f %f\n", rect.x0, rect.y0, rect.x1, rect.y1); |
| |
| printf("-+ x:%d y:%d lx:%d ly:%d\n", x, y, lx, ly); |
| printf(" + src tile: addr:%p stride:%d type:%d\n", saddr, sstride, selement_type); |
| printf(" + dst tile: addr:%p stride:%d type:%d\n", daddr, dstride, delement_type); |
| |
| |
| |
| hv_kernel<uint8_t, 4>(daddr, saddr + sstride + 4, lx, ly, dstride, sstride, [](uint8_t v[4], const uint8_t *p, int stride, int xinbytes, int yinbytes) { |
| uint32_t l00 = *reinterpret_cast<const uint32_t *>(p + -stride - 4); |
| uint32_t l10 = *reinterpret_cast<const uint32_t *>(p + -stride); |
| uint32_t l20 = *reinterpret_cast<const uint32_t *>(p + -stride + 4); |
| uint32_t l01 = *reinterpret_cast<const uint32_t *>(p - 4); |
| uint32_t l11 = *reinterpret_cast<const uint32_t *>(p); |
| uint32_t l21 = *reinterpret_cast<const uint32_t *>(p + 4); |
| uint32_t l02 = *reinterpret_cast<const uint32_t *>(p + stride - 4); |
| uint32_t l12 = *reinterpret_cast<const uint32_t *>(p + stride); |
| uint32_t l22 = *reinterpret_cast<const uint32_t *>(p + stride + 4); |
| uint32_t r = 0, g = 0, b = 0, m = 0; |
| |
| |
| |
| |
| |
| |
| |
| m += ((l00 >> 24) & 0xff); |
| m += ((l10 >> 24) & 0xff); |
| m += ((l20 >> 24) & 0xff); |
| m += ((l01 >> 24) & 0xff); |
| m += ((l11 >> 24) & 0xff); |
| m += ((l21 >> 24) & 0xff); |
| m += ((l02 >> 24) & 0xff); |
| m += ((l12 >> 24) & 0xff); |
| m += ((l22 >> 24) & 0xff); |
| |
| b += ((l00 >> 16) & 0xff); |
| b += ((l10 >> 16) & 0xff); |
| b += ((l20 >> 16) & 0xff); |
| b += ((l01 >> 16) & 0xff); |
| b += ((l11 >> 16) & 0xff); |
| b += ((l21 >> 16) & 0xff); |
| b += ((l02 >> 16) & 0xff); |
| b += ((l12 >> 16) & 0xff); |
| b += ((l22 >> 16) & 0xff); |
| |
| g += ((l00 >> 8) & 0xff); |
| g += ((l10 >> 8) & 0xff); |
| g += ((l20 >> 8) & 0xff); |
| g += ((l01 >> 8) & 0xff); |
| g += ((l11 >> 8) & 0xff); |
| g += ((l21 >> 8) & 0xff); |
| g += ((l02 >> 8) & 0xff); |
| g += ((l12 >> 8) & 0xff); |
| g += ((l22 >> 8) & 0xff); |
| |
| r += ((l00 >> 0) & 0xff); |
| r += ((l10 >> 0) & 0xff); |
| r += ((l20 >> 0) & 0xff); |
| r += ((l01 >> 0) & 0xff); |
| r += ((l11 >> 0) & 0xff); |
| r += ((l21 >> 0) & 0xff); |
| r += ((l02 >> 0) & 0xff); |
| r += ((l12 >> 0) & 0xff); |
| r += ((l22 >> 0) & 0xff); |
| |
| v[0] = static_cast<uint8_t>(r / 9); |
| v[1] = static_cast<uint8_t>(g / 9); |
| v[2] = static_cast<uint8_t>(b / 9); |
| v[3] = static_cast<uint8_t>(m / 9); |
| }); |
| } |
| } |
| } |
| |
| int do_get_bbox(toonz::node_handle_t node, const toonz::rendering_setting_t *rs, double frame, toonz::rect_t *rect) |
| { |
| printf("do_get_bbox(): node:%p\n", node); |
| bool modified = false; |
| |
| toonz::port_handle_t port = nullptr; |
| { |
| auto nodeif = grab_interf<toonz::node_interface_t>(TOONZ_UUID_NODE); |
| if (nodeif) { |
| int ret = nodeif->get_input_port(node, "IPort", &port); |
| printf("do_get_bbox(): get_input_port:%d\n", ret); |
| } |
| } |
| |
| auto portif = grab_interf<toonz::port_interface_t>(TOONZ_UUID_PORT); |
| if (port && portif) { |
| int con = 0; |
| portif->is_connected(port, &con); |
| if (con) { |
| toonz::fxnode_handle_t fx; |
| portif->get_fx(port, &fx); |
| auto fxif = grab_interf<toonz::fxnode_interface_t>(TOONZ_UUID_FXNODE); |
| if (fxif) { |
| int ret = 0; |
| |
| fxif->get_bbox(fx, rs, frame, rect, &ret); |
| |
| |
| toonz::affine_t a = rs->affine; |
| double det = a.a11 * a.a22 - a.a12 * a.a21; |
| double scale = sqrt(fabs(det)); |
| double blur = 1.0 / scale; |
| |
| ToonzRect r = conv2rect(*rect); |
| r = r.enlarge(blur, blur); |
| *rect = conv2rect(std::move(r)); |
| modified = true; |
| } |
| } |
| } |
| return modified; |
| } |
| |
| param_desc_t params0_[] = { |
| param_desc_ctor<traits_double_t>("first", "1st", {1.0 , -1.0 , 1.0 }, "description of the first param"), |
| param_desc_ctor<traits_range_t>("second", "2nd", {{48.0, 64.0} , {0.0, 180.0} }), |
| param_desc_ctor<traits_color_t>("third", "3rd", {0xff, 0xff, 0xff, 0xff} ), |
| param_desc_ctor<traits_point_t>("fourth", "4th", {{64, -64} , {-200, 200} , {-200, +200} }), |
| }; |
| |
| const char *strtbl_[] = {"tokyo", "osaka", "nagoya"}; |
| |
| param_desc_t params1_[] = { |
| param_desc_ctor<traits_enum_t>("fifth", "5th", {2, 3, strtbl_}), |
| param_desc_ctor<traits_int_t>("sixth", "6th", {2, -10, 10}, "this is integer"), |
| param_desc_ctor<traits_bool_t>("seventh", "7th", {1}), |
| }; |
| |
| toonz_param_traits_spectrum_t::valuetype points_[] = {{0.0, 1.0, 0.0, 0.0, 1.0}, |
| {0.5, 0.5, 0.0, 0.5, 1.0}, |
| {1.0, 0.0, 0.0, 0.5, 1.0}}; |
| |
| param_desc_t params2_[] = { |
| param_desc_ctor<traits_string_t>("eighth", "8th", {"this is sample message"}), |
| param_desc_ctor<traits_spectrum_t>("ninth", "9th", {0.1, 3, points_}), |
| param_desc_ctor<traits_tonecurve_t>("tenth", "10th", {}), |
| }; |
| |
| toonz_param_group_t groups0_[] = { |
| param_group_ctor("Group1", sizeof(params0_) / sizeof(param_desc_t), params0_), |
| param_group_ctor("Group2", sizeof(params1_) / sizeof(param_desc_t), params1_), |
| param_group_ctor("Group3", sizeof(params2_) / sizeof(param_desc_t), params2_), |
| }; |
| |
| toonz_param_page_t pages_[] = { |
| param_page_ctor("Properties", sizeof(groups0_) / sizeof(toonz_param_group_t), groups0_), |
| }; |
| |
| int node_setup(toonz::node_handle_t node) |
| { |
| printf("blur: setup(): node:%p\n", node); |
| |
| auto setup = grab_interf<toonz::setup_interface_t>(TOONZ_UUID_SETUP); |
| if (setup) { |
| int errcode = 0; |
| void *entry = NULL; |
| int ret = setup->set_parameter_pages_with_error(node, sizeof(pages_) / sizeof(toonz_param_page_t), pages_, &errcode, &entry); |
| if (ret) { |
| printf("setup error:0x%x reason:0x%x entry:%p\n", ret, errcode, entry); |
| } |
| setup->add_input_port(node, "IPort", TOONZ_PORT_TYPE_RASTER); |
| } |
| return 0; |
| } |
| |
| int node_create(toonz::node_handle_t node) |
| { |
| printf("blur: create(): node:%p\n", node); |
| return TOONZ_OK; |
| } |
| |
| int node_destroy(toonz::node_handle_t node) |
| { |
| printf("destroy():node:%p\n", node); |
| return TOONZ_OK; |
| } |
| |
| int can_handle(toonz_node_handle_t node, const toonz_rendering_setting_t *rs, double frame) |
| { |
| printf("%s:\n", __FUNCTION__); |
| return TOONZ_OK; |
| } |
| |
| size_t get_memory_requirement(toonz_node_handle_t node, const toonz_rendering_setting_t *rs, double frame, const toonz_rect_t *rect) |
| { |
| printf("%s:\n", __FUNCTION__); |
| return TOONZ_OK; |
| } |
| |
| void on_new_frame(toonz_node_handle_t node, const toonz_rendering_setting_t *rs, double frame) |
| { |
| printf("%s:\n", __FUNCTION__); |
| } |
| |
| void on_end_frame(toonz_node_handle_t node, const toonz_rendering_setting_t *rs, double frame) |
| { |
| printf("%s:\n", __FUNCTION__); |
| } |
| |
| toonz_nodal_rasterfx_handler_t_ toonz_plugin_node_handler = |
| { |
| {1, 0}, |
| do_compute, |
| do_get_bbox, |
| can_handle, |
| get_memory_requirement, |
| on_new_frame, |
| on_end_frame, |
| node_create, |
| node_destroy, |
| node_setup}; |
| |
| extern "C" { |
| TOONZ_PLUGIN_PROBE_BEGIN(TOONZ_IF_VER(1, 0)) |
| TOONZ_PLUGIN_PROBE_DEFINE(TOONZ_PLUGIN_VER(1, 0), "blur-plugin" , "dwango" , "libblur.plugin" , "a blur plugin for test", "http://dwango.co.jp/", TOONZ_PLUGIN_CLASS_POSTPROCESS_SLAB, &toonz_plugin_node_handler) |
| TOONZ_PLUGIN_PROBE_END; |
| } |