<commit_before>
#include "PitWizard.h"

#include <iostream>
#include <fstream>
#include <chrono>

#include <Physfs/physfs.h>

#include "s3e.h"

//#include <Photon-cpp/inc/PhotonPeer.h>

#include <GG/GameLayer.h>
#include <GG/Graphics.h>
#include <GG/Core.h>
#include <GG/Input.h>
#include <GG/EntitySystem.h>

#include <GG/Resources/ResourceManager.h>

using namespace GG;

PitWizard::PitWizard() : _deviceWidth(0), _deviceHeight(0)
{

}

PitWizard::~PitWizard()
{

}

void PitWizard::init(int argc, char** argv)
{
	_setupLoggers();

	s3eSurfaceSetup(S3E_SURFACE_PIXEL_TYPE_RGB888);

	//Initialise graphics system(s)
	if(!IwGLInit())
	{
		TRACE_ERROR("IwGLInit failed");
		return;
	}

	IwGLSwapBuffers();
	s3eDeviceYield(0);

	_deviceWidth	= IwGLGetInt(IW_GL_WIDTH);
	_deviceHeight	= IwGLGetInt(IW_GL_HEIGHT);

	_gameStateManager.addGameState( "Intro",					nullptr );
	_gameStateManager.addGameState( "MainMenu",					nullptr );
	_gameStateManager.addGameState( "SinglePlayer",				nullptr );
	_gameStateManager.addGameState( "SinglePlayerEndScreen",	nullptr );
	_gameStateManager.addGameState( "MultiPlayer",				nullptr );
	_gameStateManager.addGameState( "MultiPlayerEndScreen",		nullptr );

	json config = JsonFromFile("configs/input_config.json");
	inputSystem = std::unique_ptr<InputSystem>(new InputSystem(_deviceWidth, _deviceHeight));
	inputSystem->init(config);

	RenderState::GetInstance()->setRenderSize(_deviceWidth, _deviceHeight);

	const char * argv0 = (argc > 0) ? argv[0] : nullptr;
	FileSystem::Init(argv0);
	FileSystem::Mount("rom://", "/", true);
	FileSystem::Mount("ram://", "/", true);
	FileSystem::Mount("/", "/", true);
	FileSystem::SetWriteDirectory("ram://");

	ResourceManager::GetInstance()->registerType<Texture2D>(new Texture2DLoader());
	ResourceManager::GetInstance()->registerType<Shader>(new ShaderLoader());
	ResourceManager::GetInstance()->registerType<Material>(new MaterialLoader());

	FileStream stream("resources/TestGroup.group", OpenMode::OPEN_READ);
	ResourceGroup* group = ResourceManager::GetInstance()->createGroup(&stream);
	group->loadAllAssets();
}

void PitWizard::shutdown()
{
	inputSystem->shutdown();

	ResourceManager::ShutDown();

	Log::Shutdown();
	IwGLTerminate();
	FileSystem::Shutdown();
}

void PitWizard::doGameLoop()
{
	ResourceManager * rm = ResourceManager::GetInstance();
	ResourceH<Material> gridMat = rm->getResource<Material>("marble");

	Model gridModel;
	gridModel.setVertexProperties(POSITIONS | TEXCOORDS | NORMALS | TANGENTS | BITANGENTS);
	ObjLoader::loadFromFile("./resources/environments/forest_road/models/grid.obj", gridModel);

	Model groundModel;
	groundModel.setVertexProperties(POSITIONS | TEXCOORDS | NORMALS | TANGENTS | BITANGENTS);
	ObjLoader::loadFromFile("./resources/environments/forest_road/models/groundPlane.obj", groundModel);

	Model playerModel;
	playerModel.setVertexProperties(POSITIONS | TEXCOORDS | NORMALS | TANGENTS | BITANGENTS);
	ObjLoader::loadFromFile("./resources/environments/forest_road/models/player.obj", playerModel);
	ResourceHandle<Material> tempHolder = rm->getResource<Material>("marble");

	World* worldPtr = new World(new BasicSceneGraph(1000));
	std::unique_ptr<World> world(worldPtr);

	float aspect =	(float)_deviceWidth / (float)_deviceHeight;

	GG::Entity *	box_1		= world->createEntity("Box_1");
	GG::Mesh *		boxMesh_1	= world->addComponent<Mesh>(box_1);
	boxMesh_1->geometry = &playerModel;
	boxMesh_1->material	= gridMat.get();
	SceneNode *		boxNode_1	= box_1->getSceneNode();
	boxNode_1->setPosition(Vector3(0, 1, 0));

	GG::Entity *	box_2		= world->createEntity("Box_2");
	GG::Mesh *		boxMesh_2	= world->addComponent<Mesh>(box_2);
	boxMesh_2->geometry = &playerModel;
	boxMesh_2->material	= gridMat.get();
	SceneNode *		boxNode_2	= box_2->getSceneNode();
	boxNode_2->setPosition(Vector3(0, 0, 3));
	boxNode_2->setParent(boxNode_1);

	GG::Camera * cam = world->createCamera("Camera_1");
	cam->setPerspective(Angle::FromDegrees(80.0f), aspect, 0.1f, 300.0f);
	cam->setViewport(0, 0, 1, 1);
	cam->setClearMode(RenderState::ClearMode::CM_DEPTH | RenderState::ClearMode::CM_COLOR);
	cam->setClearColor(GG::Vector4(0.43f, 0.48f, 0.67f, 1.0f));
	GG::SceneNode * camNode_1 = cam->getEntity()->getSceneNode();
	camNode_1->setPosition(Vector3(0.0f, 3.0f, -7.0f));
	camNode_1->lookAt(boxNode_1);

	Entity *	gridEntity = world->createEntity("GridMesh");
	Mesh *		gridMeshInstance	= world->addComponent<Mesh>(gridEntity);
	gridMeshInstance->geometry		= &gridModel;
	gridMeshInstance->material		= gridMat.get();

	Entity *	groundEntity = world->createEntity("GroundMesh");
	Mesh *		groundMeshInstance	= world->addComponent<Mesh>(groundEntity);
	groundMeshInstance->geometry	= &groundModel;
	groundMeshInstance->material	= gridMat.get();

	const float camSpeed	= 5.0f;

	Time clock;

	// Loop forever, until the user or the OS performs some action to quit the app
	while(!s3eDeviceCheckQuitRequest())
	{
		clock.update();
		float deltaTime = clock.getDeltaTime();

		//Update the input systems
		inputSystem->update();
		// TEMP RESOURCE RELOADING!!! -Julian
		if(s3eKeyboardGetState(s3eKeyR) & S3E_KEY_STATE_RELEASED)
		{
			/*ResourceHandle<Shader> shader = rm->getResource<Shader>(STRING_ID("cookTorrence"));
			shader->setState(IResource::State::UNLOADED);
*/
			rm->findGroup(STRING_ID("default"))->reloadAllAssets();
		}

		if(s3eKeyboardGetState(s3eKeyLeft) & S3E_KEY_STATE_DOWN)
		{
			boxNode_1->rotate(Angle::FromDegrees(3.0f), Vector::up());
		}
		else if(s3eKeyboardGetState(s3eKeyRight) & S3E_KEY_STATE_DOWN)
		{
			boxNode_1->rotate(Angle::FromDegrees(-3.0f), Vector::up());
		}

		if(s3eKeyboardGetState(s3eKeyUp) & S3E_KEY_STATE_DOWN)
		{
			boxNode_1->translate(boxNode_1->forward() * 0.1f);
		}
		else if(s3eKeyboardGetState(s3eKeyDown) & S3E_KEY_STATE_DOWN)
		{
			boxNode_1->translate(boxNode_1->forward() * -0.1f);
		}
		if(s3eKeyboardGetState(s3eKeyP) & S3E_KEY_STATE_RELEASED)
		{
			bool hasParent = boxNode_2->getParent() != nullptr;
			boxNode_2->setParent(hasParent ? nullptr : boxNode_1);
		}

		if(s3eKeyboardGetState(s3eKeyZ) & S3E_KEY_STATE_DOWN)
		{
			camNode_1->translate(Vector::down() * camSpeed * deltaTime);
		}
		else if(s3eKeyboardGetState(s3eKeyX) & S3E_KEY_STATE_DOWN)
		{
			camNode_1->translate(Vector::up() * camSpeed * deltaTime);
		}
		camNode_1->rotate(Angle::FromDegrees(70.0f) * inputSystem->getAxis( "RotateX" ), Vector::right() );

		float walk		= inputSystem->getAxis( "Walk" );
		float strafe	= inputSystem->getAxis( "Strafe" );

		Vector3 move =	(Vector::forward() * walk) +
						(camNode_1->right() * strafe);

		move = glm::length2(move) > 0.001f ? glm::normalize(move): move;
		camNode_1->translate(move * camSpeed * deltaTime);

		world->update(1.0f / 60.0f);

		world->renderOneFrame();

			// Sleep for 0ms to allow the OS to process events etc.
		s3eDeviceYield( 0 );
	}
}

void PitWizard::_setupLoggers()
{
	const std::string filePath = _getFileLogName();

	Log::GetInstance()->registerLogger( new FileLogger( filePath ) );
	Log::GetInstance()->registerLogger( new ConsoleLogger() );
}

const std::string PitWizard::_getFileLogName() const
{
	auto now = std::chrono::system_clock::now();
	const std::time_t now_time = std::chrono::system_clock::to_time_t( now );
	auto t = localtime( &now_time );

	std::string logFilename;
	GG::StringHelper::Format(
		logFilename,
		"ram://logs/log_%d-%d-%d_%dh-%dm-%ds.txt",
		t->tm_mon + 1,
		t->tm_hour + 1,
		t->tm_year + 1900,
		t->tm_hour,
		t->tm_min,
		t->tm_sec
		);

	return logFilename;
}
<commit_msg>Setup file system earlier in init<commit_after>
#include "PitWizard.h"

#include <iostream>
#include <fstream>
#include <chrono>

#include <Physfs/physfs.h>

#include "s3e.h"

//#include <Photon-cpp/inc/PhotonPeer.h>

#include <GG/GameLayer.h>
#include <GG/Graphics.h>
#include <GG/Core.h>
#include <GG/Input.h>
#include <GG/EntitySystem.h>

#include <GG/Resources/ResourceManager.h>

using namespace GG;

PitWizard::PitWizard() : _deviceWidth(0), _deviceHeight(0)
{

}

PitWizard::~PitWizard()
{

}

void PitWizard::init(int argc, char** argv)
{
	_setupLoggers();

	const char * argv0 = (argc > 0) ? argv[0] : nullptr;
	FileSystem::Init(argv0);
	FileSystem::Mount("rom://", "/", true);
	FileSystem::Mount("ram://", "/", true);
	FileSystem::Mount("/", "/", true);
	FileSystem::SetWriteDirectory("ram://");

	s3eSurfaceSetup(S3E_SURFACE_PIXEL_TYPE_RGB888);

	//Initialise graphics system(s)
	if(!IwGLInit())
	{
		TRACE_ERROR("IwGLInit failed");
		return;
	}

	IwGLSwapBuffers();
	s3eDeviceYield(0);

	_deviceWidth	= IwGLGetInt(IW_GL_WIDTH);
	_deviceHeight	= IwGLGetInt(IW_GL_HEIGHT);

	_gameStateManager.addGameState( "Intro",					nullptr );
	_gameStateManager.addGameState( "MainMenu",					nullptr );
	_gameStateManager.addGameState( "SinglePlayer",				nullptr );
	_gameStateManager.addGameState( "SinglePlayerEndScreen",	nullptr );
	_gameStateManager.addGameState( "MultiPlayer",				nullptr );
	_gameStateManager.addGameState( "MultiPlayerEndScreen",		nullptr );

	json config = JsonFromFile("configs/input_config.json");
	inputSystem = std::unique_ptr<InputSystem>(new InputSystem(_deviceWidth, _deviceHeight));
	inputSystem->init(config);

	RenderState::GetInstance()->setRenderSize(_deviceWidth, _deviceHeight);

	ResourceManager::GetInstance()->registerType<Texture2D>(new Texture2DLoader());
	ResourceManager::GetInstance()->registerType<Shader>(new ShaderLoader());
	ResourceManager::GetInstance()->registerType<Material>(new MaterialLoader());

	FileStream stream("resources/TestGroup.group", OpenMode::OPEN_READ);
	ResourceGroup* group = ResourceManager::GetInstance()->createGroup(&stream);
	group->loadAllAssets();
}

void PitWizard::shutdown()
{
	inputSystem->shutdown();

	ResourceManager::ShutDown();

	Log::Shutdown();
	IwGLTerminate();
	FileSystem::Shutdown();
}

