<commit_before>#include "mtf/mtf.h"
#include "mtf/pipeline.h"
#include "mtf/Utilities/mexUtils.h"

#include <vector>
#include <map>
#include <memory>

#define MEX_INIT 1
#define MEX_GET_FRAME 2
#define MEX_TRACKER_CREATE 3
#define MEX_GET_REGION 4
#define MEX_SET_REGION 5
#define MEX_TRACKER_REMOVE 6
#define MEX_QUIT 7

using namespace std;
using namespace mtf::params;
typedef std::shared_ptr<mtf::utils::InputBase> Input;
typedef std::shared_ptr<mtf::TrackerBase> Tracker;
typedef PreProc_ PreProc;

static std::map<std::string, const int> cmd_list = {
	{ "init", MEX_INIT },
	{ "get_frame", MEX_GET_FRAME },
	{ "create_tracker", MEX_TRACKER_CREATE },
	{ "get_region", MEX_GET_REGION },
	{ "set_region", MEX_SET_REGION },
	{ "remove_tracker", MEX_TRACKER_REMOVE },
	{ "quit", MEX_QUIT }
};

struct TrackerStruct{
	TrackerStruct() : tracker(nullptr), pre_proc(nullptr){}
	TrackerStruct(Tracker &_tracker, PreProc &_pre_proc) :
		tracker(_tracker), pre_proc(_pre_proc){
	}
	bool create(const cv::Mat init_frame, const cv::Mat init_corners) {
		try{
			tracker.reset(mtf::getTracker(mtf_sm, mtf_am, mtf_ssm, mtf_ilm));
			if(!tracker){
				printf("Tracker could not be created successfully\n");
				return false;
			}
		} catch(const mtf::utils::Exception &err){
			printf("Exception of type %s encountered while creating the tracker: %s\n",
				err.type(), err.what());
			return false;
		}
		try{
			pre_proc = mtf::getPreProc(tracker->inputType(), pre_proc_type);
		} catch(const mtf::utils::Exception &err){
			printf("Exception of type %s encountered while creating the pre processor: %s\n",
				err.type(), err.what());
			return false;
		}
		try{
			pre_proc->initialize(init_frame);
		} catch(const mtf::utils::Exception &err){
			printf("Exception of type %s encountered while initializing the pre processor: %s\n",
				err.type(), err.what());
			return false;
		}
		double min_x = init_corners.at<double>(0, 0);
		double min_y = init_corners.at<double>(1, 0);
		double max_x = init_corners.at<double>(0, 2);
		double max_y = init_corners.at<double>(1, 2);
		double size_x = max_x - min_x;
		double size_y = max_y - min_y;
		try{
			for(PreProc curr_obj = pre_proc; curr_obj; curr_obj = curr_obj->next){
				tracker->setImage(curr_obj->getFrame());
			}
			printf("Initializing tracker with object of size %f x %f\n", size_x, size_y);
			tracker->initialize(init_corners);
		} catch(const mtf::utils::Exception &err){
			printf("Exception of type %s encountered while initializing the tracker: %s\n",
				err.type(), err.what());
			return false;
		}
	}
	bool update(const cv::Mat &curr_img, mxArray* &plhs) {
		if(!pre_proc || !tracker){
			printf("Tracker has not been created");
			return false;
		}
		double fps = 0, fps_win = 0;
		double tracking_time, tracking_time_with_input;
		mtf_clock_get(start_time_with_input);
		try{
			//! update pre-processor
			pre_proc->update(curr_img);
			mtf_clock_get(start_time);
			//! update tracker
			tracker->update();
			if(print_fps){
				mtf_clock_get(end_time);
				mtf_clock_measure(start_time, end_time, tracking_time);
				mtf_clock_measure(start_time_with_input, end_time, tracking_time_with_input);
				fps = 1.0 / tracking_time;
				fps_win = 1.0 / tracking_time_with_input;
				printf("fps: %f\t fps_win=%f\n", fps, fps_win);
			}
			if(reset_template){
				tracker->initialize(tracker->getRegion());
			}
		} catch(const mtf::utils::Exception &err){
			printf("Exception of type %s encountered while updating the tracker: %s\n",
				err.type(), err.what());
			return false;
		}
		plhs = mtf::utils::setCorners(tracker->getRegion());
		return true;
	}

	void setRegion(const cv::Mat& corners){
		if(!pre_proc || !tracker){
			printf("Tracker has not been created");
			return;
		}
		tracker->setRegion(corners);
	}
	const cv::Mat& getRegion() {
		return tracker->getRegion();
	}
	void reset() {
		tracker.reset();
	}
private:
	Tracker tracker;
	PreProc pre_proc;
};

static Input input;
static std::map<int, TrackerStruct> trackers;

static unsigned int _tracker_id = 0;

bool createInput() {
	try{
		input.reset(mtf::getInput(pipeline));
		if(!input->initialize()){
			printf("Pipeline could not be initialized successfully. Exiting...\n");
			return false;
		}
	} catch(const mtf::utils::Exception &err){
		printf("Exception of type %s encountered while initializing the input pipeline: %s\n",
			err.type(), err.what());
		return false;
	}
	return true;
}

bool updateInput(){
	if(!input){
		printf("Input pipeline is not initialized");
		return false;
	}
	if(!input->update()){
		printf("Input pipeline could not be updated");
		return false;
	}
	return true;
}

bool getFrame(mxArray* &plhs) {
	if(!updateInput()){
		return false;
	}
	const cv::Mat frame = input->getFrame();
	int n_channels = 3, n_dims = 3;
	if(frame.type() == CV_8UC1){
		n_channels = 1;
		n_dims = 2;
	}
	mwSize *dims = new mwSize[n_dims];
	dims[0] = frame.rows;
	dims[1] = frame.cols;
	if(n_channels == 3){
		dims[2] = n_channels;
	}
	plhs = mxCreateNumericArray(n_dims, dims, mxUINT8_CLASS, mxREAL);
	mtf::utils::copyMatrixToMatlab<unsigned char>(frame, (unsigned char*)mxGetPr(plhs), n_channels);
	delete(dims);
	return true;
}

bool setRegion(unsigned int tracker_id, const cv::Mat &corners, mxArray* &plhs) {
	std::map<int, TrackerStruct>::iterator it = trackers.find(tracker_id);
	if(it == trackers.end()){
		printf("Invalid tracker ID: %d\n", tracker_id);
		return false;
	}
	try{
		it->second.setRegion(corners);
	} catch(const mtf::utils::Exception &err){
		printf("Exception of type %s encountered while resetting the tracker: %s\n",
			err.type(), err.what());
		return false;
	}
	plhs = mtf::utils::setCorners(it->second.getRegion());
	return true;
}

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
	mwSize dims[2] = { 1, 1 };
	plhs[0] = mxCreateNumericArray(2, dims, mxUINT32_CLASS, mxREAL);
	//plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
	unsigned int *ret_val = (unsigned int*)mxGetPr(plhs[0]);
	if(nrhs < 1){
		mexErrMsgTxt("Not enough input arguments.");
	}
	if(!mxIsChar(prhs[0])){
		mexErrMsgTxt("The first argument must be a string.");
	}
	int cmd_str_len = mxGetM(prhs[0])*mxGetN(prhs[0]) + 1;
	char *cmd_str = (char *)mxMalloc(cmd_str_len);
	mxGetString(prhs[0], cmd_str, cmd_str_len);

	auto cmd_iter = cmd_list.find(std::string(cmd_str));
	if(cmd_iter == cmd_list.end()){
		mexErrMsgTxt(cv::format("Invalid command provided: %s.", cmd_str).c_str());
	}
	const int cmd_id = cmd_iter->second;

	switch(cmd_id) {
	case MEX_INIT:
	{
		//if(nlhs != 2){
		//	mexErrMsgTxt("2 output arguments (input_id, n_frames) are needed to create input pipeline.");
		//}
		if(nrhs > 1){
			if(!mxIsChar(prhs[1])){
				mexErrMsgTxt("Second input argument for creating input pipeline must be a string.");
			}
			if(!readParams(mtf::utils::toString(prhs[1]))) {
				mexErrMsgTxt("Parameters could not be parsed");
			}
		}
		if(!createInput()){
			*ret_val = 0;
			return;
		}
		if(nlhs >= 2){
			mwSize dims[2] = { 1, 1 };
			plhs[1] = mxCreateNumericArray(2, dims, mxUINT32_CLASS, mxREAL);
			unsigned int *n_frames = (unsigned int*)mxGetPr(plhs[1]);
			*n_frames = static_cast<unsigned int>(input->getNFrames());
		}
		return;
	}
	case MEX_GET_FRAME:
	{
		if(nlhs != 2){
			mexErrMsgTxt("2 output arguments are needed to get frame from input pipeline.");
		}
		if(!getFrame(plhs[1])){
			*ret_val = 0;
			return;
		}
		*ret_val = 1;
		return;
	}
	case MEX_TRACKER_CREATE:
	{
		if(nrhs < 2){
			mexErrMsgTxt("At least 2 input arguments are needed to create tracker.");
		}
		if(!mxIsChar(prhs[1])){
			mexErrMsgTxt("Second input argument for creating tracker must be a string.");
		}
		if(!readParams(mtf::utils::toString(prhs[1]))) {
			mexErrMsgTxt("Parameters could not be parsed");
		}
		*ret_val = 0;

		if(!updateInput()){
			return;
		}
		cv::Mat init_corners;
		if(nrhs > 2){
			init_corners = mtf::utils::getCorners(prhs[2]);
		} else{
			mtf::utils::ObjUtils obj_utils;
			try{
				if(mex_live_init){
					if(!obj_utils.selectObjects(input.get(), 1,
						patch_size, line_thickness, write_objs, sel_quad_obj,
						write_obj_fname.c_str())){
						mexErrMsgTxt("Object(s) to be tracked could not be obtained.\n");
					}
				} else{
					if(!obj_utils.selectObjects(input->getFrame(), 1, patch_size, line_thickness,
						write_objs, sel_quad_obj, write_obj_fname.c_str())){
						mexErrMsgTxt("Object(s) to be tracked could not be obtained.\n");
					}
				}

			} catch(const mtf::utils::Exception &err){
				mexErrMsgTxt(cv::format("Exception of type %s encountered while obtaining the objects to track: %s\n",
					err.type(), err.what()).c_str());
			}
			init_corners = obj_utils.getObj().corners.clone();

		TrackerStruct tracker;
		if(!tracker.create(input->getFrame(), init_corners)){
			return;
		}
		++_tracker_id;
		trackers.insert(std::pair<int, TrackerStruct>(_tracker_id, tracker));
		*ret_val = _tracker_id;
		return;
	}
	case MEX_GET_REGION:
	{
		if(nrhs < 2){
			mexErrMsgTxt("At least 2 input arguments are needed to get tracker region.");
		}
		if(nlhs != 2){
			mexErrMsgTxt("2 output arguments are needed to get tracker region.");
		}
		if(!updateInput()){
			return;
		}
		*ret_val = 0;
		unsigned int tracker_id = mtf::utils::getID(prhs[1]);
		std::map<int, TrackerStruct>::iterator it = trackers.find(tracker_id);
		if(it == trackers.end()){
			printf("Invalid tracker ID: %d\n", tracker_id);
			return;
		}
		if(!it->second.update(input->getFrame(), plhs[1])){
			return;
		}
		*ret_val = 1;
		return;
	}
	case MEX_SET_REGION:
	{
		if(nrhs < 2){
			mexErrMsgTxt("At least 2 input arguments are needed to reset tracker.");
		}
		if(nlhs != 2){
			mexErrMsgTxt("2 output arguments are needed to reset tracker.");
		}
		unsigned int tracker_id = mtf::utils::getID(prhs[1]);
		cv::Mat curr_corners = mtf::utils::getCorners(prhs[2]);
		if(!setRegion(tracker_id, curr_corners, plhs[1])){
			*ret_val = 0;
			return;
		}

		*ret_val = 1;
		return;
	}
	case MEX_TRACKER_REMOVE:
	{
		if(nrhs < 2){
			mexErrMsgTxt("At least 2 input arguments are needed to reset tracker.");
		}
		if(nlhs != 1){
			mexErrMsgTxt("1 output argument is needed to reset tracker.");
		}
		unsigned int tracker_id = mtf::utils::getID(prhs[1]);
		std::map<int, TrackerStruct>::iterator it = trackers.find(tracker_id);
		if(it == trackers.end()){
			printf("Invalid tracker ID: %d\n", tracker_id);
			*ret_val = 0;
			return;
		}
		trackers.erase(it);
		*ret_val = 1;
		return;
	}
	case MEX_QUIT:
	{
		printf("Clearing up...");
		input.reset();
		trackers.clear();
		*ret_val = 1;
		printf("Done\n");
		return;
	}
	default:
		mexErrMsgTxt(cv::format("Invalid command provided: %s.", cmd_str).c_str());
	}
}
<commit_msg>minor fix<commit_after>#include "mtf/mtf.h"
#include "mtf/pipeline.h"
#include "mtf/Utilities/mexUtils.h"

