<commit_before>#ifndef LIMONP_CODE_CONVERTER_HPP
#define LIMONP_CODE_CONVERTER_HPP

#include <iconv.h>
#include <iostream>
#include <memory.h>

namespace Limonp
{
    using namespace std;
    class CodeConverter
    {
        public:
            CodeConverter(const char *from_charset,const char *to_charset)
            {
                _iconv_handle = iconv_open(to_charset,from_charset);
            }

            ~CodeConverter()
            {
                iconv_close(_iconv_handle);
            }

            bool convert(const string& from, string& to) const
            {
                char * pfrom = (char*)from.c_str();
                size_t from_size = from.size();
                to.resize(from_size * 2); // iconv failed, may be you can raise this 2 to bigger number.
                char * pto = (char*)to.c_str();
                size_t to_size = to.size();
                if(-1 == iconv(_iconv_handle, &pfrom, &from_size, &pto, &to_size))
                {
                    to.clear();
                    return false;
                }
                to.resize(to.size() - to_size);
                return true;
            }
        private:
            iconv_t _iconv_handle;
    };

}

#endif
<commit_msg>update limonp/codeconverter.hpp<commit_after>#ifndef LIMONP_CODE_CONVERTER_HPP
#define LIMONP_CODE_CONVERTER_HPP

#include <iconv.h>
#include <iostream>
#include <memory.h>

namespace Limonp
{
    using namespace std;
    class CodeConverter
    {
        public:
            CodeConverter(const char *from_charset,const char *to_charset)
            {
                _iconv_handle = iconv_open(to_charset,from_charset);
            }

            ~CodeConverter()
            {
                iconv_close(_iconv_handle);
            }

            bool convert(const string& from, string& to) const
            {
                char * pfrom = (char*)from.c_str();
                size_t from_size = from.size();
                to.resize(from_size * 2); // iconv failed, may be you can raise this 2 to bigger number.
                char * pto = (char*)to.c_str();
                size_t to_size = to.size();
                if(-1 == iconv(_iconv_handle, &pfrom, &from_size, &pto, &to_size))
                {
                    to.clear();
                    return false;
                }
                to.resize(to.size() - to_size);
                return true;
            }
        private:
            iconv_t _iconv_handle;
    };

    inline bool code_convert(const char* from_charset, const char* to_charset, const string& from, string& to)
    {
        CodeConverter cc(from_charset, to_charset);
        return cc.convert(from, to);
    }
}

#endif
<|endoftext|>


<commit_before>
// FastNBT.cpp

// Implements the fast NBT parser and writer

#include "Globals.h"
#include "FastNBT.h"

// The number of NBT tags that are reserved when an NBT parsing is started.
// You can override this by using a cmdline define
#ifndef NBT_RESERVE_SIZE
	#define NBT_RESERVE_SIZE 200
#endif  // NBT_RESERVE_SIZE

#ifdef _MSC_VER
	// Dodge a C4127 (conditional expression is constant) for this specific macro usage
	#define RETURN_FALSE_IF_FALSE(X) do { if (!X) return false; } while ((false, false))
#else
	#define RETURN_FALSE_IF_FALSE(X) do { if (!X) return false; } while (false)
#endif

////////////////////////////////////////////////////////////////////////////////
// cParsedNBT:

#define NEEDBYTES(N) \
	if (m_Length - m_Pos < (size_t)N) \
	{ \
		return false; \
	}

cParsedNBT::cParsedNBT(const char * a_Data, size_t a_Length) :
	m_Data(a_Data),
	m_Length(a_Length),
	m_Pos(0)
{
	m_IsValid = Parse();
}

bool cParsedNBT::Parse(void)
{
	if (m_Length < 3)
	{
		// Data too short
		return false;
	}
	if (m_Data[0] != TAG_Compound)
	{
		// The top-level tag must be a Compound
		return false;
	}

	m_Tags.reserve(NBT_RESERVE_SIZE);

	m_Tags.push_back(cFastNBTTag(TAG_Compound, -1));

	m_Pos = 1;

	RETURN_FALSE_IF_FALSE(ReadString(m_Tags.back().m_NameStart, m_Tags.back().m_NameLength));
	RETURN_FALSE_IF_FALSE(ReadCompound());

	return true;
}

bool cParsedNBT::ReadString(size_t & a_StringStart, size_t & a_StringLen)
{
	NEEDBYTES(2);
	a_StringStart = m_Pos + 2;
	a_StringLen = (size_t)GetBEShort(m_Data + m_Pos);
	if (a_StringLen > 0xffff)
	{
		// Suspicious string length
		return false;
	}
	m_Pos += 2 + a_StringLen;
	return true;
}

bool cParsedNBT::ReadCompound(void)
{
	ASSERT(m_Tags.size() > 0);

	// Reads the latest tag as a compound
	int ParentIdx = (int)m_Tags.size() - 1;
	int PrevSibling = -1;
	for (;;)
	{
		NEEDBYTES(1);
		eTagType TagType = (eTagType)(m_Data[m_Pos]);
		m_Pos++;
		if (TagType == TAG_End)
		{
			break;
		}
		m_Tags.push_back(cFastNBTTag(TagType, ParentIdx, PrevSibling));
		if (PrevSibling >= 0)
		{
			m_Tags[PrevSibling].m_NextSibling = (int)m_Tags.size() - 1;
		}
		else
		{
			m_Tags[ParentIdx].m_FirstChild = (int)m_Tags.size() - 1;
		}
		PrevSibling = (int)m_Tags.size() - 1;
		RETURN_FALSE_IF_FALSE(ReadString(m_Tags.back().m_NameStart, m_Tags.back().m_NameLength));
		RETURN_FALSE_IF_FALSE(ReadTag());
	}  // while (true)
	m_Tags[ParentIdx].m_LastChild = PrevSibling;
	return true;
}

bool cParsedNBT::ReadList(eTagType a_ChildrenType)
{
	// Reads the latest tag as a list of items of type a_ChildrenType

	// Read the count:
	NEEDBYTES(4);
	int Count = GetBEInt(m_Data + m_Pos);
	m_Pos += 4;
	if (Count < 0)
	{
		return false;
	}

	// Read items:
	int ParentIdx = (int)m_Tags.size() - 1;
	int PrevSibling = -1;
	for (int i = 0; i < Count; i++)
	{
		m_Tags.push_back(cFastNBTTag(a_ChildrenType, ParentIdx, PrevSibling));
		if (PrevSibling >= 0)
		{
			m_Tags[PrevSibling].m_NextSibling = (int)m_Tags.size() - 1;
		}
		else
		{
			m_Tags[ParentIdx].m_FirstChild = (int)m_Tags.size() - 1;
		}
		PrevSibling = (int)m_Tags.size() - 1;
		RETURN_FALSE_IF_FALSE(ReadTag());
	}  // for (i)
	m_Tags[ParentIdx].m_LastChild = PrevSibling;
	return true;
}

#define CASE_SIMPLE_TAG(TAGTYPE, LEN) \
	case TAG_##TAGTYPE: \
	{ \
		NEEDBYTES(LEN); \
		Tag.m_DataStart = m_Pos; \
		Tag.m_DataLength = LEN; \
		m_Pos += LEN; \
		return true; \
	}

bool cParsedNBT::ReadTag(void)
{
	cFastNBTTag & Tag = m_Tags.back();
	switch (Tag.m_Type)
	{
		CASE_SIMPLE_TAG(Byte,   1)
		CASE_SIMPLE_TAG(Short,  2)
		CASE_SIMPLE_TAG(Int,    4)
		CASE_SIMPLE_TAG(Long,   8)
		CASE_SIMPLE_TAG(Float,  4)
		CASE_SIMPLE_TAG(Double, 8)

		case TAG_String:
		{
			return ReadString(Tag.m_DataStart, Tag.m_DataLength);
		}

		case TAG_ByteArray:
		{
			NEEDBYTES(4);
			int len = GetBEInt(m_Data + m_Pos);
			m_Pos += 4;
			if (len < 0)
			{
				// Invalid length
				return false;
			}
			NEEDBYTES(len);
			Tag.m_DataLength = len;
			Tag.m_DataStart = m_Pos;
			m_Pos += len;
			return true;
		}

		case TAG_List:
		{
			NEEDBYTES(1);
			eTagType ItemType = (eTagType)m_Data[m_Pos];
			m_Pos++;
			RETURN_FALSE_IF_FALSE(ReadList(ItemType));
			return true;
		}

		case TAG_Compound:
		{
			RETURN_FALSE_IF_FALSE(ReadCompound());
			return true;
		}

		case TAG_IntArray:
		{
			NEEDBYTES(4);
			int len = GetBEInt(m_Data + m_Pos);
			m_Pos += 4;
			if (len < 0)
			{
				// Invalid length
				return false;
			}
			len *= 4;
			NEEDBYTES(len);
			Tag.m_DataLength = len;
			Tag.m_DataStart = m_Pos;
			m_Pos += len;
			return true;
		}

		default:
		{
			ASSERT(!"Unhandled NBT tag type");
			return false;
		}
	}  // switch (iType)
}

#undef CASE_SIMPLE_TAG

int cParsedNBT::FindChildByName(int a_Tag, const char * a_Name, size_t a_NameLength) const
{
	if (a_Tag < 0)
	{
		return -1;
	}
	if (m_Tags[a_Tag].m_Type != TAG_Compound)
	{
		return -1;
	}

	if (a_NameLength == 0)
	{
		a_NameLength = strlen(a_Name);
	}
	for (int Child = m_Tags[a_Tag].m_FirstChild; Child != -1; Child = m_Tags[Child].m_NextSibling)
	{
		if (
			(m_Tags[Child].m_NameLength == a_NameLength) &&
			(memcmp(m_Data + m_Tags[Child].m_NameStart, a_Name, a_NameLength) == 0)
		)
		{
			return Child;
		}
	}  // for Child - children of a_Tag
	return -1;
}

int cParsedNBT::FindTagByPath(int a_Tag, const AString & a_Path) const
{
	if (a_Tag < 0)
	{
		return -1;
	}
	size_t Begin = 0;
	size_t Length = a_Path.length();
	int Tag = a_Tag;
	for (size_t i = 0; i < Length; i++)
	{
		if (a_Path[i] != '\\')
		{
			continue;
		}
		Tag = FindChildByName(Tag, a_Path.c_str() + Begin, i - Begin);
		if (Tag < 0)
		{
			return -1;
		}
		Begin = i + 1;
	}  // for i - a_Path[]

	if (Begin < Length)
	{
		Tag = FindChildByName(Tag, a_Path.c_str() + Begin, Length - Begin);
	}
	return Tag;
}

////////////////////////////////////////////////////////////////////////////////
// cFastNBTWriter:

cFastNBTWriter::cFastNBTWriter(const AString & a_RootTagName) :
	m_CurrentStack(0)
{
	m_Stack[0].m_Type = TAG_Compound;
	m_Result.reserve(100 * 1024);
	m_Result.push_back(TAG_Compound);
	WriteString(a_RootTagName.data(), (UInt16)a_RootTagName.size());
}

void cFastNBTWriter::BeginCompound(const AString & a_Name)
{
	if (m_CurrentStack >= MAX_STACK - 1)
	{
		ASSERT(!"Stack overflow");
		return;
	}

	TagCommon(a_Name, TAG_Compound);

	++m_CurrentStack;
	m_Stack[m_CurrentStack].m_Type = TAG_Compound;
}

void cFastNBTWriter::EndCompound(void)
{
	ASSERT(m_CurrentStack > 0);
	ASSERT(IsStackTopCompound());

	m_Result.push_back(TAG_End);
	--m_CurrentStack;
}

void cFastNBTWriter::BeginList(const AString & a_Name, eTagType a_ChildrenType)
{
	if (m_CurrentStack >= MAX_STACK - 1)
	{
		ASSERT(!"Stack overflow");
		return;
	}

	TagCommon(a_Name, TAG_List);

	m_Result.push_back((char)a_ChildrenType);
	m_Result.append(4, (char)0);

	++m_CurrentStack;
	m_Stack[m_CurrentStack].m_Type     = TAG_List;
	m_Stack[m_CurrentStack].m_Pos      = (int)m_Result.size() - 4;
	m_Stack[m_CurrentStack].m_Count    = 0;
	m_Stack[m_CurrentStack].m_ItemType = a_ChildrenType;
}

void cFastNBTWriter::EndList(void)
{
	ASSERT(m_CurrentStack > 0);
	ASSERT(m_Stack[m_CurrentStack].m_Type == TAG_List);

	// Update the list count:
	SetBEInt((char *)(m_Result.c_str() + m_Stack[m_CurrentStack].m_Pos), m_Stack[m_CurrentStack].m_Count);

	--m_CurrentStack;
}

void cFastNBTWriter::AddByte(const AString & a_Name, unsigned char a_Value)
{
	TagCommon(a_Name, TAG_Byte);
	m_Result.push_back(a_Value);
}

void cFastNBTWriter::AddShort(const AString & a_Name, Int16 a_Value)
{
	TagCommon(a_Name, TAG_Short);
	Int16 Value = htons(a_Value);
	m_Result.append((const char *)&Value, 2);
}

void cFastNBTWriter::AddInt(const AString & a_Name, Int32 a_Value)
{
	TagCommon(a_Name, TAG_Int);
	Int32 Value = htonl(a_Value);
	m_Result.append((const char *)&Value, 4);
}

void cFastNBTWriter::AddLong(const AString & a_Name, Int64 a_Value)
{
	TagCommon(a_Name, TAG_Long);
	Int64 Value = HostToNetwork8(&a_Value);
	m_Result.append((const char *)&Value, 8);
}

