<commit_before>#include "scan.h"

#include <maya/MFnDagNode.h>
#include <maya/MItDag.h>
#include <maya/MObject.h>
#include <maya/MDagPath.h>
#include <maya/MString.h>
#include <maya/MFnMesh.h>
#include <maya/MArgList.h>
#include <maya/MPoint.h>
#include <maya/MVector.h>
#include <maya/MMatrix.h>
#include <maya/MTransformationMatrix.h>
#include <maya/MColor.h>
#include <maya/MIOStream.h>
#include <maya/MPlug.h>
#include <maya/MPlugArray.h>
#include <maya/MFnAttribute.h>

#include "messaging.h"
#include "hackPrint.h"

Scan::Scan()
	:
	pMessaging(new Messaging("8080"))
{
}

Scan::~Scan()
{
}

void* Scan::creator()
{
	return new Scan;
}

MStatus	Scan::doIt(const MArgList& args)
{
	MItDag::TraversalType	traversalType = MItDag::kDepthFirst;

	MStatus status;

	// filter to only meshes
	MItDag dagIterator(traversalType, MFn::kMesh, &status);

	if (!status) {
		status.perror("MItDag constructor");
		return status;
	}

	for (; !dagIterator.isDone(); dagIterator.next()) {

		MDagPath dagPath;

		status = dagIterator.getPath(dagPath);
		if (!status) {
			status.perror("MItDag::getPath");
			continue;
		}
		MFnDagNode dagNode(dagPath, &status);
		if (!status) {
			status.perror("MFnDagNode constructor");
			continue;
		}
		bool fHasTweaks = false;

		dagPath.extendToShape();
		MObject meshNodeShape = dagPath.node();
		MFnDependencyNode depNodeFn(meshNodeShape);

		// Tweaks exist only if the multi "pnts" attribute contains
		// plugs that contain non-zero tweak values. Use false,
		// until proven true search pattern.

		MPlug tweakPlug = depNodeFn.findPlug("pnts");
		if (!tweakPlug.isNull())
		{
			// ASSERT : tweakPlug should be an array plug
			//MAssert(tweakPlug.isArray(), "tweakPlug.isArray()");
			MPlug tweak;
			MFloatVector tweakData;
			int i;
			int numElements = tweakPlug.numElements();
			for (i = 0; i < numElements; i++)
			{
				tweak = tweakPlug.elementByPhysicalIndex(i, &status);
				if (status == MS::kSuccess && !tweak.isNull())
				{
					fHasTweaks = true;
					break;
				}
			}
		}

		MFnMesh mesh(meshNodeShape, &status);

		if (!status) {
			status.perror("MFnMesh:constructor");
			continue;
		}

		HackPrint::print("Shape: ");
		HackPrint::print(mesh.name());
		HackPrint::print("history: ");

		// If the inMesh is connected, we have history
		MPlug inMeshPlug = depNodeFn.findPlug("inMesh");
		if (inMeshPlug.isConnected())
		{
			MPlugArray tempPlugArray;
			inMeshPlug.connectedTo(tempPlugArray, true, false);
			MPlug upstreamNodeSrcPlug = tempPlugArray[0];
			MFnDependencyNode upstreamNode(upstreamNodeSrcPlug.node());

			HackPrint::print(upstreamNode.typeName());
			HackPrint::print(upstreamNode.name());
			findHistory(upstreamNode, mesh);
		}

		if (fHasTweaks) HackPrint::print("tweaks: true");
		else HackPrint::print("tweaks: false");

	}
	return MS::kSuccess;
}

void Scan::findHistory(MFnDependencyNode & node, MFnMesh & mesh)
{
	// check and send data about this node
	if (node.typeName() == MString("polySplitRing"))
	{
		HackPrint::print("we have found a polysplit lets send it");
		sendNode(node, mesh);
	}

	// need a niver wya of doing this with types over strings.
	if (node.typeName() == MString("polyCube"))
	{
		HackPrint::print("Found a cube, what do?");
		sendNode(node, mesh);
	}

	// now lets see if it has a parent

	// If the inpuPolymesh is connected, we have history
	MPlug inMeshPlug = node.findPlug("inputPolymesh");

	if (inMeshPlug.isConnected())
	{
		MPlugArray tempPlugArray;
		inMeshPlug.connectedTo(tempPlugArray, true, false);

		// Only one connection should exist on meshNodeShape.inMesh!
		MPlug upstreamNodeSrcPlug = tempPlugArray[0];

		MFnDependencyNode upstreamNode(upstreamNodeSrcPlug.node());

		HackPrint::print("----------");
		HackPrint::print(upstreamNode.typeName());
		HackPrint::print(upstreamNode.name());

		findHistory(upstreamNode, mesh);
	}
}

void Scan::sendNode(MFnDependencyNode & node, MFnMesh & mesh)
{
	// this shows us all attributes.
	// there are other ways of individually finding them using plugs
	unsigned int numAttrib = node.attributeCount();
	MStatus status;

	attribMap nodeAttribs;

	for (unsigned int i = 0; i < numAttrib; i++)
	{
		MFnAttribute attrib(node.attribute(i));

		MPlug plug = node.findPlug(attrib.shortName().asChar(), status);

		if (status != MStatus::kSuccess) continue;

		attribType values;
		if (getAttribFromPlug(plug, values) == MStatus::kSuccess)
		{
			nodeAttribs.insert(values);
		}
	}

	if (nodeAttribs.empty()) return;

	GenericMessage msg;
	msg.setMeshName(std::string(mesh.name().asChar()));
	msg.setNodeName(std::string(node.name().asChar()));
	msg.setNodeType(node.typeName().asChar());
	msg.setRequestType(SCENE_UPDATE);

	msg.setAttribs(nodeAttribs);

	if (pMessaging->sendUpdate(msg))
	{
		HackPrint::print("Update sent Succesfully");
		return;
	}

	HackPrint::print("Cannot send to Server!");
}

MStatus Scan::getAttribFromPlug(MPlug& _plug, attribType& _attrib)
{

	std::string attribName = _plug.partialName().asChar();

	if (_plug.isCompound())
	{
		// if the plug is a compound then it has a number of children plugs we need to grab
		unsigned int numChild = _plug.numChildren();

		attribMap map;

		//HackPrint::print(_plug.name());

		for(unsigned int i = 0; i < numChild; ++i)
		{
			MPlug childPlug = _plug.child(i);

			//HackPrint::print(childPlug.name());

			// get values
			// and store too
			attribType values;
			if (getAttribFromPlug(childPlug, values) == MStatus::kSuccess)
			{
				map.insert(values);
			}
		}

		// not sure what i should be doing with zone.
		msgpack::zone zone;
		_attrib = attribType(attribName, msgpack::object(map, zone));
		return MStatus::kSuccess;
	}

    //MString value;
    float fValue;
    if (_plug.getValue(fValue) == MStatus::kSuccess)
    {
		_attrib = attribType(attribName, msgpack::object(fValue));
		return MStatus::kSuccess;
    }

    double dValue;
    if (_plug.getValue(dValue) == MStatus::kSuccess)
    {
        _attrib = attribType(attribName, msgpack::object(dValue));
		return MStatus::kSuccess;
    }

    MString sValue;
    if (_plug.getValue(sValue) == MStatus::kSuccess)
    {
        _attrib = attribType(attribName, msgpack::object(sValue.asChar()));
		return MStatus::kSuccess;
    }

    int iValue;
    if (_plug.getValue(iValue) == MStatus::kSuccess)
    {
        _attrib = attribType(attribName, msgpack::object(iValue));
		return MStatus::kSuccess;
    }

    bool bValue;
    if (_plug.getValue(bValue) == MStatus::kSuccess)
    {
        _attrib = attribType(attribName, msgpack::object(bValue));
		return MStatus::kSuccess;
    }

	return MStatus::kFailure;
}<commit_msg>moved array for better catching<commit_after>#include "scan.h"

#include <maya/MFnDagNode.h>
#include <maya/MItDag.h>
#include <maya/MObject.h>
#include <maya/MDagPath.h>
#include <maya/MString.h>
#include <maya/MFnMesh.h>
#include <maya/MArgList.h>
#include <maya/MPoint.h>
#include <maya/MVector.h>
#include <maya/MMatrix.h>
#include <maya/MTransformationMatrix.h>
#include <maya/MColor.h>
#include <maya/MIOStream.h>
#include <maya/MPlug.h>
#include <maya/MPlugArray.h>
#include <maya/MFnAttribute.h>

#include "messaging.h"
#include "hackPrint.h"

Scan::Scan()
	:
	pMessaging(new Messaging("8080"))
{
}

Scan::~Scan()
{
}

void* Scan::creator()
{
	return new Scan;
}

MStatus	Scan::doIt(const MArgList& args)
{
	MItDag::TraversalType	traversalType = MItDag::kDepthFirst;

	MStatus status;

	// filter to only meshes
	MItDag dagIterator(traversalType, MFn::kMesh, &status);

	if (!status) {
		status.perror("MItDag constructor");
		return status;
	}

	for (; !dagIterator.isDone(); dagIterator.next()) {

		MDagPath dagPath;

		status = dagIterator.getPath(dagPath);
		if (!status) {
			status.perror("MItDag::getPath");
			continue;
		}
		MFnDagNode dagNode(dagPath, &status);
		if (!status) {
			status.perror("MFnDagNode constructor");
			continue;
		}
		bool fHasTweaks = false;

		dagPath.extendToShape();
		MObject meshNodeShape = dagPath.node();
		MFnDependencyNode depNodeFn(meshNodeShape);

		// Tweaks exist only if the multi "pnts" attribute contains
		// plugs that contain non-zero tweak values. Use false,
		// until proven true search pattern.

		MPlug tweakPlug = depNodeFn.findPlug("pnts");
		if (!tweakPlug.isNull())
		{
			// ASSERT : tweakPlug should be an array plug
			//MAssert(tweakPlug.isArray(), "tweakPlug.isArray()");
			MPlug tweak;
			MFloatVector tweakData;
			int i;
			int numElements = tweakPlug.numElements();
			for (i = 0; i < numElements; i++)
			{
				tweak = tweakPlug.elementByPhysicalIndex(i, &status);
				if (status == MS::kSuccess && !tweak.isNull())
				{
					fHasTweaks = true;
					break;
				}
			}
		}

		MFnMesh mesh(meshNodeShape, &status);

		if (!status) {
			status.perror("MFnMesh:constructor");
			continue;
		}

		HackPrint::print("Shape: ");
		HackPrint::print(mesh.name());
		HackPrint::print("history: ");

		// If the inMesh is connected, we have history
		MPlug inMeshPlug = depNodeFn.findPlug("inMesh");
		if (inMeshPlug.isConnected())
		{
			MPlugArray tempPlugArray;
			inMeshPlug.connectedTo(tempPlugArray, true, false);
			MPlug upstreamNodeSrcPlug = tempPlugArray[0];
			MFnDependencyNode upstreamNode(upstreamNodeSrcPlug.node());

			HackPrint::print(upstreamNode.typeName());
			HackPrint::print(upstreamNode.name());
			findHistory(upstreamNode, mesh);
		}

		if (fHasTweaks) HackPrint::print("tweaks: true");
		else HackPrint::print("tweaks: false");

	}
	return MS::kSuccess;
}