#include <vector>
#include <map>
#include <memory>

#define MEX_INIT 1
#define MEX_GET_FRAME 2
#define MEX_TRACKER_CREATE 3
#define MEX_GET_REGION 4
#define MEX_SET_REGION 5
#define MEX_TRACKER_REMOVE 6
#define MEX_QUIT 7

using namespace std;
using namespace mtf::params;
typedef std::shared_ptr<mtf::utils::InputBase> Input;
typedef std::shared_ptr<mtf::TrackerBase> Tracker;
typedef PreProc_ PreProc;

static std::map<std::string, const int> cmd_list = {
	{ "init", MEX_INIT },
	{ "get_frame", MEX_GET_FRAME },
	{ "create_tracker", MEX_TRACKER_CREATE },
	{ "get_region", MEX_GET_REGION },
	{ "set_region", MEX_SET_REGION },
	{ "remove_tracker", MEX_TRACKER_REMOVE },
	{ "quit", MEX_QUIT }
};

struct TrackerStruct{
	TrackerStruct() : tracker(nullptr), pre_proc(nullptr){}
	TrackerStruct(Tracker &_tracker, PreProc &_pre_proc) :
		tracker(_tracker), pre_proc(_pre_proc){
	}
	bool create(const cv::Mat init_frame, const cv::Mat init_corners) {
		try{
			tracker.reset(mtf::getTracker(mtf_sm, mtf_am, mtf_ssm, mtf_ilm));
			if(!tracker){
				printf("Tracker could not be created successfully\n");
				return false;
			}
		} catch(const mtf::utils::Exception &err){
			printf("Exception of type %s encountered while creating the tracker: %s\n",
				err.type(), err.what());
			return false;
		}
		try{
			pre_proc = mtf::getPreProc(tracker->inputType(), pre_proc_type);
		} catch(const mtf::utils::Exception &err){
			printf("Exception of type %s encountered while creating the pre processor: %s\n",
				err.type(), err.what());
			return false;
		}
		try{
			pre_proc->initialize(init_frame);
		} catch(const mtf::utils::Exception &err){
			printf("Exception of type %s encountered while initializing the pre processor: %s\n",
				err.type(), err.what());
			return false;
		}
		double min_x = init_corners.at<double>(0, 0);
		double min_y = init_corners.at<double>(1, 0);
		double max_x = init_corners.at<double>(0, 2);
		double max_y = init_corners.at<double>(1, 2);
		double size_x = max_x - min_x;
		double size_y = max_y - min_y;
		try{
			for(PreProc curr_obj = pre_proc; curr_obj; curr_obj = curr_obj->next){
				tracker->setImage(curr_obj->getFrame());
			}
			printf("Initializing tracker with object of size %f x %f\n", size_x, size_y);
			tracker->initialize(init_corners);
		} catch(const mtf::utils::Exception &err){
			printf("Exception of type %s encountered while initializing the tracker: %s\n",
				err.type(), err.what());
			return false;
		}
	}
	bool update(const cv::Mat &curr_img, mxArray* &plhs) {
		if(!pre_proc || !tracker){
			printf("Tracker has not been created");
			return false;
		}
		double fps = 0, fps_win = 0;
		double tracking_time, tracking_time_with_input;
		mtf_clock_get(start_time_with_input);
		try{
			//! update pre-processor
			pre_proc->update(curr_img);
			mtf_clock_get(start_time);
			//! update tracker
			tracker->update();
			if(print_fps){
				mtf_clock_get(end_time);
				mtf_clock_measure(start_time, end_time, tracking_time);
				mtf_clock_measure(start_time_with_input, end_time, tracking_time_with_input);
				fps = 1.0 / tracking_time;
				fps_win = 1.0 / tracking_time_with_input;
				printf("fps: %f\t fps_win=%f\n", fps, fps_win);
			}
			if(reset_template){
				tracker->initialize(tracker->getRegion());
			}
		} catch(const mtf::utils::Exception &err){
			printf("Exception of type %s encountered while updating the tracker: %s\n",
				err.type(), err.what());
			return false;
		}
		plhs = mtf::utils::setCorners(tracker->getRegion());
		return true;
	}

	void setRegion(const cv::Mat& corners){
		if(!pre_proc || !tracker){
			printf("Tracker has not been created");
			return;
		}
		tracker->setRegion(corners);
	}
	const cv::Mat& getRegion() {
		return tracker->getRegion();
	}
	void reset() {
		tracker.reset();
	}
private:
	Tracker tracker;
	PreProc pre_proc;
};

static Input input;
static std::map<int, TrackerStruct> trackers;

static unsigned int _tracker_id = 0;

bool createInput() {
	try{
		input.reset(mtf::getInput(pipeline));
		if(!input->initialize()){
			printf("Pipeline could not be initialized successfully. Exiting...\n");
			return false;
		}
	} catch(const mtf::utils::Exception &err){
		printf("Exception of type %s encountered while initializing the input pipeline: %s\n",
			err.type(), err.what());
		return false;
	}
	return true;
}

bool updateInput(){
	if(!input){
		printf("Input pipeline is not initialized");
		return false;
	}
	if(!input->update()){
		printf("Input pipeline could not be updated");
		return false;
	}
	return true;
}

bool getFrame(mxArray* &plhs) {
	if(!updateInput()){
		return false;
	}
	const cv::Mat frame = input->getFrame();
	int n_channels = 3, n_dims = 3;
	if(frame.type() == CV_8UC1){
		n_channels = 1;
		n_dims = 2;
	}
	mwSize *dims = new mwSize[n_dims];
	dims[0] = frame.rows;
	dims[1] = frame.cols;
	if(n_channels == 3){
		dims[2] = n_channels;
	}
	plhs = mxCreateNumericArray(n_dims, dims, mxUINT8_CLASS, mxREAL);
	mtf::utils::copyMatrixToMatlab<unsigned char>(frame, (unsigned char*)mxGetPr(plhs), n_channels);
	delete(dims);
	return true;
}

bool setRegion(unsigned int tracker_id, const cv::Mat &corners, mxArray* &plhs) {
	std::map<int, TrackerStruct>::iterator it = trackers.find(tracker_id);
	if(it == trackers.end()){
		printf("Invalid tracker ID: %d\n", tracker_id);
		return false;
	}
	try{
		it->second.setRegion(corners);
	} catch(const mtf::utils::Exception &err){
		printf("Exception of type %s encountered while resetting the tracker: %s\n",
			err.type(), err.what());
		return false;
	}
	plhs = mtf::utils::setCorners(it->second.getRegion());
	return true;
}

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
	mwSize dims[2] = { 1, 1 };
	plhs[0] = mxCreateNumericArray(2, dims, mxUINT32_CLASS, mxREAL);
	//plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
	unsigned int *ret_val = (unsigned int*)mxGetPr(plhs[0]);
	if(nrhs < 1){
		mexErrMsgTxt("Not enough input arguments.");
	}
	if(!mxIsChar(prhs[0])){
		mexErrMsgTxt("The first argument must be a string.");
	}
	int cmd_str_len = mxGetM(prhs[0])*mxGetN(prhs[0]) + 1;
	char *cmd_str = (char *)mxMalloc(cmd_str_len);
	mxGetString(prhs[0], cmd_str, cmd_str_len);

	auto cmd_iter = cmd_list.find(std::string(cmd_str));
	if(cmd_iter == cmd_list.end()){
		mexErrMsgTxt(cv::format("Invalid command provided: %s.", cmd_str).c_str());
	}
	const int cmd_id = cmd_iter->second;

	switch(cmd_id) {
	case MEX_INIT:
	{
		//if(nlhs != 2){
		//	mexErrMsgTxt("2 output arguments (input_id, n_frames) are needed to create input pipeline.");
		//}
		if(nrhs > 1){
			if(!mxIsChar(prhs[1])){
				mexErrMsgTxt("Second input argument for creating input pipeline must be a string.");
			}
			if(!readParams(mtf::utils::toString(prhs[1]))) {
				mexErrMsgTxt("Parameters could not be parsed");
			}
		}
		if(!createInput()){
			*ret_val = 0;
			return;
		}
		if(nlhs >= 2){
			mwSize dims[2] = { 1, 1 };
			plhs[1] = mxCreateNumericArray(2, dims, mxUINT32_CLASS, mxREAL);
			unsigned int *n_frames = (unsigned int*)mxGetPr(plhs[1]);
			*n_frames = static_cast<unsigned int>(input->getNFrames());
		}
		return;
	}
	case MEX_GET_FRAME:
	{
		if(nlhs != 2){
			mexErrMsgTxt("2 output arguments are needed to get frame from input pipeline.");
		}
		if(!getFrame(plhs[1])){
			*ret_val = 0;
			return;
		}
		*ret_val = 1;
		return;
	}
	case MEX_TRACKER_CREATE:
	{
		if(nrhs < 2){
			mexErrMsgTxt("At least 2 input arguments are needed to create tracker.");
		}
		if(!mxIsChar(prhs[1])){
			mexErrMsgTxt("Second input argument for creating tracker must be a string.");
		}
		if(!readParams(mtf::utils::toString(prhs[1]))) {
			mexErrMsgTxt("Parameters could not be parsed");
		}
		*ret_val = 0;

		if(!updateInput()){
			return;
		}
		cv::Mat init_corners;
		if(nrhs > 2){
			init_corners = mtf::utils::getCorners(prhs[2]);
		} else{
			mtf::utils::ObjUtils obj_utils;
			try{
				if(mex_live_init){
					if(!obj_utils.selectObjects(input.get(), 1,
						patch_size, line_thickness, write_objs, sel_quad_obj,
						write_obj_fname.c_str())){
						mexErrMsgTxt("Object(s) to be tracked could not be obtained.\n");
					}
				} else{
					if(!obj_utils.selectObjects(input->getFrame(), 1, patch_size, line_thickness,
						write_objs, sel_quad_obj, write_obj_fname.c_str())){
						mexErrMsgTxt("Object(s) to be tracked could not be obtained.\n");
					}
				}

			} catch(const mtf::utils::Exception &err){
				mexErrMsgTxt(cv::format("Exception of type %s encountered while obtaining the objects to track: %s\n",
					err.type(), err.what()).c_str());
			}
			init_corners = obj_utils.getObj().corners.clone();

			TrackerStruct tracker;
			if(!tracker.create(input->getFrame(), init_corners)){
				return;
			}
			++_tracker_id;
			trackers.insert(std::pair<int, TrackerStruct>(_tracker_id, tracker));
			*ret_val = _tracker_id;
			return;
		}
	}
	case MEX_GET_REGION:
	{
		if(nrhs < 2){
			mexErrMsgTxt("At least 2 input arguments are needed to get tracker region.");
		}
		if(nlhs != 2){
			mexErrMsgTxt("2 output arguments are needed to get tracker region.");
		}
		if(!updateInput()){
			return;
		}
		*ret_val = 0;
		unsigned int tracker_id = mtf::utils::getID(prhs[1]);
		std::map<int, TrackerStruct>::iterator it = trackers.find(tracker_id);
		if(it == trackers.end()){
			printf("Invalid tracker ID: %d\n", tracker_id);
			return;
		}
		if(!it->second.update(input->getFrame(), plhs[1])){
			return;
		}
		*ret_val = 1;
		return;
	}
	case MEX_SET_REGION:
	{
		if(nrhs < 2){
			mexErrMsgTxt("At least 2 input arguments are needed to reset tracker.");
		}
		if(nlhs != 2){
			mexErrMsgTxt("2 output arguments are needed to reset tracker.");
		}
		unsigned int tracker_id = mtf::utils::getID(prhs[1]);
		cv::Mat curr_corners = mtf::utils::getCorners(prhs[2]);
		if(!setRegion(tracker_id, curr_corners, plhs[1])){
			*ret_val = 0;
			return;
		}

		*ret_val = 1;
		return;
	}
	case MEX_TRACKER_REMOVE:
	{
		if(nrhs < 2){
			mexErrMsgTxt("At least 2 input arguments are needed to reset tracker.");
		}
		if(nlhs != 1){
			mexErrMsgTxt("1 output argument is needed to reset tracker.");
		}
		unsigned int tracker_id = mtf::utils::getID(prhs[1]);
		std::map<int, TrackerStruct>::iterator it = trackers.find(tracker_id);
		if(it == trackers.end()){
			printf("Invalid tracker ID: %d\n", tracker_id);
			*ret_val = 0;
			return;
		}
		trackers.erase(it);
		*ret_val = 1;
		return;
	}
	case MEX_QUIT:
	{
		printf("Clearing up...");
		input.reset();
		trackers.clear();
		*ret_val = 1;
		printf("Done\n");
		return;
	}
	default:
		mexErrMsgTxt(cv::format("Invalid command provided: %s.", cmd_str).c_str());
	}
}
<|endoftext|>


