<commit_before>#include "System.h"
System::System()
{
	this->m_inputHandler = NULL;
	this->m_window = NULL;
}

System::~System()
{
}

int System::Shutdown()
{
	int result = 0;
	//Destroy the display window
	SDL_DestroyWindow(m_window);
	//Quit SDL subsystems
	SDL_Quit();
	this->m_graphicsHandler->Shutdown();
	delete this->m_graphicsHandler;
	delete this->m_camera;
	this->m_inputHandler->Shutdown();
	delete this->m_inputHandler;
	this->m_physicsHandler.ShutDown();

	//Shutdown Network module
	this->m_networkModule.Shutdown();
	return result;

}

int System::Initialize()
{
	int result = 1;
	this->m_fullscreen = false;
	this->m_running = true;
	this->m_window = NULL;
	//Get the instance if this application
	this->m_hinstance = GetModuleHandle(NULL);

	if (SDL_Init(SDL_INIT_VIDEO) < 0)
	{
		printf("SDL failed in initializing the window! SDL_Error: %hS\n", SDL_GetError());
	}
	else
	{
		printf("SDL succeeded in initializing the window!\n");
	}

	m_window = SDL_CreateWindow("SSD Application", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
	if (m_window == NULL)
	{
		printf("Window creation failed! SDL_ERROR: %hS\n", SDL_GetError());
	}
	else
	{
		printf("Window creation succeeded!\n");

		SDL_SysWMinfo wmInfo;
		SDL_VERSION(&wmInfo.version);
		SDL_GetWindowWMInfo(m_window, &wmInfo);
		m_hwnd = wmInfo.info.win.window;
	}

	this->m_graphicsHandler = new GraphicsHandler();
	if (this->m_graphicsHandler->Initialize(&this->m_hwnd, DirectX::XMINT2(SCREEN_WIDTH, SCREEN_HEIGHT)))
	{
		printf("GraphicsHandler did not work. RIP!\n");
	}
	this->m_camera = new Camera();
	this->m_camera->Initialize();
	Camera* oldCam = this->m_graphicsHandler->SetCamera(this->m_camera);
	delete oldCam;
	oldCam = nullptr;
	//Initialize the PhysicsHandler
	this->m_physicsHandler.Initialize();

	//Initialize the InputHandler
	this->m_inputHandler = new InputHandler();
	this->m_inputHandler->Initialize(SCREEN_WIDTH, SCREEN_HEIGHT);

	//Init the network module
	this->m_networkModule.Initialize();

	return result;
}

//Do not place things here without talking to the system designers. Place any update method in the System::Update(float dt) method
int System::Run()
{
	int result = 0;
	LARGE_INTEGER frequency, currTime, prevTime, elapsedTime;
	QueryPerformanceFrequency(&frequency);
	//QueryPerformanceCounter(&prevTime);
	QueryPerformanceCounter(&currTime);
	while (this->m_running)
	{
		prevTime = currTime;
		QueryPerformanceCounter(&currTime);
		elapsedTime.QuadPart = currTime.QuadPart - prevTime.QuadPart;
		elapsedTime.QuadPart *= 1000000;
		elapsedTime.QuadPart /= frequency.QuadPart;

		//Update the network module
		this->m_networkModule.Update();

		this->m_physicsHandler.Update();
		//Prepare the InputHandler
		this->m_inputHandler->Update();
		//Handle events and update inputhandler through said events
		result = this->HandleEvents();
		SDL_PumpEvents();
		//Update game
		if (this->m_inputHandler->IsKeyPressed(SDL_SCANCODE_ESCAPE))
		{
			this->m_running = false;
		}
		if (!this->Update((float)elapsedTime.QuadPart))
		{
			this->m_running = false;
		}
		if (this->m_inputHandler->IsKeyPressed(SDL_SCANCODE_F))
		{
			this->FullscreenToggle();
		}
		//std::cout << int(totalTime) << "\n";
		//Render
		this->m_graphicsHandler->Render();

	}
	if (this->m_fullscreen)
		this->FullscreenToggle();

	return result;
}

int System::Update(float deltaTime)
{
	int result = 1;
	int translateCameraX = 0, translateCameraY = 0, translateCameraZ = 0;
	int rotateCameraY = 0;
	std::list<CameraPacket> cList;

	//Check for camera updates from the network
	if (!this->m_networkModule.PacketBuffer_isEmpty())
	{
		cList = this->m_networkModule.PacketBuffer_GetCameraPackets();

		std::list<CameraPacket>::iterator iter;

		for (iter = cList.begin(); iter != cList.end();)
		{
			this->m_camera->SetCameraPos(iter->pos);
		}
	}

	if (this->m_inputHandler->IsKeyDown(SDL_SCANCODE_W))
	{
		translateCameraZ++;
	}
	if (this->m_inputHandler->IsKeyDown(SDL_SCANCODE_S))
	{
		translateCameraZ--;
	}
	if (this->m_inputHandler->IsKeyDown(SDL_SCANCODE_SPACE))
	{
		translateCameraY++;
		if (this->m_inputHandler->IsKeyDown(SDL_SCANCODE_LSHIFT))
		{
			translateCameraY *= -1;
		}
	}
	if (this->m_inputHandler->IsKeyDown(SDL_SCANCODE_D))
	{
		translateCameraX++;
	}
	if (this->m_inputHandler->IsKeyDown(SDL_SCANCODE_A))
	{
		translateCameraX--;
	}
	if (this->m_inputHandler->IsKeyDown(SDL_SCANCODE_E))
	{
		rotateCameraY++;
	}
	if (this->m_inputHandler->IsKeyDown(SDL_SCANCODE_Q))
	{
		rotateCameraY--;
	}
	if (translateCameraY || translateCameraX || translateCameraZ || rotateCameraY)
	{
		DirectX::XMFLOAT3 posTranslation = DirectX::XMFLOAT3(float(translateCameraX) * (deltaTime / 1000000.0f), float(translateCameraY) * (deltaTime / 1000000.0f), float(translateCameraZ) * (deltaTime / 1000000.0f));
		this->m_camera->AddToCameraPos(posTranslation);
		this->m_camera->AddToLookAt(posTranslation);
		float rotationAmount = DirectX::XM_PI / 8;
		rotationAmount *= deltaTime / 1000000.0f;
		DirectX::XMFLOAT4 newRotation = DirectX::XMFLOAT4(0.0f, rotateCameraY * DirectX::XMScalarSin(rotationAmount / 2.0f), 0.0f, DirectX::XMScalarCos(rotationAmount / 2.0f));
		this->m_camera->SetRotation(newRotation);
		this->m_camera->Update();

		//Send updates over the network
		if (this->m_networkModule.GetNrOfConnectedClients() != 0)
		{
			DirectX::XMFLOAT4 updatePos;
			this->m_camera->GetCameraPos(updatePos);
			this->m_networkModule.SendCameraPacket(updatePos);
		}

	}
	//Network
	if(this->m_inputHandler->IsKeyPressed(SDL_SCANCODE_J))
	{
		if (this->m_networkModule.GetNrOfConnectedClients() <= 0)	//If the network module is NOT connected to other clients
		{
			if (this->m_networkModule.Join(this->m_ip))				//If we succsefully connected
			{
				printf("Joined client with the ip %s\n", this->m_ip);
			}
			else
			{
				printf("Failed to connect to the client\n", this->m_ip);
			}

		}
		else
		{
			printf("Join failed since this module is already connected to other clients\n");
		}
	}
	if (this->m_inputHandler->IsKeyPressed(SDL_SCANCODE_K))
	{
		this->m_networkModule.SendFlagPacket(DISCONNECT_REQUEST);
	}
	return result;
}

int System::HandleEvents()
{
	SDL_Event m_event;
	while (SDL_PollEvent(&m_event))
	{
		switch (m_event.type)
		{
#pragma region
		case SDL_WINDOWEVENT:
		{
			switch (m_event.window.event)
			{
			case SDL_WINDOWEVENT_ENTER:
			{
				//OnMouseFocus();
				break;
			}
			case SDL_WINDOWEVENT_LEAVE:
			{
				//OnMouseBlur();
				break;
			}
			case SDL_WINDOWEVENT_FOCUS_GAINED:
			{
				//OnInputFocus();
				break;
			}
			case SDL_WINDOWEVENT_FOCUS_LOST:
			{
				//OnInputBlur();
				break;
			}
			case SDL_WINDOWEVENT_SHOWN:
			{
				break;
			}
			case SDL_WINDOWEVENT_HIDDEN:
			{
				break;
			}
			case SDL_WINDOWEVENT_EXPOSED:
			{
				break;
			}
			case SDL_WINDOWEVENT_MOVED:
			{
				break;
			}
			case SDL_WINDOWEVENT_RESIZED:
			{
				break;
			}
			case SDL_WINDOWEVENT_SIZE_CHANGED:
			{
				break;
			}
			case SDL_WINDOWEVENT_MINIMIZED:
			{
				break;
			}
			case SDL_WINDOWEVENT_MAXIMIZED:
			{
				break;
			}
			case SDL_WINDOWEVENT_RESTORED:
			{
				break;
			}
			case SDL_WINDOWEVENT_CLOSE:
			{
				break;
			}
			}
			break;
		}
#pragma endregion window events
		case SDL_MOUSEMOTION:
		{
			break;
		}
		case SDL_QUIT:
		{
			//The big X in the corner
			this->m_running = false;
			break;
		}
#pragma region
		case SDL_KEYDOWN:
		{
			//OnKeyDown(Event->key.keysym.sym, Event->key.keysym.mod, Event->key.keysym.scancode);

			this->m_inputHandler->SetKeyState(m_event.key.keysym.scancode, true);
			break;
		}
		case SDL_KEYUP:
		{
			//OnKeyUp(Event->key.keysym.sym, Event->key.keysym.mod, Event->key.keysym.scancode);
			this->m_inputHandler->SetKeyState(m_event.key.keysym.scancode, false);
			break;
		}
		case SDL_MOUSEBUTTONDOWN:
		{
			this->m_inputHandler->SetMouseState(m_event.button.button, true);
			break;
		}
		case SDL_MOUSEBUTTONUP:
		{
			this->m_inputHandler->SetMouseState(m_event.button.button, false);
			break;
		}
#pragma endregion Key / Button events
		case SDL_MOUSEWHEEL:
		{
			this->m_inputHandler->ApplyMouseWheel(m_event.wheel.x, m_event.wheel.y);
			break;
		}
		}
	}
	return 1;
}

int System::FullscreenToggle()
{
	int result = 0;
	this->m_fullscreen = SDL_GetWindowFlags(this->m_window) & SDL_WINDOW_FULLSCREEN;
	SDL_SetWindowFullscreen(this->m_window, this->m_fullscreen ? 0 : SDL_WINDOW_FULLSCREEN);
	this->m_fullscreen = SDL_GetWindowFlags(this->m_window) & SDL_WINDOW_FULLSCREEN;
	return result;
}
<commit_msg>FIX the loop that iterates cList<commit_after>#include "System.h"
System::System()
{
	this->m_inputHandler = NULL;
	this->m_window = NULL;
}

System::~System()
{
}

int System::Shutdown()
{
	int result = 0;
	//Destroy the display window
	SDL_DestroyWindow(m_window);
	//Quit SDL subsystems
	SDL_Quit();
	this->m_graphicsHandler->Shutdown();
	delete this->m_graphicsHandler;
	delete this->m_camera;
	this->m_inputHandler->Shutdown();
	delete this->m_inputHandler;
	this->m_physicsHandler.ShutDown();

	//Shutdown Network module
	this->m_networkModule.Shutdown();
	return result;

}

int System::Initialize()
{
	int result = 1;
	this->m_fullscreen = false;
	this->m_running = true;
	this->m_window = NULL;
	//Get the instance if this application
	this->m_hinstance = GetModuleHandle(NULL);

	if (SDL_Init(SDL_INIT_VIDEO) < 0)
	{
		printf("SDL failed in initializing the window! SDL_Error: %hS\n", SDL_GetError());
	}
	else
	{
		printf("SDL succeeded in initializing the window!\n");
	}

	m_window = SDL_CreateWindow("SSD Application", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
	if (m_window == NULL)
	{
		printf("Window creation failed! SDL_ERROR: %hS\n", SDL_GetError());
	}
	else
	{
		printf("Window creation succeeded!\n");

		SDL_SysWMinfo wmInfo;
		SDL_VERSION(&wmInfo.version);
		SDL_GetWindowWMInfo(m_window, &wmInfo);
		m_hwnd = wmInfo.info.win.window;
	}

	this->m_graphicsHandler = new GraphicsHandler();
	if (this->m_graphicsHandler->Initialize(&this->m_hwnd, DirectX::XMINT2(SCREEN_WIDTH, SCREEN_HEIGHT)))
	{
		printf("GraphicsHandler did not work. RIP!\n");
	}
	this->m_camera = new Camera();
	this->m_camera->Initialize();
	Camera* oldCam = this->m_graphicsHandler->SetCamera(this->m_camera);
	delete oldCam;
	oldCam = nullptr;
	//Initialize the PhysicsHandler
	this->m_physicsHandler.Initialize();

	//Initialize the InputHandler
	this->m_inputHandler = new InputHandler();
	this->m_inputHandler->Initialize(SCREEN_WIDTH, SCREEN_HEIGHT);

	//Init the network module
	this->m_networkModule.Initialize();

	return result;
}

//Do not place things here without talking to the system designers. Place any update method in the System::Update(float dt) method
int System::Run()
{
	int result = 0;
	LARGE_INTEGER frequency, currTime, prevTime, elapsedTime;
	QueryPerformanceFrequency(&frequency);
	//QueryPerformanceCounter(&prevTime);
	QueryPerformanceCounter(&currTime);
	while (this->m_running)
	{
		prevTime = currTime;
		QueryPerformanceCounter(&currTime);
		elapsedTime.QuadPart = currTime.QuadPart - prevTime.QuadPart;
		elapsedTime.QuadPart *= 1000000;
		elapsedTime.QuadPart /= frequency.QuadPart;

		//Update the network module
		this->m_networkModule.Update();

		this->m_physicsHandler.Update();
		//Prepare the InputHandler
		this->m_inputHandler->Update();
		//Handle events and update inputhandler through said events
		result = this->HandleEvents();
		SDL_PumpEvents();
		//Update game
		if (this->m_inputHandler->IsKeyPressed(SDL_SCANCODE_ESCAPE))
		{
			this->m_running = false;
		}
		if (!this->Update((float)elapsedTime.QuadPart))
		{
			this->m_running = false;
		}
		if (this->m_inputHandler->IsKeyPressed(SDL_SCANCODE_F))
		{
			this->FullscreenToggle();
		}
		//std::cout << int(totalTime) << "\n";
		//Render
		this->m_graphicsHandler->Render();

	}
	if (this->m_fullscreen)
		this->FullscreenToggle();

	return result;
}

int System::Update(float deltaTime)
{
	int result = 1;
	int translateCameraX = 0, translateCameraY = 0, translateCameraZ = 0;
	int rotateCameraY = 0;
	std::list<CameraPacket> cList;

	//Check for camera updates from the network
	if (!this->m_networkModule.PacketBuffer_isEmpty())
	{
		cList = this->m_networkModule.PacketBuffer_GetCameraPackets();

		std::list<CameraPacket>::iterator iter;

		for (iter = cList.begin(); iter != cList.end();)
		{
			this->m_camera->SetCameraPos(iter->pos);
			iter++;
		}
	}

	if (this->m_inputHandler->IsKeyDown(SDL_SCANCODE_W))
	{
		translateCameraZ++;
	}
	if (this->m_inputHandler->IsKeyDown(SDL_SCANCODE_S))
	{
		translateCameraZ--;
	}
	if (this->m_inputHandler->IsKeyDown(SDL_SCANCODE_SPACE))
	{
		translateCameraY++;
		if (this->m_inputHandler->IsKeyDown(SDL_SCANCODE_LSHIFT))
		{
			translateCameraY *= -1;
		}
	}
	if (this->m_inputHandler->IsKeyDown(SDL_SCANCODE_D))
	{
		translateCameraX++;
	}
	if (this->m_inputHandler->IsKeyDown(SDL_SCANCODE_A))
	{
		translateCameraX--;
	}
	if (this->m_inputHandler->IsKeyDown(SDL_SCANCODE_E))
	{
		rotateCameraY++;
	}
	if (this->m_inputHandler->IsKeyDown(SDL_SCANCODE_Q))
	{
		rotateCameraY--;
	}
	if (translateCameraY || translateCameraX || translateCameraZ || rotateCameraY)
	{
		DirectX::XMFLOAT3 posTranslation = DirectX::XMFLOAT3(float(translateCameraX) * (deltaTime / 1000000.0f), float(translateCameraY) * (deltaTime / 1000000.0f), float(translateCameraZ) * (deltaTime / 1000000.0f));
		this->m_camera->AddToCameraPos(posTranslation);
		this->m_camera->AddToLookAt(posTranslation);
		float rotationAmount = DirectX::XM_PI / 8;
		rotationAmount *= deltaTime / 1000000.0f;
		DirectX::XMFLOAT4 newRotation = DirectX::XMFLOAT4(0.0f, rotateCameraY * DirectX::XMScalarSin(rotationAmount / 2.0f), 0.0f, DirectX::XMScalarCos(rotationAmount / 2.0f));
		this->m_camera->SetRotation(newRotation);
		this->m_camera->Update();

		//Send updates over the network
		if (this->m_networkModule.GetNrOfConnectedClients() != 0)
		{
			DirectX::XMFLOAT4 updatePos;
			this->m_camera->GetCameraPos(updatePos);
			this->m_networkModule.SendCameraPacket(updatePos);
		}

	}
	//Network
	if(this->m_inputHandler->IsKeyPressed(SDL_SCANCODE_J))
	{
		if (this->m_networkModule.GetNrOfConnectedClients() <= 0)	//If the network module is NOT connected to other clients
		{
			if (this->m_networkModule.Join(this->m_ip))				//If we succsefully connected
			{
				printf("Joined client with the ip %s\n", this->m_ip);
			}
			else
			{
				printf("Failed to connect to the client\n", this->m_ip);
			}

		}
		else
		{
			printf("Join failed since this module is already connected to other clients\n");
		}
	}
	if (this->m_inputHandler->IsKeyPressed(SDL_SCANCODE_K))
	{
		this->m_networkModule.SendFlagPacket(DISCONNECT_REQUEST);
	}
	return result;
}

int System::HandleEvents()
{
	SDL_Event m_event;
	while (SDL_PollEvent(&m_event))
	{
		switch (m_event.type)
		{
#pragma region
		case SDL_WINDOWEVENT:
		{
			switch (m_event.window.event)
			{
			case SDL_WINDOWEVENT_ENTER:
			{
				//OnMouseFocus();
				break;
			}
			case SDL_WINDOWEVENT_LEAVE:
			{
				//OnMouseBlur();
				break;
			}
			case SDL_WINDOWEVENT_FOCUS_GAINED:
			{
				//OnInputFocus();
				break;
			}
			case SDL_WINDOWEVENT_FOCUS_LOST:
			{
				//OnInputBlur();
				break;
			}
			case SDL_WINDOWEVENT_SHOWN:
			{
				break;
			}
			case SDL_WINDOWEVENT_HIDDEN:
			{
				break;
			}
			case SDL_WINDOWEVENT_EXPOSED:
			{
				break;
			}
			case SDL_WINDOWEVENT_MOVED:
			{
				break;
			}
			case SDL_WINDOWEVENT_RESIZED:
			{
				break;
			}
			case SDL_WINDOWEVENT_SIZE_CHANGED:
			{
				break;
			}
			case SDL_WINDOWEVENT_MINIMIZED:
			{
				break;
			}
			case SDL_WINDOWEVENT_MAXIMIZED:
			{
				break;
			}
			case SDL_WINDOWEVENT_RESTORED:
			{
				break;
			}
			case SDL_WINDOWEVENT_CLOSE:
			{
				break;
			}
			}
			break;
		}
#pragma endregion window events
		case SDL_MOUSEMOTION:
		{
			break;
		}
		case SDL_QUIT:
		{
			//The big X in the corner
			this->m_running = false;
			break;
		}
#pragma region
		case SDL_KEYDOWN:
		{
			//OnKeyDown(Event->key.keysym.sym, Event->key.keysym.mod, Event->key.keysym.scancode);

			this->m_inputHandler->SetKeyState(m_event.key.keysym.scancode, true);
			break;
		}
		case SDL_KEYUP:
		{
			//OnKeyUp(Event->key.keysym.sym, Event->key.keysym.mod, Event->key.keysym.scancode);
			this->m_inputHandler->SetKeyState(m_event.key.keysym.scancode, false);
			break;
		}
		case SDL_MOUSEBUTTONDOWN:
		{
			this->m_inputHandler->SetMouseState(m_event.button.button, true);
			break;
		}
		case SDL_MOUSEBUTTONUP:
		{
			this->m_inputHandler->SetMouseState(m_event.button.button, false);
			break;
		}
#pragma endregion Key / Button events
		case SDL_MOUSEWHEEL:
		{
			this->m_inputHandler->ApplyMouseWheel(m_event.wheel.x, m_event.wheel.y);
			break;
		}
		}
	}
	return 1;
}

int System::FullscreenToggle()
{
	int result = 0;
	this->m_fullscreen = SDL_GetWindowFlags(this->m_window) & SDL_WINDOW_FULLSCREEN;
	SDL_SetWindowFullscreen(this->m_window, this->m_fullscreen ? 0 : SDL_WINDOW_FULLSCREEN);
	this->m_fullscreen = SDL_GetWindowFlags(this->m_window) & SDL_WINDOW_FULLSCREEN;
	return result;
}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "ViewDistanceCalc.h"
#include "GL3DProgram.h"

ViewDistanceCalc::ViewDistanceCalc() {
	viewDistance = 0.0;
	framesDrawn = 0;
}

//Should be called every draw cycle
//calculates the view distance
//applies to fog distance automatically
void ViewDistanceCalc::CalculateAndApply(float & fogDistance,float currentFPS) {
	//Constants used for adjustment
	//How long the visual learning rate is
	const static int maxFrameLearn = 400;
	//Target frame rates
	const float maxFrameRate = 55;
	//This should be a bit higher than what you actually want
	const float acceptableFrameRate = 35;
	framesDrawn++;
	//only calibrate for the first 2000 frames
	if (framesDrawn > maxFrameLearn) {
		fogDistance = GetViewDistance()*.80f;
		return;
	}

	//A value between 0 and 1 which indicates how fast
	//the view distance can be adjusted
	float confidenceFactor = framesDrawn/(float)maxFrameLearn;
	//confidenceFactor^3 is used to slow the learning rate very early on
	confidenceFactor = 1-confidenceFactor;
	confidenceFactor = confidenceFactor*confidenceFactor*confidenceFactor;

	//If lower than the acceptable framerate, lower the view distance quickly
	if (currentFPS < acceptableFrameRate)
		viewDistance -= confidenceFactor*(acceptableFrameRate-currentFPS)/acceptableFrameRate*.05f;
	else if (currentFPS > maxFrameRate)
		viewDistance += confidenceFactor*(currentFPS-acceptableFrameRate)/acceptableFrameRate*.02f;

	if (viewDistance < 0.0)
		viewDistance = 0.0;
	if (viewDistance > 1.0)
		viewDistance = 1.0;

	//Fog has to end before view distance
	//because view distance is not perfect
	fogDistance = GetViewDistance()*.80f;
}

//Retrieve a pair of coordinates representing the appropriate draw section
pair<vec2,vec2> ViewDistanceCalc::VoxDrawCoordinates(vec2 userPosition, float userAngle, float viewDistance) {
	//New strategy for determining draw box
	//Create a rectangle with the user on the bottom center, with the top of the rectangle
	//far away from the user in his view direction
	//Use the points of this rotated rectangle
	//to choose a min/max point of the voxel draw rectangle

	//Width code is highly experimental and will certainly have to be played with
	float rectHeight = viewDistance; //the full length of the rectangle
	float rectHalfWidth = pow(rectHeight/40.0f,3.0f)+rectHeight/5.0f+7.0f; //Half the width of the rectangle
	float rectHalfDiagonal =(float)( M_PI/2.0f-atan2(rectHeight,rectHalfWidth)); //The angle of the diagonal (to the center of the width side)
	float rectDiagonalLength = sqrt(rectHalfWidth*rectHalfWidth+rectHeight*rectHeight);
	vec2 testPoints[4] = {
		//Use the edges of a rectangle with the viewer in the bottom center
		//First the bottom left
		userPosition + vec2(cos(M_PI/2.0f+userAngle),sin(M_PI/2.0f+userAngle))*rectHalfWidth,
		//Next bottom right
		userPosition + vec2(cos(-M_PI/2.0f+userAngle),sin(-M_PI/2.0f+userAngle))*rectHalfWidth,
		//Top Left
		userPosition + vec2(cos(rectHalfDiagonal+userAngle),sin(rectHalfDiagonal+userAngle))*rectDiagonalLength,
		//Top Right
		userPosition + vec2(cos(-rectHalfDiagonal+userAngle),sin(-rectHalfDiagonal+userAngle))*rectDiagonalLength,
	};
	vec2 minPoint = testPoints[0];
	vec2 maxPoint = testPoints[0];
	for (int i = 1; i < 4; i++) {
		minPoint = glm::min(minPoint,testPoints[i]);
		maxPoint = glm::max(maxPoint,testPoints[i]);
	}

	minPoint = glm::floor(minPoint);
	maxPoint = glm::ceil(maxPoint);
	//Limit points to valid ranges (vec2() creates a zero vector)
	//minPoint = glm::max(vec2(),minPoint);
	//maxPoint = glm::min(mapExtents-vec2(1,1),maxPoint);
	return pair<vec2,vec2>(minPoint,maxPoint);
}

IntRect ViewDistanceCalc::GetDrawRegion(vec2 playerPosition, float playerFacing) {
	return VoxDrawCoordinates(playerPosition,playerFacing,GetViewDistance());

}

float ViewDistanceCalc::GetViewDistance() {
	//viewDistance is between 0 to 1, so apply scale now
	return viewDistance*(MAX_DRAW_DISTANCE-MIN_DRAW_DISTANCE)+MIN_DRAW_DISTANCE;
}<commit_msg>Modified the view distance to push the transparency out further<commit_after>#include "stdafx.h"
#include "ViewDistanceCalc.h"
#include "GL3DProgram.h"

ViewDistanceCalc::ViewDistanceCalc() {
	viewDistance = 0.0;
	framesDrawn = 0;
}

//Should be called every draw cycle
//calculates the view distance
//applies to fog distance automatically
void ViewDistanceCalc::CalculateAndApply(float & fogDistance,float currentFPS) {
	//Constants used for adjustment
	//How long the visual learning rate is
	const static int maxFrameLearn = 400;
	//Target frame rates
	const float maxFrameRate = 55;
	//This should be a bit higher than what you actually want
	const float acceptableFrameRate = 35;
	framesDrawn++;
	//only calibrate for the first 2000 frames
	if (framesDrawn > maxFrameLearn) {
		fogDistance = GetViewDistance()*.80f;
		return;
	}

	//A value between 0 and 1 which indicates how fast
	//the view distance can be adjusted
	float confidenceFactor = framesDrawn/(float)maxFrameLearn;
	//confidenceFactor^3 is used to slow the learning rate very early on
	confidenceFactor = 1-confidenceFactor;
	confidenceFactor = confidenceFactor*confidenceFactor*confidenceFactor;

	//If lower than the acceptable framerate, lower the view distance quickly
	if (currentFPS < acceptableFrameRate)
		viewDistance -= confidenceFactor*(acceptableFrameRate-currentFPS)/acceptableFrameRate*.05f;
	else if (currentFPS > maxFrameRate)
		viewDistance += confidenceFactor*(currentFPS-acceptableFrameRate)/acceptableFrameRate*.02f;

	if (viewDistance < 0.0)
		viewDistance = 0.0;
	if (viewDistance > 1.0)
		viewDistance = 1.0;

	//Fog has to end before view distance
	//because view distance is not perfect
	//fogDistance = GetViewDistance()*.80f;
	fogDistance = GetViewDistance();
}

//Retrieve a pair of coordinates representing the appropriate draw section
pair<vec2,vec2> ViewDistanceCalc::VoxDrawCoordinates(vec2 userPosition, float userAngle, float viewDistance) {
	//New strategy for determining draw box
	//Create a rectangle with the user on the bottom center, with the top of the rectangle
	//far away from the user in his view direction
	//Use the points of this rotated rectangle
	//to choose a min/max point of the voxel draw rectangle

	//Width code is highly experimental and will certainly have to be played with
	float rectHeight = viewDistance; //the full length of the rectangle
	float rectHalfWidth = pow(rectHeight/40.0f,3.0f)+rectHeight/5.0f+7.0f; //Half the width of the rectangle
	float rectHalfDiagonal =(float)( M_PI/2.0f-atan2(rectHeight,rectHalfWidth)); //The angle of the diagonal (to the center of the width side)
	float rectDiagonalLength = sqrt(rectHalfWidth*rectHalfWidth+rectHeight*rectHeight);
	vec2 testPoints[4] = {
		//Use the edges of a rectangle with the viewer in the bottom center
		//First the bottom left
		userPosition + vec2(cos(M_PI/2.0f+userAngle),sin(M_PI/2.0f+userAngle))*rectHalfWidth,
		//Next bottom right
		userPosition + vec2(cos(-M_PI/2.0f+userAngle),sin(-M_PI/2.0f+userAngle))*rectHalfWidth,
		//Top Left
		userPosition + vec2(cos(rectHalfDiagonal+userAngle),sin(rectHalfDiagonal+userAngle))*rectDiagonalLength,
		//Top Right
		userPosition + vec2(cos(-rectHalfDiagonal+userAngle),sin(-rectHalfDiagonal+userAngle))*rectDiagonalLength,
	};
	vec2 minPoint = testPoints[0];
	vec2 maxPoint = testPoints[0];
	for (int i = 1; i < 4; i++) {
		minPoint = glm::min(minPoint,testPoints[i]);
		maxPoint = glm::max(maxPoint,testPoints[i]);
	}

	minPoint = glm::floor(minPoint);
	maxPoint = glm::ceil(maxPoint);
	//Limit points to valid ranges (vec2() creates a zero vector)
	//minPoint = glm::max(vec2(),minPoint);
	//maxPoint = glm::min(mapExtents-vec2(1,1),maxPoint);
	return pair<vec2,vec2>(minPoint,maxPoint);
}

IntRect ViewDistanceCalc::GetDrawRegion(vec2 playerPosition, float playerFacing) {
	return VoxDrawCoordinates(playerPosition,playerFacing,GetViewDistance());

}

float ViewDistanceCalc::GetViewDistance() {
	//viewDistance is between 0 to 1, so apply scale now
	return viewDistance*(MAX_DRAW_DISTANCE-MIN_DRAW_DISTANCE)+MIN_DRAW_DISTANCE;
}<|endoftext|>


<commit_before>#pragma once

#include "Renderer.hpp"
#include "exprs.hpp"

namespace DS          {
namespace CAS         {
namespace Expressions {
namespace Visitors    {
namespace Render      {

template<typename T>
class Infix : public DS::CAS::Expressions::Visitors::Renderer<T>
{
public:
    Infix(std::shared_ptr<Numbers::NumberFormatter> formatter) : Renderer<T>(formatter) {}
    virtual ~Infix() {}

    virtual bool visitAdd(const Add&);
    virtual bool visitDivide(const Divide&);
    virtual bool visitFactorial(const Factorial&);
    virtual bool visitLiteral(const Literal&);
    virtual bool visitModulus(const Modulus&);
    virtual bool visitMultiply(const Multiply&);
    virtual bool visitNegate(const Negate&);
    virtual bool visitPower(const Power&);
    virtual bool visitSymbol(const Symbol&);

protected:
    virtual bool noParenthesisInDivision(void) const = 0;
    virtual bool noParenthesisInExponent(void) const = 0;
    virtual bool parenthesisInNegateDivision(void) const = 0;

    virtual T renderParenthesis(const T& arg) = 0;
    virtual T renderComma(const T& leftArg, const T& rightArg) = 0;
    virtual T renderAdjacent(const T& leftArg, const T& rightArg) = 0;
    virtual T renderString(const string& arg) = 0;
    virtual T renderBinaryOp(const string& op, const T& leftArg, const T& rightArg, bool spaces) = 0;
    virtual T renderUnaryOp(const string& op, const T& arg, bool leftRight) = 0;
    virtual T renderSuperscript(const T& base, const T& super) = 0;
    virtual T renderFraction(const T& top, const T& bottom) = 0;
};

template<typename T>
bool Infix<T>::visitAdd(const Add& exp)
{
    unsigned int nc = exp.numberOfChildren();
    T resultLeft, resultRight;
    for (unsigned int currentChild = nc-1; (currentChild+1) >= 1; currentChild--)
    {
        resultLeft = getPop(this->childResults);
        if (exp.getSignForChild(currentChild) == Expressions::Sign::n &&
            exp.getChild(currentChild)->id()  == ID::add)
            resultLeft = renderParenthesis(resultLeft);
        if (currentChild != nc-1)
        {
            if (exp.getSignForChild(currentChild+1) == Expressions::Sign::p)
                resultRight = renderBinaryOp("+", resultLeft, resultRight, true);
            else
                resultRight = renderBinaryOp("-", resultLeft, resultRight, true);
        }
        else
            resultRight = resultLeft;
    }
    if (exp.getSignForChild(0) == Expressions::Sign::n)
        resultRight = renderUnaryOp("-", resultRight, false);

    this->childResults.push(resultRight);
    return true;
}
template<typename T>
bool Infix<T>::visitDivide(const Divide& exp)
{
    T denominator = getPop(this->childResults);
    T numerator = getPop(this->childResults);
    if (!noParenthesisInDivision())
    {
        Expressions::ID numID = exp.getChild(0)->id();
        Expressions::ID denID = exp.getChild(1)->id();
        if (numID == Expressions::ID::add)
            numerator = renderParenthesis(numerator);
        if (denID == Expressions::ID::add || denID == Expressions::ID::divide ||
            denID == Expressions::ID::modulus || denID == Expressions::ID::multiply)
            denominator = renderParenthesis(denominator);
    }
    this->childResults.push(renderFraction(numerator, denominator));
    return true;
}
template<typename T>
bool Infix<T>::visitFactorial(const Factorial& exp)
{
    T arg = getPop(this->childResults);
    Expressions::ID id = exp.getChild(0)->id();
    if (id == Expressions::ID::add || id == Expressions::ID::divide || id == Expressions::ID::modulus ||
        id == Expressions::ID::multiply || id == Expressions::ID::negate || id == Expressions::ID::power)
        arg = renderParenthesis(arg);
    this->childResults.push(renderUnaryOp("!", arg, true));
    return true;
}
template<typename T>
bool Infix<T>::visitLiteral(const Literal& exp)
{
    const CAS::Numbers::Number& number = exp.getNumber();
    if (number.isReal())
        this->childResults.push(renderString(this->formatter->formatRealPart(number)));
    else if (number.isImaginary())
    {
        string iNumber = this->formatter->formatImaginaryPart(number);
        if (iNumber == "1")
            iNumber = "";
        if (iNumber == "-1")
            iNumber = "-";
        this->childResults.push(renderString(iNumber + "i"));
    }
    else
        throw logic_error("Attempting to render a number with non-zero real and imaginary parts in Visitors::Render::Infix::visitLiteral()");
    return true;
}
template<typename T>
bool Infix<T>::visitModulus(const Modulus& exp)
{
    T denominator = getPop(this->childResults);
    T numerator = getPop(this->childResults);

    Expressions::ID numID = exp.getChild(0)->id();
    Expressions::ID denID = exp.getChild(1)->id();
    if (numID == Expressions::ID::add || numID == Expressions::ID::negate)
        numerator = renderParenthesis(numerator);
    if (denID == Expressions::ID::add || denID == Expressions::ID::divide ||
        denID == Expressions::ID::modulus || denID == Expressions::ID::multiply)
        denominator = renderParenthesis(denominator);

    this->childResults.push(renderBinaryOp("%", numerator, denominator, false));
    return true;
}
template<typename T>
bool Infix<T>::visitMultiply(const Multiply& exp)
{
    unsigned int nc = exp.numberOfChildren();
    T resultLeft, resultRight;
    for (unsigned int currentChild = nc-1; (currentChild+1) >= 1; currentChild--)
    {
        resultLeft = getPop(this->childResults);
        Expressions::ID id = exp.getChild(currentChild)->id();
        if (id == Expressions::ID::add || id == Expressions::ID::modulus)
            resultLeft = renderParenthesis(resultLeft);
        if (currentChild != nc-1)
            resultRight = renderBinaryOp("*", resultLeft, resultRight, false);
        else
            resultRight = resultLeft;
    }
    this->childResults.push(resultRight);
    return true;
}
template<typename T>
bool Infix<T>::visitNegate(const Negate& exp)
{
    T arg = getPop(this->childResults);
    Expressions::ID id = exp.getChild(0)->id();
    if (id == Expressions::ID::add || (id == Expressions::ID::divide && parenthesisInNegateDivision()))
        arg = renderParenthesis(arg);
    this->childResults.push(renderUnaryOp("-", arg, false));
    return true;
}
template<typename T>
bool Infix<T>::visitPower(const Power& exp)
{
    T exponent = getPop(this->childResults);
    T base = getPop(this->childResults);

    Expressions::ID id = exp.getChild(0)->id(); // base
    if (id == Expressions::ID::add || id == Expressions::ID::divide || id == Expressions::ID::modulus ||
        id == Expressions::ID::multiply || id == Expressions::ID::negate || id == Expressions::ID::power)
        base = renderParenthesis(base);
    if (!noParenthesisInExponent())
    {
        id = exp.getChild(1)->id();
        if (id == Expressions::ID::add || id == Expressions::ID::divide ||
            id == Expressions::ID::modulus || id == Expressions::ID::multiply)
            exponent = renderParenthesis(exponent);
    }
    this->childResults.push(renderSuperscript(base, exponent));
    return true;
}
template<typename T>
bool Infix<T>::visitSymbol(const Symbol& exp)
{
    unsigned int nc = exp.numberOfChildren();
    if (!nc)
    {
        this->childResults.push(renderString(exp.getName()));
        return true;
    }
    T resultLeft, resultRight;
    for (unsigned int currentChild = nc-1; (currentChild+1) >= 1; currentChild--)
    {
        resultLeft = getPop(this->childResults);
        if (currentChild != nc-1)
            resultRight = renderComma(resultLeft, resultRight);
        else
            resultRight = resultLeft;
    }
    resultRight = renderParenthesis(resultRight);
    T name = renderString(exp.getName());
    this->childResults.push(renderAdjacent(name, resultRight));
    return true;
}

} /* namespace Render */
} /* namespace Visitors */
} /* namespace Expressions */
} /* namespace CAS */
} /* namespace DS */
<commit_msg>Fix a rendering bug<commit_after>#pragma once

#include "Renderer.hpp"
#include "exprs.hpp"

namespace DS          {
namespace CAS         {
namespace Expressions {
namespace Visitors    {
namespace Render      {

template<typename T>
class Infix : public DS::CAS::Expressions::Visitors::Renderer<T>
{
public:
    Infix(std::shared_ptr<Numbers::NumberFormatter> formatter) : Renderer<T>(formatter) {}
    virtual ~Infix() {}

    virtual bool visitAdd(const Add&);
    virtual bool visitDivide(const Divide&);
    virtual bool visitFactorial(const Factorial&);
    virtual bool visitLiteral(const Literal&);
    virtual bool visitModulus(const Modulus&);
    virtual bool visitMultiply(const Multiply&);
    virtual bool visitNegate(const Negate&);
    virtual bool visitPower(const Power&);
    virtual bool visitSymbol(const Symbol&);

protected:
    virtual bool noParenthesisInDivision(void) const = 0;
    virtual bool noParenthesisInExponent(void) const = 0;
    virtual bool parenthesisInNegateDivision(void) const = 0;

    virtual T renderParenthesis(const T& arg) = 0;
    virtual T renderComma(const T& leftArg, const T& rightArg) = 0;
    virtual T renderAdjacent(const T& leftArg, const T& rightArg) = 0;
    virtual T renderString(const string& arg) = 0;
    virtual T renderBinaryOp(const string& op, const T& leftArg, const T& rightArg, bool spaces) = 0;
    virtual T renderUnaryOp(const string& op, const T& arg, bool leftRight) = 0;
    virtual T renderSuperscript(const T& base, const T& super) = 0;
    virtual T renderFraction(const T& top, const T& bottom) = 0;
};

template<typename T>
bool Infix<T>::visitAdd(const Add& exp)
{
    unsigned int nc = exp.numberOfChildren();
    T resultLeft, resultRight;
    for (unsigned int currentChild = nc-1; (currentChild+1) >= 1; currentChild--)
    {
        resultLeft = getPop(this->childResults);
        if (exp.getSignForChild(currentChild) == Expressions::Sign::n &&
            exp.getChild(currentChild)->id()  == ID::add)
            resultLeft = renderParenthesis(resultLeft);
        if (currentChild != nc-1)
        {
            if (exp.getSignForChild(currentChild+1) == Expressions::Sign::p)
                resultRight = renderBinaryOp("+", resultLeft, resultRight, true);
            else
                resultRight = renderBinaryOp("-", resultLeft, resultRight, true);
        }
        else
            resultRight = resultLeft;
    }
    if (exp.getSignForChild(0) == Expressions::Sign::n)
        resultRight = renderUnaryOp("-", resultRight, false);

    this->childResults.push(resultRight);
    return true;
}
template<typename T>
bool Infix<T>::visitDivide(const Divide& exp)
{
    T denominator = getPop(this->childResults);
    T numerator = getPop(this->childResults);
    if (!noParenthesisInDivision())
    {
        Expressions::ID numID = exp.getChild(0)->id();
        Expressions::ID denID = exp.getChild(1)->id();
        if (numID == Expressions::ID::add)
            numerator = renderParenthesis(numerator);
        if (denID == Expressions::ID::add || denID == Expressions::ID::divide ||
            denID == Expressions::ID::modulus || denID == Expressions::ID::multiply)
            denominator = renderParenthesis(denominator);
    }
    this->childResults.push(renderFraction(numerator, denominator));
    return true;
}
template<typename T>
bool Infix<T>::visitFactorial(const Factorial& exp)
{
    T arg = getPop(this->childResults);
    Expressions::ID id = exp.getChild(0)->id();
    if (id == Expressions::ID::add || id == Expressions::ID::divide || id == Expressions::ID::modulus ||
        id == Expressions::ID::multiply || id == Expressions::ID::negate || id == Expressions::ID::power)
        arg = renderParenthesis(arg);
    this->childResults.push(renderUnaryOp("!", arg, true));
    return true;
}
template<typename T>
bool Infix<T>::visitLiteral(const Literal& exp)
{
    const CAS::Numbers::Number& number = exp.getNumber();
    if (number.isReal())
        this->childResults.push(renderString(this->formatter->formatRealPart(number)));
    else if (number.isImaginary())
    {
        string iNumber = this->formatter->formatImaginaryPart(number);
        if (iNumber == "1")
            iNumber = "";
        if (iNumber == "-1")
            iNumber = "-";
        this->childResults.push(renderString(iNumber + "i"));
    }
    else
        throw logic_error("Attempting to render a number with non-zero real and imaginary parts in Visitors::Render::Infix::visitLiteral()");
    return true;
}
template<typename T>
bool Infix<T>::visitModulus(const Modulus& exp)
{
    T denominator = getPop(this->childResults);
    T numerator = getPop(this->childResults);

    Expressions::ID numID = exp.getChild(0)->id();
    Expressions::ID denID = exp.getChild(1)->id();
    if (numID == Expressions::ID::add || numID == Expressions::ID::negate)
        numerator = renderParenthesis(numerator);
    if (denID == Expressions::ID::add || denID == Expressions::ID::divide ||
        denID == Expressions::ID::modulus || denID == Expressions::ID::multiply)
        denominator = renderParenthesis(denominator);

    this->childResults.push(renderBinaryOp("%", numerator, denominator, false));
    return true;
}
template<typename T>
bool Infix<T>::visitMultiply(const Multiply& exp)
{
    unsigned int nc = exp.numberOfChildren();
    T resultLeft, resultRight;
    for (unsigned int currentChild = nc-1; (currentChild+1) >= 1; currentChild--)
    {
        resultLeft = getPop(this->childResults);
        Expressions::ID id = exp.getChild(currentChild)->id();
        if (id == Expressions::ID::add || id == Expressions::ID::modulus)
            resultLeft = renderParenthesis(resultLeft);
        if (currentChild != nc-1)
            resultRight = renderBinaryOp("*", resultLeft, resultRight, false);
        else
            resultRight = resultLeft;
    }
    this->childResults.push(resultRight);
    return true;
}
template<typename T>
bool Infix<T>::visitNegate(const Negate& exp)
{
    T arg = getPop(this->childResults);
    Expressions::ID id = exp.getChild(0)->id();
    if (id == Expressions::ID::add || (id == Expressions::ID::divide && parenthesisInNegateDivision()))
        arg = renderParenthesis(arg);
    this->childResults.push(renderUnaryOp("-", arg, false));
    return true;
}
template<typename T>
bool Infix<T>::visitPower(const Power& exp)
{
    T exponent = getPop(this->childResults);
    T base = getPop(this->childResults);

    Expressions::ID id = exp.getChild(0)->id(); // base
    if (id == Expressions::ID::add || id == Expressions::ID::divide || id == Expressions::ID::modulus ||
        id == Expressions::ID::multiply || id == Expressions::ID::negate || id == Expressions::ID::power)
        base = renderParenthesis(base);
    if (!noParenthesisInExponent())
    {
        id = exp.getChild(1)->id();
        if (id == Expressions::ID::add     || id == Expressions::ID::divide   ||
            id == Expressions::ID::modulus || id == Expressions::ID::multiply ||
            id == Expressions::ID::negate)
            exponent = renderParenthesis(exponent);
    }
    this->childResults.push(renderSuperscript(base, exponent));
    return true;
}
template<typename T>
bool Infix<T>::visitSymbol(const Symbol& exp)
{
    unsigned int nc = exp.numberOfChildren();
    if (!nc)
    {
        this->childResults.push(renderString(exp.getName()));
        return true;
    }
    T resultLeft, resultRight;
    for (unsigned int currentChild = nc-1; (currentChild+1) >= 1; currentChild--)
    {
        resultLeft = getPop(this->childResults);
        if (currentChild != nc-1)
            resultRight = renderComma(resultLeft, resultRight);
        else
            resultRight = resultLeft;
    }
    resultRight = renderParenthesis(resultRight);
    T name = renderString(exp.getName());
    this->childResults.push(renderAdjacent(name, resultRight));
    return true;
}

} /* namespace Render */
} /* namespace Visitors */
} /* namespace Expressions */
} /* namespace CAS */
} /* namespace DS */
<|endoftext|>


<commit_before>/**
    For conditions of distribution and use, see copyright notice in LICENSE

    @file   ConsoleAPI.cpp
    @brief  Console core API. */

#include "StableHeaders.h"
#include "DebugOperatorNew.h"

#include "ConsoleAPI.h"
#include "ConsoleWidget.h"
#include "ShellInputThread.h"
#include "Application.h"
#include "Profiler.h"
#include "Framework.h"
#include "InputAPI.h"
#include "UiAPI.h"
#include "UiGraphicsView.h"
#include "LoggingFunctions.h"
#include "FunctionInvoker.h"

#include <stdlib.h>

#include <QFile>
#include <QTextStream>

#ifdef ANDROID
#include <android/log.h>
#endif

#include "MemoryLeakCheck.h"

ConsoleAPI::ConsoleAPI(Framework *fw) :
    QObject(fw),
    framework(fw),
    enabledLogChannels(LogLevelErrorWarnInfo),
    logFile(0),
    logFileText(0)
{
    if (!fw->IsHeadless())
        consoleWidget = new ConsoleWidget(framework);

    inputContext = framework->Input()->RegisterInputContext("Console", 100);
    inputContext->SetTakeKeyboardEventsOverQt(true);
    connect(inputContext.get(), SIGNAL(KeyEventReceived(KeyEvent *)), SLOT(HandleKeyEvent(KeyEvent *)));

    RegisterCommand("help", "Lists all registered commands.", this, SLOT(ListCommands()));
    RegisterCommand("clear", "Clears the console log.", this, SLOT(ClearLog()));
    RegisterCommand("setLogLevel", "Sets the current log level. Call with one of the parameters \"error\", \"warning\", \"info\", or \"debug\".",
        this, SLOT(SetLogLevel(const QString &)));
#ifdef WIN32
    RegisterCommand("createConsole", "Creates the native Windows console if Tundra was started without such.", this, SLOT(CreateNativeConsole()));
    RegisterCommand("removeConsole", "Removes the native Windows console if applicable.", this, SLOT(RemoveNativeConsole()));
#endif

    /// \todo Visual Leak Detector shows a memory leak originating from this allocation although the shellInputThread is released in the destructor. Perhaps a shared pointer is held elsewhere.
    shellInputThread = MAKE_SHARED(ShellInputThread);

    QStringList logLevel = fw->CommandLineParameters("--loglevel");
    if (logLevel.size() >= 1)
        SetLogLevel(logLevel[logLevel.size()-1]);
    if (logLevel.size() > 1)
        LogWarning("Ignoring multiple --loglevel command line parameters!");

    QStringList logFile = fw->CommandLineParameters("--logfile");
    if (logFile.size() >= 1)
        SetLogFile(logFile[logFile.size()-1]);
    if (logFile.size() > 1)
        LogWarning("Ignoring multiple --logfile command line parameters!");
}

ConsoleAPI::~ConsoleAPI()
{
    Reset();
}

void ConsoleAPI::Reset()
{
    commands.clear();
    inputContext.reset();
    SAFE_DELETE(consoleWidget);
    shellInputThread.reset();
    SAFE_DELETE(logFileText);
    SAFE_DELETE(logFile);
}

QVariant ConsoleCommand::Invoke(const QStringList &params)
{
    QVariant returnValue;

    // If we have a target QObject, invoke it.
    if (target)
    {
        // Check if we're invoking function with default arguments.
        QString func = functionName;
        int numRequiredArgs = FunctionInvoker::NumArgsForFunction(target, functionName);
        if (params.size() < numRequiredArgs && !functionNameDefaultArgs.isEmpty())
            func = functionNameDefaultArgs;

        QString errorMessage;
        FunctionInvoker::Invoke(target, func, params, &returnValue, &errorMessage);
        if (!errorMessage.isEmpty())
            LogError("ConsoleCommand::Invoke returned an error: " + errorMessage);
    }

    // Also, there may exist a script-registered handler that implements this console command - invoke it.
    emit Invoked(params);

    return returnValue;
}

QStringList ConsoleAPI::AvailableCommands() const
{
    QStringList ret;
    for(CommandMap::const_iterator iter = commands.begin(); iter != commands.end(); ++iter)
        ret << iter->first;
    return ret;
}

ConsoleCommand *ConsoleAPI::RegisterCommand(const QString &name, const QString &desc)
{
    if (name.isEmpty())
    {
        LogError("ConsoleAPI::RegisterCommand: Command name can not be an empty string.");
        return 0;
    }
    if (commands.find(name) != commands.end())
    {
        LogWarning("ConsoleAPI::RegisterCommand: Command " + name + " is already registered.");
        return commands[name].get();
    }

    shared_ptr<ConsoleCommand> command = MAKE_SHARED(ConsoleCommand, name, desc, (QObject *)0, "", "");
    commands[name] = command;
    return command.get();
}

void ConsoleAPI::RegisterCommand(const QString &name, const QString &desc, QObject *receiver, const char *memberSlot, const char *memberSlotDefaultArgs)
{
    if (name.isEmpty())
    {
        LogError("ConsoleAPI::RegisterCommand: Command name can not be an empty string.");
        return;
    }
    if (commands.find(name) != commands.end())
    {
        LogWarning("ConsoleAPI::RegisterCommand: Command " + name + " is already registered.");
        return;
    }

    shared_ptr<ConsoleCommand> command = MAKE_SHARED(ConsoleCommand, name, desc, receiver, memberSlot+1, memberSlotDefaultArgs ? memberSlotDefaultArgs+1 : "");
    commands[name] = command;
}

void ConsoleAPI::UnregisterCommand(const QString &name)
{
    CommandMap::iterator it = commands.find(name);
    if (it == commands.end())
    {
        LogWarning("ConsoleAPI: Trying to unregister non-existing command " + name + ".");
        return;
    }

    commands.erase(it);
}

/// Splits a string of form "MyFunctionName(param1, param2, param3, ...)" into
/// a commandName = "MyFunctionName" and a list of parameters as a StringList.
void ParseCommand(QString command, QString &commandName, QStringList &parameterList)
{
    command = command.trimmed();
    if (command.isEmpty())
        return;

    int split = command.indexOf("(");
    if (split == -1)
    {
        commandName = command;
        return;
    }

    commandName = command.left(split).trimmed();
    // Take into account the possible ending ")" and strip it away from the parameter list.
    // Remove it only if it's the last character in the string, as f.ex. some code execution console
    // command could contain ')' in the syntax.
    int endOfSplit = command.lastIndexOf(")");
    if (endOfSplit != -1 && endOfSplit == command.length()-1)
        command.remove(endOfSplit, 1);
    parameterList = command.mid(split+1).split(",");
    // Trim parameters in order to avoid errors if/when converting strings to other data types.
    for(int i = 0; i < parameterList.size(); ++i)
        parameterList[i] = parameterList[i].trimmed();
}

void ConsoleAPI::ExecuteCommand(const QString &command)
{
    PROFILE(ConsoleAPI_ExecuteCommand);

    QString commandName;
    QStringList parameterList;
    ParseCommand(command, commandName, parameterList);
    if (commandName.isEmpty())
        return;

    CommandMap::iterator iter = commands.find(commandName);
    if (iter == commands.end())
    {
        LogError("Cannot find a console command \"" + commandName + "\"!");
        return;
    }

    iter->second->Invoke(parameterList);
}

void ConsoleAPI::Print(const QString &message)
{
    if (consoleWidget)
        consoleWidget->PrintToConsole(message);
    ///\todo Temporary hack which appends line ending in case it's not there (output of console commands in headless mode)
    if (!message.endsWith("\n"))
    {
#ifndef ANDROID
        printf("%s\n", message.toStdString().c_str());
#else
        __android_log_print(ANDROID_LOG_INFO, "Tundra", "%s\n", message.toStdString().c_str());
#endif
        if (logFileText)
        {
            (*logFileText) << message << "\n";
            /// \note If we want to guarantee that each message gets to the log even in the presence of a crash, we must flush()
            /// after each write. Tested that on Windows 7, if you kill the process using Ctrl-C on command line, or from
            /// task manager, the log will not contain all the text, so this is required for correctness.
            /// But this flush() after each message also causes a *serious* performance drawback.
            /// One way to try avoiding this issue is to move to using C API for file writing, and at atexit() and other crash
            /// handlers, close the file handle gracefully.
            logFileText->flush();
        }
    }
    else
    {
#ifndef ANDROID
        printf("%s", message.toStdString().c_str());
#else
        __android_log_print(ANDROID_LOG_INFO, "Tundra", "%s", message.toStdString().c_str());
#endif
        if (logFileText)
        {
            (*logFileText) << message;
            logFileText->flush(); // See comment about flush() above.
        }
    }
}

void ConsoleAPI::ListCommands()
{
    Print("Available console commands (case-insensitive):");
    for(CommandMap::iterator iter = commands.begin(); iter != commands.end(); ++iter)
        Print(iter->first + " - " + iter->second->Description());
}

void ConsoleAPI::ClearLog()
{
    if (consoleWidget)
        consoleWidget->ClearLog();
#ifdef _WINDOWS
    (void)system("cls");
#else
    (void)system("clear");
#endif
}

void ConsoleAPI::SetLogLevel(const QString &level)
{
    if (level.compare("error", Qt::CaseInsensitive) == 0)
        SetEnabledLogChannels(LogLevelErrorsOnly);
    else if (level.compare("warning", Qt::CaseInsensitive) == 0)
        SetEnabledLogChannels(LogLevelErrorWarning);
    else if (level.compare("info", Qt::CaseInsensitive) == 0)
        SetEnabledLogChannels(LogLevelErrorWarnInfo);
    else if (level.compare("debug", Qt::CaseInsensitive) == 0)
        SetEnabledLogChannels(LogLevelErrorWarnInfoDebug);
    else
        LogError("Unknown parameter \"" + level + "\" specified to ConsoleAPI::SetLogLevel!");
}

void ConsoleAPI::SetLogFile(const QString &wildCardFilename)
{
    QString filename = Application::ParseWildCardFilename(wildCardFilename);

    // An empty log file closes the log output writing.
    if (filename.isEmpty())
    {
        SAFE_DELETE(logFileText);
        SAFE_DELETE(logFile);
        return;
    }
    logFile = new QFile(filename);
    bool isOpen = logFile->open(QIODevice::WriteOnly | QIODevice::Text);
    if (!isOpen)
    {
        LogError("Failed to open file \"" + filename + "\" for logging! (parsed from string \"" + wildCardFilename + "\")");
        SAFE_DELETE(logFile);
    }
    else
    {
        printf("Opened logging file \"%s\".\n", filename.toStdString().c_str());
        logFileText = new QTextStream(logFile);
    }
}

void ConsoleAPI::Update(f64 /*frametime*/)
{
    PROFILE(ConsoleAPI_Update);

    std::string input = shellInputThread->GetLine();
    if (input.length() > 0)
        ExecuteCommand(input.c_str());
}

void ConsoleAPI::ToggleConsole()
{
    if (consoleWidget)
        consoleWidget->ToggleConsole();
}

void ConsoleAPI::HandleKeyEvent(KeyEvent *e)
{
    if (e->sequence == framework->Input()->KeyBinding("ToggleConsole", QKeySequence(Qt::Key_F1)))
        ToggleConsole();
}

void ConsoleAPI::CreateNativeConsole()
{
#ifdef WIN32
    if (Application::ShowConsoleWindow(false))
        shellInputThread = MAKE_SHARED(ShellInputThread); // Recreate ShellInputThread so that we will have working input.
#endif
}

void ConsoleAPI::RemoveNativeConsole()
{
#ifdef WIN32
    FreeConsole();
#endif
}

void ConsoleAPI::LogInfo(const QString &message)
{
    ::LogInfo(message);
}

void ConsoleAPI::LogWarning(const QString &message)
{
    ::LogWarning(message);
}

void ConsoleAPI::LogError(const QString &message)
{
    ::LogError(message);
}

void ConsoleAPI::LogDebug(const QString &message)
{
    ::LogDebug(message);
}

void ConsoleAPI::Log(u32 logChannel, const QString &message)
{
    if (IsLogChannelEnabled(logChannel))
        Print(message);
}

void ConsoleAPI::SetEnabledLogChannels(u32 newChannels)
{
    enabledLogChannels = newChannels;
}

bool ConsoleAPI::IsLogChannelEnabled(u32 logChannel) const
{
    return (enabledLogChannels & logChannel) != 0;
}

u32 ConsoleAPI::EnabledLogChannels() const
{
    return enabledLogChannels;
}

<commit_msg>ConsoleAPI::ClearLog: Check that native console exists. If not and we call cls, we see a console flashing briefly on the screen which is undesirable.<commit_after>/**
    For conditions of distribution and use, see copyright notice in LICENSE

    @file   ConsoleAPI.cpp
    @brief  Console core API. */

#include "StableHeaders.h"
#include "DebugOperatorNew.h"

#include "ConsoleAPI.h"
#include "ConsoleWidget.h"
#include "ShellInputThread.h"
#include "Application.h"
#include "Profiler.h"
#include "Framework.h"
#include "InputAPI.h"
#include "UiAPI.h"
#include "UiGraphicsView.h"
#include "LoggingFunctions.h"
#include "FunctionInvoker.h"

#include <stdlib.h>

#include <QFile>
#include <QTextStream>

#ifdef ANDROID
#include <android/log.h>
#endif

#include "MemoryLeakCheck.h"

ConsoleAPI::ConsoleAPI(Framework *fw) :
    QObject(fw),
    framework(fw),
    enabledLogChannels(LogLevelErrorWarnInfo),
    logFile(0),
    logFileText(0)
{
    if (!fw->IsHeadless())
        consoleWidget = new ConsoleWidget(framework);

    inputContext = framework->Input()->RegisterInputContext("Console", 100);
    inputContext->SetTakeKeyboardEventsOverQt(true);
    connect(inputContext.get(), SIGNAL(KeyEventReceived(KeyEvent *)), SLOT(HandleKeyEvent(KeyEvent *)));

    RegisterCommand("help", "Lists all registered commands.", this, SLOT(ListCommands()));
    RegisterCommand("clear", "Clears the console log.", this, SLOT(ClearLog()));
    RegisterCommand("setLogLevel", "Sets the current log level. Call with one of the parameters \"error\", \"warning\", \"info\", or \"debug\".",
        this, SLOT(SetLogLevel(const QString &)));
#ifdef WIN32
    RegisterCommand("createConsole", "Creates the native Windows console if Tundra was started without such.", this, SLOT(CreateNativeConsole()));
    RegisterCommand("removeConsole", "Removes the native Windows console if applicable.", this, SLOT(RemoveNativeConsole()));
#endif

    /// \todo Visual Leak Detector shows a memory leak originating from this allocation although the shellInputThread is released in the destructor. Perhaps a shared pointer is held elsewhere.
    shellInputThread = MAKE_SHARED(ShellInputThread);

    QStringList logLevel = fw->CommandLineParameters("--loglevel");
    if (logLevel.size() >= 1)
        SetLogLevel(logLevel[logLevel.size()-1]);
    if (logLevel.size() > 1)
        LogWarning("Ignoring multiple --loglevel command line parameters!");

    QStringList logFile = fw->CommandLineParameters("--logfile");
    if (logFile.size() >= 1)
        SetLogFile(logFile[logFile.size()-1]);
    if (logFile.size() > 1)
        LogWarning("Ignoring multiple --logfile command line parameters!");
}

ConsoleAPI::~ConsoleAPI()
{
    Reset();
}

void ConsoleAPI::Reset()
{
    commands.clear();
    inputContext.reset();
    SAFE_DELETE(consoleWidget);
    shellInputThread.reset();
    SAFE_DELETE(logFileText);
    SAFE_DELETE(logFile);
}

QVariant ConsoleCommand::Invoke(const QStringList &params)
{
    QVariant returnValue;

    // If we have a target QObject, invoke it.
    if (target)
    {
        // Check if we're invoking function with default arguments.
        QString func = functionName;
        int numRequiredArgs = FunctionInvoker::NumArgsForFunction(target, functionName);
        if (params.size() < numRequiredArgs && !functionNameDefaultArgs.isEmpty())
            func = functionNameDefaultArgs;

        QString errorMessage;
        FunctionInvoker::Invoke(target, func, params, &returnValue, &errorMessage);
        if (!errorMessage.isEmpty())
            LogError("ConsoleCommand::Invoke returned an error: " + errorMessage);
    }

    // Also, there may exist a script-registered handler that implements this console command - invoke it.
    emit Invoked(params);

    return returnValue;
}

QStringList ConsoleAPI::AvailableCommands() const
{
    QStringList ret;
    for(CommandMap::const_iterator iter = commands.begin(); iter != commands.end(); ++iter)
        ret << iter->first;
    return ret;
}

ConsoleCommand *ConsoleAPI::RegisterCommand(const QString &name, const QString &desc)
{
    if (name.isEmpty())
    {
        LogError("ConsoleAPI::RegisterCommand: Command name can not be an empty string.");
        return 0;
    }
    if (commands.find(name) != commands.end())
    {
        LogWarning("ConsoleAPI::RegisterCommand: Command " + name + " is already registered.");
        return commands[name].get();
    }

    shared_ptr<ConsoleCommand> command = MAKE_SHARED(ConsoleCommand, name, desc, (QObject *)0, "", "");
    commands[name] = command;
    return command.get();
}

void ConsoleAPI::RegisterCommand(const QString &name, const QString &desc, QObject *receiver, const char *memberSlot, const char *memberSlotDefaultArgs)
{
    if (name.isEmpty())
    {
        LogError("ConsoleAPI::RegisterCommand: Command name can not be an empty string.");
        return;
    }
    if (commands.find(name) != commands.end())
    {
        LogWarning("ConsoleAPI::RegisterCommand: Command " + name + " is already registered.");
        return;
    }

    shared_ptr<ConsoleCommand> command = MAKE_SHARED(ConsoleCommand, name, desc, receiver, memberSlot+1, memberSlotDefaultArgs ? memberSlotDefaultArgs+1 : "");
    commands[name] = command;
}

void ConsoleAPI::UnregisterCommand(const QString &name)
{
    CommandMap::iterator it = commands.find(name);
    if (it == commands.end())
    {
        LogWarning("ConsoleAPI: Trying to unregister non-existing command " + name + ".");
        return;
    }

    commands.erase(it);
}

/// Splits a string of form "MyFunctionName(param1, param2, param3, ...)" into
/// a commandName = "MyFunctionName" and a list of parameters as a StringList.
void ParseCommand(QString command, QString &commandName, QStringList &parameterList)
{
    command = command.trimmed();
    if (command.isEmpty())
        return;

    int split = command.indexOf("(");
    if (split == -1)
    {
        commandName = command;
        return;
    }

    commandName = command.left(split).trimmed();
    // Take into account the possible ending ")" and strip it away from the parameter list.
    // Remove it only if it's the last character in the string, as f.ex. some code execution console
    // command could contain ')' in the syntax.
    int endOfSplit = command.lastIndexOf(")");
    if (endOfSplit != -1 && endOfSplit == command.length()-1)
        command.remove(endOfSplit, 1);
    parameterList = command.mid(split+1).split(",");
    // Trim parameters in order to avoid errors if/when converting strings to other data types.
    for(int i = 0; i < parameterList.size(); ++i)
        parameterList[i] = parameterList[i].trimmed();
}

void ConsoleAPI::ExecuteCommand(const QString &command)
{
    PROFILE(ConsoleAPI_ExecuteCommand);

    QString commandName;
    QStringList parameterList;
    ParseCommand(command, commandName, parameterList);
    if (commandName.isEmpty())
        return;

    CommandMap::iterator iter = commands.find(commandName);
    if (iter == commands.end())
    {
        LogError("Cannot find a console command \"" + commandName + "\"!");
        return;
    }

    iter->second->Invoke(parameterList);
}

void ConsoleAPI::Print(const QString &message)
{
    if (consoleWidget)
        consoleWidget->PrintToConsole(message);
    ///\todo Temporary hack which appends line ending in case it's not there (output of console commands in headless mode)
    if (!message.endsWith("\n"))
    {
#ifndef ANDROID
        printf("%s\n", message.toStdString().c_str());
#else
        __android_log_print(ANDROID_LOG_INFO, "Tundra", "%s\n", message.toStdString().c_str());
#endif
        if (logFileText)
        {
            (*logFileText) << message << "\n";
            /// \note If we want to guarantee that each message gets to the log even in the presence of a crash, we must flush()
            /// after each write. Tested that on Windows 7, if you kill the process using Ctrl-C on command line, or from
            /// task manager, the log will not contain all the text, so this is required for correctness.
            /// But this flush() after each message also causes a *serious* performance drawback.
            /// One way to try avoiding this issue is to move to using C API for file writing, and at atexit() and other crash
            /// handlers, close the file handle gracefully.
            logFileText->flush();
        }
    }
    else
    {
#ifndef ANDROID
        printf("%s", message.toStdString().c_str());
#else
        __android_log_print(ANDROID_LOG_INFO, "Tundra", "%s", message.toStdString().c_str());
#endif
        if (logFileText)
        {
            (*logFileText) << message;
            logFileText->flush(); // See comment about flush() above.
        }
    }
}

void ConsoleAPI::ListCommands()
{
    Print("Available console commands (case-insensitive):");
    for(CommandMap::iterator iter = commands.begin(); iter != commands.end(); ++iter)
        Print(iter->first + " - " + iter->second->Description());
}

void ConsoleAPI::ClearLog()
{
    if (consoleWidget)
        consoleWidget->ClearLog();
#ifdef _WINDOWS
    // Check that native console exists. If not and we call cls, we see a console flashing briefly on the screen which is undesirable.
    if (GetConsoleWindow())
        (void)system("cls");
#else
    (void)system("clear");
#endif
}

void ConsoleAPI::SetLogLevel(const QString &level)
{
    if (level.compare("error", Qt::CaseInsensitive) == 0)
        SetEnabledLogChannels(LogLevelErrorsOnly);
    else if (level.compare("warning", Qt::CaseInsensitive) == 0)
        SetEnabledLogChannels(LogLevelErrorWarning);
    else if (level.compare("info", Qt::CaseInsensitive) == 0)
        SetEnabledLogChannels(LogLevelErrorWarnInfo);
    else if (level.compare("debug", Qt::CaseInsensitive) == 0)
        SetEnabledLogChannels(LogLevelErrorWarnInfoDebug);
    else
        LogError("Unknown parameter \"" + level + "\" specified to ConsoleAPI::SetLogLevel!");
}

void ConsoleAPI::SetLogFile(const QString &wildCardFilename)
{
    QString filename = Application::ParseWildCardFilename(wildCardFilename);

    // An empty log file closes the log output writing.
    if (filename.isEmpty())
    {
        SAFE_DELETE(logFileText);
        SAFE_DELETE(logFile);
        return;
    }
    logFile = new QFile(filename);
    bool isOpen = logFile->open(QIODevice::WriteOnly | QIODevice::Text);
    if (!isOpen)
    {
        LogError("Failed to open file \"" + filename + "\" for logging! (parsed from string \"" + wildCardFilename + "\")");
        SAFE_DELETE(logFile);
    }
    else
    {
        printf("Opened logging file \"%s\".\n", filename.toStdString().c_str());
        logFileText = new QTextStream(logFile);
    }
}

void ConsoleAPI::Update(f64 /*frametime*/)
{
    PROFILE(ConsoleAPI_Update);

    std::string input = shellInputThread->GetLine();
    if (input.length() > 0)
        ExecuteCommand(input.c_str());
}

void ConsoleAPI::ToggleConsole()
{
    if (consoleWidget)
        consoleWidget->ToggleConsole();
}

void ConsoleAPI::HandleKeyEvent(KeyEvent *e)
{
    if (e->sequence == framework->Input()->KeyBinding("ToggleConsole", QKeySequence(Qt::Key_F1)))
        ToggleConsole();
}

void ConsoleAPI::CreateNativeConsole()
{
#ifdef WIN32
    if (Application::ShowConsoleWindow(false))
        shellInputThread = MAKE_SHARED(ShellInputThread); // Recreate ShellInputThread so that we will have working input.
#endif
}

void ConsoleAPI::RemoveNativeConsole()
{
#ifdef WIN32
    FreeConsole();
#endif
}

void ConsoleAPI::LogInfo(const QString &message)
{
    ::LogInfo(message);
}

void ConsoleAPI::LogWarning(const QString &message)
{
    ::LogWarning(message);
}

void ConsoleAPI::LogError(const QString &message)
{
    ::LogError(message);
}

void ConsoleAPI::LogDebug(const QString &message)
{
    ::LogDebug(message);
}

void ConsoleAPI::Log(u32 logChannel, const QString &message)
{
    if (IsLogChannelEnabled(logChannel))
        Print(message);
}

void ConsoleAPI::SetEnabledLogChannels(u32 newChannels)
{
    enabledLogChannels = newChannels;
}

bool ConsoleAPI::IsLogChannelEnabled(u32 logChannel) const
{
    return (enabledLogChannels & logChannel) != 0;
}

u32 ConsoleAPI::EnabledLogChannels() const
{
    return enabledLogChannels;
}

<|endoftext|>


<commit_before>//  Powiter
//
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
*Created by Alexandre GAUTHIER-FOICHAT on 6/1/2012.
*contact: immarespond at gmail dot com
*
*/

#include "ExrDecoder.h"

#ifdef __POWITER_WIN32__
#include <fstream>
#endif
#include <QtGui/QImage>
#include <QtCore/QByteArray>
#include <QtCore/QMutex>
#include <ImfPixelType.h>
#include <ImfChannelList.h>
#ifdef __POWITER_WIN32__
#include <ImfStdIO.h>
#endif

#include "Readers/Reader.h"
#include "Gui/KnobGui.h"
#include "Engine/Node.h"
#include "Gui/NodeGui.h"
#include "Gui/ViewerGL.h"
#include "Engine/Lut.h"
#include "Engine/Row.h"
#include "Engine/ImageInfo.h"

#ifndef OPENEXR_IMF_NAMESPACE
#define OPENEXR_IMF_NAMESPACE Imf
#endif
namespace Imf_ = OPENEXR_IMF_NAMESPACE;

using std::cout; using std::endl;

struct ExrDecoder::Implementation {
    Implementation();

    Imf::InputFile* _inputfile;
    std::map<Powiter::Channel, std::string> _channel_map;
    std::vector<std::string> _views;
    int _dataOffset;
#ifdef __POWITER_WIN32__
    std::ifstream* _inputStr;
    Imf::StdIFStream* _inputStdStream;
#endif
	QMutex _lock;
};

namespace EXR {
static Powiter::Channel fromExrChannel(const std::string& from)
{
    if (from == "R" ||
        from == "r" ||
        from == "Red" ||
        from == "RED" ||
        from == "red" ||
        from == "y" ||
        from == "Y") {
        return Powiter::Channel_red;
    }
    if (from == "G" ||
        from == "g" ||
        from == "Green" ||
        from == "GREEN" ||
        from == "green" ||
        from == "ry" ||
        from == "RY") {
        return Powiter::Channel_green;
    }
    if (from == "B" ||
        from == "b" ||
        from == "Blue" ||
        from == "BLUE" ||
        from == "blue" ||
        from == "by" ||
        from == "BY") {
        return Powiter::Channel_blue;
    }
    if (from == "A" ||
        from == "a" ||
        from == "Alpha" ||
        from == "ALPHA" ||
        from == "alpha") {
        return Powiter::Channel_alpha;
    }
    if (from == "Z" ||
        from == "z" ||
        from == "Depth" ||
        from == "DEPTH" ||
        from == "depth") {
        return Powiter::Channel_Z;
    }
    // The following may throw if from is not a channel name which begins with "Channel_"
    return Powiter::getChannelByName(from);
}

class ChannelExtractor
{
public:
    ChannelExtractor(const std::string& name, const std::vector<std::string>& views) :
    _mappedChannel(Powiter::Channel_black),
    _valid(false)
    {     _valid = extractExrChannelName(name.c_str(), views);  }

    ~ChannelExtractor() {}

    Powiter::Channel _mappedChannel;
    bool _valid;
    std::string _chan;
    std::string _layer;
    std::string _view;

    std::string exrName() const{
        if (!_layer.empty())
            return _layer + "." + _chan;
        return _chan;
    }

    bool isValid() const {return _valid;}

private:

    static bool IsView(const std::string& name, const std::vector<std::string>& views)
    {
        for ( size_t i = 0; i < views.size(); ++i ){
            if ( views[i] == name ){
                return true;
            }
        }

        return false;
    }

    bool extractExrChannelName(const QString& channelname,
                               const std::vector<std::string>& views){
        _chan.clear();
        _layer.clear();
        _view.clear();

        QStringList splits = channelname.split(QChar('.'),QString::SkipEmptyParts);
        QStringList newSplits;
        //remove prepending digits
        for (int i = 0; i < splits.size(); ++i) {
            QString str = splits.at(i);
            int j = 0;
            while (j < str.size() && str.at(j).isDigit()) { ++j; }
            str = str.remove(0, j);
            if(!str.isEmpty()){
                //remove non alphanumeric chars
                QString finalStr;
                for (int k = 0; k < str.size(); ++k) {
                    QChar c = str.at(k);
                    if (!c.isLetterOrNumber())  {
                        c = '_';
                    }
                    finalStr.append(c);
                }
                newSplits << finalStr;
            }
        }

        if (newSplits.size() > 1){

            for (int i = 0; i < (newSplits.size() - 1);++i) {
                std::vector<std::string>::const_iterator foundView = std::find(views.begin(), views.end(),newSplits.at(i).toStdString());
                if (foundView != views.end()) {
                    _view = *foundView;
                } else {
                    if (!_layer.empty())
                        _layer += "_";
                    _layer += newSplits.at(i).toStdString();
                }
            }
            _chan = newSplits.back().toStdString();
        } else {
            _chan = newSplits.at(0).toStdString();
        }

        try{
            _mappedChannel = EXR::fromExrChannel(_chan);
        } catch (const std::exception &e) {
            std::cout << e.what() << endl;
            return false;
        }
        return true;
    }
};

} // namespace EXR

Powiter::Status ExrDecoder::readHeader(const QString& filename){

    _imp->_channel_map.clear();
    _imp->_views.clear();
    try {
#ifdef __POWITER_WIN32__
        QByteArray ba = filename.toLocal8Bit();
        if(_imp->_inputStr){
            delete _imp->_inputStr;
        }
        if(_imp->_inputStdStream){
            delete _imp->_inputStdStream;
        }
        if(_imp->_inputfile){
            delete _imp->_inputfile;
        }
        _imp->_inputStr = new std::ifstream(PowiterWindows::s2ws(ba.data()),std::ios_base::binary);
        _imp->_inputStdStream = new Imf_::StdIFStream(*_inputStr,ba.data());
        _imp->_inputfile = new Imf_::InputFile(*_inputStdStream);
#else
        QByteArray ba = filename.toLatin1();
        if(_imp->_inputfile){
            delete _imp->_inputfile;
        }
        _imp->_inputfile = new Imf_::InputFile(ba.constData());
#endif

        // multiview is only supported with OpenEXR >= 1.7.0
#ifdef INCLUDED_IMF_STRINGVECTOR_ATTRIBUTE_H // use ImfStringVectorAttribute.h's #include guard
        const Imf_::StringAttribute* stringMultiView = 0;
        const Imf_::StringVectorAttribute* vectorMultiView = 0;

        try {
            vectorMultiView = inputfile->header().findTypedAttribute<Imf_::StringVectorAttribute>("multiView");

            if (!vectorMultiView) {
                Imf_::Header::ConstIterator it = inputfile->header().find("multiView");
                if (it != inputfile->header().end() && !strcmp(it.attribute().typeName(), "stringvector"))
                    vectorMultiView = static_cast<const Imf_::StringVectorAttribute*>(&it.attribute());
            }

            stringMultiView = inputfile->header().findTypedAttribute<Imf_::StringAttribute>("multiView");
        }
        catch (...) {
            return StatFailed;
        }

        if (vectorMultiView) {
            std::vector<std::string> s = vectorMultiView->value();

            bool setHero = false;

            for (size_t i = 0; i < s.size(); ++i) {
                if (s[i].length()) {
                    _views.push_back(s[i]);
                    if (!setHero) {
                        heroview = s[i];
                        setHero = true;
                    }
                }
            }
        }
#endif // !OPENEXR_NO_MULTIVIEW
        std::map<Imf_::PixelType, int> pixelTypes;
        // convert exr channels to powiter channels
        Powiter::ChannelSet mask;
        const Imf_::ChannelList& imfchannels = _imp->_inputfile->header().channels();
        Imf_::ChannelList::ConstIterator chan;
        for (chan = imfchannels.begin(); chan != imfchannels.end(); ++chan) {
            std::string chanName(chan.name());
            if(chanName.empty())
                continue;
            pixelTypes[chan.channel().type]++;
            EXR::ChannelExtractor exrExctractor(chan.name(), _imp->_views);
            std::set<Powiter::Channel> channels;
            if (exrExctractor.isValid()) {
                channels.insert(exrExctractor._mappedChannel);
                //cout << "size : "<< channels.size() << endl;
                for (std::set<Powiter::Channel>::const_iterator it = channels.begin(); it != channels.end(); ++it) {
                    Powiter::Channel channel = *it;
                    //cout <<" channel_map[" << Powiter::getChannelName(channel) << "] = " << chan.name() << endl;
                    bool writeChannelMapping = true;
                    ChannelsMap::const_iterator found = _imp->_channel_map.find(channel);
                    if(found != _imp->_channel_map.end()){
                        int existingLength = found->second.size();
                        int newLength = chanName.size();
                        if ((existingLength > 0) && found->second.at(0) == '.' && existingLength == (newLength + 1)) {                                writeChannelMapping = true;
                        }
                        else if (existingLength > newLength) {
                            writeChannelMapping = false;
                        }
                    }
                    if(writeChannelMapping){
                        _imp->_channel_map.insert(make_pair(channel,chanName));
                    }
                    mask += channel;
                }

            }else {
                cout << "Cannot decode channel " << chan.name() << endl;
            }

        }

        const Imath::Box2i& datawin = _imp->_inputfile->header().dataWindow();
        const Imath::Box2i& dispwin = _imp->_inputfile->header().displayWindow();
        Imath::Box2i formatwin(dispwin);
        formatwin.min.x = 0;
        formatwin.min.y = 0;
        _imp->_dataOffset = 0;
        if (dispwin.min.x != 0) {
            // Shift both to get dispwindow over to 0,0.
            _imp->_dataOffset = -dispwin.min.x;
            formatwin.max.x = dispwin.max.x + _imp->_dataOffset;
        }
        formatwin.max.y = dispwin.max.y - dispwin.min.y;
        double aspect = _imp->_inputfile->header().pixelAspectRatio();
        Format imageFormat(0,0,formatwin.max.x + 1 ,formatwin.max.y + 1,"",aspect);
        Box2D rod;

        int left = datawin.min.x + _imp->_dataOffset;
        int bottom = dispwin.max.y - datawin.max.y;
        int right = datawin.max.x + _imp->_dataOffset;
        int top = dispwin.max.y - datawin.min.y;
        if (datawin.min.x != dispwin.min.x || datawin.max.x != dispwin.max.x ||
                datawin.min.y != dispwin.min.y || datawin.max.y != dispwin.max.y) {
            --left;
            --bottom;
            ++right;
            ++top;
            //            _readerInfo->setBlackOutside(true);
        }
        rod.set(left, bottom, right+1, top+1);

        setReaderInfo(imageFormat, rod, mask);
        return Powiter::StatOK;
    }
    catch (const std::exception& exc) {
        cout << "OpenEXR error: " << exc.what() << endl;
        delete _imp->_inputfile;
        _imp->_inputfile = 0;
        return Powiter::StatFailed;
    }

}

ExrDecoder::ExrDecoder(Reader* op)
: Decoder(op)
, _imp(new Implementation)
{
}

ExrDecoder::Implementation::Implementation()
: _inputfile(0)
, _dataOffset(0)
#ifdef __POWITER_WIN32__
, _inputStr(NULL)
, _inputStdStream(NULL)
#endif
{
}

void ExrDecoder::initializeColorSpace(){
    _lut=Powiter::Color::getLut(Powiter::Color::LUT_DEFAULT_FLOAT); // linear color-space for exr files
}

ExrDecoder::~ExrDecoder(){
#ifdef __POWITER_WIN32__
    delete _imp->_inputStr ;
    delete _imp->_inputStdStream ;
#endif
    delete _imp->_inputfile;
}

void ExrDecoder::render(SequenceTime /*time*/,Powiter::Row* out){
    const Powiter::ChannelSet& channels = out->channels();
    const Imath::Box2i& dispwin = _imp->_inputfile->header().displayWindow();
    const Imath::Box2i& datawin = _imp->_inputfile->header().dataWindow();
    int exrY = dispwin.max.y - out->y();
    int r = out->right();
    int x = out->left();

    const int X = std::max(x, datawin.min.x + _imp->_dataOffset);
    const int R = std::min(r, datawin.max.x + _imp->_dataOffset +1);

    // if we're below or above the data window
    if(exrY < datawin.min.y || exrY > datawin.max.y || R <= X) {
        out->eraseAll();
        return;
    }

    Imf_::FrameBuffer fbuf;
    foreachChannels(z, channels){
        // blacking out the extra padding we added
        float* dest = out->begin(z) - out->left();
        for (int xx = x; xx < X; xx++)
            dest[xx] = 0;
        for (int xx = R; xx < r; xx++)
            dest[xx] = 0;
        ChannelsMap::const_iterator found = _imp->_channel_map.find(z);
        if(found != _imp->_channel_map.end()){
            if(found->second != "BY" && found->second != "RY"){ // if it is NOT a subsampled buffer
                fbuf.insert(found->second.c_str(),Imf_::Slice(Imf_::FLOAT, (char*)(dest /*+_dataOffset*/),sizeof(float), 0));
            }else{
                fbuf.insert(found->second.c_str(),Imf_::Slice(Imf_::FLOAT, (char*)(dest /*+_dataOffset*/),sizeof(float), 0,2,2));
            }
        }else{
            //not found in the file, we zero it out
            // we're responsible for filling all channels requested by the row
            float fillValue = 0.f;
            if (z == Powiter::Channel_alpha) {
                fillValue = 1.f;
            }
            out->fill(z,fillValue);
        }
    }
    {
        QMutexLocker locker(&_imp->_lock);
        try {
            _imp->_inputfile->setFrameBuffer(fbuf);
            _imp->_inputfile->readPixels(exrY);
        } catch (const std::exception& exc) {
            cout << exc.what() <<  endl;
            return;
        }
    }

    //  colorspace conversion
    const float* alpha = out->begin(Powiter::Channel_alpha);
    foreachChannels(z, channels){
        float* to = out->begin(z) - out->left();
        const float* from = out->begin(z) - out->left();
        if(from){
            from_float(z,to + X ,from + X,alpha, R-X,1);
        }
    }
}
<commit_msg>Missing ImfInputFile #include in ExrDecoder.cpp<commit_after>//  Powiter
//
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
*Created by Alexandre GAUTHIER-FOICHAT on 6/1/2012.
*contact: immarespond at gmail dot com
*
*/

#include "ExrDecoder.h"

#ifdef __POWITER_WIN32__
#include <fstream>
#endif
#include <QtGui/QImage>
#include <QtCore/QByteArray>
#include <QtCore/QMutex>
#include <ImfPixelType.h>
#include <ImfChannelList.h>
#include <ImfInputFile.h>
#ifdef __POWITER_WIN32__
#include <ImfStdIO.h>
#endif

#include "Readers/Reader.h"
#include "Gui/KnobGui.h"
#include "Engine/Node.h"
#include "Gui/NodeGui.h"
#include "Gui/ViewerGL.h"
#include "Engine/Lut.h"
#include "Engine/Row.h"
#include "Engine/ImageInfo.h"

#ifndef OPENEXR_IMF_NAMESPACE
#define OPENEXR_IMF_NAMESPACE Imf
#endif
namespace Imf_ = OPENEXR_IMF_NAMESPACE;

using std::cout; using std::endl;

struct ExrDecoder::Implementation {
    Implementation();

    Imf::InputFile* _inputfile;
    std::map<Powiter::Channel, std::string> _channel_map;
    std::vector<std::string> _views;
    int _dataOffset;
#ifdef __POWITER_WIN32__
    std::ifstream* _inputStr;
    Imf::StdIFStream* _inputStdStream;
#endif
	QMutex _lock;
};

namespace EXR {
static Powiter::Channel fromExrChannel(const std::string& from)
{
    if (from == "R" ||
        from == "r" ||
        from == "Red" ||
        from == "RED" ||
        from == "red" ||
        from == "y" ||
        from == "Y") {
        return Powiter::Channel_red;
    }
    if (from == "G" ||
        from == "g" ||
        from == "Green" ||
        from == "GREEN" ||
        from == "green" ||
        from == "ry" ||
        from == "RY") {
        return Powiter::Channel_green;
    }
    if (from == "B" ||
        from == "b" ||
        from == "Blue" ||
        from == "BLUE" ||
        from == "blue" ||
        from == "by" ||
        from == "BY") {
        return Powiter::Channel_blue;
    }
    if (from == "A" ||
        from == "a" ||
        from == "Alpha" ||
        from == "ALPHA" ||
        from == "alpha") {
        return Powiter::Channel_alpha;
    }
    if (from == "Z" ||
        from == "z" ||
        from == "Depth" ||
        from == "DEPTH" ||
        from == "depth") {
        return Powiter::Channel_Z;
    }
    // The following may throw if from is not a channel name which begins with "Channel_"
    return Powiter::getChannelByName(from);
}

class ChannelExtractor
{
public:
    ChannelExtractor(const std::string& name, const std::vector<std::string>& views) :
    _mappedChannel(Powiter::Channel_black),
    _valid(false)
    {     _valid = extractExrChannelName(name.c_str(), views);  }

    ~ChannelExtractor() {}

    Powiter::Channel _mappedChannel;
    bool _valid;
    std::string _chan;
    std::string _layer;
    std::string _view;

    std::string exrName() const{
        if (!_layer.empty())
            return _layer + "." + _chan;
        return _chan;
    }

    bool isValid() const {return _valid;}

private:

    static bool IsView(const std::string& name, const std::vector<std::string>& views)
    {
        for ( size_t i = 0; i < views.size(); ++i ){
            if ( views[i] == name ){
                return true;
            }
        }

        return false;
    }

    bool extractExrChannelName(const QString& channelname,
                               const std::vector<std::string>& views){
        _chan.clear();
        _layer.clear();
        _view.clear();

        QStringList splits = channelname.split(QChar('.'),QString::SkipEmptyParts);
        QStringList newSplits;
        //remove prepending digits
        for (int i = 0; i < splits.size(); ++i) {
            QString str = splits.at(i);
            int j = 0;
            while (j < str.size() && str.at(j).isDigit()) { ++j; }
            str = str.remove(0, j);
            if(!str.isEmpty()){
                //remove non alphanumeric chars
                QString finalStr;
                for (int k = 0; k < str.size(); ++k) {
                    QChar c = str.at(k);
                    if (!c.isLetterOrNumber())  {
                        c = '_';
                    }
                    finalStr.append(c);
                }
                newSplits << finalStr;
            }
        }

        if (newSplits.size() > 1){

            for (int i = 0; i < (newSplits.size() - 1);++i) {
                std::vector<std::string>::const_iterator foundView = std::find(views.begin(), views.end(),newSplits.at(i).toStdString());
                if (foundView != views.end()) {
                    _view = *foundView;
                } else {
                    if (!_layer.empty())
                        _layer += "_";
                    _layer += newSplits.at(i).toStdString();
                }
            }
            _chan = newSplits.back().toStdString();
        } else {
            _chan = newSplits.at(0).toStdString();
        }

        try{
            _mappedChannel = EXR::fromExrChannel(_chan);
        } catch (const std::exception &e) {
            std::cout << e.what() << endl;
            return false;
        }
        return true;
    }
};

} // namespace EXR

Powiter::Status ExrDecoder::readHeader(const QString& filename){

    _imp->_channel_map.clear();
    _imp->_views.clear();
    try {
#ifdef __POWITER_WIN32__
        QByteArray ba = filename.toLocal8Bit();
        if(_imp->_inputStr){
            delete _imp->_inputStr;
        }
        if(_imp->_inputStdStream){
            delete _imp->_inputStdStream;
        }
        if(_imp->_inputfile){
            delete _imp->_inputfile;
        }
        _imp->_inputStr = new std::ifstream(PowiterWindows::s2ws(ba.data()),std::ios_base::binary);
        _imp->_inputStdStream = new Imf_::StdIFStream(*_inputStr,ba.data());
        _imp->_inputfile = new Imf_::InputFile(*_inputStdStream);
#else
        QByteArray ba = filename.toLatin1();
        if(_imp->_inputfile){
            delete _imp->_inputfile;
        }
        _imp->_inputfile = new Imf_::InputFile(ba.constData());
#endif

        // multiview is only supported with OpenEXR >= 1.7.0
#ifdef INCLUDED_IMF_STRINGVECTOR_ATTRIBUTE_H // use ImfStringVectorAttribute.h's #include guard
        const Imf_::StringAttribute* stringMultiView = 0;
        const Imf_::StringVectorAttribute* vectorMultiView = 0;

        try {
            vectorMultiView = inputfile->header().findTypedAttribute<Imf_::StringVectorAttribute>("multiView");

            if (!vectorMultiView) {
                Imf_::Header::ConstIterator it = inputfile->header().find("multiView");
                if (it != inputfile->header().end() && !strcmp(it.attribute().typeName(), "stringvector"))
                    vectorMultiView = static_cast<const Imf_::StringVectorAttribute*>(&it.attribute());
            }

            stringMultiView = inputfile->header().findTypedAttribute<Imf_::StringAttribute>("multiView");
        }
        catch (...) {
            return StatFailed;
        }

        if (vectorMultiView) {
            std::vector<std::string> s = vectorMultiView->value();

            bool setHero = false;

            for (size_t i = 0; i < s.size(); ++i) {
                if (s[i].length()) {
                    _views.push_back(s[i]);
                    if (!setHero) {
                        heroview = s[i];
                        setHero = true;
                    }
                }
            }
        }
#endif // !OPENEXR_NO_MULTIVIEW
        std::map<Imf_::PixelType, int> pixelTypes;
        // convert exr channels to powiter channels
        Powiter::ChannelSet mask;
        const Imf_::ChannelList& imfchannels = _imp->_inputfile->header().channels();
        Imf_::ChannelList::ConstIterator chan;
        for (chan = imfchannels.begin(); chan != imfchannels.end(); ++chan) {
            std::string chanName(chan.name());
            if(chanName.empty())
                continue;
            pixelTypes[chan.channel().type]++;
            EXR::ChannelExtractor exrExctractor(chan.name(), _imp->_views);
            std::set<Powiter::Channel> channels;
            if (exrExctractor.isValid()) {
                channels.insert(exrExctractor._mappedChannel);
                //cout << "size : "<< channels.size() << endl;
                for (std::set<Powiter::Channel>::const_iterator it = channels.begin(); it != channels.end(); ++it) {
                    Powiter::Channel channel = *it;
                    //cout <<" channel_map[" << Powiter::getChannelName(channel) << "] = " << chan.name() << endl;
                    bool writeChannelMapping = true;
                    ChannelsMap::const_iterator found = _imp->_channel_map.find(channel);
                    if(found != _imp->_channel_map.end()){
                        int existingLength = found->second.size();
                        int newLength = chanName.size();
                        if ((existingLength > 0) && found->second.at(0) == '.' && existingLength == (newLength + 1)) {                                writeChannelMapping = true;
                        }
                        else if (existingLength > newLength) {
                            writeChannelMapping = false;
                        }
                    }
                    if(writeChannelMapping){
                        _imp->_channel_map.insert(make_pair(channel,chanName));
                    }
                    mask += channel;
                }

            }else {
                cout << "Cannot decode channel " << chan.name() << endl;
            }

        }

        const Imath::Box2i& datawin = _imp->_inputfile->header().dataWindow();
        const Imath::Box2i& dispwin = _imp->_inputfile->header().displayWindow();
        Imath::Box2i formatwin(dispwin);
        formatwin.min.x = 0;
        formatwin.min.y = 0;
        _imp->_dataOffset = 0;
        if (dispwin.min.x != 0) {
            // Shift both to get dispwindow over to 0,0.
            _imp->_dataOffset = -dispwin.min.x;
            formatwin.max.x = dispwin.max.x + _imp->_dataOffset;
        }
        formatwin.max.y = dispwin.max.y - dispwin.min.y;
        double aspect = _imp->_inputfile->header().pixelAspectRatio();
        Format imageFormat(0,0,formatwin.max.x + 1 ,formatwin.max.y + 1,"",aspect);
        Box2D rod;

        int left = datawin.min.x + _imp->_dataOffset;
        int bottom = dispwin.max.y - datawin.max.y;
        int right = datawin.max.x + _imp->_dataOffset;
        int top = dispwin.max.y - datawin.min.y;
        if (datawin.min.x != dispwin.min.x || datawin.max.x != dispwin.max.x ||
                datawin.min.y != dispwin.min.y || datawin.max.y != dispwin.max.y) {
            --left;
            --bottom;
            ++right;
            ++top;
            //            _readerInfo->setBlackOutside(true);
        }
        rod.set(left, bottom, right+1, top+1);

        setReaderInfo(imageFormat, rod, mask);
        return Powiter::StatOK;
    }
    catch (const std::exception& exc) {
        cout << "OpenEXR error: " << exc.what() << endl;
        delete _imp->_inputfile;
        _imp->_inputfile = 0;
        return Powiter::StatFailed;
    }

}

ExrDecoder::ExrDecoder(Reader* op)
: Decoder(op)
, _imp(new Implementation)
{
}

ExrDecoder::Implementation::Implementation()
: _inputfile(0)
, _dataOffset(0)
#ifdef __POWITER_WIN32__
, _inputStr(NULL)
, _inputStdStream(NULL)
#endif
{
}

void ExrDecoder::initializeColorSpace(){
    _lut=Powiter::Color::getLut(Powiter::Color::LUT_DEFAULT_FLOAT); // linear color-space for exr files
}

ExrDecoder::~ExrDecoder(){
#ifdef __POWITER_WIN32__
    delete _imp->_inputStr ;
    delete _imp->_inputStdStream ;
#endif
    delete _imp->_inputfile;
}

void ExrDecoder::render(SequenceTime /*time*/,Powiter::Row* out){
    const Powiter::ChannelSet& channels = out->channels();
    const Imath::Box2i& dispwin = _imp->_inputfile->header().displayWindow();
    const Imath::Box2i& datawin = _imp->_inputfile->header().dataWindow();
    int exrY = dispwin.max.y - out->y();
    int r = out->right();
    int x = out->left();

    const int X = std::max(x, datawin.min.x + _imp->_dataOffset);
    const int R = std::min(r, datawin.max.x + _imp->_dataOffset +1);

    // if we're below or above the data window
    if(exrY < datawin.min.y || exrY > datawin.max.y || R <= X) {
        out->eraseAll();
        return;
    }

    Imf_::FrameBuffer fbuf;
    foreachChannels(z, channels){
        // blacking out the extra padding we added
        float* dest = out->begin(z) - out->left();
        for (int xx = x; xx < X; xx++)
            dest[xx] = 0;
        for (int xx = R; xx < r; xx++)
            dest[xx] = 0;
        ChannelsMap::const_iterator found = _imp->_channel_map.find(z);
        if(found != _imp->_channel_map.end()){
            if(found->second != "BY" && found->second != "RY"){ // if it is NOT a subsampled buffer
                fbuf.insert(found->second.c_str(),Imf_::Slice(Imf_::FLOAT, (char*)(dest /*+_dataOffset*/),sizeof(float), 0));
            }else{
                fbuf.insert(found->second.c_str(),Imf_::Slice(Imf_::FLOAT, (char*)(dest /*+_dataOffset*/),sizeof(float), 0,2,2));
            }
        }else{
            //not found in the file, we zero it out
            // we're responsible for filling all channels requested by the row
            float fillValue = 0.f;
            if (z == Powiter::Channel_alpha) {
                fillValue = 1.f;
            }
            out->fill(z,fillValue);
        }
    }
    {
        QMutexLocker locker(&_imp->_lock);
        try {
            _imp->_inputfile->setFrameBuffer(fbuf);
            _imp->_inputfile->readPixels(exrY);
        } catch (const std::exception& exc) {
            cout << exc.what() <<  endl;
            return;
        }
    }

    //  colorspace conversion
    const float* alpha = out->begin(Powiter::Channel_alpha);
    foreachChannels(z, channels){
        float* to = out->begin(z) - out->left();
        const float* from = out->begin(z) - out->left();
        if(from){
            from_float(z,to + X ,from + X,alpha, R-X,1);
        }
    }
}
<|endoftext|>