void cFastNBTWriter::AddFloat(const AString & a_Name, float a_Value)
{
	TagCommon(a_Name, TAG_Float);
	Int32 Value = HostToNetwork4(&a_Value);
	m_Result.append((const char *)&Value, 4);
}

void cFastNBTWriter::AddDouble(const AString & a_Name, double a_Value)
{
	TagCommon(a_Name, TAG_Double);
	Int64 Value = HostToNetwork8(&a_Value);
	m_Result.append((const char *)&Value, 8);
}

void cFastNBTWriter::AddString(const AString & a_Name, const AString & a_Value)
{
	TagCommon(a_Name, TAG_String);
	Int16 len = htons((short)(a_Value.size()));
	m_Result.append((const char *)&len, 2);
	m_Result.append(a_Value.c_str(), a_Value.size());
}

void cFastNBTWriter::AddByteArray(const AString & a_Name, const char * a_Value, size_t a_NumElements)
{
	TagCommon(a_Name, TAG_ByteArray);
	u_long len = htonl((u_long)a_NumElements);
	m_Result.append((const char *)&len, 4);
	m_Result.append(a_Value, a_NumElements);
}

void cFastNBTWriter::AddIntArray(const AString & a_Name, const int * a_Value, size_t a_NumElements)
{
	TagCommon(a_Name, TAG_IntArray);
	u_long len = htonl((u_long)a_NumElements);
	size_t cap = m_Result.capacity();
	size_t size = m_Result.length();
	if ((cap - size) < (4 + a_NumElements * 4))
	{
		m_Result.reserve(size + 4 + (a_NumElements * 4));
	}
	m_Result.append((const char *)&len, 4);
	for (size_t i = 0; i < a_NumElements; i++)
	{
		int Element = htonl(a_Value[i]);
		m_Result.append((const char *)&Element, 4);
	}
}

void cFastNBTWriter::Finish(void)
{
	ASSERT(m_CurrentStack == 0);
	m_Result.push_back(TAG_End);
}

void cFastNBTWriter::WriteString(const char * a_Data, UInt16 a_Length)
{
	Int16 Len = htons(a_Length);
	m_Result.append((const char *)&Len, 2);
	m_Result.append(a_Data, a_Length);
}

<commit_msg>FastNBT: Added a sanity check for number of list items.<commit_after>
// FastNBT.cpp

// Implements the fast NBT parser and writer

#include "Globals.h"
#include "FastNBT.h"

/** If a list being loaded has more than this number of items, it's considered corrupted. */
static const int MAX_LIST_ITEMS = 10000;

// The number of NBT tags that are reserved when an NBT parsing is started.
// You can override this by using a cmdline define
#ifndef NBT_RESERVE_SIZE
	#define NBT_RESERVE_SIZE 200
#endif  // NBT_RESERVE_SIZE

#ifdef _MSC_VER
	// Dodge a C4127 (conditional expression is constant) for this specific macro usage
	#define RETURN_FALSE_IF_FALSE(X) do { if (!X) return false; } while ((false, false))
#else
	#define RETURN_FALSE_IF_FALSE(X) do { if (!X) return false; } while (false)
#endif

////////////////////////////////////////////////////////////////////////////////
// cParsedNBT:

#define NEEDBYTES(N) \
	if (m_Length - m_Pos < (size_t)N) \
	{ \
		return false; \
	}

cParsedNBT::cParsedNBT(const char * a_Data, size_t a_Length) :
	m_Data(a_Data),
	m_Length(a_Length),
	m_Pos(0)
{
	m_IsValid = Parse();
}

bool cParsedNBT::Parse(void)
{
	if (m_Length < 3)
	{
		// Data too short
		return false;
	}
	if (m_Data[0] != TAG_Compound)
	{
		// The top-level tag must be a Compound
		return false;
	}

	m_Tags.reserve(NBT_RESERVE_SIZE);

	m_Tags.push_back(cFastNBTTag(TAG_Compound, -1));

	m_Pos = 1;

	RETURN_FALSE_IF_FALSE(ReadString(m_Tags.back().m_NameStart, m_Tags.back().m_NameLength));
	RETURN_FALSE_IF_FALSE(ReadCompound());

	return true;
}

bool cParsedNBT::ReadString(size_t & a_StringStart, size_t & a_StringLen)
{
	NEEDBYTES(2);
	a_StringStart = m_Pos + 2;
	a_StringLen = (size_t)GetBEShort(m_Data + m_Pos);
	if (a_StringLen > 0xffff)
	{
		// Suspicious string length
		return false;
	}
	m_Pos += 2 + a_StringLen;
	return true;
}

bool cParsedNBT::ReadCompound(void)
{
	ASSERT(m_Tags.size() > 0);

	// Reads the latest tag as a compound
	int ParentIdx = (int)m_Tags.size() - 1;
	int PrevSibling = -1;
	for (;;)
	{
		NEEDBYTES(1);
		eTagType TagType = (eTagType)(m_Data[m_Pos]);
		m_Pos++;
		if (TagType == TAG_End)
		{
			break;
		}
		m_Tags.push_back(cFastNBTTag(TagType, ParentIdx, PrevSibling));
		if (PrevSibling >= 0)
		{
			m_Tags[PrevSibling].m_NextSibling = (int)m_Tags.size() - 1;
		}
		else
		{
			m_Tags[ParentIdx].m_FirstChild = (int)m_Tags.size() - 1;
		}
		PrevSibling = (int)m_Tags.size() - 1;
		RETURN_FALSE_IF_FALSE(ReadString(m_Tags.back().m_NameStart, m_Tags.back().m_NameLength));
		RETURN_FALSE_IF_FALSE(ReadTag());
	}  // while (true)
	m_Tags[ParentIdx].m_LastChild = PrevSibling;
	return true;
}

bool cParsedNBT::ReadList(eTagType a_ChildrenType)
{
	// Reads the latest tag as a list of items of type a_ChildrenType

	// Read the count:
	NEEDBYTES(4);
	int Count = GetBEInt(m_Data + m_Pos);
	m_Pos += 4;
	if ((Count < 0) || (Count > MAX_LIST_ITEMS))
	{
		return false;
	}

	// Read items:
	int ParentIdx = (int)m_Tags.size() - 1;
	int PrevSibling = -1;
	for (int i = 0; i < Count; i++)
	{
		m_Tags.push_back(cFastNBTTag(a_ChildrenType, ParentIdx, PrevSibling));
		if (PrevSibling >= 0)
		{
			m_Tags[PrevSibling].m_NextSibling = (int)m_Tags.size() - 1;
		}
		else
		{
			m_Tags[ParentIdx].m_FirstChild = (int)m_Tags.size() - 1;
		}
		PrevSibling = (int)m_Tags.size() - 1;
		RETURN_FALSE_IF_FALSE(ReadTag());
	}  // for (i)
	m_Tags[ParentIdx].m_LastChild = PrevSibling;
	return true;
}

#define CASE_SIMPLE_TAG(TAGTYPE, LEN) \
	case TAG_##TAGTYPE: \
	{ \
		NEEDBYTES(LEN); \
		Tag.m_DataStart = m_Pos; \
		Tag.m_DataLength = LEN; \
		m_Pos += LEN; \
		return true; \
	}

bool cParsedNBT::ReadTag(void)
{
	cFastNBTTag & Tag = m_Tags.back();
	switch (Tag.m_Type)
	{
		CASE_SIMPLE_TAG(Byte,   1)
		CASE_SIMPLE_TAG(Short,  2)
		CASE_SIMPLE_TAG(Int,    4)
		CASE_SIMPLE_TAG(Long,   8)
		CASE_SIMPLE_TAG(Float,  4)
		CASE_SIMPLE_TAG(Double, 8)

		case TAG_String:
		{
			return ReadString(Tag.m_DataStart, Tag.m_DataLength);
		}

		case TAG_ByteArray:
		{
			NEEDBYTES(4);
			int len = GetBEInt(m_Data + m_Pos);
			m_Pos += 4;
			if (len < 0)
			{
				// Invalid length
				return false;
			}
			NEEDBYTES(len);
			Tag.m_DataLength = len;
			Tag.m_DataStart = m_Pos;
			m_Pos += len;
			return true;
		}

		case TAG_List:
		{
			NEEDBYTES(1);
			eTagType ItemType = (eTagType)m_Data[m_Pos];
			m_Pos++;
			RETURN_FALSE_IF_FALSE(ReadList(ItemType));
			return true;
		}

		case TAG_Compound:
		{
			RETURN_FALSE_IF_FALSE(ReadCompound());
			return true;
		}

		case TAG_IntArray:
		{
			NEEDBYTES(4);
			int len = GetBEInt(m_Data + m_Pos);
			m_Pos += 4;
			if (len < 0)
			{
				// Invalid length
				return false;
			}
			len *= 4;
			NEEDBYTES(len);
			Tag.m_DataLength = len;
			Tag.m_DataStart = m_Pos;
			m_Pos += len;
			return true;
		}

		default:
		{
			ASSERT(!"Unhandled NBT tag type");
			return false;
		}
	}  // switch (iType)
}

#undef CASE_SIMPLE_TAG

int cParsedNBT::FindChildByName(int a_Tag, const char * a_Name, size_t a_NameLength) const
{
	if (a_Tag < 0)
	{
		return -1;
	}
	if (m_Tags[a_Tag].m_Type != TAG_Compound)
	{
		return -1;
	}

	if (a_NameLength == 0)
	{
		a_NameLength = strlen(a_Name);
	}
	for (int Child = m_Tags[a_Tag].m_FirstChild; Child != -1; Child = m_Tags[Child].m_NextSibling)
	{
		if (
			(m_Tags[Child].m_NameLength == a_NameLength) &&
			(memcmp(m_Data + m_Tags[Child].m_NameStart, a_Name, a_NameLength) == 0)
		)
		{
			return Child;
		}
	}  // for Child - children of a_Tag
	return -1;
}

int cParsedNBT::FindTagByPath(int a_Tag, const AString & a_Path) const
{
	if (a_Tag < 0)
	{
		return -1;
	}
	size_t Begin = 0;
	size_t Length = a_Path.length();
	int Tag = a_Tag;
	for (size_t i = 0; i < Length; i++)
	{
		if (a_Path[i] != '\\')
		{
			continue;
		}
		Tag = FindChildByName(Tag, a_Path.c_str() + Begin, i - Begin);
		if (Tag < 0)
		{
			return -1;
		}
		Begin = i + 1;
	}  // for i - a_Path[]

	if (Begin < Length)
	{
		Tag = FindChildByName(Tag, a_Path.c_str() + Begin, Length - Begin);
	}
	return Tag;
}

////////////////////////////////////////////////////////////////////////////////
// cFastNBTWriter:

cFastNBTWriter::cFastNBTWriter(const AString & a_RootTagName) :
	m_CurrentStack(0)
{
	m_Stack[0].m_Type = TAG_Compound;
	m_Result.reserve(100 * 1024);
	m_Result.push_back(TAG_Compound);
	WriteString(a_RootTagName.data(), (UInt16)a_RootTagName.size());
}

void cFastNBTWriter::BeginCompound(const AString & a_Name)
{
	if (m_CurrentStack >= MAX_STACK - 1)
	{
		ASSERT(!"Stack overflow");
		return;
	}

	TagCommon(a_Name, TAG_Compound);

	++m_CurrentStack;
	m_Stack[m_CurrentStack].m_Type = TAG_Compound;
}

void cFastNBTWriter::EndCompound(void)
{
	ASSERT(m_CurrentStack > 0);
	ASSERT(IsStackTopCompound());

	m_Result.push_back(TAG_End);
	--m_CurrentStack;
}

void cFastNBTWriter::BeginList(const AString & a_Name, eTagType a_ChildrenType)
{
	if (m_CurrentStack >= MAX_STACK - 1)
	{
		ASSERT(!"Stack overflow");
		return;
	}

	TagCommon(a_Name, TAG_List);

	m_Result.push_back((char)a_ChildrenType);
	m_Result.append(4, (char)0);

	++m_CurrentStack;
	m_Stack[m_CurrentStack].m_Type     = TAG_List;
	m_Stack[m_CurrentStack].m_Pos      = (int)m_Result.size() - 4;
	m_Stack[m_CurrentStack].m_Count    = 0;
	m_Stack[m_CurrentStack].m_ItemType = a_ChildrenType;
}

void cFastNBTWriter::EndList(void)
{
	ASSERT(m_CurrentStack > 0);
	ASSERT(m_Stack[m_CurrentStack].m_Type == TAG_List);

	// Update the list count:
	SetBEInt((char *)(m_Result.c_str() + m_Stack[m_CurrentStack].m_Pos), m_Stack[m_CurrentStack].m_Count);

	--m_CurrentStack;
}

void cFastNBTWriter::AddByte(const AString & a_Name, unsigned char a_Value)
{
	TagCommon(a_Name, TAG_Byte);
	m_Result.push_back(a_Value);
}

void cFastNBTWriter::AddShort(const AString & a_Name, Int16 a_Value)
{
	TagCommon(a_Name, TAG_Short);
	Int16 Value = htons(a_Value);
	m_Result.append((const char *)&Value, 2);
}

void cFastNBTWriter::AddInt(const AString & a_Name, Int32 a_Value)
{
	TagCommon(a_Name, TAG_Int);
	Int32 Value = htonl(a_Value);
	m_Result.append((const char *)&Value, 4);
}

void cFastNBTWriter::AddLong(const AString & a_Name, Int64 a_Value)
{
	TagCommon(a_Name, TAG_Long);
	Int64 Value = HostToNetwork8(&a_Value);
	m_Result.append((const char *)&Value, 8);
}

