<commit_before>#include <algorithm>
#define NOMINMAX // Para que nadie nos redefina min max
#include <sstream>

#include "game_window.h"
#include "../model/entity_factory.h"

#include "../parser_yaml/graphics_parser.h"
#include "../parser_yaml/ruleset_parser.h"

using namespace std;

bool GameWindow::sdlInitialized = false;

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

GameWindow::GameWindow(Game& owner, Player& player, GraphicsParser& graphicsParser, RulesetParser& rulesetParser) :
	AClient(owner, player),
	board(player.board),
	ancho_pantalla(graphicsParser.getPantalla().ancho), alto_pantalla(graphicsParser.getPantalla().alto),
	margen_pantalla(graphicsParser.getPantalla().margen_scroll), scroll_speed(graphicsParser.getPantalla().velocidad_scroll)
{
	GameWindow::initialize();
	window = SDL_CreateWindow(("Trabajo Práctico 7542 - " + owner.getBoard()->name + " - " + player.name).c_str(),
		SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
		ancho_pantalla, alto_pantalla,
		SDL_WINDOW_SHOWN);

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

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

	auto tp = graphicsParser.getPantalla();
	font = TTF_OpenFont(FUENTE_DEFAULT, graphicsParser.getPantalla().size_text);
	if (!font) {
		Logger::getInstance()->writeError("Error al abrir TTF");
	}
	inputText = "";
	minimap = std::make_shared<MiniMap>(*this, graphicsParser);
	isoview = std::make_shared<IsoView>(*this, rulesetParser);
	menu = std::make_shared<Menu>(*this, graphicsParser);
	playersList = std::make_shared<PlayersList>(*this, graphicsParser);
	chat = std::make_shared<Chat>(*this, graphicsParser);
	resourcesList = std::make_shared<ResourcesList>(*this, graphicsParser);
	commandMenu = std::make_shared<CommandMenu>(*this, graphicsParser);
	selectionMenu = std::make_shared<SelectionMenu>(*this, graphicsParser);
	sController = std::make_shared<SelectionController>(*this);
	if (player.entities().size() > 0)
		sController->setSelection(player.entities().at(0));
	focus();
	sweeping = false;
}

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

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

SDL_Renderer* GameWindow::getRenderer() {
	return renderer;
}

void GameWindow::render() {
	isoview->draw();
	if (isSweeping()) {
		r2 boardClick = isoview->screenToBoardPosition(mouseDown);
		Uint8 q = 255;
		SDL_SetRenderDrawColor(getRenderer(), q, q, q, q);
		isoview->drawRhombus(boardClick, boardMouse);
	}
	if (commandMenu->isVisibleWorker && commandMenu->showOptions && commandMenu->positioning) {
		auto w = dynamic_cast<Worker*>(sController->getSelection().front().get());
		r2 sizeBuilding = board.entityFactories[w->products[commandMenu->selectedOption].name]->size;
		if (player.getVisibility2(boardMouse) > INVISIBLE) {
			Uint8 q = 255;
			SDL_SetRenderDrawColor(getRenderer(), q, q, q, q);
			isoview->drawRhombus(boardMouse - sizeBuilding / 2, boardMouse + sizeBuilding / 2);
		}
	}
	commandMenu->draw();
	selectionMenu->draw();
	minimap->draw();
	chat->draw(inputText);
	playersList->draw();
	resourcesList->draw();

	SDL_RenderPresent(renderer);
	return;
}

void GameWindow::update(){
	sController->update();
	isoview->update();
	processInput();
	render();
	return;
}

void GameWindow::processInput(){
	SDL_GetMouseState(&mouse.x, &mouse.y);
	boardMouse = isoview->screenToBoardPosition(mouse);
	scroll();
	//	Procesar input del usuario
	while(SDL_PollEvent(EventHandler::getInstance()->getEvent())) {
		auto & e = *(EventHandler::getInstance()->getEvent());
		switch(e.type) {
			case SDL_QUIT:
				owner.exit();
				break;
			case SDL_TEXTINPUT:
				if(inputText.size() < MAX_LENGTH_MESSAGE && chat->typing) //Max largo del mensaje a ingresar.
					inputText += e.text.text;
				break;
			case SDL_KEYDOWN:
				Logger::getInstance()->writeInformation("Teclado");
				switch(e.key.keysym.sym) {
					case SDLK_c:
						if(!chat->typing && commandMenu->isVisibleWorker)
							commandMenu->showOptions = true;
						break;
					case SDLK_p:
						if(!chat->typing && commandMenu->isVisibleProducer)
							commandMenu->showOptions = true;
						break;
					case SDLK_ESCAPE:
						sController->clear();
						commandMenu->showOptions = false;
						commandMenu->positioning = false;
						break;
					case SDLK_q:
						if (commandMenu->showOptions) {
							if (commandMenu->positioning) {
								commandMenu->positioning = false;
							}
							else {
								commandMenu->showOptions = false;
							}
						}
						break;
					case SDLK_1: case SDLK_2: case SDLK_3: case SDLK_4: case SDLK_5:
					{
						size_t i = e.key.keysym.sym - SDLK_1;
						if (!chat->typing && commandMenu->showOptions) {
							if (commandMenu->isVisibleProducer) {
								auto p = dynamic_cast<Building*>(sController->getSelection().front().get());
								if (p) {
									if (i < p->products.size()) {
										board.pushCommand(std::make_shared<CreateCommand>(p->getId(),p->products[i].name));
										commandMenu->positioning = false;
										commandMenu->showOptions = false;
									}
								}
							}
							if (commandMenu->isVisibleWorker) {
								auto w = dynamic_cast<Worker*>(sController->getSelection().front().get());
								if (w) {
									if (i < w->products.size()) {
										commandMenu->positioning = true;
										commandMenu->selectedOption = i;
									}
								}
							}
						}
					}
						break;
					case SDLK_r:
						if(!chat->typing)
							owner.restart();
						break;
					case SDLK_s:
						for (auto e : sController->getSelection()) {
							if (!chat->typing && e->owner.name == player.name) {
								board.pushCommand(make_shared<StopCommand>(e->getId()));
							}
						}
						break;
					case SDLK_F2:
						chat->typing = !chat->typing;
						inputText = "";
						break;
					case SDLK_SPACE:
						if(!chat->typing)
							focus();
						break;
					case SDLK_BACKSPACE:
						if (chat->typing && inputText.length() > 0){
							inputText.pop_back();
						}
						break;
					case SDLK_RETURN:
						if (chat->typing) {
							chat->messages.push_back(inputText);
							inputText = "";
						}
						break;
				}
				break;
			case SDL_MOUSEBUTTONDOWN:
				if (EventHandler::getInstance()->getEvent()->button.button == SDL_BUTTON_LEFT) {
					if (commandMenu->isVisibleWorker && commandMenu->showOptions && commandMenu->positioning) {
						auto w = dynamic_cast<Worker*>(sController->getSelection().front().get());
						r2 sizeBuilding = board.entityFactories[w->products[commandMenu->selectedOption].name]->size;
						if (player.getVisibility(boardMouse) > INVISIBLE) {
							board.pushCommand(std::make_shared<BuildCommand>(w->getId(), boardMouse - sizeBuilding / 2, w->products[commandMenu->selectedOption].name));
							commandMenu->positioning = false;
						}
					}

					SDL_GetMouseState(&mouseDown.x, &mouseDown.y);
					sweeping = true;
				}
				break;
			case SDL_MOUSEBUTTONUP:
				ostringstream oss;
				oss << "Mouse en " << mouse.x << "," << mouse.y;
				// Conversion de coordenadas en pantalla a coordenadas mapa
				oss << "; mapa: " << boardMouse.x << "," << boardMouse.y;

				Logger::getInstance()->writeInformation(oss.str().c_str());
				if (EventHandler::getInstance()->getEvent()->button.button == SDL_BUTTON_LEFT) {
						setSelection();
						sweeping = false;
					}
				if( EventHandler::getInstance()->getEvent()->button.button == SDL_BUTTON_RIGHT) {
					Logger::getInstance()->writeInformation("Boton derecho");
					std::shared_ptr<Entity> obj = board.findEntity(rectangle(boardMouse,r2(0,0)));
					for (auto e : sController->getSelection()) {
						if ((player.getVisibility(boardMouse) == INVISIBLE || !obj) && e->owner.name == player.name) {
							if (!(SDL_GetModState()&KMOD_SHIFT)) {
								board.pushCommand(make_shared<StopCommand>(e->getId()));
							}
							board.pushCommand(make_shared<MoveCommand>(e->getId(), boardMouse));
						}
						else {
							if (e->owner.name == player.name && obj) {
								std::shared_ptr<Command> command = e->defaultCommand(*obj);
								if(command)
									board.pushCommand(command);
							}
						}
					}
				}
				break;
		}
	}
}

void GameWindow::scroll(){
	double ds = (double)scroll_speed * (double)(board.dt) / 1000.0; //deltascroll
	r2 df;

	if(mouse.x <= margen_pantalla) {
		auto dsi = interpolate(mouse.x, 0, margen_pantalla, ds, 0);
		df += {-dsi, dsi};
		Logger::getInstance()->writeInformation("Scrolleando hacia la izquierda");
	}
	if(mouse.x >= ancho_pantalla - margen_pantalla){
		auto dsi = interpolate(mouse.x, ancho_pantalla - margen_pantalla, ancho_pantalla, 0, ds);
		df += {dsi, -dsi};
		Logger::getInstance()->writeInformation("Scrolleando hacia la derecha");
	}
	if(mouse.y <= margen_pantalla) {
		auto dsi = interpolate(mouse.y, 0, margen_pantalla, ds, 0);
		df += {-dsi, -dsi};
		Logger::getInstance()->writeInformation("Scrolleando hacia arriba");
	}
	if(mouse.y >= alto_pantalla - margen_pantalla) {
		auto dsi = interpolate(mouse.y, alto_pantalla - margen_pantalla, alto_pantalla, 0, ds);
		df += {dsi, dsi};
		Logger::getInstance()->writeInformation("Scrolleando hacia abajo");
	}
	focus(focusPosition + df);
}

void GameWindow::focus(r2 newFocus) {
	focusPosition.x = clip(newFocus.x, 0, board.sizeX - 1);
	focusPosition.y = clip(newFocus.y, 0, board.sizeY - 1);
}

void GameWindow::focus() {
	if (sController->getSelection().size() > 0) {
		focus(sController->getSelection().at(0)->getPosition());
	}
}

r2 GameWindow::getFocus() {
	return focusPosition;
}

void GameWindow::setSelection() {
	r2 sweepStart = isoview->screenToBoardPosition(mouseDown);
	r2 sweepEnd = isoview->screenToBoardPosition(mouse);
	sController->setSelection(rectangle(sweepStart, sweepEnd - sweepStart));
}

std::string GameWindow::completeLine(std::string line, double width) {
	int txtAncho, txtAlto, espAncho, espAlto, esp;
	std::string result = line;
	TTF_SizeText(font, " ", &espAncho, &espAlto);
	TTF_SizeText(font, result.c_str(), &txtAncho, &txtAlto);
	esp = (int)floor((width - txtAncho) / espAncho);
	if (txtAncho < width) {
		if (esp * espAncho + txtAncho < width)
			esp++;
		if (esp > 0)result.insert(result.size(), esp, ' ');
	}
	return result;
}

SDL_Color GameWindow::getColor(int id) {
	Uint8 r = (id & 2) * 255;
	Uint8 g = (id & 1) * 255;
	Uint8 b = (id & 4) * 255;
	return{ r, g, b };
}

bool GameWindow::isSweeping() {
	return (sweeping && (mouse.x != mouseDown.x || mouse.y != mouseDown.y));
}

<commit_msg>Mantengo seleccion del worker que construye, (Ver= player.getVisibility)<commit_after>#include <algorithm>
#define NOMINMAX // Para que nadie nos redefina min max
#include <sstream>

#include "game_window.h"
#include "../model/entity_factory.h"

#include "../parser_yaml/graphics_parser.h"
#include "../parser_yaml/ruleset_parser.h"

using namespace std;

bool GameWindow::sdlInitialized = false;

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

