/**
* MLJLib
* MeshLabJS Library
*
* Copyright(C) 2015
* Paolo Cignoni
* Visual Computing Lab
* ISTI - CNR
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See theGNU General Public License
* (http://www.gnu.org/licenses/gpl.txt) for more details.
*
*/
/**
* @file Defines the basic class to create a filter plugin
* @author Stefano Gabriele
*/
/**
* @class Creates a new filter
* @description
* This class provides the basic method for adding new processing functionalities
* to meshlabjs. The main idea is that a filter is a kind of blackbox processing
* function that take in input meshes (eventually none) parameters and give back
* processed meshes. When you add a filter to meshlab it will end up in the filter
* list tab.
* You have to redefine three functions:
* * the constructor
* * the {@link _init} where you define the parameters
* * the {@link _applyTo} where you define the behaviour of the function
* @param {Object} parameters The object contains the initialization parameters
* to create filter plugin
*
* <code> parameters = {<br>
* name: //the name of filter<br>
* tooltip: //the filter description shown if mouse pointer is
* over its name<br>
* arity: //An integer:<br>
* //0 for a creation filter<br>
* //-1 special value for the deletion filter, doesn't trigger
* a layer update event
* //1 for a generic single mesh filter, e.g. a filter
* that takes a mesh, some parameters and modify just that single mesh. <br>
* //2 for a filter that take one or more mesh and/or create other layers.
* //3 for a filter that works on all visible layers.
*
* defines its own meshes<br>
* }
* </code>
* @memberOf MLJ.core.plugin
* @author Stefano Gabriele
* @example
* <caption>Refine Filter</caption>
* (function (plugin, scene) {
*
* var filter = new plugin.Filter({
* name: "Refine",
* tooltip: "Apply a subdvision surface refinement step, using various approach (midpoint/loop)",
* arity: 1
* });
*
* var iterWdg;
* filter._init = function (builder) {
*
* iterWdg = builder.Integer({
* max: 5, min: 1, step: 1, defval: 1,
* label: "Step",
* tooltip: "How many refinement iterations are applied to the mesh"
* });
*
* };
*
* filter._applyTo = function (layer) {
* Module.RefineMesh(layer.ptrMesh,iterWdg.getValue());
* };
*
* plugin.install(filter);
*
* })(MLJ.core.plugin, MLJ.core.Scene);
*/
MLJ.core.plugin.Filter = function (parameters) {
MLJ.core.plugin.Plugin.call(this, parameters.name, parameters);
var _this = this;
var entry = new MLJ.gui.component.AccordionEntry(
{label: parameters.name, tooltip: parameters.tooltip});
//Test if arity is number and is integer
if (!(Math.floor(parameters.arity) === parameters.arity &&
jQuery.isNumeric(parameters.arity))) {
parameters.arity = 1;
}
var filterBuilder = new MLJ.core.plugin.GUIBuilder(entry);
$(document).on("mljSearchSelect", function (ev, select) {
var found = false;
var tooltipMatch, nameMatch;
for (var i = 0, m = select.length; i < m; i++) {
tooltipMatch = parameters.tooltip
? parameters.tooltip.indexOf(select[i]) != -1 : false;
nameMatch = parameters.name.indexOf(select[i]) != -1;
if (nameMatch || tooltipMatch) {
entry.show();
found = true;
//exit from for cycle
i = select.length;
}
}
if (!found) {
entry.hide();
}
//MLJ.widget.TabbedPane.getFiltersAccord().refresh();
});
this._main = function () {
MLJ.widget.TabbedPane.getFiltersAccord().addEntry(entry);
var apply = new MLJ.gui.component.Button({
tooltip: "Apply to selected layer",
icon: "img/icons/apply.png",
});
entry.addHeaderButton(apply);
apply.onClick(function () {
var t0 = performance.now();
// Creation filters and filters that works on all layers ignore the current layer
// so we do not pass it
if( (_this.parameters.arity === 0) || (_this.parameters.arity===3) ) {
_this._applyTo();
}
else {
var layer = MLJ.core.Scene.getSelectedLayer();
_this._applyTo(layer);
if (_this.parameters.arity !== -1) MLJ.core.Scene.updateLayer(layer);
}
var t1 = performance.now();
MLJ.widget.Log.append(_this.name + " execution time " + Math.round(t1 - t0) + " ms");
});
if (parameters.arity !== 0) {
MLJ.gui.disabledOnSceneEmpty(apply);
}
if (parameters.arity === 1) {
var applyAll = new MLJ.gui.component.Button({
tooltip: "Apply to all visible layers",
icon: "img/icons/apply_all.png",
});
entry.addHeaderButton(applyAll);
MLJ.gui.disabledOnSceneEmpty(applyAll);
applyAll.onClick(function () {
var ptr = MLJ.core.Scene.getLayers().iterator();
var layer;
var t0 = performance.now();
while (ptr.hasNext()) {
layer = ptr.next();
if (layer.getThreeMesh().visible) {
_this._applyTo(layer);
MLJ.core.Scene.updateLayer(layer);
}
}
var t1 = performance.now();
MLJ.widget.Log.append(name + " execution time " + Math.round(t1 - t0) + " ms");
});
}
_this._init(filterBuilder);
};
};
MLJ.extend(MLJ.core.plugin.Plugin, MLJ.core.plugin.Filter);