void Scan::findHistory(MFnDependencyNode & node, MFnMesh & mesh)
{
	// check and send data about this node
	if (node.typeName() == MString("polySplitRing"))
	{
		HackPrint::print("we have found a polysplit lets send it");
		sendNode(node, mesh);
	}

	// need a niver wya of doing this with types over strings.
	if (node.typeName() == MString("polyCube"))
	{
		HackPrint::print("Found a cube, what do?");
		sendNode(node, mesh);
	}

	// now lets see if it has a parent

	// If the inpuPolymesh is connected, we have history
	MPlug inMeshPlug = node.findPlug("inputPolymesh");

	if (inMeshPlug.isConnected())
	{
		MPlugArray tempPlugArray;
		inMeshPlug.connectedTo(tempPlugArray, true, false);

		// Only one connection should exist on meshNodeShape.inMesh!
		MPlug upstreamNodeSrcPlug = tempPlugArray[0];

		MFnDependencyNode upstreamNode(upstreamNodeSrcPlug.node());

		HackPrint::print("----------");
		HackPrint::print(upstreamNode.typeName());
		HackPrint::print(upstreamNode.name());

		findHistory(upstreamNode, mesh);
	}
}

void Scan::sendNode(MFnDependencyNode & node, MFnMesh & mesh)
{
	// this shows us all attributes.
	// there are other ways of individually finding them using plugs
	unsigned int numAttrib = node.attributeCount();
	MStatus status;

	attribMap nodeAttribs;

	for (unsigned int i = 0; i < numAttrib; i++)
	{
		MFnAttribute attrib(node.attribute(i));

		MPlug plug = node.findPlug(attrib.shortName().asChar(), status);

		if (status != MStatus::kSuccess) continue;

		attribType values;
		if (getAttribFromPlug(plug, values) == MStatus::kSuccess)
		{
			nodeAttribs.insert(values);
		}
	}

	if (nodeAttribs.empty()) return;

	GenericMessage msg;
	msg.setMeshName(std::string(mesh.name().asChar()));
	msg.setNodeName(std::string(node.name().asChar()));
	msg.setNodeType(node.typeName().asChar());
	msg.setRequestType(SCENE_UPDATE);

	msg.setAttribs(nodeAttribs);

	if (pMessaging->sendUpdate(msg))
	{
		HackPrint::print("Update sent Succesfully");
		return;
	}

	HackPrint::print("Cannot send to Server!");
}

MStatus Scan::getAttribFromPlug(MPlug& _plug, attribType& _attrib)
{

	std::string attribName = _plug.partialName().asChar();

	if (_plug.isArray())
	{
		HackPrint::print(_plug.name());

		attribMap map;

		for (unsigned int i = 0; i<_plug.numElements(); ++i)
		{
			// get the MPlug for the i'th array element
			MPlug elemPlug = _plug.elementByPhysicalIndex(i);

			HackPrint::print(elemPlug.name());

			attribType values;
			if (getAttribFromPlug(elemPlug, values) == MStatus::kSuccess)
			{
				map.insert(values);
			}
		}

		msgpack::zone zone;
		_attrib = attribType(attribName, msgpack::object(map, zone));
		return MStatus::kSuccess;
	}

	if (_plug.isCompound())
	{
		// if the plug is a compound then it has a number of children plugs we need to grab
		unsigned int numChild = _plug.numChildren();

		attribMap map;

		//HackPrint::print(_plug.name());

		for(unsigned int i = 0; i < numChild; ++i)
		{
			MPlug childPlug = _plug.child(i);

			//HackPrint::print(childPlug.name());

			// get values
			// and store too
			attribType values;
			if (getAttribFromPlug(childPlug, values) == MStatus::kSuccess)
			{
				map.insert(values);
			}
		}

		// not sure what i should be doing with zone.
		msgpack::zone zone;
		_attrib = attribType(attribName, msgpack::object(map, zone));
		return MStatus::kSuccess;
	}

    //MString value;
    float fValue;
    if (_plug.getValue(fValue) == MStatus::kSuccess)
    {
		_attrib = attribType(attribName, msgpack::object(fValue));
		return MStatus::kSuccess;
    }

    double dValue;
    if (_plug.getValue(dValue) == MStatus::kSuccess)
    {
        _attrib = attribType(attribName, msgpack::object(dValue));
		return MStatus::kSuccess;
    }

    MString sValue;
    if (_plug.getValue(sValue) == MStatus::kSuccess)
    {
        _attrib = attribType(attribName, msgpack::object(sValue.asChar()));
		return MStatus::kSuccess;
    }

    int iValue;
    if (_plug.getValue(iValue) == MStatus::kSuccess)
    {
        _attrib = attribType(attribName, msgpack::object(iValue));
		return MStatus::kSuccess;
    }

    bool bValue;
    if (_plug.getValue(bValue) == MStatus::kSuccess)
    {
        _attrib = attribType(attribName, msgpack::object(bValue));
		return MStatus::kSuccess;
    }

	// TODO more maya data types

	return MStatus::kFailure;
}<|endoftext|>


<commit_before>
#include <iostream>

#include <texturebased/polarmapped.h>

int main(int /*argc*/, char* /*argv*/[])
{

    // TODO: glfw

    return 0;
}
<commit_msg>Add glfw window to texture demo<commit_after>
#include <iostream>

#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>

#include <glbinding/Binding.h>

#include <glbinding/gl/gl.h>
#include <globjects/globjects.h>

using namespace gl;

void error(int errnum, const char * errmsg)
{
    std::cerr << errnum << ": " << errmsg << std::endl;
}

void key_callback(GLFWwindow * window, int key, int /*scancode*/, int action, int /*mods*/)
{
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
        glfwSetWindowShouldClose(window, 1);
}

int main(int, char *[])
{
    if (!glfwInit())
        return 1;

    glfwSetErrorCallback(error);

    glfwDefaultWindowHints();

#ifdef SYSTEM_DARWIN
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, true);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#endif

    GLFWwindow * window = glfwCreateWindow(640, 480, "Texture Demo", nullptr, nullptr);
    if (!window)
    {
        glfwTerminate();
        return -1;
    }

    glfwSetKeyCallback(window, key_callback);

    glfwMakeContextCurrent(window);

    glbinding::Binding::initialize(false); // only resolve functions that are actually used (lazy)
    globjects::init();

    while (!glfwWindowShouldClose(window))
    {
        glfwPollEvents();
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glfwSwapBuffers(window);
    }

    glfwTerminate();
    return 0;
}
<|endoftext|>


<commit_before>#include <EarlyAnalysis/OilTypeResolution.h>

#include <OIL/OilTraversal.h>
#include <OIL/OilNamespaceDefinition.h>
#include <OIL/OilTypeRef.h>
#include <OIL/OilTraitDefinition.h>
#include <OIL/OilTypeDefinition.h>
#include <OIL/OilNamespaceDefinition.h>
#include <OIL/OilConstStatement.h>
#include <OIL/OilBindingStatement.h>
#include <OIL/OilTypeDefinition.h>
#include <OIL/OilStructDefinition.h>
#include <OIL/OilStructBinding.h>
#include <OIL/OilTemplateSpecification.h>
#include <OIL/OilBuiltinStructDefinition.h>
#include <OIL/OilTemplateDefinition.h>
#include <OIL/OilTemplateDefinitionParameter.h>
#include <OIL/OilTemplateDefinition.h>

#include <Logging/Logging.h>
#include <Encoding/CodeConversion.h>

TypeResolutionResult OilTypeResolution_TypeRef ( OilNamespaceDefinition & CurrentNS, OilTypeRef & TypeRef, TypeResolution_TemplateNameList * TemplateNames )
{

	bool VoidType = false;

	OilTypeRef * Ref = & TypeRef;

	while ( ! Ref -> IsDirectType () )
	{

		if ( Ref -> IsVoid () )
		{

			VoidType = true;

			break;

		}

		Ref = Ref -> GetSubType ();

	}

	if ( Ref -> IsTemplated () )
	{

		TypeResolutionResult TemplateResult = OilTypeResolution_TemplateSpecification ( CurrentNS, * Ref -> GetTemplateSpecification (), TemplateNames );

		if ( TemplateResult == kTypeResolutionResult_Success_Complete )
		{

			bool TemplateMismatch = false;

			OilTypeDefinition * ResolvedType = FindTypeDefinition ( * Ref, CurrentNS, TemplateMismatch );

			if ( TemplateMismatch )
			{

				LOG_FATALERROR_NOFILE ( std :: string ( "Template mismatch: template of reference to " ) + CodeConversion :: ConvertUTF32ToUTF8 ( Ref -> GetName () ) + " does not match definition." );

				return kTypeResolutionResult_Failure_TemplateMismatch;

			}

			if ( ResolvedType != NULL )
			{

				Ref -> SetResolvedTypeDefinition ( ResolvedType );

				return kTypeResolutionResult_Success_Complete;

			}
			else
			{

				TemplateMismatch = false;
				OilTraitDefinition * ResolvedTrait = FindTraitDefinition ( * Ref, CurrentNS, TemplateMismatch );

				if ( TemplateMismatch )
				{

					LOG_FATALERROR_NOFILE ( std :: string ( "Template mismatch: reference to template of " ) + CodeConversion :: ConvertUTF32ToUTF8 ( Ref -> GetName () ) + " does not match definition." );

					return kTypeResolutionResult_Failure_TemplateMismatch;

				}

				if ( ResolvedTrait == NULL )
				{

					LOG_FATALERROR_NOFILE ( std :: string ( "Type not found: " ) + CodeConversion :: ConvertUTF32ToUTF8 ( Ref -> GetName () ) );

					return kTypeResolutionResult_Failure_NonExistantType;

				}

				Ref -> SetResolvedTraitDefinition ( ResolvedTrait );

			}

			return kTypeResolutionResult_Success_Complete;

		}

		return TemplateResult;

	}

	bool TemplateMismatch = false;

	OilTypeDefinition * ResolvedType = FindTypeDefinition ( * Ref, CurrentNS, TemplateMismatch );

	if ( TemplateMismatch )
	{

		LOG_FATALERROR_NOFILE ( std :: string ( "Template mismatch: template of reference to " ) + CodeConversion :: ConvertUTF32ToUTF8 ( Ref -> GetName () ) + " does not match definition." );

		return kTypeResolutionResult_Failure_TemplateMismatch;

	}

	if ( ResolvedType != NULL )
	{

		Ref -> SetResolvedTypeDefinition ( ResolvedType );

		return kTypeResolutionResult_Success_Complete;

	}
	else
	{

		TemplateMismatch = false;
		OilTraitDefinition * ResolvedTrait = FindTraitDefinition ( * Ref, CurrentNS, TemplateMismatch );

		if ( TemplateMismatch )
		{

			LOG_FATALERROR_NOFILE ( std :: string ( "Template mismatch: template of reference to " ) + CodeConversion :: ConvertUTF32ToUTF8 ( Ref -> GetName () ) + " does not match definition." );

			return kTypeResolutionResult_Failure_TemplateMismatch;

		}

		if ( ResolvedTrait == NULL )
		{

			if ( TemplateNames != NULL )
			{

				if ( ! ( Ref -> IsNamespaced () || Ref -> IsTemplated () ) )
				{

					for ( uint32_t I = 0; I < TemplateNames -> Count; I ++ )
					{

						if ( Ref -> GetName () == TemplateNames -> Names [ I ] )
						{

							Ref -> SetResolvedTemplateParamName ();

							return kTypeResolutionResult_Success_Complete;

						}

					}

				}

			}

			LOG_FATALERROR_NOFILE ( std :: string ( "Type not found: " ) + CodeConversion :: ConvertUTF32ToUTF8 ( Ref -> GetName () ) );

			return kTypeResolutionResult_Failure_NonExistantType;

		}

		Ref -> SetResolvedTraitDefinition ( ResolvedTrait );

	}

	return kTypeResolutionResult_Success_Complete;

}