GameWindow::GameWindow(Game& owner, Player& player, GraphicsParser& graphicsParser, RulesetParser& rulesetParser) :
	AClient(owner, player),
	board(player.board),
	ancho_pantalla(graphicsParser.getPantalla().ancho), alto_pantalla(graphicsParser.getPantalla().alto),
	margen_pantalla(graphicsParser.getPantalla().margen_scroll), scroll_speed(graphicsParser.getPantalla().velocidad_scroll)
{
	GameWindow::initialize();
	window = SDL_CreateWindow(("Trabajo Práctico 7542 - " + owner.getBoard()->name + " - " + player.name).c_str(),
		SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
		ancho_pantalla, alto_pantalla,
		SDL_WINDOW_SHOWN);

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

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

	auto tp = graphicsParser.getPantalla();
	font = TTF_OpenFont(FUENTE_DEFAULT, graphicsParser.getPantalla().size_text);
	if (!font) {
		Logger::getInstance()->writeError("Error al abrir TTF");
	}
	inputText = "";
	minimap = std::make_shared<MiniMap>(*this, graphicsParser);
	isoview = std::make_shared<IsoView>(*this, rulesetParser);
	menu = std::make_shared<Menu>(*this, graphicsParser);
	playersList = std::make_shared<PlayersList>(*this, graphicsParser);
	chat = std::make_shared<Chat>(*this, graphicsParser);
	resourcesList = std::make_shared<ResourcesList>(*this, graphicsParser);
	commandMenu = std::make_shared<CommandMenu>(*this, graphicsParser);
	selectionMenu = std::make_shared<SelectionMenu>(*this, graphicsParser);
	sController = std::make_shared<SelectionController>(*this);
	if (player.entities().size() > 0)
		sController->setSelection(player.entities().at(0));
	focus();
	sweeping = false;
}

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

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

SDL_Renderer* GameWindow::getRenderer() {
	return renderer;
}

void GameWindow::render() {
	isoview->draw();
	if (isSweeping()) {
		r2 boardClick = isoview->screenToBoardPosition(mouseDown);
		Uint8 q = 255;
		SDL_SetRenderDrawColor(getRenderer(), q, q, q, q);
		isoview->drawRhombus(boardClick, boardMouse);
	}
	if (commandMenu->isVisibleWorker && commandMenu->showOptions && commandMenu->positioning) {
		auto w = dynamic_cast<Worker*>(sController->getSelection().front().get());
		r2 sizeBuilding = board.entityFactories[w->products[commandMenu->selectedOption].name]->size;
		if (player.getVisibility2(boardMouse) > INVISIBLE) { //TODO: Ver
			Uint8 q = 255;
			SDL_SetRenderDrawColor(getRenderer(), q, q, q, q);
			isoview->drawRhombus(boardMouse - sizeBuilding / 2, boardMouse + sizeBuilding / 2);
		}
	}
	commandMenu->draw();
	selectionMenu->draw();
	minimap->draw();
	chat->draw(inputText);
	playersList->draw();
	resourcesList->draw();

	SDL_RenderPresent(renderer);
	return;
}

void GameWindow::update(){
	sController->update();
	isoview->update();
	processInput();
	render();
	return;
}

void GameWindow::processInput(){
	SDL_GetMouseState(&mouse.x, &mouse.y);
	boardMouse = isoview->screenToBoardPosition(mouse);
	scroll();
	//	Procesar input del usuario
	while(SDL_PollEvent(EventHandler::getInstance()->getEvent())) {
		auto & e = *(EventHandler::getInstance()->getEvent());
		switch(e.type) {
			case SDL_QUIT:
				owner.exit();
				break;
			case SDL_TEXTINPUT:
				if(inputText.size() < MAX_LENGTH_MESSAGE && chat->typing) //Max largo del mensaje a ingresar.
					inputText += e.text.text;
				break;
			case SDL_KEYDOWN:
				Logger::getInstance()->writeInformation("Teclado");
				switch(e.key.keysym.sym) {
					case SDLK_c:
						if(!chat->typing && commandMenu->isVisibleWorker)
							commandMenu->showOptions = true;
						break;
					case SDLK_p:
						if(!chat->typing && commandMenu->isVisibleProducer)
							commandMenu->showOptions = true;
						break;
					case SDLK_ESCAPE:
						sController->clear();
						commandMenu->showOptions = false;
						commandMenu->positioning = false;
						break;
					case SDLK_q:
						if (commandMenu->showOptions) {
							if (commandMenu->positioning) {
								commandMenu->positioning = false;
							}
							else {
								commandMenu->showOptions = false;
							}
						}
						break;
					case SDLK_1: case SDLK_2: case SDLK_3: case SDLK_4: case SDLK_5:
					{
						size_t i = e.key.keysym.sym - SDLK_1;
						if (!chat->typing && commandMenu->showOptions) {
							if (commandMenu->isVisibleProducer) {
								auto p = dynamic_cast<Building*>(sController->getSelection().front().get());
								if (p) {
									if (i < p->products.size()) {
										board.pushCommand(std::make_shared<CreateCommand>(p->getId(),p->products[i].name));
										commandMenu->positioning = false;
										commandMenu->showOptions = false;
									}
								}
							}
							if (commandMenu->isVisibleWorker) {
								auto w = dynamic_cast<Worker*>(sController->getSelection().front().get());
								if (w) {
									if (i < w->products.size()) {
										commandMenu->positioning = true;
										commandMenu->selectedOption = i;
									}
								}
							}
						}
					}
						break;
					case SDLK_r:
						if(!chat->typing)
							owner.restart();
						break;
					case SDLK_s:
						for (auto e : sController->getSelection()) {
							if (!chat->typing && e->owner.name == player.name) {
								board.pushCommand(make_shared<StopCommand>(e->getId()));
							}
						}
						break;
					case SDLK_F2:
						chat->typing = !chat->typing;
						inputText = "";
						break;
					case SDLK_SPACE:
						if(!chat->typing)
							focus();
						break;
					case SDLK_BACKSPACE:
						if (chat->typing && inputText.length() > 0){
							inputText.pop_back();
						}
						break;
					case SDLK_RETURN:
						if (chat->typing) {
							chat->messages.push_back(inputText);
							inputText = "";
						}
						break;
				}
				break;
			case SDL_MOUSEBUTTONDOWN:
				if (EventHandler::getInstance()->getEvent()->button.button == SDL_BUTTON_LEFT) {
					if (commandMenu->isVisibleWorker && commandMenu->showOptions && commandMenu->positioning) {
						auto w = dynamic_cast<Worker*>(sController->getSelection().front().get());
						r2 sizeBuilding = board.entityFactories[w->products[commandMenu->selectedOption].name]->size;
						if (player.getVisibility2(boardMouse) > INVISIBLE) {//TODO: Ver
							board.pushCommand(std::make_shared<BuildCommand>(w->getId(), boardMouse - sizeBuilding / 2, w->products[commandMenu->selectedOption].name));
							commandMenu->positioning = false;
						}
					}
					else {
						SDL_GetMouseState(&mouseDown.x, &mouseDown.y);
						sweeping = true;
					}
				}
				break;
			case SDL_MOUSEBUTTONUP:
				ostringstream oss;
				oss << "Mouse en " << mouse.x << "," << mouse.y;
				// Conversion de coordenadas en pantalla a coordenadas mapa
				oss << "; mapa: " << boardMouse.x << "," << boardMouse.y;

				Logger::getInstance()->writeInformation(oss.str().c_str());
				if (EventHandler::getInstance()->getEvent()->button.button == SDL_BUTTON_LEFT) {
					if (!(commandMenu->isVisibleWorker && commandMenu->showOptions && commandMenu->positioning)) {
						setSelection();
						sweeping = false;
					}
				}
				if( EventHandler::getInstance()->getEvent()->button.button == SDL_BUTTON_RIGHT) {
					Logger::getInstance()->writeInformation("Boton derecho");
					std::shared_ptr<Entity> obj = board.findEntity(rectangle(boardMouse,r2(0,0)));
					for (auto e : sController->getSelection()) {
						if ((player.getVisibility2(boardMouse) == INVISIBLE || !obj) && e->owner.name == player.name) {//TODO: Ver
							if (!(SDL_GetModState()&KMOD_SHIFT)) {
								board.pushCommand(make_shared<StopCommand>(e->getId()));
							}
							board.pushCommand(make_shared<MoveCommand>(e->getId(), boardMouse));
						}
						else {
							if (e->owner.name == player.name && obj) {
								std::shared_ptr<Command> command = e->defaultCommand(*obj);
								if(command)
									board.pushCommand(command);
							}
						}
					}
				}
				break;
		}
	}
}

void GameWindow::scroll(){
	double ds = (double)scroll_speed * (double)(board.dt) / 1000.0; //deltascroll
	r2 df;

	if(mouse.x <= margen_pantalla) {
		auto dsi = interpolate(mouse.x, 0, margen_pantalla, ds, 0);
		df += {-dsi, dsi};
		Logger::getInstance()->writeInformation("Scrolleando hacia la izquierda");
	}
	if(mouse.x >= ancho_pantalla - margen_pantalla){
		auto dsi = interpolate(mouse.x, ancho_pantalla - margen_pantalla, ancho_pantalla, 0, ds);
		df += {dsi, -dsi};
		Logger::getInstance()->writeInformation("Scrolleando hacia la derecha");
	}
	if(mouse.y <= margen_pantalla) {
		auto dsi = interpolate(mouse.y, 0, margen_pantalla, ds, 0);
		df += {-dsi, -dsi};
		Logger::getInstance()->writeInformation("Scrolleando hacia arriba");
	}
	if(mouse.y >= alto_pantalla - margen_pantalla) {
		auto dsi = interpolate(mouse.y, alto_pantalla - margen_pantalla, alto_pantalla, 0, ds);
		df += {dsi, dsi};
		Logger::getInstance()->writeInformation("Scrolleando hacia abajo");
	}
	focus(focusPosition + df);
}

void GameWindow::focus(r2 newFocus) {
	focusPosition.x = clip(newFocus.x, 0, board.sizeX - 1);
	focusPosition.y = clip(newFocus.y, 0, board.sizeY - 1);
}

void GameWindow::focus() {
	if (sController->getSelection().size() > 0) {
		focus(sController->getSelection().at(0)->getPosition());
	}
}

r2 GameWindow::getFocus() {
	return focusPosition;
}

void GameWindow::setSelection() {
	r2 sweepStart = isoview->screenToBoardPosition(mouseDown);
	r2 sweepEnd = isoview->screenToBoardPosition(mouse);
	sController->setSelection(rectangle(sweepStart, sweepEnd - sweepStart));
}

std::string GameWindow::completeLine(std::string line, double width) {
	int txtAncho, txtAlto, espAncho, espAlto, esp;
	std::string result = line;
	TTF_SizeText(font, " ", &espAncho, &espAlto);
	TTF_SizeText(font, result.c_str(), &txtAncho, &txtAlto);
	esp = (int)floor((width - txtAncho) / espAncho);
	if (txtAncho < width) {
		if (esp * espAncho + txtAncho < width)
			esp++;
		if (esp > 0)result.insert(result.size(), esp, ' ');
	}
	return result;
}

SDL_Color GameWindow::getColor(int id) {
	Uint8 r = (id & 2) * 255;
	Uint8 g = (id & 1) * 255;
	Uint8 b = (id & 4) * 255;
	return{ r, g, b };
}

bool GameWindow::isSweeping() {
	return (sweeping && (mouse.x != mouseDown.x || mouse.y != mouseDown.y));
}

<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2012 Fernando José Iglesias García
 * Copyright (C) 2012 Fernando José Iglesias García
 */

#include <shogun/features/DotFeatures.h>
#include <shogun/mathematics/Math.h>
#include <shogun/structure/MulticlassModel.h>
#include <shogun/structure/MulticlassSOLabels.h>

using namespace shogun;

CMulticlassModel::CMulticlassModel()
: CStructuredModel()
{
	init();
}

	CMulticlassModel::CMulticlassModel(CFeatures* features, CStructuredLabels* labels)
: CStructuredModel(features, labels)
{
	init();
}

CMulticlassModel::~CMulticlassModel()
{
}

int32_t CMulticlassModel::get_dim() const
{
	// TODO make the casts safe!
	int32_t num_classes = ((CMulticlassSOLabels*) m_labels)->get_num_classes();
	int32_t feats_dim   = ((CDotFeatures*) m_features)->get_dim_feature_space();

	return feats_dim*num_classes;
}

SGVector< float64_t > CMulticlassModel::get_joint_feature_vector(int32_t feat_idx, CStructuredData* y)
{
	SGVector< float64_t > psi( get_dim() );
	psi.zero();

	SGVector< float64_t > x = ((CDotFeatures*) m_features)->
		get_computed_dot_feature_vector(feat_idx);
	CRealNumber* r = CRealNumber::obtain_from_generic(y);
	ASSERT(r != NULL)
	float64_t label_value = r->value;

	for ( index_t i = 0, j = label_value*x.vlen ; i < x.vlen ; ++i, ++j )
		psi[j] = x[i];

	return psi;
}

