<commit_before>#include "depthai/pipeline/node/StereoDepth.hpp"

// standard
#include <fstream>

#include "spdlog/spdlog.h"

namespace dai {
namespace node {

StereoDepth::StereoDepth(const std::shared_ptr<PipelineImpl>& par, int64_t nodeId) : Node(par, nodeId) {
    // 'properties' defaults already set
}

std::string StereoDepth::getName() const {
    return "StereoDepth";
}

std::vector<Node::Output> StereoDepth::getOutputs() {
    return {disparity, depth, syncedLeft, syncedRight, rectifiedLeft, rectifiedRight};
}

std::vector<Node::Input> StereoDepth::getInputs() {
    return {left, right};
}

nlohmann::json StereoDepth::getProperties() {
    nlohmann::json j;
    nlohmann::to_json(j, properties);
    return j;
}

std::shared_ptr<Node> StereoDepth::clone() {
    return std::make_shared<std::decay<decltype(*this)>::type>(*this);
}

void StereoDepth::loadCalibrationData(const std::vector<std::uint8_t>& data) {
    if(data.empty()) {
        // Will use EEPROM data
        properties.calibration.clear();
    } else {
        properties.calibration = data;
    }
}

void StereoDepth::loadCalibrationFile(const std::string& path) {
    std::vector<std::uint8_t> data;
    if(!path.empty()) {
        std::ifstream calib(path, std::ios::binary);
        if(!calib.is_open()) {
            throw std::runtime_error("StereoDepth node | Unable to open calibration file: " + path);
        }
        data = std::vector<std::uint8_t>(std::istreambuf_iterator<char>(calib), {});
    }
    loadCalibrationData(data);
}

void StereoDepth::setEmptyCalibration(void) {
    // Special case: a single element
    const std::vector<std::uint8_t> empty = {0};
    properties.calibration = empty;
}

void StereoDepth::setInputResolution(int width, int height) {
    properties.width = width;
    properties.height = height;
}
void StereoDepth::setMedianFilter(Properties::MedianFilter median) {
    properties.median = median;
}
void StereoDepth::setDepthAlign(Properties::DepthAlign align) {
    properties.depthAlign = align;
    // Unset 'depthAlignCamera', that would take precedence otherwise
    properties.depthAlignCamera = CameraBoardSocket::AUTO;
}
void StereoDepth::setDepthAlign(CameraBoardSocket camera) {
    properties.depthAlignCamera = camera;
}
void StereoDepth::setConfidenceThreshold(int confThr) {
    properties.confidenceThreshold = confThr;
}
void StereoDepth::setLeftRightCheck(bool enable) {
    properties.enableLeftRightCheck = enable;
}
void StereoDepth::setSubpixel(bool enable) {
    properties.enableSubpixel = enable;
}
void StereoDepth::setExtendedDisparity(bool enable) {
    properties.enableExtendedDisparity = enable;
}
void StereoDepth::setRectifyEdgeFillColor(int color) {
    properties.rectifyEdgeFillColor = color;
}
void StereoDepth::setRectifyMirrorFrame(bool enable) {
    properties.rectifyMirrorFrame = enable;
}
void StereoDepth::setOutputRectified(bool enable) {
    (void)enable;
    spdlog::warn("{} is deprecated. The output is auto-enabled if used", __func__);
}
void StereoDepth::setOutputDepth(bool enable) {
    (void)enable;
    spdlog::warn("{} is deprecated. The output is auto-enabled if used", __func__);
}

float StereoDepth::getMaxDisparity(void) const {
    float maxDisp = 95.0;
    if(properties.enableExtendedDisparity) maxDisp *= 2;
    if(properties.enableLeftRightCheck) maxDisp *= 32;
    return maxDisp;
}

}  // namespace node
}  // namespace dai
<commit_msg>removed void from the function's arguments<commit_after>#include "depthai/pipeline/node/StereoDepth.hpp"

// standard
#include <fstream>

#include "spdlog/spdlog.h"

namespace dai {
namespace node {

StereoDepth::StereoDepth(const std::shared_ptr<PipelineImpl>& par, int64_t nodeId) : Node(par, nodeId) {
    // 'properties' defaults already set
}

std::string StereoDepth::getName() const {
    return "StereoDepth";
}

std::vector<Node::Output> StereoDepth::getOutputs() {
    return {disparity, depth, syncedLeft, syncedRight, rectifiedLeft, rectifiedRight};
}

std::vector<Node::Input> StereoDepth::getInputs() {
    return {left, right};
}

nlohmann::json StereoDepth::getProperties() {
    nlohmann::json j;
    nlohmann::to_json(j, properties);
    return j;
}

std::shared_ptr<Node> StereoDepth::clone() {
    return std::make_shared<std::decay<decltype(*this)>::type>(*this);
}

void StereoDepth::loadCalibrationData(const std::vector<std::uint8_t>& data) {
    if(data.empty()) {
        // Will use EEPROM data
        properties.calibration.clear();
    } else {
        properties.calibration = data;
    }
}

void StereoDepth::loadCalibrationFile(const std::string& path) {
    std::vector<std::uint8_t> data;
    if(!path.empty()) {
        std::ifstream calib(path, std::ios::binary);
        if(!calib.is_open()) {
            throw std::runtime_error("StereoDepth node | Unable to open calibration file: " + path);
        }
        data = std::vector<std::uint8_t>(std::istreambuf_iterator<char>(calib), {});
    }
    loadCalibrationData(data);
}

void StereoDepth::setEmptyCalibration(void) {
    // Special case: a single element
    const std::vector<std::uint8_t> empty = {0};
    properties.calibration = empty;
}

void StereoDepth::setInputResolution(int width, int height) {
    properties.width = width;
    properties.height = height;
}
void StereoDepth::setMedianFilter(Properties::MedianFilter median) {
    properties.median = median;
}
void StereoDepth::setDepthAlign(Properties::DepthAlign align) {
    properties.depthAlign = align;
    // Unset 'depthAlignCamera', that would take precedence otherwise
    properties.depthAlignCamera = CameraBoardSocket::AUTO;
}
void StereoDepth::setDepthAlign(CameraBoardSocket camera) {
    properties.depthAlignCamera = camera;
}
void StereoDepth::setConfidenceThreshold(int confThr) {
    properties.confidenceThreshold = confThr;
}
void StereoDepth::setLeftRightCheck(bool enable) {
    properties.enableLeftRightCheck = enable;
}
void StereoDepth::setSubpixel(bool enable) {
    properties.enableSubpixel = enable;
}
void StereoDepth::setExtendedDisparity(bool enable) {
    properties.enableExtendedDisparity = enable;
}
void StereoDepth::setRectifyEdgeFillColor(int color) {
    properties.rectifyEdgeFillColor = color;
}
void StereoDepth::setRectifyMirrorFrame(bool enable) {
    properties.rectifyMirrorFrame = enable;
}
void StereoDepth::setOutputRectified(bool enable) {
    (void)enable;
    spdlog::warn("{} is deprecated. The output is auto-enabled if used", __func__);
}
void StereoDepth::setOutputDepth(bool enable) {
    (void)enable;
    spdlog::warn("{} is deprecated. The output is auto-enabled if used", __func__);
}

float StereoDepth::getMaxDisparity() const {
    float maxDisp = 95.0;
    if(properties.enableExtendedDisparity) maxDisp *= 2;
    if(properties.enableLeftRightCheck) maxDisp *= 32;
    return maxDisp;
}

}  // namespace node
}  // namespace dai
<|endoftext|>


<commit_before>#include "pch.h"
#include "jnc_ct_Namespace.h"
#include "jnc_ct_Module.h"
#include "jnc_ct_StructType.h"
#include "jnc_ct_ClassType.h"

namespace jnc {
namespace ct {

//.............................................................................

Namespace*
getItemNamespace (ModuleItem* item)
{
	ModuleItemKind itemKind = item->getItemKind ();
	switch (itemKind)
	{
	case ModuleItemKind_Namespace:
		return (GlobalNamespace*) item;

	case ModuleItemKind_Property:
		return (Property*) item;

	case ModuleItemKind_Type:
		break;

	case ModuleItemKind_Typedef:
		item = ((Typedef*) item)->getType ();
		break;

	default:
		return NULL;
	}

	Type* type = (Type*) item;
	TypeKind typeKind = type->getTypeKind ();
	switch (typeKind)
	{
	case TypeKind_Enum:
	case TypeKind_Struct:
	case TypeKind_Union:
	case TypeKind_Class:
		return ((NamedType*) type);

	default:
		return NULL;
	}
}

//.............................................................................

const char*
getNamespaceKindString (NamespaceKind namespaceKind)
{
	static const char* stringTable [NamespaceKind__Count] =
	{
		"undefined-namespace-kind",  // Namespace_Undefined = 0,
		"global-namespace",          // Namespace_Global,
		"scope",                     // Namespace_Scope,
		"named-type",                // Namespace_Type,
		"extension-namespace",       // Namespace_Extension,
		"property",                  // Namespace_Property,
		"property-template",         // Namespace_PropertyTemplate,
		"library",                   // Namespace_Library,
	};

	return (size_t) namespaceKind < NamespaceKind__Count ?
		stringTable [namespaceKind] :
		stringTable [NamespaceKind_Undefined];
}

//.............................................................................

void
Namespace::clear ()
{
	m_itemArray.clear ();
	m_itemMap.clear ();
	m_usingSet.clear ();
}

sl::String
Namespace::createQualifiedName (const char* name)
{
	if (m_qualifiedName.isEmpty ())
		return name;

	sl::String qualifiedName = m_qualifiedName;

	if (name && *name)
	{
		qualifiedName.append ('.');
		qualifiedName.append (name);
	}

	return qualifiedName;
}

ModuleItem*
Namespace::findItemByName (const char* name)
{
	if (!strchr (name, '.'))
		return findItem (name);

	QualifiedName qualifiedName;
	qualifiedName.parse (name);
	return findItem (qualifiedName);
}

ModuleItem*
Namespace::getItemByName (const char* name)
{
	ModuleItem* item = findItemByName (name);

	if (!item)
	{
		err::setFormatStringError ("'%s' not found", name);
		return NULL;
	}

	return item;
}

ModuleItem*
Namespace::findItem (const char* name)
{
	sl::StringHashTableMapIterator <ModuleItem*> it = m_itemMap.find (name);
	if (!it)
		return NULL;

	ModuleItem* item = it->m_value;
	if (!item || item->getItemKind () != ModuleItemKind_Lazy)
		return item;

	LazyModuleItem* lazyItem = (LazyModuleItem*) item;
	ASSERT (!(lazyItem->m_flags & LazyModuleItemFlag_Touched));

	it->m_value = NULL; // many lazy std-types are parsed, so remove it from namespace
	lazyItem->m_flags |= LazyModuleItemFlag_Touched;

	item = lazyItem->getActualItem ();
	if (!item)
		return NULL;

	if (!it->m_value)
	{
		m_itemArray.append (item);
		it->m_value = item;
	}

	ASSERT (it->m_value == item);
	return item;
}

ModuleItem*
Namespace::findItem (const QualifiedName& name)
{
	ModuleItem* item = findItem (name.getFirstName ());
	if (!item)
		return NULL;

	sl::BoxIterator <sl::String> nameIt = name.getNameList ().getHead ();
	for (; nameIt; nameIt++)
	{
		Namespace* nspace = getItemNamespace (item);
		if (!nspace)
			return NULL;

		item = nspace->findItem (*nameIt);
		if (!item)
			return NULL;
	}

	return item;
}

ModuleItem*
Namespace::findItemTraverse (
	const QualifiedName& name,
	MemberCoord* coord,
	uint_t flags
	)
{
	ModuleItem* item = findItemTraverse (name.getFirstName (), coord, flags);
	if (!item)
		return NULL;

	sl::BoxIterator <sl::String> nameIt = name.getNameList ().getHead ();
	for (; nameIt; nameIt++)
	{
		Namespace* nspace = getItemNamespace (item);
		if (!nspace)
			return NULL;

		item = nspace->findItem (*nameIt);
		if (!item)
			return NULL;
	}

	return item;
}

ModuleItem*
Namespace::findItemTraverseImpl (
	const char* name,
	MemberCoord* coord,
	uint_t flags
	)
{
	ModuleItem* item;

	if (!(flags & TraverseKind_NoThis))
	{
		item = findItem (name);
		if (item)
			return item;
	}

	if (!(flags & TraverseKind_NoUsingNamespaces))
	{
		item = m_usingSet.findItem (name);
		if (item)
			return item;
	}

	if (!(flags & TraverseKind_NoParentNamespace) && m_parentNamespace)
	{
		item = m_parentNamespace->findItemTraverse (name, coord, flags & ~TraverseKind_NoThis);
		if (item)
			return item;
	}

	return NULL;
}

bool
Namespace::addItem (
	const char* name,
	ModuleItem* item
	)
{
	sl::StringHashTableMapIterator <ModuleItem*> it = m_itemMap.visit (name);
	if (it->m_value)
	{
		setRedefinitionError (name);
		return false;
	}

	if (item->getItemKind () != ModuleItemKind_Lazy)
		m_itemArray.append (item);

	it->m_value = item;
	return true;
}

size_t
Namespace::addFunction (Function* function)
{
	ModuleItem* oldItem = findItem (function->m_name);
	if (!oldItem)
	{
		addItem (function);
		return 0;
	}

	if (oldItem->getItemKind () != ModuleItemKind_Function)
	{
		setRedefinitionError (function->m_name);
		return -1;
	}

	return ((Function*) oldItem)->addOverload (function);
}

Const*
Namespace::createConst (
	const sl::String& name,
	const Value& value
	)
{
	ASSERT (value.getValueKind () == ValueKind_Const && value.getType ());

	Module* module = value.getType ()->getModule ();
	sl::String qualifiedName = createQualifiedName (name);

	Const* cnst = module->m_constMgr.createConst (name, qualifiedName, value);
	bool result = addItem (cnst);
	if (!result)
		return NULL;

	return cnst;
}

bool
Namespace::exposeEnumConsts (EnumType* type)
{
	bool result;

	sl::Iterator <EnumConst> constIt = type->getConstList ().getHead ();
	for (; constIt; constIt++)
	{
		result = addItem (*constIt);
		if (!result)
			return false;
	}

	return true;
}

//.............................................................................

} // namespace ct
} // namespace jnc
<commit_msg>[jancy] bugfix: clear friendset and dual ptr type tuple map in Namespace::clear<commit_after>#include "pch.h"
#include "jnc_ct_Namespace.h"
#include "jnc_ct_Module.h"
#include "jnc_ct_StructType.h"
#include "jnc_ct_ClassType.h"