<commit_before>#ifndef ENTT_CORE_ANY_HPP
#define ENTT_CORE_ANY_HPP

#include <cstddef>
#include <functional>
#include <new>
#include <type_traits>
#include <utility>
#include "../config/config.h"
#include "fwd.hpp"
#include "type_info.hpp"
#include "type_traits.hpp"

namespace entt {

/**
 * @brief A SBO friendly, type-safe container for single values of any type.
 * @tparam Len Size of the storage reserved for the small buffer optimization.
 */
template<std::size_t Len>
class basic_any {
    enum class operation { COPY, MOVE, DTOR, COMP, ADDR, CADDR, REF, CREF, TYPE };

    using storage_type = std::aligned_storage_t<Len == 0u ? 1u : Len>;
    using vtable_type = const void *(const operation, const basic_any &, const void *);

    template<typename Type>
    static constexpr auto in_situ = (Len != 0u) && (sizeof(Type) <= sizeof(storage_type)) && std::is_nothrow_move_constructible_v<Type>;

    template<typename Type>
    [[nodiscard]] static bool compare(const void *lhs, const void *rhs) {
        if constexpr(!std::is_function_v<Type> && is_equality_comparable_v<Type>) {
            return *static_cast<const Type *>(lhs) == *static_cast<const Type *>(rhs);
        } else {
            return lhs == rhs;
        }
    }

    template<typename Type>
    static Type & as(const void *to) {
        return *const_cast<Type *>(static_cast<const Type *>(to));
    }

    template<typename Type>
    static const void * basic_vtable([[maybe_unused]] const operation op, [[maybe_unused]] const basic_any &from, [[maybe_unused]] const void *to) {
        if constexpr(!std::is_void_v<Type>) {
            if constexpr(std::is_lvalue_reference_v<Type>) {
                using base_type = std::remove_const_t<std::remove_reference_t<Type>>;

                switch(op) {
                case operation::COPY:
                    if constexpr(std::is_copy_constructible_v<base_type>) {
                        as<basic_any>(to).template emplace<base_type>(*static_cast<const base_type *>(from.instance));
                    }
                    break;
                case operation::MOVE:
                    as<basic_any>(to).instance = from.instance;
                case operation::DTOR:
                    break;
                case operation::COMP:
                    return compare<base_type>(from.instance, to) ? to : nullptr;
                case operation::ADDR:
                    return std::is_const_v<std::remove_reference_t<Type>> ? nullptr : from.instance;
                case operation::CADDR:
                    return from.instance;
                case operation::REF:
                    as<basic_any>(to).instance = from.instance;
                    as<basic_any>(to).vtable = basic_vtable<Type>;
                    break;
                case operation::CREF:
                    as<basic_any>(to).instance = from.instance;
                    as<basic_any>(to).vtable = basic_vtable<const base_type &>;
                    break;
                case operation::TYPE:
                    as<type_info>(to) = type_id<base_type>();
                    break;
                }
            } else if constexpr(in_situ<Type>) {
                #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L
                auto *instance = const_cast<Type *>(std::launder(reinterpret_cast<const Type *>(&from.storage)));
                #else
                auto *instance = const_cast<Type *>(reinterpret_cast<const Type *>(&from.storage));
                #endif

                switch(op) {
                case operation::COPY:
                    if constexpr(std::is_copy_constructible_v<Type>) {
                        new (&as<basic_any>(to).storage) Type{std::as_const(*instance)};
                        as<basic_any>(to).vtable = from.vtable;
                    }
                    break;
                case operation::MOVE:
                    new (&as<basic_any>(to).storage) Type{std::move(*instance)};
                    [[fallthrough]];
                case operation::DTOR:
                    instance->~Type();
                    break;
                case operation::COMP:
                    return compare<Type>(instance, to) ? to : nullptr;
                case operation::ADDR:
                case operation::CADDR:
                    return instance;
                case operation::REF:
                    as<basic_any>(to).instance = instance;
                    as<basic_any>(to).vtable = basic_vtable<Type &>;
                    break;
                case operation::CREF:
                    as<basic_any>(to).instance = instance;
                    as<basic_any>(to).vtable = basic_vtable<const Type &>;
                    break;
                case operation::TYPE:
                    as<type_info>(to) = type_id<Type>();
                    break;
                }
            } else {
                switch(op) {
                case operation::COPY:
                    if constexpr(std::is_copy_constructible_v<Type>) {
                        as<basic_any>(to).instance = new Type{*static_cast<const Type *>(from.instance)};
                        as<basic_any>(to).vtable = from.vtable;
                    }
                    break;
                case operation::MOVE:
                    as<basic_any>(to).instance = from.instance;
                    break;
                case operation::DTOR:
                    if constexpr(std::is_array_v<Type>) {
                        delete[] static_cast<const Type *>(from.instance);
                    } else {
                        delete static_cast<const Type *>(from.instance);
                    }
                    break;
                case operation::COMP:
                    return compare<Type>(from.instance, to) ? to : nullptr;
                case operation::ADDR:
                case operation::CADDR:
                    return from.instance;
                case operation::REF:
                    as<basic_any>(to).instance = from.instance;
                    as<basic_any>(to).vtable = basic_vtable<Type &>;
                    break;
                case operation::CREF:
                    as<basic_any>(to).instance = from.instance;
                    as<basic_any>(to).vtable = basic_vtable<const Type &>;
                    break;
                case operation::TYPE:
                    as<type_info>(to) = type_id<Type>();
                    break;
                }
            }
        }

        return nullptr;
    }

public:
    /*! @brief Default constructor. */
    basic_any() ENTT_NOEXCEPT
        : basic_any{std::in_place_type<void>}
    {}

    /**
     * @brief Constructs an any by directly initializing the new object.
     * @tparam Type Type of object to use to initialize the wrapper.
     * @tparam Args Types of arguments to use to construct the new instance.
     * @param args Parameters to use to construct the instance.
     */
    template<typename Type, typename... Args>
    explicit basic_any(std::in_place_type_t<Type>, [[maybe_unused]] Args &&... args)
        : vtable{&basic_vtable<Type>},
          instance{}
    {
        if constexpr(!std::is_void_v<Type>) {
            if constexpr(std::is_lvalue_reference_v<Type>) {
                static_assert(sizeof...(Args) == 1u && (std::is_lvalue_reference_v<Args> && ...));
                instance = (&args, ...);
            } else if constexpr(in_situ<Type>) {
                new (&storage) Type(std::forward<Args>(args)...);
            } else {
                instance = new Type(std::forward<Args>(args)...);
            }
        }
    }

    /**
     * @brief Constructs an any that holds an unmanaged object.
     * @tparam Type Type of object to use to initialize the wrapper.
     * @param value An instance of an object to use to initialize the wrapper.
     */
    template<typename Type>
    basic_any(std::reference_wrapper<Type> value) ENTT_NOEXCEPT
        : basic_any{std::in_place_type<Type &>, value.get()}
    {}

    /**
     * @brief Constructs an any from a given value.
     * @tparam Type Type of object to use to initialize the wrapper.
     * @param value An instance of an object to use to initialize the wrapper.
     */
    template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, basic_any>>>
    basic_any(Type &&value)
        : basic_any{std::in_place_type<std::decay_t<Type>>, std::forward<Type>(value)}
    {}

    /**
     * @brief Copy constructor.
     * @param other The instance to copy from.
     */
    basic_any(const basic_any &other)
        : basic_any{}
    {
        other.vtable(operation::COPY, other, this);
    }

    /**
     * @brief Move constructor.
     * @param other The instance to move from.
     */
    basic_any(basic_any &&other) ENTT_NOEXCEPT
        : basic_any{}
    {
        other.vtable(operation::MOVE, other, this);
        vtable = std::exchange(other.vtable, &basic_vtable<void>);
    }

    /*! @brief Frees the internal storage, whatever it means. */
    ~basic_any() {
        vtable(operation::DTOR, *this, nullptr);
    }

    /**
     * @brief Assignment operator.
     * @param other The instance to assign from.
     * @return This any object.
     */
    basic_any & operator=(basic_any other) {
        swap(*this, other);
        return *this;
    }

    /**
     * @brief Returns the type of the contained object.
     * @return The type of the contained object, if any.
     */
    [[nodiscard]] type_info type() const ENTT_NOEXCEPT {
        type_info info;
        vtable(operation::TYPE, *this, &info);
        return info;
    }

    /**
     * @brief Returns an opaque pointer to the contained instance.
     * @return An opaque pointer the contained instance, if any.
     */
    [[nodiscard]] const void * data() const ENTT_NOEXCEPT {
        return vtable(operation::CADDR, *this, nullptr);
    }

    /*! @copydoc data */
    [[nodiscard]] void * data() ENTT_NOEXCEPT {
        return const_cast<void *>(vtable(operation::ADDR, *this, nullptr));
    }

    /**
     * @brief Replaces the contained object by creating a new instance directly.
     * @tparam Type Type of object to use to initialize the wrapper.
     * @tparam Args Types of arguments to use to construct the new instance.
     * @param args Parameters to use to construct the instance.
     */
    template<typename Type, typename... Args>
    void emplace(Args &&... args) {
        *this = basic_any{std::in_place_type<Type>, std::forward<Args>(args)...};
    }

    /*! @brief Destroys contained object */
    void reset() {
        *this = basic_any{};
    }

    /**
     * @brief Returns false if a wrapper is empty, true otherwise.
     * @return False if the wrapper is empty, true otherwise.
     */
    [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
        return !(vtable(operation::CADDR, *this, nullptr) == nullptr);
    }

    /**
     * @brief Checks if two wrappers differ in their content.
     * @param other Wrapper with which to compare.
     * @return False if the two objects differ in their content, true otherwise.
     */
    bool operator==(const basic_any &other) const ENTT_NOEXCEPT {
        return type() == other.type() && (vtable(operation::COMP, *this, other.data()) == other.data());
    }

    /**
     * @brief Swaps two any objects.
     * @param lhs A valid any object.
     * @param rhs A valid any object.
     */
    friend void swap(basic_any &lhs, basic_any &rhs) {
        basic_any tmp{};
        lhs.vtable(operation::MOVE, lhs, &tmp);
        rhs.vtable(operation::MOVE, rhs, &lhs);
        lhs.vtable(operation::MOVE, tmp, &rhs);
        std::swap(lhs.vtable, rhs.vtable);
    }

    /**
     * @brief Aliasing constructor.
     * @return An any that shares a reference to an unmanaged object.
     */
    [[nodiscard]] basic_any as_ref() ENTT_NOEXCEPT {
        basic_any ref{};
        vtable(operation::REF, *this, &ref);
        return ref;
    }

    /*! @copydoc as_ref */
    [[nodiscard]] basic_any as_ref() const ENTT_NOEXCEPT {
        basic_any ref{};
        vtable(operation::CREF, *this, &ref);
        return ref;
    }

private:
    vtable_type *vtable;
    union { const void *instance; storage_type storage{}; };
};

/**
 * @brief Checks if two wrappers differ in their content.
 * @tparam Len Size of the storage reserved for the small buffer optimization.
 * @param lhs A wrapper, either empty or not.
 * @param rhs A wrapper, either empty or not.
 * @return True if the two wrappers differ in their content, false otherwise.
 */
template<std::size_t Len>
[[nodiscard]] inline bool operator!=(const basic_any<Len> &lhs, const basic_any<Len> &rhs) ENTT_NOEXCEPT {
    return !(lhs == rhs);
}

/**
 * @brief Performs type-safe access to the contained object.
 * @tparam Len Size of the storage reserved for the small buffer optimization.
 * @tparam Type Type to which conversion is required.
 * @param data Target any object.
 * @return The element converted to the requested type.
 */
template<typename Type, std::size_t Len>
Type any_cast(const basic_any<Len> &data) ENTT_NOEXCEPT {
    const auto * const instance = any_cast<std::remove_reference_t<Type>>(&data);
    ENTT_ASSERT(instance);
    return static_cast<Type>(*instance);
}

/*! @copydoc any_cast */
template<typename Type, std::size_t Len>
Type any_cast(basic_any<Len> &data) ENTT_NOEXCEPT {
    // forces const on non-reference types to make them work also with wrappers for const references
    auto * const instance = any_cast<std::conditional_t<std::is_reference_v<Type>, std::remove_reference_t<Type>, const Type>>(&data);
    ENTT_ASSERT(instance);
    return static_cast<Type>(*instance);
}

/*! @copydoc any_cast */
template<typename Type, std::size_t Len>
Type any_cast(basic_any<Len> &&data) ENTT_NOEXCEPT {
    // forces const on non-reference types to make them work also with wrappers for const references
    auto * const instance = any_cast<std::conditional_t<std::is_reference_v<Type>, std::remove_reference_t<Type>, const Type>>(&data);
    ENTT_ASSERT(instance);
    return static_cast<Type>(std::move(*instance));
}

/*! @copydoc any_cast */
template<typename Type, std::size_t Len>
const Type * any_cast(const basic_any<Len> *data) ENTT_NOEXCEPT {
    return (data->type() == type_id<Type>() ? static_cast<const Type *>(data->data()) : nullptr);
}

/*! @copydoc any_cast */
template<typename Type, std::size_t Len>
Type * any_cast(basic_any<Len> *data) ENTT_NOEXCEPT {
    // last attempt to make wrappers for const references return their values
    return (data->type() == type_id<Type>() ? static_cast<Type *>(static_cast<constness_as_t<basic_any<Len>, Type> *>(data)->data()) : nullptr);
}

}