CResultSet* CMulticlassModel::argmax(
		SGVector< float64_t > w,
		int32_t feat_idx,
		bool const training)
{
	CDotFeatures* df = (CDotFeatures*) m_features;
	int32_t feats_dim   = df->get_dim_feature_space();

	if ( training )
	{
		CMulticlassSOLabels* ml = (CMulticlassSOLabels*) m_labels;
		m_num_classes = ml->get_num_classes();
	}
	else
	{
		REQUIRE(m_num_classes > 0, "The model needs to be trained before "
				"using it for prediction\n");
	}

	ASSERT(feats_dim*m_num_classes == w.vlen);

	// Find the class that gives the maximum score

	float64_t score = 0, ypred = 0;
	float64_t max_score = -CMath::INFTY;

	for ( int32_t c = 0 ; c < m_num_classes ; ++c )
	{
		score = df->dense_dot(feat_idx, w.vector+c*feats_dim, feats_dim);
		if ( training )
			score += delta_loss(feat_idx, c);

		if ( score > max_score )
		{
			max_score = score;
			ypred = c;
		}
	}

	// Build the CResultSet object to return
	CResultSet* ret = new CResultSet();
	CRealNumber* y  = new CRealNumber(ypred);
	SG_REF(ret);
	SG_REF(y);

	ret->psi_pred = get_joint_feature_vector(feat_idx, y);
	ret->score    = max_score;
	ret->argmax   = y;
	if ( training )
	{
		ret->psi_truth = CStructuredModel::get_joint_feature_vector(feat_idx, feat_idx);
		ret->delta     = CStructuredModel::delta_loss(feat_idx, y);
	}

	return ret;
}

float64_t CMulticlassModel::delta_loss(CStructuredData* y1, CStructuredData* y2)
{
	CRealNumber* rn1 = CRealNumber::obtain_from_generic(y1);
	CRealNumber* rn2 = CRealNumber::obtain_from_generic(y2);
	ASSERT(rn1 != NULL);
	ASSERT(rn2 != NULL);

	return delta_loss(rn1->value, rn2->value);
}

float64_t CMulticlassModel::delta_loss(int32_t y1_idx, float64_t y2)
{
	REQUIRE(y1_idx >= 0 || y1_idx < m_labels->get_num_labels(),
			"The label index must be inside [0, num_labels-1]\n");

	CRealNumber* rn1 = CRealNumber::obtain_from_generic(m_labels->get_label(y1_idx));
	float64_t ret = delta_loss(rn1->value, y2);
	SG_UNREF(rn1);

	return ret;
}

float64_t CMulticlassModel::delta_loss(float64_t y1, float64_t y2)
{
	return (y1 == y2) ? 0 : 1;
}

void CMulticlassModel::init_opt(
		SGMatrix< float64_t > & A,
		SGVector< float64_t > a,
		SGMatrix< float64_t > B,
		SGVector< float64_t > & b,
		SGVector< float64_t > lb,
		SGVector< float64_t > ub,
		SGMatrix< float64_t > & C)
{
	C = SGMatrix< float64_t >::create_identity_matrix(get_dim(), 1);
}

void CMulticlassModel::init()
{
	SG_ADD(&m_num_classes, "m_num_classes", "The number of classes",
			MS_NOT_AVAILABLE);

	m_num_classes = 0;
}

float64_t CMulticlassModel::risk(float64_t* subgrad, float64_t* W, TMultipleCPinfo* info)
{
	CDotFeatures* X=(CDotFeatures*)m_features;
	CMulticlassSOLabels* y=(CMulticlassSOLabels*)m_labels;
	m_num_classes = y->get_num_classes();
	uint32_t from, to;

	if (info)
	{
		from=info->_from;
		to=(info->N == 0) ? X->get_num_vectors() : from+info->N;
	} else {
		from=0;
		to=X->get_num_vectors();
	}

	uint32_t num_classes=y->get_num_classes();
	uint32_t feats_dim=X->get_dim_feature_space();
	const uint32_t w_dim=get_dim();

	float64_t R=0.0;
	for (uint32_t i=0; i<w_dim; i++)
		subgrad[i] = 0;

	float64_t Rtmp=0.0;
	float64_t Rmax=0.0;
	float64_t loss=0.0;
	uint32_t yhat=0;
	uint32_t GT=0;
	CRealNumber* GT_rn=NULL;

	/* loop through examples */
	for(uint32_t i=from; i<to; ++i)
	{
		Rmax=-CMath::INFTY;
		GT_rn=CRealNumber::obtain_from_generic(y->get_label(i));
		GT=(uint32_t)GT_rn->value;

		for (uint32_t c = 0; c < num_classes; ++c)
		{
			loss=(c == GT) ? 0.0 : 1.0;
			Rtmp=loss+X->dense_dot(i, W+c*feats_dim, feats_dim)
				-X->dense_dot(i, W+GT*feats_dim, feats_dim);

			if (Rtmp > Rmax)
			{
				Rmax=Rtmp;
				yhat=c;
			}
		}
		R += Rmax;

		X->add_to_dense_vec(1.0, i, subgrad+yhat*feats_dim, feats_dim);
		X->add_to_dense_vec(-1.0, i, subgrad+GT*feats_dim, feats_dim);

		SG_UNREF(GT_rn);
	}

	return R;
}

<commit_msg>~ MulticlassModel::argmax returns the true score instead of score+delta<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2012 Fernando José Iglesias García
 * Copyright (C) 2012 Fernando José Iglesias García
 */

#include <shogun/features/DotFeatures.h>
#include <shogun/mathematics/Math.h>
#include <shogun/structure/MulticlassModel.h>
#include <shogun/structure/MulticlassSOLabels.h>

using namespace shogun;

CMulticlassModel::CMulticlassModel()
: CStructuredModel()
{
	init();
}

	CMulticlassModel::CMulticlassModel(CFeatures* features, CStructuredLabels* labels)
: CStructuredModel(features, labels)
{
	init();
}

CMulticlassModel::~CMulticlassModel()
{
}

int32_t CMulticlassModel::get_dim() const
{
	// TODO make the casts safe!
	int32_t num_classes = ((CMulticlassSOLabels*) m_labels)->get_num_classes();
	int32_t feats_dim   = ((CDotFeatures*) m_features)->get_dim_feature_space();

	return feats_dim*num_classes;
}

SGVector< float64_t > CMulticlassModel::get_joint_feature_vector(int32_t feat_idx, CStructuredData* y)
{
	SGVector< float64_t > psi( get_dim() );
	psi.zero();

	SGVector< float64_t > x = ((CDotFeatures*) m_features)->
		get_computed_dot_feature_vector(feat_idx);
	CRealNumber* r = CRealNumber::obtain_from_generic(y);
	ASSERT(r != NULL)
	float64_t label_value = r->value;

	for ( index_t i = 0, j = label_value*x.vlen ; i < x.vlen ; ++i, ++j )
		psi[j] = x[i];

	return psi;
}

CResultSet* CMulticlassModel::argmax(
		SGVector< float64_t > w,
		int32_t feat_idx,
		bool const training)
{
	CDotFeatures* df = (CDotFeatures*) m_features;
	int32_t feats_dim   = df->get_dim_feature_space();

	if ( training )
	{
		CMulticlassSOLabels* ml = (CMulticlassSOLabels*) m_labels;
		m_num_classes = ml->get_num_classes();
	}
	else
	{
		REQUIRE(m_num_classes > 0, "The model needs to be trained before "
				"using it for prediction\n");
	}

	ASSERT(feats_dim*m_num_classes == w.vlen);

	// Find the class that gives the maximum score

	float64_t score = 0, ypred = 0;
	float64_t max_score = -CMath::INFTY;

	for ( int32_t c = 0 ; c < m_num_classes ; ++c )
	{
		score = df->dense_dot(feat_idx, w.vector+c*feats_dim, feats_dim);
		if ( training )
			score += delta_loss(feat_idx, c);

		if ( score > max_score )
		{
			max_score = score;
			ypred = c;
		}
	}

	// Build the CResultSet object to return
	CResultSet* ret = new CResultSet();
	CRealNumber* y  = new CRealNumber(ypred);
	SG_REF(ret);
	SG_REF(y);

	ret->psi_pred = get_joint_feature_vector(feat_idx, y);
	ret->score    = max_score;
	ret->argmax   = y;
	if ( training )
	{
		ret->psi_truth = CStructuredModel::get_joint_feature_vector(feat_idx, feat_idx);
		ret->delta     = CStructuredModel::delta_loss(feat_idx, y);
		ret->score    -= ret->delta;
	}

	return ret;
}

float64_t CMulticlassModel::delta_loss(CStructuredData* y1, CStructuredData* y2)
{
	CRealNumber* rn1 = CRealNumber::obtain_from_generic(y1);
	CRealNumber* rn2 = CRealNumber::obtain_from_generic(y2);
	ASSERT(rn1 != NULL);
	ASSERT(rn2 != NULL);

	return delta_loss(rn1->value, rn2->value);
}

float64_t CMulticlassModel::delta_loss(int32_t y1_idx, float64_t y2)
{
	REQUIRE(y1_idx >= 0 || y1_idx < m_labels->get_num_labels(),
			"The label index must be inside [0, num_labels-1]\n");

	CRealNumber* rn1 = CRealNumber::obtain_from_generic(m_labels->get_label(y1_idx));
	float64_t ret = delta_loss(rn1->value, y2);
	SG_UNREF(rn1);

	return ret;
}

float64_t CMulticlassModel::delta_loss(float64_t y1, float64_t y2)
{
	return (y1 == y2) ? 0 : 1;
}

void CMulticlassModel::init_opt(
		SGMatrix< float64_t > & A,
		SGVector< float64_t > a,
		SGMatrix< float64_t > B,
		SGVector< float64_t > & b,
		SGVector< float64_t > lb,
		SGVector< float64_t > ub,
		SGMatrix< float64_t > & C)
{
	C = SGMatrix< float64_t >::create_identity_matrix(get_dim(), 1);
}

void CMulticlassModel::init()
{
	SG_ADD(&m_num_classes, "m_num_classes", "The number of classes",
			MS_NOT_AVAILABLE);

	m_num_classes = 0;
}

float64_t CMulticlassModel::risk(float64_t* subgrad, float64_t* W, TMultipleCPinfo* info)
{
	CDotFeatures* X=(CDotFeatures*)m_features;
	CMulticlassSOLabels* y=(CMulticlassSOLabels*)m_labels;
	m_num_classes = y->get_num_classes();
	uint32_t from, to;

	if (info)
	{
		from=info->_from;
		to=(info->N == 0) ? X->get_num_vectors() : from+info->N;
	} else {
		from=0;
		to=X->get_num_vectors();
	}

	uint32_t num_classes=y->get_num_classes();
	uint32_t feats_dim=X->get_dim_feature_space();
	const uint32_t w_dim=get_dim();

	float64_t R=0.0;
	for (uint32_t i=0; i<w_dim; i++)
		subgrad[i] = 0;

	float64_t Rtmp=0.0;
	float64_t Rmax=0.0;
	float64_t loss=0.0;
	uint32_t yhat=0;
	uint32_t GT=0;
	CRealNumber* GT_rn=NULL;

	/* loop through examples */
	for(uint32_t i=from; i<to; ++i)
	{
		Rmax=-CMath::INFTY;
		GT_rn=CRealNumber::obtain_from_generic(y->get_label(i));
		GT=(uint32_t)GT_rn->value;

		for (uint32_t c = 0; c < num_classes; ++c)
		{
			loss=(c == GT) ? 0.0 : 1.0;
			Rtmp=loss+X->dense_dot(i, W+c*feats_dim, feats_dim)
				-X->dense_dot(i, W+GT*feats_dim, feats_dim);

			if (Rtmp > Rmax)
			{
				Rmax=Rtmp;
				yhat=c;
			}
		}
		R += Rmax;

		X->add_to_dense_vec(1.0, i, subgrad+yhat*feats_dim, feats_dim);
		X->add_to_dense_vec(-1.0, i, subgrad+GT*feats_dim, feats_dim);

		SG_UNREF(GT_rn);
	}

	return R;
}

<|endoftext|>


<commit_before>// Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html
#include "cairo-inlined/cairo.h"
#include "cairocontext.hh"