namespace jnc {
namespace ct {

//.............................................................................

Namespace*
getItemNamespace (ModuleItem* item)
{
	ModuleItemKind itemKind = item->getItemKind ();
	switch (itemKind)
	{
	case ModuleItemKind_Namespace:
		return (GlobalNamespace*) item;

	case ModuleItemKind_Property:
		return (Property*) item;

	case ModuleItemKind_Type:
		break;

	case ModuleItemKind_Typedef:
		item = ((Typedef*) item)->getType ();
		break;

	default:
		return NULL;
	}

	Type* type = (Type*) item;
	TypeKind typeKind = type->getTypeKind ();
	switch (typeKind)
	{
	case TypeKind_Enum:
	case TypeKind_Struct:
	case TypeKind_Union:
	case TypeKind_Class:
		return ((NamedType*) type);

	default:
		return NULL;
	}
}

//.............................................................................

const char*
getNamespaceKindString (NamespaceKind namespaceKind)
{
	static const char* stringTable [NamespaceKind__Count] =
	{
		"undefined-namespace-kind",  // Namespace_Undefined = 0,
		"global-namespace",          // Namespace_Global,
		"scope",                     // Namespace_Scope,
		"named-type",                // Namespace_Type,
		"extension-namespace",       // Namespace_Extension,
		"property",                  // Namespace_Property,
		"property-template",         // Namespace_PropertyTemplate,
		"library",                   // Namespace_Library,
	};

	return (size_t) namespaceKind < NamespaceKind__Count ?
		stringTable [namespaceKind] :
		stringTable [NamespaceKind_Undefined];
}

//.............................................................................

void
Namespace::clear ()
{
	m_itemArray.clear ();
	m_itemMap.clear ();
	m_friendSet.clear ();
	m_dualPtrTypeTupleMap.clear ();
	m_usingSet.clear ();
}

sl::String
Namespace::createQualifiedName (const char* name)
{
	if (m_qualifiedName.isEmpty ())
		return name;

	sl::String qualifiedName = m_qualifiedName;

	if (name && *name)
	{
		qualifiedName.append ('.');
		qualifiedName.append (name);
	}

	return qualifiedName;
}

ModuleItem*
Namespace::findItemByName (const char* name)
{
	if (!strchr (name, '.'))
		return findItem (name);

	QualifiedName qualifiedName;
	qualifiedName.parse (name);
	return findItem (qualifiedName);
}

ModuleItem*
Namespace::getItemByName (const char* name)
{
	ModuleItem* item = findItemByName (name);

	if (!item)
	{
		err::setFormatStringError ("'%s' not found", name);
		return NULL;
	}

	return item;
}

ModuleItem*
Namespace::findItem (const char* name)
{
	sl::StringHashTableMapIterator <ModuleItem*> it = m_itemMap.find (name);
	if (!it)
		return NULL;

	ModuleItem* item = it->m_value;
	if (!item || item->getItemKind () != ModuleItemKind_Lazy)
		return item;

	LazyModuleItem* lazyItem = (LazyModuleItem*) item;
	ASSERT (!(lazyItem->m_flags & LazyModuleItemFlag_Touched));

	it->m_value = NULL; // many lazy std-types are parsed, so remove it from namespace
	lazyItem->m_flags |= LazyModuleItemFlag_Touched;

	item = lazyItem->getActualItem ();
	if (!item)
		return NULL;

	if (!it->m_value)
	{
		m_itemArray.append (item);
		it->m_value = item;
	}

	ASSERT (it->m_value == item);
	return item;
}

ModuleItem*
Namespace::findItem (const QualifiedName& name)
{
	ModuleItem* item = findItem (name.getFirstName ());
	if (!item)
		return NULL;

	sl::BoxIterator <sl::String> nameIt = name.getNameList ().getHead ();
	for (; nameIt; nameIt++)
	{
		Namespace* nspace = getItemNamespace (item);
		if (!nspace)
			return NULL;

		item = nspace->findItem (*nameIt);
		if (!item)
			return NULL;
	}

	return item;
}

ModuleItem*
Namespace::findItemTraverse (
	const QualifiedName& name,
	MemberCoord* coord,
	uint_t flags
	)
{
	ModuleItem* item = findItemTraverse (name.getFirstName (), coord, flags);
	if (!item)
		return NULL;

	sl::BoxIterator <sl::String> nameIt = name.getNameList ().getHead ();
	for (; nameIt; nameIt++)
	{
		Namespace* nspace = getItemNamespace (item);
		if (!nspace)
			return NULL;

		item = nspace->findItem (*nameIt);
		if (!item)
			return NULL;
	}

	return item;
}

ModuleItem*
Namespace::findItemTraverseImpl (
	const char* name,
	MemberCoord* coord,
	uint_t flags
	)
{
	ModuleItem* item;

	if (!(flags & TraverseKind_NoThis))
	{
		item = findItem (name);
		if (item)
			return item;
	}

	if (!(flags & TraverseKind_NoUsingNamespaces))
	{
		item = m_usingSet.findItem (name);
		if (item)
			return item;
	}

	if (!(flags & TraverseKind_NoParentNamespace) && m_parentNamespace)
	{
		item = m_parentNamespace->findItemTraverse (name, coord, flags & ~TraverseKind_NoThis);
		if (item)
			return item;
	}

	return NULL;
}

bool
Namespace::addItem (
	const char* name,
	ModuleItem* item
	)
{
	sl::StringHashTableMapIterator <ModuleItem*> it = m_itemMap.visit (name);
	if (it->m_value)
	{
		setRedefinitionError (name);
		return false;
	}

	if (item->getItemKind () != ModuleItemKind_Lazy)
		m_itemArray.append (item);

	it->m_value = item;
	return true;
}

size_t
Namespace::addFunction (Function* function)
{
	ModuleItem* oldItem = findItem (function->m_name);
	if (!oldItem)
	{
		addItem (function);
		return 0;
	}

	if (oldItem->getItemKind () != ModuleItemKind_Function)
	{
		setRedefinitionError (function->m_name);
		return -1;
	}

	return ((Function*) oldItem)->addOverload (function);
}

Const*
Namespace::createConst (
	const sl::String& name,
	const Value& value
	)
{
	ASSERT (value.getValueKind () == ValueKind_Const && value.getType ());

	Module* module = value.getType ()->getModule ();
	sl::String qualifiedName = createQualifiedName (name);

	Const* cnst = module->m_constMgr.createConst (name, qualifiedName, value);
	bool result = addItem (cnst);
	if (!result)
		return NULL;

	return cnst;
}

bool
Namespace::exposeEnumConsts (EnumType* type)
{
	bool result;

	sl::Iterator <EnumConst> constIt = type->getConstList ().getHead ();
	for (; constIt; constIt++)
	{
		result = addItem (*constIt);
		if (!result)
			return false;
	}

	return true;
}

//.............................................................................

} // namespace ct
} // namespace jnc
<|endoftext|>


<commit_before>#include "fSharpGeneratorPlugin.h"

#include <QtWidgets/QApplication>
#include <QtCore/QFileInfo>
#include <QtCore/QProcess>
#include <qrkernel/settingsManager.h>
#include <qrutils/invocationUtils/functorOperation.h>

#include <QtCore/QDebug>

#include <utils/tcpRobotCommunicator.h>
#include "fSharpMasterGenerator.h"

using namespace fSharp;
using namespace qReal;

FSharpGeneratorPlugin::FSharpGeneratorPlugin()
		: mGenerateCodeAction(nullptr)
		, mUploadProgramAction(nullptr)
		, mRunProgramAction(nullptr)
		, mStopRobotAction(nullptr)
{
	mAppTranslator.load(":/FSharpGenerator_" + QLocale().name());
	QApplication::installTranslator(&mAppTranslator);
}

FSharpGeneratorPlugin::~FSharpGeneratorPlugin()
{
}

QString FSharpGeneratorPlugin::kitId() const
{
	return "trikKit";
}

QList<ActionInfo> FSharpGeneratorPlugin::actions()
{
	mGenerateCodeAction.setText(tr("Generate FSharp code"));
	mGenerateCodeAction.setIcon(QIcon(":/images/generateQtsCode.svg"));
	ActionInfo generateCodeActionInfo(&mGenerateCodeAction, "generators", "tools");
	connect(&mGenerateCodeAction, SIGNAL(triggered()), this, SLOT(generateCode()));

	mUploadProgramAction.setText(tr("Upload program FSharp"));
	mUploadProgramAction.setIcon(QIcon(":/images/uploadProgram.svg"));
	ActionInfo uploadProgramActionInfo(&mUploadProgramAction, "generators", "tools");
	connect(&mUploadProgramAction, SIGNAL(triggered()), this, SLOT(uploadProgram()));

	mRunProgramAction.setText(tr("Run program FSharp"));
	mRunProgramAction.setIcon(QIcon(":/images/uploadAndExecuteProgram.svg"));
	ActionInfo runProgramActionInfo(&mRunProgramAction, "generators", "tools");
	connect(&mRunProgramAction, SIGNAL(triggered()), this, SLOT(runProgram()));

	mStopRobotAction.setText(tr("Stop robot"));
	mStopRobotAction.setIcon(QIcon(":/images/stopRobot.svg"));
	ActionInfo stopRobotActionInfo(&mStopRobotAction, "generators", "tools");
	connect(&mStopRobotAction, SIGNAL(triggered()), this, SLOT(stopRobot()));

	return {generateCodeActionInfo, uploadProgramActionInfo, runProgramActionInfo, stopRobotActionInfo};
}

QList<HotKeyActionInfo> FSharpGeneratorPlugin::hotKeyActions()
{
	mGenerateCodeAction.setShortcut(QKeySequence(Qt::CTRL + Qt::Key_H));
	mUploadProgramAction.setShortcut(QKeySequence(Qt::CTRL + Qt::Key_I));
	mRunProgramAction.setShortcut(QKeySequence(Qt::CTRL + Qt::Key_F6));
	mStopRobotAction.setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_F6));

	HotKeyActionInfo generateCodeInfo("Generator.GenerateFSharp", tr("Generate FSharp Code"), &mGenerateCodeAction);
	HotKeyActionInfo uploadProgramInfo("Generator.UploadFSharp", tr("Upload FSharp Program"), &mUploadProgramAction);
	HotKeyActionInfo runProgramInfo("Generator.RunFSharp", tr("Run FSharp Program"), &mRunProgramAction);
	HotKeyActionInfo stopRobotInfo("Generator.StopFSharp", tr("Stop FSharp Robot"), &mStopRobotAction);

	return {generateCodeInfo, uploadProgramInfo, runProgramInfo, stopRobotInfo};
}

generatorBase::MasterGeneratorBase *FSharpGeneratorPlugin::masterGenerator()
{
	return new FSharpMasterGenerator(*mRepo
			, *mMainWindowInterface->errorReporter()
			, *mRobotModelManager
			, mMainWindowInterface->activeDiagram());
}

void FSharpGeneratorPlugin::regenerateExtraFiles(QFileInfo const &newFileInfo)
{
	Q_UNUSED(newFileInfo);
}

QString FSharpGeneratorPlugin::defaultFilePath(QString const &projectName) const
{
	return QString("trik/%1/%1.fs").arg(projectName);
}

QString FSharpGeneratorPlugin::extension() const
{
	return "fs";
}