#endif
<commit_msg>any: try to get around an issue with clang only<commit_after>#ifndef ENTT_CORE_ANY_HPP
#define ENTT_CORE_ANY_HPP

#include <cstddef>
#include <functional>
#include <new>
#include <type_traits>
#include <utility>
#include "../config/config.h"
#include "fwd.hpp"
#include "type_info.hpp"
#include "type_traits.hpp"

namespace entt {

/**
 * @brief A SBO friendly, type-safe container for single values of any type.
 * @tparam Len Size of the storage reserved for the small buffer optimization.
 */
template<std::size_t Len>
class basic_any {
    enum class operation { COPY, MOVE, DTOR, COMP, ADDR, CADDR, REF, CREF, TYPE };

    using storage_type = std::aligned_storage_t<Len == 0u ? 1u : Len>;
    using vtable_type = const void *(const operation, const basic_any &, const void *);

    template<typename Type>
    static constexpr bool in_situ = Len && sizeof(Type) <= sizeof(storage_type) && std::is_nothrow_move_constructible_v<Type>;

    template<typename Type>
    [[nodiscard]] static bool compare(const void *lhs, const void *rhs) {
        if constexpr(!std::is_function_v<Type> && is_equality_comparable_v<Type>) {
            return *static_cast<const Type *>(lhs) == *static_cast<const Type *>(rhs);
        } else {
            return lhs == rhs;
        }
    }

    template<typename Type>
    static Type & as(const void *to) {
        return *const_cast<Type *>(static_cast<const Type *>(to));
    }

    template<typename Type>
    static const void * basic_vtable([[maybe_unused]] const operation op, [[maybe_unused]] const basic_any &from, [[maybe_unused]] const void *to) {
        if constexpr(!std::is_void_v<Type>) {
            if constexpr(std::is_lvalue_reference_v<Type>) {
                using base_type = std::remove_const_t<std::remove_reference_t<Type>>;

                switch(op) {
                case operation::COPY:
                    if constexpr(std::is_copy_constructible_v<base_type>) {
                        as<basic_any>(to).template emplace<base_type>(*static_cast<const base_type *>(from.instance));
                    }
                    break;
                case operation::MOVE:
                    as<basic_any>(to).instance = from.instance;
                case operation::DTOR:
                    break;
                case operation::COMP:
                    return compare<base_type>(from.instance, to) ? to : nullptr;
                case operation::ADDR:
                    return std::is_const_v<std::remove_reference_t<Type>> ? nullptr : from.instance;
                case operation::CADDR:
                    return from.instance;
                case operation::REF:
                    as<basic_any>(to).instance = from.instance;
                    as<basic_any>(to).vtable = basic_vtable<Type>;
                    break;
                case operation::CREF:
                    as<basic_any>(to).instance = from.instance;
                    as<basic_any>(to).vtable = basic_vtable<const base_type &>;
                    break;
                case operation::TYPE:
                    as<type_info>(to) = type_id<base_type>();
                    break;
                }
            } else if constexpr(in_situ<Type>) {
                #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L
                auto *instance = const_cast<Type *>(std::launder(reinterpret_cast<const Type *>(&from.storage)));
                #else
                auto *instance = const_cast<Type *>(reinterpret_cast<const Type *>(&from.storage));
                #endif

                switch(op) {
                case operation::COPY:
                    if constexpr(std::is_copy_constructible_v<Type>) {
                        new (&as<basic_any>(to).storage) Type{std::as_const(*instance)};
                        as<basic_any>(to).vtable = from.vtable;
                    }
                    break;
                case operation::MOVE:
                    new (&as<basic_any>(to).storage) Type{std::move(*instance)};
                    [[fallthrough]];
                case operation::DTOR:
                    instance->~Type();
                    break;
                case operation::COMP:
                    return compare<Type>(instance, to) ? to : nullptr;
                case operation::ADDR:
                case operation::CADDR:
                    return instance;
                case operation::REF:
                    as<basic_any>(to).instance = instance;
                    as<basic_any>(to).vtable = basic_vtable<Type &>;
                    break;
                case operation::CREF:
                    as<basic_any>(to).instance = instance;
                    as<basic_any>(to).vtable = basic_vtable<const Type &>;
                    break;
                case operation::TYPE:
                    as<type_info>(to) = type_id<Type>();
                    break;
                }
            } else {
                switch(op) {
                case operation::COPY:
                    if constexpr(std::is_copy_constructible_v<Type>) {
                        as<basic_any>(to).instance = new Type{*static_cast<const Type *>(from.instance)};
                        as<basic_any>(to).vtable = from.vtable;
                    }
                    break;
                case operation::MOVE:
                    as<basic_any>(to).instance = from.instance;
                    break;
                case operation::DTOR:
                    if constexpr(std::is_array_v<Type>) {
                        delete[] static_cast<const Type *>(from.instance);
                    } else {
                        delete static_cast<const Type *>(from.instance);
                    }
                    break;
                case operation::COMP:
                    return compare<Type>(from.instance, to) ? to : nullptr;
                case operation::ADDR:
                case operation::CADDR:
                    return from.instance;
                case operation::REF:
                    as<basic_any>(to).instance = from.instance;
                    as<basic_any>(to).vtable = basic_vtable<Type &>;
                    break;
                case operation::CREF:
                    as<basic_any>(to).instance = from.instance;
                    as<basic_any>(to).vtable = basic_vtable<const Type &>;
                    break;
                case operation::TYPE:
                    as<type_info>(to) = type_id<Type>();
                    break;
                }
            }
        }

        return nullptr;
    }

public:
    /*! @brief Default constructor. */
    basic_any() ENTT_NOEXCEPT
        : basic_any{std::in_place_type<void>}
    {}

    /**
     * @brief Constructs an any by directly initializing the new object.
     * @tparam Type Type of object to use to initialize the wrapper.
     * @tparam Args Types of arguments to use to construct the new instance.
     * @param args Parameters to use to construct the instance.
     */
    template<typename Type, typename... Args>
    explicit basic_any(std::in_place_type_t<Type>, [[maybe_unused]] Args &&... args)
        : vtable{&basic_vtable<Type>},
          instance{}
    {
        if constexpr(!std::is_void_v<Type>) {
            if constexpr(std::is_lvalue_reference_v<Type>) {
                static_assert(sizeof...(Args) == 1u && (std::is_lvalue_reference_v<Args> && ...));
                instance = (&args, ...);
            } else if constexpr(in_situ<Type>) {
                new (&storage) Type(std::forward<Args>(args)...);
            } else {
                instance = new Type(std::forward<Args>(args)...);
            }
        }
    }

    /**
     * @brief Constructs an any that holds an unmanaged object.
     * @tparam Type Type of object to use to initialize the wrapper.
     * @param value An instance of an object to use to initialize the wrapper.
     */
    template<typename Type>
    basic_any(std::reference_wrapper<Type> value) ENTT_NOEXCEPT
        : basic_any{std::in_place_type<Type &>, value.get()}
    {}

    /**
     * @brief Constructs an any from a given value.
     * @tparam Type Type of object to use to initialize the wrapper.
     * @param value An instance of an object to use to initialize the wrapper.
     */
    template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, basic_any>>>
    basic_any(Type &&value)
        : basic_any{std::in_place_type<std::decay_t<Type>>, std::forward<Type>(value)}
    {}

    /**
     * @brief Copy constructor.
     * @param other The instance to copy from.
     */
    basic_any(const basic_any &other)
        : basic_any{}
    {
        other.vtable(operation::COPY, other, this);
    }

    /**
     * @brief Move constructor.
     * @param other The instance to move from.
     */
    basic_any(basic_any &&other) ENTT_NOEXCEPT
        : basic_any{}
    {
        other.vtable(operation::MOVE, other, this);
        vtable = std::exchange(other.vtable, &basic_vtable<void>);
    }

    /*! @brief Frees the internal storage, whatever it means. */
    ~basic_any() {
        vtable(operation::DTOR, *this, nullptr);
    }

    /**
     * @brief Assignment operator.
     * @param other The instance to assign from.
     * @return This any object.
     */
    basic_any & operator=(basic_any other) {
        swap(*this, other);
        return *this;
    }

    /**
     * @brief Returns the type of the contained object.
     * @return The type of the contained object, if any.
     */
    [[nodiscard]] type_info type() const ENTT_NOEXCEPT {
        type_info info;
        vtable(operation::TYPE, *this, &info);
        return info;
    }

    /**
     * @brief Returns an opaque pointer to the contained instance.
     * @return An opaque pointer the contained instance, if any.
     */
    [[nodiscard]] const void * data() const ENTT_NOEXCEPT {
        return vtable(operation::CADDR, *this, nullptr);
    }

    /*! @copydoc data */
    [[nodiscard]] void * data() ENTT_NOEXCEPT {
        return const_cast<void *>(vtable(operation::ADDR, *this, nullptr));
    }

    /**
     * @brief Replaces the contained object by creating a new instance directly.
     * @tparam Type Type of object to use to initialize the wrapper.
     * @tparam Args Types of arguments to use to construct the new instance.
     * @param args Parameters to use to construct the instance.
     */
    template<typename Type, typename... Args>
    void emplace(Args &&... args) {
        *this = basic_any{std::in_place_type<Type>, std::forward<Args>(args)...};
    }

    /*! @brief Destroys contained object */
    void reset() {
        *this = basic_any{};
    }

    /**
     * @brief Returns false if a wrapper is empty, true otherwise.
     * @return False if the wrapper is empty, true otherwise.
     */
    [[nodiscard]] explicit operator bool() const ENTT_NOEXCEPT {
        return !(vtable(operation::CADDR, *this, nullptr) == nullptr);
    }

    /**
     * @brief Checks if two wrappers differ in their content.
     * @param other Wrapper with which to compare.
     * @return False if the two objects differ in their content, true otherwise.
     */
    bool operator==(const basic_any &other) const ENTT_NOEXCEPT {
        return type() == other.type() && (vtable(operation::COMP, *this, other.data()) == other.data());
    }

    /**
     * @brief Swaps two any objects.
     * @param lhs A valid any object.
     * @param rhs A valid any object.
     */
    friend void swap(basic_any &lhs, basic_any &rhs) {
        basic_any tmp{};
        lhs.vtable(operation::MOVE, lhs, &tmp);
        rhs.vtable(operation::MOVE, rhs, &lhs);
        lhs.vtable(operation::MOVE, tmp, &rhs);
        std::swap(lhs.vtable, rhs.vtable);
    }

    /**
     * @brief Aliasing constructor.
     * @return An any that shares a reference to an unmanaged object.
     */
    [[nodiscard]] basic_any as_ref() ENTT_NOEXCEPT {
        basic_any ref{};
        vtable(operation::REF, *this, &ref);
        return ref;
    }