namespace Rapicorn {

/* --- Painter --- */
CairoContext::CairoContext() :
  cr (NULL)
{}
CairoContext::~CairoContext()
{
  set_cairo (NULL);
}

void
CairoContext::set_cairo (cairo_t *n_cr)
{
  if (n_cr)
    n_cr = cairo_reference (n_cr);
  if (cr)
    cairo_destroy (cr);
  cr = n_cr;
}

void
CairoContext::save ()
{
  cairo_save (cr);
}

void
CairoContext::restore ()
{
  cairo_restore (cr);
}

void
CairoContext::set_tolerance (double tolerance)
{
  cairo_set_tolerance (cr, tolerance);
}

static cairo_antialias_t
convert_antialias (CairoContext::Antialias antialias)
{
  switch (antialias)
    {
    default:
    case CairoContext::CAIRO_ANTIALIAS_DEFAULT:       return CAIRO_ANTIALIAS_DEFAULT;
    case CairoContext::CAIRO_ANTIALIAS_NONE:          return CAIRO_ANTIALIAS_NONE;
    case CairoContext::CAIRO_ANTIALIAS_GRAY:          return CAIRO_ANTIALIAS_GRAY;
    case CairoContext::CAIRO_ANTIALIAS_SUBPIXEL:      return CAIRO_ANTIALIAS_SUBPIXEL;
    }
}

void
CairoContext::set_antialias (Antialias antialias)
{
  cairo_set_antialias (cr, convert_antialias (antialias));
}

static cairo_fill_rule_t
convert_fill_rule (CairoContext::FillRule fill_rule)
{
  switch (fill_rule)
    {
    default:
    case CairoContext::CAIRO_FILL_RULE_WINDING:         return CAIRO_FILL_RULE_WINDING;
    case CairoContext::CAIRO_FILL_RULE_EVEN_ODD:        return CAIRO_FILL_RULE_EVEN_ODD;
    }
}

void
CairoContext::set_fill_rule (FillRule  fill_rule)
{
  cairo_set_fill_rule (cr, convert_fill_rule (fill_rule));
}

void
CairoContext::set_line_width (double    width)
{
  cairo_set_line_width (cr, width);
}

static cairo_line_cap_t
convert_line_cap (CairoContext::LineCap line_cap)
{
  switch (line_cap)
    {
    default:
    case CairoContext::CAIRO_LINE_CAP_BUTT:     return CAIRO_LINE_CAP_BUTT;
    case CairoContext::CAIRO_LINE_CAP_ROUND:    return CAIRO_LINE_CAP_ROUND;
    case CairoContext::CAIRO_LINE_CAP_SQUARE:   return CAIRO_LINE_CAP_SQUARE;
    }
}

void
CairoContext::set_line_cap (LineCap line_cap)
{
  cairo_set_line_cap (cr, convert_line_cap (line_cap));
}

static cairo_line_join_t
convert_line_join (CairoContext::LineJoin line_join)
{
  switch (line_join)
    {
    default:
    case CairoContext::CAIRO_LINE_JOIN_MITER:   return CAIRO_LINE_JOIN_MITER;
    case CairoContext::CAIRO_LINE_JOIN_ROUND:   return CAIRO_LINE_JOIN_ROUND;
    case CairoContext::CAIRO_LINE_JOIN_BEVEL:   return CAIRO_LINE_JOIN_BEVEL;
    }
}

void
CairoContext::set_line_join (LineJoin line_join)
{
  cairo_set_line_join (cr, convert_line_join (line_join));
}

void
CairoContext::set_miter_limit (double limit)
{
  cairo_set_miter_limit (cr, limit);
}

void
CairoContext::set_dash (double   *dashes,
                        int       num_dashes,
                        double    offset)
{
  cairo_set_dash (cr, dashes, num_dashes, offset);
}

void
CairoContext::set_source_color (Color c)
{
  cairo_set_source_rgba (cr, c.red() / 255., c.green() / 255., c.blue() / 255., c.alpha() / 255.);
}

void
CairoContext::translate (double x, double y)
{
  cairo_translate (cr, x, y);
}

void CairoContext::new_path ()
{
  cairo_new_path (cr);
}

void
CairoContext::move_to (double x,  double y)
{
  cairo_move_to (cr, x, y);
}

void
CairoContext::line_to (double x,  double y)
{
  cairo_line_to (cr, x, y);
}

void
CairoContext::rel_move_to (double x,  double y)
{
  cairo_rel_move_to (cr, x, y);
}

void
CairoContext::rel_line_to (double x,  double y)
{
  cairo_rel_line_to (cr, x, y);
}

void
CairoContext::rectangle (double x, double y, double width, double height)
{
  cairo_rectangle (cr, x, y, width, height);
}

void
CairoContext::curve_to (double x1, double y1,
                        double x2, double y2,
                        double x3, double y3)
{
  cairo_curve_to (cr, x1, y1, x2, y2, x3, y3);
}

void
CairoContext::arc (double xc, double yc, double radius,
                   double angle1, double angle2)
{
  cairo_arc (cr, xc, yc, radius, angle1, angle2);
}

void
CairoContext::arc_negative (double xc, double yc, double radius,
                            double angle1, double angle2)
{
  cairo_arc_negative (cr, xc, yc, radius, angle1, angle2);
}

void
CairoContext::close_path ()
{
  cairo_close_path (cr);
}

void
CairoContext::paint ()
{
  cairo_paint (cr);
}

void
CairoContext::stroke ()
{
  cairo_stroke (cr);
}

void
CairoContext::stroke_preserve ()
{
  cairo_stroke_preserve (cr);
}

void
CairoContext::fill ()
{
  cairo_fill (cr);
}

void
CairoContext::fill_preserve ()
{
  cairo_fill_preserve (cr);
}

CairoContext*
CairoContext::cairo_context_from_plane (Plane &plane)
{
  uint32 *buffer = plane.peek (0, 0);
  cairo_surface_t *cs = cairo_image_surface_create_for_data ((uint8*) buffer, CAIRO_FORMAT_ARGB32, plane.width(), plane.height(), plane.pixstride());
  cairo_t *cr = cairo_create (cs);
  cairo_surface_destroy (cs);
  cairo_translate (cr, -plane.xstart(), -plane.ystart());
  CairoContext *cc = new CairoContext;
  cc->set_cairo (cr);
  return cc;
}

CairoPainter::CairoPainter (Plane &plane) :
  Painter (plane),
  cc (*CairoContext::cairo_context_from_plane (m_plane))
{}

CairoPainter::~CairoPainter()
{
  delete &cc;
}

void
CairoPainter::draw_arrow (double x, double y, double width, double height, Color c, double angle)
{
  double mx = x + width / 2, my = y + height / 2;
  double angle0 = (angle + 0) * PI / 180., angle1 = (angle + 120) * PI / 180., angle2 = (angle - 120) * PI / 180.;
  cc.set_source_color (c);
  /* east point */
  cc.move_to (mx + cos (angle0) * width / 2, my + sin (angle0) * height / 2);
  /* north-west point */
  cc.line_to (mx + cos (angle1) * width / 2, my + sin (angle1) * height / 2);
  /* south-west point */
  cc.line_to (mx + cos (angle2) * width / 2, my + sin (angle2) * height / 2);
  //cc.move_to (x,              y);
  //cc.line_to (x + width,      y);
  //cc.line_to (x + width / 2., y + height);
  cc.close_path();
  cc.fill();
}

void
CairoPainter::draw_dir_arrow (double x, double y, double width, double height, Color c, DirType dir)
{
  double xhalf = width / 2., yhalf = height / 2.;
  cc.set_source_color (c);
  switch (dir)
    {
    default:
    case DIR_RIGHT:
      cc.move_to (x + width, y + yhalf);
      cc.line_to (x,         y + height);
      cc.line_to (x,         y);
      break;
    case DIR_UP:
      cc.move_to (x,         y);
      cc.line_to (x + width, y);
      cc.line_to (x + xhalf, y + height);
      break;
    case DIR_LEFT:
      cc.move_to (x,         y + yhalf);
      cc.line_to (x + width, y);
      cc.line_to (x + width, y + height);
      break;
    case DIR_DOWN:
      cc.move_to (x,         y + height);
      cc.line_to (x + xhalf, y);
      cc.line_to (x + width, y + height);
      break;
    }
  cc.close_path();
  cc.fill();
}

void
CairoPainter::draw_dot (double x, double y, double width, double height, Color c1, Color c2, FrameType frame)
{
  cc.rectangle (x, y, width, height);
  cc.set_source_color (c1);
  cc.fill();
}

} // Rapicorn
<commit_msg>UI: cairocontext member renames<commit_after>// Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html
#include "cairo-inlined/cairo.h"
#include "cairocontext.hh"