QString FSharpGeneratorPlugin::extDescrition() const
{
	return tr("FSharp Source File");
}

QString FSharpGeneratorPlugin::generatorName() const
{
	return "FSharp";
}

bool FSharpGeneratorPlugin::uploadProgram()
{
	QProcess myProcess;
	QFileInfo const fileInfo = generateCodeForProcessing();

	QString pathToTheTrikCore = " -r \"..\\..\\Trik.Core.dll\"";
	QString command = "\"" + qReal::SettingsManager::value("FSharpPath").toString() + "\" "
			+ "\"" + fileInfo.absoluteFilePath() + "\""
			+ pathToTheTrikCore;

	myProcess.setWorkingDirectory(fileInfo.absoluteDir().path());
	myProcess.start(command);
	myProcess.waitForFinished();
	qDebug() << command;
	qDebug() << myProcess.workingDirectory();

	QString moveCommand = "\"" + qReal::SettingsManager::value("WinScpPath").toString().replace("?","") + "\""
			+ " /command  \"open scp://root@" + qReal::SettingsManager::value("TrikTcpServer").toString() + "\""
			+ " \"put "+ fileInfo.absoluteFilePath().replace("fs","exe").replace("/","\\")
			+ " /home/root/trik/FSharp/Environment/\"";

	myProcess.startDetached(moveCommand);
	//myProcess.waitForFinished();
	mMainWindowInterface->errorReporter()->addInformation(
		tr("After downloading the program, enter 'exit' or close the window")
	);
}

void FSharpGeneratorPlugin::runProgram()
{
	mMainWindowInterface->errorReporter()->addWarning(
		tr("Attention, the robot starts about a half-minute")
	);

	utils::TcpRobotCommunicator communicator("TrikTcpServer");

	communicator.runDirectCommand(
			"brick.system(\"mono FSharp/Environment/example0.exe\"); "
	);

}

void FSharpGeneratorPlugin::stopRobot()
{
	utils::TcpRobotCommunicator communicator("TrikTcpServer");

	if (!communicator.stopRobot()) {
		mMainWindowInterface->errorReporter()->addError(tr("No connection to robot"));
	}

	communicator.runDirectCommand(
			"brick.system(\"killall mono FSharp/Environment/example0.exe\"); "
			"brick.system(\"killall aplay\"); \n"
			"brick.system(\"killall vlc\"); \n"
			"brick.system(\"killall rover-cv\");"
	);

}
<commit_msg>input errow with empty path to utils<commit_after>#include "fSharpGeneratorPlugin.h"

#include <QtWidgets/QApplication>
#include <QtCore/QFileInfo>
#include <QtCore/QProcess>
#include <qrkernel/settingsManager.h>
#include <qrutils/invocationUtils/functorOperation.h>

#include <QtCore/QDebug>

#include <utils/tcpRobotCommunicator.h>
#include "fSharpMasterGenerator.h"

using namespace fSharp;
using namespace qReal;

FSharpGeneratorPlugin::FSharpGeneratorPlugin()
		: mGenerateCodeAction(nullptr)
		, mUploadProgramAction(nullptr)
		, mRunProgramAction(nullptr)
		, mStopRobotAction(nullptr)
{
	mAppTranslator.load(":/FSharpGenerator_" + QLocale().name());
	QApplication::installTranslator(&mAppTranslator);
}

FSharpGeneratorPlugin::~FSharpGeneratorPlugin()
{
}

QString FSharpGeneratorPlugin::kitId() const
{
	return "trikKit";
}

QList<ActionInfo> FSharpGeneratorPlugin::actions()
{
	mGenerateCodeAction.setText(tr("Generate FSharp code"));
	mGenerateCodeAction.setIcon(QIcon(":/images/generateQtsCode.svg"));
	ActionInfo generateCodeActionInfo(&mGenerateCodeAction, "generators", "tools");
	connect(&mGenerateCodeAction, SIGNAL(triggered()), this, SLOT(generateCode()));

	mUploadProgramAction.setText(tr("Upload program FSharp"));
	mUploadProgramAction.setIcon(QIcon(":/images/uploadProgram.svg"));
	ActionInfo uploadProgramActionInfo(&mUploadProgramAction, "generators", "tools");
	connect(&mUploadProgramAction, SIGNAL(triggered()), this, SLOT(uploadProgram()));

	mRunProgramAction.setText(tr("Run program FSharp"));
	mRunProgramAction.setIcon(QIcon(":/images/uploadAndExecuteProgram.svg"));
	ActionInfo runProgramActionInfo(&mRunProgramAction, "generators", "tools");
	connect(&mRunProgramAction, SIGNAL(triggered()), this, SLOT(runProgram()));

	mStopRobotAction.setText(tr("Stop robot"));
	mStopRobotAction.setIcon(QIcon(":/images/stopRobot.svg"));
	ActionInfo stopRobotActionInfo(&mStopRobotAction, "generators", "tools");
	connect(&mStopRobotAction, SIGNAL(triggered()), this, SLOT(stopRobot()));

	return {generateCodeActionInfo, uploadProgramActionInfo, runProgramActionInfo, stopRobotActionInfo};
}

QList<HotKeyActionInfo> FSharpGeneratorPlugin::hotKeyActions()
{
	mGenerateCodeAction.setShortcut(QKeySequence(Qt::CTRL + Qt::Key_H));
	mUploadProgramAction.setShortcut(QKeySequence(Qt::CTRL + Qt::Key_I));
	mRunProgramAction.setShortcut(QKeySequence(Qt::CTRL + Qt::Key_F6));
	mStopRobotAction.setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_F6));

	HotKeyActionInfo generateCodeInfo("Generator.GenerateFSharp", tr("Generate FSharp Code"), &mGenerateCodeAction);
	HotKeyActionInfo uploadProgramInfo("Generator.UploadFSharp", tr("Upload FSharp Program"), &mUploadProgramAction);
	HotKeyActionInfo runProgramInfo("Generator.RunFSharp", tr("Run FSharp Program"), &mRunProgramAction);
	HotKeyActionInfo stopRobotInfo("Generator.StopFSharp", tr("Stop FSharp Robot"), &mStopRobotAction);

	return {generateCodeInfo, uploadProgramInfo, runProgramInfo, stopRobotInfo};
}

generatorBase::MasterGeneratorBase *FSharpGeneratorPlugin::masterGenerator()
{
	return new FSharpMasterGenerator(*mRepo
			, *mMainWindowInterface->errorReporter()
			, *mRobotModelManager
			, mMainWindowInterface->activeDiagram());
}

void FSharpGeneratorPlugin::regenerateExtraFiles(QFileInfo const &newFileInfo)
{
	Q_UNUSED(newFileInfo);
}

QString FSharpGeneratorPlugin::defaultFilePath(QString const &projectName) const
{
	return QString("trik/%1/%1.fs").arg(projectName);
}

QString FSharpGeneratorPlugin::extension() const
{
	return "fs";
}

QString FSharpGeneratorPlugin::extDescrition() const
{
	return tr("FSharp Source File");
}

QString FSharpGeneratorPlugin::generatorName() const
{
	return "FSharp";
}

bool FSharpGeneratorPlugin::uploadProgram()
{
	QProcess myProcess;
	QFileInfo const fileInfo = generateCodeForProcessing();

	QString pathToTheTrikCore = " -r \"..\\..\\Trik.Core.dll\"";

	if (qReal::SettingsManager::value("FSharpPath").toString() == "") {
		mMainWindowInterface->errorReporter()->addError(
			tr("Input path to the FSharp Compiler!!!")
		);
		return 0;
	}

	QString command = "\"" + qReal::SettingsManager::value("FSharpPath").toString() + "\" "
			+ "\"" + fileInfo.absoluteFilePath() + "\""
			+ pathToTheTrikCore;

	myProcess.setWorkingDirectory(fileInfo.absoluteDir().path());
	myProcess.start(command);
	myProcess.waitForFinished();

	if (qReal::SettingsManager::value("WinScpPath").toString() == "") {
		mMainWindowInterface->errorReporter()->addError(
			tr("Input path to the WinSCP!!!")
		);
		return 0;
	}

	QString moveCommand = "\"" + qReal::SettingsManager::value("WinScpPath").toString() + "\""
			+ " /command  \"open scp://root@" + qReal::SettingsManager::value("TrikTcpServer").toString() + "\""
			+ " \"put "+ fileInfo.absoluteFilePath().replace("fs","exe").replace("/","\\")
			+ " /home/root/trik/FSharp/Environment/\"";

	myProcess.startDetached(moveCommand);
	//myProcess.waitForFinished();
	mMainWindowInterface->errorReporter()->addInformation(
		tr("After downloading the program, enter 'exit' or close the window")
	);

	return 1;
}

void FSharpGeneratorPlugin::runProgram()
{
	mMainWindowInterface->errorReporter()->addWarning(
		tr("Attention, the robot starts about a half-minute")
	);

	utils::TcpRobotCommunicator communicator("TrikTcpServer");

	communicator.runDirectCommand(
			"brick.system(\"mono FSharp/Environment/example0.exe\"); "
	);

}

void FSharpGeneratorPlugin::stopRobot()
{
	utils::TcpRobotCommunicator communicator("TrikTcpServer");

	if (!communicator.stopRobot()) {
		mMainWindowInterface->errorReporter()->addError(tr("No connection to robot"));
	}

	communicator.runDirectCommand(
			"brick.system(\"killall mono FSharp/Environment/example0.exe\"); "
			"brick.system(\"killall aplay\"); \n"
			"brick.system(\"killall vlc\"); \n"
			"brick.system(\"killall rover-cv\");"
	);

}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
 */

#pragma once

#include <uavcan_stm32/build_config.hpp>
#include <uavcan_stm32/thread.hpp>
#include <uavcan/driver/can.hpp>
#include <uavcan_stm32/bxcan.hpp>

namespace uavcan_stm32
{
/**
 * Driver error codes.
 * These values can be returned from driver functions negated.
 */
//static const uavcan::int16_t ErrUnknown               = 1000; ///< Reserved for future use
static const uavcan::int16_t ErrNotImplemented          = 1001; ///< Feature not implemented
static const uavcan::int16_t ErrInvalidBitRate          = 1002; ///< Bit rate not supported
static const uavcan::int16_t ErrLogic                   = 1003; ///< Internal logic error
static const uavcan::int16_t ErrUnsupportedFrame        = 1004; ///< Frame not supported (e.g. RTR, CAN FD, etc)
static const uavcan::int16_t ErrMsrInakNotSet           = 1005; ///< INAK bit of the MSR register is not 1
static const uavcan::int16_t ErrMsrInakNotCleared       = 1006; ///< INAK bit of the MSR register is not 0
static const uavcan::int16_t ErrBitRateNotDetected      = 1007; ///< Auto bit rate detection could not be finished

/**
 * RX queue item.
 * The application shall not use this directly.
 */
struct CanRxItem
{
    uavcan::uint64_t utc_usec;
    uavcan::CanFrame frame;
    uavcan::CanIOFlags flags;
    CanRxItem()
        : utc_usec(0)
        , flags(0)
    { }
};

/**
 * Single CAN iface.
 * The application shall not use this directly.
 */
class CanIface : public uavcan::ICanIface, uavcan::Noncopyable
{
    class RxQueue
    {
        CanRxItem* const buf_;
        const uavcan::uint8_t capacity_;
        uavcan::uint8_t in_;
        uavcan::uint8_t out_;
        uavcan::uint8_t len_;
        uavcan::uint32_t overflow_cnt_;

        void registerOverflow();

    public:
        RxQueue(CanRxItem* buf, uavcan::uint8_t capacity)
            : buf_(buf)
            , capacity_(capacity)
            , in_(0)
            , out_(0)
            , len_(0)
            , overflow_cnt_(0)
        { }

        void push(const uavcan::CanFrame& frame, const uint64_t& utc_usec, uavcan::CanIOFlags flags);
        void pop(uavcan::CanFrame& out_frame, uavcan::uint64_t& out_utc_usec, uavcan::CanIOFlags& out_flags);

        void reset();

        unsigned getLength() const { return len_; }

        uavcan::uint32_t getOverflowCount() const { return overflow_cnt_; }
    };

    struct Timings
    {
        uavcan::uint16_t prescaler;
        uavcan::uint8_t sjw;
        uavcan::uint8_t bs1;
        uavcan::uint8_t bs2;

        Timings()
            : prescaler(0)
            , sjw(0)
            , bs1(0)
            , bs2(0)
        { }
    };

    struct TxItem
    {
        uavcan::MonotonicTime deadline;
        uavcan::CanFrame frame;
        bool pending;
        bool loopback;
        bool abort_on_error;

        TxItem()
            : pending(false)
            , loopback(false)
            , abort_on_error(false)
        { }
    };

    enum { NumTxMailboxes = 3 };
    enum { NumFilters = 14 };

    static const uavcan::uint32_t TSR_ABRQx[NumTxMailboxes];