    /*! @copydoc as_ref */
    [[nodiscard]] basic_any as_ref() const ENTT_NOEXCEPT {
        basic_any ref{};
        vtable(operation::CREF, *this, &ref);
        return ref;
    }

private:
    vtable_type *vtable;
    union { const void *instance; storage_type storage{}; };
};

/**
 * @brief Checks if two wrappers differ in their content.
 * @tparam Len Size of the storage reserved for the small buffer optimization.
 * @param lhs A wrapper, either empty or not.
 * @param rhs A wrapper, either empty or not.
 * @return True if the two wrappers differ in their content, false otherwise.
 */
template<std::size_t Len>
[[nodiscard]] inline bool operator!=(const basic_any<Len> &lhs, const basic_any<Len> &rhs) ENTT_NOEXCEPT {
    return !(lhs == rhs);
}

/**
 * @brief Performs type-safe access to the contained object.
 * @tparam Len Size of the storage reserved for the small buffer optimization.
 * @tparam Type Type to which conversion is required.
 * @param data Target any object.
 * @return The element converted to the requested type.
 */
template<typename Type, std::size_t Len>
Type any_cast(const basic_any<Len> &data) ENTT_NOEXCEPT {
    const auto * const instance = any_cast<std::remove_reference_t<Type>>(&data);
    ENTT_ASSERT(instance);
    return static_cast<Type>(*instance);
}

/*! @copydoc any_cast */
template<typename Type, std::size_t Len>
Type any_cast(basic_any<Len> &data) ENTT_NOEXCEPT {
    // forces const on non-reference types to make them work also with wrappers for const references
    auto * const instance = any_cast<std::conditional_t<std::is_reference_v<Type>, std::remove_reference_t<Type>, const Type>>(&data);
    ENTT_ASSERT(instance);
    return static_cast<Type>(*instance);
}

/*! @copydoc any_cast */
template<typename Type, std::size_t Len>
Type any_cast(basic_any<Len> &&data) ENTT_NOEXCEPT {
    // forces const on non-reference types to make them work also with wrappers for const references
    auto * const instance = any_cast<std::conditional_t<std::is_reference_v<Type>, std::remove_reference_t<Type>, const Type>>(&data);
    ENTT_ASSERT(instance);
    return static_cast<Type>(std::move(*instance));
}

/*! @copydoc any_cast */
template<typename Type, std::size_t Len>
const Type * any_cast(const basic_any<Len> *data) ENTT_NOEXCEPT {
    return (data->type() == type_id<Type>() ? static_cast<const Type *>(data->data()) : nullptr);
}

/*! @copydoc any_cast */
template<typename Type, std::size_t Len>
Type * any_cast(basic_any<Len> *data) ENTT_NOEXCEPT {
    // last attempt to make wrappers for const references return their values
    return (data->type() == type_id<Type>() ? static_cast<Type *>(static_cast<constness_as_t<basic_any<Len>, Type> *>(data)->data()) : nullptr);
}

}

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2009-2012 The Bitcoin developers
// Copyright (c) 2011-2012 Litecoin Developers
// Copyright (c) 2013 Florincoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <boost/assign/list_of.hpp> // for 'map_list_of()'
#include <boost/foreach.hpp>

#include "checkpoints.h"

#include "main.h"
#include "uint256.h"

namespace Checkpoints
{
    typedef std::map<int, uint256> MapCheckpoints;

    //
    // What makes a good checkpoint block?
    // + Is surrounded by blocks with reasonable timestamps
    //   (no blocks before with a timestamp after, none after with
    //    timestamp before)
    // + Contains no strange transactions
    //
    static MapCheckpoints mapCheckpoints =
        boost::assign::map_list_of
        (     0, hashGenesisBlock)
        (  8002, uint256("0x73bc3b16d99bbf797f396c9532f80c3b73bb21304280de2efbc5edcb75739234"))
        ( 18001, uint256("0x5a7a4821aa4fc7ee3dea2f8319e9fa4d991a8c6762e79cb624c64e4cf1031582"))
        ( 38002, uint256("0x4962437c6d0a450f44c1e40cd38ff220f8122af1517e1329f1abd07fb7791e40"))
        (160002, uint256("0x478d381c92298614c3a05fb934a4fffc4d3e5b573efbba9b3e8b2ce8d26a0f8f"))
        (208001, uint256("0x2bb3f8b2d5081aefa0af9f5d8de42bd73a5d89eebf78aa7421cd63dc40a56d4c"))
        (270001, uint256("0x74988a3179ae6bbc5986e63f71bafc855202502b07e4d9331015eee82df80860"))
        (290036, uint256("0x145994381e5e4f0e5674adc1ace9a03b670838792f6bd6b650c80466453c2da3"))
        (344665, uint256("0x40fe36d8dec357aa529b6b1d99b2989a37ed8c7b065a0e3345cd15a751b9c1ad"))
        (400236, uint256("0xf9a4b8e21d410539e45ff3f11c28dee8966de7edffc45fd02dd1a5f4e7d4ef38"))
        (415000, uint256("0x16ef8ab98a7300039a5755d5bdc00e31dada9d2f1c440ff7928f43c4ea41c0a8"))
        (420937, uint256("0x48a75e4687021ec0dda2031439de50b61933e197a4e1a1185d131cc2b59b8444"))
        ;

    bool CheckBlock(int nHeight, const uint256& hash)
    {
        if (fTestNet) return true; // Testnet has no checkpoints

        MapCheckpoints::const_iterator i = mapCheckpoints.find(nHeight);
        if (i == mapCheckpoints.end()) return true;
        return hash == i->second;
    }

    int GetTotalBlocksEstimate()
    {
        if (fTestNet) return 0;

        return mapCheckpoints.rbegin()->first;
    }

    CBlockIndex* GetLastCheckpoint(const std::map<uint256, CBlockIndex*>& mapBlockIndex)
    {
        if (fTestNet) return NULL;

        BOOST_REVERSE_FOREACH(const MapCheckpoints::value_type& i, mapCheckpoints)
        {
            const uint256& hash = i.second;
            std::map<uint256, CBlockIndex*>::const_iterator t = mapBlockIndex.find(hash);
            if (t != mapBlockIndex.end())
                return t->second;
        }
        return NULL;
    }
}
<commit_msg>Checkpoint<commit_after>// Copyright (c) 2009-2012 The Bitcoin developers
// Copyright (c) 2011-2012 Litecoin Developers
// Copyright (c) 2013 Florincoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <boost/assign/list_of.hpp> // for 'map_list_of()'
#include <boost/foreach.hpp>

#include "checkpoints.h"

#include "main.h"
#include "uint256.h"

namespace Checkpoints
{
    typedef std::map<int, uint256> MapCheckpoints;

    //
    // What makes a good checkpoint block?
    // + Is surrounded by blocks with reasonable timestamps
    //   (no blocks before with a timestamp after, none after with
    //    timestamp before)
    // + Contains no strange transactions
    //
    static MapCheckpoints mapCheckpoints =
        boost::assign::map_list_of
        (     0, hashGenesisBlock)
        (  8002, uint256("0x73bc3b16d99bbf797f396c9532f80c3b73bb21304280de2efbc5edcb75739234"))
        ( 18001, uint256("0x5a7a4821aa4fc7ee3dea2f8319e9fa4d991a8c6762e79cb624c64e4cf1031582"))
        ( 38002, uint256("0x4962437c6d0a450f44c1e40cd38ff220f8122af1517e1329f1abd07fb7791e40"))
        (160002, uint256("0x478d381c92298614c3a05fb934a4fffc4d3e5b573efbba9b3e8b2ce8d26a0f8f"))
        (208001, uint256("0x2bb3f8b2d5081aefa0af9f5d8de42bd73a5d89eebf78aa7421cd63dc40a56d4c"))
        (270001, uint256("0x74988a3179ae6bbc5986e63f71bafc855202502b07e4d9331015eee82df80860"))
        (290036, uint256("0x145994381e5e4f0e5674adc1ace9a03b670838792f6bd6b650c80466453c2da3"))
        (344665, uint256("0x40fe36d8dec357aa529b6b1d99b2989a37ed8c7b065a0e3345cd15a751b9c1ad"))
        (400236, uint256("0xf9a4b8e21d410539e45ff3f11c28dee8966de7edffc45fd02dd1a5f4e7d4ef38"))
        (415000, uint256("0x16ef8ab98a7300039a5755d5bdc00e31dada9d2f1c440ff7928f43c4ea41c0a8"))
        (420937, uint256("0x48a75e4687021ec0dda2031439de50b61933e197a4e1a1185d131cc2b59b8444"))
        (425606, uint256("0x62c8d811b1a49f6fdaffded704dc48b1c98d6f8dd736d8afb96c9b097774a85e"))
        ;

    bool CheckBlock(int nHeight, const uint256& hash)
    {
        if (fTestNet) return true; // Testnet has no checkpoints

        MapCheckpoints::const_iterator i = mapCheckpoints.find(nHeight);
        if (i == mapCheckpoints.end()) return true;
        return hash == i->second;
    }

    int GetTotalBlocksEstimate()
    {
        if (fTestNet) return 0;

        return mapCheckpoints.rbegin()->first;
    }

    CBlockIndex* GetLastCheckpoint(const std::map<uint256, CBlockIndex*>& mapBlockIndex)
    {
        if (fTestNet) return NULL;

        BOOST_REVERSE_FOREACH(const MapCheckpoints::value_type& i, mapCheckpoints)
        {
            const uint256& hash = i.second;
            std::map<uint256, CBlockIndex*>::const_iterator t = mapBlockIndex.find(hash);
            if (t != mapBlockIndex.end())
                return t->second;
        }
        return NULL;
    }
}
<|endoftext|>


<commit_before>#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "../test_utils.h"

#include <babylon/babylon_stl_util.h>
#include <babylon/engines/scene.h>
#include <babylon/meshes/buffer.h>
#include <babylon/meshes/geometry.h>
#include <babylon/meshes/vertex_buffer.h>

TEST(TestGeometry, TestGetVerticesData_Vec3FloatColor)
{
  using namespace BABYLON;
  // vec3 float color tightly packed
  auto subject = createSubject();
  auto scene   = Scene::New(subject.get());
  Float32Array data{0.4f, 0.4f, 0.4f, 0.6f, 0.6f, 0.6f,
                    0.8f, 0.8f, 0.8f, 1.f,  1.f,  1.f};
  auto buffer       = std::make_unique<Buffer>(subject.get(), data, false);
  auto vertexBuffer = std::make_shared<VertexBuffer>(
    subject.get(), buffer.get(), VertexBuffer::ColorKind, false, std::nullopt,
    std::nullopt, std::nullopt, std::nullopt, 3);

  auto geometry = Geometry::New("geometry1", scene.get());
  geometry->setVerticesBuffer(vertexBuffer);
  IndicesArray indices{0u, 1u, 2u, 3u};
  geometry->setIndices(indices, 4);

  auto result = geometry->getVerticesData(VertexBuffer::ColorKind);
  EXPECT_THAT(result, ::testing::ContainerEq(data));
}
<commit_msg>Formatted Geometry test<commit_after>#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "../test_utils.h"

#include <babylon/babylon_stl_util.h>
#include <babylon/engines/scene.h>
#include <babylon/meshes/buffer.h>
#include <babylon/meshes/geometry.h>
#include <babylon/meshes/vertex_buffer.h>

TEST(TestGeometry, TestGetVerticesData_Vec3FloatColor)
{
  using namespace BABYLON;
  // vec3 float color tightly packed
  auto subject = createSubject();
  auto scene   = Scene::New(subject.get());
  Float32Array data{0.4f, 0.4f, 0.4f, 0.6f, 0.6f, 0.6f, 0.8f, 0.8f, 0.8f, 1.f, 1.f, 1.f};
  auto buffer = std::make_unique<Buffer>(subject.get(), data, false);
  auto vertexBuffer
    = std::make_shared<VertexBuffer>(subject.get(), buffer.get(), VertexBuffer::ColorKind, false,
                                     std::nullopt, std::nullopt, std::nullopt, std::nullopt, 3);

  auto geometry = Geometry::New("geometry1", scene.get());
  geometry->setVerticesBuffer(vertexBuffer);
  IndicesArray indices{0u, 1u, 2u, 3u};
  geometry->setIndices(indices, 4);

  auto result = geometry->getVerticesData(VertexBuffer::ColorKind);
  EXPECT_THAT(result, ::testing::ContainerEq(data));
}
<|endoftext|>


<commit_before>// $Id: shiftModule.C,v 1.7 2000/09/20 11:16:09 oliver Exp $

#include<BALL/NMR/shiftModule.h>

using namespace std;

namespace BALL
{

	const char* ShiftModule::PROPERTY__SHIFT = "ChemicalShift";

	ShiftModule::ShiftModule()
		throw()
		:	module_name_(""),
			parameters_(0)
	{
	}

	ShiftModule::~ShiftModule()
		throw()
	{
	}

	ShiftModule::ShiftModule(Parameters& parameters, const String& name)
		throw()
		:	module_name_(name),
			parameters_(&parameters)
	{
	}

	ShiftModule::ShiftModule(const ShiftModule& module)
		throw()
		:	UnaryProcessor<Composite>(module),
			module_name_(module.module_name_),
			parameters_(module.parameters_)
	{
	}

	void ShiftModule::clear()
		throw()
	{
		module_name_ = "";
		parameters_ = 0;
	}

	void ShiftModule::init()
		throw()
	{
		// empty method
	}