TypeResolutionResult OilTypeResolution_TemplateSpecification ( OilNamespaceDefinition & CurrentNS, OilTemplateSpecification & TemplateSpecification, TypeResolution_TemplateNameList * TemplateNames )
{

	bool Unresolved = false;

	uint32_t ResolvedCount = 0;
	uint32_t TypeRefCount = TemplateSpecification.GetTypeRefCount ();

	for ( uint32_t I = 0; I < TypeRefCount; I ++ )
	{

		OilTypeRef * TypeRef = TemplateSpecification.GetTypeRef ( I );

		if ( ! TypeRef -> IsResolved () )
		{

			TypeResolutionResult ResolutionResult = OilTypeResolution_TypeRef ( CurrentNS, * TypeRef, TemplateNames );

			if ( ResolutionResult != kTypeResolutionResult_Success_Complete )
			{

				Unresolved = true;

				if ( ( ResolutionResult == kTypeResolutionResult_Failure_TemplateMismatch ) || ( ResolutionResult == kTypeResolutionResult_Failure_NonExistantType ) )
					return ResolutionResult;

				if ( kTypeResolutionResult_Success_Progress )
					ResolvedCount ++;

			}
			else
				ResolvedCount ++;

		}

	}

	if ( ( ResolvedCount == 0 ) && Unresolved )
		return kTypeResolutionResult_Success_NoProgress;

	if ( Unresolved )
		return kTypeResolutionResult_Success_Progress;

	return kTypeResolutionResult_Success_Complete;

}

TypeResolutionResult OilTypeResolution_TemplateDefinition ( OilNamespaceDefinition & CurrentNS, OilTemplateDefinition & TemplateDefinition )
{

	bool Unresolved = false;

	uint32_t ResolvedCount = 0;
	uint32_t ParamCount = TemplateDefinition.GetTemplateParameterCount ();

	for ( uint32_t I = 0; I < ParamCount; I ++ )
	{

		OilTemplateDefinitionParameter * Param = TemplateDefinition.GetTemplateParameter ( I );

		if ( Param -> IsRestricted () )
		{

			uint32_t RestrictionCount = Param -> GetRestrictionCount ();

			for ( uint32_t J = 0; J < RestrictionCount; J ++ )
			{

				OilTypeRef * RestrictType = Param -> GetRestriction ( J );

				if ( ! RestrictType -> IsResolved () )
				{

					TypeResolutionResult ResolutionResult = OilTypeResolution_TypeRef ( CurrentNS, * RestrictType, NULL );

					if ( ResolutionResult == kTypeResolutionResult_Success_Complete )
					{

						ResolvedCount ++;

						if ( ! RestrictType -> IsResolvedAsTrait () )
						{

							LOG_FATALERROR_NOFILE ( "Template restrictions cannot reference non-trait types" );

							return kTypeResolutionResult_Failure_NonExistantType;

						}

					}
					else if ( ResolutionResult == kTypeResolutionResult_Success_Progress )
					{

						ResolvedCount ++;
						Unresolved = true;

					}
					else if ( ResolutionResult == kTypeResolutionResult_Success_NoProgress )
						Unresolved = true;
					else
						return ResolutionResult;

				}

			}

		}

	}

	if ( Unresolved )
	{

		if ( ResolvedCount > 0 )
			return kTypeResolutionResult_Success_Progress;
		else
			return kTypeResolutionResult_Success_NoProgress;

	}

	return kTypeResolutionResult_Success_Complete;

}

TypeResolutionResult OilResolveTypes_Constants ( OilNamespaceDefinition & CurrentNS )
{

	bool Unresolved = false;
	bool Progress = false;

	uint32_t ConstantCount = CurrentNS.GetConstStatementCount ();

	for ( uint32_t I = 0; I < ConstantCount; I ++ )
	{

		OilConstStatement * Statement = CurrentNS.GetConstStatement ( I );
		OilTypeRef * TypeRef = Statement -> GetType ();

		TypeResolutionResult ResolutionResult = OilTypeResolution_TypeRef ( CurrentNS, * TypeRef );

		if ( ( ResolutionResult == kTypeResolutionResult_Failure_TemplateMismatch ) || ( ResolutionResult == kTypeResolutionResult_Failure_NonExistantType ) )
			return ResolutionResult;

		if ( ResolutionResult == kTypeResolutionResult_Success_Complete )
			Progress = true;
		else if ( ResolutionResult == kTypeResolutionResult_Success_Progress )
		{

			Progress = true;
			Unresolved = true;

		}
		else
			Unresolved = true;

	}

	uint32_t SubNamespaces = CurrentNS.GetSubNamespaceDefinitionCount ();

	for ( uint32_t I = 0; I < SubNamespaces; I ++ )
	{

		TypeResolutionResult ResolutionResult = OilResolveTypes_Constants ( * CurrentNS.GetNamespaceDefinition ( I ) );

		if ( ( ResolutionResult == kTypeResolutionResult_Failure_TemplateMismatch ) || ( ResolutionResult == kTypeResolutionResult_Failure_NonExistantType ) )
			return ResolutionResult;

		if ( ResolutionResult == kTypeResolutionResult_Success_Complete )
			Progress = true;
		else if ( ResolutionResult == kTypeResolutionResult_Success_Progress )
		{

			Progress = true;
			Unresolved = true;

		}
		else
			Unresolved = true;

	}

	if ( Unresolved )
	{

		if ( Progress )
			return kTypeResolutionResult_Success_Progress;
		else
			return kTypeResolutionResult_Success_NoProgress;

	}
	else
		return kTypeResolutionResult_Success_Complete;

}

TypeResolutionResult OilResolveTypes_Bindings ( OilNamespaceDefinition & CurrentNS )
{

	bool Unresolved = false;
	bool Progress = false;

	uint32_t BindingCount = CurrentNS.GetBindingStatementCount ();

	for ( uint32_t I = 0; I < BindingCount; I ++ )
	{

		OilBindingStatement * Statement = CurrentNS.GetBindingStatement ( I );
		OilTypeRef * TypeRef = Statement -> GetType ();

		TypeResolutionResult ResolutionResult = OilTypeResolution_TypeRef ( CurrentNS, * TypeRef );

		if ( ( ResolutionResult == kTypeResolutionResult_Failure_TemplateMismatch ) || ( ResolutionResult == kTypeResolutionResult_Failure_NonExistantType ) )
			return ResolutionResult;

		if ( ResolutionResult == kTypeResolutionResult_Success_Complete )
			Progress = true;
		else if ( ResolutionResult == kTypeResolutionResult_Success_Progress )
		{

			Progress = true;
			Unresolved = true;

		}
		else
			Unresolved = true;

	}

	uint32_t SubNamespaces = CurrentNS.GetSubNamespaceDefinitionCount ();

	for ( uint32_t I = 0; I < SubNamespaces; I ++ )
	{

		TypeResolutionResult ResolutionResult = OilResolveTypes_Bindings ( * CurrentNS.GetNamespaceDefinition ( I ) );

		if ( ResolutionResult == kTypeResolutionResult_Success_Complete )
			Progress = true;
		else if ( ResolutionResult == kTypeResolutionResult_Success_Progress )
		{

			Progress = true;
			Unresolved = true;

		}
		else if ( kTypeResolutionResult_Success_NoProgress )
			Unresolved = true;
		else
			return ResolutionResult;

	}

	if ( Unresolved )
	{

		if ( Progress )
			return kTypeResolutionResult_Success_Progress;
		else
			return kTypeResolutionResult_Success_NoProgress;

	}
	else
		return kTypeResolutionResult_Success_Complete;

}

TypeResolutionResult OilResolveTypes_StructDefinitions ( OilNamespaceDefinition & CurrentNS )
{

	bool Unresolved = false;
	bool Progress = false;

	uint32_t TypeDefCount = CurrentNS.GetTypeDefinitionCount ();

	for ( uint32_t I = 0; I < TypeDefCount; I ++ )
	{

		OilTypeDefinition * TypeDef = CurrentNS.GetTypeDefinition ( I );
		OilStructDefinition * StructDef = NULL;
		OilTemplateDefinition * TemplateDef = NULL;

		if ( TypeDef -> IsBuiltinStructure () )
		{

			OilBuiltinStructDefinition * BuiltinStructDef = TypeDef -> GetBuiltinStructDefinition ();

			if ( ! BuiltinStructDef -> HasUnderlyingStructure () )
				continue;

			StructDef = BuiltinStructDef -> GetUnderlyingStructure ();

			if ( BuiltinStructDef -> IsTemplated () )
				TemplateDef = BuiltinStructDef -> GetTemplateDefinition ();

		}
		else
			StructDef = TypeDef -> GetStructDefinition ();

		if ( StructDef -> IsTemplated () )
			TemplateDef = StructDef -> GetTemplateDefinition ();

		TypeResolution_TemplateNameList TemplateNames;

		if ( TemplateDef != NULL )
		{

			TypeResolutionResult ResolutionResult = OilTypeResolution_TemplateDefinition ( CurrentNS, * TemplateDef );

			if ( ResolutionResult == kTypeResolutionResult_Success_Complete )
				Progress = true;
			else if ( ResolutionResult == kTypeResolutionResult_Success_Progress )
			{

				Progress = true;
				Unresolved = true;

				continue;

			}
			else if ( ResolutionResult == kTypeResolutionResult_Success_NoProgress )
			{

				Unresolved = true;

				continue;

			}
			else
				return ResolutionResult;

			uint32_t NameCount = TemplateDef -> GetTemplateParameterCount ();

			TemplateNames.Names = new std :: u32string [ NameCount ];
			TemplateNames.Count = NameCount;

			for ( uint32_t J = 0; J < NameCount; J ++ )
				TemplateNames.Names [ J ] = TemplateDef -> GetTemplateParameter ( J ) -> GetName ();

		}

		uint32_t StructMemberCount = StructDef -> GetBindingCount ();

		for ( uint32_t J = 0; J < StructMemberCount; J ++ )
		{

			OilStructBinding * Binding = StructDef -> GetBinding ( J );
			OilTypeRef * BindingTypeRef = Binding -> GetTypeRef ();

			if ( BindingTypeRef -> IsResolved () )
				continue;

			TypeResolutionResult ResolutionResult = OilTypeResolution_TypeRef ( CurrentNS, * BindingTypeRef, & TemplateNames );

			if ( ResolutionResult == kTypeResolutionResult_Success_Complete )
				Progress = true;
			else if ( ResolutionResult == kTypeResolutionResult_Success_Progress )
			{

				Progress = true;
				Unresolved = true;

			}
			else if ( ResolutionResult == kTypeResolutionResult_Success_NoProgress )
				Unresolved = true;
			else
			{

				if ( TemplateDef != NULL )
					delete [] TemplateNames.Names;

				return ResolutionResult;

			}

		}

		if ( TemplateDef != NULL )
			delete [] TemplateNames.Names;

	}

	if ( Unresolved )
	{

		if ( Progress )
			return kTypeResolutionResult_Success_Progress;
		else
			return kTypeResolutionResult_Success_NoProgress;

	}

	return kTypeResolutionResult_Success_Complete;

}
<commit_msg>Fixed struct member type resolution to resolve in sub-namespaces<commit_after>#include <EarlyAnalysis/OilTypeResolution.h>