    RxQueue rx_queue_;
    bxcan::CanType* const can_;
    uavcan::uint64_t error_cnt_;
    uavcan::uint32_t served_aborts_cnt_;
    BusEvent& update_event_;
    TxItem pending_tx_[NumTxMailboxes];
    uavcan::uint8_t peak_tx_mailbox_index_;
    const uavcan::uint8_t self_index_;
    bool had_activity_;

    int computeTimings(uavcan::uint32_t target_bitrate, Timings& out_timings);

    virtual uavcan::int16_t send(const uavcan::CanFrame& frame, uavcan::MonotonicTime tx_deadline,
                                 uavcan::CanIOFlags flags);

    virtual uavcan::int16_t receive(uavcan::CanFrame& out_frame, uavcan::MonotonicTime& out_ts_monotonic,
                                    uavcan::UtcTime& out_ts_utc, uavcan::CanIOFlags& out_flags);

    virtual uavcan::int16_t configureFilters(const uavcan::CanFilterConfig* filter_configs,
                                             uavcan::uint16_t num_configs);

    virtual uavcan::uint16_t getNumFilters() const { return NumFilters; }

    void handleTxMailboxInterrupt(uavcan::uint8_t mailbox_index, bool txok, uavcan::uint64_t utc_usec);

    bool waitMsrINakBitStateChange(bool target_state);

public:
    enum { MaxRxQueueCapacity = 254 };

    enum OperatingMode
    {
        NormalMode,
        SilentMode
    };

    CanIface(bxcan::CanType* can, BusEvent& update_event, uavcan::uint8_t self_index,
             CanRxItem* rx_queue_buffer, uavcan::uint8_t rx_queue_capacity)
        : rx_queue_(rx_queue_buffer, rx_queue_capacity)
        , can_(can)
        , error_cnt_(0)
        , served_aborts_cnt_(0)
        , update_event_(update_event)
        , peak_tx_mailbox_index_(0)
        , self_index_(self_index)
        , had_activity_(false)
    {
        UAVCAN_ASSERT(self_index_ < UAVCAN_STM32_NUM_IFACES);
    }

    /**
     * Initializes the hardware CAN controller.
     * Assumes:
     *   - Iface clock is enabled
     *   - Iface has been resetted via RCC
     *   - Caller will configure NVIC by itself
     */
    int init(const uavcan::uint32_t bitrate, const OperatingMode mode);

    void handleTxInterrupt(uavcan::uint64_t utc_usec);
    void handleRxInterrupt(uavcan::uint8_t fifo_index, uavcan::uint64_t utc_usec);

    /**
     * This method is used to count errors and abort transmission on error if necessary.
     * This functionality used to be implemented in the SCE interrupt handler, but that approach was
     * generating too much processing overhead, especially on disconnected interfaces.
     *
     * Should be called from RX ISR, TX ISR, and select(); interrupts must be enabled.
     */
    void pollErrorFlagsFromISR();

    void discardTimedOutTxMailboxes(uavcan::MonotonicTime current_time);

    bool canAcceptNewTxFrame(const uavcan::CanFrame& frame) const;
    bool isRxBufferEmpty() const;

    /**
     * Total number of hardware failures.
     * May increase continuously if the interface is not connected to the bus.
     */
    virtual uavcan::uint64_t getErrorCount() const;

    /**
     * Number of times the driver exercised library's requirement to abort transmission on first error.
     * This is an atomic read, it doesn't require a critical section.
     * See @ref uavcan::CanIOFlagAbortOnError.
     */
    uavcan::uint32_t getVoluntaryTxAbortCount() const { return served_aborts_cnt_; }

    /**
     * Returns number of frames pending in the RX queue.
     * This is intended for debug use only.
     */
    unsigned getRxQueueLength() const;

    /**
     * Whether this iface had at least one successful IO since previous call of this method.
     * This is designed for use with iface activity LEDs.
     */
    bool hadActivity();

    /**
     * Peak number of TX mailboxes used concurrently since initialization.
     * Range is [1, 3].
     * Value of 3 suggests that priority inversion could be taking place.
     */
    uavcan::uint8_t getPeakNumTxMailboxesUsed() const { return uavcan::uint8_t(peak_tx_mailbox_index_ + 1); }
};

/**
 * CAN driver, incorporates all available CAN ifaces.
 * Please avoid direct use, prefer @ref CanInitHelper instead.
 */
class CanDriver : public uavcan::ICanDriver, uavcan::Noncopyable
{
    BusEvent update_event_;
    CanIface if0_;
#if UAVCAN_STM32_NUM_IFACES > 1
    CanIface if1_;
#endif

    virtual uavcan::int16_t select(uavcan::CanSelectMasks& inout_masks,
                                   const uavcan::CanFrame* (& pending_tx)[uavcan::MaxCanIfaces],
                                   uavcan::MonotonicTime blocking_deadline);

    static void initOnce();

public:
    template <unsigned RxQueueCapacity>
    CanDriver(CanRxItem (&rx_queue_storage)[UAVCAN_STM32_NUM_IFACES][RxQueueCapacity])
        : update_event_(*this)
        , if0_(bxcan::Can[0], update_event_, 0, rx_queue_storage[0], RxQueueCapacity)
#if UAVCAN_STM32_NUM_IFACES > 1
        , if1_(bxcan::Can[1], update_event_, 1, rx_queue_storage[1], RxQueueCapacity)
#endif
    {
        uavcan::StaticAssert<(RxQueueCapacity <= CanIface::MaxRxQueueCapacity)>::check();
    }

    /**
     * This function returns select masks indicating which interfaces are available for read/write.
     */
    uavcan::CanSelectMasks makeSelectMasks(const uavcan::CanFrame* (& pending_tx)[uavcan::MaxCanIfaces]) const;

    /**
     * Whether there's at least one interface where receive() would return a frame.
     */
    bool hasReadableInterfaces() const;

    /**
     * Returns zero if OK.
     * Returns negative value if failed (e.g. invalid bitrate).
     */
    int init(const uavcan::uint32_t bitrate, const CanIface::OperatingMode mode);

    virtual CanIface* getIface(uavcan::uint8_t iface_index);

    virtual uavcan::uint8_t getNumIfaces() const { return UAVCAN_STM32_NUM_IFACES; }

    /**
     * Whether at least one iface had at least one successful IO since previous call of this method.
     * This is designed for use with iface activity LEDs.
     */
    bool hadActivity();
};

/**
 * Helper class.
 * Normally only this class should be used by the application.
 * 145 usec per Extended CAN frame @ 1 Mbps, e.g. 32 RX slots * 145 usec --> 4.6 msec before RX queue overruns.
 */
template <unsigned RxQueueCapacity = 32>
class CanInitHelper
{
    CanRxItem queue_storage_[UAVCAN_STM32_NUM_IFACES][RxQueueCapacity];

public:
    enum { BitRateAutoDetect = 0 };

    CanDriver driver;

    CanInitHelper() :
        driver(queue_storage_)
    { }

    /**
     * This overload simply configures the provided bitrate.
     * Auto bit rate detection will not be performed.
     * Bitrate value must be positive.
     * @return  Negative value on error; non-negative on success. Refer to constants Err*.
     */
    int init(uavcan::uint32_t bitrate)
    {
        return driver.init(bitrate, CanIface::NormalMode);
    }

    /**
     * This function can either initialize the driver at a fixed bit rate, or it can perform
     * automatic bit rate detection. For theory please refer to the CiA application note #801.
     *
     * @param delay_callable    A callable entity that suspends execution for strictly more than one second.
     *                          The callable entity will be invoked without arguments.
     *                          @ref getRecommendedListeningDelay().
     *
     * @param inout_bitrate     Fixed bit rate or zero. Zero invokes the bit rate detection process.
     *                          If auto detection was used, the function will update the argument
     *                          with established bit rate. In case of an error the value will be undefined.
     *
     * @return                  Negative value on error; non-negative on success. Refer to constants Err*.
     */
    template <typename DelayCallable>
    int init(DelayCallable delay_callable, uavcan::uint32_t& inout_bitrate = BitRateAutoDetect)
    {
        if (inout_bitrate > 0)
        {
            return driver.init(inout_bitrate, CanIface::NormalMode);
        }
        else
        {
            static const uavcan::uint32_t StandardBitRates[] =
            {
                1000000,
                500000,
                250000,
                125000
            };

            for (uavcan::uint8_t br = 0; br < sizeof(StandardBitRates) / sizeof(StandardBitRates[0]); br++)
            {
                inout_bitrate = StandardBitRates[br];

                const int res = driver.init(inout_bitrate, CanIface::SilentMode);

                delay_callable();

                if (res >= 0)
                {
                    for (uavcan::uint8_t iface = 0; iface < driver.getNumIfaces(); iface++)
                    {
                        if (!driver.getIface(iface)->isRxBufferEmpty())
                        {
                            // Re-initializing in normal mode
                            return driver.init(inout_bitrate, CanIface::NormalMode);
                        }
                    }
                }
            }

            return -ErrBitRateNotDetected;
        }
    }

    /**
     * Use this value for listening delay during automatic bit rate detection.
     */
    static uavcan::MonotonicDuration getRecommendedListeningDelay()
    {
        return uavcan::MonotonicDuration::fromMSec(1050);
    }
};

}
<commit_msg>STM32 driver: getRxQueueOverflowCount()<commit_after>/*
 * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
 */

#pragma once

#include <uavcan_stm32/build_config.hpp>
#include <uavcan_stm32/thread.hpp>
#include <uavcan/driver/can.hpp>
#include <uavcan_stm32/bxcan.hpp>

namespace uavcan_stm32
{
/**
 * Driver error codes.
 * These values can be returned from driver functions negated.
 */
//static const uavcan::int16_t ErrUnknown               = 1000; ///< Reserved for future use
static const uavcan::int16_t ErrNotImplemented          = 1001; ///< Feature not implemented
static const uavcan::int16_t ErrInvalidBitRate          = 1002; ///< Bit rate not supported
static const uavcan::int16_t ErrLogic                   = 1003; ///< Internal logic error
static const uavcan::int16_t ErrUnsupportedFrame        = 1004; ///< Frame not supported (e.g. RTR, CAN FD, etc)
static const uavcan::int16_t ErrMsrInakNotSet           = 1005; ///< INAK bit of the MSR register is not 1
static const uavcan::int16_t ErrMsrInakNotCleared       = 1006; ///< INAK bit of the MSR register is not 0
static const uavcan::int16_t ErrBitRateNotDetected      = 1007; ///< Auto bit rate detection could not be finished

/**
 * RX queue item.
 * The application shall not use this directly.
 */
struct CanRxItem
{
    uavcan::uint64_t utc_usec;
    uavcan::CanFrame frame;
    uavcan::CanIOFlags flags;
    CanRxItem()
        : utc_usec(0)
        , flags(0)
    { }
};

/**
 * Single CAN iface.
 * The application shall not use this directly.
 */
class CanIface : public uavcan::ICanIface, uavcan::Noncopyable
{
    class RxQueue
    {
        CanRxItem* const buf_;
        const uavcan::uint8_t capacity_;
        uavcan::uint8_t in_;
        uavcan::uint8_t out_;
        uavcan::uint8_t len_;
        uavcan::uint32_t overflow_cnt_;

        void registerOverflow();

    public:
        RxQueue(CanRxItem* buf, uavcan::uint8_t capacity)
            : buf_(buf)
            , capacity_(capacity)
            , in_(0)
            , out_(0)
            , len_(0)
            , overflow_cnt_(0)
        { }

        void push(const uavcan::CanFrame& frame, const uint64_t& utc_usec, uavcan::CanIOFlags flags);
        void pop(uavcan::CanFrame& out_frame, uavcan::uint64_t& out_utc_usec, uavcan::CanIOFlags& out_flags);

        void reset();

        unsigned getLength() const { return len_; }

        uavcan::uint32_t getOverflowCount() const { return overflow_cnt_; }
    };

    struct Timings
    {
        uavcan::uint16_t prescaler;
        uavcan::uint8_t sjw;
        uavcan::uint8_t bs1;
        uavcan::uint8_t bs2;

        Timings()
            : prescaler(0)
            , sjw(0)
            , bs1(0)
            , bs2(0)
        { }
    };

    struct TxItem
    {
        uavcan::MonotonicTime deadline;
        uavcan::CanFrame frame;
        bool pending;
        bool loopback;
        bool abort_on_error;

        TxItem()
            : pending(false)
            , loopback(false)
            , abort_on_error(false)
        { }
    };

    enum { NumTxMailboxes = 3 };
    enum { NumFilters = 14 };

    static const uavcan::uint32_t TSR_ABRQx[NumTxMailboxes];

    RxQueue rx_queue_;
    bxcan::CanType* const can_;
    uavcan::uint64_t error_cnt_;
    uavcan::uint32_t served_aborts_cnt_;
    BusEvent& update_event_;
    TxItem pending_tx_[NumTxMailboxes];
    uavcan::uint8_t peak_tx_mailbox_index_;
    const uavcan::uint8_t self_index_;
    bool had_activity_;