namespace Rapicorn {

/* --- Painter --- */
CairoContext::CairoContext() :
  cr (NULL)
{}
CairoContext::~CairoContext()
{
  set_cairo (NULL);
}

void
CairoContext::set_cairo (cairo_t *n_cr)
{
  if (n_cr)
    n_cr = cairo_reference (n_cr);
  if (cr)
    cairo_destroy (cr);
  cr = n_cr;
}

void
CairoContext::save ()
{
  cairo_save (cr);
}

void
CairoContext::restore ()
{
  cairo_restore (cr);
}

void
CairoContext::set_tolerance (double tolerance)
{
  cairo_set_tolerance (cr, tolerance);
}

static cairo_antialias_t
convert_antialias (CairoContext::Antialias antialias)
{
  switch (antialias)
    {
    default:
    case CairoContext::CAIRO_ANTIALIAS_DEFAULT:       return CAIRO_ANTIALIAS_DEFAULT;
    case CairoContext::CAIRO_ANTIALIAS_NONE:          return CAIRO_ANTIALIAS_NONE;
    case CairoContext::CAIRO_ANTIALIAS_GRAY:          return CAIRO_ANTIALIAS_GRAY;
    case CairoContext::CAIRO_ANTIALIAS_SUBPIXEL:      return CAIRO_ANTIALIAS_SUBPIXEL;
    }
}

void
CairoContext::set_antialias (Antialias antialias)
{
  cairo_set_antialias (cr, convert_antialias (antialias));
}

static cairo_fill_rule_t
convert_fill_rule (CairoContext::FillRule fill_rule)
{
  switch (fill_rule)
    {
    default:
    case CairoContext::CAIRO_FILL_RULE_WINDING:         return CAIRO_FILL_RULE_WINDING;
    case CairoContext::CAIRO_FILL_RULE_EVEN_ODD:        return CAIRO_FILL_RULE_EVEN_ODD;
    }
}

void
CairoContext::set_fill_rule (FillRule  fill_rule)
{
  cairo_set_fill_rule (cr, convert_fill_rule (fill_rule));
}

void
CairoContext::set_line_width (double    width)
{
  cairo_set_line_width (cr, width);
}

static cairo_line_cap_t
convert_line_cap (CairoContext::LineCap line_cap)
{
  switch (line_cap)
    {
    default:
    case CairoContext::CAIRO_LINE_CAP_BUTT:     return CAIRO_LINE_CAP_BUTT;
    case CairoContext::CAIRO_LINE_CAP_ROUND:    return CAIRO_LINE_CAP_ROUND;
    case CairoContext::CAIRO_LINE_CAP_SQUARE:   return CAIRO_LINE_CAP_SQUARE;
    }
}

void
CairoContext::set_line_cap (LineCap line_cap)
{
  cairo_set_line_cap (cr, convert_line_cap (line_cap));
}

static cairo_line_join_t
convert_line_join (CairoContext::LineJoin line_join)
{
  switch (line_join)
    {
    default:
    case CairoContext::CAIRO_LINE_JOIN_MITER:   return CAIRO_LINE_JOIN_MITER;
    case CairoContext::CAIRO_LINE_JOIN_ROUND:   return CAIRO_LINE_JOIN_ROUND;
    case CairoContext::CAIRO_LINE_JOIN_BEVEL:   return CAIRO_LINE_JOIN_BEVEL;
    }
}

void
CairoContext::set_line_join (LineJoin line_join)
{
  cairo_set_line_join (cr, convert_line_join (line_join));
}

void
CairoContext::set_miter_limit (double limit)
{
  cairo_set_miter_limit (cr, limit);
}

void
CairoContext::set_dash (double   *dashes,
                        int       num_dashes,
                        double    offset)
{
  cairo_set_dash (cr, dashes, num_dashes, offset);
}

void
CairoContext::set_source_color (Color c)
{
  cairo_set_source_rgba (cr, c.red() / 255., c.green() / 255., c.blue() / 255., c.alpha() / 255.);
}

void
CairoContext::translate (double x, double y)
{
  cairo_translate (cr, x, y);
}

void CairoContext::new_path ()
{
  cairo_new_path (cr);
}

void
CairoContext::move_to (double x,  double y)
{
  cairo_move_to (cr, x, y);
}

void
CairoContext::line_to (double x,  double y)
{
  cairo_line_to (cr, x, y);
}

void
CairoContext::rel_move_to (double x,  double y)
{
  cairo_rel_move_to (cr, x, y);
}

void
CairoContext::rel_line_to (double x,  double y)
{
  cairo_rel_line_to (cr, x, y);
}

void
CairoContext::rectangle (double x, double y, double width, double height)
{
  cairo_rectangle (cr, x, y, width, height);
}

void
CairoContext::curve_to (double x1, double y1,
                        double x2, double y2,
                        double x3, double y3)
{
  cairo_curve_to (cr, x1, y1, x2, y2, x3, y3);
}

void
CairoContext::arc (double xc, double yc, double radius,
                   double angle1, double angle2)
{
  cairo_arc (cr, xc, yc, radius, angle1, angle2);
}

void
CairoContext::arc_negative (double xc, double yc, double radius,
                            double angle1, double angle2)
{
  cairo_arc_negative (cr, xc, yc, radius, angle1, angle2);
}

void
CairoContext::close_path ()
{
  cairo_close_path (cr);
}

void
CairoContext::paint ()
{
  cairo_paint (cr);
}

void
CairoContext::stroke ()
{
  cairo_stroke (cr);
}

void
CairoContext::stroke_preserve ()
{
  cairo_stroke_preserve (cr);
}

void
CairoContext::fill ()
{
  cairo_fill (cr);
}

void
CairoContext::fill_preserve ()
{
  cairo_fill_preserve (cr);
}

CairoContext*
CairoContext::cairo_context_from_plane (Plane &plane)
{
  uint32 *buffer = plane.peek (0, 0);
  cairo_surface_t *cs = cairo_image_surface_create_for_data ((uint8*) buffer, CAIRO_FORMAT_ARGB32, plane.width(), plane.height(), plane.pixstride());
  cairo_t *cr = cairo_create (cs);
  cairo_surface_destroy (cs);
  cairo_translate (cr, -plane.xstart(), -plane.ystart());
  CairoContext *cc = new CairoContext;
  cc->set_cairo (cr);
  return cc;
}

CairoPainter::CairoPainter (Plane &plane) :
  Painter (plane),
  cc (*CairoContext::cairo_context_from_plane (plane_))
{}

CairoPainter::~CairoPainter()
{
  delete &cc;
}

void
CairoPainter::draw_arrow (double x, double y, double width, double height, Color c, double angle)
{
  double mx = x + width / 2, my = y + height / 2;
  double angle0 = (angle + 0) * PI / 180., angle1 = (angle + 120) * PI / 180., angle2 = (angle - 120) * PI / 180.;
  cc.set_source_color (c);
  /* east point */
  cc.move_to (mx + cos (angle0) * width / 2, my + sin (angle0) * height / 2);
  /* north-west point */
  cc.line_to (mx + cos (angle1) * width / 2, my + sin (angle1) * height / 2);
  /* south-west point */
  cc.line_to (mx + cos (angle2) * width / 2, my + sin (angle2) * height / 2);
  //cc.move_to (x,              y);
  //cc.line_to (x + width,      y);
  //cc.line_to (x + width / 2., y + height);
  cc.close_path();
  cc.fill();
}

void
CairoPainter::draw_dir_arrow (double x, double y, double width, double height, Color c, DirType dir)
{
  double xhalf = width / 2., yhalf = height / 2.;
  cc.set_source_color (c);
  switch (dir)
    {
    default:
    case DIR_RIGHT:
      cc.move_to (x + width, y + yhalf);
      cc.line_to (x,         y + height);
      cc.line_to (x,         y);
      break;
    case DIR_UP:
      cc.move_to (x,         y);
      cc.line_to (x + width, y);
      cc.line_to (x + xhalf, y + height);
      break;
    case DIR_LEFT:
      cc.move_to (x,         y + yhalf);
      cc.line_to (x + width, y);
      cc.line_to (x + width, y + height);
      break;
    case DIR_DOWN:
      cc.move_to (x,         y + height);
      cc.line_to (x + xhalf, y);
      cc.line_to (x + width, y + height);
      break;
    }
  cc.close_path();
  cc.fill();
}

void
CairoPainter::draw_dot (double x, double y, double width, double height, Color c1, Color c2, FrameType frame)
{
  cc.rectangle (x, y, width, height);
  cc.set_source_color (c1);
  cc.fill();
}

} // Rapicorn
<|endoftext|>


<commit_before>#include <algorithm>
#define NOMINMAX // Para que nadie nos redefina min max
#include <sstream>

#include "game_window.h"

#include "../parser_yaml/graphics_parser.h"
#include "../parser_yaml/ruleset_parser.h"

using namespace std;

bool GameWindow::sdlInitialized = false;

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

GameWindow::GameWindow(Game& owner, Player& player, GraphicsParser& graphicsParser, RulesetParser& rulesetParser) :
	AClient(owner, player),
	board(player.board),
	ancho_pantalla(graphicsParser.getPantalla().ancho), alto_pantalla(graphicsParser.getPantalla().alto),
	margen_pantalla(graphicsParser.getPantalla().margen_scroll), scroll_speed(graphicsParser.getPantalla().velocidad_scroll)
{
	GameWindow::initialize();
	window = SDL_CreateWindow(("Trabajo Práctico 7542 - " + owner.getBoard()->name + " - " + player.name).c_str(),
		SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
		ancho_pantalla, alto_pantalla,
		SDL_WINDOW_SHOWN);

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

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

	auto tp = graphicsParser.getPantalla();
	font = TTF_OpenFont(FUENTE_DEFAULT, graphicsParser.getPantalla().size_text);
	if (!font) {
		Logger::getInstance()->writeError("Error al abrir TTF");
	}
	inputText = "";
	minimap = std::make_shared<MiniMap>(*this, graphicsParser);
	isoview = std::make_shared<IsoView>(*this, rulesetParser);
	menu = std::make_shared<Menu>(*this, graphicsParser);
	playersList = std::make_shared<PlayersList>(*this, graphicsParser);
	chat = std::make_shared<Chat>(*this, graphicsParser);
	resourcesList = std::make_shared<ResourcesList>(*this, graphicsParser);
	commandMenu = std::make_shared<CommandMenu>(*this, graphicsParser);
	selectionMenu = std::make_shared<SelectionMenu>(*this, graphicsParser);
	sController = std::make_shared<SelectionController>(*this);
	if (player.entities().size() > 0)
		sController->setSelection(player.entities().at(0));
	focus();
	sweeping = false;
}

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

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

SDL_Renderer* GameWindow::getRenderer() {
	return renderer;
}

void GameWindow::render() {
	isoview->draw();
	//menu->draw();TODO: MENU DEBERIA CONTENER A COMMANDMENU SELECTIONMENU MINIMAP
	commandMenu->draw();
	selectionMenu->draw();
	minimap->draw();
	chat->draw(inputText);
	playersList->draw();
	resourcesList->draw();
	if (isSweeping()) {
		r2 boardClick = isoview->screenToBoardPosition(mouseDown);
		r2 boardMouse = isoview->screenToBoardPosition(mouse);
		isoview->drawRhombus(boardClick, boardMouse);
	}

	SDL_RenderPresent(renderer);
	return;
}

void GameWindow::update(){
	sController->update();
	isoview->update();
	processInput();
	render();
	return;
}

void GameWindow::processInput(){
	SDL_GetMouseState(&mouse.x, &mouse.y);
	boardMouse = isoview->screenToBoardPosition(mouse);
	scroll();
	//	Procesar input del usuario
	while(SDL_PollEvent(EventHandler::getInstance()->getEvent())) {
		auto & e = *(EventHandler::getInstance()->getEvent());
		switch(e.type) {
			case SDL_QUIT:
				owner.exit();
				break;
			case SDL_TEXTINPUT:
				if(inputText.size() < MAX_LENGTH_MESSAGE && chat->typing) //Max largo del mensaje a ingresar.
					inputText += e.text.text;
				break;
			case SDL_KEYDOWN:
				Logger::getInstance()->writeInformation("Teclado");
				switch(e.key.keysym.sym) {
					case SDLK_c:
						if(!chat->typing && commandMenu->isVisibleWorker)
							commandMenu->showOptions = true;
						break;
					case SDLK_p:
						if(!chat->typing && commandMenu->isVisibleProducer)
							commandMenu->showOptions = true;
						break;
					case SDLK_ESCAPE:
						commandMenu->showOptions = false;
						break;
					case SDLK_1: case SDLK_2: case SDLK_3: case SDLK_4: case SDLK_5:
					{
						size_t i = e.key.keysym.sym - SDLK_1;
						if (!chat->typing && commandMenu->showOptions) {
							//if (commandMenu->isVisibleProducer) {
							//	auto p = dynamic_cast<Building*>(sController->getSelection().front().get());
							//	if (p) {
							//		if (i < p->products.size()) {
							//			int j = 0;
							//			for (auto& prod : p->products) {
							//				if (i == j) {
							//					board.pushCommand(make_shared<CreateCommand>(p->getId(), prod.first));
							//					j++;
							//				}
							//			}
							//
							//		}
							//	}
							//}
							if (commandMenu->isVisibleWorker) {
								//CONSTRUIR PRODUCTO DEL WORKER SELECCIONADO 1.
							}
						}
					}
						break;
					case SDLK_r:
						if(!chat->typing)
							owner.restart();
						break;
					case SDLK_s:
						for (auto e : sController->getSelection()) {
							if (!chat->typing && e->owner.name == player.name) {
								board.pushCommand(make_shared<StopCommand>(e->getId()));
							}
						}
						break;
					case SDLK_F2:
						chat->typing = !chat->typing;
						inputText = "";
						break;
					case SDLK_SPACE:
						if(!chat->typing)
							focus();
						break;
					case SDLK_BACKSPACE:
						if (chat->typing && inputText.length() > 0){
							inputText.pop_back();
						}
						break;
					case SDLK_RETURN:
						if (chat->typing) {
							chat->messages.push_back(inputText);
							inputText = "";
						}
						break;
				}
				break;
			case SDL_MOUSEBUTTONDOWN:
				if (EventHandler::getInstance()->getEvent()->button.button == SDL_BUTTON_LEFT) {
					SDL_GetMouseState(&mouseDown.x, &mouseDown.y);
					sweeping = true;
				}
				break;
			case SDL_MOUSEBUTTONUP:
				ostringstream oss;
				oss << "Mouse en " << mouse.x << "," << mouse.y;
				// Conversion de coordenadas en pantalla a coordenadas mapa
				oss << "; mapa: " << boardMouse.x << "," << boardMouse.y;

				Logger::getInstance()->writeInformation(oss.str().c_str());
				if (EventHandler::getInstance()->getEvent()->button.button == SDL_BUTTON_LEFT) {
						setSelection();
						sweeping = false;
					}
				if( EventHandler::getInstance()->getEvent()->button.button == SDL_BUTTON_RIGHT) {
					Logger::getInstance()->writeInformation("Boton derecho");
					std::shared_ptr<Entity> obj = board.findEntity(rectangle(boardMouse,r2(0,0)));
					for (auto e : sController->getSelection()) {
						if (e->owner.name == player.name) {
							if (!(SDL_GetModState()&KMOD_SHIFT)) {
								board.pushCommand(make_shared<StopCommand>(e->getId()));
							}
							board.pushCommand(make_shared<MoveCommand>(e->getId(), boardMouse));
						}
					}

				}
				break;
		}
	}
}

void GameWindow::scroll(){
	double ds = (double)scroll_speed * (double)(board.dt) / 1000.0; //deltascroll
	r2 df;

	if(mouse.x <= margen_pantalla) {
		auto dsi = interpolate(mouse.x, 0, margen_pantalla, ds, 0);
		df += {-dsi, dsi};
		Logger::getInstance()->writeInformation("Scrolleando hacia la izquierda");
	}
	if(mouse.x >= ancho_pantalla - margen_pantalla){
		auto dsi = interpolate(mouse.x, ancho_pantalla - margen_pantalla, ancho_pantalla, 0, ds);
		df += {dsi, -dsi};
		Logger::getInstance()->writeInformation("Scrolleando hacia la derecha");
	}
	if(mouse.y <= margen_pantalla) {
		auto dsi = interpolate(mouse.y, 0, margen_pantalla, ds, 0);
		df += {-dsi, -dsi};
		Logger::getInstance()->writeInformation("Scrolleando hacia arriba");
	}
	if(mouse.y >= alto_pantalla - margen_pantalla) {
		auto dsi = interpolate(mouse.y, alto_pantalla - margen_pantalla, alto_pantalla, 0, ds);
		df += {dsi, dsi};
		Logger::getInstance()->writeInformation("Scrolleando hacia abajo");
	}
	focus(focusPosition + df);
}