void cFastNBTWriter::AddFloat(const AString & a_Name, float a_Value)
{
	TagCommon(a_Name, TAG_Float);
	Int32 Value = HostToNetwork4(&a_Value);
	m_Result.append((const char *)&Value, 4);
}

void cFastNBTWriter::AddDouble(const AString & a_Name, double a_Value)
{
	TagCommon(a_Name, TAG_Double);
	Int64 Value = HostToNetwork8(&a_Value);
	m_Result.append((const char *)&Value, 8);
}

void cFastNBTWriter::AddString(const AString & a_Name, const AString & a_Value)
{
	TagCommon(a_Name, TAG_String);
	Int16 len = htons((short)(a_Value.size()));
	m_Result.append((const char *)&len, 2);
	m_Result.append(a_Value.c_str(), a_Value.size());
}

void cFastNBTWriter::AddByteArray(const AString & a_Name, const char * a_Value, size_t a_NumElements)
{
	TagCommon(a_Name, TAG_ByteArray);
	u_long len = htonl((u_long)a_NumElements);
	m_Result.append((const char *)&len, 4);
	m_Result.append(a_Value, a_NumElements);
}

void cFastNBTWriter::AddIntArray(const AString & a_Name, const int * a_Value, size_t a_NumElements)
{
	TagCommon(a_Name, TAG_IntArray);
	u_long len = htonl((u_long)a_NumElements);
	size_t cap = m_Result.capacity();
	size_t size = m_Result.length();
	if ((cap - size) < (4 + a_NumElements * 4))
	{
		m_Result.reserve(size + 4 + (a_NumElements * 4));
	}
	m_Result.append((const char *)&len, 4);
	for (size_t i = 0; i < a_NumElements; i++)
	{
		int Element = htonl(a_Value[i]);
		m_Result.append((const char *)&Element, 4);
	}
}

void cFastNBTWriter::Finish(void)
{
	ASSERT(m_CurrentStack == 0);
	m_Result.push_back(TAG_End);
}

void cFastNBTWriter::WriteString(const char * a_Data, UInt16 a_Length)
{
	Int16 Len = htons(a_Length);
	m_Result.append((const char *)&Len, 2);
	m_Result.append(a_Data, a_Length);
}

<|endoftext|>


<commit_before>/*
 * Copyright 2009-2019 The VOTCA Development Team (http://www.votca.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
#include <cassert>

#include "../../include/votca/csg/beadstructure.h"

#include <votca/tools/graph_bf_visitor.h>
#include <votca/tools/graphalgorithm.h>
#include <votca/tools/graphdistvisitor.h>

using namespace std;
using namespace votca;
using namespace votca::csg;
using namespace votca::tools;

/**********************
 * Internal Functions *
 **********************/

void BeadStructure::InitializeGraph_() {
  if (!graphUpToDate) {
    std::vector<tools::Edge> connections_vector;
    for (const tools::Edge &edge : connections_) {
      connections_vector.push_back(edge);
    }

    for (std::pair<const Index, BeadInfo> &id_bead_ptr_pair : beads_) {
      graphnodes_[id_bead_ptr_pair.first] =
          BeadInfoToGraphNode_(id_bead_ptr_pair.second);
    }
    graph_ = tools::Graph(connections_vector, graphnodes_);
    graphUpToDate = true;
  }
}

void BeadStructure::CalculateStructure_() {

  InitializeGraph_();
  if (!structureIdUpToDate) {
    structure_id_ = tools::findStructureId<tools::GraphDistVisitor>(graph_);
    structureIdUpToDate = true;
  }
}

tools::GraphNode BeadStructure::BeadInfoToGraphNode_(
    const BeadInfo &bead_info) {
  std::unordered_map<std::string, double> attributes1;
  std::unordered_map<std::string, std::string> attributes2;

  attributes1["Mass"] = bead_info.mass;
  attributes2["Name"] = bead_info.name;

  /// Add graphnodes
  tools::GraphNode graphnode;
  graphnode.setDouble(attributes1);
  graphnode.setStr(attributes2);

  return graphnode;
}

/***************************
 * Public Facing Functions *
 ***************************/

BeadStructure BeadStructure::getSubStructure(
    const std::vector<Index> &bead_ids,
    const std::vector<tools::Edge> &connections) const {
  BeadStructure new_beadstructure;
  for (const Index &bead_id : bead_ids) {
    new_beadstructure.beads_[bead_id] = beads_.at(bead_id);
  }
  for (const tools::Edge &edge : connections) {
    new_beadstructure.ConnectBeads(edge.getEndPoint1(), edge.getEndPoint2());
  }
  return new_beadstructure;
}

void BeadStructure::ConnectBeads(const Index &bead1_id, const Index &bead2_id) {
  if (!(beads_.count(bead1_id)) || !(beads_.count(bead2_id))) {
    std::string err =
        "Cannot connect beads in bead structure that do not exist";
    throw std::invalid_argument(err);
  }
  if (bead1_id == bead2_id) {
    std::string err = "Beads cannot be self-connected";
    throw std::invalid_argument(err);
  }
  size_t numberOfConnections = connections_.size();
  connections_.insert(tools::Edge(bead1_id, bead2_id));
  if (numberOfConnections != connections_.size()) {
    single_structureUpToDate_ = false;
    graphUpToDate = false;
    structureIdUpToDate = false;
  }
}

tools::Graph BeadStructure::getGraph() {
  InitializeGraph_();
  return graph_;
}

bool BeadStructure::isSingleStructure() {

  InitializeGraph_();
  if (single_structureUpToDate_ == false) {
    std::vector<Index> vertices = graph_.getVertices();
    if (vertices.size() == 0) {
      single_structure_ = false;
      return single_structure_;
    }
    // Choose first vertex that is actually in the graph as the starting vertex
    tools::Graph_BF_Visitor gv_breadth_first;
    gv_breadth_first.setStartingVertex(vertices.at(0));
    if (!singleNetwork(graph_, gv_breadth_first)) {
      single_structure_ = false;
      return single_structure_;
    }
    if (beads_.size() == 0) {
      single_structure_ = false;
      return single_structure_;
    }
    if (vertices.size() != beads_.size()) {
      single_structure_ = false;
      return single_structure_;
    }
    single_structure_ = true;
    single_structureUpToDate_ = true;
  }
  return single_structure_;
}

bool BeadStructure::isStructureEquivalent(BeadStructure &beadstructure) {
  if (!structureIdUpToDate) {
    CalculateStructure_();
  }
  if (!beadstructure.structureIdUpToDate) {
    beadstructure.CalculateStructure_();
  }
  return structure_id_.compare(beadstructure.structure_id_) == 0;
}

std::vector<Index> BeadStructure::getNeighBeadIds(const Index &index) {
  if (!graphUpToDate) {
    InitializeGraph_();
  }
  std::vector<Index> neighbor_ids = graph_.getNeighVertices(index);
  return neighbor_ids;
}

std::vector<Index> BeadStructure::getBeadIds() const {
  /// Do not use graph_.getVertices() because this would require that the graph
  /// is updated
  vector<Index> bead_ids;
  for (auto &id_and_bead_info : beads_) {
    bead_ids.push_back(id_and_bead_info.first);
  }
  return bead_ids;
}
<commit_msg>Added exceptions if method requirements are not satisfied<commit_after>/*
 * Copyright 2009-2019 The VOTCA Development Team (http://www.votca.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
#include <cassert>

#include "../../include/votca/csg/beadstructure.h"

#include <votca/tools/graph_bf_visitor.h>
#include <votca/tools/graphalgorithm.h>
#include <votca/tools/graphdistvisitor.h>

using namespace std;
using namespace votca;
using namespace votca::csg;
using namespace votca::tools;

/**********************
 * Internal Functions *
 **********************/

void BeadStructure::InitializeGraph_() {
  if (!graphUpToDate) {
    std::vector<tools::Edge> connections_vector;
    for (const tools::Edge &edge : connections_) {
      connections_vector.push_back(edge);
    }

    for (std::pair<const Index, BeadInfo> &id_bead_ptr_pair : beads_) {
      graphnodes_[id_bead_ptr_pair.first] =
          BeadInfoToGraphNode_(id_bead_ptr_pair.second);
    }
    graph_ = tools::Graph(connections_vector, graphnodes_);
    graphUpToDate = true;
  }
}

void BeadStructure::CalculateStructure_() {

  InitializeGraph_();
  if (!structureIdUpToDate) {
    structure_id_ = tools::findStructureId<tools::GraphDistVisitor>(graph_);
    structureIdUpToDate = true;
  }
}

tools::GraphNode BeadStructure::BeadInfoToGraphNode_(
    const BeadInfo &bead_info) {
  std::unordered_map<std::string, double> attributes1;
  std::unordered_map<std::string, std::string> attributes2;

  attributes1["Mass"] = bead_info.mass;
  attributes2["Name"] = bead_info.name;

  /// Add graphnodes
  tools::GraphNode graphnode;
  graphnode.setDouble(attributes1);
  graphnode.setStr(attributes2);

  return graphnode;
}

/***************************
 * Public Facing Functions *
 ***************************/

BeadStructure BeadStructure::getSubStructure(
    const std::vector<Index> &bead_ids,
    const std::vector<tools::Edge> &connections) const {
  BeadStructure new_beadstructure;
  for (const Index &bead_id : bead_ids) {
    if (beads_.count(bead_id) == 0) {
      string error_msg =
          "Cannot get bead substructure from current "
          "BeadStructure, bead with id " +
          to_string(bead_id) +
          " is not found in"
          " the BeadStructure";
      throw runtime_error(error_msg);
    }
    new_beadstructure.beads_[bead_id] = beads_.at(bead_id);
  }
  for (const tools::Edge &edge : connections) {
    if (connections_.count(edge) == 0) {
      string error_msg =
          "Cannot get bead substructure from current "
          "BeadStructure, edge between beads " +
          to_string(edge.getEndPoint1()) + " and " +
          to_string(edge.getEndPoint2()) +
          " is not found in the "
          "BeadStructure";
      throw runtime_error(error_msg);
    }
    new_beadstructure.ConnectBeads(edge.getEndPoint1(), edge.getEndPoint2());
  }
  return new_beadstructure;
}

void BeadStructure::ConnectBeads(const Index &bead1_id, const Index &bead2_id) {
  if (!(beads_.count(bead1_id)) || !(beads_.count(bead2_id))) {
    std::string err =
        "Cannot connect beads in bead structure that do not exist";
    throw std::invalid_argument(err);
  }
  if (bead1_id == bead2_id) {
    std::string err = "Beads cannot be self-connected";
    throw std::invalid_argument(err);
  }
  size_t numberOfConnections = connections_.size();
  connections_.insert(tools::Edge(bead1_id, bead2_id));
  if (numberOfConnections != connections_.size()) {
    single_structureUpToDate_ = false;
    graphUpToDate = false;
    structureIdUpToDate = false;
  }
}

tools::Graph BeadStructure::getGraph() {
  InitializeGraph_();
  return graph_;
}

bool BeadStructure::isSingleStructure() {

  InitializeGraph_();
  if (single_structureUpToDate_ == false) {
    std::vector<Index> vertices = graph_.getVertices();
    if (vertices.size() == 0) {
      single_structure_ = false;
      return single_structure_;
    }
    // Choose first vertex that is actually in the graph as the starting vertex
    tools::Graph_BF_Visitor gv_breadth_first;
    gv_breadth_first.setStartingVertex(vertices.at(0));
    if (!singleNetwork(graph_, gv_breadth_first)) {
      single_structure_ = false;
      return single_structure_;
    }
    if (beads_.size() == 0) {
      single_structure_ = false;
      return single_structure_;
    }
    if (vertices.size() != beads_.size()) {
      single_structure_ = false;
      return single_structure_;
    }
    single_structure_ = true;
    single_structureUpToDate_ = true;
  }
  return single_structure_;
}

bool BeadStructure::isStructureEquivalent(BeadStructure &beadstructure) {
  if (!structureIdUpToDate) {
    CalculateStructure_();
  }
  if (!beadstructure.structureIdUpToDate) {
    beadstructure.CalculateStructure_();
  }
  return structure_id_.compare(beadstructure.structure_id_) == 0;
}

std::vector<Index> BeadStructure::getNeighBeadIds(const Index &index) {
  if (!graphUpToDate) {
    InitializeGraph_();
  }
  std::vector<Index> neighbor_ids = graph_.getNeighVertices(index);
  return neighbor_ids;
}

std::vector<Index> BeadStructure::getBeadIds() const {
  /// Do not use graph_.getVertices() because this would require that the graph
  /// is updated
  vector<Index> bead_ids;
  for (auto &id_and_bead_info : beads_) {
    bead_ids.push_back(id_and_bead_info.first);
  }
  return bead_ids;
}
<|endoftext|>


<commit_before>#include "game_window.h"
#include <sstream>
#include <algorithm>

bool GameWindow::sdlInitialized = false;

bool GameWindow::initialize() {
	Logger::getInstance()->writeInformation("Initializing graphics");
	if (GameWindow::sdlInitialized) {
		Logger::getInstance()->writeWarning("SDL already initialized");
	} else {
		atexit(SDL_Quit);
		if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) {
			Logger::getInstance()->writeError("SDL could not initialize!");
			Logger::getInstance()->writeError(SDL_GetError());
			GameWindow::sdlInitialized = false;
		} else {
			GameWindow::sdlInitialized = true;
		}
	}
	return GameWindow::sdlInitialized;
}