    int computeTimings(uavcan::uint32_t target_bitrate, Timings& out_timings);

    virtual uavcan::int16_t send(const uavcan::CanFrame& frame, uavcan::MonotonicTime tx_deadline,
                                 uavcan::CanIOFlags flags);

    virtual uavcan::int16_t receive(uavcan::CanFrame& out_frame, uavcan::MonotonicTime& out_ts_monotonic,
                                    uavcan::UtcTime& out_ts_utc, uavcan::CanIOFlags& out_flags);

    virtual uavcan::int16_t configureFilters(const uavcan::CanFilterConfig* filter_configs,
                                             uavcan::uint16_t num_configs);

    virtual uavcan::uint16_t getNumFilters() const { return NumFilters; }

    void handleTxMailboxInterrupt(uavcan::uint8_t mailbox_index, bool txok, uavcan::uint64_t utc_usec);

    bool waitMsrINakBitStateChange(bool target_state);

public:
    enum { MaxRxQueueCapacity = 254 };

    enum OperatingMode
    {
        NormalMode,
        SilentMode
    };

    CanIface(bxcan::CanType* can, BusEvent& update_event, uavcan::uint8_t self_index,
             CanRxItem* rx_queue_buffer, uavcan::uint8_t rx_queue_capacity)
        : rx_queue_(rx_queue_buffer, rx_queue_capacity)
        , can_(can)
        , error_cnt_(0)
        , served_aborts_cnt_(0)
        , update_event_(update_event)
        , peak_tx_mailbox_index_(0)
        , self_index_(self_index)
        , had_activity_(false)
    {
        UAVCAN_ASSERT(self_index_ < UAVCAN_STM32_NUM_IFACES);
    }

    /**
     * Initializes the hardware CAN controller.
     * Assumes:
     *   - Iface clock is enabled
     *   - Iface has been resetted via RCC
     *   - Caller will configure NVIC by itself
     */
    int init(const uavcan::uint32_t bitrate, const OperatingMode mode);

    void handleTxInterrupt(uavcan::uint64_t utc_usec);
    void handleRxInterrupt(uavcan::uint8_t fifo_index, uavcan::uint64_t utc_usec);

    /**
     * This method is used to count errors and abort transmission on error if necessary.
     * This functionality used to be implemented in the SCE interrupt handler, but that approach was
     * generating too much processing overhead, especially on disconnected interfaces.
     *
     * Should be called from RX ISR, TX ISR, and select(); interrupts must be enabled.
     */
    void pollErrorFlagsFromISR();

    void discardTimedOutTxMailboxes(uavcan::MonotonicTime current_time);

    bool canAcceptNewTxFrame(const uavcan::CanFrame& frame) const;
    bool isRxBufferEmpty() const;

    /**
     * Number of RX frames lost due to queue overflow.
     */
    uavcan::uint32_t getRxQueueOverflowCount() const { return rx_queue_.getOverflowCount(); }

    /**
     * Total number of hardware failures and other kinds of errors (e.g. queue overruns).
     * May increase continuously if the interface is not connected to the bus.
     */
    virtual uavcan::uint64_t getErrorCount() const;

    /**
     * Number of times the driver exercised library's requirement to abort transmission on first error.
     * This is an atomic read, it doesn't require a critical section.
     * See @ref uavcan::CanIOFlagAbortOnError.
     */
    uavcan::uint32_t getVoluntaryTxAbortCount() const { return served_aborts_cnt_; }

    /**
     * Returns number of frames pending in the RX queue.
     * This is intended for debug use only.
     */
    unsigned getRxQueueLength() const;

    /**
     * Whether this iface had at least one successful IO since previous call of this method.
     * This is designed for use with iface activity LEDs.
     */
    bool hadActivity();

    /**
     * Peak number of TX mailboxes used concurrently since initialization.
     * Range is [1, 3].
     * Value of 3 suggests that priority inversion could be taking place.
     */
    uavcan::uint8_t getPeakNumTxMailboxesUsed() const { return uavcan::uint8_t(peak_tx_mailbox_index_ + 1); }
};

/**
 * CAN driver, incorporates all available CAN ifaces.
 * Please avoid direct use, prefer @ref CanInitHelper instead.
 */
class CanDriver : public uavcan::ICanDriver, uavcan::Noncopyable
{
    BusEvent update_event_;
    CanIface if0_;
#if UAVCAN_STM32_NUM_IFACES > 1
    CanIface if1_;
#endif

    virtual uavcan::int16_t select(uavcan::CanSelectMasks& inout_masks,
                                   const uavcan::CanFrame* (& pending_tx)[uavcan::MaxCanIfaces],
                                   uavcan::MonotonicTime blocking_deadline);

    static void initOnce();

public:
    template <unsigned RxQueueCapacity>
    CanDriver(CanRxItem (&rx_queue_storage)[UAVCAN_STM32_NUM_IFACES][RxQueueCapacity])
        : update_event_(*this)
        , if0_(bxcan::Can[0], update_event_, 0, rx_queue_storage[0], RxQueueCapacity)
#if UAVCAN_STM32_NUM_IFACES > 1
        , if1_(bxcan::Can[1], update_event_, 1, rx_queue_storage[1], RxQueueCapacity)
#endif
    {
        uavcan::StaticAssert<(RxQueueCapacity <= CanIface::MaxRxQueueCapacity)>::check();
    }

    /**
     * This function returns select masks indicating which interfaces are available for read/write.
     */
    uavcan::CanSelectMasks makeSelectMasks(const uavcan::CanFrame* (& pending_tx)[uavcan::MaxCanIfaces]) const;

    /**
     * Whether there's at least one interface where receive() would return a frame.
     */
    bool hasReadableInterfaces() const;

    /**
     * Returns zero if OK.
     * Returns negative value if failed (e.g. invalid bitrate).
     */
    int init(const uavcan::uint32_t bitrate, const CanIface::OperatingMode mode);

    virtual CanIface* getIface(uavcan::uint8_t iface_index);

    virtual uavcan::uint8_t getNumIfaces() const { return UAVCAN_STM32_NUM_IFACES; }

    /**
     * Whether at least one iface had at least one successful IO since previous call of this method.
     * This is designed for use with iface activity LEDs.
     */
    bool hadActivity();
};

/**
 * Helper class.
 * Normally only this class should be used by the application.
 * 145 usec per Extended CAN frame @ 1 Mbps, e.g. 32 RX slots * 145 usec --> 4.6 msec before RX queue overruns.
 */
template <unsigned RxQueueCapacity = 32>
class CanInitHelper
{
    CanRxItem queue_storage_[UAVCAN_STM32_NUM_IFACES][RxQueueCapacity];

public:
    enum { BitRateAutoDetect = 0 };

    CanDriver driver;

    CanInitHelper() :
        driver(queue_storage_)
    { }

    /**
     * This overload simply configures the provided bitrate.
     * Auto bit rate detection will not be performed.
     * Bitrate value must be positive.
     * @return  Negative value on error; non-negative on success. Refer to constants Err*.
     */
    int init(uavcan::uint32_t bitrate)
    {
        return driver.init(bitrate, CanIface::NormalMode);
    }

    /**
     * This function can either initialize the driver at a fixed bit rate, or it can perform
     * automatic bit rate detection. For theory please refer to the CiA application note #801.
     *
     * @param delay_callable    A callable entity that suspends execution for strictly more than one second.
     *                          The callable entity will be invoked without arguments.
     *                          @ref getRecommendedListeningDelay().
     *
     * @param inout_bitrate     Fixed bit rate or zero. Zero invokes the bit rate detection process.
     *                          If auto detection was used, the function will update the argument
     *                          with established bit rate. In case of an error the value will be undefined.
     *
     * @return                  Negative value on error; non-negative on success. Refer to constants Err*.
     */
    template <typename DelayCallable>
    int init(DelayCallable delay_callable, uavcan::uint32_t& inout_bitrate = BitRateAutoDetect)
    {
        if (inout_bitrate > 0)
        {
            return driver.init(inout_bitrate, CanIface::NormalMode);
        }
        else
        {
            static const uavcan::uint32_t StandardBitRates[] =
            {
                1000000,
                500000,
                250000,
                125000
            };

            for (uavcan::uint8_t br = 0; br < sizeof(StandardBitRates) / sizeof(StandardBitRates[0]); br++)
            {
                inout_bitrate = StandardBitRates[br];

                const int res = driver.init(inout_bitrate, CanIface::SilentMode);

                delay_callable();

                if (res >= 0)
                {
                    for (uavcan::uint8_t iface = 0; iface < driver.getNumIfaces(); iface++)
                    {
                        if (!driver.getIface(iface)->isRxBufferEmpty())
                        {
                            // Re-initializing in normal mode
                            return driver.init(inout_bitrate, CanIface::NormalMode);
                        }
                    }
                }
            }

            return -ErrBitRateNotDetected;
        }
    }

    /**
     * Use this value for listening delay during automatic bit rate detection.
     */
    static uavcan::MonotonicDuration getRecommendedListeningDelay()
    {
        return uavcan::MonotonicDuration::fromMSec(1050);
    }
};

}
<|endoftext|>


