<commit_before>/// @file
/// @version 2.2
///
/// @section LICENSE
///
/// This program is free software; you can redistribute it and/or modify it under
/// the terms of the BSD license: http://opensource.org/licenses/BSD-3-Clause

#include <stdint.h>

#include <gtypes/Rectangle.h>
#include <gtypes/Vector2.h>
#include <hltypes/harray.h>
#include <hltypes/hlog.h>
#include <hltypes/hmap.h>
#include <hltypes/hsbase.h>
#include <hltypes/hstring.h>

#include "Deserialize.h"
#include "Factory.h"
#include "liteser.h"
#include "Serializable.h"
#include "Type.h"
#include "Utility.h"
#include "Variable.h"

namespace liteser
{
	inline void __loadVariable(Variable* variable, Type::Value loadType)
	{
		switch (loadType)
		{
		case Type::INT8:	*variable->value<char>()			= stream->load_char();		break;
		case Type::UINT8:	*variable->value<unsigned char>()	= stream->load_uchar();		break;
		case Type::INT16:	*variable->value<int16_t>()			= stream->load_short();		break;
		case Type::UINT16:	*variable->value<uint16_t>()		= stream->load_ushort();	break;
		case Type::INT32:	*variable->value<int32_t>()			= stream->load_int();		break;
		case Type::UINT32:	*variable->value<uint32_t>()		= stream->load_uint();		break;
		case Type::FLOAT:	*variable->value<float>()			= stream->load_float();		break;
		case Type::DOUBLE:	*variable->value<double>()			= stream->load_double();	break;
		case Type::BOOL:	*variable->value<bool>()			= stream->load_bool();		break;
		case Type::HSTR:	_load(variable->value<hstr>());									break;
		case Type::GRECT:	_load(variable->value<grect>());								break;
		case Type::GVEC2:	_load(variable->value<gvec2>());								break;
		case Type::GVEC3:	_load(variable->value<gvec3>());								break;
		case Type::OBJECT:	_load(variable->value<Serializable>());							break;
		case Type::OBJPTR:	_load(variable->value<Serializable*>());						break;
		case Type::HARRAY:	__loadContainer(variable, loadType);							break;
		case Type::HMAP:	__loadContainer(variable, loadType);							break;
		}
	}

	inline bool __skipVariable(Type::Value loadType)
	{
		switch (loadType)
		{
		case Type::INT8:	stream->load_char();			return true;
		case Type::UINT8:	stream->load_uchar();			return true;
		case Type::INT16:	stream->load_short();			return true;
		case Type::UINT16:	stream->load_ushort();			return true;
		case Type::INT32:	stream->load_int();				return true;
		case Type::UINT32:	stream->load_uint();			return true;
		case Type::FLOAT:	stream->load_float();			return true;
		case Type::DOUBLE:	stream->load_double();			return true;
		case Type::BOOL:	stream->load_bool();			return true;
		case Type::HSTR:	{ hstr var;		_load(&var);	return true; }
		case Type::GRECT:	{ grect var;	_load(&var);	return true; }
		case Type::GVEC2:	{ gvec2 var;	_load(&var);	return true; }
		case Type::GVEC3:	{ gvec3 var;	_load(&var);	return true; }
		case Type::OBJECT:	return __skipObject();
		case Type::OBJPTR:	return __skipObject();
		case Type::HARRAY:	return __skipContainer(loadType);
		case Type::HMAP:	return __skipContainer(loadType);
		}
		return false;
	}

	void __loadContainer(Variable* variable, Type::Value type)
	{
		variable->containerSize = stream->load_uint();
		if (variable->containerSize > 0)
		{
			Type::Value loadType = Type::NONE;
			uint32_t typeSize = stream->load_uint();
			if (typeSize != variable->type->subTypes.size())
			{
				throw hl_exception(hsprintf("Number of types for container does not match. Expected: %d, Got: %d", variable->type->subTypes.size(), typeSize));
			}
			for_itert (uint32_t, i, 0, typeSize)
			{
				loadType = (Type::Value)stream->load_uchar();
				if (loadType != variable->type->subTypes[i]->value)
				{
					throw hl_exception(hsprintf("Variable type has changed. Expected: %02X, Got: %02X", variable->type->value, loadType));
				}
				if (loadType == Type::HARRAY || loadType == Type::HMAP)
				{
					throw hl_exception(hsprintf("Template container within a template container detected, not supported: %02X", loadType));
				}
			}
			variable->createSubVariables(type);
			foreach (Variable*, it, variable->subVariables)
			{
				__loadVariable((*it), (*it)->type->value);
			}
			if (type == Type::HMAP)
			{
				variable->applyHmapSubVariables(type);
			}
		}
	}

	bool __skipContainer(Type::Value type)
	{
		bool result = true;
		uint32_t containerSize = stream->load_uint();
		if (containerSize > 0)
		{
			harray<Type::Value> subTypes;
			int subTypesSize = (type == Type::HMAP ? 2 : 1);
			uint32_t typeSize = stream->load_uint();
			if (typeSize != subTypesSize)
			{
				throw hl_exception(hsprintf("Number of types for container does not match. Expected: %d, Got: %d", subTypesSize, typeSize));
			}
			for_itert (uint32_t, i, 0, typeSize)
			{
				subTypes += (Type::Value)stream->load_uchar();
			}
			foreach (Type::Value, it, subTypes)
			{
				for_itert (uint32_t, i, 0, containerSize)
				{
					result &= __skipVariable(*it);
				}
			}
		}
		return result;
	}

	void _load(hstr* value)
	{
		uint32_t id = stream->load_uint();
		if (!__tryGetString(id, value))
		{
			*value = stream->load_string();
			__tryMapString(&id, *value);
		}
	}

	void _load(grect* value)
	{
		value->x = stream->load_float();
		value->y = stream->load_float();
		value->w = stream->load_float();
		value->h = stream->load_float();
	}

	void _load(gvec2* value)
	{
		value->x = stream->load_float();
		value->y = stream->load_float();
	}

	void _load(gvec3* value)
	{
		value->x = stream->load_float();
		value->y = stream->load_float();
		value->z = stream->load_float();
	}

	void _load(Serializable* value)
	{
		__loadObject(&value);
	}

	void _load(Serializable** value)
	{
		if (*value != NULL)
		{
			delete (*value);
			*value = NULL;
		}
		__loadObject(value);
	}

	void __loadObject(Serializable** value)
	{
		uint32_t id = stream->load_uint();
		if (!__tryGetObject(id, value))
		{
			hstr className;
			_load(&className);
			if (*value == NULL)
			{
				*value = Factory::create(className);
			}
			__tryMapObject(&id, *value);
			harray<Variable*> variables = (*value)->_lsVars();
			uint32_t size = stream->load_uint();
			Variable* variable = NULL;
			hstr variableName;
			Type::Value loadType;
			while (size > 0 && variables.size() > 0)
			{
				_load(&variableName);
				variable = NULL;
				foreach (Variable*, it, variables)
				{
					if ((*it)->name == variableName)
					{
						variable = (*it);
						break;
					}
				}
				loadType = (Type::Value)stream->load_uchar();
				if (variable != NULL)
				{
					if (loadType != variable->type->value)
					{
						throw hl_exception(hsprintf("Variable type has changed. Expected: %02X, Got: %02X", variable->type->value, loadType));
					}
					__loadVariable(variable, loadType);
					variables.remove(variable);
					delete variable;
				}
				else
				{
					hlog::warn(liteser::logTag, "Could not find variable with name: " + variableName);
					__skipVariable(loadType);
				}
				--size;
			}
			if (variables.size() > 0)
			{
				hlog::warn(liteser::logTag, "Not all variables were previously saved in class: " + className);
				foreach (Variable*, it, variables)
				{
					delete (*it);
				}
			}
		}
		else if (id == 0)
		{
			*value = NULL;
		}
	}

	bool __skipObject()
	{
		Serializable* dummy = NULL;
		uint32_t id = stream->load_uint();
		if (!__tryGetObject(id, &dummy))
		{
			hstr className;
			_load(&className);
			__forceMapEmptyObject(); // required for proper indexing of later variables
			uint32_t size = stream->load_uint();
			hstr variableName;
			for_itert (uint32_t, i, 0, size)
			{
				_load(&variableName);
				__skipVariable((Type::Value)stream->load_uchar());
			}
		}
		return true;
	}

	void _loadHarray(harray<Serializable*>* value)
	{
		uint32_t size = stream->load_uint();
		if (size > 0)
		{
			Serializable* object;
			for_itert (uint32_t, i, 0, size)
			{
				object = NULL;
				__loadObject(&object);
				value->add(object);
			}
		}
	}

#define DEFINE_LOAD_HARRAY(type, loadType) \
	void _loadHarray(harray<type>* value) \
	{ \
		uint32_t size = stream->load_uint(); \
		for_itert (uint32_t, i, 0, size) \
		{ \
			value->add(stream->load_ ## loadType()); \
		} \
	}

#define DEFINE_LOAD_HARRAY_X(type) \
	void _loadHarray(harray<type>* value) \
	{ \
		uint32_t size = stream->load_uint(); \
		if (size > 0) \
		{ \
			type object; \
			for_itert (uint32_t, i, 0, size) \
			{ \
				_load(&object); \
				value->add(object); \
			} \
		} \
	}

	DEFINE_LOAD_HARRAY(char, char);
	DEFINE_LOAD_HARRAY(unsigned char, uchar);
	DEFINE_LOAD_HARRAY(int16_t, short);
	DEFINE_LOAD_HARRAY(uint16_t, ushort);
	DEFINE_LOAD_HARRAY(int32_t, int);
	DEFINE_LOAD_HARRAY(uint32_t, uint);
	DEFINE_LOAD_HARRAY(float, float);
	DEFINE_LOAD_HARRAY(double, double);
	DEFINE_LOAD_HARRAY_X(hstr);
	DEFINE_LOAD_HARRAY_X(grect);
	DEFINE_LOAD_HARRAY_X(gvec2);
	DEFINE_LOAD_HARRAY_X(gvec3);

}
<commit_msg>- fixed small bug when loading NULL values<commit_after>/// @file
/// @version 2.2
///
/// @section LICENSE
///
/// This program is free software; you can redistribute it and/or modify it under
/// the terms of the BSD license: http://opensource.org/licenses/BSD-3-Clause

#include <stdint.h>

#include <gtypes/Rectangle.h>
#include <gtypes/Vector2.h>
#include <hltypes/harray.h>
#include <hltypes/hlog.h>
#include <hltypes/hmap.h>
#include <hltypes/hsbase.h>
#include <hltypes/hstring.h>

#include "Deserialize.h"
#include "Factory.h"
#include "liteser.h"
#include "Serializable.h"
#include "Type.h"
#include "Utility.h"
#include "Variable.h"

namespace liteser
{
	inline void __loadVariable(Variable* variable, Type::Value loadType)
	{
		switch (loadType)
		{
		case Type::INT8:	*variable->value<char>()			= stream->load_char();		break;
		case Type::UINT8:	*variable->value<unsigned char>()	= stream->load_uchar();		break;
		case Type::INT16:	*variable->value<int16_t>()			= stream->load_short();		break;
		case Type::UINT16:	*variable->value<uint16_t>()		= stream->load_ushort();	break;
		case Type::INT32:	*variable->value<int32_t>()			= stream->load_int();		break;
		case Type::UINT32:	*variable->value<uint32_t>()		= stream->load_uint();		break;
		case Type::FLOAT:	*variable->value<float>()			= stream->load_float();		break;
		case Type::DOUBLE:	*variable->value<double>()			= stream->load_double();	break;
		case Type::BOOL:	*variable->value<bool>()			= stream->load_bool();		break;
		case Type::HSTR:	_load(variable->value<hstr>());									break;
		case Type::GRECT:	_load(variable->value<grect>());								break;
		case Type::GVEC2:	_load(variable->value<gvec2>());								break;
		case Type::GVEC3:	_load(variable->value<gvec3>());								break;
		case Type::OBJECT:	_load(variable->value<Serializable>());							break;
		case Type::OBJPTR:	_load(variable->value<Serializable*>());						break;
		case Type::HARRAY:	__loadContainer(variable, loadType);							break;
		case Type::HMAP:	__loadContainer(variable, loadType);							break;
		}
	}