GameWindow::GameWindow() {
	this->parser = new ParserYAML(CONFIG_FILE_PATH);
	this->parser->parse();
	TagPantalla tp = this->parser->getPantalla();
	this->model = nullptr;
	this->exit = false;
	this->focus_x = 0;
	this->focus_y = 0;
	this->alto_pantalla = tp.alto;
	this->ancho_pantalla = tp.ancho;

	Logger::getInstance()->writeInformation("Creating window");

	GameWindow::initialize();
	window = SDL_CreateWindow("Trabajo Práctico 7542",
		SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
		tp.ancho, tp.alto,
		SDL_WINDOW_SHOWN);

	Logger::getInstance()->writeInformation("Creating renderer");
	renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED );

	SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); // Color: negro opaco
	SDL_RenderClear(renderer); // Limpio pantalla inicialmente
	SDL_RenderPresent( renderer );
}

GameWindow::~GameWindow() {
	map<std::string, SpriteSheet*>::const_iterator itr;
	for(itr = spritesSheets.begin(); itr != spritesSheets.end(); ++itr){
		delete itr->second;
	}

	delete parser;
	delete model;

	Logger::getInstance()->writeInformation("Destroying renderer");
	if (renderer) {
		SDL_DestroyRenderer(renderer);
		renderer = nullptr;
	}

	Logger::getInstance()->writeInformation("Destroying window");
	if (window) {
		SDL_DestroyWindow(window);
	} else {
		Logger::getInstance()->writeWarning("Window never initialized");
	}
}

bool GameWindow::endOfGame(){
	return this->exit;
}

void GameWindow::render(){
	//	Dibujar
	SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
	SDL_RenderClear(renderer);
	Board & board = *this->model->getBoard();
	// Dibujamos el terreno
	for (size_t x = 0; x < board.sizeX; x++) {
		for (size_t y = 0; y < board.sizeY; y++) {
			Entity & tile = board.getTerrain(x, y);
			spritesSheets[tile.name]->render(tile, 0, renderer, this->alto_pantalla, this->ancho_pantalla);
		}
	}
	std::vector<std::shared_ptr<Entity>> entities = board.getEntities();
	std::map<std::string,SpriteSheet*>::iterator it;
	SpriteSheet* ss;
	// Ordenamos las entidades por oclusión
	std::sort(entities.begin(), entities.end(), [](std::shared_ptr<Entity> a, std::shared_ptr<Entity> b) {
		return ((a->getX() + a->sizeX < b->getX()) || (a->getY() + a->sizeY < b->getY())) &&
			!((b->getX() + b->sizeX < a->getX()) || (b->getY() + b->sizeY < a->getY()));
	});
	for (std::size_t i =0; i < entities.size(); ++i){
		it = this->spritesSheets.find(entities[i]->name);
		if(it != this->spritesSheets.end()){
			ss = it->second;
			ss->render(*entities[i], 0, renderer, this->alto_pantalla, this->ancho_pantalla);
		}
		else
			Logger::getInstance()->writeWarning("No existe SpriteSheet para este tipo de entidad" + entities[i]->name);
	}

	SDL_RenderPresent( renderer );
	return;
}

void GameWindow::restart(){
	delete model;

	map<std::string, SpriteSheet*>::const_iterator itr;
	for(itr = spritesSheets.begin(); itr != spritesSheets.end(); ++itr){
		delete itr->second;
	}
	spritesSheets.clear();

	this->parser->parse();

	init();
	{
		auto protagonist = model->getBoard()->getProtagonist();
		focus_x = protagonist.getX();
		focus_y = protagonist.getY();
	}
}

void GameWindow::init(){ //NO DEBERIA INICIALIZARSE TODO ACA, ME DIO PROBLEMA DE REFERENCIAS LLEVARLO AL PARSER
	std::vector<TagTipoEntidad> tte = this->parser->getTiposEntidades();
	TagConfiguracion tc = this->parser->getConfiguracion();
	TagEscenario te = this->parser->getEscenario();
	this->model = new Game(te.size_x, te.size_y);
	Board* board = this->model->getBoard();

	addSpriteSheet(ENTIDAD_DEFAULT_NOMBRE, ENTIDAD_DEFAULT_IMAGEN, ENTIDAD_DEFAULT_PIXEL_REF_X, ENTIDAD_DEFAULT_PIXEL_REF_Y, ENTIDAD_DEFAULT_ALTO_SPRITE, ENTIDAD_DEFAULT_ANCHO_SPRITE, ENTIDAD_DEFAULT_CANTIDAD_SPRITES, ENTIDAD_DEFAULT_FPS, ENTIDAD_DEFAULT_DELAY);
	board->createEntityFactory(ENTIDAD_DEFAULT_NOMBRE, ENTIDAD_DEFAULT_ANCHO_BASE, ENTIDAD_DEFAULT_ALTO_BASE, 0);

	addSpriteSheet(TERRENO_DEFAULT_NOMBRE, TERRENO_DEFAULT_IMAGEN, TERRENO_DEFAULT_PIXEL_REF_X, TERRENO_DEFAULT_PIXEL_REF_Y, TERRENO_DEFAULT_ALTO_SPRITE, TERRENO_DEFAULT_ANCHO_SPRITE, TERRENO_DEFAULT_CANTIDAD_SPRITES, TERRENO_DEFAULT_FPS, TERRENO_DEFAULT_DELAY);
	board->createEntityFactory(TERRENO_DEFAULT_NOMBRE, TERRENO_DEFAULT_ANCHO_BASE, TERRENO_DEFAULT_ALTO_BASE, 0);

	addSpriteSheet(PROTAGONISTA_DEFAULT_NOMBRE, PROTAGONISTA_DEFAULT_IMAGEN, PROTAGONISTA_DEFAULT_PIXEL_REF_X, PROTAGONISTA_DEFAULT_PIXEL_REF_Y, PROTAGONISTA_DEFAULT_ALTO_SPRITE, PROTAGONISTA_DEFAULT_ANCHO_SPRITE, PROTAGONISTA_DEFAULT_CANTIDAD_SPRITES, PROTAGONISTA_DEFAULT_FPS, PROTAGONISTA_DEFAULT_DELAY);
	board->createEntityFactory(PROTAGONISTA_DEFAULT_NOMBRE, PROTAGONISTA_DEFAULT_ANCHO_BASE, PROTAGONISTA_DEFAULT_ALTO_BASE, VELOCIDAD_PERSONAJE_DEFAULT);

	for (std::size_t i =0; i < tte.size(); ++i){
		addSpriteSheet(tte[i].nombre, tte[i].imagen, tte[i].pixel_ref_x, tte[i].pixel_ref_y, tte[i].alto_sprite, tte[i].ancho_sprite,  tte[i].cantidad_sprites, tte[i].fps, tte[i].delay);
		board->createEntityFactory(tte[i].nombre, tte[i].ancho_base, tte[i].alto_base,tc.vel_personaje); // LA VELOCIDAD DEBERIA IR SOLO AL PROTAGONISTA
	}

	for(std::size_t i =0; i < te.terrenos.size(); ++i){
		board->setTerrain(te.terrenos[i].tipoEntidad,te.terrenos[i].pos_x,te.terrenos[i].pos_y); // ACA TENDRIA QE VALIDARSE SUPERPOSICION
	}
	board->createProtagonist(te.protagonista.tipoEntidad,te.protagonista.pos_x, te.protagonista.pos_y);

	for(std::size_t i =0; i < te.entidades.size(); ++i){
		board->createEntity(te.entidades[i].tipoEntidad,te.entidades[i].pos_x,te.entidades[i].pos_y); // ACA TENDRIA QE VALIDARSE SUPERPOSICION
	}

	for(size_t x = 0; x < board->sizeX; x++) {
		for(size_t y = 0; y < board->sizeY; y++) {
			if (!&board->getTerrain(x, y)) {
				board->setTerrain(TERRENO_DEFAULT_NOMBRE, x, y); // VER QUE EL PASTO NO DEBERIA VENIR EN EL ARCHIVO
			}
		}
	}
}

void GameWindow::update(){
	GameTimer::update();
	map<std::string, SpriteSheet*>::const_iterator itr;
	for(itr = spritesSheets.begin(); itr != spritesSheets.end(); ++itr){
		itr->second->update();
	}
	model->update();
	return;
}

void GameWindow::addSpriteSheet(std::string name, std::string pPath, int pixelRefX, int pixelRefY, int altoSprite, int anchoSprite, int cantSprites, double fps, double delay) {
	std::map<std::string,SpriteSheet*>::iterator it;
	it = this->spritesSheets.find(name);
	if(it != this->spritesSheets.end())
		Logger::getInstance()->writeError("Ya existe un spriteSheet para el tipo de entidad con nombre " + name);
	else{
		spritesSheets[name] = new SpriteSheet(pPath, pixelRefX, pixelRefY, altoSprite, anchoSprite, cantSprites, fps, delay, *this);
		Logger::getInstance()->writeInformation("Se agrega spriteSheet para el tipo de entidad con nombre " + name);
	}
}

void GameWindow::processInput(){
	int mouse_x_screen, mouse_y_screen;

	//	Procesar input del usuario
	while(SDL_PollEvent(EventHandler::getInstance()->getEvent())) {
		if(EventHandler::getInstance()->getEvent()->type == SDL_QUIT )
			this->exit = true;
		if(EventHandler::getInstance()->getEvent()->type == SDL_KEYDOWN ){
			Logger::getInstance()->writeInformation("Teclado");
			if(EventHandler::getInstance()->getEvent()->key.keysym.sym == SDLK_r){
				restart();
			}
		}
		if( EventHandler::getInstance()->getEvent()->type == SDL_MOUSEBUTTONUP ){
			SDL_GetMouseState(&mouse_x_screen, &mouse_y_screen);
			std::ostringstream oss;
			oss << "Mouse en " << mouse_x_screen << "," << mouse_y_screen;

			// Conversion de coordenadas en pantalla a coordenadas mapa

			double XsTerm = (double)((double)mouse_x_screen - ancho_pantalla/2)/(double)TILE_WIDTH_DEFAULT;
			double YsTerm = (double)((double)mouse_y_screen - alto_pantalla/2)/(double)TILE_HEIGHT_DEFAULT;

			double x_mapa = focus_x + XsTerm + YsTerm + .5;
			double y_mapa = focus_y - XsTerm + YsTerm + .5;

			oss << "; mapa: " << x_mapa << "," << y_mapa;

			Logger::getInstance()->writeInformation(oss.str().c_str());
			if( EventHandler::getInstance()->getEvent()->button.button == SDL_BUTTON_LEFT ) {
				Logger::getInstance()->writeInformation("Boton Izquierdo");
				model->getBoard()->getProtagonist().setTarget(x_mapa, y_mapa);
			}
			if( EventHandler::getInstance()->getEvent()->button.button == SDL_BUTTON_RIGHT) {
				Logger::getInstance()->writeInformation("Boton derecho");
			}
		}
	}
}

void GameWindow::scroll(){
	Uint8 mouse_b;
	int mouse_x, mouse_y;
	const double SCROLL_SPEED = 40;

	double ds = SCROLL_SPEED * model->getBoard()->dt / 1000; //deltascroll
	SDL_GetMouseState(&mouse_x, &mouse_y);

	if(mouse_x <= MARGEN_PANTALLA_DEFAULT)
	{
		double dsi = (1.0 - ((double)mouse_x / (double)MARGEN_PANTALLA_DEFAULT)) * ds;

		focus_x -= dsi;
		focus_y += dsi;
		Logger::getInstance()->writeInformation("Scrolleando hacia la izquierda");
	}
	else if(mouse_x >= ancho_pantalla - MARGEN_PANTALLA_DEFAULT){

		double dsi = ((double)(mouse_x + MARGEN_PANTALLA_DEFAULT - ancho_pantalla)/(double)MARGEN_PANTALLA_DEFAULT) * ds;

		focus_x += dsi;
		focus_y -= dsi;
		Logger::getInstance()->writeInformation("Scrolleando hacia la derecha");
	}
	if(mouse_y <= MARGEN_PANTALLA_DEFAULT)
	{
		double dsi = (1.0 - ((double)mouse_y / (double)MARGEN_PANTALLA_DEFAULT)) * ds;
		focus_x -= dsi;
		focus_y -= dsi;
		Logger::getInstance()->writeInformation("Scrolleando hacia arriba");
	}
	if(mouse_y >= alto_pantalla - MARGEN_PANTALLA_DEFAULT)
	{
		double dsi = ((double)(mouse_y + MARGEN_PANTALLA_DEFAULT - alto_pantalla)/(double)MARGEN_PANTALLA_DEFAULT) * ds;

		focus_x += dsi;
		focus_y += dsi;
		Logger::getInstance()->writeInformation("Scrolleando hacia abajo");
	}

	auto & board = *(model->getBoard());

	if(focus_x >= board.sizeX - 1){
		focus_x = board.sizeX - 1;
	}
	else if(focus_x < 0){
		focus_x = 0;
	}

	if(focus_y >= board.sizeY - 1){
		focus_y = board.sizeY - 1;
	}else if(focus_y < 0){
		focus_y = 0;
	}
}

int GameWindow::start(){
	init();
	{
		auto protagonist = model->getBoard()->getProtagonist();
		focus_x = protagonist.getX();
		focus_y = protagonist.getY();
	}

	while (!endOfGame())
	{
		scroll();
		processInput();
		update();
		render();

		SDL_Delay(model->getBoard()->dt); // TODO: Optimizar, sacar hardcodeo
	}
	return 0;
}<commit_msg>Afino un poco criterio de oclusión<commit_after>#include "game_window.h"
#include <sstream>
#include <algorithm>

bool GameWindow::sdlInitialized = false;

bool GameWindow::initialize() {
	Logger::getInstance()->writeInformation("Initializing graphics");
	if (GameWindow::sdlInitialized) {
		Logger::getInstance()->writeWarning("SDL already initialized");
	} else {
		atexit(SDL_Quit);
		if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) {
			Logger::getInstance()->writeError("SDL could not initialize!");
			Logger::getInstance()->writeError(SDL_GetError());
			GameWindow::sdlInitialized = false;
		} else {
			GameWindow::sdlInitialized = true;
		}
	}
	return GameWindow::sdlInitialized;
}