void PitWizard::doGameLoop()
{
	ResourceManager * rm = ResourceManager::GetInstance();
	ResourceH<Material> gridMat = rm->getResource<Material>("marble");

	Model gridModel;
	gridModel.setVertexProperties(POSITIONS | TEXCOORDS | NORMALS | TANGENTS | BITANGENTS);
	ObjLoader::loadFromFile("./resources/environments/forest_road/models/grid.obj", gridModel);

	Model groundModel;
	groundModel.setVertexProperties(POSITIONS | TEXCOORDS | NORMALS | TANGENTS | BITANGENTS);
	ObjLoader::loadFromFile("./resources/environments/forest_road/models/groundPlane.obj", groundModel);

	Model playerModel;
	playerModel.setVertexProperties(POSITIONS | TEXCOORDS | NORMALS | TANGENTS | BITANGENTS);
	ObjLoader::loadFromFile("./resources/environments/forest_road/models/player.obj", playerModel);
	ResourceHandle<Material> tempHolder = rm->getResource<Material>("marble");

	World* worldPtr = new World(new BasicSceneGraph(1000));
	std::unique_ptr<World> world(worldPtr);

	float aspect =	(float)_deviceWidth / (float)_deviceHeight;

	GG::Entity *	box_1		= world->createEntity("Box_1");
	GG::Mesh *		boxMesh_1	= world->addComponent<Mesh>(box_1);
	boxMesh_1->geometry = &playerModel;
	boxMesh_1->material	= gridMat.get();
	SceneNode *		boxNode_1	= box_1->getSceneNode();
	boxNode_1->setPosition(Vector3(0, 1, 0));

	GG::Entity *	box_2		= world->createEntity("Box_2");
	GG::Mesh *		boxMesh_2	= world->addComponent<Mesh>(box_2);
	boxMesh_2->geometry = &playerModel;
	boxMesh_2->material	= gridMat.get();
	SceneNode *		boxNode_2	= box_2->getSceneNode();
	boxNode_2->setPosition(Vector3(0, 0, 3));
	boxNode_2->setParent(boxNode_1);

	GG::Camera * cam = world->createCamera("Camera_1");
	cam->setPerspective(Angle::FromDegrees(80.0f), aspect, 0.1f, 300.0f);
	cam->setViewport(0, 0, 1, 1);
	cam->setClearMode(RenderState::ClearMode::CM_DEPTH | RenderState::ClearMode::CM_COLOR);
	cam->setClearColor(GG::Vector4(0.43f, 0.48f, 0.67f, 1.0f));
	GG::SceneNode * camNode_1 = cam->getEntity()->getSceneNode();
	camNode_1->setPosition(Vector3(0.0f, 3.0f, -7.0f));
	camNode_1->lookAt(boxNode_1);

	Entity *	gridEntity = world->createEntity("GridMesh");
	Mesh *		gridMeshInstance	= world->addComponent<Mesh>(gridEntity);
	gridMeshInstance->geometry		= &gridModel;
	gridMeshInstance->material		= gridMat.get();

	Entity *	groundEntity = world->createEntity("GroundMesh");
	Mesh *		groundMeshInstance	= world->addComponent<Mesh>(groundEntity);
	groundMeshInstance->geometry	= &groundModel;
	groundMeshInstance->material	= gridMat.get();

	const float camSpeed	= 5.0f;

	Time clock;

	// Loop forever, until the user or the OS performs some action to quit the app
	while(!s3eDeviceCheckQuitRequest())
	{
		clock.update();
		float deltaTime = clock.getDeltaTime();

		//Update the input systems
		inputSystem->update();
		// TEMP RESOURCE RELOADING!!! -Julian
		if(s3eKeyboardGetState(s3eKeyR) & S3E_KEY_STATE_RELEASED)
		{
			/*ResourceHandle<Shader> shader = rm->getResource<Shader>(STRING_ID("cookTorrence"));
			shader->setState(IResource::State::UNLOADED);
*/
			rm->findGroup(STRING_ID("default"))->reloadAllAssets();
		}

		if(s3eKeyboardGetState(s3eKeyLeft) & S3E_KEY_STATE_DOWN)
		{
			boxNode_1->rotate(Angle::FromDegrees(3.0f), Vector::up());
		}
		else if(s3eKeyboardGetState(s3eKeyRight) & S3E_KEY_STATE_DOWN)
		{
			boxNode_1->rotate(Angle::FromDegrees(-3.0f), Vector::up());
		}

		if(s3eKeyboardGetState(s3eKeyUp) & S3E_KEY_STATE_DOWN)
		{
			boxNode_1->translate(boxNode_1->forward() * 0.1f);
		}
		else if(s3eKeyboardGetState(s3eKeyDown) & S3E_KEY_STATE_DOWN)
		{
			boxNode_1->translate(boxNode_1->forward() * -0.1f);
		}
		if(s3eKeyboardGetState(s3eKeyP) & S3E_KEY_STATE_RELEASED)
		{
			bool hasParent = boxNode_2->getParent() != nullptr;
			boxNode_2->setParent(hasParent ? nullptr : boxNode_1);
		}

		if(s3eKeyboardGetState(s3eKeyZ) & S3E_KEY_STATE_DOWN)
		{
			camNode_1->translate(Vector::down() * camSpeed * deltaTime);
		}
		else if(s3eKeyboardGetState(s3eKeyX) & S3E_KEY_STATE_DOWN)
		{
			camNode_1->translate(Vector::up() * camSpeed * deltaTime);
		}
		camNode_1->rotate(Angle::FromDegrees(70.0f) * inputSystem->getAxis( "RotateX" ), Vector::right() );

		float walk		= inputSystem->getAxis( "Walk" );
		float strafe	= inputSystem->getAxis( "Strafe" );

		Vector3 move =	(Vector::forward() * walk) +
						(camNode_1->right() * strafe);

		move = glm::length2(move) > 0.001f ? glm::normalize(move): move;
		camNode_1->translate(move * camSpeed * deltaTime);

		world->update(1.0f / 60.0f);

		world->renderOneFrame();

			// Sleep for 0ms to allow the OS to process events etc.
		s3eDeviceYield( 0 );
	}
}

void PitWizard::_setupLoggers()
{
	const std::string filePath = _getFileLogName();

	Log::GetInstance()->registerLogger( new FileLogger( filePath ) );
	Log::GetInstance()->registerLogger( new ConsoleLogger() );
}

const std::string PitWizard::_getFileLogName() const
{
	auto now = std::chrono::system_clock::now();
	const std::time_t now_time = std::chrono::system_clock::to_time_t( now );
	auto t = localtime( &now_time );

	std::string logFilename;
	GG::StringHelper::Format(
		logFilename,
		"ram://logs/log_%d-%d-%d_%dh-%dm-%ds.txt",
		t->tm_mon + 1,
		t->tm_hour + 1,
		t->tm_year + 1900,
		t->tm_hour,
		t->tm_min,
		t->tm_sec
		);

	return logFilename;
}
<|endoftext|>


<commit_before>// Vertex.hpp

/*
* (C) Copyright 2015 Noah Roth
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser General Public License
* (LGPL) version 2.1 which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/lgpl-2.1.html
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
*/

#pragma once

#include "stdafx.hpp"

namespace RCT3Asset
{

	struct Vector2
	{
		float X;
		float Y;

		Vector2() : X(0.0f), Y(0.0f) { }
	};

	struct Vector3
	{
		float X;
		float Y;
		float Z;

		Vector3() : X(0.0f), Y(0.0f), Z(0.0f) { }
	};

	struct Vertex
	{
		Vector3 Position;
		Vector3 Normal;
		unsigned int Color;
		//float U;
		//float V;
		Vector2 UVCoords;
	};

	struct WeightedVertex
	{
		Vector3 Position;
		Vector3 Normal;
		signed char Bone[4];
		unsigned char BoneWeight[4];
		unsigned int Color;
		Vector2 UVCoords;
	};

	struct Triangle
	{
		unsigned int A;
		unsigned int B;
		unsigned int C;
	};

	struct Matrix4x4
	{
		union
		{
			float M[4][4];

			struct
			{
				float A1, A2, A3, A4;
				float B1, B2, B3, B4;
				float C1, C2, C3, C4;
				float D1, D2, D3, D4;
			};
		};
	};

	struct GameColor
	{
		unsigned int Color1;
		unsigned int Color2;
		unsigned int Color3;

		GameColor() : Color1(0), Color2(0), Color3(0) { }
	};

	struct BGRAColor
	{
		unsigned char B;
		unsigned char G;
		unsigned char R;
		unsigned char A;

		BGRAColor() : B(0), G(0), R(0), A(0) { }
	};

	// For use with libsquish
	struct U8Color
	{
		squish::u8 R;
		squish::u8 G;
		squish::u8 B;
		squish::u8 A;

		U8Color() : R(0), G(0), B(0), A(0) { }
	};

}<commit_msg>added keyframe<commit_after>// Vertex.hpp

/*
* (C) Copyright 2015 Noah Roth
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser General Public License
* (LGPL) version 2.1 which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/lgpl-2.1.html
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
*/

#pragma once

#include "stdafx.hpp"

namespace RCT3Asset
{

	struct Vector2
	{
		float X;
		float Y;

		Vector2() : X(0.0f), Y(0.0f) { }
	};

	struct Vector3
	{
		float X;
		float Y;
		float Z;

		Vector3() : X(0.0f), Y(0.0f), Z(0.0f) { }
	};

	struct Vertex
	{
		Vector3 Position;
		Vector3 Normal;
		unsigned int Color;
		//float U;
		//float V;
		Vector2 UVCoords;
	};

	struct WeightedVertex
	{
		Vector3 Position;
		Vector3 Normal;
		signed char Bone[4];
		unsigned char BoneWeight[4];
		unsigned int Color;
		Vector2 UVCoords;
	};

	struct Triangle
	{
		unsigned int A;
		unsigned int B;
		unsigned int C;
	};

	struct Matrix4x4
	{
		union
		{
			float M[4][4];

			struct
			{
				float A1, A2, A3, A4;
				float B1, B2, B3, B4;
				float C1, C2, C3, C4;
				float D1, D2, D3, D4;
			};
		};
	};

	struct KeyFrame
	{
		float Time;
		Vector3 TranslateRotate;
	};

	struct GameColor
	{
		unsigned int Color1;
		unsigned int Color2;
		unsigned int Color3;

		GameColor() : Color1(0), Color2(0), Color3(0) { }
	};

	struct BGRAColor
	{
		unsigned char B;
		unsigned char G;
		unsigned char R;
		unsigned char A;

		BGRAColor() : B(0), G(0), R(0), A(0) { }
	};

	// For use with libsquish
	struct U8Color
	{
		squish::u8 R;
		squish::u8 G;
		squish::u8 B;
		squish::u8 A;

		U8Color() : R(0), G(0), B(0), A(0) { }
	};

}<|endoftext|>


<commit_before>/*
* daemon-tools.node
*** A node.JS addon that allows creating Unix/Linux Daemons in pure Javascript.
*** Copyright 2010 (c) <arthur@norgic.com>
* Under MIT License. See LICENSE file.
* Updated by Daniel Bartlett 2011 <dan@f-box.org>
*/

#include <v8.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <ev.h>
#include <pwd.h>

#define PID_MAXLEN 10

using namespace v8;

// Go through special routines to become a daemon.
// if successful, returns daemon's PID
Handle<Value> Start(const Arguments& args) {
	pid_t pid, sid;
	int do_cd_root;
	if (args.Length() < 1) {
		return ThrowException(Exception::TypeError(
			String::New("Must have one argument true/false as to if we cd /")));
	}

	do_cd_root = args[0]->Int32Value();

	pid = fork();
	if(pid > 0) exit(0);
	if(pid < 0) exit(1);

	ev_default_fork();

	// Can be changed after with process.umaks
	umask(0);

	sid = setsid();
	if(sid < 0) exit(1);

	// Can be changed with process.chdir
	if (do_cd_root == 1) {
		chdir("/");
	}

	return Integer::New(getpid());
}

// Close Standard IN/OUT/ERR Streams
Handle<Value> CloseIO(const Arguments& args) {
	freopen("/dev/null", "r", stdin);
	freopen("/dev/null", "w", stdout);
	freopen("/dev/null", "w", stderr);
}

// File-lock to make sure that only one instance of daemon is running.. also for storing PID
/* lock ( filename )
*** filename: a path to a lock-file.
*** Note: if filename doesn't exist, it will be created when function is called.
*/
Handle<Value> LockD(const Arguments& args) {
	if(!args[0]->IsString())
		return Boolean::New(false);

	String::Utf8Value data(args[0]->ToString());
	char pid_str[PID_MAXLEN+1];

	int lfp = open(*data, O_RDWR | O_CREAT, 0640);
	if(lfp < 0) exit(1);
	if(lockf(lfp, F_TLOCK, 0) < 0) exit(0);

	int len = snprintf(pid_str, PID_MAXLEN, "%d", getpid());
	write(lfp, pid_str, len);

	return Boolean::New(true);
}

const char* ToCString(const v8::String::Utf8Value& value) {
	return *value ? *value : "<string conversion failed>";
}

/* chroot ( folder )
 * folder: The new root
*/
Handle<Value> Chroot(const Arguments& args) {
	if (args.Length() < 1) {
		return ThrowException(Exception::TypeError(
			String::New("Must have one argument; a string of the folder to chroot to.")
		));
	}
	uid_t uid;
	int rv;

	uid = getuid();
	if (uid != 0) {
		return ThrowException(Exception::Error(
			String::New("You must be root in order to use chroot.")
		));
	}

	String::Utf8Value folderUtf8(args[0]->ToString());
	const char *folder = ToCString(folderUtf8);
	rv = chroot(folder);
	if (rv != 0) {
		return ThrowException(Exception::Error(
			String::New("Failed do chroot to the folder.")
		));
	}
	chdir("/");

	return Boolean::New(true);
}