	inline bool __skipVariable(Type::Value loadType)
	{
		switch (loadType)
		{
		case Type::INT8:	stream->load_char();			return true;
		case Type::UINT8:	stream->load_uchar();			return true;
		case Type::INT16:	stream->load_short();			return true;
		case Type::UINT16:	stream->load_ushort();			return true;
		case Type::INT32:	stream->load_int();				return true;
		case Type::UINT32:	stream->load_uint();			return true;
		case Type::FLOAT:	stream->load_float();			return true;
		case Type::DOUBLE:	stream->load_double();			return true;
		case Type::BOOL:	stream->load_bool();			return true;
		case Type::HSTR:	{ hstr var;		_load(&var);	return true; }
		case Type::GRECT:	{ grect var;	_load(&var);	return true; }
		case Type::GVEC2:	{ gvec2 var;	_load(&var);	return true; }
		case Type::GVEC3:	{ gvec3 var;	_load(&var);	return true; }
		case Type::OBJECT:	return __skipObject();
		case Type::OBJPTR:	return __skipObject();
		case Type::HARRAY:	return __skipContainer(loadType);
		case Type::HMAP:	return __skipContainer(loadType);
		}
		return false;
	}

	void __loadContainer(Variable* variable, Type::Value type)
	{
		variable->containerSize = stream->load_uint();
		if (variable->containerSize > 0)
		{
			Type::Value loadType = Type::NONE;
			uint32_t typeSize = stream->load_uint();
			if (typeSize != variable->type->subTypes.size())
			{
				throw hl_exception(hsprintf("Number of types for container does not match. Expected: %d, Got: %d", variable->type->subTypes.size(), typeSize));
			}
			for_itert (uint32_t, i, 0, typeSize)
			{
				loadType = (Type::Value)stream->load_uchar();
				if (loadType != variable->type->subTypes[i]->value)
				{
					throw hl_exception(hsprintf("Variable type has changed. Expected: %02X, Got: %02X", variable->type->value, loadType));
				}
				if (loadType == Type::HARRAY || loadType == Type::HMAP)
				{
					throw hl_exception(hsprintf("Template container within a template container detected, not supported: %02X", loadType));
				}
			}
			variable->createSubVariables(type);
			foreach (Variable*, it, variable->subVariables)
			{
				__loadVariable((*it), (*it)->type->value);
			}
			if (type == Type::HMAP)
			{
				variable->applyHmapSubVariables(type);
			}
		}
	}

	bool __skipContainer(Type::Value type)
	{
		bool result = true;
		uint32_t containerSize = stream->load_uint();
		if (containerSize > 0)
		{
			harray<Type::Value> subTypes;
			int subTypesSize = (type == Type::HMAP ? 2 : 1);
			uint32_t typeSize = stream->load_uint();
			if (typeSize != subTypesSize)
			{
				throw hl_exception(hsprintf("Number of types for container does not match. Expected: %d, Got: %d", subTypesSize, typeSize));
			}
			for_itert (uint32_t, i, 0, typeSize)
			{
				subTypes += (Type::Value)stream->load_uchar();
			}
			foreach (Type::Value, it, subTypes)
			{
				for_itert (uint32_t, i, 0, containerSize)
				{
					result &= __skipVariable(*it);
				}
			}
		}
		return result;
	}

	void _load(hstr* value)
	{
		uint32_t id = stream->load_uint();
		if (!__tryGetString(id, value))
		{
			*value = stream->load_string();
			__tryMapString(&id, *value);
		}
	}

	void _load(grect* value)
	{
		value->x = stream->load_float();
		value->y = stream->load_float();
		value->w = stream->load_float();
		value->h = stream->load_float();
	}

	void _load(gvec2* value)
	{
		value->x = stream->load_float();
		value->y = stream->load_float();
	}

	void _load(gvec3* value)
	{
		value->x = stream->load_float();
		value->y = stream->load_float();
		value->z = stream->load_float();
	}

	void _load(Serializable* value)
	{
		__loadObject(&value);
	}

	void _load(Serializable** value)
	{
		__loadObject(value);
	}

	void __loadObject(Serializable** value)
	{
		uint32_t id = stream->load_uint();
		if (!__tryGetObject(id, value))
		{
			hstr className;
			_load(&className);
			if (*value == NULL)
			{
				*value = Factory::create(className);
			}
			__tryMapObject(&id, *value);
			harray<Variable*> variables = (*value)->_lsVars();
			uint32_t size = stream->load_uint();
			Variable* variable = NULL;
			hstr variableName;
			Type::Value loadType;
			while (size > 0 && variables.size() > 0)
			{
				_load(&variableName);
				variable = NULL;
				foreach (Variable*, it, variables)
				{
					if ((*it)->name == variableName)
					{
						variable = (*it);
						break;
					}
				}
				loadType = (Type::Value)stream->load_uchar();
				if (variable != NULL)
				{
					if (loadType != variable->type->value)
					{
						throw hl_exception(hsprintf("Variable type has changed. Expected: %02X, Got: %02X", variable->type->value, loadType));
					}
					__loadVariable(variable, loadType);
					variables.remove(variable);
					delete variable;
				}
				else
				{
					hlog::warn(liteser::logTag, "Could not find variable with name: " + variableName);
					__skipVariable(loadType);
				}
				--size;
			}
			if (variables.size() > 0)
			{
				hlog::warn(liteser::logTag, "Not all variables were previously saved in class: " + className);
				foreach (Variable*, it, variables)
				{
					delete (*it);
				}
			}
		}
		else if (id == 0)
		{
			*value = NULL;
		}
	}

	bool __skipObject()
	{
		Serializable* dummy = NULL;
		uint32_t id = stream->load_uint();
		if (!__tryGetObject(id, &dummy))
		{
			hstr className;
			_load(&className);
			__forceMapEmptyObject(); // required for proper indexing of later variables
			uint32_t size = stream->load_uint();
			hstr variableName;
			for_itert (uint32_t, i, 0, size)
			{
				_load(&variableName);
				__skipVariable((Type::Value)stream->load_uchar());
			}
		}
		return true;
	}

	void _loadHarray(harray<Serializable*>* value)
	{
		uint32_t size = stream->load_uint();
		if (size > 0)
		{
			Serializable* object;
			for_itert (uint32_t, i, 0, size)
			{
				object = NULL;
				__loadObject(&object);
				value->add(object);
			}
		}
	}

#define DEFINE_LOAD_HARRAY(type, loadType) \
	void _loadHarray(harray<type>* value) \
	{ \
		uint32_t size = stream->load_uint(); \
		for_itert (uint32_t, i, 0, size) \
		{ \
			value->add(stream->load_ ## loadType()); \
		} \
	}

#define DEFINE_LOAD_HARRAY_X(type) \
	void _loadHarray(harray<type>* value) \
	{ \
		uint32_t size = stream->load_uint(); \
		if (size > 0) \
		{ \
			type object; \
			for_itert (uint32_t, i, 0, size) \
			{ \
				_load(&object); \
				value->add(object); \
			} \
		} \
	}

	DEFINE_LOAD_HARRAY(char, char);
	DEFINE_LOAD_HARRAY(unsigned char, uchar);
	DEFINE_LOAD_HARRAY(int16_t, short);
	DEFINE_LOAD_HARRAY(uint16_t, ushort);
	DEFINE_LOAD_HARRAY(int32_t, int);
	DEFINE_LOAD_HARRAY(uint32_t, uint);
	DEFINE_LOAD_HARRAY(float, float);
	DEFINE_LOAD_HARRAY(double, double);
	DEFINE_LOAD_HARRAY_X(hstr);
	DEFINE_LOAD_HARRAY_X(grect);
	DEFINE_LOAD_HARRAY_X(gvec2);
	DEFINE_LOAD_HARRAY_X(gvec3);

}
<|endoftext|>


<commit_before>#include <sh/sh.hpp>
#include <sh/shutil.hpp>
#include <iostream>
#include "Shader.hpp"
#include "Globals.hpp"

using namespace SH;
using namespace ShUtil;

class DiscoShader : public Shader {
public:
  DiscoShader();
  ~DiscoShader();

  bool init();
  void bind();

  ShProgram vertex() { return vsh;}
  ShProgram fragment() { return fsh;}

  ShProgram vsh, fsh;
};

DiscoShader::DiscoShader()
  : Shader("Cellnoise Disco Shader")
{
}

DiscoShader::~DiscoShader()
{
}

bool DiscoShader::init()
{
  std::cerr << "Initializing " << name() << std::endl;
  vsh = ShKernelLib::shVsh( Globals::mv, Globals::mvp );
  vsh = vsh << shExtract("lightPos") << Globals::lightPos;
  vsh = namedCombine(vsh, keep<ShPoint4f>("posm"));
  vsh = shSwizzle("texcoord", "normal", "halfVec", "lightVec", "posh") << vsh;

  ShAttrib1f SH_DECL(time) = 0.0;
  time.range(0.0f, 4.0f);

  ShAttrib1f SH_DECL(tileFrequency) = 16.0;
  tileFrequency.range(0.0, 128.0);

  ShAttrib1f SH_DECL(exponent) = ShAttrib1f(35.0);
  exponent.range(5.0f, 500.0f);

  ShProgram discoTiler = SH_BEGIN_PROGRAM() {
    ShInputTexCoord2f SH_DECL(texcoord);
    ShOutputColor3f SH_DECL(kd);
    ShOutputColor3f SH_DECL(ks);

    ShAttrib3f p;
    p(0,1) = (texcoord * tileFrequency);
    p(2) = 0.0f; // use z for the time parameter

    // use cellnoise to decide when to switch colours on a cell
    ShAttrib1f timestep = cellnoise<1>(p);
    ShAttrib1f timeoffset = time / timestep;
    p(2) = timeoffset;

    // use cellnoise to find colour of a cell
    ks = kd = cellnoise<3>(p);
  } SH_END;

  fsh = ShKernelLib::shPhong<ShColor3f>() << shExtract("specExp") << exponent;
  fsh = fsh << discoTiler;
  return true;
}

void DiscoShader::bind()
{
  vsh->code()->print(std::cerr);
  fsh->code()->print(std::cerr);
  std::cerr << "Binding " << name() << std::endl;
  shBindShader(vsh);
  shBindShader(fsh);
}

DiscoShader the_disco_shader;
<commit_msg>updated Disco Shader<commit_after>#include <sh/sh.hpp>
#include <sh/shutil.hpp>
#include <iostream>
#include "Shader.hpp"
#include "Globals.hpp"

using namespace SH;
using namespace ShUtil;

class DiscoShader : public Shader {
public:
  DiscoShader();
  ~DiscoShader();

  bool init();
  void bind();

  ShProgram vertex() { return vsh;}
  ShProgram fragment() { return fsh;}