GameWindow::GameWindow() {
	this->parser = new ParserYAML(CONFIG_FILE_PATH);
	this->parser->parse();
	TagPantalla tp = this->parser->getPantalla();
	this->model = nullptr;
	this->exit = false;
	this->focus_x = 0;
	this->focus_y = 0;
	this->alto_pantalla = tp.alto;
	this->ancho_pantalla = tp.ancho;

	Logger::getInstance()->writeInformation("Creating window");

	GameWindow::initialize();
	window = SDL_CreateWindow("Trabajo Práctico 7542",
		SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
		tp.ancho, tp.alto,
		SDL_WINDOW_SHOWN);

	Logger::getInstance()->writeInformation("Creating renderer");
	renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED );

	SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); // Color: negro opaco
	SDL_RenderClear(renderer); // Limpio pantalla inicialmente
	SDL_RenderPresent( renderer );
}

GameWindow::~GameWindow() {
	map<std::string, SpriteSheet*>::const_iterator itr;
	for(itr = spritesSheets.begin(); itr != spritesSheets.end(); ++itr){
		delete itr->second;
	}

	delete parser;
	delete model;

	Logger::getInstance()->writeInformation("Destroying renderer");
	if (renderer) {
		SDL_DestroyRenderer(renderer);
		renderer = nullptr;
	}

	Logger::getInstance()->writeInformation("Destroying window");
	if (window) {
		SDL_DestroyWindow(window);
	} else {
		Logger::getInstance()->writeWarning("Window never initialized");
	}
}

bool GameWindow::endOfGame(){
	return this->exit;
}

void GameWindow::render(){
	//	Dibujar
	SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
	SDL_RenderClear(renderer);
	Board & board = *this->model->getBoard();
	// Dibujamos el terreno
	for (size_t x = 0; x < board.sizeX; x++) {
		for (size_t y = 0; y < board.sizeY; y++) {
			Entity & tile = board.getTerrain(x, y);
			spritesSheets[tile.name]->render(tile, 0, renderer, this->alto_pantalla, this->ancho_pantalla);
		}
	}
	std::vector<std::shared_ptr<Entity>> entities = board.getEntities();
	std::map<std::string,SpriteSheet*>::iterator it;
	SpriteSheet* ss;
	// Ordenamos las entidades por oclusión
	std::sort(entities.begin(), entities.end(), [](std::shared_ptr<Entity> a, std::shared_ptr<Entity> b) {
		return ((a->getX() + a->sizeX <= b->getX()) || (a->getY() + a->sizeY <= b->getY())) &&
			!((b->getX() + b->sizeX <= a->getX()) || (b->getY() + b->sizeY <= a->getY()));
	});
	for (std::size_t i =0; i < entities.size(); ++i){
		it = this->spritesSheets.find(entities[i]->name);
		if(it != this->spritesSheets.end()){
			ss = it->second;
			ss->render(*entities[i], 0, renderer, this->alto_pantalla, this->ancho_pantalla);
		}
		else
			Logger::getInstance()->writeWarning("No existe SpriteSheet para este tipo de entidad" + entities[i]->name);
	}

	SDL_RenderPresent( renderer );
	return;
}

void GameWindow::restart(){
	delete model;

	map<std::string, SpriteSheet*>::const_iterator itr;
	for(itr = spritesSheets.begin(); itr != spritesSheets.end(); ++itr){
		delete itr->second;
	}
	spritesSheets.clear();

	this->parser->parse();

	init();
	{
		auto protagonist = model->getBoard()->getProtagonist();
		focus_x = protagonist.getX();
		focus_y = protagonist.getY();
	}
}

void GameWindow::init(){ //NO DEBERIA INICIALIZARSE TODO ACA, ME DIO PROBLEMA DE REFERENCIAS LLEVARLO AL PARSER
	std::vector<TagTipoEntidad> tte = this->parser->getTiposEntidades();
	TagConfiguracion tc = this->parser->getConfiguracion();
	TagEscenario te = this->parser->getEscenario();
	this->model = new Game(te.size_x, te.size_y);
	Board* board = this->model->getBoard();

	addSpriteSheet(ENTIDAD_DEFAULT_NOMBRE, ENTIDAD_DEFAULT_IMAGEN, ENTIDAD_DEFAULT_PIXEL_REF_X, ENTIDAD_DEFAULT_PIXEL_REF_Y, ENTIDAD_DEFAULT_ALTO_SPRITE, ENTIDAD_DEFAULT_ANCHO_SPRITE, ENTIDAD_DEFAULT_CANTIDAD_SPRITES, ENTIDAD_DEFAULT_FPS, ENTIDAD_DEFAULT_DELAY);
	board->createEntityFactory(ENTIDAD_DEFAULT_NOMBRE, ENTIDAD_DEFAULT_ANCHO_BASE, ENTIDAD_DEFAULT_ALTO_BASE, 0);

	addSpriteSheet(TERRENO_DEFAULT_NOMBRE, TERRENO_DEFAULT_IMAGEN, TERRENO_DEFAULT_PIXEL_REF_X, TERRENO_DEFAULT_PIXEL_REF_Y, TERRENO_DEFAULT_ALTO_SPRITE, TERRENO_DEFAULT_ANCHO_SPRITE, TERRENO_DEFAULT_CANTIDAD_SPRITES, TERRENO_DEFAULT_FPS, TERRENO_DEFAULT_DELAY);
	board->createEntityFactory(TERRENO_DEFAULT_NOMBRE, TERRENO_DEFAULT_ANCHO_BASE, TERRENO_DEFAULT_ALTO_BASE, 0);

	addSpriteSheet(PROTAGONISTA_DEFAULT_NOMBRE, PROTAGONISTA_DEFAULT_IMAGEN, PROTAGONISTA_DEFAULT_PIXEL_REF_X, PROTAGONISTA_DEFAULT_PIXEL_REF_Y, PROTAGONISTA_DEFAULT_ALTO_SPRITE, PROTAGONISTA_DEFAULT_ANCHO_SPRITE, PROTAGONISTA_DEFAULT_CANTIDAD_SPRITES, PROTAGONISTA_DEFAULT_FPS, PROTAGONISTA_DEFAULT_DELAY);
	board->createEntityFactory(PROTAGONISTA_DEFAULT_NOMBRE, PROTAGONISTA_DEFAULT_ANCHO_BASE, PROTAGONISTA_DEFAULT_ALTO_BASE, VELOCIDAD_PERSONAJE_DEFAULT);

	for (std::size_t i =0; i < tte.size(); ++i){
		addSpriteSheet(tte[i].nombre, tte[i].imagen, tte[i].pixel_ref_x, tte[i].pixel_ref_y, tte[i].alto_sprite, tte[i].ancho_sprite,  tte[i].cantidad_sprites, tte[i].fps, tte[i].delay);
		board->createEntityFactory(tte[i].nombre, tte[i].ancho_base, tte[i].alto_base,tc.vel_personaje); // LA VELOCIDAD DEBERIA IR SOLO AL PROTAGONISTA
	}

	for(std::size_t i =0; i < te.terrenos.size(); ++i){
		board->setTerrain(te.terrenos[i].tipoEntidad,te.terrenos[i].pos_x,te.terrenos[i].pos_y); // ACA TENDRIA QE VALIDARSE SUPERPOSICION
	}
	board->createProtagonist(te.protagonista.tipoEntidad,te.protagonista.pos_x, te.protagonista.pos_y);

	for(std::size_t i =0; i < te.entidades.size(); ++i){
		board->createEntity(te.entidades[i].tipoEntidad,te.entidades[i].pos_x,te.entidades[i].pos_y); // ACA TENDRIA QE VALIDARSE SUPERPOSICION
	}

	for(size_t x = 0; x < board->sizeX; x++) {
		for(size_t y = 0; y < board->sizeY; y++) {
			if (!&board->getTerrain(x, y)) {
				board->setTerrain(TERRENO_DEFAULT_NOMBRE, x, y); // VER QUE EL PASTO NO DEBERIA VENIR EN EL ARCHIVO
			}
		}
	}
}

void GameWindow::update(){
	GameTimer::update();
	map<std::string, SpriteSheet*>::const_iterator itr;
	for(itr = spritesSheets.begin(); itr != spritesSheets.end(); ++itr){
		itr->second->update();
	}
	model->update();
	return;
}

void GameWindow::addSpriteSheet(std::string name, std::string pPath, int pixelRefX, int pixelRefY, int altoSprite, int anchoSprite, int cantSprites, double fps, double delay) {
	std::map<std::string,SpriteSheet*>::iterator it;
	it = this->spritesSheets.find(name);
	if(it != this->spritesSheets.end())
		Logger::getInstance()->writeError("Ya existe un spriteSheet para el tipo de entidad con nombre " + name);
	else{
		spritesSheets[name] = new SpriteSheet(pPath, pixelRefX, pixelRefY, altoSprite, anchoSprite, cantSprites, fps, delay, *this);
		Logger::getInstance()->writeInformation("Se agrega spriteSheet para el tipo de entidad con nombre " + name);
	}
}

void GameWindow::processInput(){
	int mouse_x_screen, mouse_y_screen;

	//	Procesar input del usuario
	while(SDL_PollEvent(EventHandler::getInstance()->getEvent())) {
		if(EventHandler::getInstance()->getEvent()->type == SDL_QUIT )
			this->exit = true;
		if(EventHandler::getInstance()->getEvent()->type == SDL_KEYDOWN ){
			Logger::getInstance()->writeInformation("Teclado");
			if(EventHandler::getInstance()->getEvent()->key.keysym.sym == SDLK_r){
				restart();
			}
		}
		if( EventHandler::getInstance()->getEvent()->type == SDL_MOUSEBUTTONUP ){
			SDL_GetMouseState(&mouse_x_screen, &mouse_y_screen);
			std::ostringstream oss;
			oss << "Mouse en " << mouse_x_screen << "," << mouse_y_screen;

			// Conversion de coordenadas en pantalla a coordenadas mapa

			double XsTerm = (double)((double)mouse_x_screen - ancho_pantalla/2)/(double)TILE_WIDTH_DEFAULT;
			double YsTerm = (double)((double)mouse_y_screen - alto_pantalla/2)/(double)TILE_HEIGHT_DEFAULT;

			double x_mapa = focus_x + XsTerm + YsTerm + .5;
			double y_mapa = focus_y - XsTerm + YsTerm + .5;

			oss << "; mapa: " << x_mapa << "," << y_mapa;

			Logger::getInstance()->writeInformation(oss.str().c_str());
			if( EventHandler::getInstance()->getEvent()->button.button == SDL_BUTTON_LEFT ) {
				Logger::getInstance()->writeInformation("Boton Izquierdo");
				model->getBoard()->getProtagonist().setTarget(x_mapa, y_mapa);
			}
			if( EventHandler::getInstance()->getEvent()->button.button == SDL_BUTTON_RIGHT) {
				Logger::getInstance()->writeInformation("Boton derecho");
			}
		}
	}
}

void GameWindow::scroll(){
	Uint8 mouse_b;
	int mouse_x, mouse_y;
	const double SCROLL_SPEED = 40;

	double ds = SCROLL_SPEED * model->getBoard()->dt / 1000; //deltascroll
	SDL_GetMouseState(&mouse_x, &mouse_y);

	if(mouse_x <= MARGEN_PANTALLA_DEFAULT)
	{
		double dsi = (1.0 - ((double)mouse_x / (double)MARGEN_PANTALLA_DEFAULT)) * ds;

		focus_x -= dsi;
		focus_y += dsi;
		Logger::getInstance()->writeInformation("Scrolleando hacia la izquierda");
	}
	else if(mouse_x >= ancho_pantalla - MARGEN_PANTALLA_DEFAULT){

		double dsi = ((double)(mouse_x + MARGEN_PANTALLA_DEFAULT - ancho_pantalla)/(double)MARGEN_PANTALLA_DEFAULT) * ds;

		focus_x += dsi;
		focus_y -= dsi;
		Logger::getInstance()->writeInformation("Scrolleando hacia la derecha");
	}
	if(mouse_y <= MARGEN_PANTALLA_DEFAULT)
	{
		double dsi = (1.0 - ((double)mouse_y / (double)MARGEN_PANTALLA_DEFAULT)) * ds;
		focus_x -= dsi;
		focus_y -= dsi;
		Logger::getInstance()->writeInformation("Scrolleando hacia arriba");
	}
	if(mouse_y >= alto_pantalla - MARGEN_PANTALLA_DEFAULT)
	{
		double dsi = ((double)(mouse_y + MARGEN_PANTALLA_DEFAULT - alto_pantalla)/(double)MARGEN_PANTALLA_DEFAULT) * ds;

		focus_x += dsi;
		focus_y += dsi;
		Logger::getInstance()->writeInformation("Scrolleando hacia abajo");
	}

	auto & board = *(model->getBoard());

	if(focus_x >= board.sizeX - 1){
		focus_x = board.sizeX - 1;
	}
	else if(focus_x < 0){
		focus_x = 0;
	}

	if(focus_y >= board.sizeY - 1){
		focus_y = board.sizeY - 1;
	}else if(focus_y < 0){
		focus_y = 0;
	}
}

int GameWindow::start(){
	init();
	{
		auto protagonist = model->getBoard()->getProtagonist();
		focus_x = protagonist.getX();
		focus_y = protagonist.getY();
	}

	while (!endOfGame())
	{
		scroll();
		processInput();
		update();
		render();

		SDL_Delay(model->getBoard()->dt); // TODO: Optimizar, sacar hardcodeo
	}
	return 0;
}
<|endoftext|>