	const ShiftModule& ShiftModule::operator = (const ShiftModule& module)
		throw()
	{
		module_name_ = module.module_name_;
		parameters_ = module.parameters_;

		return *this;
	}

	void ShiftModule::setName(const String& name)
		throw()
	{
		module_name_ = name;
	}

	const String& ShiftModule::getName() const
		throw()
	{
		return module_name_;
	}

	void ShiftModule::setParameters(Parameters& parameters)
		throw()
	{
		parameters_ = &parameters;
	}

	const Parameters* ShiftModule::getParameters() const
		throw()
	{
		return parameters_;
	}

}	// namespace BALL
<commit_msg>added: isValid/valid_ added: dummy implementations for start/finish<commit_after>// $Id: shiftModule.C,v 1.8 2000/09/21 13:48:04 oliver Exp $

#include<BALL/NMR/shiftModule.h>

using namespace std;

namespace BALL
{

	const char* ShiftModule::PROPERTY__SHIFT = "ChemicalShift";

	ShiftModule::ShiftModule()
		throw()
		:	module_name_(""),
			parameters_(0),
			valid_(false)
	{
	}

	ShiftModule::~ShiftModule()
		throw()
	{
	}

	ShiftModule::ShiftModule(Parameters& parameters, const String& name)
		throw()
		:	module_name_(name),
			parameters_(&parameters),
			valid_(false)
	{
	}

	ShiftModule::ShiftModule(const ShiftModule& module)
		throw()
		:	UnaryProcessor<Composite>(module),
			module_name_(module.module_name_),
			parameters_(module.parameters_),
			valid_(module.valid_)
	{
	}

	void ShiftModule::clear()
		throw()
	{
		module_name_ = "";
		parameters_ = 0;
		valid_ = false;
	}

	void ShiftModule::init()
		throw()
	{
		// empty method
	}

	const ShiftModule& ShiftModule::operator = (const ShiftModule& module)
		throw()
	{
		module_name_ = module.module_name_;
		parameters_ = module.parameters_;
		valid_ = module.valid_;

		return *this;
	}

	void ShiftModule::setName(const String& name)
		throw()
	{
		module_name_ = name;
	}

	const String& ShiftModule::getName() const
		throw()
	{
		return module_name_;
	}

	void ShiftModule::setParameters(Parameters& parameters)
		throw()
	{
		parameters_ = &parameters;
		valid_ = false;
	}

	const Parameters* ShiftModule::getParameters() const
		throw()
	{
		return parameters_;
	}

	bool ShiftModule::start()
		throw()
	{
		// abort if the module was not correctly initialized
		return valid_;
	}

	bool ShiftModule::finish()
		throw()
	{
		// abort if the module was not correctly initialized
		return valid_;
	}

	bool ShiftModule::isValid() const
		throw()
	{
		return valid_;
	}

}	// namespace BALL
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2008-2009, Thomas Jaeger <ThJaeger@gmail.com>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
#include "prefdb.h"
#include "main.h"
#include "win.h"
#include <glibmm/i18n.h>

#include <fstream>
#include <iostream>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/set.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/export.hpp>

const ButtonInfo default_button(Button2);
const int default_pressure_threshold = 192;

PrefDB::PrefDB() :
	TimeoutWatcher(5000),
	good_state(true),
	button(default_button),
	trace(TraceDefault),
	advanced_ignore(false),
	ignore_grab(false),
	timing_workaround(false),
	pressure_abort(false),
	pressure_threshold(default_pressure_threshold),
	proximity(false),
	feedback(true),
	left_handed(false),
	init_timeout(250),
	final_timeout(250),
	timeout_profile(TimeoutDefault),
	timeout_gestures(false),
	tray_icon(true),
	color(Gdk::Color("#980101")),
	trace_width(5),
	advanced_popups(true),
	scroll_invert(true),
	scroll_speed(2.0),
	tray_feedback(false),
	show_osd(true)
{}

template<class Archive> void PrefDB::serialize(Archive & ar, const unsigned int version) {
	if (version < 11) {
		std::set<std::string> old;
		ar & old;
		for (std::set<std::string>::iterator i = old.begin(); i != old.end(); i++)
			exceptions.unsafe_ref()[*i] = RButtonInfo();
	} else ar & exceptions.unsafe_ref();
	if (version < 14) {
		double p = 0.5;
		ar & p;
	}
	ar & button.unsafe_ref();
	if (version < 2) {
		bool help;
		ar & help;
	}
	ar & trace.unsafe_ref();
	if (trace.get() == TraceShape)
		trace.unsafe_ref() = TraceDefault;
	if (version < 3) {
		int delay;
		ar & delay;
	}
	if (version == 1) {
		ButtonInfo foo;
		ar & foo;
		ar & foo;
		return;
	}
	if (version < 2) return;
	if (version != 6)
		ar & advanced_ignore.unsafe_ref();
	int radius = 16;
	ar & radius;
	if (version < 4) return;
	ar & ignore_grab.unsafe_ref();
	ar & timing_workaround.unsafe_ref();
	bool show_clicks = false;
	ar & show_clicks;
	ar & pressure_abort.unsafe_ref();
	ar & pressure_threshold.unsafe_ref();
	ar & proximity.unsafe_ref();
	if (version < 5) return;
	ar & feedback.unsafe_ref();
	ar & left_handed.unsafe_ref();
	ar & init_timeout.unsafe_ref();
	ar & final_timeout.unsafe_ref();
	if (version < 8) return;
	ar & timeout_profile.unsafe_ref();
	if (version < 9) return;
	ar & timeout_gestures.unsafe_ref();
	ar & tray_icon.unsafe_ref();
	if (version < 10) return;
	ar & excluded_devices.unsafe_ref();
	if (version < 12) {
		unsigned long c = 0;
		ar & c;
		color.unsafe_ref().color.set_rgb(257*(c >> 16), 257*((c >> 8) % 256), 257*(c % 256));
		return;
	} else {
		ar & color.unsafe_ref();
	}
	ar & trace_width.unsafe_ref();
	if (version < 13) return;
	ar & extra_buttons.unsafe_ref();
	ar & advanced_popups.unsafe_ref();
	ar & scroll_invert.unsafe_ref();
	ar & scroll_speed.unsafe_ref();
	ar & tray_feedback.unsafe_ref();
}

void PrefDB::timeout() {
	std::string filename = config_dir+"preferences"+versions[0];
	std::string tmp = filename + ".tmp";
	try {
		std::ofstream ofs(tmp.c_str());
		boost::archive::text_oarchive oa(ofs);
		const PrefDB *me = this;
		oa << *me;
		if (rename(tmp.c_str(), filename.c_str()))
			throw std::runtime_error("rename() failed");
		if (verbosity >= 2)
			printf("Saved preferences.\n");
	} catch (std::exception &e) {
		printf(_("Error: Couldn't save preferences: %s.\n"), e.what());
		if (!good_state)
			return;
		good_state = false;
		error_dialog(Glib::ustring::compose(_( "Couldn't save %1.  Your changes will be lost.  "
				"Make sure that \"%2\" is a directory and that you have write access to it.  "
				"You can change the configuration directory "
				"using the -c or --config-dir command line options."), _("preferences"), config_dir));
	}
}

bool ButtonInfo::overlap(const ButtonInfo &bi) const {
	if (button != bi.button)
		return false;
	if (state == AnyModifier || bi.state == AnyModifier)
		return true;
	return !((state ^ bi.state) & ~LockMask & ~Mod2Mask);
}

class TimeoutProfile : private Base {
	Out<TimeoutType> ∈
public:
	virtual void notify() {
		switch (in.get()) {
			case TimeoutOff:
				prefs.init_timeout.set(0);
				prefs.final_timeout.set(0);
				break;
			case TimeoutConservative:
				prefs.init_timeout.set(750);
				prefs.final_timeout.set(750);
				break;
			case TimeoutDefault:
				prefs.init_timeout.set(250);
				prefs.final_timeout.set(250);
				break;
			case TimeoutMedium:
				prefs.init_timeout.set(100);
				prefs.final_timeout.set(100);
				break;
			case TimeoutAggressive:
				prefs.init_timeout.set(50);
				prefs.final_timeout.set(75);
				break;
			case TimeoutFlick:
				prefs.init_timeout.set(30);
				prefs.final_timeout.set(50);
				break;
			case TimeoutCustom:
				break;
		}
	}
	TimeoutProfile(Out<TimeoutType> &in_) : in(in_) {
		in.connect(this);
		notify();
	}
};

void PrefDB::init() {
	std::string filename = config_dir+"preferences";
	for (const char **v = versions; *v; v++) {
		if (is_file(filename + *v)) {
			filename += *v;
			try {
				std::ifstream ifs(filename.c_str(), std::ios::binary);
				if (!ifs.fail()) {
					boost::archive::text_iarchive ia(ifs);
					ia >> *this;
					if (verbosity >= 2)
						std::cout << "Loaded preferences." << std::endl;
				}
			} catch (...) {
				printf(_("Error: Couldn't read preferences.\n"));
			}
			break;
		}
	}
	std::map<std::string, RButtonInfo>::iterator i = exceptions.unsafe_ref().find("(window manager frame)");
	if (i != exceptions.unsafe_ref().end()) {
		RButtonInfo bi = i->second;
		exceptions.unsafe_ref().erase(i);
		exceptions.unsafe_ref()[""] = bi;
	}
	new TimeoutProfile(prefs.timeout_profile);
}