  ShProgram vsh, fsh;
};

DiscoShader::DiscoShader()
  : Shader("Cellnoise Disco Shader")
{
}

DiscoShader::~DiscoShader()
{
}

bool DiscoShader::init()
{
  std::cerr << "Initializing " << name() << std::endl;
  vsh = ShKernelLib::shVsh( Globals::mv, Globals::mvp );
  vsh = vsh << shExtract("lightPos") << Globals::lightPos;
  vsh = namedCombine(vsh, keep<ShPoint4f>("posm"));
  vsh = shSwizzle("texcoord", "normal", "halfVec", "lightVec", "posh") << vsh;

  ShAttrib1f SH_DECL(time) = 0.0;
  time.range(0.0f, 4.0f);

  ShAttrib1f SH_DECL(tileFrequency) = 16.0;
  tileFrequency.range(0.0, 128.0);

  ShAttrib1f SH_DECL(exponent) = ShAttrib1f(35.0);
  exponent.range(5.0f, 500.0f);

  ShProgram discoTiler = SH_BEGIN_PROGRAM() {
    ShInputTexCoord2f SH_DECL(texcoord);
    ShOutputColor3f SH_DECL(kd);
    ShOutputColor3f SH_DECL(ks);

    ShAttrib3f p;
    p(0,1) = (texcoord * tileFrequency);
    p(2) = 0.0f; // use z for the time parameter

    // use cellnoise to decide when to switch colours on a cell
    ShAttrib1f timestep = cellnoise<1>(p);
    ShAttrib1f timeoffset = time / timestep;
    p(2) = timeoffset;

    // use cellnoise to find colour of a cell and use power to make
    // colours funkier (and maybe add environment mapping sweetness?)
    kd = 2.0f * cellnoise<3>(p);
    kd(0) = pow(kd(0), ShConstant1f(2.0f));
    kd(1) = pow(kd(1), ShConstant1f(2.0f));
    kd(2) = pow(kd(2), ShConstant1f(2.0f));
    ks = kd;
  } SH_END;

  fsh = ShKernelLib::shPhong<ShColor3f>() << shExtract("specExp") << exponent;
  fsh = fsh << discoTiler;
  return true;
}

void DiscoShader::bind()
{
  vsh->code()->print(std::cerr);
  fsh->code()->print(std::cerr);
  std::cerr << "Binding " << name() << std::endl;
  shBindShader(vsh);
  shBindShader(fsh);
}

DiscoShader the_disco_shader;
<|endoftext|>


<commit_before>/*
 * FD8Protocol.hpp
 *
 *  Created on: Jun 19, 2014
 *      Author: Pimenta
 */

#ifndef FD8PROTOCOL_HPP_
#define FD8PROTOCOL_HPP_

namespace fd8protocol {

enum {
  MTYPE_SYNC = 0,
  MTYPE_CREATE_FOLDER,
  MTYPE_UPDATE_FOLDER,
  MTYPE_DELETE_FOLDER,
  MTYPE_CREATE_FILE,
  MTYPE_UPDATE_FILE,
  MTYPE_DELETE_FILE,
  MTYPE_COMMANDS,
  MTYPE_CMD_DUPLICATION,
  MTYPE_FILE

};

} // namespace fd8protocol

#endif /* FD8PROTOCOL_HPP_ */
<commit_msg>Refactoring duplication commands list to generic commands list<commit_after>/*
 * FD8Protocol.hpp
 *
 *  Created on: Jun 19, 2014
 *      Author: Pimenta
 */

#ifndef FD8PROTOCOL_HPP_
#define FD8PROTOCOL_HPP_

namespace fd8protocol {

enum {
  MTYPE_SYNC = 0,
  MTYPE_CREATE_FOLDER,
  MTYPE_UPDATE_FOLDER,
  MTYPE_DELETE_FOLDER,
  MTYPE_CREATE_FILE,
  MTYPE_UPDATE_FILE,
  MTYPE_DELETE_FILE,
  MTYPE_COMMANDS,
  MTYPE_CMD_DUPLICATION,
  MTYPE_FILE
};

} // namespace fd8protocol

#endif /* FD8PROTOCOL_HPP_ */
<|endoftext|>


<commit_before>#include <QCache>
#include <QDebug>
#include <QString>
#include <QStringList>
#include <QtConcurrentRun>

#include <algorithm>

#include <AlpinoCorpus/Error.hh>
#include "FilterModel.hh"

FilterModel::FilterModel(CorpusPtr corpus, QObject *parent)
:
    QAbstractTableModel(parent),
    d_corpus(corpus),
    d_hits(0),
    d_entryCache(new EntryCache(1000000)),
    d_timer(new QTimer)
{
    connect(d_timer.data(), SIGNAL(timeout()),
        SLOT(fireDataChanged()));
    connect(this, SIGNAL(queryStopped(int, int)),
        SLOT(lastDataChanged(int, int)));
    connect(this, SIGNAL(queryFinished(int, int, bool)),
        SLOT(lastDataChanged(int, int, bool)));
    connect(this, SIGNAL(queryFinished(int, int, bool)),
        SLOT(finalizeQuery(int, int, bool)));
}

FilterModel::~FilterModel()
{
    cancelQuery();
}

int FilterModel::columnCount(QModelIndex const &index) const
{
    return 2;
}

int FilterModel::rowCount(QModelIndex const &index) const
{
    QMutexLocker locker(&d_resultsMutex);
    return d_results.size();
}

QVariant FilterModel::data(QModelIndex const &index, int role) const
{
    QMutexLocker locker(&d_resultsMutex);

    if (!index.isValid()
        || index.row() >= d_results.size()
        || index.row() < 0
        || !(role == Qt::DisplayRole || role == Qt::UserRole))
        return QVariant();

    switch (index.column())
    {
        case 0:
            return d_results.at(index.row()).first;
        case 1:
            return d_results.at(index.row()).second;
        default:
            return QVariant();
    }
}

void FilterModel::finalizeQuery(int n, int totalEntries, bool cached)
{
    if (!cached) {
        // Cache the query
        d_entryCache->insert(d_query, new CacheItem(d_hits, d_results));
    }
}

QVariant FilterModel::headerData(int column, Qt::Orientation orientation, int role) const
{
    if (orientation != Qt::Horizontal
        || role != Qt::DisplayRole)
        return QVariant();

    switch (column)
    {
        case 0:
            return tr("File");
        case 1:
            return tr("Hits");
        default:
            return QVariant();
    }
}

QModelIndex FilterModel::indexOfFile(QString const &filename) const
{
    QMutexLocker locker(&d_resultsMutex);
    int index = -1;
    for (int i = 0, size = d_results.size(); i < size; ++i)
    {
        if (d_results.at(i).first == filename)
        {
            index = i;
            break;
        }
    }

    return createIndex(index, 0);
}

void FilterModel::fireDataChanged()
{
    // @TODO make this more robust so no assumption is required.

    int rows;
    {
      QMutexLocker locker(&d_resultsMutex);
      rows = d_results.size();
    }

    emit dataChanged(index(d_lastRow, 0), index(rows, 1));
    emit nEntriesFound(rows, d_hits);

    d_lastRow = rows - 1;
}

void FilterModel::lastDataChanged(int n, int totalEntries)
{
  Q_UNUSED(n);
  Q_UNUSED(totalEntries);

  fireDataChanged();

}

void FilterModel::lastDataChanged(int n, int totalEntries, bool cached)
{
  if (cached)
    return;

  lastDataChanged(n, totalEntries);

  d_timer->stop();
}

void FilterModel::runQuery(QString const &query)
{
    cancelQuery(); // just in case

    int size;
    {
      QMutexLocker locker(&d_resultsMutex);
      size = d_results.size();
      d_results.clear();
    }

    emit dataChanged(index(0, 0), index(size, 0));

    d_query = query;

    // Do nothing if this is a dummy filter model with a stupid null pointer
    if (!d_corpus)
        return;

    d_timer->setInterval(100);
    d_timer->setSingleShot(false);
    d_lastRow = 0;
    d_timer->start();

    if (!d_query.isEmpty())
        d_entriesFuture = QtConcurrent::run(this, &FilterModel::getEntriesWithQuery, d_query);
    else
        d_entriesFuture = QtConcurrent::run(this, &FilterModel::getEntries,
            d_corpus->begin(),
            d_corpus->end());
}

QString const &FilterModel::lastQuery() const
{
    return d_query;
}

void FilterModel::cancelQuery()
{
    d_cancelled = true;
    d_entryIterator.interrupt();
    d_entriesFuture.waitForFinished();
    d_timer->stop();
}

// run async, because query() starts searching immediately
void FilterModel::getEntriesWithQuery(QString const &query)
{
    if (d_entryCache->contains(query)) {
        {
          QMutexLocker locker(&d_resultsMutex);
          d_results = d_entryCache->object(query)->entries;
        }

        d_hits = d_entryCache->object(query)->hits;

        emit queryFinished(d_results.size(), d_results.size(), true);
        return;
    }

    try {
        FilterModel::getEntries(
            d_corpus->query(alpinocorpus::CorpusReader::XPATH, query.toUtf8().constData()),
            d_corpus->end());
    } catch (alpinocorpus::Error const &e) {
        qDebug() << "Alpino Error in FilterModel::getEntries: " << e.what();
        emit queryFailed(e.what());
    } catch (std::exception const &e) {
        qDebug() << "Error in FilterModel::getEntries: " << e.what();
        emit queryFailed(e.what());
    }
}

// run async
void FilterModel::getEntries(EntryIterator const &begin, EntryIterator const &end)
{
    try {
        emit queryStarted(0); // we don't know how many entries will be found

        d_cancelled = false;
        d_hits = 0;
        d_entryIterator = begin;

        for (EntryIterator itr(begin); !d_cancelled && itr != end; ++itr)
        {
            ++d_hits;

            QString entry(QString::fromUtf8((*itr).c_str()));

            // Lock the results list.
            QMutexLocker locker(&d_resultsMutex);

            /*
             * WARNING: This assumes all the hits per result only occur right after
             * each other, never shuffled. Otherwise we might want to change to QHash
             * or QMap for fast lookup.
             */
            int row = d_results.size() - 1;
            if (row >= 0 && d_results[row].first == entry)
                ++d_results[row].second;
            // Add found file to the list
            else
            {
                ++row;
                d_results.append(value_type(entry, 1));
            }
        }

        if (d_cancelled)
            emit queryStopped(d_results.size(), d_results.size());
        else
            emit queryFinished(d_results.size(), d_results.size(), false);
    }
    // When d_entryIterator.interrupt() is called by cancelQuery():
    catch (alpinocorpus::IterationInterrupted const &e) {
        emit queryStopped(d_results.size(), d_results.size());
    }
    // When something goes terribly terribly wrong, like entering a query
    // that doesn't yield nodes but strings.
    catch (alpinocorpus::Error const &e) {
        qDebug() << "Error in FilterModel::getEntries: " << e.what();
        emit queryFailed(e.what());
    }
}
<commit_msg>Don't interrupt on a copy of an iterator.<commit_after>#include <QCache>
#include <QDebug>
#include <QString>
#include <QStringList>
#include <QtConcurrentRun>

#include <algorithm>

#include <AlpinoCorpus/Error.hh>
#include "FilterModel.hh"

FilterModel::FilterModel(CorpusPtr corpus, QObject *parent)
:
    QAbstractTableModel(parent),
    d_corpus(corpus),
    d_hits(0),
    d_entryCache(new EntryCache(1000000)),
    d_timer(new QTimer)
{
    connect(d_timer.data(), SIGNAL(timeout()),
        SLOT(fireDataChanged()));
    connect(this, SIGNAL(queryStopped(int, int)),
        SLOT(lastDataChanged(int, int)));
    connect(this, SIGNAL(queryFinished(int, int, bool)),
        SLOT(lastDataChanged(int, int, bool)));
    connect(this, SIGNAL(queryFinished(int, int, bool)),
        SLOT(finalizeQuery(int, int, bool)));
}

FilterModel::~FilterModel()
{
    cancelQuery();
}

int FilterModel::columnCount(QModelIndex const &index) const
{
    return 2;
}

int FilterModel::rowCount(QModelIndex const &index) const
{
    QMutexLocker locker(&d_resultsMutex);
    return d_results.size();
}

QVariant FilterModel::data(QModelIndex const &index, int role) const
{
    QMutexLocker locker(&d_resultsMutex);

    if (!index.isValid()
        || index.row() >= d_results.size()
        || index.row() < 0
        || !(role == Qt::DisplayRole || role == Qt::UserRole))
        return QVariant();

    switch (index.column())
    {
        case 0:
            return d_results.at(index.row()).first;
        case 1:
            return d_results.at(index.row()).second;
        default:
            return QVariant();
    }
}

void FilterModel::finalizeQuery(int n, int totalEntries, bool cached)
{
    if (!cached) {
        // Cache the query
        d_entryCache->insert(d_query, new CacheItem(d_hits, d_results));
    }
}

QVariant FilterModel::headerData(int column, Qt::Orientation orientation, int role) const
{
    if (orientation != Qt::Horizontal
        || role != Qt::DisplayRole)
        return QVariant();

    switch (column)
    {
        case 0:
            return tr("File");
        case 1:
            return tr("Hits");
        default:
            return QVariant();
    }
}

QModelIndex FilterModel::indexOfFile(QString const &filename) const
{
    QMutexLocker locker(&d_resultsMutex);
    int index = -1;
    for (int i = 0, size = d_results.size(); i < size; ++i)
    {
        if (d_results.at(i).first == filename)
        {
            index = i;
            break;
        }
    }

    return createIndex(index, 0);
}

void FilterModel::fireDataChanged()
{
    // @TODO make this more robust so no assumption is required.

    int rows;
    {
      QMutexLocker locker(&d_resultsMutex);
      rows = d_results.size();
    }

    emit dataChanged(index(d_lastRow, 0), index(rows, 1));
    emit nEntriesFound(rows, d_hits);

    d_lastRow = rows - 1;
}

void FilterModel::lastDataChanged(int n, int totalEntries)
{
  Q_UNUSED(n);
  Q_UNUSED(totalEntries);

  fireDataChanged();

}

void FilterModel::lastDataChanged(int n, int totalEntries, bool cached)
{
  if (cached)
    return;

  lastDataChanged(n, totalEntries);

  d_timer->stop();
}

void FilterModel::runQuery(QString const &query)
{
    cancelQuery(); // just in case

    int size;
    {
      QMutexLocker locker(&d_resultsMutex);
      size = d_results.size();
      d_results.clear();
    }

    emit dataChanged(index(0, 0), index(size, 0));

    d_query = query;

    // Do nothing if this is a dummy filter model with a stupid null pointer
    if (!d_corpus)
        return;

    d_timer->setInterval(100);
    d_timer->setSingleShot(false);
    d_lastRow = 0;
    d_timer->start();

    if (!d_query.isEmpty())
        d_entriesFuture = QtConcurrent::run(this, &FilterModel::getEntriesWithQuery, d_query);
    else
        d_entriesFuture = QtConcurrent::run(this, &FilterModel::getEntries,
            d_corpus->begin(),
            d_corpus->end());
}

QString const &FilterModel::lastQuery() const
{
    return d_query;
}

void FilterModel::cancelQuery()
{
    d_cancelled = true;
    d_entryIterator.interrupt();
    d_entriesFuture.waitForFinished();
    d_timer->stop();
}

// run async, because query() starts searching immediately
void FilterModel::getEntriesWithQuery(QString const &query)
{
    if (d_entryCache->contains(query)) {
        {
          QMutexLocker locker(&d_resultsMutex);
          d_results = d_entryCache->object(query)->entries;
        }

        d_hits = d_entryCache->object(query)->hits;

        emit queryFinished(d_results.size(), d_results.size(), true);
        return;
    }

    try {
        FilterModel::getEntries(
            d_corpus->query(alpinocorpus::CorpusReader::XPATH, query.toUtf8().constData()),
            d_corpus->end());
    } catch (alpinocorpus::Error const &e) {
        qDebug() << "Alpino Error in FilterModel::getEntries: " << e.what();
        emit queryFailed(e.what());
    } catch (std::exception const &e) {
        qDebug() << "Error in FilterModel::getEntries: " << e.what();
        emit queryFailed(e.what());
    }
}

// run async
void FilterModel::getEntries(EntryIterator const &begin, EntryIterator const &end)
{
    try {
        emit queryStarted(0); // we don't know how many entries will be found

        d_cancelled = false;
        d_hits = 0;
        d_entryIterator = begin;

        for (d_entryIterator; !d_cancelled && d_entryIterator != end;
          ++d_entryIterator)
        {
            ++d_hits;

            QString entry(QString::fromUtf8((*d_entryIterator).c_str()));

            // Lock the results list.
            QMutexLocker locker(&d_resultsMutex);

            /*
             * WARNING: This assumes all the hits per result only occur right after
             * each other, never shuffled. Otherwise we might want to change to QHash
             * or QMap for fast lookup.
             */
            int row = d_results.size() - 1;
            if (row >= 0 && d_results[row].first == entry)
                ++d_results[row].second;
            // Add found file to the list
            else
            {
                ++row;
                d_results.append(value_type(entry, 1));
            }
        }

        if (d_cancelled)
            emit queryStopped(d_results.size(), d_results.size());
        else
            emit queryFinished(d_results.size(), d_results.size(), false);
    }
    // When d_entryIterator.interrupt() is called by cancelQuery():
    catch (alpinocorpus::IterationInterrupted const &e) {
        emit queryStopped(d_results.size(), d_results.size());
    }
    // When something goes terribly terribly wrong, like entering a query
    // that doesn't yield nodes but strings.
    catch (alpinocorpus::Error const &e) {
        qDebug() << "Error in FilterModel::getEntries: " << e.what();
        emit queryFailed(e.what());
    }
}
<|endoftext|>


<commit_before>#include "QCodeHighlighter.h"

#include "xo/system/assert.h"
#include "xo/filesystem/path.h"
#include "xo/numerical/math.h"
#include "xo/string/string_tools.h"
#include "xo/utility/hash.h"
#include "xo/container/flat_map.h"
#include <string>

QCodeHighlighter::QCodeHighlighter( QObject* parent, Language l ) : QSyntaxHighlighter( parent )
{
	setLanguage( l );
}

QCodeHighlighter::QCodeHighlighter( QTextDocument* parent, Language l ) : QSyntaxHighlighter( parent )
{
	setLanguage( l );
}

void QCodeHighlighter::highlightBlock( const QString &text )
{
	for ( auto& r : rules )
		applyRule( text, r );

	// apply multi-line comments
	if ( !commentStartRegex.pattern().isEmpty() )
	{
		int commentStart = 0, searchIndex = 0;
		bool isComment = previousBlockState() == 1;

		while ( searchIndex >= 0 )
		{
			if ( isComment )
			{
				auto matchEnd = match( commentEndRegex, text, searchIndex );
				if ( !matchEnd.hasMatch() )
				{
					// multiline comment goes beyond this line
					setFormat( commentStart, text.length() - commentStart, commentFormat );
					break;
				}
				else
				{
					// multiline comment ends here
					setFormat( commentStart, matchEnd.capturedEnd() - commentStart, commentFormat );
					searchIndex = matchEnd.capturedEnd();
					isComment = false;
				}
			}
			if ( !isComment )
			{
				auto matchStart = match( commentStartRegex, text, searchIndex );
				if ( matchStart.hasMatch() )
				{
					// multiline comment starts here
					commentStart = matchStart.capturedStart();
					searchIndex = matchStart.capturedEnd();
					isComment = true;
				}
				else break; // no more comments in this line
			}
		}
		setCurrentBlockState( isComment ? 1 : 0 );
	}
}

bool QCodeHighlighter::isBetweenQuotes( const QString & text, int index )
{
	int quotes_before = 0;
	for ( int i = 0; i < index; ++i )
		quotes_before += int( text[ i ] == '\"' );
	return xo::is_odd( quotes_before );
}

QRegularExpressionMatch QCodeHighlighter::match( const QRegularExpression & regex, const QString & text, int index )
{
	auto m = regex.match( text, index );
	while ( m.hasMatch() && isBetweenQuotes( text, m.capturedStart() ) )
		m = regex.match( text, m.capturedEnd() );
	return m;
}

void QCodeHighlighter::applyRule( const QString& text, const HighlightRule& r )
{
	for ( auto m = match( r.regExp, text, 0 ); m.hasMatch(); m = match( r.regExp, text, m.capturedEnd() ) )
		setFormat( m.capturedStart(), m.capturedLength(), r.format );
}

void QCodeHighlighter::setRegexes()
{
	rules.clear();
	commentStartRegex.setPattern( "" );
	commentEndRegex.setPattern( "" );

	switch ( language )
	{
	case Language::xml:
		rules.emplace_back( "<[\\s]*[/]?[\\s]*([^\\n]\\w*)(?=[\\s/>])", elementFormat );
		rules.emplace_back( "\\w+(?=\\=)", attributeFormat );
		rules.emplace_back( "\"[^\\n\"]+\"(?=[\\s/>])", valueFormat );
		rules.emplace_back( "/.^/", specialFormat );
		rules.emplace_back( "(<\\?|/>|>|<|</|\\?>", operatorFormat );
		rules.emplace_back( "\\b([-+]?[\\.\\d]+)", numberFormat );
		commentStartRegex.setPattern( "<!--" );
		commentEndRegex.setPattern( "-->" );
		break;

	case Language::zml:
		rules.emplace_back( "\\w+\\s*\\=?\\s*[\\{\\[]", elementFormat );
		rules.emplace_back( "\\w+\\s*(\\=)", attributeFormat ); // key = value
		rules.emplace_back( "\\w+(:\\s+)", attributeFormat ); // key: value
		rules.emplace_back( "\"[^\\n\"]*\"", valueFormat );
		rules.emplace_back( "<<\\s.*\\s>>", specialFormat );
		rules.emplace_back( "([\\{\\}\\[\\]\\=]|:\\s)", operatorFormat );
		rules.emplace_back( "\\b([-+]?[\\.\\d]+)", numberFormat );
		rules.emplace_back( "\\@\\w+", macroFormat );
		rules.emplace_back( "\\$\\w+", macroFormat );
		rules.emplace_back( "#[^\\n]*", commentFormat ); // #
		commentStartRegex.setPattern( "#{3,}" );
		commentEndRegex.setPattern( "#{3,}" );
		break;

	case Language::lua:
		rules.emplace_back( "\\b(and|break|do|else|elseif|end|false|for|function|goto|if|in|local|nil|not|or|repeat|return|then|true|until|while)\\b", elementFormat );
		rules.emplace_back( "\"[^\\n\"]*\"", valueFormat );
		rules.emplace_back( "\\b([-+]?[\\.\\d]+)", numberFormat );
		rules.emplace_back( "[\\+\\-\\*\\/\\%\\\\#\\&\\~\\|\\<\\>\\(\\)\\{\\}\\[\\]\\=\\;\\:\\,\\.]", operatorFormat );
		rules.emplace_back( "--[^\\n]*", commentFormat );
		commentStartRegex.setPattern( "--\\[\\[" );
		commentEndRegex.setPattern( "\\]\\]" );
	default:
		break;
	}
}

void QCodeHighlighter::setFormats()
{
	operatorFormat.setForeground( Qt::darkGray );
	elementFormat.setForeground( Qt::darkBlue );
	elementFormat.setFontWeight( QFont::Bold );
	attributeFormat.setForeground( Qt::darkBlue );
	//attributeFormat.setFontItalic( true );
	//attributeFormat.setFontWeight( QFont::Bold );
	valueFormat.setForeground( Qt::darkRed );
	commentFormat.setForeground( Qt::gray );
	commentFormat.setFontItalic( true );
	numberFormat.setForeground( Qt::darkCyan );
	macroFormat.setForeground( Qt::darkMagenta );
	//macroFormat.setFontItalic( true );
	specialFormat.setForeground( Qt::darkMagenta );
	specialFormat.setFontItalic( true );
	//specialFormat.setFontWeight( QFont::Bold );
}

void QCodeHighlighter::setLanguage( Language l )
{
	language = l;
	setFormats();
	setRegexes();
}

xo::flat_map< std::string, QCodeHighlighter::Language > g_languages{
	{ "xml", QCodeHighlighter::Language::xml },
	{ "zml", QCodeHighlighter::Language::zml },
	{ "lua", QCodeHighlighter::Language::lua },
	{ "scone", QCodeHighlighter::Language::zml }
};

QCodeHighlighter::Language QCodeHighlighter::detectLanguage( const QString& filename )
{
	auto ext = xo::to_lower( xo::path( filename.toStdString() ).extension_no_dot().str() );
	if ( auto l = g_languages.find( ext ); l != g_languages.end() )
		return l->second;
	else return Language::unknown;
}

void QCodeHighlighter::registerLanguage( const QString& ext, Language lang )
{
	g_languages[ xo::to_lower( ext.toStdString() ) ] = lang;
}
<commit_msg>U: QCodeHighlighter supports .osim and .hfd<commit_after>#include "QCodeHighlighter.h"

#include "xo/system/assert.h"
#include "xo/filesystem/path.h"
#include "xo/numerical/math.h"
#include "xo/string/string_tools.h"
#include "xo/utility/hash.h"
#include "xo/container/flat_map.h"
#include <string>

QCodeHighlighter::QCodeHighlighter( QObject* parent, Language l ) : QSyntaxHighlighter( parent )
{
	setLanguage( l );
}

QCodeHighlighter::QCodeHighlighter( QTextDocument* parent, Language l ) : QSyntaxHighlighter( parent )
{
	setLanguage( l );
}

void QCodeHighlighter::highlightBlock( const QString &text )
{
	for ( auto& r : rules )
		applyRule( text, r );

	// apply multi-line comments
	if ( !commentStartRegex.pattern().isEmpty() )
	{
		int commentStart = 0, searchIndex = 0;
		bool isComment = previousBlockState() == 1;

		while ( searchIndex >= 0 )
		{
			if ( isComment )
			{
				auto matchEnd = match( commentEndRegex, text, searchIndex );
				if ( !matchEnd.hasMatch() )
				{
					// multiline comment goes beyond this line
					setFormat( commentStart, text.length() - commentStart, commentFormat );
					break;
				}
				else
				{
					// multiline comment ends here
					setFormat( commentStart, matchEnd.capturedEnd() - commentStart, commentFormat );
					searchIndex = matchEnd.capturedEnd();
					isComment = false;
				}
			}
			if ( !isComment )
			{
				auto matchStart = match( commentStartRegex, text, searchIndex );
				if ( matchStart.hasMatch() )
				{
					// multiline comment starts here
					commentStart = matchStart.capturedStart();
					searchIndex = matchStart.capturedEnd();
					isComment = true;
				}
				else break; // no more comments in this line
			}
		}
		setCurrentBlockState( isComment ? 1 : 0 );
	}
}

bool QCodeHighlighter::isBetweenQuotes( const QString & text, int index )
{
	int quotes_before = 0;
	for ( int i = 0; i < index; ++i )
		quotes_before += int( text[ i ] == '\"' );
	return xo::is_odd( quotes_before );
}

QRegularExpressionMatch QCodeHighlighter::match( const QRegularExpression & regex, const QString & text, int index )
{
	auto m = regex.match( text, index );
	while ( m.hasMatch() && isBetweenQuotes( text, m.capturedStart() ) )
		m = regex.match( text, m.capturedEnd() );
	return m;
}

void QCodeHighlighter::applyRule( const QString& text, const HighlightRule& r )
{
	for ( auto m = match( r.regExp, text, 0 ); m.hasMatch(); m = match( r.regExp, text, m.capturedEnd() ) )
		setFormat( m.capturedStart(), m.capturedLength(), r.format );
}

void QCodeHighlighter::setRegexes()
{
	rules.clear();
	commentStartRegex.setPattern( "" );
	commentEndRegex.setPattern( "" );

	switch ( language )
	{
	case Language::xml:
		rules.emplace_back( "<[\\s]*[/]?[\\s]*([^\\n]\\w*)(?=[\\s/>])", elementFormat );
		rules.emplace_back( "\\w+(?=\\=)", attributeFormat );
		rules.emplace_back( "\"[^\\n\"]+\"(?=[\\s/>])", valueFormat );
		rules.emplace_back( "/.^/", specialFormat );
		rules.emplace_back( "(<\\?|/>|>|<|</|\\?>", operatorFormat );
		rules.emplace_back( "\\b([-+]?[\\.\\d]+)", numberFormat );
		commentStartRegex.setPattern( "<!--" );
		commentEndRegex.setPattern( "-->" );
		break;

	case Language::zml:
		rules.emplace_back( "\\w+\\s*\\=?\\s*[\\{\\[]", elementFormat );
		rules.emplace_back( "\\w+\\s*(\\=)", attributeFormat ); // key = value
		rules.emplace_back( "\\w+(:\\s+)", attributeFormat ); // key: value
		rules.emplace_back( "\"[^\\n\"]*\"", valueFormat );
		rules.emplace_back( "<<\\s.*\\s>>", specialFormat );
		rules.emplace_back( "([\\{\\}\\[\\]\\=]|:\\s)", operatorFormat );
		rules.emplace_back( "\\b([-+]?[\\.\\d]+)", numberFormat );
		rules.emplace_back( "\\@\\w+", macroFormat );
		rules.emplace_back( "\\$\\w+", macroFormat );
		rules.emplace_back( "#[^\\n]*", commentFormat ); // #
		commentStartRegex.setPattern( "#{3,}" );
		commentEndRegex.setPattern( "#{3,}" );
		break;

	case Language::lua:
		rules.emplace_back( "\\b(and|break|do|else|elseif|end|false|for|function|goto|if|in|local|nil|not|or|repeat|return|then|true|until|while)\\b", elementFormat );
		rules.emplace_back( "\"[^\\n\"]*\"", valueFormat );
		rules.emplace_back( "\\b([-+]?[\\.\\d]+)", numberFormat );
		rules.emplace_back( "[\\+\\-\\*\\/\\%\\\\#\\&\\~\\|\\<\\>\\(\\)\\{\\}\\[\\]\\=\\;\\:\\,\\.]", operatorFormat );
		rules.emplace_back( "--[^\\n]*", commentFormat );
		commentStartRegex.setPattern( "--\\[\\[" );
		commentEndRegex.setPattern( "\\]\\]" );
	default:
		break;
	}
}

void QCodeHighlighter::setFormats()
{
	operatorFormat.setForeground( Qt::darkGray );
	elementFormat.setForeground( Qt::darkBlue );
	elementFormat.setFontWeight( QFont::Bold );
	attributeFormat.setForeground( Qt::darkBlue );
	//attributeFormat.setFontItalic( true );
	//attributeFormat.setFontWeight( QFont::Bold );
	valueFormat.setForeground( Qt::darkRed );
	commentFormat.setForeground( Qt::gray );
	commentFormat.setFontItalic( true );
	numberFormat.setForeground( Qt::darkCyan );
	macroFormat.setForeground( Qt::darkMagenta );
	//macroFormat.setFontItalic( true );
	specialFormat.setForeground( Qt::darkMagenta );
	specialFormat.setFontItalic( true );
	//specialFormat.setFontWeight( QFont::Bold );
}

void QCodeHighlighter::setLanguage( Language l )
{
	language = l;
	setFormats();
	setRegexes();
}

xo::flat_map< std::string, QCodeHighlighter::Language > g_languages{
	{ "scone", QCodeHighlighter::Language::zml },
	{ "xml", QCodeHighlighter::Language::xml },
	{ "osim", QCodeHighlighter::Language::xml },
	{ "lua", QCodeHighlighter::Language::lua },
	{ "zml", QCodeHighlighter::Language::zml },
	{ "hfd", QCodeHighlighter::Language::zml }
};

QCodeHighlighter::Language QCodeHighlighter::detectLanguage( const QString& filename )
{
	auto ext = xo::to_lower( xo::path( filename.toStdString() ).extension_no_dot().str() );
	if ( auto l = g_languages.find( ext ); l != g_languages.end() )
		return l->second;
	else return Language::unknown;
}

void QCodeHighlighter::registerLanguage( const QString& ext, Language lang )
{
	g_languages[ xo::to_lower( ext.toStdString() ) ] = lang;
}
<|endoftext|>


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

QGroundControl Open Source Ground Control Station

(c) 2009, 2010 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>

This file is part of the QGROUNDCONTROL project