<commit_before><commit_msg>External: ""glm::decompose()" is using float-type instead of templated-type #869" (https://github.com/g-truc/glm/issues/869) related commit<commit_after><|endoftext|>


<commit_before>#ifndef OPENFLOW_INSTRUCTION_H
#define OPENFLOW_INSTRUCTION_H

#include "of13action.hh"
#include "openflow-13.h"
#include <list>
#include <set>

namespace fluid_msg {

namespace of13 {

class Instruction {
protected:
    uint16_t type_;
    uint16_t length_;
public:
    Instruction();
    Instruction(uint16_t type, uint16_t length);
    virtual ~Instruction() {
    }
    virtual bool equals(const Instruction & other);
    virtual bool operator==(const Instruction &other) const;
    virtual bool operator!=(const Instruction &other) const;
    virtual uint16_t set_order() const {
        return 0;
    }
    virtual Instruction* clone() {
        return new Instruction(*this);
    }
    virtual size_t pack(uint8_t* buffer);
    virtual of_error unpack(uint8_t* buffer);
    uint16_t type() {
        return this->type_;
    }
    uint16_t length() {
        return this->length_;
    }
    void type(uint16_t type) {
        this->type_ = type;
    }
    void length(uint16_t length) {
        this->length_ = length;
    }
    static Instruction* make_instruction(uint16_t type);
};

struct comp_inst_set_order {
    bool operator()(Instruction* lhs, Instruction* rhs) const {
        return lhs->set_order() < rhs->set_order();
    }
};

class InstructionSet {
private:
    uint16_t length_;
    std::set<Instruction*, comp_inst_set_order> instruction_set_;
public:
    InstructionSet()
        : length_(0) {
    }
    InstructionSet(std::set<Instruction*> instruction_set);
    InstructionSet(const InstructionSet &other);
    InstructionSet& operator=(InstructionSet other);
    ~InstructionSet();
    bool operator==(const InstructionSet &other) const;
    bool operator!=(const InstructionSet &other) const;
    size_t pack(uint8_t* buffer);
    of_error unpack(uint8_t* buffer);
    friend void swap(InstructionSet& first, InstructionSet& second);
    uint16_t length() {
        return this->length_;
    }
    std::set<Instruction*, comp_inst_set_order> instruction_set(){
        return this->instruction_set_;
    }
    void add_instruction(Instruction &inst);
    void add_instruction(Instruction *inst);
    void length(uint16_t length) {
        this->length_ = length;
    }
};

class GoToTable: public Instruction {
private:
    uint8_t table_id_;
    const uint16_t set_order_;
public:
    GoToTable()
        : Instruction(of13::OFPIT_GOTO_TABLE,
              sizeof(struct of13::ofp_instruction_goto_table)),
          set_order_(60) {
    }
    GoToTable(uint8_t table_id);
    ~GoToTable() {
    }
    uint16_t set_order() const {
        return this->set_order_;
    }
    virtual bool equals(const Instruction & other);
    virtual GoToTable* clone() {
        return new GoToTable(*this);
    }
    size_t pack(uint8_t* buffer);
    of_error unpack(uint8_t* buffer);
    uint8_t table_id() {
        return this->table_id_;
    }
    void table_id(uint8_t table_id) {
        this->table_id_ = table_id;
    }
};

class WriteMetadata: public Instruction {
private:
    uint64_t metadata_;
    uint64_t metadata_mask_;
    const uint16_t set_order_;
public:
    WriteMetadata()
        : Instruction(of13::OFPIT_WRITE_METADATA,
              sizeof(struct of13::ofp_instruction_write_metadata)),
          set_order_(50) {
    }
    WriteMetadata(uint64_t metadata, uint64_t metadata_mask);
    ~WriteMetadata() {
    }
    uint16_t set_order() const {
        return this->set_order_;
    }
    virtual bool equals(const Instruction & other);
    virtual WriteMetadata* clone() {
        return new WriteMetadata(*this);
    }
    size_t pack(uint8_t* buffer);
    of_error unpack(uint8_t* buffer);
    uint64_t metadata() {
        return this->metadata_;
    }
    uint64_t metadata_mask() {
        return this->metadata_mask_;
    }
    void metadata(uint64_t metadata) {
        this->metadata_ = metadata;
    }
    void metadata_mask(uint64_t metadata_mask) {
        this->metadata_mask_ = metadata_mask;
    }
};

class WriteActions: public Instruction {
private:
    ActionSet actions_;
    const uint16_t set_order_;
public:
    WriteActions()
        : Instruction(of13::OFPIT_WRITE_ACTIONS,
              sizeof(struct of13::ofp_instruction_actions)),
          set_order_(40) {
    }
    WriteActions(ActionSet actions);
    ~WriteActions() {
    }
    uint16_t set_order() const {
        return this->set_order_;
    }
    virtual bool equals(const Instruction & other);
    size_t pack(uint8_t* buffer);
    virtual WriteActions* clone() {
        return new WriteActions(*this);
    }
    of_error unpack(uint8_t* buffer);
    ActionSet actions() {
        return this->actions_;
    }
    void actions(ActionSet actions);
    void add_action(Action &action);
    void add_action(Action* action);
};

class ApplyActions: public Instruction {
private:
    ActionList actions_;
    const uint16_t set_order_;
public:
    ApplyActions()
        : Instruction(of13::OFPIT_APPLY_ACTIONS,
              sizeof(struct of13::ofp_instruction_actions)),
          set_order_(20) {
    }
    ApplyActions(ActionList actions);
    ~ApplyActions() {
    }
    uint16_t set_order() const {
        return this->set_order_;
    }
    virtual bool equals(const Instruction & other);
    virtual ApplyActions* clone() {
        return new ApplyActions(*this);
    }
    size_t pack(uint8_t* buffer);
    of_error unpack(uint8_t* buffer);
    ActionList actions() {
        return this->actions_;
    }
    void actions(ActionList actions);
    void add_action(Action &action);
    void add_action(Action* action);
};

class ClearActions: public Instruction {
private:
    const uint16_t set_order_;
public:
    ClearActions()
        : Instruction(of13::OFPIT_CLEAR_ACTIONS,
              sizeof(struct of13::ofp_instruction) + 4),
          set_order_(30) {
    }
    ~ClearActions() {
    }
    uint16_t set_order() const {
        return this->set_order_;
    }
    virtual ClearActions* clone() {
        return new ClearActions(*this);
    }
    size_t pack(uint8_t* buffer);
    of_error unpack(uint8_t* buffer);
};

class Meter: public Instruction {
private:
    uint32_t meter_id_;
    const uint16_t set_order_;
public:
    Meter()
        : Instruction(of13::OFPIT_METER,
              sizeof(struct of13::ofp_instruction_meter)),
          set_order_(10) {
    }
    Meter(uint32_t meter_id);
    ~Meter() {
    }
    uint16_t set_order() const {
        return this->set_order_;
    }
    virtual bool equals(const Instruction & other);
    virtual Meter* clone() {
        return new Meter(*this);
    }
    size_t pack(uint8_t* buffer);
    of_error unpack(uint8_t* buffer);
    uint32_t meter_id() {
        return this->meter_id_;
    }
    void meter_id(uint32_t meter_id) {
        this->meter_id_ = meter_id;
    }
};

class InstructionExperimenter: public Instruction {
protected:
    uint32_t experimenter_;
public:
    InstructionExperimenter() {
    }
    InstructionExperimenter(uint32_t experimenter);
    ~InstructionExperimenter() {
    }
    virtual bool equals(const Instruction & other);
    virtual InstructionExperimenter* clone() {
        return new InstructionExperimenter(*this);
    }
    size_t pack(uint8_t* buffer);
    of_error unpack(uint8_t* buffer);
    uint32_t experimenter() {
        return this->experimenter_;
    }
    void experimenter(uint32_t experimenter) {
        this->experimenter_ = experimenter;
    }
};

}

} //End of namespace fluid_msg
#endif
<commit_msg>Bugfix: Clear-Actions instruction too long.<commit_after>#ifndef OPENFLOW_INSTRUCTION_H
#define OPENFLOW_INSTRUCTION_H

#include "of13action.hh"
#include "openflow-13.h"
#include <list>
#include <set>

namespace fluid_msg {

namespace of13 {

class Instruction {
protected:
    uint16_t type_;
    uint16_t length_;
public:
    Instruction();
    Instruction(uint16_t type, uint16_t length);
    virtual ~Instruction() {
    }
    virtual bool equals(const Instruction & other);
    virtual bool operator==(const Instruction &other) const;
    virtual bool operator!=(const Instruction &other) const;
    virtual uint16_t set_order() const {
        return 0;
    }
    virtual Instruction* clone() {
        return new Instruction(*this);
    }
    virtual size_t pack(uint8_t* buffer);
    virtual of_error unpack(uint8_t* buffer);
    uint16_t type() {
        return this->type_;
    }
    uint16_t length() {
        return this->length_;
    }
    void type(uint16_t type) {
        this->type_ = type;
    }
    void length(uint16_t length) {
        this->length_ = length;
    }
    static Instruction* make_instruction(uint16_t type);
};

struct comp_inst_set_order {
    bool operator()(Instruction* lhs, Instruction* rhs) const {
        return lhs->set_order() < rhs->set_order();
    }
};

class InstructionSet {
private:
    uint16_t length_;
    std::set<Instruction*, comp_inst_set_order> instruction_set_;
public:
    InstructionSet()
        : length_(0) {
    }
    InstructionSet(std::set<Instruction*> instruction_set);
    InstructionSet(const InstructionSet &other);
    InstructionSet& operator=(InstructionSet other);
    ~InstructionSet();
    bool operator==(const InstructionSet &other) const;
    bool operator!=(const InstructionSet &other) const;
    size_t pack(uint8_t* buffer);
    of_error unpack(uint8_t* buffer);
    friend void swap(InstructionSet& first, InstructionSet& second);
    uint16_t length() {
        return this->length_;
    }
    std::set<Instruction*, comp_inst_set_order> instruction_set(){
        return this->instruction_set_;
    }
    void add_instruction(Instruction &inst);
    void add_instruction(Instruction *inst);
    void length(uint16_t length) {
        this->length_ = length;
    }
};

class GoToTable: public Instruction {
private:
    uint8_t table_id_;
    const uint16_t set_order_;
public:
    GoToTable()
        : Instruction(of13::OFPIT_GOTO_TABLE,
              sizeof(struct of13::ofp_instruction_goto_table)),
          set_order_(60) {
    }
    GoToTable(uint8_t table_id);
    ~GoToTable() {
    }
    uint16_t set_order() const {
        return this->set_order_;
    }
    virtual bool equals(const Instruction & other);
    virtual GoToTable* clone() {
        return new GoToTable(*this);
    }
    size_t pack(uint8_t* buffer);
    of_error unpack(uint8_t* buffer);
    uint8_t table_id() {
        return this->table_id_;
    }
    void table_id(uint8_t table_id) {
        this->table_id_ = table_id;
    }
};

class WriteMetadata: public Instruction {
private:
    uint64_t metadata_;
    uint64_t metadata_mask_;
    const uint16_t set_order_;
public:
    WriteMetadata()
        : Instruction(of13::OFPIT_WRITE_METADATA,
              sizeof(struct of13::ofp_instruction_write_metadata)),
          set_order_(50) {
    }
    WriteMetadata(uint64_t metadata, uint64_t metadata_mask);
    ~WriteMetadata() {
    }
    uint16_t set_order() const {
        return this->set_order_;
    }
    virtual bool equals(const Instruction & other);
    virtual WriteMetadata* clone() {
        return new WriteMetadata(*this);
    }
    size_t pack(uint8_t* buffer);
    of_error unpack(uint8_t* buffer);
    uint64_t metadata() {
        return this->metadata_;
    }
    uint64_t metadata_mask() {
        return this->metadata_mask_;
    }
    void metadata(uint64_t metadata) {
        this->metadata_ = metadata;
    }
    void metadata_mask(uint64_t metadata_mask) {
        this->metadata_mask_ = metadata_mask;
    }
};

class WriteActions: public Instruction {
private:
    ActionSet actions_;
    const uint16_t set_order_;
public:
    WriteActions()
        : Instruction(of13::OFPIT_WRITE_ACTIONS,
              sizeof(struct of13::ofp_instruction_actions)),
          set_order_(40) {
    }
    WriteActions(ActionSet actions);
    ~WriteActions() {
    }
    uint16_t set_order() const {
        return this->set_order_;
    }
    virtual bool equals(const Instruction & other);
    size_t pack(uint8_t* buffer);
    virtual WriteActions* clone() {
        return new WriteActions(*this);
    }
    of_error unpack(uint8_t* buffer);
    ActionSet actions() {
        return this->actions_;
    }
    void actions(ActionSet actions);
    void add_action(Action &action);
    void add_action(Action* action);
};

class ApplyActions: public Instruction {
private:
    ActionList actions_;
    const uint16_t set_order_;
public:
    ApplyActions()
        : Instruction(of13::OFPIT_APPLY_ACTIONS,
              sizeof(struct of13::ofp_instruction_actions)),
          set_order_(20) {
    }
    ApplyActions(ActionList actions);
    ~ApplyActions() {
    }
    uint16_t set_order() const {
        return this->set_order_;
    }
    virtual bool equals(const Instruction & other);
    virtual ApplyActions* clone() {
        return new ApplyActions(*this);
    }
    size_t pack(uint8_t* buffer);
    of_error unpack(uint8_t* buffer);
    ActionList actions() {
        return this->actions_;
    }
    void actions(ActionList actions);
    void add_action(Action &action);
    void add_action(Action* action);
};

class ClearActions: public Instruction {
private:
    const uint16_t set_order_;
public:
    ClearActions()
        : Instruction(of13::OFPIT_CLEAR_ACTIONS,
              sizeof(struct of13::ofp_instruction)),
          set_order_(30) {
    }
    ~ClearActions() {
    }
    uint16_t set_order() const {
        return this->set_order_;
    }
    virtual ClearActions* clone() {
        return new ClearActions(*this);
    }
    size_t pack(uint8_t* buffer);
    of_error unpack(uint8_t* buffer);
};

class Meter: public Instruction {
private:
    uint32_t meter_id_;
    const uint16_t set_order_;
public:
    Meter()
        : Instruction(of13::OFPIT_METER,
              sizeof(struct of13::ofp_instruction_meter)),
          set_order_(10) {
    }
    Meter(uint32_t meter_id);
    ~Meter() {
    }
    uint16_t set_order() const {
        return this->set_order_;
    }
    virtual bool equals(const Instruction & other);
    virtual Meter* clone() {
        return new Meter(*this);
    }
    size_t pack(uint8_t* buffer);
    of_error unpack(uint8_t* buffer);
    uint32_t meter_id() {
        return this->meter_id_;
    }
    void meter_id(uint32_t meter_id) {
        this->meter_id_ = meter_id;
    }
};

class InstructionExperimenter: public Instruction {
protected:
    uint32_t experimenter_;
public:
    InstructionExperimenter() {
    }
    InstructionExperimenter(uint32_t experimenter);
    ~InstructionExperimenter() {
    }
    virtual bool equals(const Instruction & other);
    virtual InstructionExperimenter* clone() {
        return new InstructionExperimenter(*this);
    }
    size_t pack(uint8_t* buffer);
    of_error unpack(uint8_t* buffer);
    uint32_t experimenter() {
        return this->experimenter_;
    }
    void experimenter(uint32_t experimenter) {
        this->experimenter_ = experimenter;
    }
};

}

} //End of namespace fluid_msg
#endif
<|endoftext|>


<commit_before>#include "RenderThread.hpp"
#include <Core/Engine.hh>
#include <Context/SdlContext.hh>
#include <Utils/ThreadName.hpp>
#include <Threads/Tasks/ToRenderTasks.hpp>
#include <Threads/Commands/ToRenderCommands.hpp>
#include <Threads/Tasks/BasicTasks.hpp>
#include <Context/SdlContext.hh>
#include <Utils/Containers/Vector.hpp>
#include <Threads/ThreadManager.hpp>
#include <Core/Engine.hh>
#include <Context/SdlContext.hh>
#include <Render/GeometryManagement/Painting/Painter.hh>
#include <Render/Pipelining/Pipelines/CustomPipeline/BasicPipeline.hh>
#include <Render/Pipelining/Pipelines/CustomPipeline/DeferredShading.hh>
#include <Utils/OpenGL.hh>
#include <Utils/Age_Imgui.hpp>
#include <Render/Properties/Transformation.hh>
#include <SpacePartitioning/Ouptut/RenderCamera.hh>
#include <SpacePartitioning/Ouptut/RenderLight.hh>
#include <SpacePartitioning/Ouptut/RenderPipeline.hh>
#include <Utils/Debug.hpp>

namespace AGE
{
	RenderThread::RenderThread()
		: Thread(AGE::Thread::ThreadType::Render)
		, _context(nullptr),
		paintingManager(std::make_shared<PaintingManager>()),
		pipelines(2)
	{
	}

	RenderThread::~RenderThread()
	{}

	bool RenderThread::init()
	{
		registerCallback<Tasks::Render::CreateRenderContext>([this](Tasks::Render::CreateRenderContext &msg)
		{
			_context = msg.engine->setInstance<SdlContext, IRenderContext>();
			if (!_context->init(0, 1280, 720, "~AGE~ V0.00001 Demo"))
			{
				msg.setValue(false);
				return;
			}
			//pipelines[DEFERRED] = std::make_unique<DeferredShading>(_context->getScreenSize(), paintingManager);
			pipelines[BASIC] = std::make_unique<DeferredShading>(glm::uvec2(1280, 720), paintingManager);
//			pipelines[DEFERRED] = std::make_unique<BasicPipeline>(paintingManager);
			msg.setValue(true);
		});

 		registerCallback<Commands::ToRender::Flush>([&](Commands::ToRender::Flush& msg)
		{
			_context->swapContext();
			glClear(GL_COLOR_BUFFER_BIT);
		});

		registerCallback<Tasks::Render::GetWindowSize>([&](Tasks::Render::GetWindowSize &msg)
		{
			msg.setValue(_context->getScreenSize());
		});

		registerCallback<Tasks::Render::SetWindowSize>([&](Tasks::Render::SetWindowSize& msg)
		{
			_context->setScreenSize(msg.size);
		});

		registerCallback<Commands::ToRender::CopyDrawLists>([&](Commands::ToRender::CopyDrawLists& msg)
		{
			_drawlistPtr = msg.listContainer;
		});

		registerCallback<Commands::ToRender::RenderDrawLists>([&](Commands::ToRender::RenderDrawLists& msg)
		{
			uint32_t pipelineIdx = 0;

			if (!_drawlistPtr) // nothing to draw
				return;
			AGE_ASSERT(_drawlistPtr != nullptr);

			for (auto &curPipeline : pipelines)
			{
				auto &drawlist = _drawlistPtr->container.cameras;
				for (auto &curCamera : drawlist)
				{
					if (pipelineIdx < curCamera.pipelines.size()) {
						curPipeline->render(curCamera.pipelines[pipelineIdx], curCamera.lights, curCamera.camInfos);
					}
				}
				++pipelineIdx;
			}
			_drawlistPtr = nullptr;
		});

		registerSharedCallback<AGE::Tasks::Basic::BoolFunction>([&](AGE::Tasks::Basic::BoolFunction& msg)
		{
			msg.setValue(msg.function());
		});

		registerCallback<AGE::Tasks::Basic::VoidFunction>([&](AGE::Tasks::Basic::VoidFunction& msg)
		{
			if (msg.function)
				msg.function();
		});

		registerCallback<AGE::Tasks::Basic::Exit>([&](AGE::Tasks::Basic::Exit& msg)
		{
			AGE::CreateEngine()->deleteInstance<IRenderContext>();
			this->_insideRun = false;
		});

#ifdef USE_IMGUI
		registerCallback<AGE::RenderImgui>([&](AGE::RenderImgui &msg)
		{
			AGE::Imgui::getInstance()->renderThreadRenderFn(msg.cmd_lists);
		});
#endif

		return true;
	}

	bool RenderThread::release()
	{
		return true;
	}

	bool RenderThread::launch()
	{
		if (!init())
			return false;
		_threadHandle = std::thread(&RenderThread::update, std::ref(*this));
		return true;
	}

	bool RenderThread::stop()
	{
		getQueue()->emplaceTask<Tasks::Basic::Exit>();
		if (_threadHandle.joinable())
			_threadHandle.join();
		return true;
	}

	bool RenderThread::update()
	{
		/*
		- Tant qu'il n'y a pas de command
		-> je pop des task
		- Une fois que j'ai mes commandes
		-> pour chacunes d'elles
		-> je regarde si c'est a moi de les traiter (ex : changement de scene)
		-> si ca n'est pas a moi de les traiter
		-> je les passe au render context actif
		-> si il n'y a pas de render context actif, c'est que j'ai fait une erreur, et j'assert dans ta face :D
		*/

		_registerId();

		_run = true;
		_insideRun = true;
		DWORD threadId = GetThreadId(static_cast<HANDLE>(_threadHandle.native_handle()));
		SetThreadName(threadId, this->_name.c_str());

		TMQ::PtrQueue commands;
		TMQ::PtrQueue tasks;
		bool commandSuccess;
		bool taskSuccess;

		std::chrono::system_clock::time_point waitStart;
		std::chrono::system_clock::time_point waitEnd;
		std::chrono::system_clock::time_point workStart;
		std::chrono::system_clock::time_point workEnd;

		while (_run && _insideRun)
		{
			waitStart = std::chrono::high_resolution_clock::now();
			taskSuccess = commandSuccess = false;
			do {
				if (_context)
					_context->refreshInputs();
				getQueue()->getTaskAndCommandQueue(tasks, taskSuccess, commands, commandSuccess, TMQ::HybridQueue::Block);
			} while (!taskSuccess && !commandSuccess);
			waitEnd = std::chrono::high_resolution_clock::now();
			workStart = std::chrono::high_resolution_clock::now();
			if (taskSuccess)
			{
				while (!tasks.empty() && _insideRun)
				{
					//pop all tasks
					auto task = tasks.front();
					assert(execute(task)); // we receive a task that we cannot treat
					tasks.pop();
					taskCounter--;
					workEnd = std::chrono::high_resolution_clock::now();
					const std::size_t toWait = 33;
					const std::size_t elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(workEnd - workStart).count();
					if (elapsed >= toWait)
					{
						std::cout << elapsed << ", ";
						while (!tasks.empty() && _insideRun)
						{
							auto task = tasks.front();
							getQueue()->moveTask(task, tasks.getFrontSize());
							tasks.pop();
						}
					}
				}
			}
			if (commandSuccess)
			{
				// pop all commands
				while (!commands.empty() && _insideRun)
				{
					auto command = commands.front();
					assert(execute(command));
					commands.pop();
				}

				workEnd = std::chrono::high_resolution_clock::now();
				GetThreadManager()->updateThreadStatistics(this->_id
					, std::chrono::duration_cast<std::chrono::microseconds>(workEnd - workStart).count()
					, std::chrono::duration_cast<std::chrono::microseconds>(waitEnd - waitStart).count());
			}
		}
		return true;
	}
}<commit_msg>both activated<commit_after>#include "RenderThread.hpp"
#include <Core/Engine.hh>
#include <Context/SdlContext.hh>
#include <Utils/ThreadName.hpp>
#include <Threads/Tasks/ToRenderTasks.hpp>
#include <Threads/Commands/ToRenderCommands.hpp>
#include <Threads/Tasks/BasicTasks.hpp>
#include <Context/SdlContext.hh>
#include <Utils/Containers/Vector.hpp>
#include <Threads/ThreadManager.hpp>
#include <Core/Engine.hh>
#include <Context/SdlContext.hh>
#include <Render/GeometryManagement/Painting/Painter.hh>
#include <Render/Pipelining/Pipelines/CustomPipeline/BasicPipeline.hh>
#include <Render/Pipelining/Pipelines/CustomPipeline/DeferredShading.hh>
#include <Utils/OpenGL.hh>
#include <Utils/Age_Imgui.hpp>
#include <Render/Properties/Transformation.hh>
#include <SpacePartitioning/Ouptut/RenderCamera.hh>
#include <SpacePartitioning/Ouptut/RenderLight.hh>
#include <SpacePartitioning/Ouptut/RenderPipeline.hh>
#include <Utils/Debug.hpp>

namespace AGE
{
	RenderThread::RenderThread()
		: Thread(AGE::Thread::ThreadType::Render)
		, _context(nullptr),
		paintingManager(std::make_shared<PaintingManager>()),
		pipelines(2)
	{
	}

	RenderThread::~RenderThread()
	{}

	bool RenderThread::init()
	{
		registerCallback<Tasks::Render::CreateRenderContext>([this](Tasks::Render::CreateRenderContext &msg)
		{
			_context = msg.engine->setInstance<SdlContext, IRenderContext>();
			if (!_context->init(0, 1280, 720, "~AGE~ V0.00001 Demo"))
			{
				msg.setValue(false);
				return;
			}
			//pipelines[DEFERRED] = std::make_unique<DeferredShading>(_context->getScreenSize(), paintingManager);
			pipelines[DEFERRED] = std::make_unique<DeferredShading>(glm::uvec2(1280, 720), paintingManager);
			pipelines[BASIC] = std::make_unique<BasicPipeline>(paintingManager);
			msg.setValue(true);
		});

 		registerCallback<Commands::ToRender::Flush>([&](Commands::ToRender::Flush& msg)
		{
			_context->swapContext();
			glClear(GL_COLOR_BUFFER_BIT);
		});

		registerCallback<Tasks::Render::GetWindowSize>([&](Tasks::Render::GetWindowSize &msg)
		{
			msg.setValue(_context->getScreenSize());
		});

		registerCallback<Tasks::Render::SetWindowSize>([&](Tasks::Render::SetWindowSize& msg)
		{
			_context->setScreenSize(msg.size);
		});

		registerCallback<Commands::ToRender::CopyDrawLists>([&](Commands::ToRender::CopyDrawLists& msg)
		{
			_drawlistPtr = msg.listContainer;
		});

		registerCallback<Commands::ToRender::RenderDrawLists>([&](Commands::ToRender::RenderDrawLists& msg)
		{
			uint32_t pipelineIdx = 0;

			if (!_drawlistPtr) // nothing to draw
				return;
			AGE_ASSERT(_drawlistPtr != nullptr);

			for (auto &curPipeline : pipelines)
			{
				auto &drawlist = _drawlistPtr->container.cameras;
				for (auto &curCamera : drawlist)
				{
					if (pipelineIdx < curCamera.pipelines.size()) {
						curPipeline->render(curCamera.pipelines[pipelineIdx], curCamera.lights, curCamera.camInfos);
					}
				}
				++pipelineIdx;
			}
			_drawlistPtr = nullptr;
		});

		registerSharedCallback<AGE::Tasks::Basic::BoolFunction>([&](AGE::Tasks::Basic::BoolFunction& msg)
		{
			msg.setValue(msg.function());
		});

		registerCallback<AGE::Tasks::Basic::VoidFunction>([&](AGE::Tasks::Basic::VoidFunction& msg)
		{
			if (msg.function)
				msg.function();
		});

		registerCallback<AGE::Tasks::Basic::Exit>([&](AGE::Tasks::Basic::Exit& msg)
		{
			AGE::CreateEngine()->deleteInstance<IRenderContext>();
			this->_insideRun = false;
		});

#ifdef USE_IMGUI
		registerCallback<AGE::RenderImgui>([&](AGE::RenderImgui &msg)
		{
			AGE::Imgui::getInstance()->renderThreadRenderFn(msg.cmd_lists);
		});
#endif

		return true;
	}

	bool RenderThread::release()
	{
		return true;
	}

	bool RenderThread::launch()
	{
		if (!init())
			return false;
		_threadHandle = std::thread(&RenderThread::update, std::ref(*this));
		return true;
	}

	bool RenderThread::stop()
	{
		getQueue()->emplaceTask<Tasks::Basic::Exit>();
		if (_threadHandle.joinable())
			_threadHandle.join();
		return true;
	}

	bool RenderThread::update()
	{
		/*
		- Tant qu'il n'y a pas de command
		-> je pop des task
		- Une fois que j'ai mes commandes
		-> pour chacunes d'elles
		-> je regarde si c'est a moi de les traiter (ex : changement de scene)
		-> si ca n'est pas a moi de les traiter
		-> je les passe au render context actif
		-> si il n'y a pas de render context actif, c'est que j'ai fait une erreur, et j'assert dans ta face :D
		*/

		_registerId();

		_run = true;
		_insideRun = true;
		DWORD threadId = GetThreadId(static_cast<HANDLE>(_threadHandle.native_handle()));
		SetThreadName(threadId, this->_name.c_str());

		TMQ::PtrQueue commands;
		TMQ::PtrQueue tasks;
		bool commandSuccess;
		bool taskSuccess;

		std::chrono::system_clock::time_point waitStart;
		std::chrono::system_clock::time_point waitEnd;
		std::chrono::system_clock::time_point workStart;
		std::chrono::system_clock::time_point workEnd;

		while (_run && _insideRun)
		{
			waitStart = std::chrono::high_resolution_clock::now();
			taskSuccess = commandSuccess = false;
			do {
				if (_context)
					_context->refreshInputs();
				getQueue()->getTaskAndCommandQueue(tasks, taskSuccess, commands, commandSuccess, TMQ::HybridQueue::Block);
			} while (!taskSuccess && !commandSuccess);
			waitEnd = std::chrono::high_resolution_clock::now();
			workStart = std::chrono::high_resolution_clock::now();
			if (taskSuccess)
			{
				while (!tasks.empty() && _insideRun)
				{
					//pop all tasks
					auto task = tasks.front();
					assert(execute(task)); // we receive a task that we cannot treat
					tasks.pop();
					taskCounter--;
					workEnd = std::chrono::high_resolution_clock::now();
					const std::size_t toWait = 33;
					const std::size_t elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(workEnd - workStart).count();
					if (elapsed >= toWait)
					{
						std::cout << elapsed << ", ";
						while (!tasks.empty() && _insideRun)
						{
							auto task = tasks.front();
							getQueue()->moveTask(task, tasks.getFrontSize());
							tasks.pop();
						}
					}
				}
			}
			if (commandSuccess)
			{
				// pop all commands
				while (!commands.empty() && _insideRun)
				{
					auto command = commands.front();
					assert(execute(command));
					commands.pop();
				}

				workEnd = std::chrono::high_resolution_clock::now();
				GetThreadManager()->updateThreadStatistics(this->_id
					, std::chrono::duration_cast<std::chrono::microseconds>(workEnd - workStart).count()
					, std::chrono::duration_cast<std::chrono::microseconds>(waitEnd - waitStart).count());
			}
		}
		return true;
	}
}<|endoftext|>


<commit_before>// Copyright 2016 Benjamin Glatzel
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Precompiled header file
#include "stdafx.h"
#include "stdafx_editor.h"

// Ui
#include "ui_IntrinsicEdPropertyEditorRotation.h"

IntrinsicEdPropertyEditorRotation::IntrinsicEdPropertyEditorRotation(
    rapidjson::Document* p_Document, rapidjson::Value* p_CurrentProperties,
    rapidjson::Value* p_CurrentProperty, const char* p_PropertyName,
    QWidget* parent)
    : QWidget(parent), _properties(p_CurrentProperties),
      _property(p_CurrentProperty), _propertyName(p_PropertyName),
      _document(p_Document)
{
  _ui.setupUi(this);
  updateFromProperty();

  QObject::connect(_ui.yaw, SIGNAL(valueChanged(double)), this,
                   SLOT(onValueChanged()));
  QObject::connect(_ui.pitch, SIGNAL(valueChanged(double)), this,
                   SLOT(onValueChanged()));
  QObject::connect(_ui.roll, SIGNAL(valueChanged(double)), this,
                   SLOT(onValueChanged()));
  QObject::connect(_ui.sYaw, SIGNAL(valueChanged(int)), this,
                   SLOT(onSliderValueChanged()));
  QObject::connect(_ui.sPitch, SIGNAL(valueChanged(int)), this,
                   SLOT(onSliderValueChanged()));
  QObject::connect(_ui.sRoll, SIGNAL(valueChanged(int)), this,
                   SLOT(onSliderValueChanged()));
}

IntrinsicEdPropertyEditorRotation::~IntrinsicEdPropertyEditorRotation() {}

void IntrinsicEdPropertyEditorRotation::updateFromProperty()
{
  _INTR_ASSERT(_property);
  const rapidjson::Value& prop = *_property;

  if (prop["readOnly"].GetBool())
  {
    _ui.yaw->setReadOnly(true);
    _ui.pitch->setReadOnly(true);
    _ui.roll->setReadOnly(true);
    _ui.sYaw->setDisabled(true);
    _ui.sPitch->setDisabled(true);
    _ui.sRoll->setDisabled(true);
  }

  glm::vec3 euler;

  if (strcmp(prop["type"].GetString(), "quat") == 0u)
  {
    const glm::quat quat =
        glm::quat(prop["values"][3].GetFloat(), prop["values"][0].GetFloat(),
                  prop["values"][1].GetFloat(), prop["values"][3].GetFloat());
    euler = glm::eulerAngles(quat);
  }
  else if (strcmp(prop["type"].GetString(), "vec3") == 0u)
  {
    euler =
        glm::vec3(glm::radians(glm::mod(prop["values"][0].GetFloat(), 360.0f)),
                  glm::radians(glm::mod(prop["values"][1].GetFloat(), 360.0f)),
                  glm::radians(glm::mod(prop["values"][2].GetFloat(), 360.0f)));
  }

  _ui.yaw->setValue(glm::degrees(euler.x));
  _ui.pitch->setValue(glm::degrees(euler.y));
  _ui.roll->setValue(glm::degrees(euler.z));
  _ui.sYaw->setValue(glm::degrees(euler.x));
  _ui.sPitch->setValue(glm::degrees(euler.y));
  _ui.sRoll->setValue(glm::degrees(euler.z));

  _ui.propertyTitle->setText(_propertyName.c_str());
}

void IntrinsicEdPropertyEditorRotation::onValueChanged()
{
  _INTR_ASSERT(_property);
  rapidjson::Value& prop = *_property;

  _ui.sYaw->setValue(_ui.yaw->value());
  _ui.sPitch->setValue(_ui.pitch->value());
  _ui.sRoll->setValue(_ui.roll->value());

  const glm::vec3 euler = glm::vec3(glm::radians(_ui.yaw->value()),
                                    glm::radians(_ui.pitch->value()),
                                    glm::radians(_ui.roll->value()));

  if (strcmp(prop["type"].GetString(), "quat") == 0u)
  {
    const glm::quat quat = glm::quat(euler);
    prop["values"][0].SetFloat(quat.x);
    prop["values"][1].SetFloat(quat.y);
    prop["values"][2].SetFloat(quat.z);
    prop["values"][3].SetFloat(quat.w);
  }
  else if (strcmp(prop["type"].GetString(), "vec3") == 0u)
  {
    prop["values"][0].SetFloat(glm::degrees(euler.x));
    prop["values"][1].SetFloat(glm::degrees(euler.y));
    prop["values"][2].SetFloat(glm::degrees(euler.z));
  }

  emit valueChanged(*_properties);
}

void IntrinsicEdPropertyEditorRotation::onSliderValueChanged()
{
  _INTR_ASSERT(_property);
  rapidjson::Value& prop = *_property;

  _ui.yaw->setValue(_ui.sYaw->value());
  _ui.pitch->setValue(_ui.sPitch->value());
  _ui.roll->setValue(_ui.sRoll->value());

  onValueChanged();
}
<commit_msg>Fix: Typo in the IntrinsicEd rotation <> quaternion conversion<commit_after>// Copyright 2016 Benjamin Glatzel
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Precompiled header file
#include "stdafx.h"
#include "stdafx_editor.h"

// Ui
#include "ui_IntrinsicEdPropertyEditorRotation.h"

IntrinsicEdPropertyEditorRotation::IntrinsicEdPropertyEditorRotation(
    rapidjson::Document* p_Document, rapidjson::Value* p_CurrentProperties,
    rapidjson::Value* p_CurrentProperty, const char* p_PropertyName,
    QWidget* parent)
    : QWidget(parent), _properties(p_CurrentProperties),
      _property(p_CurrentProperty), _propertyName(p_PropertyName),
      _document(p_Document)
{
  _ui.setupUi(this);
  updateFromProperty();

  QObject::connect(_ui.yaw, SIGNAL(valueChanged(double)), this,
                   SLOT(onValueChanged()));
  QObject::connect(_ui.pitch, SIGNAL(valueChanged(double)), this,
                   SLOT(onValueChanged()));
  QObject::connect(_ui.roll, SIGNAL(valueChanged(double)), this,
                   SLOT(onValueChanged()));
  QObject::connect(_ui.sYaw, SIGNAL(valueChanged(int)), this,
                   SLOT(onSliderValueChanged()));
  QObject::connect(_ui.sPitch, SIGNAL(valueChanged(int)), this,
                   SLOT(onSliderValueChanged()));
  QObject::connect(_ui.sRoll, SIGNAL(valueChanged(int)), this,
                   SLOT(onSliderValueChanged()));
}

IntrinsicEdPropertyEditorRotation::~IntrinsicEdPropertyEditorRotation() {}

void IntrinsicEdPropertyEditorRotation::updateFromProperty()
{
  _INTR_ASSERT(_property);
  const rapidjson::Value& prop = *_property;

  if (prop["readOnly"].GetBool())
  {
    _ui.yaw->setReadOnly(true);
    _ui.pitch->setReadOnly(true);
    _ui.roll->setReadOnly(true);
    _ui.sYaw->setDisabled(true);
    _ui.sPitch->setDisabled(true);
    _ui.sRoll->setDisabled(true);
  }

  glm::vec3 euler;

  if (strcmp(prop["type"].GetString(), "quat") == 0u)
  {
    const glm::quat quat =
        glm::quat(prop["values"][3].GetFloat(), prop["values"][0].GetFloat(),
                  prop["values"][1].GetFloat(), prop["values"][2].GetFloat());
    euler = glm::eulerAngles(quat);
  }
  else if (strcmp(prop["type"].GetString(), "vec3") == 0u)
  {
    euler =
        glm::vec3(glm::radians(glm::mod(prop["values"][0].GetFloat(), 360.0f)),
                  glm::radians(glm::mod(prop["values"][1].GetFloat(), 360.0f)),
                  glm::radians(glm::mod(prop["values"][2].GetFloat(), 360.0f)));
  }

  _ui.yaw->setValue(glm::degrees(euler.x));
  _ui.pitch->setValue(glm::degrees(euler.y));
  _ui.roll->setValue(glm::degrees(euler.z));
  _ui.sYaw->setValue(glm::degrees(euler.x));
  _ui.sPitch->setValue(glm::degrees(euler.y));
  _ui.sRoll->setValue(glm::degrees(euler.z));

  _ui.propertyTitle->setText(_propertyName.c_str());
}

void IntrinsicEdPropertyEditorRotation::onValueChanged()
{
  _INTR_ASSERT(_property);
  rapidjson::Value& prop = *_property;

  _ui.sYaw->setValue(_ui.yaw->value());
  _ui.sPitch->setValue(_ui.pitch->value());
  _ui.sRoll->setValue(_ui.roll->value());

  const glm::vec3 euler = glm::vec3(glm::radians(_ui.yaw->value()),
                                    glm::radians(_ui.pitch->value()),
                                    glm::radians(_ui.roll->value()));

  if (strcmp(prop["type"].GetString(), "quat") == 0u)
  {
    const glm::quat quat = glm::quat(euler);
    prop["values"][0].SetFloat(quat.x);
    prop["values"][1].SetFloat(quat.y);
    prop["values"][2].SetFloat(quat.z);
    prop["values"][3].SetFloat(quat.w);
  }
  else if (strcmp(prop["type"].GetString(), "vec3") == 0u)
  {
    prop["values"][0].SetFloat(glm::degrees(euler.x));
    prop["values"][1].SetFloat(glm::degrees(euler.y));
    prop["values"][2].SetFloat(glm::degrees(euler.z));
  }

  emit valueChanged(*_properties);
}

void IntrinsicEdPropertyEditorRotation::onSliderValueChanged()
{
  _INTR_ASSERT(_property);
  rapidjson::Value& prop = *_property;

  _ui.yaw->setValue(_ui.sYaw->value());
  _ui.pitch->setValue(_ui.sPitch->value());
  _ui.roll->setValue(_ui.sRoll->value());

  onValueChanged();
}
<|endoftext|>