PrefDB prefs;
<commit_msg>Actually save OSD preference<commit_after>/*
 * Copyright (c) 2008-2009, Thomas Jaeger <ThJaeger@gmail.com>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
#include "prefdb.h"
#include "main.h"
#include "win.h"
#include <glibmm/i18n.h>

#include <fstream>
#include <iostream>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/set.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/export.hpp>

const ButtonInfo default_button(Button2);
const int default_pressure_threshold = 192;

PrefDB::PrefDB() :
	TimeoutWatcher(5000),
	good_state(true),
	button(default_button),
	trace(TraceDefault),
	advanced_ignore(false),
	ignore_grab(false),
	timing_workaround(false),
	pressure_abort(false),
	pressure_threshold(default_pressure_threshold),
	proximity(false),
	feedback(true),
	left_handed(false),
	init_timeout(250),
	final_timeout(250),
	timeout_profile(TimeoutDefault),
	timeout_gestures(false),
	tray_icon(true),
	color(Gdk::Color("#980101")),
	trace_width(5),
	advanced_popups(true),
	scroll_invert(true),
	scroll_speed(2.0),
	tray_feedback(false),
	show_osd(true)
{}

template<class Archive> void PrefDB::serialize(Archive & ar, const unsigned int version) {
	if (version < 11) {
		std::set<std::string> old;
		ar & old;
		for (std::set<std::string>::iterator i = old.begin(); i != old.end(); i++)
			exceptions.unsafe_ref()[*i] = RButtonInfo();
	} else ar & exceptions.unsafe_ref();
	if (version < 14) {
		double p = 0.5;
		ar & p;
	}
	ar & button.unsafe_ref();
	if (version < 2) {
		bool help;
		ar & help;
	}
	ar & trace.unsafe_ref();
	if (trace.get() == TraceShape)
		trace.unsafe_ref() = TraceDefault;
	if (version < 3) {
		int delay;
		ar & delay;
	}
	if (version == 1) {
		ButtonInfo foo;
		ar & foo;
		ar & foo;
		return;
	}
	if (version < 2) return;
	if (version != 6)
		ar & advanced_ignore.unsafe_ref();
	int radius = 16;
	ar & radius;
	if (version < 4) return;
	ar & ignore_grab.unsafe_ref();
	ar & timing_workaround.unsafe_ref();
	bool show_clicks = false;
	ar & show_clicks;
	ar & pressure_abort.unsafe_ref();
	ar & pressure_threshold.unsafe_ref();
	ar & proximity.unsafe_ref();
	if (version < 5) return;
	ar & feedback.unsafe_ref();
	ar & left_handed.unsafe_ref();
	ar & init_timeout.unsafe_ref();
	ar & final_timeout.unsafe_ref();
	if (version < 8) return;
	ar & timeout_profile.unsafe_ref();
	if (version < 9) return;
	ar & timeout_gestures.unsafe_ref();
	ar & tray_icon.unsafe_ref();
	if (version < 10) return;
	ar & excluded_devices.unsafe_ref();
	if (version < 12) {
		unsigned long c = 0;
		ar & c;
		color.unsafe_ref().color.set_rgb(257*(c >> 16), 257*((c >> 8) % 256), 257*(c % 256));
		return;
	} else {
		ar & color.unsafe_ref();
	}
	ar & trace_width.unsafe_ref();
	if (version < 13) return;
	ar & extra_buttons.unsafe_ref();
	ar & advanced_popups.unsafe_ref();
	ar & scroll_invert.unsafe_ref();
	ar & scroll_speed.unsafe_ref();
	ar & tray_feedback.unsafe_ref();
	ar & show_osd.unsafe_ref();
}

void PrefDB::timeout() {
	std::string filename = config_dir+"preferences"+versions[0];
	std::string tmp = filename + ".tmp";
	try {
		std::ofstream ofs(tmp.c_str());
		boost::archive::text_oarchive oa(ofs);
		const PrefDB *me = this;
		oa << *me;
		if (rename(tmp.c_str(), filename.c_str()))
			throw std::runtime_error("rename() failed");
		if (verbosity >= 2)
			printf("Saved preferences.\n");
	} catch (std::exception &e) {
		printf(_("Error: Couldn't save preferences: %s.\n"), e.what());
		if (!good_state)
			return;
		good_state = false;
		error_dialog(Glib::ustring::compose(_( "Couldn't save %1.  Your changes will be lost.  "
				"Make sure that \"%2\" is a directory and that you have write access to it.  "
				"You can change the configuration directory "
				"using the -c or --config-dir command line options."), _("preferences"), config_dir));
	}
}

bool ButtonInfo::overlap(const ButtonInfo &bi) const {
	if (button != bi.button)
		return false;
	if (state == AnyModifier || bi.state == AnyModifier)
		return true;
	return !((state ^ bi.state) & ~LockMask & ~Mod2Mask);
}

class TimeoutProfile : private Base {
	Out<TimeoutType> ∈
public:
	virtual void notify() {
		switch (in.get()) {
			case TimeoutOff:
				prefs.init_timeout.set(0);
				prefs.final_timeout.set(0);
				break;
			case TimeoutConservative:
				prefs.init_timeout.set(750);
				prefs.final_timeout.set(750);
				break;
			case TimeoutDefault:
				prefs.init_timeout.set(250);
				prefs.final_timeout.set(250);
				break;
			case TimeoutMedium:
				prefs.init_timeout.set(100);
				prefs.final_timeout.set(100);
				break;
			case TimeoutAggressive:
				prefs.init_timeout.set(50);
				prefs.final_timeout.set(75);
				break;
			case TimeoutFlick:
				prefs.init_timeout.set(30);
				prefs.final_timeout.set(50);
				break;
			case TimeoutCustom:
				break;
		}
	}
	TimeoutProfile(Out<TimeoutType> &in_) : in(in_) {
		in.connect(this);
		notify();
	}
};

void PrefDB::init() {
	std::string filename = config_dir+"preferences";
	for (const char **v = versions; *v; v++) {
		if (is_file(filename + *v)) {
			filename += *v;
			try {
				std::ifstream ifs(filename.c_str(), std::ios::binary);
				if (!ifs.fail()) {
					boost::archive::text_iarchive ia(ifs);
					ia >> *this;
					if (verbosity >= 2)
						std::cout << "Loaded preferences." << std::endl;
				}
			} catch (...) {
				printf(_("Error: Couldn't read preferences.\n"));
			}
			break;
		}
	}
	std::map<std::string, RButtonInfo>::iterator i = exceptions.unsafe_ref().find("(window manager frame)");
	if (i != exceptions.unsafe_ref().end()) {
		RButtonInfo bi = i->second;
		exceptions.unsafe_ref().erase(i);
		exceptions.unsafe_ref()[""] = bi;
	}
	new TimeoutProfile(prefs.timeout_profile);
}

PrefDB prefs;
<|endoftext|>


<commit_before>#include "ssnes_dsp.h"
#include <iostream>
#include "abstract_plugin.hpp"
#include <math.h>

struct PlugVolume : public AbstractPlugin
{
   PlugVolume()
   {
      PluginOption opt = {0};

      opt.type = PluginOption::Type::Double;
      opt.id = VOLUME;
      opt.description = "Volume";
      opt.d.min = -80.0;
      opt.d.max = +24.0;
      opt.d.current = 0.0;
      dsp_options.push_back(opt);

      opt.type = PluginOption::Type::Integer;
      opt.id = PAN;
      opt.description = "Pan";
      opt.i.min = -100;
      opt.i.max = 100;
      opt.i.current = 0;
      dsp_options.push_back(opt);

      m_vol = 1.0;
      m_pan_vol_l = 1.0;
      m_pan_vol_r = 1.0;
   }

   enum IDs : PluginOption::ID { VOLUME, PAN };
   enum SelIDs : PluginOption::ID { FOO1, FOO2, FOO3 };

   void set_option_double(PluginOption::ID id, double val)
   {
      switch (id)
      {
         case VOLUME:
            m_vol = db2gain(val);
            break;

         default:
            std::cerr << "Err ..." << std::endl;
      }
   }

   void set_option_int(PluginOption::ID id, int val)
   {
      switch (id)
      {
         case PAN:
            pan2gain(m_pan_vol_l, m_pan_vol_r, val);

         default:
            std::cerr << "Err ..." << std::endl;
      }
   }

#ifdef __GNUC__
   float buf[4096] __attribute__((aligned(16)));
#else
   float buf[4096];
#endif

   void process(const float *in, unsigned frames)
   {
      float vol_left = m_vol * m_pan_vol_l;
      float vol_right = m_vol * m_pan_vol_r;
      for (unsigned i = 0; i < frames; i++)
      {
         buf[(i << 1) + 0] = in[(i << 1) + 0] * vol_left;
         buf[(i << 1) + 1] = in[(i << 1) + 1] * vol_right;
      }
   }

   float m_vol;
   float m_pan_vol_l;
   float m_pan_vol_r;

   static float db2gain(float val)
   {
      return powf(10.0, val / 20.0);
   }

   static void pan2gain(float &left, float &right, int val)
   {
      left = (100 - val) / 100.0f;
      right = (val + 100) / 100.0f;
      if (left > 1.0)
         left = 1.0;
      if (right > 1.0)
         right = 1.0;
   }
};

static void *dsp_init(const ssnes_dsp_info_t *)
{
   return new PlugVolume;
}

static void dsp_process(void *data, ssnes_dsp_output_t *output,
      const ssnes_dsp_input *input)
{
   PlugVolume *vol = reinterpret_cast<PlugVolume*>(data);

   output->samples = vol->buf;
   vol->process(input->samples, input->frames);
   output->frames = input->frames;
   output->should_resample = SSNES_TRUE;
}

static void dsp_free(void *data)
{
   delete reinterpret_cast<PlugVolume*>(data);
}

static void dsp_config(void *)
{}

const ssnes_dsp_plugin_t dsp_plug = {
   dsp_init,
   dsp_process,
   dsp_free,
   SSNES_DSP_API_VERSION,
   dsp_config,
   "Volume plugin"
};

SSNES_API_EXPORT const ssnes_dsp_plugin_t* SSNES_API_CALLTYPE ssnes_dsp_plugin_init(void)
{
   return &dsp_plug;
}

<commit_msg>Fix message.<commit_after>#include "ssnes_dsp.h"
#include <iostream>
#include "abstract_plugin.hpp"
#include <math.h>

struct PlugVolume : public AbstractPlugin
{
   PlugVolume()
   {
      PluginOption opt = {0};

      opt.type = PluginOption::Type::Double;
      opt.id = VOLUME;
      opt.description = "Volume";
      opt.d.min = -80.0;
      opt.d.max = +24.0;
      opt.d.current = 0.0;
      dsp_options.push_back(opt);

      opt.type = PluginOption::Type::Integer;
      opt.id = PAN;
      opt.description = "Pan";
      opt.i.min = -100;
      opt.i.max = 100;
      opt.i.current = 0;
      dsp_options.push_back(opt);

      m_vol = 1.0;
      m_pan_vol_l = 1.0;
      m_pan_vol_r = 1.0;
   }

   enum IDs : PluginOption::ID { VOLUME, PAN };
   enum SelIDs : PluginOption::ID { FOO1, FOO2, FOO3 };

   void set_option_double(PluginOption::ID id, double val)
   {
      switch (id)
      {
         case VOLUME:
            m_vol = db2gain(val);
            break;

         default:
            std::cerr << "Err ..." << std::endl;
      }
   }

   void set_option_int(PluginOption::ID id, int val)
   {
      switch (id)
      {
         case PAN:
            pan2gain(m_pan_vol_l, m_pan_vol_r, val);
            break;

         default:
            std::cerr << "Err ..." << std::endl;
      }
   }

#ifdef __GNUC__
   float buf[4096] __attribute__((aligned(16)));
#else
   float buf[4096];
#endif

   void process(const float *in, unsigned frames)
   {
      float vol_left = m_vol * m_pan_vol_l;
      float vol_right = m_vol * m_pan_vol_r;
      for (unsigned i = 0; i < frames; i++)
      {
         buf[(i << 1) + 0] = in[(i << 1) + 0] * vol_left;
         buf[(i << 1) + 1] = in[(i << 1) + 1] * vol_right;
      }
   }

   float m_vol;
   float m_pan_vol_l;
   float m_pan_vol_r;

   static float db2gain(float val)
   {
      return powf(10.0, val / 20.0);
   }

   static void pan2gain(float &left, float &right, int val)
   {
      left = (100 - val) / 100.0f;
      right = (val + 100) / 100.0f;
      if (left > 1.0)
         left = 1.0;
      if (right > 1.0)
         right = 1.0;
   }
};

static void *dsp_init(const ssnes_dsp_info_t *)
{
   return new PlugVolume;
}

static void dsp_process(void *data, ssnes_dsp_output_t *output,
      const ssnes_dsp_input *input)
{
   PlugVolume *vol = reinterpret_cast<PlugVolume*>(data);

   output->samples = vol->buf;
   vol->process(input->samples, input->frames);
   output->frames = input->frames;
   output->should_resample = SSNES_TRUE;
}

static void dsp_free(void *data)
{
   delete reinterpret_cast<PlugVolume*>(data);
}

static void dsp_config(void *)
{}

const ssnes_dsp_plugin_t dsp_plug = {
   dsp_init,
   dsp_process,
   dsp_free,
   SSNES_DSP_API_VERSION,
   dsp_config,
   "Volume plugin"
};

SSNES_API_EXPORT const ssnes_dsp_plugin_t* SSNES_API_CALLTYPE ssnes_dsp_plugin_init(void)
{
   return &dsp_plug;
}

<|endoftext|>


<commit_before>#ifdef LEGACY_LINUX

// Wrappers for eventfd(), since CentOS backported the system
// calls but not the libc wrappers.

#include "arch/linux/system_event/eventfd.hpp"
#include "utils.hpp"
#include <sys/syscall.h>

int eventfd(int count, int flags) {
    rassert(flags == 0); // Legacy kernel doesn't have eventfd2.
    return syscall(SYS_eventfd, count);
}

int eventfd_read(int fd, eventfd_t *value) {
    int res = read(fd, value, sizeof(eventfd_t));
    return (res == sizeof(eventfd_t)) ? 0 : -1;
}

int eventfd_write(int fd, eventfd_t value) {
  int res = write(fd, &value, sizeof(eventfd_t));
  return (res == sizeof(eventfd_t)) ? 0 : -1;
}

#endif
<commit_msg>Fix a compiler error glitch with some bullshit.<commit_after>#ifdef LEGACY_LINUX

// Wrappers for eventfd(), since CentOS backported the system
// calls but not the libc wrappers.

#include "arch/linux/system_event/eventfd.hpp"
#include "utils.hpp"
#include <sys/syscall.h>

int eventfd(int count, UNUSED int flags) {
    rassert(flags == 0); // Legacy kernel doesn't have eventfd2.
    return syscall(SYS_eventfd, count);
}

int eventfd_read(int fd, eventfd_t *value) {
    int res = read(fd, value, sizeof(eventfd_t));
    return (res == sizeof(eventfd_t)) ? 0 : -1;
}

int eventfd_write(int fd, eventfd_t value) {
  int res = write(fd, &value, sizeof(eventfd_t));
  return (res == sizeof(eventfd_t)) ? 0 : -1;
}

#endif
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkSquarifyLayoutStrategy.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
/*-------------------------------------------------------------------------
  Copyright 2008 Sandia Corporation.
  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
  the U.S. Government retains certain rights in this software.
-------------------------------------------------------------------------*/
#include "vtkSquarifyLayoutStrategy.h"

#include "vtkDataArray.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkPoints.h"
#include "vtkTree.h"

vtkCxxRevisionMacro(vtkSquarifyLayoutStrategy, "1.8");
vtkStandardNewMacro(vtkSquarifyLayoutStrategy);

vtkSquarifyLayoutStrategy::vtkSquarifyLayoutStrategy()
{
}