    QGROUNDCONTROL is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    QGROUNDCONTROL is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.

======================================================================*/

/**
 * @file
 *   @brief Implementation of audio output
 *
 *   @author Lorenz Meier <mavteam@student.ethz.ch>
 *   @author Thomas Gubler <thomasgubler@gmail.com>
 *
 */

#include <QApplication>
#include <QSettings>
#include <QTemporaryFile>
#include "GAudioOutput.h"
#include "MG.h"

#include <QDebug>

#if defined Q_OS_MAC && defined QGC_SPEECH_ENABLED
#include <ApplicationServices/ApplicationServices.h>
#endif

// Speech synthesis is only supported with MSVC compiler
#if defined _MSC_VER && defined QGC_SPEECH_ENABLED
// Documentation: http://msdn.microsoft.com/en-us/library/ee125082%28v=VS.85%29.aspx
#include <sapi.h>
#endif

#if defined Q_OS_LINUX && defined QGC_SPEECH_ENABLED
// Using eSpeak for speech synthesis: following https://github.com/mondhs/espeak-sample/blob/master/sampleSpeak.cpp
#include <espeak/speak_lib.h>
#endif

#if defined _MSC_VER && defined QGC_SPEECH_ENABLED
ISpVoice *GAudioOutput::pVoice = NULL;
#endif

/**
 * This class follows the singleton design pattern
 * @see http://en.wikipedia.org/wiki/Singleton_pattern
 * A call to this function thus returns the only instance of this object
 * the call can occur at any place in the code, no reference to the
 * GAudioOutput object has to be passed.
 */
GAudioOutput *GAudioOutput::instance()
{
    static GAudioOutput *_instance = 0;

    if (_instance == 0)
    {
        _instance = new GAudioOutput();
        // Set the application as parent to ensure that this object
        // will be destroyed when the main application exits
        _instance->setParent(qApp);
    }

    return _instance;
}

#define QGC_GAUDIOOUTPUT_KEY QString("QGC_AUDIOOUTPUT_")

GAudioOutput::GAudioOutput(QObject *parent) : QObject(parent),
    voiceIndex(0),
    emergency(false),
    muted(false)
{
    // Load settings
    QSettings settings;
    settings.sync();
    muted = settings.value(QGC_GAUDIOOUTPUT_KEY + "muted", muted).toBool();

#if defined Q_OS_LINUX && defined QGC_SPEECH_ENABLED
    espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 500, NULL, 0); // initialize for playback with 500ms buffer and no options (see speak_lib.h)
    espeak_VOICE espeak_voice = {};
    espeak_voice.languages = "en-uk"; // Default to British English
    espeak_voice.identifier = NULL; // no specific voice file specified
    espeak_voice.name = "klatt"; // espeak voice name
    espeak_voice.gender = 2; // Female
    espeak_voice.age = 0; // age not specified
    espeak_SetVoiceByProperties(&espeak_voice);
#endif

#if defined _MSC_VER && defined QGC_SPEECH_ENABLED
    pVoice = NULL;