void GameWindow::focus(r2 newFocus) {
	focusPosition.x = clip(newFocus.x, 0, board.sizeX - 1);
	focusPosition.y = clip(newFocus.y, 0, board.sizeY - 1);
}

void GameWindow::focus() {
	if (sController->getSelection().size() > 0) {
		focus(sController->getSelection().at(0)->getPosition());
	}
}

r2 GameWindow::getFocus() {
	return focusPosition;
}

void GameWindow::setSelection() {
	r2 sweepStart = isoview->screenToBoardPosition(mouseDown);
	r2 sweepEnd = isoview->screenToBoardPosition(mouse);
	sController->setSelection(rectangle(sweepStart, sweepEnd - sweepStart));
}

std::string GameWindow::completeLine(std::string line, double width) {
	int txtAncho, txtAlto, espAncho, espAlto, esp;
	std::string result = line;
	TTF_SizeText(font, " ", &espAncho, &espAlto);
	TTF_SizeText(font, result.c_str(), &txtAncho, &txtAlto);
	esp = (int)floor((width - txtAncho) / espAncho);
	if (txtAncho < width) {
		if (esp * espAncho + txtAncho < width)
			esp++;
		if (esp > 0)result.insert(result.size(), esp, ' ');
	}
	return result;
}

SDL_Color GameWindow::getColor(int id) {
	Uint8 r = (id & 2) * 255;
	Uint8 g = (id & 1) * 255;
	Uint8 b = (id & 4) * 255;
	return{ r, g, b };
}

bool GameWindow::isSweeping() {
	return (sweeping && (mouse.x != mouseDown.x || mouse.y != mouseDown.y));
}

<commit_msg>Comandos de creacion<commit_after>#include <algorithm>
#define NOMINMAX // Para que nadie nos redefina min max
#include <sstream>

#include "game_window.h"

#include "../parser_yaml/graphics_parser.h"
#include "../parser_yaml/ruleset_parser.h"

using namespace std;

bool GameWindow::sdlInitialized = false;

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

GameWindow::GameWindow(Game& owner, Player& player, GraphicsParser& graphicsParser, RulesetParser& rulesetParser) :
	AClient(owner, player),
	board(player.board),
	ancho_pantalla(graphicsParser.getPantalla().ancho), alto_pantalla(graphicsParser.getPantalla().alto),
	margen_pantalla(graphicsParser.getPantalla().margen_scroll), scroll_speed(graphicsParser.getPantalla().velocidad_scroll)
{
	GameWindow::initialize();
	window = SDL_CreateWindow(("Trabajo Práctico 7542 - " + owner.getBoard()->name + " - " + player.name).c_str(),
		SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
		ancho_pantalla, alto_pantalla,
		SDL_WINDOW_SHOWN);

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

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

	auto tp = graphicsParser.getPantalla();
	font = TTF_OpenFont(FUENTE_DEFAULT, graphicsParser.getPantalla().size_text);
	if (!font) {
		Logger::getInstance()->writeError("Error al abrir TTF");
	}
	inputText = "";
	minimap = std::make_shared<MiniMap>(*this, graphicsParser);
	isoview = std::make_shared<IsoView>(*this, rulesetParser);
	menu = std::make_shared<Menu>(*this, graphicsParser);
	playersList = std::make_shared<PlayersList>(*this, graphicsParser);
	chat = std::make_shared<Chat>(*this, graphicsParser);
	resourcesList = std::make_shared<ResourcesList>(*this, graphicsParser);
	commandMenu = std::make_shared<CommandMenu>(*this, graphicsParser);
	selectionMenu = std::make_shared<SelectionMenu>(*this, graphicsParser);
	sController = std::make_shared<SelectionController>(*this);
	if (player.entities().size() > 0)
		sController->setSelection(player.entities().at(0));
	focus();
	sweeping = false;
}

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

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

SDL_Renderer* GameWindow::getRenderer() {
	return renderer;
}

void GameWindow::render() {
	isoview->draw();
	//menu->draw();TODO: MENU DEBERIA CONTENER A COMMANDMENU SELECTIONMENU MINIMAP
	commandMenu->draw();
	selectionMenu->draw();
	minimap->draw();
	chat->draw(inputText);
	playersList->draw();
	resourcesList->draw();
	if (isSweeping()) {
		r2 boardClick = isoview->screenToBoardPosition(mouseDown);
		r2 boardMouse = isoview->screenToBoardPosition(mouse);
		isoview->drawRhombus(boardClick, boardMouse);
	}

	SDL_RenderPresent(renderer);
	return;
}

void GameWindow::update(){
	sController->update();
	isoview->update();
	processInput();
	render();
	return;
}

void GameWindow::processInput(){
	SDL_GetMouseState(&mouse.x, &mouse.y);
	boardMouse = isoview->screenToBoardPosition(mouse);
	scroll();
	//	Procesar input del usuario
	while(SDL_PollEvent(EventHandler::getInstance()->getEvent())) {
		auto & e = *(EventHandler::getInstance()->getEvent());
		switch(e.type) {
			case SDL_QUIT:
				owner.exit();
				break;
			case SDL_TEXTINPUT:
				if(inputText.size() < MAX_LENGTH_MESSAGE && chat->typing) //Max largo del mensaje a ingresar.
					inputText += e.text.text;
				break;
			case SDL_KEYDOWN:
				Logger::getInstance()->writeInformation("Teclado");
				switch(e.key.keysym.sym) {
					case SDLK_c:
						if(!chat->typing && commandMenu->isVisibleWorker)
							commandMenu->showOptions = true;
						break;
					case SDLK_p:
						if(!chat->typing && commandMenu->isVisibleProducer)
							commandMenu->showOptions = true;
						break;
					case SDLK_ESCAPE:
						commandMenu->showOptions = false;
						break;
					case SDLK_1: case SDLK_2: case SDLK_3: case SDLK_4: case SDLK_5:
					{
						size_t i = e.key.keysym.sym - SDLK_1;
						if (!chat->typing && commandMenu->showOptions) {
							if (commandMenu->isVisibleProducer) {
								auto p = dynamic_cast<Building*>(sController->getSelection().front().get());
								if (p) {
									if (i < p->products.size()) {
										board.pushCommand(std::make_shared<CreateCommand>(p->getId(),p->products[i].name));
									}
								}
							}
							if (commandMenu->isVisibleWorker) {
								auto w = dynamic_cast<Worker*>(sController->getSelection().front().get());
								if (w) {
									if (i < w->products.size()) {
										board.pushCommand(std::make_shared<CreateCommand>(w->getId(), w->products[i].name));
									}
								}
							}
						}
					}
						break;
					case SDLK_r:
						if(!chat->typing)
							owner.restart();
						break;
					case SDLK_s:
						for (auto e : sController->getSelection()) {
							if (!chat->typing && e->owner.name == player.name) {
								board.pushCommand(make_shared<StopCommand>(e->getId()));
							}
						}
						break;
					case SDLK_F2:
						chat->typing = !chat->typing;
						inputText = "";
						break;
					case SDLK_SPACE:
						if(!chat->typing)
							focus();
						break;
					case SDLK_BACKSPACE:
						if (chat->typing && inputText.length() > 0){
							inputText.pop_back();
						}
						break;
					case SDLK_RETURN:
						if (chat->typing) {
							chat->messages.push_back(inputText);
							inputText = "";
						}
						break;
				}
				break;
			case SDL_MOUSEBUTTONDOWN:
				if (EventHandler::getInstance()->getEvent()->button.button == SDL_BUTTON_LEFT) {
					SDL_GetMouseState(&mouseDown.x, &mouseDown.y);
					sweeping = true;
				}
				break;
			case SDL_MOUSEBUTTONUP:
				ostringstream oss;
				oss << "Mouse en " << mouse.x << "," << mouse.y;
				// Conversion de coordenadas en pantalla a coordenadas mapa
				oss << "; mapa: " << boardMouse.x << "," << boardMouse.y;

				Logger::getInstance()->writeInformation(oss.str().c_str());
				if (EventHandler::getInstance()->getEvent()->button.button == SDL_BUTTON_LEFT) {
						setSelection();
						sweeping = false;
					}
				if( EventHandler::getInstance()->getEvent()->button.button == SDL_BUTTON_RIGHT) {
					Logger::getInstance()->writeInformation("Boton derecho");
					std::shared_ptr<Entity> obj = board.findEntity(rectangle(boardMouse,r2(0,0)));
					for (auto e : sController->getSelection()) {
						if (e->owner.name == player.name) {
							if (!(SDL_GetModState()&KMOD_SHIFT)) {
								board.pushCommand(make_shared<StopCommand>(e->getId()));
							}
							board.pushCommand(make_shared<MoveCommand>(e->getId(), boardMouse));
						}
					}

				}
				break;
		}
	}
}

void GameWindow::scroll(){
	double ds = (double)scroll_speed * (double)(board.dt) / 1000.0; //deltascroll
	r2 df;

	if(mouse.x <= margen_pantalla) {
		auto dsi = interpolate(mouse.x, 0, margen_pantalla, ds, 0);
		df += {-dsi, dsi};
		Logger::getInstance()->writeInformation("Scrolleando hacia la izquierda");
	}
	if(mouse.x >= ancho_pantalla - margen_pantalla){
		auto dsi = interpolate(mouse.x, ancho_pantalla - margen_pantalla, ancho_pantalla, 0, ds);
		df += {dsi, -dsi};
		Logger::getInstance()->writeInformation("Scrolleando hacia la derecha");
	}
	if(mouse.y <= margen_pantalla) {
		auto dsi = interpolate(mouse.y, 0, margen_pantalla, ds, 0);
		df += {-dsi, -dsi};
		Logger::getInstance()->writeInformation("Scrolleando hacia arriba");
	}
	if(mouse.y >= alto_pantalla - margen_pantalla) {
		auto dsi = interpolate(mouse.y, alto_pantalla - margen_pantalla, alto_pantalla, 0, ds);
		df += {dsi, dsi};
		Logger::getInstance()->writeInformation("Scrolleando hacia abajo");
	}
	focus(focusPosition + df);
}

void GameWindow::focus(r2 newFocus) {
	focusPosition.x = clip(newFocus.x, 0, board.sizeX - 1);
	focusPosition.y = clip(newFocus.y, 0, board.sizeY - 1);
}

void GameWindow::focus() {
	if (sController->getSelection().size() > 0) {
		focus(sController->getSelection().at(0)->getPosition());
	}
}

r2 GameWindow::getFocus() {
	return focusPosition;
}

void GameWindow::setSelection() {
	r2 sweepStart = isoview->screenToBoardPosition(mouseDown);
	r2 sweepEnd = isoview->screenToBoardPosition(mouse);
	sController->setSelection(rectangle(sweepStart, sweepEnd - sweepStart));
}

std::string GameWindow::completeLine(std::string line, double width) {
	int txtAncho, txtAlto, espAncho, espAlto, esp;
	std::string result = line;
	TTF_SizeText(font, " ", &espAncho, &espAlto);
	TTF_SizeText(font, result.c_str(), &txtAncho, &txtAlto);
	esp = (int)floor((width - txtAncho) / espAncho);
	if (txtAncho < width) {
		if (esp * espAncho + txtAncho < width)
			esp++;
		if (esp > 0)result.insert(result.size(), esp, ' ');
	}
	return result;
}

SDL_Color GameWindow::getColor(int id) {
	Uint8 r = (id & 2) * 255;
	Uint8 g = (id & 1) * 255;
	Uint8 b = (id & 4) * 255;
	return{ r, g, b };
}

bool GameWindow::isSweeping() {
	return (sweeping && (mouse.x != mouseDown.x || mouse.y != mouseDown.y));
}

<|endoftext|>


<commit_before>/* Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html */
#include <rcore/testutils.hh>
#include <ui/uithread.hh>
using namespace Rapicorn;