#include <OIL/OilTraversal.h>
#include <OIL/OilNamespaceDefinition.h>
#include <OIL/OilTypeRef.h>
#include <OIL/OilTraitDefinition.h>
#include <OIL/OilTypeDefinition.h>
#include <OIL/OilNamespaceDefinition.h>
#include <OIL/OilConstStatement.h>
#include <OIL/OilBindingStatement.h>
#include <OIL/OilTypeDefinition.h>
#include <OIL/OilStructDefinition.h>
#include <OIL/OilStructBinding.h>
#include <OIL/OilTemplateSpecification.h>
#include <OIL/OilBuiltinStructDefinition.h>
#include <OIL/OilTemplateDefinition.h>
#include <OIL/OilTemplateDefinitionParameter.h>
#include <OIL/OilTemplateDefinition.h>

#include <Logging/Logging.h>
#include <Encoding/CodeConversion.h>

TypeResolutionResult OilTypeResolution_TypeRef ( OilNamespaceDefinition & CurrentNS, OilTypeRef & TypeRef, TypeResolution_TemplateNameList * TemplateNames )
{

	bool VoidType = false;

	OilTypeRef * Ref = & TypeRef;

	while ( ! Ref -> IsDirectType () )
	{

		if ( Ref -> IsVoid () )
		{

			VoidType = true;

			break;

		}

		Ref = Ref -> GetSubType ();

	}

	if ( Ref -> IsTemplated () )
	{

		TypeResolutionResult TemplateResult = OilTypeResolution_TemplateSpecification ( CurrentNS, * Ref -> GetTemplateSpecification (), TemplateNames );

		if ( TemplateResult == kTypeResolutionResult_Success_Complete )
		{

			bool TemplateMismatch = false;

			OilTypeDefinition * ResolvedType = FindTypeDefinition ( * Ref, CurrentNS, TemplateMismatch );

			if ( TemplateMismatch )
			{

				LOG_FATALERROR_NOFILE ( std :: string ( "Template mismatch: template of reference to " ) + CodeConversion :: ConvertUTF32ToUTF8 ( Ref -> GetName () ) + " does not match definition." );

				return kTypeResolutionResult_Failure_TemplateMismatch;

			}

			if ( ResolvedType != NULL )
			{

				Ref -> SetResolvedTypeDefinition ( ResolvedType );

				return kTypeResolutionResult_Success_Complete;

			}
			else
			{

				TemplateMismatch = false;
				OilTraitDefinition * ResolvedTrait = FindTraitDefinition ( * Ref, CurrentNS, TemplateMismatch );

				if ( TemplateMismatch )
				{

					LOG_FATALERROR_NOFILE ( std :: string ( "Template mismatch: reference to template of " ) + CodeConversion :: ConvertUTF32ToUTF8 ( Ref -> GetName () ) + " does not match definition." );

					return kTypeResolutionResult_Failure_TemplateMismatch;

				}

				if ( ResolvedTrait == NULL )
				{

					LOG_FATALERROR_NOFILE ( std :: string ( "Type not found: " ) + CodeConversion :: ConvertUTF32ToUTF8 ( Ref -> GetName () ) );

					return kTypeResolutionResult_Failure_NonExistantType;

				}

				Ref -> SetResolvedTraitDefinition ( ResolvedTrait );

			}

			return kTypeResolutionResult_Success_Complete;

		}

		return TemplateResult;

	}

	bool TemplateMismatch = false;

	OilTypeDefinition * ResolvedType = FindTypeDefinition ( * Ref, CurrentNS, TemplateMismatch );

	if ( TemplateMismatch )
	{

		LOG_FATALERROR_NOFILE ( std :: string ( "Template mismatch: template of reference to " ) + CodeConversion :: ConvertUTF32ToUTF8 ( Ref -> GetName () ) + " does not match definition." );

		return kTypeResolutionResult_Failure_TemplateMismatch;

	}

	if ( ResolvedType != NULL )
	{

		Ref -> SetResolvedTypeDefinition ( ResolvedType );

		return kTypeResolutionResult_Success_Complete;

	}
	else
	{

		TemplateMismatch = false;
		OilTraitDefinition * ResolvedTrait = FindTraitDefinition ( * Ref, CurrentNS, TemplateMismatch );

		if ( TemplateMismatch )
		{

			LOG_FATALERROR_NOFILE ( std :: string ( "Template mismatch: template of reference to " ) + CodeConversion :: ConvertUTF32ToUTF8 ( Ref -> GetName () ) + " does not match definition." );

			return kTypeResolutionResult_Failure_TemplateMismatch;

		}

		if ( ResolvedTrait == NULL )
		{

			if ( TemplateNames != NULL )
			{

				if ( ! ( Ref -> IsNamespaced () || Ref -> IsTemplated () ) )
				{

					for ( uint32_t I = 0; I < TemplateNames -> Count; I ++ )
					{

						if ( Ref -> GetName () == TemplateNames -> Names [ I ] )
						{

							Ref -> SetResolvedTemplateParamName ();

							return kTypeResolutionResult_Success_Complete;

						}

					}

				}

			}

			LOG_FATALERROR_NOFILE ( std :: string ( "Type not found: " ) + CodeConversion :: ConvertUTF32ToUTF8 ( Ref -> GetName () ) );

			return kTypeResolutionResult_Failure_NonExistantType;

		}

		Ref -> SetResolvedTraitDefinition ( ResolvedTrait );

	}

	return kTypeResolutionResult_Success_Complete;

}

TypeResolutionResult OilTypeResolution_TemplateSpecification ( OilNamespaceDefinition & CurrentNS, OilTemplateSpecification & TemplateSpecification, TypeResolution_TemplateNameList * TemplateNames )
{

	bool Unresolved = false;

	uint32_t ResolvedCount = 0;
	uint32_t TypeRefCount = TemplateSpecification.GetTypeRefCount ();

	for ( uint32_t I = 0; I < TypeRefCount; I ++ )
	{

		OilTypeRef * TypeRef = TemplateSpecification.GetTypeRef ( I );

		if ( ! TypeRef -> IsResolved () )
		{

			TypeResolutionResult ResolutionResult = OilTypeResolution_TypeRef ( CurrentNS, * TypeRef, TemplateNames );

			if ( ResolutionResult != kTypeResolutionResult_Success_Complete )
			{

				Unresolved = true;

				if ( ( ResolutionResult == kTypeResolutionResult_Failure_TemplateMismatch ) || ( ResolutionResult == kTypeResolutionResult_Failure_NonExistantType ) )
					return ResolutionResult;

				if ( kTypeResolutionResult_Success_Progress )
					ResolvedCount ++;

			}
			else
				ResolvedCount ++;

		}

	}

	if ( ( ResolvedCount == 0 ) && Unresolved )
		return kTypeResolutionResult_Success_NoProgress;

	if ( Unresolved )
		return kTypeResolutionResult_Success_Progress;

	return kTypeResolutionResult_Success_Complete;

}

TypeResolutionResult OilTypeResolution_TemplateDefinition ( OilNamespaceDefinition & CurrentNS, OilTemplateDefinition & TemplateDefinition )
{

	bool Unresolved = false;

	uint32_t ResolvedCount = 0;
	uint32_t ParamCount = TemplateDefinition.GetTemplateParameterCount ();

	for ( uint32_t I = 0; I < ParamCount; I ++ )
	{

		OilTemplateDefinitionParameter * Param = TemplateDefinition.GetTemplateParameter ( I );

		if ( Param -> IsRestricted () )
		{

			uint32_t RestrictionCount = Param -> GetRestrictionCount ();

			for ( uint32_t J = 0; J < RestrictionCount; J ++ )
			{

				OilTypeRef * RestrictType = Param -> GetRestriction ( J );

				if ( ! RestrictType -> IsResolved () )
				{

					TypeResolutionResult ResolutionResult = OilTypeResolution_TypeRef ( CurrentNS, * RestrictType, NULL );

					if ( ResolutionResult == kTypeResolutionResult_Success_Complete )
					{

						ResolvedCount ++;

						if ( ! RestrictType -> IsResolvedAsTrait () )
						{

							LOG_FATALERROR_NOFILE ( "Template restrictions cannot reference non-trait types" );

							return kTypeResolutionResult_Failure_NonExistantType;

						}

					}
					else if ( ResolutionResult == kTypeResolutionResult_Success_Progress )
					{

						ResolvedCount ++;
						Unresolved = true;

					}
					else if ( ResolutionResult == kTypeResolutionResult_Success_NoProgress )
						Unresolved = true;
					else
						return ResolutionResult;

				}

			}

		}

	}

	if ( Unresolved )
	{

		if ( ResolvedCount > 0 )
			return kTypeResolutionResult_Success_Progress;
		else
			return kTypeResolutionResult_Success_NoProgress;

	}

	return kTypeResolutionResult_Success_Complete;

}

TypeResolutionResult OilResolveTypes_Constants ( OilNamespaceDefinition & CurrentNS )
{

	bool Unresolved = false;
	bool Progress = false;

	uint32_t ConstantCount = CurrentNS.GetConstStatementCount ();

	for ( uint32_t I = 0; I < ConstantCount; I ++ )
	{

		OilConstStatement * Statement = CurrentNS.GetConstStatement ( I );
		OilTypeRef * TypeRef = Statement -> GetType ();

		TypeResolutionResult ResolutionResult = OilTypeResolution_TypeRef ( CurrentNS, * TypeRef );

		if ( ( ResolutionResult == kTypeResolutionResult_Failure_TemplateMismatch ) || ( ResolutionResult == kTypeResolutionResult_Failure_NonExistantType ) )
			return ResolutionResult;

		if ( ResolutionResult == kTypeResolutionResult_Success_Complete )
			Progress = true;
		else if ( ResolutionResult == kTypeResolutionResult_Success_Progress )
		{

			Progress = true;
			Unresolved = true;

		}
		else
			Unresolved = true;

	}

	uint32_t SubNamespaces = CurrentNS.GetSubNamespaceDefinitionCount ();

	for ( uint32_t I = 0; I < SubNamespaces; I ++ )
	{

		TypeResolutionResult ResolutionResult = OilResolveTypes_Constants ( * CurrentNS.GetNamespaceDefinition ( I ) );

		if ( ( ResolutionResult == kTypeResolutionResult_Failure_TemplateMismatch ) || ( ResolutionResult == kTypeResolutionResult_Failure_NonExistantType ) )
			return ResolutionResult;

		if ( ResolutionResult == kTypeResolutionResult_Success_Complete )
			Progress = true;
		else if ( ResolutionResult == kTypeResolutionResult_Success_Progress )
		{

			Progress = true;
			Unresolved = true;

		}
		else
			Unresolved = true;

	}

	if ( Unresolved )
	{

		if ( Progress )
			return kTypeResolutionResult_Success_Progress;
		else
			return kTypeResolutionResult_Success_NoProgress;

	}
	else
		return kTypeResolutionResult_Success_Complete;

}