vtkSquarifyLayoutStrategy::~vtkSquarifyLayoutStrategy()
{
}

void vtkSquarifyLayoutStrategy::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
}

void vtkSquarifyLayoutStrategy::Layout(
    vtkTree* inputTree,
    vtkDataArray* coordsArray,
    vtkDataArray* sizeArray)
{
  if (!inputTree)
    {
    return;
    }
  if (!coordsArray)
    {
    vtkErrorMacro("Area array undefined");
    return;
    }

  // Get the root vertex and set it to 0,1,0,1
  vtkIdType rootId = inputTree->GetRoot();
  float coords[] = {0,1,0,1};
  coordsArray->SetTuple(rootId, coords);
  inputTree->GetPoints()->SetPoint(rootId, 0.5, 0.5, 0.0);

  // Now layout the children vertices
  this->AddBorder(coords);
  this->LayoutChildren(inputTree, coordsArray, sizeArray,
      inputTree->GetNumberOfChildren(rootId), rootId, 0,
      coords[0], coords[1], coords[2], coords[3]);
}

void vtkSquarifyLayoutStrategy::LayoutChildren(
  vtkTree *tree,
  vtkDataArray *coordsArray,
  vtkDataArray *sizeArray,
  vtkIdType nchildren,
  vtkIdType parent,
  vtkIdType begin,
  float minX, float maxX,
  float minY, float maxY)
{
  float sizeX = maxX - minX;
  float sizeY = maxY - minY;
  if ((sizeX == 0.0) || (sizeY == 0.0))
    {
    vtkErrorMacro(<< "Invalid Box Sizes for Vertex: "
                  << tree->GetChild(parent, begin) << " ("
                  << sizeX << ", " << sizeY << ")");
    return;
    }
  bool vertical = (sizeX < sizeY);
  float total = 0;
  if (sizeArray)
    {
    for (vtkIdType i = begin; i < nchildren; i++)
      {
      total += static_cast<float>(sizeArray->GetTuple1(tree->GetChild(parent, i)));
      }
    }
  else
    {
    total = nchildren;
    }
  float factor = (sizeX * sizeY) / total;

  vtkIdType cur = begin;
  float oldRowError = VTK_FLOAT_MAX;
  float rowError = VTK_FLOAT_MAX;
  float oldCurTotal = 0;
  float curTotal = 0;
  while (rowError <= oldRowError && cur < nchildren)
    {
    oldCurTotal = curTotal;
    if (sizeArray)
      {
      curTotal += factor * static_cast<float>(sizeArray->GetTuple1(tree->GetChild(parent, cur)));
      }
    else
      {
      curTotal += 1.0f;
      }

    oldRowError = rowError;
    // Compute the new row error
    rowError = 0;
    float width = vertical ? (curTotal / sizeX) : (curTotal / sizeY);
    for (vtkIdType i = begin; i <= cur; i++)
      {
      float curValue = 1.0f;
      if (sizeArray)
        {
        curValue = static_cast<float>(sizeArray->GetTuple1(tree->GetChild(parent, i)));
        }
      float curHeight = factor * curValue / width;
      float ratio1 = curHeight / width;
      float ratio2 = width / curHeight;
      float curError = (ratio1 > ratio2) ? ratio1 : ratio2;
      if (curError > rowError)
        {
        rowError = curError;
        }
      }
    cur++;
    }
  if (rowError > oldRowError)
    {
    cur--;
    curTotal = oldCurTotal;
    }

  float coords[4];
  float rowMinX = minX;
  float rowMinY = minY;
  float rowMaxX;
  float rowMaxY = maxY;
  if (vertical)
    {
    rowMaxX = maxX;
    rowMinY = rowMaxY - curTotal / sizeX;
    }
  else
    {
    rowMaxX = rowMinX + curTotal / sizeY;
    rowMinY = minY;
    }
  float part = 0;
  float oldPosition = 0;
  float position = 0;
  for (vtkIdType j = begin; j < cur; j++)
    {
    int id = tree->GetChild(parent, j);
    if (sizeArray)
      {
      part += factor * static_cast<float>(sizeArray->GetTuple1(id));
      }
    else
      {
      part += factor * 1.0f;
      }
    oldPosition = position;
    // Give children their positions
    if (vertical)
      {
      if (curTotal == 0)
        {
        position = 0;
        }
      else
        {
        position = sizeX * (part / curTotal);
        }
      coords[0] = rowMinX + oldPosition;     // minX
      coords[1] = rowMinX + position;        // maxX
      coords[2] = rowMinY;                   // minY
      coords[3] = rowMaxY;                   // maxY
      }
    else
      {
      if (curTotal == 0)
        {
        position = 0;
        }
      else
        {
        position = sizeY * (part / curTotal);
        }
      coords[0] = rowMinX;                   // minX
      coords[1] = rowMaxX;                   // maxX
      coords[2] = rowMaxY - position;        // minY
      coords[3] = rowMaxY - oldPosition;     // maxY
      }

    coordsArray->SetTuple(id, coords);
    tree->GetPoints()->SetPoint(id,
        (coords[0] + coords[1])/2.0,
        (coords[2] + coords[3])/2.0, 0.0);
    vtkIdType numNewChildren = tree->GetNumberOfChildren(id);
    if (numNewChildren > 0)
      {
      this->AddBorder(coords);
      this->LayoutChildren(tree, coordsArray, sizeArray, numNewChildren, id, 0,
        coords[0], coords[1], coords[2], coords[3]);
      }
    }

  if (cur < nchildren)
    {
    float restMinX;
    float restMaxX;
    float restMinY;
    float restMaxY;
    if (vertical)
      {
      restMinY = minY;
      restMaxY = rowMinY;
      restMinX = rowMinX;
      restMaxX = rowMaxX;
      }
    else
      {
      restMinX = rowMaxX;
      restMaxX = maxX;
      restMinY = rowMinY;
      restMaxY = rowMaxY;
      }
    this->LayoutChildren(tree, coordsArray, sizeArray, nchildren, parent, cur,
      restMinX, restMaxX, restMinY, restMaxY);
    }
}
<commit_msg>BUG: Allow empty trees in squarify layout strategy.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkSquarifyLayoutStrategy.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
/*-------------------------------------------------------------------------
  Copyright 2008 Sandia Corporation.
  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
  the U.S. Government retains certain rights in this software.
-------------------------------------------------------------------------*/
#include "vtkSquarifyLayoutStrategy.h"

#include "vtkDataArray.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkPoints.h"
#include "vtkTree.h"

vtkCxxRevisionMacro(vtkSquarifyLayoutStrategy, "1.9");
vtkStandardNewMacro(vtkSquarifyLayoutStrategy);

vtkSquarifyLayoutStrategy::vtkSquarifyLayoutStrategy()
{
}

vtkSquarifyLayoutStrategy::~vtkSquarifyLayoutStrategy()
{
}

void vtkSquarifyLayoutStrategy::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
}

void vtkSquarifyLayoutStrategy::Layout(
    vtkTree* inputTree,
    vtkDataArray* coordsArray,
    vtkDataArray* sizeArray)
{
  if (!inputTree || inputTree->GetNumberOfVertices() == 0)
    {
    return;
    }
  if (!coordsArray)
    {
    vtkErrorMacro("Area array undefined");
    return;
    }

  // Get the root vertex and set it to 0,1,0,1
  vtkIdType rootId = inputTree->GetRoot();
  float coords[] = {0,1,0,1};
  coordsArray->SetTuple(rootId, coords);
  inputTree->GetPoints()->SetPoint(rootId, 0.5, 0.5, 0.0);

  // Now layout the children vertices
  this->AddBorder(coords);
  this->LayoutChildren(inputTree, coordsArray, sizeArray,
      inputTree->GetNumberOfChildren(rootId), rootId, 0,
      coords[0], coords[1], coords[2], coords[3]);
}

void vtkSquarifyLayoutStrategy::LayoutChildren(
  vtkTree *tree,
  vtkDataArray *coordsArray,
  vtkDataArray *sizeArray,
  vtkIdType nchildren,
  vtkIdType parent,
  vtkIdType begin,
  float minX, float maxX,
  float minY, float maxY)
{
  float sizeX = maxX - minX;
  float sizeY = maxY - minY;
  if ((sizeX == 0.0) || (sizeY == 0.0))
    {
    vtkErrorMacro(<< "Invalid Box Sizes for Vertex: "
                  << tree->GetChild(parent, begin) << " ("
                  << sizeX << ", " << sizeY << ")");
    return;
    }
  bool vertical = (sizeX < sizeY);
  float total = 0;
  if (sizeArray)
    {
    for (vtkIdType i = begin; i < nchildren; i++)
      {
      total += static_cast<float>(sizeArray->GetTuple1(tree->GetChild(parent, i)));
      }
    }
  else
    {
    total = nchildren;
    }
  float factor = (sizeX * sizeY) / total;

  vtkIdType cur = begin;
  float oldRowError = VTK_FLOAT_MAX;
  float rowError = VTK_FLOAT_MAX;
  float oldCurTotal = 0;
  float curTotal = 0;
  while (rowError <= oldRowError && cur < nchildren)
    {
    oldCurTotal = curTotal;
    if (sizeArray)
      {
      curTotal += factor * static_cast<float>(sizeArray->GetTuple1(tree->GetChild(parent, cur)));
      }
    else
      {
      curTotal += 1.0f;
      }

    oldRowError = rowError;
    // Compute the new row error
    rowError = 0;
    float width = vertical ? (curTotal / sizeX) : (curTotal / sizeY);
    for (vtkIdType i = begin; i <= cur; i++)
      {
      float curValue = 1.0f;
      if (sizeArray)
        {
        curValue = static_cast<float>(sizeArray->GetTuple1(tree->GetChild(parent, i)));
        }
      float curHeight = factor * curValue / width;
      float ratio1 = curHeight / width;
      float ratio2 = width / curHeight;
      float curError = (ratio1 > ratio2) ? ratio1 : ratio2;
      if (curError > rowError)
        {
        rowError = curError;
        }
      }
    cur++;
    }
  if (rowError > oldRowError)
    {
    cur--;
    curTotal = oldCurTotal;
    }

  float coords[4];
  float rowMinX = minX;
  float rowMinY = minY;
  float rowMaxX;
  float rowMaxY = maxY;
  if (vertical)
    {
    rowMaxX = maxX;
    rowMinY = rowMaxY - curTotal / sizeX;
    }
  else
    {
    rowMaxX = rowMinX + curTotal / sizeY;
    rowMinY = minY;
    }
  float part = 0;
  float oldPosition = 0;
  float position = 0;
  for (vtkIdType j = begin; j < cur; j++)
    {
    int id = tree->GetChild(parent, j);
    if (sizeArray)
      {
      part += factor * static_cast<float>(sizeArray->GetTuple1(id));
      }
    else
      {
      part += factor * 1.0f;
      }
    oldPosition = position;
    // Give children their positions
    if (vertical)
      {
      if (curTotal == 0)
        {
        position = 0;
        }
      else
        {
        position = sizeX * (part / curTotal);
        }
      coords[0] = rowMinX + oldPosition;     // minX
      coords[1] = rowMinX + position;        // maxX
      coords[2] = rowMinY;                   // minY
      coords[3] = rowMaxY;                   // maxY
      }
    else
      {
      if (curTotal == 0)
        {
        position = 0;
        }
      else
        {
        position = sizeY * (part / curTotal);
        }
      coords[0] = rowMinX;                   // minX
      coords[1] = rowMaxX;                   // maxX
      coords[2] = rowMaxY - position;        // minY
      coords[3] = rowMaxY - oldPosition;     // maxY
      }

    coordsArray->SetTuple(id, coords);
    tree->GetPoints()->SetPoint(id,
        (coords[0] + coords[1])/2.0,
        (coords[2] + coords[3])/2.0, 0.0);
    vtkIdType numNewChildren = tree->GetNumberOfChildren(id);
    if (numNewChildren > 0)
      {
      this->AddBorder(coords);
      this->LayoutChildren(tree, coordsArray, sizeArray, numNewChildren, id, 0,
        coords[0], coords[1], coords[2], coords[3]);
      }
    }

  if (cur < nchildren)
    {
    float restMinX;
    float restMaxX;
    float restMinY;
    float restMaxY;
    if (vertical)
      {
      restMinY = minY;
      restMaxY = rowMinY;
      restMinX = rowMinX;
      restMaxX = rowMaxX;
      }
    else
      {
      restMinX = rowMaxX;
      restMaxX = maxX;
      restMinY = rowMinY;
      restMaxY = rowMaxY;
      }
    this->LayoutChildren(tree, coordsArray, sizeArray, nchildren, parent, cur,
      restMinX, restMaxX, restMinY, restMaxY);
    }
}
<|endoftext|>