// Allow changing the real and effective user ID of this process so a root process
// can become unprivileged
Handle<Value> SetREUID(const Arguments& args) {
	if(args.Length() == 0 || !args[0]->IsString())
		return ThrowException(Exception::Error(
			String::New("Must give a username to become")
		));

	String::AsciiValue username(args[0]);

	struct passwd* pwd_entry = getpwnam(*username);

	if(pwd_entry) {
		setreuid(pwd_entry->pw_uid, pwd_entry->pw_uid);
	} else {
		return ThrowException(Exception::Error(
			String::New("User not found")
		));
	}
}

extern "C" void init(Handle<Object> target) {
	HandleScope scope;

	target->Set(String::New("start"), FunctionTemplate::New(Start)->GetFunction());
	target->Set(String::New("lock"), FunctionTemplate::New(LockD)->GetFunction());
	target->Set(String::New("closeIO"), FunctionTemplate::New(CloseIO)->GetFunction());
	target->Set(String::New("chroot"), FunctionTemplate::New(Chroot)->GetFunction());
	target->Set(String::New("setreuid"), FunctionTemplate::New(SetREUID)->GetFunction());
}
<commit_msg>Adding setreuid_username and setreuid<commit_after>/*
* daemon-tools.node
*** A node.JS addon that allows creating Unix/Linux Daemons in pure Javascript.
*** Copyright 2010 (c) <arthur@norgic.com>
* Under MIT License. See LICENSE file.
* Updated by Daniel Bartlett 2011 <dan@f-box.org>
*/

#include <v8.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <ev.h>
#include <pwd.h>

#define PID_MAXLEN 10

using namespace v8;

// Go through special routines to become a daemon.
// if successful, returns daemon's PID
Handle<Value> Start(const Arguments& args) {
	pid_t pid, sid;
	int do_cd_root;
	if (args.Length() < 1) {
		return ThrowException(Exception::TypeError(
			String::New("Must have one argument true/false as to if we cd /")));
	}

	do_cd_root = args[0]->Int32Value();

	pid = fork();
	if(pid > 0) exit(0);
	if(pid < 0) exit(1);

	ev_default_fork();

	// Can be changed after with process.umaks
	umask(0);

	sid = setsid();
	if(sid < 0) exit(1);

	// Can be changed with process.chdir
	if (do_cd_root == 1) {
		chdir("/");
	}

	return Integer::New(getpid());
}

// Close Standard IN/OUT/ERR Streams
Handle<Value> CloseIO(const Arguments& args) {
	freopen("/dev/null", "r", stdin);
	freopen("/dev/null", "w", stdout);
	freopen("/dev/null", "w", stderr);
}

// File-lock to make sure that only one instance of daemon is running.. also for storing PID
/* lock ( filename )
*** filename: a path to a lock-file.
*** Note: if filename doesn't exist, it will be created when function is called.
*/
Handle<Value> LockD(const Arguments& args) {
	if(!args[0]->IsString())
		return Boolean::New(false);

	String::Utf8Value data(args[0]->ToString());
	char pid_str[PID_MAXLEN+1];

	int lfp = open(*data, O_RDWR | O_CREAT, 0640);
	if(lfp < 0) exit(1);
	if(lockf(lfp, F_TLOCK, 0) < 0) exit(0);

	int len = snprintf(pid_str, PID_MAXLEN, "%d", getpid());
	write(lfp, pid_str, len);

	return Boolean::New(true);
}

const char* ToCString(const v8::String::Utf8Value& value) {
	return *value ? *value : "<string conversion failed>";
}

/* chroot ( folder )
 * folder: The new root
*/
Handle<Value> Chroot(const Arguments& args) {
	if (args.Length() < 1) {
		return ThrowException(Exception::TypeError(
			String::New("Must have one argument; a string of the folder to chroot to.")
		));
	}
	uid_t uid;
	int rv;

	uid = getuid();
	if (uid != 0) {
		return ThrowException(Exception::Error(
			String::New("You must be root in order to use chroot.")
		));
	}

	String::Utf8Value folderUtf8(args[0]->ToString());
	const char *folder = ToCString(folderUtf8);
	rv = chroot(folder);
	if (rv != 0) {
		return ThrowException(Exception::Error(
			String::New("Failed do chroot to the folder.")
		));
	}
	chdir("/");

	return Boolean::New(true);
}

// Allow changing the real and effective user ID of this process so a root process
// can become unprivileged
Handle<Value> SetREUID(const Arguments& args) {
	uid_t uid;
	if(args.Length() == 0)
		return ThrowException(Exception::Error(
			String::New("Must give a uid to become")
		));

	uid = args[0]->Int32Value();
	setreuid(uid, uid);
}

// Allow changing the real and effective user ID of this process so a root process
// can become unprivileged
Handle<Value> SetREUID_username(const Arguments& args) {
	if(args.Length() == 0 || !args[0]->IsString())
		return ThrowException(Exception::Error(
			String::New("Must give a username to become")
		));

	String::AsciiValue username(args[0]);

	struct passwd* pwd_entry = getpwnam(*username);

	if(pwd_entry) {
		setreuid(pwd_entry->pw_uid, pwd_entry->pw_uid);
	} else {
		return ThrowException(Exception::Error(
			String::New("User not found")
		));
	}
}

extern "C" void init(Handle<Object> target) {
	HandleScope scope;

	target->Set(String::New("start"), FunctionTemplate::New(Start)->GetFunction());
	target->Set(String::New("lock"), FunctionTemplate::New(LockD)->GetFunction());
	target->Set(String::New("closeIO"), FunctionTemplate::New(CloseIO)->GetFunction());
	target->Set(String::New("chroot"), FunctionTemplate::New(Chroot)->GetFunction());
	target->Set(String::New("setreuid_username"), FunctionTemplate::New(SetREUID_username)->GetFunction());
	target->Set(String::New("setreuid"), FunctionTemplate::New(SetREUID)->GetFunction());
}
<|endoftext|>


<commit_before>#include "./core.hpp"
#include "./darwin/darwin.hpp"
#include <cstdlib>
darwin::pixel pencil;
darwin::sync_clock dclock(30);
void init(){
    cov_basic::storage.add_var("darwin_loadmodule",cov_basic::native_interface([](const std::deque<cov::any>& args)->cov_basic::number{
		darwin::runtime.load(args.at(0).val<std::string>());
		return 0;
	}));
    cov_basic::storage.add_var("darwin_fitwindow",cov_basic::native_interface([](const std::deque<cov::any>& args)->cov_basic::number{
		darwin::runtime.fit_drawable();
		return 0;
	}));
    cov_basic::storage.add_var("darwin_updatepaint",cov_basic::native_interface([](const std::deque<cov::any>& args)->cov_basic::number{
		darwin::runtime.update_drawable();
        dclock.sync();
        dclock.reset();
		return 0;
	}));
    cov_basic::storage.add_var("darwin_clearpaint",cov_basic::native_interface([](const std::deque<cov::any>& args)->cov_basic::number{
		darwin::runtime.get_drawable()->clear();
		return 0;
	}));
    cov_basic::storage.add_var("darwin_fillpaint",cov_basic::native_interface([](const std::deque<cov::any>& args)->cov_basic::number{
        darwin::runtime.get_drawable()->fill(pencil);
		return 0;
	}));
    cov_basic::storage.add_var("darwin_windowheight",cov_basic::native_interface([](const std::deque<cov::any>& args)->cov_basic::number{
		return darwin::runtime.get_drawable()->get_height();
	}));
    cov_basic::storage.add_var("darwin_windowwidth",cov_basic::native_interface([](const std::deque<cov::any>& args)->cov_basic::number{
		return darwin::runtime.get_drawable()->get_width();
	}));
    cov_basic::storage.add_var("darwin_drawpoint",cov_basic::native_interface([](const std::deque<cov::any>& args)->cov_basic::number{
        darwin::runtime.get_drawable()->draw_pixel(args.at(0).val<cov_basic::number>(),args.at(1).val<cov_basic::number>(),pencil);
		return 0;
	}));
    cov_basic::storage.add_var("darwin_drawline",cov_basic::native_interface([](const std::deque<cov::any>& args)->cov_basic::number{
        darwin::runtime.get_drawable()->draw_line(args.at(0).val<cov_basic::number>(),args.at(1).val<cov_basic::number>(),args.at(2).val<cov_basic::number>(),args.at(3).val<cov_basic::number>(),pencil);
		return 0;
	}));
    cov_basic::storage.add_var("darwin_setpencil",cov_basic::native_interface([](const std::deque<cov::any>& args)->cov_basic::number{
		char ch=args.at(0).val<std::string>().at(0);
        bool bright=args.at(1).val<bool>();
        bool underline=args.at(2).val<bool>();
        darwin::colors fc,bc;
        switch(int(args.at(3).val<cov_basic::number>()))
        {
            case 0:
                fc=darwin::colors::black;
                break;
            case 1:
                fc=darwin::colors::white;
                break;
            case 2:
                fc=darwin::colors::red;
                break;
            case 3:
                fc=darwin::colors::green;
                break;
            case 4:
                fc=darwin::colors::blue;
                break;
            case 5:
                fc=darwin::colors::pink;
                break;
            case 6:
                fc=darwin::colors::yellow;
                break;
            case 7:
                fc=darwin::colors::cyan;
                break;
        }
        switch(int(args.at(4).val<cov_basic::number>()))
        {
            case 0:
                bc=darwin::colors::black;
                break;
            case 1:
                bc=darwin::colors::white;
                break;
            case 2:
                bc=darwin::colors::red;
                break;
            case 3:
                bc=darwin::colors::green;
                break;
            case 4:
                bc=darwin::colors::blue;
                break;
            case 5:
                bc=darwin::colors::pink;
                break;
            case 6:
                bc=darwin::colors::yellow;
                break;
            case 7:
                bc=darwin::colors::cyan;
                break;
        }
        pencil=darwin::pixel(ch,bright,underline,fc,bc);
		return 0;
	}));
}<commit_msg>Delete darwin_core.hpp<commit_after><|endoftext|>


<commit_before>#ifndef __Data_course__
#define __Data_course__

#include "data-general.hpp"
#include "data-major.hpp"
#include "data-department.hpp"
using namespace std;

class Course {
protected:
	string ID;
	int number;
	string title;
	string description;
	char section;

	vector<Major> majors;
	Department* department;
	string concentrations;
	string conversations;
	string professor;

	int half_semester;
	bool pass_fail;
	float credits;
	string location;

	bool lab;
	GenEd* geneds;

	bool days[7];
	float time[7];
public:
	Course(istream &is) {
		if (!is) return;

		string tmpLine;
		getline(is, tmpLine); // remove the extra data of course status

		vector<string> record = split(tmpLine, ',');
		for (vector<string>::iterator i=record.begin(); i != record.end(); ++i)
			*i=removeAllQuotes(*i);

		// Ignore the first column;
		record.at(0);

		// Second column has the course ID,
		//number = stringToInt(record.at(1));
		ID = record.at(1);
		number = parseID(ID);

		// Third column has the section,
		section = record.at(2)[0];

		// Fourth holds the lab boolean,
		if (record.at(3).empty())
			lab = false;
		else
			lab = true;

		// while Fifth contains the title of the course;
		title = record.at(4);

		// Sixth hands over the length (half semester or not)
		// it's actually an int that tells us how many times the course is offered per semester.
		half_semester = stringToInt(record.at(5));

		// Seventh tells us the number of credits,
		credits = stringToFloat(record.at(6));

		// Eighth shows us if it can be taken pass/no-pass,
		if (record.at(7) == "Y")
			pass_fail = true;
		else
			pass_fail = false;

		// while Nine gives us the GEs of the course,
		// GEreqs = record.at(9);

		// and Ten spits out the days and times;
		// Times = record.at(10);

		// Eleven holds the location,
		location = record.at(11);

		// and Twelve knows who teaches.
		professor = record.at(12);
	}

	void parseID(string str) {
		unsigned int foundLoc = str.find('/');
		string tempDept = str.substr(0,str.find(' ')-1);

		if (foundLoc != str.npos) {
			string dept1 = tempDept.substr(0,2);
			department.push_back(Department(dept1));

			string dept2 = tempDept.substr(2,2);
			department.push_back(Department(dept2));
		}
		else {
			department.push_back(Department(tempDept));
		}
	}

	void updateID() {
		string dept;
		for (std::vector<Department>::iterator i = department.begin(); i != department.end(); ++i)
			dept += i->getName();
		ID = dept + tostring(number) + section;
	}
	string getID() {
		return ID;
	}

	ostream& getData(ostream &os) {
		os << ID << section << " - ";
		os << title << " | ";
		// os << professor << endl;
		return os;
	}
	void display();
};

ostream &operator<<(ostream &os, Course &item) { return item.getData(os); }
void Course::display() { if(this==0) cout << *this << endl; }

#endif

<commit_msg>Switch to a vector of departments<commit_after>#ifndef __Data_course__
#define __Data_course__