static void
test_server_smart_handle()
{
  ApplicationImpl &app = ApplicationImpl::the(); // FIXME: use Application_SmartHandle once C++ bindings are ready
  ApplicationIface *ab = &app;
  Aida::FieldBuffer8 fb (4);
  fb.add_object (uint64 ((BaseObject*) ab));
  // FIXME: Aida::Coupler &c = *rope_thread_coupler();
  // c.reader.reset (fb);
  ApplicationImpl *am = dynamic_cast<ApplicationImpl*> (ab);
  assert (am == &app);
  ApplicationIface *ai = am;
  assert (ai == ab);
}
REGISTER_UITHREAD_TEST ("Server/Smart Handle", test_server_smart_handle);

static void
test_stock_resources()
{
  String s;
  s = Stock::stock_label ("broken-image");
  TASSERT (s.empty() == false);
  s = Stock::stock_string ("broken-image", "image");
  TASSERT (s.empty() == false);
  Blob b = Stock::stock_image ("broken-image");
  TASSERT (b && b.size() > 16);
  b = Stock::stock_image (" .no.. +such+ -image- ~hCZ75jv27j");
  TASSERT (!b && errno != 0);
}
REGISTER_UITHREAD_TEST ("Server/Stock Resources", test_stock_resources);

static void
test_application_xurl()
{
  ApplicationImpl &app = ApplicationImpl::the();
  bool success;

  struct Dummy : public ListModelRelayImpl { using ListModelRelayImpl::create_list_model_relay; };
  ListModelRelayIface &lmr1 = Dummy::create_list_model_relay ();
  ListModelIface      &lm1  = *lmr1.model();
  ListModelRelayIface &lmr2 = Dummy::create_list_model_relay ();
  ListModelIface      &lm2  = *lmr2.model();
  ListModelRelayIface &lmr3 = Dummy::create_list_model_relay ();
  ListModelIface      &lm3  = *lmr3.model();
  ListModelIface *lmi;
  String path;

  // model1 + lmr1 tests
  lmi = app.xurl_find ("//local/data/unknown");                 TASSERT (lmi == NULL);
  lmi = app.xurl_find ("//local/data/model1");                  TASSERT (lmi == NULL);
  path = app.xurl_path (lm1);                                   TASSERT (path == "");
  success = app.xurl_add ("//local/data/model1", lm1);          TASSERT (success == true);
  path = app.xurl_path (lm1);                                   TASSERT (path == "//local/data/model1");
  success = app.xurl_add ("//local/data/model1", lm1);          TASSERT (success == false);
  success = app.xurl_add ("//local/data/model1", lm2);          TASSERT (success == false);
  success = app.xurl_add ("//local/data/unknown", lm1);         TASSERT (success == false);
  lmi = app.xurl_find ("//local/data/model1");                  TASSERT (lmi == &lm1);
  success = app.xurl_sub (lm1);                                 TASSERT (success == true);
  success = app.xurl_sub (lm1);                                 TASSERT (success == false);
  path = app.xurl_path (lm1);                                   TASSERT (path == "");
  lmi = app.xurl_find ("//local/data/model1");                  TASSERT (lmi == NULL);
  success = app.xurl_add ("//local/data/model1", lm1);          TASSERT (success == true);
  path = app.xurl_path (lm1);                                   TASSERT (path == "//local/data/model1");

  // model2 + lmr2 tests
  lmi = app.xurl_find ("//local/data/model2");                  TASSERT (lmi == NULL);
  path = app.xurl_path (lm2);                                   TASSERT (path == "");
  success = app.xurl_sub (lm2);                                 TASSERT (success == false);
  success = app.xurl_add ("//local/data/model2", lm2);          TASSERT (success == true);
  path = app.xurl_path (lm2);                                   TASSERT (path == "//local/data/model2");
  success = app.xurl_add ("//local/data/model2", lm1);          TASSERT (success == false);
  success = app.xurl_add ("//local/data/model2", lm3);          TASSERT (success == false);
  success = app.xurl_add ("//local/data/unknown", lm2);         TASSERT (success == false);
  lmi = app.xurl_find ("//local/data/model2");                  TASSERT (lmi == &lm2);
  success = app.xurl_sub (lm2);                                 TASSERT (success == true);
  success = app.xurl_sub (lm2);                                 TASSERT (success == false);
  lmi = app.xurl_find ("//local/data/model2");                  TASSERT (lmi == NULL);
  success = app.xurl_add ("//local/data/model2", lm2);          TASSERT (success == true);
  lmi = app.xurl_find ("//local/data/model2");                  TASSERT (lmi == &lm2);

  // model3 + lmr3 tests
  lmi = app.xurl_find ("//local/data/model3");                  TASSERT (lmi == NULL);
  path = app.xurl_path (lm3);                                   TASSERT (path == "");
  success = app.xurl_add ("//local/data/model3", lm3);          TASSERT (success == true);
  path = app.xurl_path (lm3);                                   TASSERT (path == "//local/data/model3");
  success = app.xurl_add ("//local/data/unknown", lm3);         TASSERT (success == false);
  lmi = app.xurl_find ("//local/data/model3");                  TASSERT (lmi == &lm3);

  // removal checks
  lmi = app.xurl_find ("//local/data/model1");                  TASSERT (lmi == &lm1);
  unref (ref_sink (lmr1));
  lmi = app.xurl_find ("//local/data/model1");                  TASSERT (lmi == NULL);

  lmi = app.xurl_find ("//local/data/model2");                  TASSERT (lmi == &lm2);
  success = app.xurl_sub (lm2);                                 TASSERT (success == true);
  success = app.xurl_sub (lm2);                                 TASSERT (success == false);
  unref (ref_sink (lmr2));
  lmi = app.xurl_find ("//local/data/model2");                  TASSERT (lmi == NULL);

  lmi = app.xurl_find ("//local/data/model3");                  TASSERT (lmi == &lm3);
  unref (ref_sink (lmr3));
  lmi = app.xurl_find ("//local/data/model3");                  TASSERT (lmi == NULL);
}
REGISTER_UITHREAD_TEST ("Server/Application XUrl Map", test_application_xurl);
<commit_msg>UI: tests: add primitive TypeCode test<commit_after>/* Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html */
#include <rcore/testutils.hh>
#include <ui/uithread.hh>
using namespace Rapicorn;

static void
test_server_smart_handle()
{
  ApplicationImpl &app = ApplicationImpl::the(); // FIXME: use Application_SmartHandle once C++ bindings are ready
  ApplicationIface *ab = &app;
  Aida::FieldBuffer8 fb (4);
  fb.add_object (uint64 ((BaseObject*) ab));
  // FIXME: Aida::Coupler &c = *rope_thread_coupler();
  // c.reader.reset (fb);
  ApplicationImpl *am = dynamic_cast<ApplicationImpl*> (ab);
  assert (am == &app);
  ApplicationIface *ai = am;
  assert (ai == ab);
}
REGISTER_UITHREAD_TEST ("Server/Smart Handle", test_server_smart_handle);

static void
test_stock_resources()
{
  String s;
  s = Stock::stock_label ("broken-image");
  TASSERT (s.empty() == false);
  s = Stock::stock_string ("broken-image", "image");
  TASSERT (s.empty() == false);
  Blob b = Stock::stock_image ("broken-image");
  TASSERT (b && b.size() > 16);
  b = Stock::stock_image (" .no.. +such+ -image- ~hCZ75jv27j");
  TASSERT (!b && errno != 0);
}
REGISTER_UITHREAD_TEST ("Server/Stock Resources", test_stock_resources);

static void
test_application_xurl()
{
  ApplicationImpl &app = ApplicationImpl::the();
  bool success;

  struct Dummy : public ListModelRelayImpl { using ListModelRelayImpl::create_list_model_relay; };
  ListModelRelayIface &lmr1 = Dummy::create_list_model_relay ();
  ListModelIface      &lm1  = *lmr1.model();
  ListModelRelayIface &lmr2 = Dummy::create_list_model_relay ();
  ListModelIface      &lm2  = *lmr2.model();
  ListModelRelayIface &lmr3 = Dummy::create_list_model_relay ();
  ListModelIface      &lm3  = *lmr3.model();
  ListModelIface *lmi;
  String path;

  // model1 + lmr1 tests
  lmi = app.xurl_find ("//local/data/unknown");                 TASSERT (lmi == NULL);
  lmi = app.xurl_find ("//local/data/model1");                  TASSERT (lmi == NULL);
  path = app.xurl_path (lm1);                                   TASSERT (path == "");
  success = app.xurl_add ("//local/data/model1", lm1);          TASSERT (success == true);
  path = app.xurl_path (lm1);                                   TASSERT (path == "//local/data/model1");
  success = app.xurl_add ("//local/data/model1", lm1);          TASSERT (success == false);
  success = app.xurl_add ("//local/data/model1", lm2);          TASSERT (success == false);
  success = app.xurl_add ("//local/data/unknown", lm1);         TASSERT (success == false);
  lmi = app.xurl_find ("//local/data/model1");                  TASSERT (lmi == &lm1);
  success = app.xurl_sub (lm1);                                 TASSERT (success == true);
  success = app.xurl_sub (lm1);                                 TASSERT (success == false);
  path = app.xurl_path (lm1);                                   TASSERT (path == "");
  lmi = app.xurl_find ("//local/data/model1");                  TASSERT (lmi == NULL);
  success = app.xurl_add ("//local/data/model1", lm1);          TASSERT (success == true);
  path = app.xurl_path (lm1);                                   TASSERT (path == "//local/data/model1");

  // model2 + lmr2 tests
  lmi = app.xurl_find ("//local/data/model2");                  TASSERT (lmi == NULL);
  path = app.xurl_path (lm2);                                   TASSERT (path == "");
  success = app.xurl_sub (lm2);                                 TASSERT (success == false);
  success = app.xurl_add ("//local/data/model2", lm2);          TASSERT (success == true);
  path = app.xurl_path (lm2);                                   TASSERT (path == "//local/data/model2");
  success = app.xurl_add ("//local/data/model2", lm1);          TASSERT (success == false);
  success = app.xurl_add ("//local/data/model2", lm3);          TASSERT (success == false);
  success = app.xurl_add ("//local/data/unknown", lm2);         TASSERT (success == false);
  lmi = app.xurl_find ("//local/data/model2");                  TASSERT (lmi == &lm2);
  success = app.xurl_sub (lm2);                                 TASSERT (success == true);
  success = app.xurl_sub (lm2);                                 TASSERT (success == false);
  lmi = app.xurl_find ("//local/data/model2");                  TASSERT (lmi == NULL);
  success = app.xurl_add ("//local/data/model2", lm2);          TASSERT (success == true);
  lmi = app.xurl_find ("//local/data/model2");                  TASSERT (lmi == &lm2);

  // model3 + lmr3 tests
  lmi = app.xurl_find ("//local/data/model3");                  TASSERT (lmi == NULL);
  path = app.xurl_path (lm3);                                   TASSERT (path == "");
  success = app.xurl_add ("//local/data/model3", lm3);          TASSERT (success == true);
  path = app.xurl_path (lm3);                                   TASSERT (path == "//local/data/model3");
  success = app.xurl_add ("//local/data/unknown", lm3);         TASSERT (success == false);
  lmi = app.xurl_find ("//local/data/model3");                  TASSERT (lmi == &lm3);

  // removal checks
  lmi = app.xurl_find ("//local/data/model1");                  TASSERT (lmi == &lm1);
  unref (ref_sink (lmr1));
  lmi = app.xurl_find ("//local/data/model1");                  TASSERT (lmi == NULL);

  lmi = app.xurl_find ("//local/data/model2");                  TASSERT (lmi == &lm2);
  success = app.xurl_sub (lm2);                                 TASSERT (success == true);
  success = app.xurl_sub (lm2);                                 TASSERT (success == false);
  unref (ref_sink (lmr2));
  lmi = app.xurl_find ("//local/data/model2");                  TASSERT (lmi == NULL);

  lmi = app.xurl_find ("//local/data/model3");                  TASSERT (lmi == &lm3);
  unref (ref_sink (lmr3));
  lmi = app.xurl_find ("//local/data/model3");                  TASSERT (lmi == NULL);
}
REGISTER_UITHREAD_TEST ("Server/Application XUrl Map", test_application_xurl);

static void
test_type_codes()
{
  ApplicationImpl &app = ApplicationImpl::the();
  Aida::TypeCode tc = app.__aida_type_code__();
  assert (tc.kind() == Aida::INSTANCE);
  assert (tc.name() == "Rapicorn::Application");
  assert (tc.untyped() == false);
}
REGISTER_UITHREAD_TEST ("Server/IDL Type Codes", test_type_codes);
<|endoftext|>