TypeResolutionResult OilResolveTypes_Bindings ( OilNamespaceDefinition & CurrentNS )
{

	bool Unresolved = false;
	bool Progress = false;

	uint32_t BindingCount = CurrentNS.GetBindingStatementCount ();

	for ( uint32_t I = 0; I < BindingCount; I ++ )
	{

		OilBindingStatement * Statement = CurrentNS.GetBindingStatement ( I );
		OilTypeRef * TypeRef = Statement -> GetType ();

		TypeResolutionResult ResolutionResult = OilTypeResolution_TypeRef ( CurrentNS, * TypeRef );

		if ( ( ResolutionResult == kTypeResolutionResult_Failure_TemplateMismatch ) || ( ResolutionResult == kTypeResolutionResult_Failure_NonExistantType ) )
			return ResolutionResult;

		if ( ResolutionResult == kTypeResolutionResult_Success_Complete )
			Progress = true;
		else if ( ResolutionResult == kTypeResolutionResult_Success_Progress )
		{

			Progress = true;
			Unresolved = true;

		}
		else
			Unresolved = true;

	}

	uint32_t SubNamespaces = CurrentNS.GetSubNamespaceDefinitionCount ();

	for ( uint32_t I = 0; I < SubNamespaces; I ++ )
	{

		TypeResolutionResult ResolutionResult = OilResolveTypes_Bindings ( * CurrentNS.GetNamespaceDefinition ( I ) );

		if ( ResolutionResult == kTypeResolutionResult_Success_Complete )
			Progress = true;
		else if ( ResolutionResult == kTypeResolutionResult_Success_Progress )
		{

			Progress = true;
			Unresolved = true;

		}
		else if ( kTypeResolutionResult_Success_NoProgress )
			Unresolved = true;
		else
			return ResolutionResult;

	}

	if ( Unresolved )
	{

		if ( Progress )
			return kTypeResolutionResult_Success_Progress;
		else
			return kTypeResolutionResult_Success_NoProgress;

	}
	else
		return kTypeResolutionResult_Success_Complete;

}

TypeResolutionResult OilResolveTypes_StructDefinitions ( OilNamespaceDefinition & CurrentNS )
{

	bool Unresolved = false;
	bool Progress = false;

	uint32_t TypeDefCount = CurrentNS.GetTypeDefinitionCount ();

	for ( uint32_t I = 0; I < TypeDefCount; I ++ )
	{

		OilTypeDefinition * TypeDef = CurrentNS.GetTypeDefinition ( I );
		OilStructDefinition * StructDef = NULL;
		OilTemplateDefinition * TemplateDef = NULL;

		if ( TypeDef -> IsBuiltinStructure () )
		{

			OilBuiltinStructDefinition * BuiltinStructDef = TypeDef -> GetBuiltinStructDefinition ();

			if ( ! BuiltinStructDef -> HasUnderlyingStructure () )
				continue;

			StructDef = BuiltinStructDef -> GetUnderlyingStructure ();

			if ( BuiltinStructDef -> IsTemplated () )
				TemplateDef = BuiltinStructDef -> GetTemplateDefinition ();

		}
		else
			StructDef = TypeDef -> GetStructDefinition ();

		if ( StructDef -> IsTemplated () )
			TemplateDef = StructDef -> GetTemplateDefinition ();

		TypeResolution_TemplateNameList TemplateNames;

		if ( TemplateDef != NULL )
		{

			TypeResolutionResult ResolutionResult = OilTypeResolution_TemplateDefinition ( CurrentNS, * TemplateDef );

			if ( ResolutionResult == kTypeResolutionResult_Success_Complete )
				Progress = true;
			else if ( ResolutionResult == kTypeResolutionResult_Success_Progress )
			{

				Progress = true;
				Unresolved = true;

				continue;

			}
			else if ( ResolutionResult == kTypeResolutionResult_Success_NoProgress )
			{

				Unresolved = true;

				continue;

			}
			else
				return ResolutionResult;

			uint32_t NameCount = TemplateDef -> GetTemplateParameterCount ();

			TemplateNames.Names = new std :: u32string [ NameCount ];
			TemplateNames.Count = NameCount;

			for ( uint32_t J = 0; J < NameCount; J ++ )
				TemplateNames.Names [ J ] = TemplateDef -> GetTemplateParameter ( J ) -> GetName ();

		}

		uint32_t StructMemberCount = StructDef -> GetBindingCount ();

		for ( uint32_t J = 0; J < StructMemberCount; J ++ )
		{

			OilStructBinding * Binding = StructDef -> GetBinding ( J );
			OilTypeRef * BindingTypeRef = Binding -> GetTypeRef ();

			if ( BindingTypeRef -> IsResolved () )
				continue;

			TypeResolutionResult ResolutionResult = OilTypeResolution_TypeRef ( CurrentNS, * BindingTypeRef, & TemplateNames );

			if ( ResolutionResult == kTypeResolutionResult_Success_Complete )
				Progress = true;
			else if ( ResolutionResult == kTypeResolutionResult_Success_Progress )
			{

				Progress = true;
				Unresolved = true;

			}
			else if ( ResolutionResult == kTypeResolutionResult_Success_NoProgress )
				Unresolved = true;
			else
			{

				if ( TemplateDef != NULL )
					delete [] TemplateNames.Names;

				return ResolutionResult;

			}

		}

		if ( TemplateDef != NULL )
			delete [] TemplateNames.Names;

	}

	uint32_t SubNSCount = CurrentNS.GetSubNamespaceDefinitionCount ();

	for ( uint32_t I = 0; I < SubNSCount; I ++ )
	{

		TypeResolutionResult ResolutionResult = OilResolveTypes_StructDefinitions ( * CurrentNS.GetNamespaceDefinition ( I ) );

		if ( ResolutionResult == kTypeResolutionResult_Success_Complete )
			Progress = true;
		else if ( ResolutionResult == kTypeResolutionResult_Success_Progress )
		{

			Progress = true;
			Unresolved = true;

		}
		else if ( ResolutionResult == kTypeResolutionResult_Success_NoProgress )
			Unresolved = true;
		else
			return ResolutionResult;

	}

	if ( Unresolved )
	{

		if ( Progress )
			return kTypeResolutionResult_Success_Progress;
		else
			return kTypeResolutionResult_Success_NoProgress;

	}

	return kTypeResolutionResult_Success_Complete;

}
<|endoftext|>


<commit_before>// this function computes the hubbard contribution to the hamiltonian
// and add it to ophi.

// the S matrix is already applied to phi_i

void apply_hubbard_potential(K_point& kp,
                             const int idx__,
                             const int n__,
                             Wave_functions& phi,
                             Wave_functions& ophi)
{
    auto &hub_wf = kp.hubbard_wave_functions();
    // First calculate the local part of the projections
    // dm(i, n)  = <phi_i | psi_{nk}>

    // for colinear magnetism the wavefunctions of the up and down block
    // are stored in the up and down part of the "spinor" so we
    // calculate Overlap ^ up = <phi_i^up | phi_j^up> stored in the
    // first half of dm the down part in the other half

    // the overlaps are then contiguous
    int Nfc = 1;
    if (ctx_.num_mag_dims() == 1)
        Nfc *= 2;

    dmatrix<double_complex> dm(this->number_of_hubbard_orbitals(),
                               n__ * Nfc);

    dm.zero();

    if (ctx_.num_mag_dims() == 3) {
        inner(ctx_.processing_unit(),
              2,
              hub_wf,
              0,
              this->number_of_hubbard_orbitals(),
              phi,
              idx__,
              n__,
              dm,
              0,
              0);

    } else {
        // compute the overlaps
        for (int ispn = 0; ispn < ctx_.num_spins(); ispn++) {
            inner(ctx_.processing_unit(),
                  ispn,
                  hub_wf,
                  0,
                  this->number_of_hubbard_orbitals(),
                  phi,
                  idx__,
                  n__,
                  dm,
                  0,
                  ispn * n__);
        }
    }

    for (int ia = 0; ia < ctx_.unit_cell().num_atoms(); ++ia) {
        const auto& atom = ctx_.unit_cell().atom(ia);
        const int lmax_at = 2 * atom.type().hubbard_l() + 1;
        if (atom.type().hubbard_correction()) {
            // we apply the hubbard correction. For now I have no papers
            // giving me the formula for the SO case so I rely on QE for it
            // but I do not like it at all
            if (ctx_.num_mag_dims() == 3) {
                dmatrix<double_complex> Up(lmax_at * ctx_.num_spins(), n__);
                Up.zero();
                for (int s1 = 0; s1 < ctx_.num_spins(); s1++) {
                    for (int s2 = 0; s2 < ctx_.num_spins(); s2++) {
                        const int ind = (s1 == s2) * s1 + (1 + 2 * s2 + s1) * (s1 != s2);
                        linalg<CPU>::gemm(0, 0,
                                          lmax_at,
                                          n__,
                                          lmax_at,
                                          linalg_const<double_complex>::one(),
                                          this->hubbard_potential_.template at<CPU>(0, 0, ind, ia, 0),
                                          this->hubbard_potential_.ld(),
                                          dm.template at<CPU>(this->offset[ia] + s2 * lmax_at, 0),
                                          dm.ld(),
                                          linalg_const<double_complex>::one(),
                                          Up.template at<CPU>(s1 * lmax_at, 0), Up.ld());
                    }
                }

                transform<double_complex>(ctx_.processing_unit(),
                                          2,
                                          1.0,
                                          hub_wf,
                                          this->offset[ia],
                                          2 * lmax_at,
                                          Up,
                                          0,
                                          0,
                                          1.0,
                                          ophi,
                                          idx__,
                                          n__);
            } else {
                //Conventional LDA or colinear magnetism
                dmatrix<double_complex> Up(lmax_at, n__);
                for (int ispn = 0; ispn < ctx_.num_spins(); ispn++) {
                    Up.zero();
                    linalg<CPU>::gemm(0, 0,
                                      lmax_at,
                                      n__,
                                      lmax_at,
                                      linalg_const<double_complex>::one(),
                                      this->hubbard_potential_.template at<CPU>(0, 0, ispn, ia, 0),
                                      this->hubbard_potential_.ld(),
                                      dm.template at<CPU>(this->offset[ia], ispn * n__),
                                      dm.ld(),
                                      linalg_const<double_complex>::one(),
                                      Up.template at<CPU>(0, 0),
                                      Up.ld());

                    transform<double_complex>(ctx_.processing_unit(),
                                              ispn,
                                              1.0,
                                              hub_wf,
                                              this->offset[ia],
                                              lmax_at,
                                              Up,
                                              0,
                                              0,
                                              1.0,
                                              ophi,
                                              idx__,
                                              n__);
                }
            }
        }
    }
}
<commit_msg>Allocate memory on GPU for overlap matrices<commit_after>// this function computes the hubbard contribution to the hamiltonian
// and add it to ophi.

// the S matrix is already applied to phi_i