#include "data-general.hpp"
#include "data-major.hpp"
#include "data-department.hpp"
using namespace std;

class Course {
protected:
	string ID;
	int number;
	string title;
	string description;
	char section;

	vector<Major> majors;
	vector<Department> department;
	string concentrations;
	string conversations;
	string professor;

	int half_semester;
	bool pass_fail;
	float credits;
	string location;

	bool lab;
	GenEd* geneds;

	bool days[7];
	float time[7];
public:
	Course(istream &is) {
		if (!is) return;

		string tmpLine;
		getline(is, tmpLine); // remove the extra data of course status

		vector<string> record = split(tmpLine, ',');
		for (vector<string>::iterator i=record.begin(); i != record.end(); ++i)
			*i=removeAllQuotes(*i);

		// Ignore the first column;
		record.at(0);

		// Second column has the course ID,
		//number = stringToInt(record.at(1));
		ID = record.at(1);
		number = parseID(ID);

		// Third column has the section,
		section = record.at(2)[0];

		// Fourth holds the lab boolean,
		if (record.at(3).empty())
			lab = false;
		else
			lab = true;

		// while Fifth contains the title of the course;
		title = record.at(4);

		// Sixth hands over the length (half semester or not)
		// it's actually an int that tells us how many times the course is offered per semester.
		half_semester = stringToInt(record.at(5));

		// Seventh tells us the number of credits,
		credits = stringToFloat(record.at(6));

		// Eighth shows us if it can be taken pass/no-pass,
		if (record.at(7) == "Y")
			pass_fail = true;
		else
			pass_fail = false;

		// while Nine gives us the GEs of the course,
		// GEreqs = record.at(9);

		// and Ten spits out the days and times;
		// Times = record.at(10);

		// Eleven holds the location,
		location = record.at(11);

		// and Twelve knows who teaches.
		professor = record.at(12);
	}

	void parseID(string str) {
		unsigned int foundLoc = str.find('/');
		string tempDept = str.substr(0,str.find(' ')-1);

		if (foundLoc != str.npos) {
			string dept1 = tempDept.substr(0,2);
			department.push_back(Department(dept1));

			string dept2 = tempDept.substr(2,2);
			department.push_back(Department(dept2));
		}
		else {
			department.push_back(Department(tempDept));
		}
	}

	void updateID() {
		string dept;
		for (std::vector<Department>::iterator i = department.begin(); i != department.end(); ++i)
			dept += i->getName();
		ID = dept + tostring(number) + section;
	}
	string getID() {
		return ID;
	}

	ostream& getData(ostream &os) {
		os << ID << section << " - ";
		os << title << " | ";
		// os << professor << endl;
		return os;
	}
	void display();
};

ostream &operator<<(ostream &os, Course &item) { return item.getData(os); }
void Course::display() { if(this==0) cout << *this << endl; }

#endif

<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "sandbox/src/win_utils.h"

#include <map>

#include "base/logging.h"
#include "base/scoped_ptr.h"
#include "sandbox/src/internal_types.h"
#include "sandbox/src/nt_internals.h"

namespace {

// Holds the information about a known registry key.
struct KnownReservedKey {
  const wchar_t* name;
  HKEY key;
};

// Contains all the known registry key by name and by handle.
const KnownReservedKey kKnownKey[] = {
    { L"HKEY_CLASSES_ROOT", HKEY_CLASSES_ROOT },
    { L"HKEY_CURRENT_USER", HKEY_CURRENT_USER },
    { L"HKEY_LOCAL_MACHINE", HKEY_LOCAL_MACHINE},
    { L"HKEY_USERS", HKEY_USERS},
    { L"HKEY_PERFORMANCE_DATA", HKEY_PERFORMANCE_DATA},
    { L"HKEY_PERFORMANCE_TEXT", HKEY_PERFORMANCE_TEXT},
    { L"HKEY_PERFORMANCE_NLSTEXT", HKEY_PERFORMANCE_NLSTEXT},
    { L"HKEY_CURRENT_CONFIG", HKEY_CURRENT_CONFIG},
    { L"HKEY_DYN_DATA", HKEY_DYN_DATA}
};

}  // namespace

namespace sandbox {

HKEY GetReservedKeyFromName(const std::wstring& name) {
  for (size_t i = 0; i < arraysize(kKnownKey); ++i) {
    if (name == kKnownKey[i].name)
      return kKnownKey[i].key;
  }

  return NULL;
}

bool ResolveRegistryName(std::wstring name, std::wstring* resolved_name) {
  for (size_t i = 0; i < arraysize(kKnownKey); ++i) {
    if (name.find(kKnownKey[i].name) == 0) {
      HKEY key;
      DWORD disposition;
      if (ERROR_SUCCESS != ::RegCreateKeyEx(kKnownKey[i].key, L"", 0, NULL, 0,
                                            MAXIMUM_ALLOWED, NULL, &key,
                                            &disposition))
        return false;

      bool result = GetPathFromHandle(key, resolved_name);
      ::RegCloseKey(key);

      if (!result)
        return false;

      *resolved_name += name.substr(wcslen(kKnownKey[i].name));
      return true;
    }
  }

  return false;
}

DWORD IsReparsePoint(const std::wstring& full_path, bool* result) {
  std::wstring path = full_path;

  // Remove the nt prefix.
  if (0 == path.compare(0, kNTPrefixLen, kNTPrefix))
    path = path.substr(kNTPrefixLen);

  // Check if it's a pipe. We can't query the attributes of a pipe.
  const wchar_t kPipe[] = L"pipe\\";
  if (0 == path.compare(0, arraysize(kPipe) - 1, kPipe)) {
    *result = FALSE;
    return ERROR_SUCCESS;
  }

  std::wstring::size_type last_pos = std::wstring::npos;

  do {
    path = path.substr(0, last_pos);

    DWORD attributes = ::GetFileAttributes(path.c_str());
    if (INVALID_FILE_ATTRIBUTES == attributes) {
      DWORD error = ::GetLastError();
      if (error != ERROR_FILE_NOT_FOUND &&
          error != ERROR_PATH_NOT_FOUND &&
          error != ERROR_INVALID_NAME) {
        // Unexpected error.
        NOTREACHED();
        return error;
      }
    } else if (FILE_ATTRIBUTE_REPARSE_POINT & attributes) {
      // This is a reparse point.
      *result = true;
      return ERROR_SUCCESS;
    }

    last_pos = path.rfind(L'\\');
  } while (last_pos != std::wstring::npos);

  *result = false;
  return ERROR_SUCCESS;
}

bool ConvertToLongPath(const std::wstring& short_path,
                       std::wstring* long_path) {
  // Check if the path is a NT path.
  bool is_nt_path = false;
  std::wstring path = short_path;
  if (0 == path.compare(0, kNTPrefixLen, kNTPrefix)) {
    path = path.substr(kNTPrefixLen);
    is_nt_path = true;
  }

  DWORD size = MAX_PATH;
  scoped_array<wchar_t> long_path_buf(new wchar_t[size]);

  DWORD return_value = ::GetLongPathName(path.c_str(), long_path_buf.get(),
                                         size);
  while (return_value >= size) {
    size *= 2;
    long_path_buf.reset(new wchar_t[size]);
    return_value = ::GetLongPathName(path.c_str(), long_path_buf.get(), size);
  }

  DWORD last_error = ::GetLastError();
  if (0 == return_value && (ERROR_FILE_NOT_FOUND == last_error ||
                            ERROR_PATH_NOT_FOUND == last_error ||
                            ERROR_INVALID_NAME == last_error)) {
    // The file does not exist, but maybe a sub path needs to be expanded.
    std::wstring::size_type last_slash = path.rfind(L'\\');
    if (std::wstring::npos == last_slash)
      return false;

    std::wstring begin = path.substr(0, last_slash);
    std::wstring end = path.substr(last_slash);
    if (!ConvertToLongPath(begin, &begin))
      return false;

    // Ok, it worked. Let's reset the return value.
    path = begin + end;
    return_value = 1;
  } else if (0 != return_value) {
    path = long_path_buf.get();
  }

  if (return_value != 0) {
    if (is_nt_path) {
      *long_path = kNTPrefix;
      *long_path += path;
    } else {
      *long_path = path;
    }

    return true;
  }

  return false;
}

bool GetPathFromHandle(HANDLE handle, std::wstring* path) {
  NtQueryObjectFunction NtQueryObject = NULL;
  ResolveNTFunctionPtr("NtQueryObject", &NtQueryObject);

  OBJECT_NAME_INFORMATION* name = NULL;
  ULONG size = 0;
  // Query the name information a first time to get the size of the name.
  NTSTATUS status = NtQueryObject(handle, ObjectNameInformation, name, size,
                                  &size);

  scoped_ptr<OBJECT_NAME_INFORMATION> name_ptr;
  if (size) {
    name = reinterpret_cast<OBJECT_NAME_INFORMATION*>(new BYTE[size]);
    name_ptr.reset(name);

    // Query the name information a second time to get the name of the
    // object referenced by the handle.
    status = NtQueryObject(handle, ObjectNameInformation, name, size, &size);
  }

  if (STATUS_SUCCESS != status)
    return false;

  path->assign(name->ObjectName.Buffer, name->ObjectName.Length /
                                        sizeof(name->ObjectName.Buffer[0]));
  return true;
}

};  // namespace sandbox

// TODO(cpu): Revert this change to use a map to speed up the function once
// this has been deployed in the dev channel for a week. See bug 11789.
void ResolveNTFunctionPtr(const char* name, void* ptr) {
  static HMODULE ntdll = ::GetModuleHandle(sandbox::kNtdllName);

  FARPROC* function_ptr = reinterpret_cast<FARPROC*>(ptr);
  *function_ptr = ::GetProcAddress(ntdll, name);
  CHECK(*function_ptr) << "Failed to resolve NTDLL function";
}
<commit_msg>Change again the way we do ResolveNTFunctionPtr - This version is different from last two<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "sandbox/src/win_utils.h"

#include <map>

#include "base/logging.h"
#include "base/scoped_ptr.h"
#include "sandbox/src/internal_types.h"
#include "sandbox/src/nt_internals.h"

namespace {

// Holds the information about a known registry key.
struct KnownReservedKey {
  const wchar_t* name;
  HKEY key;
};

// Contains all the known registry key by name and by handle.
const KnownReservedKey kKnownKey[] = {
    { L"HKEY_CLASSES_ROOT", HKEY_CLASSES_ROOT },
    { L"HKEY_CURRENT_USER", HKEY_CURRENT_USER },
    { L"HKEY_LOCAL_MACHINE", HKEY_LOCAL_MACHINE},
    { L"HKEY_USERS", HKEY_USERS},
    { L"HKEY_PERFORMANCE_DATA", HKEY_PERFORMANCE_DATA},
    { L"HKEY_PERFORMANCE_TEXT", HKEY_PERFORMANCE_TEXT},
    { L"HKEY_PERFORMANCE_NLSTEXT", HKEY_PERFORMANCE_NLSTEXT},
    { L"HKEY_CURRENT_CONFIG", HKEY_CURRENT_CONFIG},
    { L"HKEY_DYN_DATA", HKEY_DYN_DATA}
};

}  // namespace