<commit_before>/* -------------------------------------------------------------------------- *
 *                      SimTK Core: SimTK Simbody(tm)                         *
 * -------------------------------------------------------------------------- *
 * This is part of the SimTK Core biosimulation toolkit originating from      *
 * Simbios, the NIH National Center for Physics-Based Simulation of           *
 * Biological Structures at Stanford, funded under the NIH Roadmap for        *
 * Medical Research, grant U54 GM072970. See https://simtk.org.               *
 *                                                                            *
 * Portions copyright (c) 2006-7 Stanford University and the Authors.         *
 * Authors: Michael Sherman                                                   *
 * Contributors:                                                              *
 *                                                                            *
 * Permission is hereby granted, free of charge, to any person obtaining a    *
 * copy of this software and associated documentation files (the "Software"), *
 * to deal in the Software without restriction, including without limitation  *
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,   *
 * and/or sell copies of the Software, and to permit persons to whom the      *
 * Software is furnished to do so, subject to the following conditions:       *
 *                                                                            *
 * The above copyright notice and this permission notice shall be included in *
 * all copies or substantial portions of the Software.                        *
 *                                                                            *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,   *
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    *
 * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,    *
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR      *
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE  *
 * USE OR OTHER DEALINGS IN THE SOFTWARE.                                     *
 * -------------------------------------------------------------------------- */

/** @file
 * Defines the standard SimTK core "version" and "about" routines.
 */

#include "SimTKcommon.h"
#include "simbody/internal/common.h"

#include <string>
#include <cstring>
#include <cctype>

#define STR(var) #var
#define MAKE_VERSION_STRING(maj,min,build)  STR(maj.min.build)
#define MAKE_COPYRIGHT_STRING(y,a) \
    "Copyright (c) " STR(y) " Stanford University, " STR(a)
#define MAKE_STRING(a) STR(a)

#define GET_VERSION_STRING  \
    MAKE_VERSION_STRING(SimTK_SIMBODY_MAJOR_VERSION,  \
                        SimTK_SIMBODY_MINOR_VERSION,  \
                        SimTK_SIMBODY_BUILD_VERSION)

#define GET_COPYRIGHT_STRING \
    MAKE_COPYRIGHT_STRING(SimTK_SIMBODY_COPYRIGHT_YEARS, \
                          SimTK_SIMBODY_AUTHORS)

#define GET_SVN_REVISION_STRING \
    MAKE_STRING(SimTK_SIMBODY_SVN_REVISION)

#define GET_AUTHORS_STRING \
    MAKE_STRING(SimTK_SIMBODY_AUTHORS)

#define GET_LIBRARY_STRING \
    MAKE_STRING(SimTK_SIMBODY_LIBRARY_NAME)

#if defined(SimTK_SIMBODY_BUILDING_SHARED_LIBRARY)
    #define GET_TYPE_STRING "shared"
#elif defined(SimTK_SIMBODY_BUILDING_STATIC_LIBRARY)
    #define GET_TYPE_STRING "static"
#else
    #define GET_TYPE_STRING "<unknown library type?!>"
#endif

#ifndef NDEBUG
    #define GET_DEBUG_STRING "debug"
#else
    #define GET_DEBUG_STRING "release"
#endif

extern "C" {

void SimTK_version_simbody(int* major, int* minor, int* build) {
    static const char* l = "SimTK library="   GET_LIBRARY_STRING;
    static const char* t = "SimTK type="      GET_TYPE_STRING;
    static const char* d = "SimTK debug="     GET_DEBUG_STRING;
    static const char* v = "SimTK version="   GET_VERSION_STRING;
    static const char* r = "SimTK svn_revision=" GET_SVN_REVISION_STRING;
    static const char* c = "SimTK copyright=" GET_COPYRIGHT_STRING;

    if (major) *major = SimTK_SIMBODY_MAJOR_VERSION;
    if (minor) *minor = SimTK_SIMBODY_MINOR_VERSION;
    if (build) *build = SimTK_SIMBODY_BUILD_VERSION;

    // Force statics to be present in the binary (Release mode otherwise
    // optimizes them away).
    volatile int i=0;
    if (i) { // never true, but compiler doesn't know ...
        *major = *l + *t + *d + *v + *r + *c;
    }
}

void SimTK_about_simbody(const char* key, int maxlen, char* value) {
    if (maxlen <= 0 || value==0) return;
    value[0] = '\0'; // in case we don't find a match
    if (key==0) return;

    // downshift the key
    std::string skey(key);
    for (size_t i=0; i<skey.size(); ++i)
        skey[i] = std::tolower(skey[i]);

    char* v = 0;
    if      (skey == "version")   v = GET_VERSION_STRING;
    else if (skey == "library")   v = GET_LIBRARY_STRING;
    else if (skey == "type")      v = GET_TYPE_STRING;
    else if (skey == "copyright") v = GET_COPYRIGHT_STRING;
    else if (skey == "svn_revision") v = GET_SVN_REVISION_STRING;
    else if (skey == "authors")   v = GET_AUTHORS_STRING;
    else if (skey == "debug")     v = GET_DEBUG_STRING;

    if (v) {
        std::strncpy(value,v,maxlen-1);
        value[maxlen-1] = '\0'; // in case we ran out of room
    }
}

}
<commit_msg>Fix warning from Snow Leopard gcc.<commit_after>/* -------------------------------------------------------------------------- *
 *                      SimTK Core: SimTK Simbody(tm)                         *
 * -------------------------------------------------------------------------- *
 * This is part of the SimTK Core biosimulation toolkit originating from      *
 * Simbios, the NIH National Center for Physics-Based Simulation of           *
 * Biological Structures at Stanford, funded under the NIH Roadmap for        *
 * Medical Research, grant U54 GM072970. See https://simtk.org.               *
 *                                                                            *
 * Portions copyright (c) 2006-7 Stanford University and the Authors.         *
 * Authors: Michael Sherman                                                   *
 * Contributors:                                                              *
 *                                                                            *
 * Permission is hereby granted, free of charge, to any person obtaining a    *
 * copy of this software and associated documentation files (the "Software"), *
 * to deal in the Software without restriction, including without limitation  *
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,   *
 * and/or sell copies of the Software, and to permit persons to whom the      *
 * Software is furnished to do so, subject to the following conditions:       *
 *                                                                            *
 * The above copyright notice and this permission notice shall be included in *
 * all copies or substantial portions of the Software.                        *
 *                                                                            *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,   *
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    *
 * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,    *
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR      *
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE  *
 * USE OR OTHER DEALINGS IN THE SOFTWARE.                                     *
 * -------------------------------------------------------------------------- */

/** @file
 * Defines the standard SimTK core "version" and "about" routines.
 */

#include "SimTKcommon.h"
#include "simbody/internal/common.h"

#include <string>
#include <cstring>
#include <cctype>

#define STR(var) #var
#define MAKE_VERSION_STRING(maj,min,build)  STR(maj.min.build)
#define MAKE_COPYRIGHT_STRING(y,a) \
    "Copyright (c) " STR(y) " Stanford University, " STR(a)
#define MAKE_STRING(a) STR(a)

#define GET_VERSION_STRING  \
    MAKE_VERSION_STRING(SimTK_SIMBODY_MAJOR_VERSION,  \
                        SimTK_SIMBODY_MINOR_VERSION,  \
                        SimTK_SIMBODY_BUILD_VERSION)

#define GET_COPYRIGHT_STRING \
    MAKE_COPYRIGHT_STRING(SimTK_SIMBODY_COPYRIGHT_YEARS, \
                          SimTK_SIMBODY_AUTHORS)

#define GET_SVN_REVISION_STRING \
    MAKE_STRING(SimTK_SIMBODY_SVN_REVISION)

#define GET_AUTHORS_STRING \
    MAKE_STRING(SimTK_SIMBODY_AUTHORS)

#define GET_LIBRARY_STRING \
    MAKE_STRING(SimTK_SIMBODY_LIBRARY_NAME)

#if defined(SimTK_SIMBODY_BUILDING_SHARED_LIBRARY)
    #define GET_TYPE_STRING "shared"
#elif defined(SimTK_SIMBODY_BUILDING_STATIC_LIBRARY)
    #define GET_TYPE_STRING "static"
#else
    #define GET_TYPE_STRING "<unknown library type?!>"
#endif

#ifndef NDEBUG
    #define GET_DEBUG_STRING "debug"
#else
    #define GET_DEBUG_STRING "release"
#endif

extern "C" {

void SimTK_version_simbody(int* major, int* minor, int* build) {
    static const char* l = "SimTK library="   GET_LIBRARY_STRING;
    static const char* t = "SimTK type="      GET_TYPE_STRING;
    static const char* d = "SimTK debug="     GET_DEBUG_STRING;
    static const char* v = "SimTK version="   GET_VERSION_STRING;
    static const char* r = "SimTK svn_revision=" GET_SVN_REVISION_STRING;
    static const char* c = "SimTK copyright=" GET_COPYRIGHT_STRING;

    if (major) *major = SimTK_SIMBODY_MAJOR_VERSION;
    if (minor) *minor = SimTK_SIMBODY_MINOR_VERSION;
    if (build) *build = SimTK_SIMBODY_BUILD_VERSION;

    // Force statics to be present in the binary (Release mode otherwise
    // optimizes them away).
    volatile int i=0;
    if (i) { // never true, but compiler doesn't know ...
        *major = *l + *t + *d + *v + *r + *c;
    }
}

void SimTK_about_simbody(const char* key, int maxlen, char* value) {
    if (maxlen <= 0 || value==0) return;
    value[0] = '\0'; // in case we don't find a match
    if (key==0) return;

    // downshift the key
    std::string skey(key);
    for (size_t i=0; i<skey.size(); ++i)
        skey[i] = std::tolower(skey[i]);

    const char* v = 0;
    if      (skey == "version")   v = GET_VERSION_STRING;
    else if (skey == "library")   v = GET_LIBRARY_STRING;
    else if (skey == "type")      v = GET_TYPE_STRING;
    else if (skey == "copyright") v = GET_COPYRIGHT_STRING;
    else if (skey == "svn_revision") v = GET_SVN_REVISION_STRING;
    else if (skey == "authors")   v = GET_AUTHORS_STRING;
    else if (skey == "debug")     v = GET_DEBUG_STRING;

    if (v) {
        std::strncpy(value,v,maxlen-1);
        value[maxlen-1] = '\0'; // in case we ran out of room
    }
}

}
<|endoftext|>


<commit_before>#include "Chunk.h"

#include <cstdlib>

uint qHash(const Int3D & coord)
{
    return (coord.x * 8191 + coord.z) * 131071 + coord.y;
}

Chunk::Chunk(const Int3D &pos, const Int3D &size) :
    m_pos(pos),
    m_size(size),
    m_blocks(m_size.x * m_size.y * m_size.z)
{
}

int Chunk::indexOf(const Int3D & coord) const
{
    Q_ASSERT(0 <= coord.x && coord.x < m_size.x &&
             0 <= coord.y && coord.y < m_size.y &&
             0 <= coord.z && coord.z < m_size.z);
    return coord.y + (coord.z * m_size.y) + (coord.x * m_size.y * m_size.z);
}

Block Chunk::getBlock(const Int3D & coord) const
{
    return m_blocks.at(indexOf(coord));
}
void Chunk::setBlock(const Int3D &coord, const Block &value)
{
    m_blocks.replace(indexOf(coord), value);
}
<commit_msg>fill chunks with air so we don't see trash<commit_after>#include "Chunk.h"

#include <cstdlib>

uint qHash(const Int3D & coord)
{
    return (coord.x * 8191 + coord.z) * 131071 + coord.y;
}

Chunk::Chunk(const Int3D &pos, const Int3D &size) :
    m_pos(pos),
    m_size(size),
    m_blocks(m_size.x * m_size.y * m_size.z)
{
    m_blocks.fill(Block(Block::Air, 0, 0, 0));
}

int Chunk::indexOf(const Int3D & coord) const
{
    Q_ASSERT(0 <= coord.x && coord.x < m_size.x &&
             0 <= coord.y && coord.y < m_size.y &&
             0 <= coord.z && coord.z < m_size.z);
    return coord.y + (coord.z * m_size.y) + (coord.x * m_size.y * m_size.z);
}

Block Chunk::getBlock(const Int3D & coord) const
{
    return m_blocks.at(indexOf(coord));
}
void Chunk::setBlock(const Int3D &coord, const Block &value)
{
    m_blocks.replace(indexOf(coord), value);
}
<|endoftext|>