void apply_hubbard_potential(K_point& kp,
                             const int idx__,
                             const int n__,
                             Wave_functions& phi,
                             Wave_functions& ophi)
{
    auto &hub_wf = kp.hubbard_wave_functions();
    // First calculate the local part of the projections
    // dm(i, n)  = <phi_i | psi_{nk}>

    // for colinear magnetism the wavefunctions of the up and down block
    // are stored in the up and down part of the "spinor" so we
    // calculate Overlap ^ up = <phi_i^up | phi_j^up> stored in the
    // first half of dm the down part in the other half

    // the overlaps are then contiguous
    int Nfc = 1;
    if (ctx_.num_mag_dims() == 1)
        Nfc *= 2;

    dmatrix<double_complex> dm(this->number_of_hubbard_orbitals(), n__ * Nfc);

    dm.zero();
    dm.allocate_on_device();

    if (ctx_.num_mag_dims() == 3) {
        inner(ctx_.processing_unit(),
              2,
              hub_wf,
              0,
              this->number_of_hubbard_orbitals(),
              phi,
              idx__,
              n__,
              dm,
              0,
              0);

    } else {
        // compute the overlaps
        for (int ispn = 0; ispn < ctx_.num_spins(); ispn++) {
            inner(ctx_.processing_unit(),
                  ispn,
                  hub_wf,
                  0,
                  this->number_of_hubbard_orbitals(),
                  phi,
                  idx__,
                  n__,
                  dm,
                  0,
                  ispn * n__);
        }
    }

    dm.deallocate_on_device();

    for (int ia = 0; ia < ctx_.unit_cell().num_atoms(); ++ia) {
        const auto& atom = ctx_.unit_cell().atom(ia);
        const int lmax_at = 2 * atom.type().hubbard_l() + 1;
        if (atom.type().hubbard_correction()) {
            // we apply the hubbard correction. For now I have no papers
            // giving me the formula for the SO case so I rely on QE for it
            // but I do not like it at all
            if (ctx_.num_mag_dims() == 3) {
                dmatrix<double_complex> Up(lmax_at * ctx_.num_spins(), n__);
                Up.zero();
                for (int s1 = 0; s1 < ctx_.num_spins(); s1++) {
                    for (int s2 = 0; s2 < ctx_.num_spins(); s2++) {
                        const int ind = (s1 == s2) * s1 + (1 + 2 * s2 + s1) * (s1 != s2);
                        linalg<CPU>::gemm(0, 0,
                                          lmax_at,
                                          n__,
                                          lmax_at,
                                          linalg_const<double_complex>::one(),
                                          this->hubbard_potential_.template at<CPU>(0, 0, ind, ia, 0),
                                          this->hubbard_potential_.ld(),
                                          dm.template at<CPU>(this->offset[ia] + s2 * lmax_at, 0),
                                          dm.ld(),
                                          linalg_const<double_complex>::one(),
                                          Up.template at<CPU>(s1 * lmax_at, 0), Up.ld());
                    }
                }

                transform<double_complex>(ctx_.processing_unit(),
                                          2,
                                          1.0,
                                          hub_wf,
                                          this->offset[ia],
                                          2 * lmax_at,
                                          Up,
                                          0,
                                          0,
                                          1.0,
                                          ophi,
                                          idx__,
                                          n__);
            } else {
                //Conventional LDA or colinear magnetism
                dmatrix<double_complex> Up(lmax_at, n__);
                for (int ispn = 0; ispn < ctx_.num_spins(); ispn++) {
                    Up.zero();
                    linalg<CPU>::gemm(0, 0,
                                      lmax_at,
                                      n__,
                                      lmax_at,
                                      linalg_const<double_complex>::one(),
                                      this->hubbard_potential_.template at<CPU>(0, 0, ispn, ia, 0),
                                      this->hubbard_potential_.ld(),
                                      dm.template at<CPU>(this->offset[ia], ispn * n__),
                                      dm.ld(),
                                      linalg_const<double_complex>::one(),
                                      Up.template at<CPU>(0, 0),
                                      Up.ld());

                    transform<double_complex>(ctx_.processing_unit(),
                                              ispn,
                                              1.0,
                                              hub_wf,
                                              this->offset[ia],
                                              lmax_at,
                                              Up,
                                              0,
                                              0,
                                              1.0,
                                              ophi,
                                              idx__,
                                              n__);
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>/*
    This file is part of Magnum.

    Copyright © 2010, 2011, 2012, 2013, 2014, 2015
              Vladimír Vondruš <mosra@centrum.cz>

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included
    in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.
*/

#include <Corrade/TestSuite/Compare/Container.h>

#include "Magnum/Buffer.h"
#include "Magnum/BufferTexture.h"
#include "Magnum/Test/AbstractOpenGLTester.h"

namespace Magnum { namespace Test {

struct BufferTextureGLTest: AbstractOpenGLTester {
    explicit BufferTextureGLTest();

    void construct();
    void wrap();

    void bind();
    void setBuffer();
    void setBufferOffset();
};

BufferTextureGLTest::BufferTextureGLTest() {
    addTests({&BufferTextureGLTest::construct,
              &BufferTextureGLTest::wrap,

              &BufferTextureGLTest::bind,
              &BufferTextureGLTest::setBuffer,
              &BufferTextureGLTest::setBufferOffset});
}

void BufferTextureGLTest::construct() {
    if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_buffer_object>())
        CORRADE_SKIP(Extensions::GL::ARB::texture_buffer_object::string() + std::string(" is not supported."));

    {
        BufferTexture texture;

        MAGNUM_VERIFY_NO_ERROR();
        CORRADE_VERIFY(texture.id() > 0);
    }

    MAGNUM_VERIFY_NO_ERROR();
}

void BufferTextureGLTest::wrap() {
    if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_buffer_object>())
        CORRADE_SKIP(Extensions::GL::ARB::texture_buffer_object::string() + std::string(" is not supported."));

    GLuint id;
    glGenTextures(1, &id);

    /* Releasing won't delete anything */
    {
        auto texture = BufferTexture::wrap(id, ObjectFlag::DeleteOnDestruction);
        CORRADE_COMPARE(texture.release(), id);
    }

    /* ...so we can wrap it again */
    BufferTexture::wrap(id);
    glDeleteTextures(1, &id);
}

void BufferTextureGLTest::bind() {
    if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_buffer_object>())
        CORRADE_SKIP(Extensions::GL::ARB::texture_buffer_object::string() + std::string(" is not supported."));

    BufferTexture texture;
    texture.bind(15);

    MAGNUM_VERIFY_NO_ERROR();

    AbstractTexture::unbind(15);

    MAGNUM_VERIFY_NO_ERROR();

    AbstractTexture::bind(7, {&texture, nullptr, &texture});

    MAGNUM_VERIFY_NO_ERROR();

    AbstractTexture::unbind(7, 3);

    MAGNUM_VERIFY_NO_ERROR();
}

void BufferTextureGLTest::setBuffer() {
    if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_buffer_object>())
        CORRADE_SKIP(Extensions::GL::ARB::texture_buffer_object::string() + std::string(" is not supported."));

    BufferTexture texture;
    Buffer buffer;
    constexpr UnsignedByte data[] = {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
    };
    buffer.setData(data, BufferUsage::StaticDraw);
    texture.setBuffer(BufferTextureFormat::R8UI, buffer);

    MAGNUM_VERIFY_NO_ERROR();
}

void BufferTextureGLTest::setBufferOffset() {
    if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_buffer_object>())
        CORRADE_SKIP(Extensions::GL::ARB::texture_buffer_object::string() + std::string(" is not supported."));

    /* Check that we have correct offset alignment */
    CORRADE_INTERNAL_ASSERT(256 % BufferTexture::offsetAlignment() == 0);

    BufferTexture texture;
    Buffer buffer;
    constexpr UnsignedByte data[] = {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
        0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
    };
    buffer.setData({nullptr, 1024}, BufferUsage::StaticDraw);
    buffer.setSubData(256 - 16, data);
    texture.setBuffer(BufferTextureFormat::R8UI, buffer, 256, 8);

    MAGNUM_VERIFY_NO_ERROR();
}

}}

CORRADE_TEST_MAIN(Magnum::Test::BufferTextureGLTest)
<commit_msg>Properly check extensions in BufferTextureGLTest.<commit_after>/*
    This file is part of Magnum.

    Copyright © 2010, 2011, 2012, 2013, 2014, 2015
              Vladimír Vondruš <mosra@centrum.cz>

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included
    in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.
*/

#include <Corrade/TestSuite/Compare/Container.h>

#include "Magnum/Buffer.h"
#include "Magnum/BufferTexture.h"
#include "Magnum/Test/AbstractOpenGLTester.h"

namespace Magnum { namespace Test {

struct BufferTextureGLTest: AbstractOpenGLTester {
    explicit BufferTextureGLTest();

    void construct();
    void wrap();

    void bind();
    void setBuffer();
    void setBufferOffset();
};

BufferTextureGLTest::BufferTextureGLTest() {
    addTests({&BufferTextureGLTest::construct,
              &BufferTextureGLTest::wrap,

              &BufferTextureGLTest::bind,
              &BufferTextureGLTest::setBuffer,
              &BufferTextureGLTest::setBufferOffset});
}

void BufferTextureGLTest::construct() {
    if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_buffer_object>())
        CORRADE_SKIP(Extensions::GL::ARB::texture_buffer_object::string() + std::string(" is not supported."));

    {
        BufferTexture texture;

        MAGNUM_VERIFY_NO_ERROR();
        CORRADE_VERIFY(texture.id() > 0);
    }

    MAGNUM_VERIFY_NO_ERROR();
}

void BufferTextureGLTest::wrap() {
    if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_buffer_object>())
        CORRADE_SKIP(Extensions::GL::ARB::texture_buffer_object::string() + std::string(" is not supported."));

    GLuint id;
    glGenTextures(1, &id);

    /* Releasing won't delete anything */
    {
        auto texture = BufferTexture::wrap(id, ObjectFlag::DeleteOnDestruction);
        CORRADE_COMPARE(texture.release(), id);
    }

    /* ...so we can wrap it again */
    BufferTexture::wrap(id);
    glDeleteTextures(1, &id);
}

void BufferTextureGLTest::bind() {
    if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_buffer_object>())
        CORRADE_SKIP(Extensions::GL::ARB::texture_buffer_object::string() + std::string(" is not supported."));

    BufferTexture texture;
    texture.bind(15);

    MAGNUM_VERIFY_NO_ERROR();

    AbstractTexture::unbind(15);

    MAGNUM_VERIFY_NO_ERROR();

    AbstractTexture::bind(7, {&texture, nullptr, &texture});

    MAGNUM_VERIFY_NO_ERROR();

    AbstractTexture::unbind(7, 3);

    MAGNUM_VERIFY_NO_ERROR();
}

void BufferTextureGLTest::setBuffer() {
    if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_buffer_object>())
        CORRADE_SKIP(Extensions::GL::ARB::texture_buffer_object::string() + std::string(" is not supported."));

    BufferTexture texture;
    Buffer buffer;
    constexpr UnsignedByte data[] = {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
    };
    buffer.setData(data, BufferUsage::StaticDraw);
    texture.setBuffer(BufferTextureFormat::R8UI, buffer);

    MAGNUM_VERIFY_NO_ERROR();
}

void BufferTextureGLTest::setBufferOffset() {
    if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_buffer_object>())
        CORRADE_SKIP(Extensions::GL::ARB::texture_buffer_object::string() + std::string(" is not supported."));
    if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::texture_buffer_range>())
        CORRADE_SKIP(Extensions::GL::ARB::texture_buffer_range::string() + std::string(" is not supported."));

    /* Check that we have correct offset alignment */
    CORRADE_INTERNAL_ASSERT(256 % BufferTexture::offsetAlignment() == 0);

    BufferTexture texture;
    Buffer buffer;
    constexpr UnsignedByte data[] = {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
        0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
    };
    buffer.setData({nullptr, 1024}, BufferUsage::StaticDraw);
    buffer.setSubData(256 - 16, data);
    texture.setBuffer(BufferTextureFormat::R8UI, buffer, 256, 8);

    MAGNUM_VERIFY_NO_ERROR();
}

}}

CORRADE_TEST_MAIN(Magnum::Test::BufferTextureGLTest)
<|endoftext|>


<commit_before>/*
    This file is part of Magnum.

    Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016
              Vladimír Vondruš <mosra@centrum.cz>

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included
    in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.
*/

#include <sstream>
#include <Corrade/TestSuite/Tester.h>

#include "Magnum/AbstractResourceLoader.h"
#include "Magnum/ResourceManager.h"

namespace Magnum { namespace Test {

struct ResourceManagerTest: TestSuite::Tester {
    explicit ResourceManagerTest();

    void state();
    void stateFallback();
    void stateDisallowed();
    void basic();
    void residentPolicy();
    void referenceCountedPolicy();
    void manualPolicy();
    void defaults();
    void clear();
    void clearWhileReferenced();
    void loader();
};

struct Data {
    static std::size_t count;