namespace sandbox {

HKEY GetReservedKeyFromName(const std::wstring& name) {
  for (size_t i = 0; i < arraysize(kKnownKey); ++i) {
    if (name == kKnownKey[i].name)
      return kKnownKey[i].key;
  }

  return NULL;
}

bool ResolveRegistryName(std::wstring name, std::wstring* resolved_name) {
  for (size_t i = 0; i < arraysize(kKnownKey); ++i) {
    if (name.find(kKnownKey[i].name) == 0) {
      HKEY key;
      DWORD disposition;
      if (ERROR_SUCCESS != ::RegCreateKeyEx(kKnownKey[i].key, L"", 0, NULL, 0,
                                            MAXIMUM_ALLOWED, NULL, &key,
                                            &disposition))
        return false;

      bool result = GetPathFromHandle(key, resolved_name);
      ::RegCloseKey(key);

      if (!result)
        return false;

      *resolved_name += name.substr(wcslen(kKnownKey[i].name));
      return true;
    }
  }

  return false;
}

DWORD IsReparsePoint(const std::wstring& full_path, bool* result) {
  std::wstring path = full_path;

  // Remove the nt prefix.
  if (0 == path.compare(0, kNTPrefixLen, kNTPrefix))
    path = path.substr(kNTPrefixLen);

  // Check if it's a pipe. We can't query the attributes of a pipe.
  const wchar_t kPipe[] = L"pipe\\";
  if (0 == path.compare(0, arraysize(kPipe) - 1, kPipe)) {
    *result = FALSE;
    return ERROR_SUCCESS;
  }

  std::wstring::size_type last_pos = std::wstring::npos;

  do {
    path = path.substr(0, last_pos);

    DWORD attributes = ::GetFileAttributes(path.c_str());
    if (INVALID_FILE_ATTRIBUTES == attributes) {
      DWORD error = ::GetLastError();
      if (error != ERROR_FILE_NOT_FOUND &&
          error != ERROR_PATH_NOT_FOUND &&
          error != ERROR_INVALID_NAME) {
        // Unexpected error.
        NOTREACHED();
        return error;
      }
    } else if (FILE_ATTRIBUTE_REPARSE_POINT & attributes) {
      // This is a reparse point.
      *result = true;
      return ERROR_SUCCESS;
    }

    last_pos = path.rfind(L'\\');
  } while (last_pos != std::wstring::npos);

  *result = false;
  return ERROR_SUCCESS;
}

bool ConvertToLongPath(const std::wstring& short_path,
                       std::wstring* long_path) {
  // Check if the path is a NT path.
  bool is_nt_path = false;
  std::wstring path = short_path;
  if (0 == path.compare(0, kNTPrefixLen, kNTPrefix)) {
    path = path.substr(kNTPrefixLen);
    is_nt_path = true;
  }

  DWORD size = MAX_PATH;
  scoped_array<wchar_t> long_path_buf(new wchar_t[size]);

  DWORD return_value = ::GetLongPathName(path.c_str(), long_path_buf.get(),
                                         size);
  while (return_value >= size) {
    size *= 2;
    long_path_buf.reset(new wchar_t[size]);
    return_value = ::GetLongPathName(path.c_str(), long_path_buf.get(), size);
  }

  DWORD last_error = ::GetLastError();
  if (0 == return_value && (ERROR_FILE_NOT_FOUND == last_error ||
                            ERROR_PATH_NOT_FOUND == last_error ||
                            ERROR_INVALID_NAME == last_error)) {
    // The file does not exist, but maybe a sub path needs to be expanded.
    std::wstring::size_type last_slash = path.rfind(L'\\');
    if (std::wstring::npos == last_slash)
      return false;

    std::wstring begin = path.substr(0, last_slash);
    std::wstring end = path.substr(last_slash);
    if (!ConvertToLongPath(begin, &begin))
      return false;

    // Ok, it worked. Let's reset the return value.
    path = begin + end;
    return_value = 1;
  } else if (0 != return_value) {
    path = long_path_buf.get();
  }

  if (return_value != 0) {
    if (is_nt_path) {
      *long_path = kNTPrefix;
      *long_path += path;
    } else {
      *long_path = path;
    }

    return true;
  }

  return false;
}

bool GetPathFromHandle(HANDLE handle, std::wstring* path) {
  NtQueryObjectFunction NtQueryObject = NULL;
  ResolveNTFunctionPtr("NtQueryObject", &NtQueryObject);

  OBJECT_NAME_INFORMATION* name = NULL;
  ULONG size = 0;
  // Query the name information a first time to get the size of the name.
  NTSTATUS status = NtQueryObject(handle, ObjectNameInformation, name, size,
                                  &size);

  scoped_ptr<OBJECT_NAME_INFORMATION> name_ptr;
  if (size) {
    name = reinterpret_cast<OBJECT_NAME_INFORMATION*>(new BYTE[size]);
    name_ptr.reset(name);

    // Query the name information a second time to get the name of the
    // object referenced by the handle.
    status = NtQueryObject(handle, ObjectNameInformation, name, size, &size);
  }

  if (STATUS_SUCCESS != status)
    return false;

  path->assign(name->ObjectName.Buffer, name->ObjectName.Length /
                                        sizeof(name->ObjectName.Buffer[0]));
  return true;
}

};  // namespace sandbox

// TODO(cpu): This is not the final code we want here but we are yet
// to understand what is going on. See bug 11789.
void ResolveNTFunctionPtr(const char* name, void* ptr) {
  static HMODULE ntdll = ::GetModuleHandle(sandbox::kNtdllName);

  FARPROC* function_ptr = reinterpret_cast<FARPROC*>(ptr);
  *function_ptr = ::GetProcAddress(ntdll, name);
  if (*function_ptr)
    return;
  // We have data that re-trying helps.
  *function_ptr = ::GetProcAddress(ntdll, name);
  CHECK(*function_ptr);
}
<|endoftext|>


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

  Program:   Insight Segmentation & Registration Toolkit
  Module:    BiasCorrector.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

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

=========================================================================*/
#include <string>
#include <vector>
#include <vnl/vnl_math.h>

#include "mydefs.h"
#include "imageutils.h"
#include "OptionList.h"
#include "itkMRIBiasFieldCorrectionFilter.h"

void print_usage()
{
  print_line("MRIBiasCorrection 1.0 (21.June.2001)");

  print_line("usage: BiasCorrector --input file" ) ;
  print_line("       --output file") ;
  print_line("       --class-mean mean(1) ... mean(i)" ) ;
  print_line("       --class-sigma sigma(1) ... sigma(i)" ) ;
  print_line("       --use-log [yes|no]") ;
  print_line("       [--input-mask file]" ) ;
  print_line("       [--output-mask file]" ) ;
  print_line("       [--degree int] ") ;
  print_line("       [--growth double] [--shrink double] [--max-iteration int]");
  print_line("       [--init-step-size double] ");
  print_line("       [--use-slab-identification [yes|no]]") ;
  print_line("       [--slice-direction [0-2]]" ) ;

  print_line("");

  print_line("--input file") ;
  print_line("        input image file name [meta image format]" );
  print_line("--output file") ;
  print_line("        output image file name [meta image format]" );
  print_line("--class-mean mean(1),...,mean(i)" ) ;
  print_line("        intensity means  of the differen i tissue classes") ;
  print_line("--class-sigma sig(1),...,sig(i)" ) ;
  print_line("        intensity sigmas of the different i tissue clases") ;
  print_line("        NOTE: The sigmas should be listed in the SAME ORDER") ;
  print_line("              of means");
  print_line("        and each value should be SEPERATED BY A SPACE)") ;
  print_line("--input-mask file" ) ;
  print_line("        mask input with file [meta image format]");
  print_line("--output-mask file" ) ;
  print_line("        mask output with file [meta image format]");
  print_line("--degree int") ;
  print_line("        degree of legendre polynomial used for the") ;
  print_line("        approximation of the bias field" );
  print_line("--use-log [yes|no]") ;
  print_line("        if yes, assume a multiplicative bias field") ;
  print_line("        (use log of image, class-mean, class-sigma,") ;
  print_line("         and init-step-size)" );
  print_line("--growth double") ;
  print_line("        stepsize growth factor. must be greater than 1.0") ;
  print_line("        [default 1.05]" ) ;
  print_line("--shrink double") ;
  print_line("        stepsize shrink factor ") ;
  print_line("        [default growth^(-0.25)]" ) ;
  print_line("--max-iteration int") ;
  print_line("        maximal number of iterations") ;
  print_line("        [default 20]" ) ;
  print_line("--init-step-size double") ;
  print_line("        inital step size [default 1.02]" );
  print_line("--use-slab-identification [yes|no]") ;
  print_line("       if yes, the bias correction will first identify slabs,") ;
  print_line("       and then apply the bias correction to each slab") ;
  print_line("--slice-direction [0-2]" ) ;
  print_line("        slice creation direction ( 0 - x axis, 1 - y axis") ;
  print_line("        2 - z axis) [default 2]") ;

  print_line("");

  print_line("example: BiasCorrector --input sample.mhd") ;
  print_line("         --output sample.corrected.mhd") ;
  print_line("         --class-mean 1500 570") ;
  print_line("         --class-sigma 100 70 --use-log yes");
  print_line("         --input-mask sample.mask.mhd ") ;
  print_line("         --output-mask sample.mask2.mhd ") ;
  print_line("         --degree 3 --growth 1.05 --shrink 0.9");
  print_line("         --max-iteration 2000 --init-step-size 1.1") ;
  print_line("         --use-slab-identification no") ;
  print_line("         --slice-direction 2") ;
}

int main(int argc, char* argv[])
{
  if (argc <= 1)
    {
      print_usage() ;
      exit(0) ;
    }

  OptionList options(argc, argv) ;

  typedef itk::MRIBiasFieldCorrectionFilter<ImageType, ImageType> Corrector ;
  Corrector::Pointer filter = Corrector::New() ;

  std::string inputFileName ;
  std::string outputFileName ;
  std::string inputMaskFileName = "" ;
  std::string outputMaskFileName = "" ;
  bool useLog ;
  int degree ;
  int sliceDirection ;
  vnl_vector<double> coefficientVector ;
  itk::Array<double> classMeans ;
  itk::Array<double> classSigmas ;
  int maximumIteration ;
  double initialRadius ;
  double growth ;
  double shrink ;

  bool usingSlabIdentification ;

  try
    {
      // get image file options
      options.GetStringOption("input", &inputFileName, true) ;
      options.GetStringOption("output", &outputFileName, true) ;
      options.GetStringOption("input-mask", &inputMaskFileName, false) ;
      options.GetStringOption("output-mask", &outputMaskFileName, false) ;

      // get bias field options
      useLog = options.GetBooleanOption("use-log", true, true) ;
      degree = options.GetIntOption("degree", 3, false) ;
      sliceDirection = options.GetIntOption("slice-direction", 2, false) ;

      // get energyfunction options
      options.GetMultiDoubleOption("class-mean", &classMeans, true) ;
      options.GetMultiDoubleOption("class-sigma", &classSigmas, true) ;

      // get optimizer options
      maximumIteration = options.GetIntOption("max-iteration", 20, false) ;
      growth = options.GetDoubleOption("growth", 1.05, false) ;
      shrink = pow(growth, -0.25) ;
      shrink = options.GetDoubleOption("shrink", shrink, false) ;
      initialRadius = options.GetDoubleOption("init-step-size", 1.02, false) ;

      // get the filter operation option
      usingSlabIdentification =
        options.GetBooleanOption("use-slab-identification", false, false) ;
    }
  catch(OptionList::RequiredOptionMissing e)
    {
      std::cout << "Error: The '" << e.OptionTag
                << "' option is required but missing."
                << std::endl ;
    }

  // load images
  ImagePointer input = ImageType::New() ;
  MaskPointer inputMask = MaskType::New() ;
  MaskPointer outputMask = MaskType::New() ;

  try
    {
      std::cout << "Loading images..." << std::endl ;
      loadImage(inputFileName, input) ;
      filter->SetInput(input) ;
      std::cout << "Input image loaded." << std::endl ;
      if (inputMaskFileName != "")
        {
          loadMask(inputMaskFileName, inputMask) ;
          filter->SetInputMask(inputMask) ;
          std::cout << "Input mask image loaded." << std::endl ;
        }
      if (outputMaskFileName != "")
        {
          loadMask(outputMaskFileName, outputMask) ;
          filter->SetOutputMask(outputMask) ;
          std::cout << "Output mask image loaded." << std::endl ;
        }
      std::cout << "Images loaded." << std::endl ;
    }
  catch (ImageIOError e)
    {
      std::cout << "Error: " << e.Operation << " file name:"
                << e.FileName << std::endl ;
      exit(0) ;
    }

  ImagePointer output = ImageType::New() ;
  output->SetLargestPossibleRegion(input->GetLargestPossibleRegion()) ;
  output->SetRequestedRegion(input->GetLargestPossibleRegion()) ;

  filter->SetOutput(output) ;

  filter->IsBiasFieldMultiplicative(useLog) ;
  filter->SetTissueClassStatistics(classMeans, classSigmas) ;
  filter->SetOptimizerGrowthFactor(growth) ;
  filter->SetOptimizerShrinkFactor(shrink) ;
  filter->SetOptimizerMaximumIteration(maximumIteration) ;
  filter->SetOptimizerInitialRadius(initialRadius) ;
  filter->SetBiasFieldDegree(degree) ;
  filter->SetUsingSlabIdentification(usingSlabIdentification) ;
  filter->SetSlicingDirection(sliceDirection) ;
  filter->Update() ;

  std::cout << "Writing the output image..." << std::endl ;

  try
    {
      writeImage(outputFileName, output) ;
    }
  catch (ImageIOError e)
    {
      std::cout << "Error: " << e.Operation << " file name:"
                << e.FileName << std::endl ;
      exit(0) ;
    }

  return 0 ;
}
<commit_msg>ERR: warnings about possible uninitialized variables.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    BiasCorrector.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

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

=========================================================================*/
#include <string>
#include <vector>
#include <vnl/vnl_math.h>

#include "mydefs.h"
#include "imageutils.h"
#include "OptionList.h"
#include "itkMRIBiasFieldCorrectionFilter.h"