    if (FAILED(::CoInitialize(NULL)))
    {
        qDebug() << "ERROR: Creating COM object for audio output failed!";
    }

    else
    {

        HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice);

        if (FAILED(hr))
        {
            qDebug() << "ERROR: Initializing voice for audio output failed!";
        }
    }

#endif

    // Prepare regular emergency signal, will be fired off on calling startEmergency()
    emergencyTimer = new QTimer();
    connect(emergencyTimer, SIGNAL(timeout()), this, SLOT(beep()));

    switch (voiceIndex)
    {
    case 0:
        selectFemaleVoice();
        break;

    default:
        selectMaleVoice();
        break;
    }
}

GAudioOutput::~GAudioOutput()
{
#if defined _MSC_VER && defined QGC_SPEECH_ENABLED
    pVoice->Release();
    pVoice = NULL;
    ::CoUninitialize();
#endif
}

void GAudioOutput::mute(bool mute)
{
    if (mute != muted)
    {
        this->muted = mute;
        QSettings settings;
        settings.setValue(QGC_GAUDIOOUTPUT_KEY + "muted", this->muted);
        settings.sync();
        emit mutedChanged(muted);
    }
}

bool GAudioOutput::isMuted()
{
    return this->muted;
}

bool GAudioOutput::say(QString text, int severity)
{
    if (!muted)
    {
        // TODO Add severity filter
        Q_UNUSED(severity);
        bool res = false;

        if (!emergency)
        {

#if defined _MSC_VER && defined QGC_SPEECH_ENABLED
            pVoice->Speak(text.toStdWString().c_str(), SPF_ASYNC, NULL);

#elif defined Q_OS_LINUX && defined QGC_SPEECH_ENABLED
            // Set size of string for espeak: +1 for the null-character
            unsigned int espeak_size = strlen(text.toStdString().c_str()) + 1;
            espeak_Synth(text.toStdString().c_str(), espeak_size, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL);

#elif defined Q_OS_MAC && defined QGC_SPEECH_ENABLED
            // Slashes necessary to have the right start to the sentence
            // copying data prevents SpeakString from reading additional chars
            text = "\\" + text;
            std::wstring str = text.toStdWString();
            unsigned char str2[1024] = {};
            memcpy(str2, text.toLatin1().data(), str.length());
            SpeakString(str2);
            res = true;

#else
            // Make sure there isn't an unused variable warning when speech output is disabled
            Q_UNUSED(text);
#endif
        }

        return res;
    }

    else
    {
        return false;
    }
}