    explicit Data() { ++count; }
    ~Data() { --count; }
};

typedef Magnum::ResourceManager<Int, Data> ResourceManager;

size_t Data::count = 0;

ResourceManagerTest::ResourceManagerTest() {
    addTests({&ResourceManagerTest::state,
              &ResourceManagerTest::stateFallback,
              &ResourceManagerTest::stateDisallowed,
              &ResourceManagerTest::basic,
              &ResourceManagerTest::residentPolicy,
              &ResourceManagerTest::referenceCountedPolicy,
              &ResourceManagerTest::manualPolicy,
              &ResourceManagerTest::defaults,
              &ResourceManagerTest::clear,
              &ResourceManagerTest::clearWhileReferenced,
              &ResourceManagerTest::loader});
}

void ResourceManagerTest::state() {
    ResourceManager rm;

    Resource<Data> data = rm.get<Data>("data");
    CORRADE_VERIFY(!data);
    CORRADE_COMPARE(data.state(), ResourceState::NotLoaded);
    CORRADE_COMPARE(rm.state<Data>("data"), ResourceState::NotLoaded);

    rm.set<Data>("data", nullptr, ResourceDataState::Loading, ResourcePolicy::Resident);
    CORRADE_VERIFY(!data);
    CORRADE_COMPARE(data.state(), ResourceState::Loading);
    CORRADE_COMPARE(rm.state<Data>("data"), ResourceState::Loading);

    rm.set<Data>("data", nullptr, ResourceDataState::NotFound, ResourcePolicy::Resident);
    CORRADE_VERIFY(!data);
    CORRADE_COMPARE(data.state(), ResourceState::NotFound);
    CORRADE_COMPARE(rm.state<Data>("data"), ResourceState::NotFound);

    /* Nothing happened at all */
    CORRADE_COMPARE(Data::count, 0);
}

void ResourceManagerTest::stateFallback() {
    {
        ResourceManager rm;
        rm.setFallback(new Data);

        Resource<Data> data = rm.get<Data>("data");
        CORRADE_VERIFY(data);
        CORRADE_COMPARE(data.state(), ResourceState::NotLoadedFallback);
        CORRADE_COMPARE(rm.state<Data>("data"), ResourceState::NotLoadedFallback);

        rm.set<Data>("data", nullptr, ResourceDataState::Loading, ResourcePolicy::Resident);
        CORRADE_VERIFY(data);
        CORRADE_COMPARE(data.state(), ResourceState::LoadingFallback);
        CORRADE_COMPARE(rm.state<Data>("data"), ResourceState::LoadingFallback);

        rm.set<Data>("data", nullptr, ResourceDataState::NotFound, ResourcePolicy::Resident);
        CORRADE_VERIFY(data);
        CORRADE_COMPARE(data.state(), ResourceState::NotFoundFallback);
        CORRADE_COMPARE(rm.state<Data>("data"), ResourceState::NotFoundFallback);

        /* Only fallback is here */
        CORRADE_COMPARE(Data::count, 1);
    }

    /* Fallback gets destroyed */
    CORRADE_COMPARE(Data::count, 0);
}

void ResourceManagerTest::stateDisallowed() {
    ResourceManager rm;

    std::ostringstream out;
    Error redirectError{&out};

    rm.set("data", Data(), ResourceDataState::Loading, ResourcePolicy::Resident);
    CORRADE_COMPARE(out.str(), "ResourceManager::set(): data should be null if and only if state is NotFound or Loading\n");

    out.str({});
    rm.set<Data>("data", nullptr, ResourceDataState::Final, ResourcePolicy::Resident);
    CORRADE_COMPARE(out.str(), "ResourceManager::set(): data should be null if and only if state is NotFound or Loading\n");
}

void ResourceManagerTest::basic() {
    ResourceManager rm;

    /* One mutable, one final */
    ResourceKey questionKey("the-question");
    ResourceKey answerKey("the-answer");
    rm.set(questionKey, 10, ResourceDataState::Mutable, ResourcePolicy::Resident);
    rm.set(answerKey, 42, ResourceDataState::Final, ResourcePolicy::Resident);
    Resource<Int> theQuestion = rm.get<Int>(questionKey);
    Resource<Int> theAnswer = rm.get<Int>(answerKey);

    /* Check basic functionality */
    CORRADE_COMPARE(theQuestion.state(), ResourceState::Mutable);
    CORRADE_COMPARE(theAnswer.state(), ResourceState::Final);
    CORRADE_COMPARE(*theQuestion, 10);
    CORRADE_COMPARE(*theAnswer, 42);
    CORRADE_COMPARE(rm.count<Int>(), 2);

    /* Cannot change already final resource */
    std::ostringstream out;
    Error redirectError{&out};
    rm.set(answerKey, 43, ResourceDataState::Mutable, ResourcePolicy::Resident);
    CORRADE_COMPARE(*theAnswer, 42);
    CORRADE_COMPARE(out.str(), "ResourceManager::set(): cannot change already final resource " + answerKey.hexString() + '\n');

    /* But non-final can be changed */
    rm.set(questionKey, 20, ResourceDataState::Final, ResourcePolicy::Resident);
    CORRADE_COMPARE(theQuestion.state(), ResourceState::Final);
    CORRADE_COMPARE(*theQuestion, 20);
}

void ResourceManagerTest::residentPolicy() {
    ResourceManager* rm = new ResourceManager;

    rm->set("blah", new Data, ResourceDataState::Mutable, ResourcePolicy::Resident);
    CORRADE_COMPARE(Data::count, 1);

    rm->free();
    CORRADE_COMPARE(Data::count, 1);

    delete rm;
    CORRADE_COMPARE(Data::count, 0);
}

void ResourceManagerTest::referenceCountedPolicy() {
    ResourceManager rm;

    ResourceKey dataRefCountKey("dataRefCount");

    /* Resource is deleted after all references are removed */
    rm.set(dataRefCountKey, new Data, ResourceDataState::Final, ResourcePolicy::ReferenceCounted);
    CORRADE_COMPARE(rm.count<Data>(), 1);
    {
        Resource<Data> data = rm.get<Data>(dataRefCountKey);
        CORRADE_COMPARE(data.state(), ResourceState::Final);
        CORRADE_COMPARE(Data::count, 1);
    }

    CORRADE_COMPARE(rm.count<Data>(), 0);
    CORRADE_COMPARE(Data::count, 0);

    /* Reference counted resources which were not used once will stay loaded
       until free() is called */
    rm.set(dataRefCountKey, new Data, ResourceDataState::Final, ResourcePolicy::ReferenceCounted);
    CORRADE_COMPARE(rm.count<Data>(), 1);
    CORRADE_COMPARE(rm.state<Data>(dataRefCountKey), ResourceState::Final);
    CORRADE_COMPARE(rm.referenceCount<Data>(dataRefCountKey), 0);

    rm.free<Data>();
    CORRADE_COMPARE(rm.count<Data>(), 0);
    CORRADE_COMPARE(rm.state<Data>(dataRefCountKey), ResourceState::NotLoaded);
    CORRADE_COMPARE(rm.referenceCount<Data>(dataRefCountKey), 0);
}

void ResourceManagerTest::manualPolicy() {
    ResourceManager rm;

    ResourceKey dataKey("data");

    /* Manual free */
    {
        rm.set(dataKey, new Data, ResourceDataState::Mutable, ResourcePolicy::Manual);
        Resource<Data> data = rm.get<Data>(dataKey);
        rm.free();
    }

    CORRADE_COMPARE(rm.count<Data>(), 1);
    CORRADE_COMPARE(Data::count, 1);
    rm.free();
    CORRADE_COMPARE(rm.count<Data>(), 0);
    CORRADE_COMPARE(Data::count, 0);

    rm.set(dataKey, new Data, ResourceDataState::Mutable, ResourcePolicy::Manual);
    CORRADE_COMPARE(rm.count<Data>(), 1);
    CORRADE_COMPARE(Data::count, 1);
}

void ResourceManagerTest::defaults() {
    ResourceManager rm;
    rm.set("data", new Data);
    CORRADE_COMPARE(rm.state<Data>("data"), ResourceState::Final);
}

void ResourceManagerTest::clear() {
    ResourceManager rm;

    rm.set("blah", new Data);
    CORRADE_COMPARE(Data::count, 1);

    rm.free();
    CORRADE_COMPARE(Data::count, 1);

    rm.clear();
    CORRADE_COMPARE(Data::count, 0);
}

void ResourceManagerTest::clearWhileReferenced() {
    /* Should cover also the destruction case */

    std::ostringstream out;
    Error redirectError{&out};

    ResourceManager rm;
    rm.set("blah", Int());
    /** @todo this will leak, is there any better solution without hitting
        assertion in decrementReferenceCount()? */
    new Resource<Int>(rm.get<Int>("blah"));

    rm.clear();
    CORRADE_COMPARE(out.str(), "ResourceManager: cleared/destroyed while data are still referenced\n");
}

void ResourceManagerTest::loader() {
    class IntResourceLoader: public AbstractResourceLoader<Int> {
        public:
            IntResourceLoader(): resource(ResourceManager::instance().get<Data>("data")) {}

            void load() {
                set("hello", 773, ResourceDataState::Final, ResourcePolicy::Resident);
                setNotFound("world");
            }

        private:
            void doLoad(ResourceKey) override {}

            std::string doName(ResourceKey key) const override {
                if(key == ResourceKey("hello")) return "hello";
                return "";
            }

            /* To verify that the loader is destroyed before unloading
               _all types of_ resources */
            Resource<Data> resource;
    };

    auto rm = new ResourceManager;
    auto loader = new IntResourceLoader;
    rm->setLoader(loader);

    {
        Resource<Data> data = rm->get<Data>("data");
        Resource<Int> hello = rm->get<Int>("hello");
        Resource<Int> world = rm->get<Int>("world");
        CORRADE_COMPARE(data.state(), ResourceState::NotLoaded);
        CORRADE_COMPARE(hello.state(), ResourceState::Loading);
        CORRADE_COMPARE(world.state(), ResourceState::Loading);

        CORRADE_COMPARE(loader->requestedCount(), 2);
        CORRADE_COMPARE(loader->loadedCount(), 0);
        CORRADE_COMPARE(loader->notFoundCount(), 0);
        CORRADE_COMPARE(loader->name(ResourceKey("hello")), "hello");

        loader->load();
        CORRADE_COMPARE(hello.state(), ResourceState::Final);
        CORRADE_COMPARE(*hello, 773);
        CORRADE_COMPARE(world.state(), ResourceState::NotFound);

        CORRADE_COMPARE(loader->requestedCount(), 2);
        CORRADE_COMPARE(loader->loadedCount(), 1);
        CORRADE_COMPARE(loader->notFoundCount(), 1);

        /* Verify that the loader is deleted at proper time */
        rm->set("data", new Data);
        CORRADE_COMPARE(Data::count, 1);
    }

    delete rm;
    CORRADE_COMPARE(Data::count, 0);
}

}}

CORRADE_TEST_MAIN(Magnum::Test::ResourceManagerTest)
<commit_msg>Test ResourceState debug output.<commit_after>/*
    This file is part of Magnum.

    Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016
              Vladimír Vondruš <mosra@centrum.cz>

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included
    in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.
*/

#include <sstream>
#include <Corrade/TestSuite/Tester.h>

#include "Magnum/AbstractResourceLoader.h"
#include "Magnum/ResourceManager.h"

namespace Magnum { namespace Test {

struct ResourceManagerTest: TestSuite::Tester {
    explicit ResourceManagerTest();