void print_usage()
{
  print_line("MRIBiasCorrection 1.0 (21.June.2001)");

  print_line("usage: BiasCorrector --input file" ) ;
  print_line("       --output file") ;
  print_line("       --class-mean mean(1) ... mean(i)" ) ;
  print_line("       --class-sigma sigma(1) ... sigma(i)" ) ;
  print_line("       --use-log [yes|no]") ;
  print_line("       [--input-mask file]" ) ;
  print_line("       [--output-mask file]" ) ;
  print_line("       [--degree int] ") ;
  print_line("       [--growth double] [--shrink double] [--max-iteration int]");
  print_line("       [--init-step-size double] ");
  print_line("       [--use-slab-identification [yes|no]]") ;
  print_line("       [--slice-direction [0-2]]" ) ;

  print_line("");

  print_line("--input file") ;
  print_line("        input image file name [meta image format]" );
  print_line("--output file") ;
  print_line("        output image file name [meta image format]" );
  print_line("--class-mean mean(1),...,mean(i)" ) ;
  print_line("        intensity means  of the differen i tissue classes") ;
  print_line("--class-sigma sig(1),...,sig(i)" ) ;
  print_line("        intensity sigmas of the different i tissue clases") ;
  print_line("        NOTE: The sigmas should be listed in the SAME ORDER") ;
  print_line("              of means");
  print_line("        and each value should be SEPERATED BY A SPACE)") ;
  print_line("--input-mask file" ) ;
  print_line("        mask input with file [meta image format]");
  print_line("--output-mask file" ) ;
  print_line("        mask output with file [meta image format]");
  print_line("--degree int") ;
  print_line("        degree of legendre polynomial used for the") ;
  print_line("        approximation of the bias field" );
  print_line("--use-log [yes|no]") ;
  print_line("        if yes, assume a multiplicative bias field") ;
  print_line("        (use log of image, class-mean, class-sigma,") ;
  print_line("         and init-step-size)" );
  print_line("--growth double") ;
  print_line("        stepsize growth factor. must be greater than 1.0") ;
  print_line("        [default 1.05]" ) ;
  print_line("--shrink double") ;
  print_line("        stepsize shrink factor ") ;
  print_line("        [default growth^(-0.25)]" ) ;
  print_line("--max-iteration int") ;
  print_line("        maximal number of iterations") ;
  print_line("        [default 20]" ) ;
  print_line("--init-step-size double") ;
  print_line("        inital step size [default 1.02]" );
  print_line("--use-slab-identification [yes|no]") ;
  print_line("       if yes, the bias correction will first identify slabs,") ;
  print_line("       and then apply the bias correction to each slab") ;
  print_line("--slice-direction [0-2]" ) ;
  print_line("        slice creation direction ( 0 - x axis, 1 - y axis") ;
  print_line("        2 - z axis) [default 2]") ;

  print_line("");

  print_line("example: BiasCorrector --input sample.mhd") ;
  print_line("         --output sample.corrected.mhd") ;
  print_line("         --class-mean 1500 570") ;
  print_line("         --class-sigma 100 70 --use-log yes");
  print_line("         --input-mask sample.mask.mhd ") ;
  print_line("         --output-mask sample.mask2.mhd ") ;
  print_line("         --degree 3 --growth 1.05 --shrink 0.9");
  print_line("         --max-iteration 2000 --init-step-size 1.1") ;
  print_line("         --use-slab-identification no") ;
  print_line("         --slice-direction 2") ;
}

int main(int argc, char* argv[])
{
  if (argc <= 1)
    {
      print_usage() ;
      exit(0) ;
    }

  OptionList options(argc, argv) ;

  typedef itk::MRIBiasFieldCorrectionFilter<ImageType, ImageType> Corrector ;
  Corrector::Pointer filter = Corrector::New() ;

  std::string inputFileName ;
  std::string outputFileName ;
  std::string inputMaskFileName = "" ;
  std::string outputMaskFileName = "" ;
  bool useLog = true;
  int degree = 3;
  int sliceDirection = 2;
  vnl_vector<double> coefficientVector ;
  itk::Array<double> classMeans ;
  itk::Array<double> classSigmas ;
  int maximumIteration = 20;
  double initialRadius ;
  double growth = 1.05;
  double shrink = 0.0;

  bool usingSlabIdentification = false;

  try
    {
      // get image file options
      options.GetStringOption("input", &inputFileName, true) ;
      options.GetStringOption("output", &outputFileName, true) ;
      options.GetStringOption("input-mask", &inputMaskFileName, false) ;
      options.GetStringOption("output-mask", &outputMaskFileName, false) ;

      // get bias field options
      useLog = options.GetBooleanOption("use-log", true, true) ;
      degree = options.GetIntOption("degree", 3, false) ;
      sliceDirection = options.GetIntOption("slice-direction", 2, false) ;

      // get energyfunction options
      options.GetMultiDoubleOption("class-mean", &classMeans, true) ;
      options.GetMultiDoubleOption("class-sigma", &classSigmas, true) ;

      // get optimizer options
      maximumIteration = options.GetIntOption("max-iteration", 20, false) ;
      growth = options.GetDoubleOption("growth", 1.05, false) ;
      shrink = pow(growth, -0.25) ;
      shrink = options.GetDoubleOption("shrink", shrink, false) ;
      initialRadius = options.GetDoubleOption("init-step-size", 1.02, false) ;

      // get the filter operation option
      usingSlabIdentification =
        options.GetBooleanOption("use-slab-identification", false, false) ;
    }
  catch(OptionList::RequiredOptionMissing e)
    {
      std::cout << "Error: The '" << e.OptionTag
                << "' option is required but missing."
                << std::endl ;
    }

  // load images
  ImagePointer input = ImageType::New() ;
  MaskPointer inputMask = MaskType::New() ;
  MaskPointer outputMask = MaskType::New() ;

  try
    {
      std::cout << "Loading images..." << std::endl ;
      loadImage(inputFileName, input) ;
      filter->SetInput(input) ;
      std::cout << "Input image loaded." << std::endl ;
      if (inputMaskFileName != "")
        {
          loadMask(inputMaskFileName, inputMask) ;
          filter->SetInputMask(inputMask) ;
          std::cout << "Input mask image loaded." << std::endl ;
        }
      if (outputMaskFileName != "")
        {
          loadMask(outputMaskFileName, outputMask) ;
          filter->SetOutputMask(outputMask) ;
          std::cout << "Output mask image loaded." << std::endl ;
        }
      std::cout << "Images loaded." << std::endl ;
    }
  catch (ImageIOError e)
    {
      std::cout << "Error: " << e.Operation << " file name:"
                << e.FileName << std::endl ;
      exit(0) ;
    }

  ImagePointer output = ImageType::New() ;
  output->SetLargestPossibleRegion(input->GetLargestPossibleRegion()) ;
  output->SetRequestedRegion(input->GetLargestPossibleRegion()) ;

  filter->SetOutput(output) ;

  filter->IsBiasFieldMultiplicative(useLog) ;
  filter->SetTissueClassStatistics(classMeans, classSigmas) ;
  filter->SetOptimizerGrowthFactor(growth) ;
  filter->SetOptimizerShrinkFactor(shrink) ;
  filter->SetOptimizerMaximumIteration(maximumIteration) ;
  filter->SetOptimizerInitialRadius(initialRadius) ;
  filter->SetBiasFieldDegree(degree) ;
  filter->SetUsingSlabIdentification(usingSlabIdentification) ;
  filter->SetSlicingDirection(sliceDirection) ;
  filter->Update() ;

  std::cout << "Writing the output image..." << std::endl ;

  try
    {
      writeImage(outputFileName, output) ;
    }
  catch (ImageIOError e)
    {
      std::cout << "Error: " << e.Operation << " file name:"
                << e.FileName << std::endl ;
      exit(0) ;
    }

  return 0 ;
}
<|endoftext|>


<commit_before>/*
 * (c) 2015 Raghavendra Nayak, All Rights Reserved.
 * www.openguru.com/
 */

#include <iostream>
#include <string>

// Window is the abstract base for all concrete Window implementations
class Window {
public:
    Window() {
    }
    virtual ~Window() {
    }
    virtual void draw() = 0;
};

// MainWindow is a type of Window
class MainWindow : public Window {
    int height;
    int width;
    std::string windowName;
public:
    MainWindow(const std::string& name, int height, int width)
        : height(height), width(width), windowName(name) {
    }
    ~MainWindow() {
    }

    std::string name() {
        return windowName;
    }

    virtual void draw() {
        std::cout << "Rendering the MainWindow: " << name()
            << " with height: " << height << ", width: " << width << std::endl;
    }
};

// SimpleWindow does not have any name
class SimpleWindow : public Window {
    int height;
    int width;
public:
    SimpleWindow(int height, int width)
        : height(height), width(width) {
    }
    ~SimpleWindow() {
    }

    virtual void draw() {
        std::cout << "Rendering the SimpleWindow: "
            << " with height: " << height << ", width: " << width << std::endl;
    }
};

// Below class is a decorator or wrapper
class WindowDecorator : public Window {
    // Here we store the reference
    Window& decoratedWindow;
public:
    // Constructor
    WindowDecorator(Window& window)
        : decoratedWindow(window) {
    }
    virtual ~WindowDecorator() {
    }

    // Call our wrapper object's function
    virtual void draw() {
        decoratedWindow.draw();
    }
};

class MenubarDecorator : public WindowDecorator {
    void drawMenuBar() {
        std::cout << "Drawing the Menu bar. " << std::endl;
    }
public:
    MenubarDecorator(Window& decoratedWindow)
        : WindowDecorator(decoratedWindow) {
    }
    ~MenubarDecorator() {
    }

    virtual void draw() {
        // Draw Wrapped Window first as it is in the background
        WindowDecorator::draw();
        // Now draw the actual menu bar
        drawMenuBar();
    }
};

class StatusbarDecorator : public WindowDecorator {
    void drawStatusbar() {
        std::cout << "Drawing the Status bar." << std::endl;
    }
public:
    StatusbarDecorator(Window& decoratedWindow)
        : WindowDecorator(decoratedWindow) {
    }
    ~StatusbarDecorator() {
    }

    virtual void draw() {
        // Draw Wrapped Window first as it is in the background
        WindowDecorator::draw();

        // Now draw the actual menu bar
        drawStatusbar();
    }
};

int main(int argc, char **argv)
{
    // Draw a MainWindow
    MainWindow mainWindow("simple window", 1024, 768);
    mainWindow.draw();

    // Now for the same MainWindow we can add the menubar
    // via MenubarDecorator
    MenubarDecorator windowWithMenubar(mainWindow);
    windowWithMenubar.draw();

    // Now we can add Statusbar via StatusbarDecorator
    StatusbarDecorator windowWithMenubarAndStatusBar(windowWithMenubar);
    windowWithMenubarAndStatusBar.draw();

    // Draw a simpleWindow
    SimpleWindow simpleWindow(1024, 768);
    simpleWindow.draw();

    // Now lets decorate SimpleWindow with Menubar
    MenubarDecorator simpleWindowWithMenubar(simpleWindow);
    simpleWindowWithMenubar.draw();

    return 0;
}<commit_msg>Modified to improve the clarity.<commit_after>/*
 * (c) 2015 Raghavendra Nayak, All Rights Reserved.
 * www.openguru.com/
 */

#include <iostream>
#include <string>

// Window is the abstract base for all concrete Window implementations
class Window {
    std::string windowName;
public:
    Window(const std::string& windowName)
        : windowName(windowName) {
    }
    Window() {
    }
    virtual ~Window() {
    }
    virtual std::string name() {
        return windowName;
    }
    virtual void draw() = 0;
};

// MainWindow is a type of Window
class MainWindow : public Window {
    int height;
    int width;
public:
    MainWindow(const std::string& windowName, int height, int width)
        : Window(windowName), height(height), width(width) {
    }
    ~MainWindow() {
    }

    virtual void draw() {
        std::cout << "Rendering the MainWindow: [" << name()
            << "] with height: " << height << ", width: " << width << std::endl;
    }
};

// SquareWindow have same height & width
class SquareWindow : public Window {
    int dimension;

public:
    SquareWindow(const std::string& windowName, int dimension)
        : Window(windowName), dimension(dimension) {
    }
    ~SquareWindow() {
    }

    virtual void draw() {
        std::cout << "Rendering the SquareWindow: [" << name()
            << "] with dimensions: " << dimension << std::endl;
    }
};

// Below class is a decorator or wrapper
class WindowDecorator : public Window {
    // Here we store the reference
    Window& decoratedWindow;
public:
    // Constructor
    WindowDecorator(Window& window)
        : decoratedWindow(window) {
    }
    virtual ~WindowDecorator() {
    }

    // Call our wrapper object's function
    virtual std::string name() {
        return decoratedWindow.name();
    }

    // Call our wrapper object's function
    virtual void draw() {
        decoratedWindow.draw();
    }
};

class MenubarDecorator : public WindowDecorator {
    void drawMenuBar() {
        std::cout << "Drawing the Menu bar for ["
            << WindowDecorator::name() << "]" << std::endl;
    }
public:
    MenubarDecorator(Window& decoratedWindow)
        : WindowDecorator(decoratedWindow) {
    }
    ~MenubarDecorator() {
    }

    virtual std::string name() {
        return WindowDecorator::name();
    }

    virtual void draw() {
        // Draw Wrapped Window first as it is in the background
        WindowDecorator::draw();
        // Now draw the actual menu bar
        drawMenuBar();
    }
};

class StatusbarDecorator : public WindowDecorator {
    void drawStatusbar() {
        std::cout << "Drawing the Status bar for ["
            << WindowDecorator::name() << "]" << std::endl;
    }
public:
    StatusbarDecorator(Window& decoratedWindow)
        : WindowDecorator(decoratedWindow) {
    }
    ~StatusbarDecorator() {
    }

    virtual std::string name() {
        return WindowDecorator::name();
    }

    virtual void draw() {
        // Draw Wrapped Window first as it is in the background
        WindowDecorator::draw();

        // Now draw the actual menu bar
        drawStatusbar();
    }
};