<commit_before>/*
* Filter interface for Cipher_Modes
* (C) 2013,2014,2017 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/cipher_filter.h>
#include <botan/internal/rounding.h>

namespace Botan {

namespace {

size_t choose_update_size(size_t update_granularity)
   {
   const size_t target_size = 1024;

   if(update_granularity >= target_size)
      return update_granularity;

   return round_up(target_size, update_granularity);
   }

}

Cipher_Mode_Filter::Cipher_Mode_Filter(Cipher_Mode* mode) :
   Buffered_Filter(choose_update_size(mode->update_granularity()),
                   mode->minimum_final_size()),
   m_mode(mode),
   m_nonce(mode->default_nonce_length() == 0),
   m_buffer(m_mode->update_granularity())
   {
   }

std::string Cipher_Mode_Filter::name() const
   {
   return m_mode->name();
   }

void Cipher_Mode_Filter::set_iv(const InitializationVector& iv)
   {
   m_nonce = unlock(iv.bits_of());
   }

void Cipher_Mode_Filter::set_key(const SymmetricKey& key)
   {
   m_mode->set_key(key);
   }

Key_Length_Specification Cipher_Mode_Filter::key_spec() const
   {
   return m_mode->key_spec();
   }

bool Cipher_Mode_Filter::valid_iv_length(size_t length) const
   {
   return m_mode->valid_nonce_length(length);
   }

void Cipher_Mode_Filter::write(const uint8_t input[], size_t input_length)
   {
   Buffered_Filter::write(input, input_length);
   }

void Cipher_Mode_Filter::end_msg()
   {
   Buffered_Filter::end_msg();
   }

void Cipher_Mode_Filter::start_msg()
   {
   if(m_nonce.empty() && !m_mode->valid_nonce_length(0))
      throw Invalid_State("Cipher " + m_mode->name() + " requires a fresh nonce for each message");

   m_mode->start(m_nonce);
   m_nonce.clear();
   }

void Cipher_Mode_Filter::buffered_block(const uint8_t input[], size_t input_length)
   {
   while(input_length)
      {
      const size_t take = std::min(m_mode->update_granularity(), input_length);

      m_buffer.assign(input, input + take);
      m_mode->update(m_buffer);

      send(m_buffer);

      input += take;
      input_length -= take;
      }
   }

void Cipher_Mode_Filter::buffered_final(const uint8_t input[], size_t input_length)
   {
   secure_vector<uint8_t> buf(input, input + input_length);
   m_mode->finish(buf);
   send(buf);
   }

}
<commit_msg>Addressed #1071 (unfinished change in master cipher_filter.cpp)<commit_after>/*
* Filter interface for Cipher_Modes
* (C) 2013,2014,2017 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/cipher_filter.h>
#include <botan/internal/rounding.h>

namespace Botan {

namespace {

size_t choose_update_size(size_t update_granularity)
   {
   const size_t target_size = 1024;

   if(update_granularity >= target_size)
      return update_granularity;

   return round_up(target_size, update_granularity);
   }

}

Cipher_Mode_Filter::Cipher_Mode_Filter(Cipher_Mode* mode) :
   Buffered_Filter(choose_update_size(mode->update_granularity()),
                   mode->minimum_final_size()),
   m_mode(mode),
   m_nonce(mode->default_nonce_length()),
   m_buffer(m_mode->update_granularity())
   {
   }

std::string Cipher_Mode_Filter::name() const
   {
   return m_mode->name();
   }

void Cipher_Mode_Filter::set_iv(const InitializationVector& iv)
   {
   m_nonce = unlock(iv.bits_of());
   }

void Cipher_Mode_Filter::set_key(const SymmetricKey& key)
   {
   m_mode->set_key(key);
   }

Key_Length_Specification Cipher_Mode_Filter::key_spec() const
   {
   return m_mode->key_spec();
   }

bool Cipher_Mode_Filter::valid_iv_length(size_t length) const
   {
   return m_mode->valid_nonce_length(length);
   }

void Cipher_Mode_Filter::write(const uint8_t input[], size_t input_length)
   {
   Buffered_Filter::write(input, input_length);
   }

void Cipher_Mode_Filter::end_msg()
   {
   Buffered_Filter::end_msg();
   }

void Cipher_Mode_Filter::start_msg()
   {
   if(m_nonce.empty() && !m_mode->valid_nonce_length(0))
      throw Invalid_State("Cipher " + m_mode->name() + " requires a fresh nonce for each message");

   m_mode->start(m_nonce);
   m_nonce.clear();
   }

void Cipher_Mode_Filter::buffered_block(const uint8_t input[], size_t input_length)
   {
   while(input_length)
      {
      const size_t take = std::min(m_mode->update_granularity(), input_length);

      m_buffer.assign(input, input + take);
      m_mode->update(m_buffer);

      send(m_buffer);

      input += take;
      input_length -= take;
      }
   }

void Cipher_Mode_Filter::buffered_final(const uint8_t input[], size_t input_length)
   {
   secure_vector<uint8_t> buf(input, input + input_length);
   m_mode->finish(buf);
   send(buf);
   }

}
<|endoftext|>


<commit_before>#include <vector>
#include "visualizer/atengl.h"
#include "visualizer/shader.h"

namespace aten {
	GLuint createShader(const char* path, GLenum type)
	{
		FILE* fp = nullptr;
		fopen_s(&fp, path, "rt");
		AT_ASSERT(fp != nullptr);

		fseek(fp, 0, SEEK_END);
		auto size = ftell(fp);
		fseek(fp, 0, SEEK_SET);

		std::vector<char> program(size + 1);
		fread(&program[0], 1, size, fp);

		fclose(fp);

		CALL_GL_API(auto shader = ::glCreateShader(type));
		AT_ASSERT(shader != 0);

		const char* p = &program[0];
		const char** pp = &p;

		CALL_GL_API(::glShaderSource(
			shader,
			1,
			pp,
			nullptr));

		CALL_GL_API(::glCompileShader(shader));

		return shader;
	}

	GLuint createProgram(GLuint vs, GLuint fs)
	{
		auto program = ::glCreateProgram();
		AT_ASSERT(program != 0);

		CALL_GL_API(::glAttachShader(program, vs));
		CALL_GL_API(::glAttachShader(program, fs));

		CALL_GL_API(::glLinkProgram(program));

		GLint isLinked = 0;
		CALL_GL_API(::glGetProgramiv(program, GL_LINK_STATUS, &isLinked));
		//AT_ASSERT(isLinked != 0);

		if (isLinked == 0) {
			GLint infoLen = 0;

			CALL_GL_API(::glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen));

			if (infoLen > 1) {
				char* log = (char*)malloc(infoLen);
				memset(log, 0, infoLen);

				CALL_GL_API(::glGetProgramInfoLog(program, infoLen, NULL, log));
				AT_ASSERT(false);

				AT_PRINTF("%s\n", log);

				free(log);
			}
		}

		return program;
	}

	bool shader::init(
		int width, int height,
		const char* pathVS,
		const char* pathFS)
	{
		auto vs = createShader(pathVS, GL_VERTEX_SHADER);
		AT_VRETURN(vs != 0, false);

		auto fs = createShader(pathFS, GL_FRAGMENT_SHADER);
		AT_VRETURN(fs != 0, false);

		m_program = createProgram(vs, fs);
		AT_VRETURN(m_program != 0, false);

		m_width = width;
		m_height = height;

		return true;
	}

	void shader::prepareRender(
		const void* pixels,
		bool revert)
	{
		CALL_GL_API(::glUseProgram(m_program));
	}

	GLint shader::getHandle(const char* name)
	{
		auto handle = ::glGetUniformLocation(m_program, name);
		return handle;
	}
}<commit_msg>Fix a bug about read mode.<commit_after>#include <vector>
#include "visualizer/atengl.h"
#include "visualizer/shader.h"

namespace aten {
	GLuint createShader(const char* path, GLenum type)
	{
		FILE* fp = nullptr;
		fopen_s(&fp, path, "rb");
		AT_ASSERT(fp != nullptr);

		fseek(fp, 0, SEEK_END);
		auto size = ftell(fp);
		fseek(fp, 0, SEEK_SET);

		std::vector<char> program(size + 1);
		fread(&program[0], 1, size, fp);

		fclose(fp);

		CALL_GL_API(auto shader = ::glCreateShader(type));
		AT_ASSERT(shader != 0);

		const char* p = &program[0];
		const char** pp = &p;

		CALL_GL_API(::glShaderSource(
			shader,
			1,
			pp,
			nullptr));

		CALL_GL_API(::glCompileShader(shader));

		return shader;
	}

	GLuint createProgram(GLuint vs, GLuint fs)
	{
		auto program = ::glCreateProgram();
		AT_ASSERT(program != 0);

		CALL_GL_API(::glAttachShader(program, vs));
		CALL_GL_API(::glAttachShader(program, fs));

		CALL_GL_API(::glLinkProgram(program));

		GLint isLinked = 0;
		CALL_GL_API(::glGetProgramiv(program, GL_LINK_STATUS, &isLinked));
		//AT_ASSERT(isLinked != 0);

		if (isLinked == 0) {
			GLint infoLen = 0;

			CALL_GL_API(::glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen));

			if (infoLen > 1) {
				char* log = (char*)malloc(infoLen);
				memset(log, 0, infoLen);

				CALL_GL_API(::glGetProgramInfoLog(program, infoLen, NULL, log));
				AT_ASSERT(false);

				AT_PRINTF("%s\n", log);

				free(log);
			}
		}

		return program;
	}

	bool shader::init(
		int width, int height,
		const char* pathVS,
		const char* pathFS)
	{
		auto vs = createShader(pathVS, GL_VERTEX_SHADER);
		AT_VRETURN(vs != 0, false);

		auto fs = createShader(pathFS, GL_FRAGMENT_SHADER);
		AT_VRETURN(fs != 0, false);

		m_program = createProgram(vs, fs);
		AT_VRETURN(m_program != 0, false);

		m_width = width;
		m_height = height;

		return true;
	}

	void shader::prepareRender(
		const void* pixels,
		bool revert)
	{
		CALL_GL_API(::glUseProgram(m_program));
	}

	GLint shader::getHandle(const char* name)
	{
		auto handle = ::glGetUniformLocation(m_program, name);
		return handle;
	}
}<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://www.qt.io/licensing.  For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "codegeneration.h"

#include "algorithm.h"

#include <QTextStream>
#include <QSet>
#include <QStringList>
#include <QFileInfo>

namespace Utils {

QTCREATOR_UTILS_EXPORT QString fileNameToCppIdentifier(const QString &s)
{
    QString rc;
    const int len = s.size();
    const QChar underscore =  QLatin1Char('_');
    const QChar dot =  QLatin1Char('.');

    for (int i = 0; i < len; i++) {
        const QChar c = s.at(i);
        if (c == underscore || c.isLetterOrNumber())
            rc += c;
        else if (c == dot)
            rc += underscore;
    }
    return rc;
}

QTCREATOR_UTILS_EXPORT QString headerGuard(const QString &file)
{
    return headerGuard(file, QStringList());
}

QTCREATOR_UTILS_EXPORT QString headerGuard(const QString &file, const QStringList &namespaceList)
{
    const QChar underscore = QLatin1Char('_');
    QString rc;
    for (int i = 0; i < namespaceList.count(); i++)
        rc += namespaceList.at(i).toUpper() + underscore;

    const QFileInfo fi(file);
    rc += fileNameToCppIdentifier(fi.fileName()).toUpper();
    return rc;
}

QTCREATOR_UTILS_EXPORT
void writeIncludeFileDirective(const QString &file, bool globalInclude,
                               QTextStream &str)
{
    const QChar opening = globalInclude ?  QLatin1Char('<') : QLatin1Char('"');
    const QChar closing = globalInclude ?  QLatin1Char('>') : QLatin1Char('"');
    str << QLatin1String("#include ") << opening << file <<  closing << QLatin1Char('\n');
}

QTCREATOR_UTILS_EXPORT void writeBeginQtVersionCheck(QTextStream &str)
{
    str << QLatin1String("#if QT_VERSION >= 0x050000\n");
}

static void qtSection(const QStringList &qtIncludes, QTextStream &str)
{
    QStringList sorted = qtIncludes;
    Utils::sort(sorted);
    foreach (const QString &inc, sorted) {
        if (!inc.isEmpty())
            str << QStringLiteral("#include <%1>\n").arg(inc);
    }
}

QTCREATOR_UTILS_EXPORT
void writeQtIncludeSection(const QStringList &qt4,
                           const QStringList &qt5,
                           bool addQtVersionCheck,
                           bool includeQtModule,
                           QTextStream &str)
{
    std::function<QString(const QString &)> trans;
    if (includeQtModule)
        trans = [](const QString &i) { return i; };
    else
        trans = [](const QString &i) { return i.mid(i.indexOf(QLatin1Char('/')) + 1); };

    QSet<QString> qt4Only = QSet<QString>::fromList(Utils::transform(qt4, trans));
    QSet<QString> qt5Only = QSet<QString>::fromList(Utils::transform(qt5, trans));

    if (addQtVersionCheck) {
        QSet<QString> common = qt4Only;
        common.intersect(qt5Only);

        qt4Only.subtract(common);
        qt5Only.subtract(common);

        qtSection(common.toList(), str);

        if (!qt4Only.isEmpty() || !qt5Only.isEmpty()) {
            if (addQtVersionCheck)
                writeBeginQtVersionCheck(str);
            qtSection(qt5Only.toList(), str);
            if (addQtVersionCheck)
                str << QLatin1String("#else\n");
            qtSection(qt4Only.toList(), str);
            if (addQtVersionCheck)
                str << QLatin1String("#endif\n");
        }
    } else {
        if (!qt5Only.isEmpty()) // default to Qt5
            qtSection(qt5Only.toList(), str);
        else
            qtSection(qt4Only.toList(), str);
    }
}

QTCREATOR_UTILS_EXPORT
QString writeOpeningNameSpaces(const QStringList &l, const QString &indent,
                               QTextStream &str)
{
    const int count = l.size();
    QString rc;
    if (count) {
        str << '\n';
        for (int i = 0; i < count; i++) {
            str << rc << "namespace " << l.at(i) << " {\n";
            rc += indent;
        }
    }
    return rc;
}

QTCREATOR_UTILS_EXPORT
void writeClosingNameSpaces(const QStringList &l, const QString &indent,
                            QTextStream &str)
{
    if (!l.empty())
        str << '\n';
    for (int i = l.size() - 1; i >= 0; i--) {
        if (i)
            str << QString(indent.size() * i, QLatin1Char(' '));
        str << "} // namespace " <<  l.at(i) << '\n';
    }
}

} // namespace Utils
<commit_msg>Qt includes: Include qglobal.h when using QT_VERSION<commit_after>/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://www.qt.io/licensing.  For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "codegeneration.h"

#include "algorithm.h"

#include <QTextStream>
#include <QSet>
#include <QStringList>
#include <QFileInfo>

namespace Utils {

QTCREATOR_UTILS_EXPORT QString fileNameToCppIdentifier(const QString &s)
{
    QString rc;
    const int len = s.size();
    const QChar underscore =  QLatin1Char('_');
    const QChar dot =  QLatin1Char('.');

    for (int i = 0; i < len; i++) {
        const QChar c = s.at(i);
        if (c == underscore || c.isLetterOrNumber())
            rc += c;
        else if (c == dot)
            rc += underscore;
    }
    return rc;
}

QTCREATOR_UTILS_EXPORT QString headerGuard(const QString &file)
{
    return headerGuard(file, QStringList());
}

QTCREATOR_UTILS_EXPORT QString headerGuard(const QString &file, const QStringList &namespaceList)
{
    const QChar underscore = QLatin1Char('_');
    QString rc;
    for (int i = 0; i < namespaceList.count(); i++)
        rc += namespaceList.at(i).toUpper() + underscore;

    const QFileInfo fi(file);
    rc += fileNameToCppIdentifier(fi.fileName()).toUpper();
    return rc;
}

QTCREATOR_UTILS_EXPORT
void writeIncludeFileDirective(const QString &file, bool globalInclude,
                               QTextStream &str)
{
    const QChar opening = globalInclude ?  QLatin1Char('<') : QLatin1Char('"');
    const QChar closing = globalInclude ?  QLatin1Char('>') : QLatin1Char('"');
    str << QLatin1String("#include ") << opening << file <<  closing << QLatin1Char('\n');
}

QTCREATOR_UTILS_EXPORT void writeBeginQtVersionCheck(QTextStream &str)
{
    str << QLatin1String("#if QT_VERSION >= 0x050000\n");
}

static void qtSection(const QStringList &qtIncludes, QTextStream &str)
{
    QStringList sorted = qtIncludes;
    Utils::sort(sorted);
    foreach (const QString &inc, sorted) {
        if (!inc.isEmpty())
            str << QStringLiteral("#include <%1>\n").arg(inc);
    }
}

QTCREATOR_UTILS_EXPORT
void writeQtIncludeSection(const QStringList &qt4,
                           const QStringList &qt5,
                           bool addQtVersionCheck,
                           bool includeQtModule,
                           QTextStream &str)
{
    std::function<QString(const QString &)> trans;
    if (includeQtModule)
        trans = [](const QString &i) { return i; };
    else
        trans = [](const QString &i) { return i.mid(i.indexOf(QLatin1Char('/')) + 1); };

    QSet<QString> qt4Only = QSet<QString>::fromList(Utils::transform(qt4, trans));
    QSet<QString> qt5Only = QSet<QString>::fromList(Utils::transform(qt5, trans));

    if (addQtVersionCheck) {
        QSet<QString> common = qt4Only;
        common.intersect(qt5Only);

        // qglobal.h is needed for QT_VERSION
        if (includeQtModule)
            common.insert(QLatin1String("QtCore/qglobal.h"));
        else
            common.insert(QLatin1String("qglobal.h"));

        qt4Only.subtract(common);
        qt5Only.subtract(common);

        qtSection(common.toList(), str);

        if (!qt4Only.isEmpty() || !qt5Only.isEmpty()) {
            if (addQtVersionCheck)
                writeBeginQtVersionCheck(str);
            qtSection(qt5Only.toList(), str);
            if (addQtVersionCheck)
                str << QLatin1String("#else\n");
            qtSection(qt4Only.toList(), str);
            if (addQtVersionCheck)
                str << QLatin1String("#endif\n");
        }
    } else {
        if (!qt5Only.isEmpty()) // default to Qt5
            qtSection(qt5Only.toList(), str);
        else
            qtSection(qt4Only.toList(), str);
    }
}

QTCREATOR_UTILS_EXPORT
QString writeOpeningNameSpaces(const QStringList &l, const QString &indent,
                               QTextStream &str)
{
    const int count = l.size();
    QString rc;
    if (count) {
        str << '\n';
        for (int i = 0; i < count; i++) {
            str << rc << "namespace " << l.at(i) << " {\n";
            rc += indent;
        }
    }
    return rc;
}

QTCREATOR_UTILS_EXPORT
void writeClosingNameSpaces(const QStringList &l, const QString &indent,
                            QTextStream &str)
{
    if (!l.empty())
        str << '\n';
    for (int i = l.size() - 1; i >= 0; i--) {
        if (i)
            str << QString(indent.size() * i, QLatin1Char(' '));
        str << "} // namespace " <<  l.at(i) << '\n';
    }
}

} // namespace Utils
<|endoftext|>


<commit_before>
//  Camera.cpp
//  InternetMap
//

#include "Camera.hpp"
#include <stdlib.h>

static const float MOVE_TIME = 1.0f;
static const float MIN_ZOOM = -10.0f;
//we need a bound on the max. zoom because on small nodes the calculated max puts the target behind the camera.
//this might be a bug in targeting...?
static const float MAX_MAX_ZOOM = -0.2f;

// TODO: better way to register this
void cameraMoveFinishedCallback(void);

Camera::Camera() :
    _displayWidth(0.0f),
    _displayHeight(0.0f),
    _target(0.0f, 0.0f, 0.0f),
    _isMovingToTarget(false),
    _allowIdleAnimation(false),
    _rotation(0.0f),
    _zoom(-3.0f),
    _maxZoom(MAX_MAX_ZOOM),
    _targetMoveStartTime(MAXFLOAT),
    _targetMoveStartPosition(0.0f, 0.0f, 0.0f),
    _zoomStart(0.0f),
    _zoomTarget(0.0f),
    _zoomStartTime(0.0f),
    _zoomDuration(0.0f),
    _updateTime(0.0f),
    _idleStartTime(0.0f),
    _panEndTime(0.0f),
    _zoomVelocity(0.0f),
    _zoomEndTime(0.0f),
    _rotationVelocity(0.0f),
    _rotationEndTime(0.0f),
    _rotationStartTime(0.0f),
    _rotationDuration(0.0f)
{
    _rotationMatrix = Matrix4::identity();
    _zoom = -3.0f;
    _isMovingToTarget = false;
    _panVelocity.x = 0.0f;
    _panVelocity.y = 0.0f;
}

#pragma mark - Main update loop

void Camera::update(TimeInterval currentTime) {
    TimeInterval delta = currentTime - _updateTime;
    _updateTime = currentTime;

    handleIdleMovement(delta);
    handleMomentumPan(delta);
    handleMomentumZoom(delta);
    handleMomentumRotation(delta);
    Vector3 currentTarget = calculateMoveTarget(delta);
    handleAnimatedZoom(delta);
    handleAnimatedRotation(delta);

    float aspect = fabsf(_displayWidth / _displayHeight);
    Matrix4 model = _rotationMatrix * Matrix4::translation(Vector3(-currentTarget.getX(), -currentTarget.getY(), -currentTarget.getZ()));
    Matrix4 view = Matrix4::translation(Vector3(0.0f, 0.0f, _zoom));
    Matrix4 modelView = view * model;
    Matrix4 projectionMatrix = Matrix4::perspective(DegreesToRadians(65.0f), aspect, 0.1f, 100.0f);

    _projectionMatrix = projectionMatrix;
    _modelViewMatrix = modelView;
    _modelViewProjectionMatrix = projectionMatrix * modelView;
}

#pragma mark - Update loop helpers

void Camera::handleIdleMovement(TimeInterval delta) {
    // Rotate camera if idle
    TimeInterval idleTime = _updateTime - _idleStartTime;
    float idleDelay = 0.1;

    if (_allowIdleAnimation && (idleTime > idleDelay)) {
        // Ease in
        float spinupFactor = fminf(1.0, (idleTime - idleDelay) / 2);
        rotateRadiansX(0.0006 * spinupFactor);
        rotateRadiansY(0.0001 * spinupFactor);
    }
}

void Camera::handleMomentumPan(TimeInterval delta) {
    //momentum panning
    if (_panVelocity.x != 0 && _panVelocity.y != 0) {

        TimeInterval rotationTime = _updateTime-_panEndTime;
        static TimeInterval totalTime = 1.0;
        float timeT = rotationTime / totalTime;
        if(timeT > 1.0) {
            _panVelocity.x = _panVelocity.y = 0.0f;
        }
        else {
            //quadratic ease out
            float positionT = 1+(timeT*timeT-2.0f*timeT);

            rotateRadiansX(_panVelocity.x*delta*positionT);
            rotateRadiansY(_panVelocity.y*delta*positionT);
        }
    }
}

void Camera::handleMomentumZoom(TimeInterval delta) {
    //momentum zooming
    if (_zoomVelocity != 0) {
        static TimeInterval totalTime = 0.5;
        TimeInterval zoomTime = _updateTime-_zoomEndTime;
        float timeT = zoomTime / totalTime;
        if(timeT > 1.0) {
            _zoomVelocity = 0;
        }
        else {
            //quadratic ease out
            float positionT = 1+(timeT*timeT-2.0f*timeT);
            zoomByScale(_zoomVelocity*delta*positionT);
        }
    }
}

void Camera::handleMomentumRotation(TimeInterval delta) {
    //momentum rotation
    if (_rotationVelocity != 0) {
        TimeInterval rotationTime = _updateTime-_rotationEndTime;
        static TimeInterval totalTime = 1.0;
        float timeT = rotationTime / totalTime;
        if(timeT > 1.0) {
            _rotationVelocity = 0;
        }
        else {
            //quadratic ease out
            float positionT = 1+(timeT*timeT-2.0f*timeT);

            rotateRadiansZ(_rotationVelocity*delta*positionT);
        }
    }
}

void Camera::handleAnimatedZoom(TimeInterval delta) {
    //animated zoom
    if(_zoomStartTime < _updateTime) {
        float timeT = (_updateTime - _zoomStartTime) / _zoomDuration;
        if(timeT > 1.0f) {
            _zoomStartTime = MAXFLOAT;
        }
        else {
            float positionT;

            // Quadratic ease-in / ease-out
            if (timeT < 0.5f)
            {
                positionT = timeT * timeT * 2;
            }
            else {
                positionT = 1.0f - ((timeT - 1.0f) * (timeT - 1.0f) * 2.0f);
            }
            _zoom = _zoomStart + (_zoomTarget-_zoomStart)*positionT;
        }
    }
}

void Camera::handleAnimatedRotation(TimeInterval delta) {
    //animated rotation
    if (_rotationStartTime < _updateTime) {
        float timeT = (_updateTime - _rotationStartTime) / _rotationDuration;
        if(timeT > 1.0f) {
            _rotationStartTime = MAXFLOAT;
        }
        else {
            float positionT;

            // Quadratic ease-in / ease-out
            if (timeT < 0.5f)
            {
                positionT = timeT * timeT * 2;
            }
            else {
                positionT = 1.0f - ((timeT - 1.0f) * (timeT - 1.0f) * 2.0f);
            }
            _rotationMatrix = Matrix4(Vectormath::Aos::slerp(positionT, _rotationStart , _rotationTarget), Vector3(0.0f, 0.0f, 0.0f));
        }
    }
}
Vector3 Camera::calculateMoveTarget(TimeInterval delta) {
    Vector3 currentTarget;

    //animated move to target
    if(_targetMoveStartTime < _updateTime) {
        float timeT = (_updateTime - _targetMoveStartTime) / MOVE_TIME;
        if(timeT > 1.0f) {
            currentTarget = _target;
            _targetMoveStartTime = MAXFLOAT;
            _isMovingToTarget = false;
            cameraMoveFinishedCallback();
        }
        else {
            float positionT;

            // Quadratic ease-in / ease-out
            if (timeT < 0.5f)
            {
                positionT = timeT * timeT * 2;
            }
            else {
                positionT = 1.0f - ((timeT - 1.0f) * (timeT - 1.0f) * 2.0f);
            }

            currentTarget = _targetMoveStartPosition + ((_target - _targetMoveStartPosition) * positionT);
        }
    }
    else {
        currentTarget = _target;
    }

    return currentTarget;
}

#pragma mark - Information retrieval

float Camera::currentZoom(void) {
    return _zoom;
}

Matrix4 Camera::currentModelViewProjection(void) {
    return _modelViewProjectionMatrix;
}

Matrix4 Camera::currentModelView(void) {
    return _modelViewMatrix;
}

Matrix4 Camera::currentProjection(void) {
    return _projectionMatrix;
}

Vector3 Camera::cameraInObjectSpace(void) {
    Matrix4 invertedModelViewMatrix = Vectormath::Aos::inverse(_modelViewMatrix);
    return invertedModelViewMatrix.getTranslation();
}

Vector3 Camera::applyModelViewToPoint(Vector2 point) {
    Vector4 vec4FromPoint(point.x, point.y, -0.1, 1);
    Matrix4 invertedModelViewProjectionMatrix = Vectormath::Aos::inverse(_modelViewProjectionMatrix);
    vec4FromPoint = invertedModelViewProjectionMatrix * vec4FromPoint;
    vec4FromPoint = vec4FromPoint / vec4FromPoint.getW();

    return Vector3(vec4FromPoint.getX(), vec4FromPoint.getY(), vec4FromPoint.getZ());
}

#pragma mark - View manipulation

void Camera::rotateRadiansX(float rotate) {
    _rotationMatrix = Matrix4::rotation(rotate, Vector3(0.0f, 1.0f, 0.0f)) * _rotationMatrix;
}

void Camera::rotateRadiansY(float rotate) {
    _rotationMatrix = Matrix4::rotation(rotate, Vector3(1.0f, 0.0f, 0.0f)) * _rotationMatrix;
}

void Camera::rotateRadiansZ(float rotate) {
    _rotationMatrix = Matrix4::rotation(rotate, Vector3(0.0f, 0.0f, 1.0f)) * _rotationMatrix;
}

void Camera::rotateAnimated(Matrix4 rotation, TimeInterval duration) {
    _rotationStart = Quaternion(_rotationMatrix.getUpper3x3());
    _rotationTarget = Quaternion(rotation.getUpper3x3());
    _rotationStartTime = _updateTime;
    _rotationDuration = duration;
}

void Camera::zoomByScale(float zoom) {
    _zoom += zoom * -_zoom;
    if(_zoom > _maxZoom) {
        _zoom = _maxZoom;
    }

    if(_zoom < MIN_ZOOM) {
        _zoom = MIN_ZOOM;
    }
}

void Camera::zoomAnimated(float zoom, TimeInterval duration) {
    if(zoom > _maxZoom) {
        zoom = _maxZoom;
    }

    if(zoom < MIN_ZOOM) {
        zoom = MIN_ZOOM;
    }

    _zoomStart = _zoom;
    _zoomTarget = zoom;
    _zoomStartTime = _updateTime;
    _zoomDuration = duration;
}

void Camera::setTarget(const Target& target) {
    _targetMoveStartPosition = _target;
    _target = target.vector;
    _targetMoveStartTime = _updateTime;
    _isMovingToTarget = true;
    _maxZoom = target.maxZoom;
    if (_maxZoom > MAX_MAX_ZOOM) {
        _maxZoom = MAX_MAX_ZOOM;
    }
    zoomAnimated(target.zoom, MOVE_TIME);
}

#pragma mark - Momentum Panning/Zooming/Rotation

void Camera::startMomentumPanWithVelocity(Vector2 velocity) {
    _panEndTime = _updateTime;
    _panVelocity = velocity;
}

void Camera::stopMomentumPan(void) {
    _panVelocity.x = _panVelocity.y = 0.0f;
}

void Camera::startMomentumZoomWithVelocity(float velocity) {
    _zoomEndTime = _updateTime;
    _zoomVelocity = velocity*0.5;
}

void Camera::stopMomentumZoom(void) {
    _zoomVelocity = 0;
}

void Camera::startMomentumRotationWithVelocity(float velocity) {
    _rotationVelocity = velocity;
    _rotationEndTime = _updateTime;
}

void Camera::stopMomentumRotation(void) {
    _rotationVelocity = 0;
}

#pragma mark - Idle Timer

void Camera::resetIdleTimer() {
    _idleStartTime = _updateTime;
}
<commit_msg>fix double initialization<commit_after>
//  Camera.cpp
//  InternetMap
//

#include "Camera.hpp"
#include <stdlib.h>

static const float MOVE_TIME = 1.0f;
static const float MIN_ZOOM = -10.0f;
//we need a bound on the max. zoom because on small nodes the calculated max puts the target behind the camera.
//this might be a bug in targeting...?
static const float MAX_MAX_ZOOM = -0.2f;

// TODO: better way to register this
void cameraMoveFinishedCallback(void);

Camera::Camera() :
    _displayWidth(0.0f),
    _displayHeight(0.0f),
    _target(0.0f, 0.0f, 0.0f),
    _isMovingToTarget(false),
    _allowIdleAnimation(false),
    _rotation(0.0f),
    _zoom(-3.0f),
    _maxZoom(MAX_MAX_ZOOM),
    _targetMoveStartTime(MAXFLOAT),
    _targetMoveStartPosition(0.0f, 0.0f, 0.0f),
    _zoomStart(0.0f),
    _zoomTarget(0.0f),
    _zoomStartTime(0.0f),
    _zoomDuration(0.0f),
    _updateTime(0.0f),
    _idleStartTime(0.0f),
    _panEndTime(0.0f),
    _zoomVelocity(0.0f),
    _zoomEndTime(0.0f),
    _rotationVelocity(0.0f),
    _rotationEndTime(0.0f),
    _rotationStartTime(0.0f),
    _rotationDuration(0.0f)
{
    _rotationMatrix = Matrix4::identity();
    _panVelocity.x = 0.0f;
    _panVelocity.y = 0.0f;
}

#pragma mark - Main update loop

void Camera::update(TimeInterval currentTime) {
    TimeInterval delta = currentTime - _updateTime;
    _updateTime = currentTime;

    handleIdleMovement(delta);
    handleMomentumPan(delta);
    handleMomentumZoom(delta);
    handleMomentumRotation(delta);
    Vector3 currentTarget = calculateMoveTarget(delta);
    handleAnimatedZoom(delta);
    handleAnimatedRotation(delta);

    float aspect = fabsf(_displayWidth / _displayHeight);
    Matrix4 model = _rotationMatrix * Matrix4::translation(Vector3(-currentTarget.getX(), -currentTarget.getY(), -currentTarget.getZ()));
    Matrix4 view = Matrix4::translation(Vector3(0.0f, 0.0f, _zoom));
    Matrix4 modelView = view * model;
    Matrix4 projectionMatrix = Matrix4::perspective(DegreesToRadians(65.0f), aspect, 0.1f, 100.0f);

    _projectionMatrix = projectionMatrix;
    _modelViewMatrix = modelView;
    _modelViewProjectionMatrix = projectionMatrix * modelView;
}

#pragma mark - Update loop helpers

void Camera::handleIdleMovement(TimeInterval delta) {
    // Rotate camera if idle
    TimeInterval idleTime = _updateTime - _idleStartTime;
    float idleDelay = 0.1;

    if (_allowIdleAnimation && (idleTime > idleDelay)) {
        // Ease in
        float spinupFactor = fminf(1.0, (idleTime - idleDelay) / 2);
        rotateRadiansX(0.0006 * spinupFactor);
        rotateRadiansY(0.0001 * spinupFactor);
    }
}

void Camera::handleMomentumPan(TimeInterval delta) {
    //momentum panning
    if (_panVelocity.x != 0 && _panVelocity.y != 0) {

        TimeInterval rotationTime = _updateTime-_panEndTime;
        static TimeInterval totalTime = 1.0;
        float timeT = rotationTime / totalTime;
        if(timeT > 1.0) {
            _panVelocity.x = _panVelocity.y = 0.0f;
        }
        else {
            //quadratic ease out
            float positionT = 1+(timeT*timeT-2.0f*timeT);

            rotateRadiansX(_panVelocity.x*delta*positionT);
            rotateRadiansY(_panVelocity.y*delta*positionT);
        }
    }
}

void Camera::handleMomentumZoom(TimeInterval delta) {
    //momentum zooming
    if (_zoomVelocity != 0) {
        static TimeInterval totalTime = 0.5;
        TimeInterval zoomTime = _updateTime-_zoomEndTime;
        float timeT = zoomTime / totalTime;
        if(timeT > 1.0) {
            _zoomVelocity = 0;
        }
        else {
            //quadratic ease out
            float positionT = 1+(timeT*timeT-2.0f*timeT);
            zoomByScale(_zoomVelocity*delta*positionT);
        }
    }
}

void Camera::handleMomentumRotation(TimeInterval delta) {
    //momentum rotation
    if (_rotationVelocity != 0) {
        TimeInterval rotationTime = _updateTime-_rotationEndTime;
        static TimeInterval totalTime = 1.0;
        float timeT = rotationTime / totalTime;
        if(timeT > 1.0) {
            _rotationVelocity = 0;
        }
        else {
            //quadratic ease out
            float positionT = 1+(timeT*timeT-2.0f*timeT);

            rotateRadiansZ(_rotationVelocity*delta*positionT);
        }
    }
}

void Camera::handleAnimatedZoom(TimeInterval delta) {
    //animated zoom
    if(_zoomStartTime < _updateTime) {
        float timeT = (_updateTime - _zoomStartTime) / _zoomDuration;
        if(timeT > 1.0f) {
            _zoomStartTime = MAXFLOAT;
        }
        else {
            float positionT;

            // Quadratic ease-in / ease-out
            if (timeT < 0.5f)
            {
                positionT = timeT * timeT * 2;
            }
            else {
                positionT = 1.0f - ((timeT - 1.0f) * (timeT - 1.0f) * 2.0f);
            }
            _zoom = _zoomStart + (_zoomTarget-_zoomStart)*positionT;
        }
    }
}

void Camera::handleAnimatedRotation(TimeInterval delta) {
    //animated rotation
    if (_rotationStartTime < _updateTime) {
        float timeT = (_updateTime - _rotationStartTime) / _rotationDuration;
        if(timeT > 1.0f) {
            _rotationStartTime = MAXFLOAT;
        }
        else {
            float positionT;

            // Quadratic ease-in / ease-out
            if (timeT < 0.5f)
            {
                positionT = timeT * timeT * 2;
            }
            else {
                positionT = 1.0f - ((timeT - 1.0f) * (timeT - 1.0f) * 2.0f);
            }
            _rotationMatrix = Matrix4(Vectormath::Aos::slerp(positionT, _rotationStart , _rotationTarget), Vector3(0.0f, 0.0f, 0.0f));
        }
    }
}
Vector3 Camera::calculateMoveTarget(TimeInterval delta) {
    Vector3 currentTarget;

    //animated move to target
    if(_targetMoveStartTime < _updateTime) {
        float timeT = (_updateTime - _targetMoveStartTime) / MOVE_TIME;
        if(timeT > 1.0f) {
            currentTarget = _target;
            _targetMoveStartTime = MAXFLOAT;
            _isMovingToTarget = false;
            cameraMoveFinishedCallback();
        }
        else {
            float positionT;

            // Quadratic ease-in / ease-out
            if (timeT < 0.5f)
            {
                positionT = timeT * timeT * 2;
            }
            else {
                positionT = 1.0f - ((timeT - 1.0f) * (timeT - 1.0f) * 2.0f);
            }

            currentTarget = _targetMoveStartPosition + ((_target - _targetMoveStartPosition) * positionT);
        }
    }
    else {
        currentTarget = _target;
    }

    return currentTarget;
}

#pragma mark - Information retrieval

float Camera::currentZoom(void) {
    return _zoom;
}

Matrix4 Camera::currentModelViewProjection(void) {
    return _modelViewProjectionMatrix;
}

Matrix4 Camera::currentModelView(void) {
    return _modelViewMatrix;
}

Matrix4 Camera::currentProjection(void) {
    return _projectionMatrix;
}

Vector3 Camera::cameraInObjectSpace(void) {
    Matrix4 invertedModelViewMatrix = Vectormath::Aos::inverse(_modelViewMatrix);
    return invertedModelViewMatrix.getTranslation();
}

Vector3 Camera::applyModelViewToPoint(Vector2 point) {
    Vector4 vec4FromPoint(point.x, point.y, -0.1, 1);
    Matrix4 invertedModelViewProjectionMatrix = Vectormath::Aos::inverse(_modelViewProjectionMatrix);
    vec4FromPoint = invertedModelViewProjectionMatrix * vec4FromPoint;
    vec4FromPoint = vec4FromPoint / vec4FromPoint.getW();

    return Vector3(vec4FromPoint.getX(), vec4FromPoint.getY(), vec4FromPoint.getZ());
}

#pragma mark - View manipulation

void Camera::rotateRadiansX(float rotate) {
    _rotationMatrix = Matrix4::rotation(rotate, Vector3(0.0f, 1.0f, 0.0f)) * _rotationMatrix;
}

void Camera::rotateRadiansY(float rotate) {
    _rotationMatrix = Matrix4::rotation(rotate, Vector3(1.0f, 0.0f, 0.0f)) * _rotationMatrix;
}

void Camera::rotateRadiansZ(float rotate) {
    _rotationMatrix = Matrix4::rotation(rotate, Vector3(0.0f, 0.0f, 1.0f)) * _rotationMatrix;
}

void Camera::rotateAnimated(Matrix4 rotation, TimeInterval duration) {
    _rotationStart = Quaternion(_rotationMatrix.getUpper3x3());
    _rotationTarget = Quaternion(rotation.getUpper3x3());
    _rotationStartTime = _updateTime;
    _rotationDuration = duration;
}

void Camera::zoomByScale(float zoom) {
    _zoom += zoom * -_zoom;
    if(_zoom > _maxZoom) {
        _zoom = _maxZoom;
    }

    if(_zoom < MIN_ZOOM) {
        _zoom = MIN_ZOOM;
    }
}

void Camera::zoomAnimated(float zoom, TimeInterval duration) {
    if(zoom > _maxZoom) {
        zoom = _maxZoom;
    }

    if(zoom < MIN_ZOOM) {
        zoom = MIN_ZOOM;
    }

    _zoomStart = _zoom;
    _zoomTarget = zoom;
    _zoomStartTime = _updateTime;
    _zoomDuration = duration;
}

void Camera::setTarget(const Target& target) {
    _targetMoveStartPosition = _target;
    _target = target.vector;
    _targetMoveStartTime = _updateTime;
    _isMovingToTarget = true;
    _maxZoom = target.maxZoom;
    if (_maxZoom > MAX_MAX_ZOOM) {
        _maxZoom = MAX_MAX_ZOOM;
    }
    zoomAnimated(target.zoom, MOVE_TIME);
}

#pragma mark - Momentum Panning/Zooming/Rotation

void Camera::startMomentumPanWithVelocity(Vector2 velocity) {
    _panEndTime = _updateTime;
    _panVelocity = velocity;
}

void Camera::stopMomentumPan(void) {
    _panVelocity.x = _panVelocity.y = 0.0f;
}

void Camera::startMomentumZoomWithVelocity(float velocity) {
    _zoomEndTime = _updateTime;
    _zoomVelocity = velocity*0.5;
}

void Camera::stopMomentumZoom(void) {
    _zoomVelocity = 0;
}

void Camera::startMomentumRotationWithVelocity(float velocity) {
    _rotationVelocity = velocity;
    _rotationEndTime = _updateTime;
}

void Camera::stopMomentumRotation(void) {
    _rotationVelocity = 0;
}

#pragma mark - Idle Timer

void Camera::resetIdleTimer() {
    _idleStartTime = _updateTime;
}
<|endoftext|>