    void state();
    void stateFallback();
    void stateDisallowed();
    void basic();
    void residentPolicy();
    void referenceCountedPolicy();
    void manualPolicy();
    void defaults();
    void clear();
    void clearWhileReferenced();
    void loader();

    void debugResourceState();
};

struct Data {
    static std::size_t count;

    explicit Data() { ++count; }
    ~Data() { --count; }
};

typedef Magnum::ResourceManager<Int, Data> ResourceManager;

size_t Data::count = 0;

ResourceManagerTest::ResourceManagerTest() {
    addTests({&ResourceManagerTest::state,
              &ResourceManagerTest::stateFallback,
              &ResourceManagerTest::stateDisallowed,
              &ResourceManagerTest::basic,
              &ResourceManagerTest::residentPolicy,
              &ResourceManagerTest::referenceCountedPolicy,
              &ResourceManagerTest::manualPolicy,
              &ResourceManagerTest::defaults,
              &ResourceManagerTest::clear,
              &ResourceManagerTest::clearWhileReferenced,
              &ResourceManagerTest::loader,

              &ResourceManagerTest::debugResourceState});
}

void ResourceManagerTest::state() {
    ResourceManager rm;

    Resource<Data> data = rm.get<Data>("data");
    CORRADE_VERIFY(!data);
    CORRADE_COMPARE(data.state(), ResourceState::NotLoaded);
    CORRADE_COMPARE(rm.state<Data>("data"), ResourceState::NotLoaded);

    rm.set<Data>("data", nullptr, ResourceDataState::Loading, ResourcePolicy::Resident);
    CORRADE_VERIFY(!data);
    CORRADE_COMPARE(data.state(), ResourceState::Loading);
    CORRADE_COMPARE(rm.state<Data>("data"), ResourceState::Loading);

    rm.set<Data>("data", nullptr, ResourceDataState::NotFound, ResourcePolicy::Resident);
    CORRADE_VERIFY(!data);
    CORRADE_COMPARE(data.state(), ResourceState::NotFound);
    CORRADE_COMPARE(rm.state<Data>("data"), ResourceState::NotFound);

    /* Nothing happened at all */
    CORRADE_COMPARE(Data::count, 0);
}

void ResourceManagerTest::stateFallback() {
    {
        ResourceManager rm;
        rm.setFallback(new Data);

        Resource<Data> data = rm.get<Data>("data");
        CORRADE_VERIFY(data);
        CORRADE_COMPARE(data.state(), ResourceState::NotLoadedFallback);
        CORRADE_COMPARE(rm.state<Data>("data"), ResourceState::NotLoadedFallback);

        rm.set<Data>("data", nullptr, ResourceDataState::Loading, ResourcePolicy::Resident);
        CORRADE_VERIFY(data);
        CORRADE_COMPARE(data.state(), ResourceState::LoadingFallback);
        CORRADE_COMPARE(rm.state<Data>("data"), ResourceState::LoadingFallback);

        rm.set<Data>("data", nullptr, ResourceDataState::NotFound, ResourcePolicy::Resident);
        CORRADE_VERIFY(data);
        CORRADE_COMPARE(data.state(), ResourceState::NotFoundFallback);
        CORRADE_COMPARE(rm.state<Data>("data"), ResourceState::NotFoundFallback);

        /* Only fallback is here */
        CORRADE_COMPARE(Data::count, 1);
    }

    /* Fallback gets destroyed */
    CORRADE_COMPARE(Data::count, 0);
}

void ResourceManagerTest::stateDisallowed() {
    ResourceManager rm;

    std::ostringstream out;
    Error redirectError{&out};

    rm.set("data", Data(), ResourceDataState::Loading, ResourcePolicy::Resident);
    CORRADE_COMPARE(out.str(), "ResourceManager::set(): data should be null if and only if state is NotFound or Loading\n");

    out.str({});
    rm.set<Data>("data", nullptr, ResourceDataState::Final, ResourcePolicy::Resident);
    CORRADE_COMPARE(out.str(), "ResourceManager::set(): data should be null if and only if state is NotFound or Loading\n");
}

void ResourceManagerTest::basic() {
    ResourceManager rm;

    /* One mutable, one final */
    ResourceKey questionKey("the-question");
    ResourceKey answerKey("the-answer");
    rm.set(questionKey, 10, ResourceDataState::Mutable, ResourcePolicy::Resident);
    rm.set(answerKey, 42, ResourceDataState::Final, ResourcePolicy::Resident);
    Resource<Int> theQuestion = rm.get<Int>(questionKey);
    Resource<Int> theAnswer = rm.get<Int>(answerKey);

    /* Check basic functionality */
    CORRADE_COMPARE(theQuestion.state(), ResourceState::Mutable);
    CORRADE_COMPARE(theAnswer.state(), ResourceState::Final);
    CORRADE_COMPARE(*theQuestion, 10);
    CORRADE_COMPARE(*theAnswer, 42);
    CORRADE_COMPARE(rm.count<Int>(), 2);

    /* Cannot change already final resource */
    std::ostringstream out;
    Error redirectError{&out};
    rm.set(answerKey, 43, ResourceDataState::Mutable, ResourcePolicy::Resident);
    CORRADE_COMPARE(*theAnswer, 42);
    CORRADE_COMPARE(out.str(), "ResourceManager::set(): cannot change already final resource " + answerKey.hexString() + '\n');

    /* But non-final can be changed */
    rm.set(questionKey, 20, ResourceDataState::Final, ResourcePolicy::Resident);
    CORRADE_COMPARE(theQuestion.state(), ResourceState::Final);
    CORRADE_COMPARE(*theQuestion, 20);
}

void ResourceManagerTest::residentPolicy() {
    ResourceManager* rm = new ResourceManager;

    rm->set("blah", new Data, ResourceDataState::Mutable, ResourcePolicy::Resident);
    CORRADE_COMPARE(Data::count, 1);

    rm->free();
    CORRADE_COMPARE(Data::count, 1);

    delete rm;
    CORRADE_COMPARE(Data::count, 0);
}

void ResourceManagerTest::referenceCountedPolicy() {
    ResourceManager rm;

    ResourceKey dataRefCountKey("dataRefCount");

    /* Resource is deleted after all references are removed */
    rm.set(dataRefCountKey, new Data, ResourceDataState::Final, ResourcePolicy::ReferenceCounted);
    CORRADE_COMPARE(rm.count<Data>(), 1);
    {
        Resource<Data> data = rm.get<Data>(dataRefCountKey);
        CORRADE_COMPARE(data.state(), ResourceState::Final);
        CORRADE_COMPARE(Data::count, 1);
    }

    CORRADE_COMPARE(rm.count<Data>(), 0);
    CORRADE_COMPARE(Data::count, 0);

    /* Reference counted resources which were not used once will stay loaded
       until free() is called */
    rm.set(dataRefCountKey, new Data, ResourceDataState::Final, ResourcePolicy::ReferenceCounted);
    CORRADE_COMPARE(rm.count<Data>(), 1);
    CORRADE_COMPARE(rm.state<Data>(dataRefCountKey), ResourceState::Final);
    CORRADE_COMPARE(rm.referenceCount<Data>(dataRefCountKey), 0);

    rm.free<Data>();
    CORRADE_COMPARE(rm.count<Data>(), 0);
    CORRADE_COMPARE(rm.state<Data>(dataRefCountKey), ResourceState::NotLoaded);
    CORRADE_COMPARE(rm.referenceCount<Data>(dataRefCountKey), 0);
}

void ResourceManagerTest::manualPolicy() {
    ResourceManager rm;

    ResourceKey dataKey("data");

    /* Manual free */
    {
        rm.set(dataKey, new Data, ResourceDataState::Mutable, ResourcePolicy::Manual);
        Resource<Data> data = rm.get<Data>(dataKey);
        rm.free();
    }

    CORRADE_COMPARE(rm.count<Data>(), 1);
    CORRADE_COMPARE(Data::count, 1);
    rm.free();
    CORRADE_COMPARE(rm.count<Data>(), 0);
    CORRADE_COMPARE(Data::count, 0);

    rm.set(dataKey, new Data, ResourceDataState::Mutable, ResourcePolicy::Manual);
    CORRADE_COMPARE(rm.count<Data>(), 1);
    CORRADE_COMPARE(Data::count, 1);
}

void ResourceManagerTest::defaults() {
    ResourceManager rm;
    rm.set("data", new Data);
    CORRADE_COMPARE(rm.state<Data>("data"), ResourceState::Final);
}

void ResourceManagerTest::clear() {
    ResourceManager rm;

    rm.set("blah", new Data);
    CORRADE_COMPARE(Data::count, 1);

    rm.free();
    CORRADE_COMPARE(Data::count, 1);

    rm.clear();
    CORRADE_COMPARE(Data::count, 0);
}

void ResourceManagerTest::clearWhileReferenced() {
    /* Should cover also the destruction case */

    std::ostringstream out;
    Error redirectError{&out};

    ResourceManager rm;
    rm.set("blah", Int());
    /** @todo this will leak, is there any better solution without hitting
        assertion in decrementReferenceCount()? */
    new Resource<Int>(rm.get<Int>("blah"));

    rm.clear();
    CORRADE_COMPARE(out.str(), "ResourceManager: cleared/destroyed while data are still referenced\n");
}

void ResourceManagerTest::loader() {
    class IntResourceLoader: public AbstractResourceLoader<Int> {
        public:
            IntResourceLoader(): resource(ResourceManager::instance().get<Data>("data")) {}

            void load() {
                set("hello", 773, ResourceDataState::Final, ResourcePolicy::Resident);
                setNotFound("world");
            }

        private:
            void doLoad(ResourceKey) override {}

            std::string doName(ResourceKey key) const override {
                if(key == ResourceKey("hello")) return "hello";
                return "";
            }

            /* To verify that the loader is destroyed before unloading
               _all types of_ resources */
            Resource<Data> resource;
    };

    auto rm = new ResourceManager;
    auto loader = new IntResourceLoader;
    rm->setLoader(loader);

    {
        Resource<Data> data = rm->get<Data>("data");
        Resource<Int> hello = rm->get<Int>("hello");
        Resource<Int> world = rm->get<Int>("world");
        CORRADE_COMPARE(data.state(), ResourceState::NotLoaded);
        CORRADE_COMPARE(hello.state(), ResourceState::Loading);
        CORRADE_COMPARE(world.state(), ResourceState::Loading);

        CORRADE_COMPARE(loader->requestedCount(), 2);
        CORRADE_COMPARE(loader->loadedCount(), 0);
        CORRADE_COMPARE(loader->notFoundCount(), 0);
        CORRADE_COMPARE(loader->name(ResourceKey("hello")), "hello");

        loader->load();
        CORRADE_COMPARE(hello.state(), ResourceState::Final);
        CORRADE_COMPARE(*hello, 773);
        CORRADE_COMPARE(world.state(), ResourceState::NotFound);

        CORRADE_COMPARE(loader->requestedCount(), 2);
        CORRADE_COMPARE(loader->loadedCount(), 1);
        CORRADE_COMPARE(loader->notFoundCount(), 1);

        /* Verify that the loader is deleted at proper time */
        rm->set("data", new Data);
        CORRADE_COMPARE(Data::count, 1);
    }

    delete rm;
    CORRADE_COMPARE(Data::count, 0);
}

void ResourceManagerTest::debugResourceState() {
    std::ostringstream out;
    Debug{&out} << ResourceState::Loading;
    CORRADE_COMPARE(out.str(), "ResourceState::Loading\n");
}

}}

CORRADE_TEST_MAIN(Magnum::Test::ResourceManagerTest)
<|endoftext|>