int main(int argc, char **argv)
{
    // Draw a MainWindow
    MainWindow mainWindow("Main window", 1024, 768);
    mainWindow.draw();

    // Now for the same MainWindow we can add the menubar
    // via MenubarDecorator
    MenubarDecorator windowWithMenubar(mainWindow);
    windowWithMenubar.draw();

    // Now we can add Statusbar via StatusbarDecorator
    StatusbarDecorator windowWithMenubarAndStatusBar(windowWithMenubar);
    windowWithMenubarAndStatusBar.draw();

    // Draw a squareWindow
    SquareWindow squareWindow("Square Window", 1024);
    squareWindow.draw();

    // Now lets decorate SquareWindow with Menubar
    MenubarDecorator squareWindowWithMenubar(squareWindow);
    squareWindowWithMenubar.draw();

    return 0;
}<|endoftext|>


<commit_before>// Copyright (c) 2020 by Apex.AI Inc. All rights reserved.
//
// 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.

#ifndef IOX_UTILS_CONCURRENT_PERIODIC_TASK_HPP
#define IOX_UTILS_CONCURRENT_PERIODIC_TASK_HPP

#include "iceoryx_utils/cxx/string.hpp"
#include "iceoryx_utils/internal/units/duration.hpp"
#include "iceoryx_utils/posix_wrapper/semaphore.hpp"
#include "iceoryx_utils/posix_wrapper/thread.hpp"

#include <thread>

namespace iox
{
namespace concurrent
{
/// @brief This class periodically executes a callable specified by the template parameter.
///        This can be a struct with a `operator()()` overload, a `cxx::function_ref<void()>` or `std::fuction<void()>`
/// @tparam T is a callable type without function parameters
template <typename T>
class PeriodicTask
{
  public:
    /// @brief Creates a periodic task. The specified callable is stored but not executed.
    /// To run the task, `void start(const units::Duration interval)` must be called.
    /// @tparam Args are variadic template parameter for which are forwarded to the underlying callable object
    /// @param[in] taskName will be set as thread name
    /// @param[in] args are forwarded to the underlying callable object
    template <typename... Args>
    PeriodicTask(const posix::ThreadName_t taskName, Args&&... args) noexcept;

    /// @brief Creates a periodic task by spawning a thread. The specified callable is executed immediately on creation
    /// and then periodically after the interval duration.
    /// @tparam Args are variadic template parameter for which are forwarded to the underlying callable object
    /// @param[in] interval is the time the thread waits between two invocations of the callable
    /// @param[in] taskName will be set as thread name
    /// @param[in] args are forwarded to the underlying callable object
    template <typename... Args>
    PeriodicTask(const units::Duration interval, const posix::ThreadName_t taskName, Args&&... args) noexcept;

    /// @brief Stops and joins the thread spawned by the constructor.
    /// @note This is blocking and the blocking time depends on the callable.
    ~PeriodicTask() noexcept;

    PeriodicTask(const PeriodicTask&) = delete;
    PeriodicTask(PeriodicTask&&) = delete;

    PeriodicTask& operator=(const PeriodicTask&) = delete;
    PeriodicTask& operator=(PeriodicTask&&) = delete;

    /// @brief Spawns a thread and immediately executes the callable specified with the constructor.
    /// The execution is repeated after the specified interval is passed.
    /// @param[in] interval is the time the thread waits between two invocations of the callable
    /// @attention If the PeriodicTask instance has already a running thread, this will be stopped and started again
    /// with the new interval. This might take some time if a slow task is executing during this call.
    void start(const units::Duration interval) noexcept;

    /// @brief This stops the thread if it's running, otherwise does nothing. When this method returns, the thread is
    /// stopped.
    /// @attention This might take some time if a slow task is executing during this call.
    void stop() noexcept;

    /// @brief This method check if a thread is spawned and running, potentially executing a task.
    /// @return true if the thread is running, false otherwise.
    bool isActive() const noexcept;

  private:
    void run() noexcept;

  private:
    T m_callable;
    posix::ThreadName_t m_taskName;
    units::Duration m_interval{units::Duration::milliseconds<long double>(0.0)};
    /// @todo use a refactored posix::Timer object once available
    posix::Semaphore m_stop{posix::Semaphore::create(posix::CreateUnnamedSingleProcessSemaphore, 0U).value()};
    std::thread m_taskExecutor;
};

} // namespace concurrent
} // namespace iox

#include "iceoryx_utils/internal/concurrent/periodic_task.inl"

#endif // IOX_UTILS_CONCURRENT_PERIODIC_TASK_HPP
<commit_msg>iox-#489 Update PeriodicTask documentation<commit_after>// Copyright (c) 2020 by Apex.AI Inc. All rights reserved.
//
// 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.

#ifndef IOX_UTILS_CONCURRENT_PERIODIC_TASK_HPP
#define IOX_UTILS_CONCURRENT_PERIODIC_TASK_HPP

#include "iceoryx_utils/cxx/string.hpp"
#include "iceoryx_utils/internal/units/duration.hpp"
#include "iceoryx_utils/posix_wrapper/semaphore.hpp"
#include "iceoryx_utils/posix_wrapper/thread.hpp"

#include <thread>

namespace iox
{
namespace concurrent
{
/// @brief This class periodically executes a callable specified by the template parameter.
///        This can be a struct with a `operator()()` overload, a `cxx::function_ref<void()>` or `std::fuction<void()>`.
/// @note Currently execution time of the callable is added to the interval.
/// @tparam T is a callable type without function parameters
template <typename T>
class PeriodicTask
{
  public:
    /// @brief Creates a periodic task. The specified callable is stored but not executed.
    /// To run the task, `void start(const units::Duration interval)` must be called.
    /// @tparam Args are variadic template parameter for which are forwarded to the underlying callable object
    /// @param[in] taskName will be set as thread name
    /// @param[in] args are forwarded to the underlying callable object
    template <typename... Args>
    PeriodicTask(const posix::ThreadName_t taskName, Args&&... args) noexcept;

    /// @brief Creates a periodic task by spawning a thread. The specified callable is executed immediately on creation
    /// and then periodically after the interval duration.
    /// @tparam Args are variadic template parameter for which are forwarded to the underlying callable object
    /// @param[in] interval is the time the thread waits between two invocations of the callable
    /// @param[in] taskName will be set as thread name
    /// @param[in] args are forwarded to the underlying callable object
    template <typename... Args>
    PeriodicTask(const units::Duration interval, const posix::ThreadName_t taskName, Args&&... args) noexcept;

    /// @brief Stops and joins the thread spawned by the constructor.
    /// @note This is blocking and the blocking time depends on the callable.
    ~PeriodicTask() noexcept;

    PeriodicTask(const PeriodicTask&) = delete;
    PeriodicTask(PeriodicTask&&) = delete;

    PeriodicTask& operator=(const PeriodicTask&) = delete;
    PeriodicTask& operator=(PeriodicTask&&) = delete;

    /// @brief Spawns a thread and immediately executes the callable specified with the constructor.
    /// The execution is repeated after the specified interval is passed.
    /// @param[in] interval is the time the thread waits between two invocations of the callable
    /// @attention If the PeriodicTask instance has already a running thread, this will be stopped and started again
    /// with the new interval. This might take some time if a slow task is executing during this call.
    void start(const units::Duration interval) noexcept;

    /// @brief This stops the thread if it's running, otherwise does nothing. When this method returns, the thread is
    /// stopped.
    /// @attention This might take some time if a slow task is executing during this call.
    void stop() noexcept;

    /// @brief This method check if a thread is spawned and running, potentially executing a task.
    /// @return true if the thread is running, false otherwise.
    bool isActive() const noexcept;

  private:
    void run() noexcept;

  private:
    T m_callable;
    posix::ThreadName_t m_taskName;
    units::Duration m_interval{units::Duration::milliseconds<long double>(0.0)};
    /// @todo use a refactored posix::Timer object once available
    posix::Semaphore m_stop{posix::Semaphore::create(posix::CreateUnnamedSingleProcessSemaphore, 0U).value()};
    std::thread m_taskExecutor;
};

} // namespace concurrent
} // namespace iox

#include "iceoryx_utils/internal/concurrent/periodic_task.inl"

#endif // IOX_UTILS_CONCURRENT_PERIODIC_TASK_HPP
<|endoftext|>


<commit_before><commit_msg>Displaying results.<commit_after><|endoftext|>


<commit_before>#include "stdafx.h"

#include <graphics/dynamictexture.h>

#include "fogrenderer.h"
#include <temple/dll.h>
#include <common.h>

using namespace gfx;

#pragma pack(push, 1)
struct FogOfWarVertex {
	XMFLOAT3 pos;
	XMFLOAT2 uv;
};
#pragma pack(pop)

FogOfWarRenderer::FogOfWarRenderer(MdfMaterialFactory& mdfFactory, RenderingDevice& device)
	: mMdfFactory(mdfFactory),
	  mDevice(device),
	  mNumSubtilesX(temple::GetRef<uint32_t>(0x10820458)),
	  mNumSubtilesY(temple::GetRef<uint32_t>(0x10824490)) {

	mBlurredFogWidth = (mNumSubtilesX / 32) * 32 + 32; // Has to be a multiple of 4
	mBlurredFogHeight = (mNumSubtilesY / 32) * 32 + 32;

	mBlurredFogTexture = mDevice.CreateDynamicTexture(D3DFMT_A8, mBlurredFogWidth, mBlurredFogHeight);
	mBlurredFog.resize(mBlurredFogWidth * mBlurredFogHeight);

	auto vs = device.GetShaders().LoadVertexShader("fogofwar_vs");
	auto ps = device.GetShaders().LoadPixelShader("fogofwar_ps");
	BlendState blendState;
	blendState.blendEnable = true;
	blendState.srcBlend = D3DBLEND_SRCALPHA;
	blendState.destBlend = D3DBLEND_INVSRCALPHA;
	DepthStencilState depthStencilState;
	depthStencilState.depthEnable = false;
	RasterizerState rasterizerState;
	// rasterizerState.cullMode = D3DCULL_NONE;
	SamplerState samplerState;
	samplerState.addressU = D3DTADDRESS_CLAMP;
	samplerState.addressV = D3DTADDRESS_CLAMP;
	std::vector<MaterialSamplerBinding> samplers{
		MaterialSamplerBinding(mBlurredFogTexture, samplerState)
	};

	mMaterial = std::make_unique<Material>(blendState, depthStencilState, rasterizerState, samplers, vs, ps);

	uint16_t indices[6] { 0, 2, 1, 2, 0, 3 };
	mIndexBuffer = device.CreateIndexBuffer(indices);
	mVertexBuffer = device.CreateEmptyVertexBuffer(sizeof(FogOfWarVertex) * 4);

	mBufferBinding.AddBuffer(mVertexBuffer, 0, sizeof(FogOfWarVertex))
	              .AddElement(VertexElementType::Float3, VertexElementSemantic::Position)
	              .AddElement(VertexElementType::Float2, VertexElementSemantic::TexCoord);
}

struct FogBlurKernel {
	// 4 kernels (shifted by 0,1,2,3 pixels right), each has
	// 5 rows with 8 columns (for shift-compensation)
	uint8_t patterns[4][5][8]; // [xShift][y][x]
	FogBlurKernel() {
		memset(patterns, 0, sizeof(patterns));
	}

	static FogBlurKernel Create(uint8_t totalPatternValue);
};