/**
 * @param text This message will be played after the alert beep
 */
bool GAudioOutput::alert(QString text)
{
    if (!emergency || !muted)
    {
        // Play alert sound
        beep();
        // Say alert message
        say(text, 2);
        return true;
    }

    else
    {
        return false;
    }
}

void GAudioOutput::notifyPositive()
{
    if (!muted)
    {
        // Use QFile to transform path for all OS
        // FIXME: Get working with Qt5's QtMultimedia module
        //QFile f(QCoreApplication::applicationDirPath() + QString("/files/audio/double_notify.wav"));
        //m_media->setCurrentSource(Phonon::MediaSource(f.fileName().toStdString().c_str()));
        //m_media->play();
    }
}

void GAudioOutput::notifyNegative()
{
    if (!muted)
    {
        // Use QFile to transform path for all OS
        // FIXME: Get working with Qt5's QtMultimedia module
        //QFile f(QCoreApplication::applicationDirPath() + QString("/files/audio/flat_notify.wav"));
        //m_media->setCurrentSource(Phonon::MediaSource(f.fileName().toStdString().c_str()));
        //m_media->play();
    }
}

/**
 * The emergency sound will be played continously during the emergency.
 * call stopEmergency() to disable it again. No speech synthesis or other
 * audio output is available during the emergency.
 *
 * @return true if the emergency could be started, false else
 */
bool GAudioOutput::startEmergency()
{
    if (!emergency)
    {
        emergency = true;

        // Beep immediately and then start timer
        if (!muted) beep();

        emergencyTimer->start(1500);
        QTimer::singleShot(5000, this, SLOT(stopEmergency()));
    }

    return true;
}

/**
 * Stops the continous emergency sound. Use startEmergency() to start
 * the emergency sound.
 *
 * @return true if the emergency could be stopped, false else
 */
bool GAudioOutput::stopEmergency()
{
    if (emergency)
    {
        emergency = false;
        emergencyTimer->stop();
    }

    return true;
}

void GAudioOutput::beep()
{
    if (!muted)
    {
        // FIXME: Re-enable audio beeps
        // Use QFile to transform path for all OS
        //QFile f(QCoreApplication::applicationDirPath() + QString("/files/audio/alert.wav"));
        //qDebug() << "FILE:" << f.fileName();
        //m_media->setCurrentSource(Phonon::MediaSource(f.fileName().toStdString().c_str()));
        //m_media->play();
    }
}

void GAudioOutput::selectFemaleVoice()
{
#if defined Q_OS_LINUX && defined QGC_SPEECH_ENABLED
    // FIXME: Enable selecting a female voice on all platforms
    //this->voice = register_cmu_us_slt(NULL);
#endif
}

void GAudioOutput::selectMaleVoice()
{
#if defined Q_OS_LINUX && defined QGC_SPEECH_ENABLED
    // FIXME: Enable selecting a male voice on all platforms
    //this->voice = register_cmu_us_rms(NULL);
#endif
}

QStringList GAudioOutput::listVoices(void)
{
    // No voice selection is currently supported, so just return an empty list
    QStringList l;
    return l;
}
<commit_msg>Fixed issue with incomplete initialization of struct. Changed to get the current voice properties, then modify then and set new ones.<commit_after>/*=====================================================================

QGroundControl Open Source Ground Control Station

(c) 2009, 2010 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>

This file is part of the QGROUNDCONTROL project

    QGROUNDCONTROL is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    QGROUNDCONTROL is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.

======================================================================*/

/**
 * @file
 *   @brief Implementation of audio output
 *
 *   @author Lorenz Meier <mavteam@student.ethz.ch>
 *   @author Thomas Gubler <thomasgubler@gmail.com>
 *
 */

#include <QApplication>
#include <QSettings>
#include <QTemporaryFile>
#include "GAudioOutput.h"
#include "MG.h"

#include <QDebug>

#if defined Q_OS_MAC && defined QGC_SPEECH_ENABLED
#include <ApplicationServices/ApplicationServices.h>
#endif

// Speech synthesis is only supported with MSVC compiler
#if defined _MSC_VER && defined QGC_SPEECH_ENABLED
// Documentation: http://msdn.microsoft.com/en-us/library/ee125082%28v=VS.85%29.aspx
#include <sapi.h>
#endif

#if defined Q_OS_LINUX && defined QGC_SPEECH_ENABLED
// Using eSpeak for speech synthesis: following https://github.com/mondhs/espeak-sample/blob/master/sampleSpeak.cpp
#include <espeak/speak_lib.h>
#endif

#if defined _MSC_VER && defined QGC_SPEECH_ENABLED
ISpVoice *GAudioOutput::pVoice = NULL;
#endif

/**
 * This class follows the singleton design pattern
 * @see http://en.wikipedia.org/wiki/Singleton_pattern
 * A call to this function thus returns the only instance of this object
 * the call can occur at any place in the code, no reference to the
 * GAudioOutput object has to be passed.
 */
GAudioOutput *GAudioOutput::instance()
{
    static GAudioOutput *_instance = 0;

    if (_instance == 0)
    {
        _instance = new GAudioOutput();
        // Set the application as parent to ensure that this object
        // will be destroyed when the main application exits
        _instance->setParent(qApp);
    }

    return _instance;
}

#define QGC_GAUDIOOUTPUT_KEY QString("QGC_AUDIOOUTPUT_")

GAudioOutput::GAudioOutput(QObject *parent) : QObject(parent),
    voiceIndex(0),
    emergency(false),
    muted(false)
{
    // Load settings
    QSettings settings;
    settings.sync();
    muted = settings.value(QGC_GAUDIOOUTPUT_KEY + "muted", muted).toBool();

#if defined Q_OS_LINUX && defined QGC_SPEECH_ENABLED
    espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 500, NULL, 0); // initialize for playback with 500ms buffer and no options (see speak_lib.h)
    espeak_VOICE *espeak_voice = espeak_GetCurrentVoice();
    espeak_voice->languages = "en-uk"; // Default to British English
    espeak_voice->identifier = NULL; // no specific voice file specified
    espeak_voice->name = "klatt"; // espeak voice name
    espeak_voice->gender = 2; // Female
    espeak_voice->age = 0; // age not specified
    espeak_SetVoiceByProperties(espeak_voice);
#endif

#if defined _MSC_VER && defined QGC_SPEECH_ENABLED
    pVoice = NULL;

    if (FAILED(::CoInitialize(NULL)))
    {
        qDebug() << "ERROR: Creating COM object for audio output failed!";
    }

    else
    {

        HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice);

        if (FAILED(hr))
        {
            qDebug() << "ERROR: Initializing voice for audio output failed!";
        }
    }

#endif

    // Prepare regular emergency signal, will be fired off on calling startEmergency()
    emergencyTimer = new QTimer();
    connect(emergencyTimer, SIGNAL(timeout()), this, SLOT(beep()));

    switch (voiceIndex)
    {
    case 0:
        selectFemaleVoice();
        break;

    default:
        selectMaleVoice();
        break;
    }
}

GAudioOutput::~GAudioOutput()
{
#if defined _MSC_VER && defined QGC_SPEECH_ENABLED
    pVoice->Release();
    pVoice = NULL;
    ::CoUninitialize();
#endif
}

void GAudioOutput::mute(bool mute)
{
    if (mute != muted)
    {
        this->muted = mute;
        QSettings settings;
        settings.setValue(QGC_GAUDIOOUTPUT_KEY + "muted", this->muted);
        settings.sync();
        emit mutedChanged(muted);
    }
}

bool GAudioOutput::isMuted()
{
    return this->muted;
}

bool GAudioOutput::say(QString text, int severity)
{
    if (!muted)
    {
        // TODO Add severity filter
        Q_UNUSED(severity);
        bool res = false;

        if (!emergency)
        {

#if defined _MSC_VER && defined QGC_SPEECH_ENABLED
            pVoice->Speak(text.toStdWString().c_str(), SPF_ASYNC, NULL);

#elif defined Q_OS_LINUX && defined QGC_SPEECH_ENABLED
            // Set size of string for espeak: +1 for the null-character
            unsigned int espeak_size = strlen(text.toStdString().c_str()) + 1;
            espeak_Synth(text.toStdString().c_str(), espeak_size, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL);

#elif defined Q_OS_MAC && defined QGC_SPEECH_ENABLED
            // Slashes necessary to have the right start to the sentence
            // copying data prevents SpeakString from reading additional chars
            text = "\\" + text;
            std::wstring str = text.toStdWString();
            unsigned char str2[1024] = {};
            memcpy(str2, text.toLatin1().data(), str.length());
            SpeakString(str2);
            res = true;

#else
            // Make sure there isn't an unused variable warning when speech output is disabled
            Q_UNUSED(text);
#endif
        }

        return res;
    }

    else
    {
        return false;
    }
}

/**
 * @param text This message will be played after the alert beep
 */
bool GAudioOutput::alert(QString text)
{
    if (!emergency || !muted)
    {
        // Play alert sound
        beep();
        // Say alert message
        say(text, 2);
        return true;
    }

    else
    {
        return false;
    }
}

void GAudioOutput::notifyPositive()
{
    if (!muted)
    {
        // Use QFile to transform path for all OS
        // FIXME: Get working with Qt5's QtMultimedia module
        //QFile f(QCoreApplication::applicationDirPath() + QString("/files/audio/double_notify.wav"));
        //m_media->setCurrentSource(Phonon::MediaSource(f.fileName().toStdString().c_str()));
        //m_media->play();
    }
}

void GAudioOutput::notifyNegative()
{
    if (!muted)
    {
        // Use QFile to transform path for all OS
        // FIXME: Get working with Qt5's QtMultimedia module
        //QFile f(QCoreApplication::applicationDirPath() + QString("/files/audio/flat_notify.wav"));
        //m_media->setCurrentSource(Phonon::MediaSource(f.fileName().toStdString().c_str()));
        //m_media->play();
    }
}

/**
 * The emergency sound will be played continously during the emergency.
 * call stopEmergency() to disable it again. No speech synthesis or other
 * audio output is available during the emergency.
 *
 * @return true if the emergency could be started, false else
 */
bool GAudioOutput::startEmergency()
{
    if (!emergency)
    {
        emergency = true;

        // Beep immediately and then start timer
        if (!muted) beep();

        emergencyTimer->start(1500);
        QTimer::singleShot(5000, this, SLOT(stopEmergency()));
    }

    return true;
}

/**
 * Stops the continous emergency sound. Use startEmergency() to start
 * the emergency sound.
 *
 * @return true if the emergency could be stopped, false else
 */
bool GAudioOutput::stopEmergency()
{
    if (emergency)
    {
        emergency = false;
        emergencyTimer->stop();
    }

    return true;
}

void GAudioOutput::beep()
{
    if (!muted)
    {
        // FIXME: Re-enable audio beeps
        // Use QFile to transform path for all OS
        //QFile f(QCoreApplication::applicationDirPath() + QString("/files/audio/alert.wav"));
        //qDebug() << "FILE:" << f.fileName();
        //m_media->setCurrentSource(Phonon::MediaSource(f.fileName().toStdString().c_str()));
        //m_media->play();
    }
}

void GAudioOutput::selectFemaleVoice()
{
#if defined Q_OS_LINUX && defined QGC_SPEECH_ENABLED
    // FIXME: Enable selecting a female voice on all platforms
    //this->voice = register_cmu_us_slt(NULL);
#endif
}

void GAudioOutput::selectMaleVoice()
{
#if defined Q_OS_LINUX && defined QGC_SPEECH_ENABLED
    // FIXME: Enable selecting a male voice on all platforms
    //this->voice = register_cmu_us_rms(NULL);
#endif
}