void FogOfWarRenderer::Render() {
	static auto& sFoggingEnabled = temple::GetRef<uint32_t>(0x108254A0);
	if (!(sFoggingEnabled & 1)) {
		return;
	}

	// Reset the blurred buffer
	std::fill(mBlurredFog.begin(), mBlurredFog.end(), 0);

	static auto sOpaquePattern = FogBlurKernel::Create(0xFF);
	static auto sHalfTransparentPattern = FogBlurKernel::Create(0xA0);

	static auto& fogCheckData = temple::GetRef<uint8_t*>(0x108A5498);

	// Get [1,1] of the subtile data
	auto fogCheckSubtile = &fogCheckData[mNumSubtilesX + 1];

	for (size_t y = 1; y < mNumSubtilesY - 1; y++) {
		for (size_t x = 1; x < mNumSubtilesX - 1; x++) {
			auto fogState = *fogCheckSubtile;

			// Bit 2 -> Currently in LoS of the party
			if (!(fogState & 2)) {
				uint8_t* patternSrc;
				// Bit 3 -> Explored
				if (fogState & 4) {
					patternSrc = &sHalfTransparentPattern.patterns[x & 3][0][0];
				} else {
					patternSrc = &sOpaquePattern.patterns[x & 3][0][0];
				}

				// Now we copy 5 rows of 2 dwords each, to apply
				// the filter-kernel to the blurred fog map
				for (auto row = 0; row < 5; ++row) {
					auto src = (uint64_t*) &patternSrc[row * 8];
					auto roundedDownX = (x / 4) * 4;
					auto dest = (uint64_t*) &mBlurredFog[(y + row) * mBlurredFogWidth + roundedDownX];
					// Due to how the kernel is layed out, the individual bytes in this 8-byte addition will never carry
					// over to the next higher byte, thus this is equivalent to 8 separate 1-byte additions
					*dest += *src;
				}
			}
			++fogCheckSubtile;
		}

		// Skips the last subtile of the row and the first of the next row
		fogCheckSubtile += 2;

	}

	static auto& fogMinX = temple::GetRef<uint64_t>(0x10824468);
	static auto& fogMinY = temple::GetRef<uint64_t>(0x108EC4C8);

	auto mFogOriginX = (uint32_t) fogMinX;
	auto mFogOriginY = (uint32_t) fogMinY;

	mBlurredFogTexture->Update<uint8_t>({&mBlurredFog[0], mBlurredFog.size()});

	FogOfWarVertex mVertices[4];
	mVertices[0].pos.x = (mFogOriginX * 3) * INCH_PER_SUBTILE;
	mVertices[0].pos.y = 0;
	mVertices[0].pos.z = (mFogOriginY * 3) * INCH_PER_SUBTILE;
	mVertices[0].uv = {0, 0};

	mVertices[1].pos.x = (mFogOriginX * 3 + mBlurredFogWidth) * INCH_PER_SUBTILE;
	mVertices[1].pos.y = 0;
	mVertices[1].pos.z = (mFogOriginY * 3) * INCH_PER_SUBTILE;
	mVertices[1].uv = {1, 0};

	mVertices[2].pos.x = (mFogOriginX * 3 + mBlurredFogWidth) * INCH_PER_SUBTILE;
	mVertices[2].pos.y = 0;
	mVertices[2].pos.z = (mFogOriginY * 3 + mBlurredFogHeight) * INCH_PER_SUBTILE;
	mVertices[2].uv = {1, 1};

	mVertices[3].pos.x = (mFogOriginX * 3) * INCH_PER_SUBTILE;
	mVertices[3].pos.y = 0;
	mVertices[3].pos.z = (mFogOriginY * 3 + mBlurredFogHeight) * INCH_PER_SUBTILE;
	mVertices[3].uv = {0, 1};

	mVertexBuffer->Update<FogOfWarVertex>(mVertices);

	mBufferBinding.Bind();
	mDevice.GetDevice()->SetIndices(mIndexBuffer->GetBuffer());

	mDevice.SetMaterial(*mMaterial);
	mDevice.SetVertexShaderConstant(0, StandardSlotSemantic::ViewProjMatrix);

	mDevice.GetDevice()->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 4, 0, 2);

}

FogBlurKernel FogBlurKernel::Create(uint8_t totalPatternValue) {

	FogBlurKernel result;

	// Precompute 5x5 inverted blur kernel for distributing the total pattern value
	float weights[5][5];
	auto weightSum = 0.0f;
	auto weightOut = &weights[0][0];
	for (auto y = -2; y <= 2; y++) {
		for (auto x = -2; x <= 2; x++) {
			auto strength = 3.0f - sqrtf((float)(x * x + y * y));
			*weightOut++ = strength;
			weightSum += strength;
		}
	}

	// Now use the computed weights to calculate the actual pattern based on the requested total value
	auto patternSum = 0;

	for (auto y = 0; y < 5; ++y) {
		for (auto x = 0; x < 5; ++x) {
			auto pixelValue = (uint8_t)(weights[y][x] / weightSum * totalPatternValue);
			result.patterns[0][y][x] = pixelValue;
			patternSum += pixelValue;
		}
	}

	// This assigns any remainder of the total pattern value (loss due to rounding down above)
	// to the center pixel of the 5x5 kernel
	result.patterns[0][2][2] += totalPatternValue - patternSum;

	// Now create 3 versions of the pattern that are shifted by 1-3 pixels to the right
	// This is for optimization reasons since addition is done using 32-bit (4 bytes) addition
	// and the resulting patterns are in reality 8 pixels wide
	for (auto xShift = 1; xShift <= 3; ++xShift) {
		for (auto y = 0; y < 5; ++y) {
			for (auto x = 0; x < 5; ++x) {
				// Output here is shifted by {1,2,3} pixels right
				result.patterns[xShift][y][x + xShift] = result.patterns[0][y][x];
			}
		}
	}

	return result;
}

<commit_msg>Possible fix for flashing unexplored tiles when rendering fog.<commit_after>#include "stdafx.h"

#include <graphics/dynamictexture.h>

#include "fogrenderer.h"
#include <temple/dll.h>
#include <common.h>

using namespace gfx;

#pragma pack(push, 1)
struct FogOfWarVertex {
	XMFLOAT3 pos;
	XMFLOAT2 uv;
};
#pragma pack(pop)

FogOfWarRenderer::FogOfWarRenderer(MdfMaterialFactory& mdfFactory, RenderingDevice& device)
	: mMdfFactory(mdfFactory),
	  mDevice(device),
	  mNumSubtilesX(temple::GetRef<uint32_t>(0x10820458)),
	  mNumSubtilesY(temple::GetRef<uint32_t>(0x10824490)) {

	mBlurredFogWidth = (mNumSubtilesX / 4) * 4 + 8;
	mBlurredFogHeight = (mNumSubtilesY / 4) * 4 + 8;

	mBlurredFogTexture = mDevice.CreateDynamicTexture(D3DFMT_A8, mBlurredFogWidth, mBlurredFogHeight);
	mBlurredFog.resize(mBlurredFogWidth * mBlurredFogHeight);

	auto vs = device.GetShaders().LoadVertexShader("fogofwar_vs");
	auto ps = device.GetShaders().LoadPixelShader("fogofwar_ps");
	BlendState blendState;
	blendState.blendEnable = true;
	blendState.srcBlend = D3DBLEND_SRCALPHA;
	blendState.destBlend = D3DBLEND_INVSRCALPHA;
	DepthStencilState depthStencilState;
	depthStencilState.depthEnable = false;
	RasterizerState rasterizerState;
	SamplerState samplerState;
	samplerState.addressU = D3DTADDRESS_CLAMP;
	samplerState.addressV = D3DTADDRESS_CLAMP;
	samplerState.magFilter = D3DTEXF_LINEAR;
	samplerState.minFilter = D3DTEXF_LINEAR;
	std::vector<MaterialSamplerBinding> samplers{
		MaterialSamplerBinding(mBlurredFogTexture, samplerState)
	};

	mMaterial = std::make_unique<Material>(blendState, depthStencilState, rasterizerState, samplers, vs, ps);

	uint16_t indices[6]{0, 2, 1, 2, 0, 3};
	mIndexBuffer = device.CreateIndexBuffer(indices);
	mVertexBuffer = device.CreateEmptyVertexBuffer(sizeof(FogOfWarVertex) * 4);

	mBufferBinding.AddBuffer(mVertexBuffer, 0, sizeof(FogOfWarVertex))
	              .AddElement(VertexElementType::Float3, VertexElementSemantic::Position)
	              .AddElement(VertexElementType::Float2, VertexElementSemantic::TexCoord);
}

struct FogBlurKernel {
	// 4 kernels (shifted by 0,1,2,3 pixels right), each has
	// 5 rows with 8 columns (for shift-compensation)
	uint8_t patterns[4][5][8]; // [xShift][y][x]
	FogBlurKernel() {
		memset(patterns, 0, sizeof(patterns));
	}

	static FogBlurKernel Create(uint8_t totalPatternValue);
};

void FogOfWarRenderer::Render() {
	static auto& sFoggingEnabled = temple::GetRef<uint32_t>(0x108254A0);
	if (!(sFoggingEnabled & 1)) {
		return;
	}

	// Reset the blurred buffer
	std::fill(mBlurredFog.begin(), mBlurredFog.end(), 0);

	static auto sOpaquePattern = FogBlurKernel::Create(0xFF);
	static auto sHalfTransparentPattern = FogBlurKernel::Create(0xA0);

	static auto& fogCheckData = temple::GetRef<uint8_t*>(0x108A5498);

	// Get [0,0] of the subtile data
	auto fogCheckSubtile = &fogCheckData[0];

	for (size_t y = 0; y < mNumSubtilesY; y++) {
		for (size_t x = 0; x < mNumSubtilesX; x++) {
			auto fogState = *fogCheckSubtile;

			// Bit 2 -> Currently in LoS of the party
			if (!(fogState & 2)) {
				uint8_t* patternSrc;
				// Bit 3 -> Explored
				if (fogState & 4) {
					patternSrc = &sHalfTransparentPattern.patterns[x & 3][0][0];
				} else {
					patternSrc = &sOpaquePattern.patterns[x & 3][0][0];
				}

				// Now we copy 5 rows of 2 dwords each, to apply
				// the filter-kernel to the blurred fog map
				for (auto row = 0; row < 5; ++row) {
					auto src = (uint64_t*) &patternSrc[row * 8];
					auto roundedDownX = (x / 4) * 4;
					auto dest = (uint64_t*) &mBlurredFog[(y + row) * mBlurredFogWidth + roundedDownX];
					// Due to how the kernel is layed out, the individual bytes in this 8-byte addition will never carry
					// over to the next higher byte, thus this is equivalent to 8 separate 1-byte additions
					*dest += *src;
				}
			}
			++fogCheckSubtile;
		}

		// Skips the last subtile of the row and the first of the next row
		// fogCheckSubtile += 2;

	}

	static auto& fogMinX = temple::GetRef<uint64_t>(0x10824468);
	static auto& fogMinY = temple::GetRef<uint64_t>(0x108EC4C8);

	auto mFogOriginX = (uint32_t) fogMinX;
	auto mFogOriginY = (uint32_t) fogMinY;

	mBlurredFogTexture->Update<uint8_t>({&mBlurredFog[0], mBlurredFog.size()});

	// Use only the relevant subportion of the texture
	auto umin = 2.5f / (float)mBlurredFogWidth;
	auto vmin = 2.5f / (float)mBlurredFogHeight;
	auto umax = mNumSubtilesX / (float)mBlurredFogWidth;
	auto vmax = mNumSubtilesY / (float)mBlurredFogHeight;

	FogOfWarVertex mVertices[4];
	mVertices[0].pos.x = (mFogOriginX * 3) * INCH_PER_SUBTILE;
	mVertices[0].pos.y = 0;
	mVertices[0].pos.z = (mFogOriginY * 3) * INCH_PER_SUBTILE;
	mVertices[0].uv = {umin, vmin};

	mVertices[1].pos.x = (mFogOriginX * 3 + mNumSubtilesX) * INCH_PER_SUBTILE;
	mVertices[1].pos.y = 0;
	mVertices[1].pos.z = (mFogOriginY * 3) * INCH_PER_SUBTILE;
	mVertices[1].uv = {umax, vmin};

	mVertices[2].pos.x = (mFogOriginX * 3 + mNumSubtilesX) * INCH_PER_SUBTILE;
	mVertices[2].pos.y = 0;
	mVertices[2].pos.z = (mFogOriginY * 3 + mNumSubtilesY) * INCH_PER_SUBTILE;
	mVertices[2].uv = {umax, vmax};

	mVertices[3].pos.x = (mFogOriginX * 3) * INCH_PER_SUBTILE;
	mVertices[3].pos.y = 0;
	mVertices[3].pos.z = (mFogOriginY * 3 + mNumSubtilesY) * INCH_PER_SUBTILE;
	mVertices[3].uv = {umin, vmax};

	mVertexBuffer->Update<FogOfWarVertex>(mVertices);

	mBufferBinding.Bind();
	mDevice.GetDevice()->SetIndices(mIndexBuffer->GetBuffer());

	mDevice.SetMaterial(*mMaterial);
	mDevice.SetVertexShaderConstant(0, StandardSlotSemantic::ViewProjMatrix);

	mDevice.GetDevice()->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 4, 0, 2);

}

FogBlurKernel FogBlurKernel::Create(uint8_t totalPatternValue) {

	FogBlurKernel result;

	// Precompute 5x5 inverted blur kernel for distributing the total pattern value
	float weights[5][5];
	auto weightSum = 0.0f;
	auto weightOut = &weights[0][0];
	for (auto y = -2; y <= 2; y++) {
		for (auto x = -2; x <= 2; x++) {
			auto strength = 3.0f - sqrtf((float)(x * x + y * y));
			*weightOut++ = strength;
			weightSum += strength;
		}
	}

	// Now use the computed weights to calculate the actual pattern based on the requested total value
	auto patternSum = 0;

	for (auto y = 0; y < 5; ++y) {
		for (auto x = 0; x < 5; ++x) {
			auto pixelValue = (uint8_t)(weights[y][x] / weightSum * totalPatternValue);
			result.patterns[0][y][x] = pixelValue;
			patternSum += pixelValue;
		}
	}

	// This assigns any remainder of the total pattern value (loss due to rounding down above)
	// to the center pixel of the 5x5 kernel
	result.patterns[0][2][2] += totalPatternValue - patternSum;

	// Now create 3 versions of the pattern that are shifted by 1-3 pixels to the right
	// This is for optimization reasons since addition is done using 32-bit (4 bytes) addition
	// and the resulting patterns are in reality 8 pixels wide
	for (auto xShift = 1; xShift <= 3; ++xShift) {
		for (auto y = 0; y < 5; ++y) {
			for (auto x = 0; x < 5; ++x) {
				// Output here is shifted by {1,2,3} pixels right
				result.patterns[xShift][y][x + xShift] = result.patterns[0][y][x];
			}
		}
	}

	return result;
}

<|endoftext|>