QStringList GAudioOutput::listVoices(void)
{
    // No voice selection is currently supported, so just return an empty list
    QStringList l;
    return l;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <time.h>
#include <array>
#include "GameManager.h"
#include "Log.h"
#include "Menu.h"
#include "Timer.h"

GameManager::GameManager(Window* window):
    window(window)
{
    currentState = STATE_MENU;
    _quit = false;
}

void GameManager::runGame()
{
    Entity* paddle = new Entity(window, "paddle.bmp", 305, 490);
    paddle->setMoveRate(5);
    entities.push_back(paddle);

    ball = new Ball(window, "ball.bmp", window->getWidth() / 2, window->getHeight() / 2, paddle);
    ball->setOnPaddle(true);

    ball2 = new Ball(window, "ball2.bmp", window->getWidth() / 2, window->getHeight() / 2, paddle);
    setOnPaddle(true);

    //used for random powerup spwaning
    srand(time(NULL));
    randNum = rand() % 2;
    mod = new Mods(window, "PowerUP.bmp", 305, 0 );//makes a new power down object

    upNum = rand() % 2;
	downNum = rand() % 2;

    Timer fpsTimer;
    Timer capTimer;

    uint32_t frameCount = 0;
    fpsTimer.start();

    Menu mainMenu(this);
    mainMenu.addEntry("Play");
    mainMenu.addEntry("Settings");
    mainMenu.addEntry("Exit");

    Menu settingsMenu(this);
    settingsMenu.addEntry("Back");

    while (!_quit)
    {
        window->clear();

        capTimer.start();

        switch (currentState)
        {
        case STATE_MENU:
            mainMenu.tick();
            break;
        case STATE_SETTINGS:
            break;
        case STATE_PLAYING:
            gameTick();
            break;
        default:
            Log::warn("Recieved unhandled gamestate: " + std::to_string(currentState));
            break;
        }

        // divide the amount of frames displayed by the runtime in seconds to get the average fps
        float avgFps = frameCount / (fpsTimer.getTicks() / 1000.f);
        if (avgFps > 2000000)
            avgFps = 0;

        window->renderText(std::to_string((int)avgFps), window->getWidth()-30, 0, { 0, 0, 0 }, 25, FONT_RENDER_BLENDED, { 0, 0, 0 });

        window->render();

        frameCount++;

        // if our fps it too high, wait here until we're back to ~60fps
        if (capTimer.getTicks() < (1000 / window->getMaxFps()))
        {
            int waitTime = (1000 / window->getMaxFps()) - capTimer.getTicks();
            //Log::info("Waiting " + std::to_string(waitTime) + " MS");
            SDL_Delay(waitTime);
        }
    }
}

void GameManager::gameTick()
{
    SDL_PollEvent(&event);

    // paddle is always added to the entities vector first, so this is fine
    Entity* paddle = entities[0];

    switch (event.type)
    {
    // if user clicks the red X
    case SDL_QUIT:
        _quit = true;
        break;

    case SDL_KEYDOWN:
        switch (event.key.keysym.sym)
        {
        case SDLK_LEFT:
            paddle->startMoving(MOVE_LEFT);
            break;
        case SDLK_RIGHT:
            paddle->startMoving(MOVE_RIGHT);
            break;
        case SDLK_SPACE:
            if (ball->isOnPaddle())
                ball->detach();
            break;
        }
        break;

    case SDL_KEYUP:
        switch (event.key.keysym.sym)
        {
        case SDLK_LEFT:
            paddle->stopMoving(MOVE_LEFT);
            break;
        case SDLK_RIGHT:
            paddle->stopMoving(MOVE_RIGHT);
            break;
        }
        break;
    }

    for (Entity* e : entities)
    {
        // don't think this is that cpu intensive but I guess it could be
        if (ball->collidedWith(e))
        {
            ball->handleCollision(e);

        }

        if(ball2->collidedWith(e))
            ball2->handleCollision(e);

        e->update();
    }

/************** Code segment used for powerup implementation ***************/
if(randNum == 0)    //anthony is gay
{
    mod->update();
        if(mod->collidedWith(paddle))
        {
          mod->doubleBalls();
          ball2->detach();
          mod->remove();
        }
        ball2->update();
        ball2->outOfBounds();
}

if(randNum == 1)
{
  mod->update();
  if(mod->collidedWith(paddle))
  {
    mod->largePaddle();
    mod->remove();
  }
}

if(randNum == 2)
{
    mod->update();
        if(mod->collidedWith(paddle))
        {
            mod->slowerPaddle();
            paddle->setMoveRate(3);
            mod->remove();
        }
    }
  if(randNum == 3)
  {
      mod->update();
        if(mod->collidedWith(paddle))
        {
            mod->smallPaddle();
            mod->remove();
        }
    }
/***************************************************************************/

    ball->update();
}
<commit_msg>Edited some modifier stuff.<commit_after>#include <iostream>
#include <time.h>
#include <array>
#include "GameManager.h"
#include "Log.h"
#include "Menu.h"
#include "Timer.h"

GameManager::GameManager(Window* window):
    window(window)
{
    currentState = STATE_MENU;
    _quit = false;
}

void GameManager::runGame()
{
    Entity* paddle = new Entity(window, "paddle.bmp", 305, 490);
    paddle->setMoveRate(5);
    entities.push_back(paddle);

    ball = new Ball(window, "ball.bmp", window->getWidth() / 2, window->getHeight() / 2, paddle);
    ball->setOnPaddle(true);

    ball2 = new Ball(window, "ball2.bmp", window->getWidth() / 2, window->getHeight() / 2, paddle);
    ball2->setOnPaddle(true);

    //used for random powerup spwaning
    srand(time(NULL));
    randNum = rand() % 2;
    mod = new Mods(window, "PowerUP.bmp", 305, 0 );//makes a new power down object

    upNum = rand() % 2;
	downNum = rand() % 2;

    Timer fpsTimer;
    Timer capTimer;

    uint32_t frameCount = 0;
    fpsTimer.start();

    Menu mainMenu(this);
    mainMenu.addEntry("Play");
    mainMenu.addEntry("Settings");
    mainMenu.addEntry("Exit");

    Menu settingsMenu(this);
    settingsMenu.addEntry("Back");

    while (!_quit)
    {
        window->clear();

        capTimer.start();

        switch (currentState)
        {
        case STATE_MENU:
            mainMenu.tick();
            break;
        case STATE_SETTINGS:
            break;
        case STATE_PLAYING:
            gameTick();
            break;
        default:
            Log::warn("Recieved unhandled gamestate: " + std::to_string(currentState));
            break;
        }

        // divide the amount of frames displayed by the runtime in seconds to get the average fps
        float avgFps = frameCount / (fpsTimer.getTicks() / 1000.f);
        if (avgFps > 2000000)
            avgFps = 0;

        window->renderText(std::to_string((int)avgFps), window->getWidth()-30, 0, { 0, 0, 0 }, 25, FONT_RENDER_BLENDED, { 0, 0, 0 });

        window->render();

        frameCount++;

        // if our fps it too high, wait here until we're back to ~60fps
        if (capTimer.getTicks() < (1000 / window->getMaxFps()))
        {
            int waitTime = (1000 / window->getMaxFps()) - capTimer.getTicks();
            //Log::info("Waiting " + std::to_string(waitTime) + " MS");
            SDL_Delay(waitTime);
        }
    }
}

void GameManager::gameTick()
{
    SDL_PollEvent(&event);

    // paddle is always added to the entities vector first, so this is fine
    Entity* paddle = entities[0];

    switch (event.type)
    {
    // if user clicks the red X
    case SDL_QUIT:
        _quit = true;
        break;

    case SDL_KEYDOWN:
        switch (event.key.keysym.sym)
        {
        case SDLK_LEFT:
            paddle->startMoving(MOVE_LEFT);
            break;
        case SDLK_RIGHT:
            paddle->startMoving(MOVE_RIGHT);
            break;
        case SDLK_SPACE:
            if (ball->isOnPaddle())
                ball->detach();
            break;
        }
        break;

    case SDL_KEYUP:
        switch (event.key.keysym.sym)
        {
        case SDLK_LEFT:
            paddle->stopMoving(MOVE_LEFT);
            break;
        case SDLK_RIGHT:
            paddle->stopMoving(MOVE_RIGHT);
            break;
        }
        break;
    }

    for (Entity* e : entities)
    {
        // don't think this is that cpu intensive but I guess it could be
        if (ball->collidedWith(e))
        {
            ball->handleCollision(e);

        }

        if(ball2->collidedWith(e))
            ball2->handleCollision(e);

        e->update();
    }

/************** Code segment used for powerup implementation ***************/
if(randNum == 0)    //anthony is gay
{
    mod->update();
        if(mod->collidedWith(paddle))
        {
          mod->doubleBalls();
          ball2->detach();
          mod->remove();
        }
        ball2->update();
        ball2->outOfBounds();
}

if(randNum == 1)
{
  mod->update();
  if(mod->collidedWith(paddle))
  {
    mod->largePaddle();
    mod->remove();
  }
}

if(randNum == 2)
{
    mod->update();
        if(mod->collidedWith(paddle))
        {
            mod->slowerPaddle();
            paddle->setMoveRate(3);
            mod->remove();
        }
    }
  if(randNum == 3)
  {
      mod->update();
        if(mod->collidedWith(paddle))
        {
            mod->smallPaddle();
            mod->remove();
        }
    }
/***************************************************************************/

    ball->update();
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2020 mogemimi. Distributed under the MIT license.

#include "Pomdog/Logging/Log.hpp"
#include "Pomdog/Basic/ConditionalCompilation.hpp"
#include "Pomdog/Logging/LogChannel.hpp"
#include "Pomdog/Logging/LogEntry.hpp"
#include "Pomdog/Signals/Connection.hpp"
#include "Pomdog/Signals/ScopedConnection.hpp"

POMDOG_SUPPRESS_WARNINGS_GENERATED_BY_STD_HEADERS_BEGIN
#include <algorithm>
#include <memory>
#include <mutex>
#include <vector>
POMDOG_SUPPRESS_WARNINGS_GENERATED_BY_STD_HEADERS_END

namespace Pomdog {
namespace {

class Logger final {
public:
    Connection Connect(const std::function<void(const LogEntry&)>& slot);

    Connection Connect(std::function<void(const LogEntry&)>&& slot);

    Connection Connect(
        const std::string& channelName,
        const std::function<void(const LogEntry&)>& slot);

    Connection Connect(
        const std::string& channelName,
        std::function<void(const LogEntry&)>&& slot);

    LogLevel GetLevel() const;

    void SetLevel(LogLevel verbosity);

    LogLevel GetLevel(const std::string& channelName) const;

    void SetLevel(const std::string& channelName, LogLevel verbosity);

    void Log(const std::string& message, LogLevel verbosity);

    void Log(const LogEntry& entry);

private:
    LogChannel defaultChannel;
    struct ChannelTuple {
        LogChannel channel;
        ScopedConnection connection;
    };
    std::vector<ChannelTuple> channels;
    std::recursive_mutex channelsProtection;
};

Connection Logger::Connect(const std::function<void(const LogEntry&)>& slot)
{
    return defaultChannel.Connect(slot);
}

Connection Logger::Connect(std::function<void(const LogEntry&)>&& slot)
{
    return defaultChannel.Connect(std::move(slot));
}

template <typename T>
auto FindChannnel(const std::string& channelName, T& channels)
    -> decltype(channels.begin())
{
    return std::find_if(std::begin(channels), std::end(channels),
        [&channelName](const decltype(channels.front())& tuple) {
            return channelName == tuple.channel.GetName();
        });
}

Connection Logger::Connect(
    const std::string& channelName,
    const std::function<void(const LogEntry&)>& slot)
{
    auto iter = FindChannnel(channelName, channels);
    if (std::end(channels) == iter) {
        std::lock_guard<std::recursive_mutex> lock(channelsProtection);

        ChannelTuple tuple;
        tuple.channel = LogChannel{channelName};
        channels.push_back(std::move(tuple));
        iter = std::prev(channels.end());
    }

    POMDOG_ASSERT(iter != std::end(channels));
    POMDOG_ASSERT(channelName == iter->channel.GetName());

    auto& channel = iter->channel;
    auto& connection = iter->connection;

    connection = channel.Connect([this](const LogEntry& entry) {
        defaultChannel.Log(entry);
    });
    return channel.Connect(slot);
}

Connection Logger::Connect(
    const std::string& channelName,
    std::function<void(const LogEntry&)>&& slot)
{
    auto iter = FindChannnel(channelName, channels);
    if (std::end(channels) == iter) {
        std::lock_guard<std::recursive_mutex> lock(channelsProtection);

        ChannelTuple tuple;
        tuple.channel = LogChannel{channelName};
        channels.push_back(std::move(tuple));
        iter = std::prev(channels.end());
    }

    POMDOG_ASSERT(iter != std::end(channels));
    POMDOG_ASSERT(channelName == iter->channel.GetName());

    auto& channel = iter->channel;
    auto& connection = iter->connection;

    connection = channel.Connect([this](const LogEntry& entry) {
        defaultChannel.Log(entry);
    });
    return channel.Connect(std::move(slot));
}

LogLevel Logger::GetLevel() const
{
    return defaultChannel.GetLevel();
}

void Logger::SetLevel(LogLevel level)
{
    defaultChannel.SetLevel(level);
}

LogLevel Logger::GetLevel(const std::string& channelName) const
{
    auto iter = FindChannnel(channelName, channels);
    if (iter != std::end(channels)) {
        return iter->channel.GetLevel();
    }
    return defaultChannel.GetLevel();
}

void Logger::SetLevel(const std::string& channelName, LogLevel level)
{
    auto iter = FindChannnel(channelName, channels);
    if (iter != std::end(channels)) {
        iter->channel.SetLevel(level);
    }
}

void Logger::Log(const std::string& message, LogLevel verbosity)
{
    defaultChannel.Log(message, verbosity);
}

void Logger::Log(const LogEntry& entry)
{
    auto iter = FindChannnel(entry.Tag, channels);
    if (std::end(channels) != iter) {
        iter->channel.Log(entry);
    }
    else {
        defaultChannel.Log(entry);
    }
}

Logger& GetLoggerInstance()
{
    static Logger logger;
    return logger;
}

} // namespace

// MARK: - Log class

Connection Log::Connect(const std::function<void(const LogEntry&)>& slot)
{
    auto& logger = GetLoggerInstance();
    return logger.Connect(slot);
}

Connection Log::Connect(std::function<void(const LogEntry&)>&& slot)
{
    auto& logger = GetLoggerInstance();
    return logger.Connect(std::move(slot));
}

Connection Log::Connect(const std::string& channelName,
    const std::function<void(const LogEntry&)>& slot)
{
    auto& logger = GetLoggerInstance();
    return logger.Connect(channelName, slot);
}

Connection Log::Connect(const std::string& channelName,
    std::function<void(const LogEntry&)>&& slot)
{
    auto& logger = GetLoggerInstance();
    return logger.Connect(channelName, std::move(slot));
}

LogLevel Log::GetLevel()
{
    auto& logger = GetLoggerInstance();
    return logger.GetLevel();
}

void Log::SetLevel(LogLevel verbosity)
{
    auto& logger = GetLoggerInstance();
    return logger.SetLevel(verbosity);
}

LogLevel Log::GetLevel(const std::string& channelName)
{
    auto& logger = GetLoggerInstance();
    return logger.GetLevel(channelName);
}

void Log::SetLevel(const std::string& channelName, LogLevel verbosity)
{
    auto& logger = GetLoggerInstance();
    return logger.SetLevel(channelName, verbosity);
}

void Log::Critical(const std::string& channelName, const std::string& message)
{
    auto& logger = GetLoggerInstance();
    logger.Log(LogEntry{message, channelName, LogLevel::Critical});
}

void Log::Warning(const std::string& channelName, const std::string& message)
{
    auto& logger = GetLoggerInstance();
    logger.Log(LogEntry{message, channelName, LogLevel::Warning});
}

void Log::Info(const std::string& message)
{
    auto& logger = GetLoggerInstance();
    logger.Log(message, LogLevel::Info);
}

void Log::Info(const std::string& channelName, const std::string& message)
{
    auto& logger = GetLoggerInstance();
    logger.Log(LogEntry{message, channelName, LogLevel::Info});
}

void Log::Verbose(const std::string& message)
{
    auto& logger = GetLoggerInstance();
    logger.Log(message, LogLevel::Verbose);
}

void Log::Verbose(const std::string& channelName, const std::string& message)
{
    auto& logger = GetLoggerInstance();
    logger.Log(LogEntry{message, channelName, LogLevel::Verbose});
}

void Log::Internal(const std::string& message)
{
    auto& logger = GetLoggerInstance();
    logger.Log(message, LogLevel::Internal);
}

void Log::Internal(const std::string& channelName, const std::string& message)
{
    auto& logger = GetLoggerInstance();
    logger.Log(LogEntry{message, channelName, LogLevel::Internal});
}

} // namespace Pomdog
<commit_msg>Suppress warning -Wexit-time-destructors<commit_after>// Copyright (c) 2013-2020 mogemimi. Distributed under the MIT license.

#include "Pomdog/Logging/Log.hpp"
#include "Pomdog/Basic/ConditionalCompilation.hpp"
#include "Pomdog/Logging/LogChannel.hpp"
#include "Pomdog/Logging/LogEntry.hpp"
#include "Pomdog/Signals/Connection.hpp"
#include "Pomdog/Signals/ScopedConnection.hpp"

POMDOG_SUPPRESS_WARNINGS_GENERATED_BY_STD_HEADERS_BEGIN
#include <algorithm>
#include <memory>
#include <mutex>
#include <vector>
POMDOG_SUPPRESS_WARNINGS_GENERATED_BY_STD_HEADERS_END

namespace Pomdog {
namespace {

class Logger final {
public:
    Connection Connect(const std::function<void(const LogEntry&)>& slot);

    Connection Connect(std::function<void(const LogEntry&)>&& slot);

    Connection Connect(
        const std::string& channelName,
        const std::function<void(const LogEntry&)>& slot);

    Connection Connect(
        const std::string& channelName,
        std::function<void(const LogEntry&)>&& slot);

    LogLevel GetLevel() const;

    void SetLevel(LogLevel verbosity);

    LogLevel GetLevel(const std::string& channelName) const;

    void SetLevel(const std::string& channelName, LogLevel verbosity);

    void Log(const std::string& message, LogLevel verbosity);

    void Log(const LogEntry& entry);

private:
    LogChannel defaultChannel;
    struct ChannelTuple {
        LogChannel channel;
        ScopedConnection connection;
    };
    std::vector<ChannelTuple> channels;
    std::recursive_mutex channelsProtection;
};

Connection Logger::Connect(const std::function<void(const LogEntry&)>& slot)
{
    return defaultChannel.Connect(slot);
}

Connection Logger::Connect(std::function<void(const LogEntry&)>&& slot)
{
    return defaultChannel.Connect(std::move(slot));
}

template <typename T>
auto FindChannnel(const std::string& channelName, T& channels)
    -> decltype(channels.begin())
{
    return std::find_if(std::begin(channels), std::end(channels),
        [&channelName](const decltype(channels.front())& tuple) {
            return channelName == tuple.channel.GetName();
        });
}

Connection Logger::Connect(
    const std::string& channelName,
    const std::function<void(const LogEntry&)>& slot)
{
    auto iter = FindChannnel(channelName, channels);
    if (std::end(channels) == iter) {
        std::lock_guard<std::recursive_mutex> lock(channelsProtection);

        ChannelTuple tuple;
        tuple.channel = LogChannel{channelName};
        channels.push_back(std::move(tuple));
        iter = std::prev(channels.end());
    }

    POMDOG_ASSERT(iter != std::end(channels));
    POMDOG_ASSERT(channelName == iter->channel.GetName());

    auto& channel = iter->channel;
    auto& connection = iter->connection;

    connection = channel.Connect([this](const LogEntry& entry) {
        defaultChannel.Log(entry);
    });
    return channel.Connect(slot);
}

Connection Logger::Connect(
    const std::string& channelName,
    std::function<void(const LogEntry&)>&& slot)
{
    auto iter = FindChannnel(channelName, channels);
    if (std::end(channels) == iter) {
        std::lock_guard<std::recursive_mutex> lock(channelsProtection);

        ChannelTuple tuple;
        tuple.channel = LogChannel{channelName};
        channels.push_back(std::move(tuple));
        iter = std::prev(channels.end());
    }

    POMDOG_ASSERT(iter != std::end(channels));
    POMDOG_ASSERT(channelName == iter->channel.GetName());

    auto& channel = iter->channel;
    auto& connection = iter->connection;

    connection = channel.Connect([this](const LogEntry& entry) {
        defaultChannel.Log(entry);
    });
    return channel.Connect(std::move(slot));
}

LogLevel Logger::GetLevel() const
{
    return defaultChannel.GetLevel();
}

void Logger::SetLevel(LogLevel level)
{
    defaultChannel.SetLevel(level);
}

LogLevel Logger::GetLevel(const std::string& channelName) const
{
    auto iter = FindChannnel(channelName, channels);
    if (iter != std::end(channels)) {
        return iter->channel.GetLevel();
    }
    return defaultChannel.GetLevel();
}

void Logger::SetLevel(const std::string& channelName, LogLevel level)
{
    auto iter = FindChannnel(channelName, channels);
    if (iter != std::end(channels)) {
        iter->channel.SetLevel(level);
    }
}

void Logger::Log(const std::string& message, LogLevel verbosity)
{
    defaultChannel.Log(message, verbosity);
}

void Logger::Log(const LogEntry& entry)
{
    auto iter = FindChannnel(entry.Tag, channels);
    if (std::end(channels) != iter) {
        iter->channel.Log(entry);
    }
    else {
        defaultChannel.Log(entry);
    }
}

Logger& GetLoggerInstance()
{
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wexit-time-destructors"
#endif
    static Logger logger;
    return logger;
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
}

} // namespace

// MARK: - Log class

Connection Log::Connect(const std::function<void(const LogEntry&)>& slot)
{
    auto& logger = GetLoggerInstance();
    return logger.Connect(slot);
}

Connection Log::Connect(std::function<void(const LogEntry&)>&& slot)
{
    auto& logger = GetLoggerInstance();
    return logger.Connect(std::move(slot));
}

Connection Log::Connect(const std::string& channelName,
    const std::function<void(const LogEntry&)>& slot)
{
    auto& logger = GetLoggerInstance();
    return logger.Connect(channelName, slot);
}

Connection Log::Connect(const std::string& channelName,
    std::function<void(const LogEntry&)>&& slot)
{
    auto& logger = GetLoggerInstance();
    return logger.Connect(channelName, std::move(slot));
}

LogLevel Log::GetLevel()
{
    auto& logger = GetLoggerInstance();
    return logger.GetLevel();
}

void Log::SetLevel(LogLevel verbosity)
{
    auto& logger = GetLoggerInstance();
    return logger.SetLevel(verbosity);
}

LogLevel Log::GetLevel(const std::string& channelName)
{
    auto& logger = GetLoggerInstance();
    return logger.GetLevel(channelName);
}

void Log::SetLevel(const std::string& channelName, LogLevel verbosity)
{
    auto& logger = GetLoggerInstance();
    return logger.SetLevel(channelName, verbosity);
}

void Log::Critical(const std::string& channelName, const std::string& message)
{
    auto& logger = GetLoggerInstance();
    logger.Log(LogEntry{message, channelName, LogLevel::Critical});
}

void Log::Warning(const std::string& channelName, const std::string& message)
{
    auto& logger = GetLoggerInstance();
    logger.Log(LogEntry{message, channelName, LogLevel::Warning});
}

void Log::Info(const std::string& message)
{
    auto& logger = GetLoggerInstance();
    logger.Log(message, LogLevel::Info);
}

void Log::Info(const std::string& channelName, const std::string& message)
{
    auto& logger = GetLoggerInstance();
    logger.Log(LogEntry{message, channelName, LogLevel::Info});
}

void Log::Verbose(const std::string& message)
{
    auto& logger = GetLoggerInstance();
    logger.Log(message, LogLevel::Verbose);
}

void Log::Verbose(const std::string& channelName, const std::string& message)
{
    auto& logger = GetLoggerInstance();
    logger.Log(LogEntry{message, channelName, LogLevel::Verbose});
}

void Log::Internal(const std::string& message)
{
    auto& logger = GetLoggerInstance();
    logger.Log(message, LogLevel::Internal);
}

void Log::Internal(const std::string& channelName, const std::string& message)
{
    auto& logger = GetLoggerInstance();
    logger.Log(LogEntry{message, channelName, LogLevel::Internal});
}

} // namespace Pomdog
<|endoftext|>