<commit_before>#include "./scene.h"
#include <Eigen/Core>
#include <Eigen/Geometry>
#include <string>
#include <vector>
#include <map>
#include "./graphics/gl.h"
#include "./input/invoke_manager.h"
#include "./graphics/render_data.h"
#include "./graphics/managers.h"
#include "./graphics/volume_manager.h"
#include "./graphics/shader_program.h"
#include "./graphics/buffer_drawer.h"
#include "./camera_controllers.h"
#include "./nodes.h"
#include "./camera_node.h"
#include "./label_node.h"
#include "./eigen_qdebug.h"
#include "./utils/path_helper.h"
#include "./placement/to_gray.h"
#include "./placement/distance_transform.h"
#include "./placement/apollonius.h"
#include "./texture_mapper_manager.h"
#include "./constraint_buffer_object.h"
#include "./labelling_coordinator.h"

Scene::Scene(int layerCount, std::shared_ptr<InvokeManager> invokeManager,
             std::shared_ptr<Nodes> nodes, std::shared_ptr<Labels> labels,
             std::shared_ptr<LabellingCoordinator> labellingCoordinator,
             std::shared_ptr<TextureMapperManager> textureMapperManager)

  : nodes(nodes), labels(labels), labellingCoordinator(labellingCoordinator),
    frustumOptimizer(nodes), textureMapperManager(textureMapperManager)
{
  cameraControllers =
      std::make_shared<CameraControllers>(invokeManager, getCamera());

  fbo = std::make_shared<Graphics::FrameBufferObject>(layerCount);
  constraintBufferObject = std::make_shared<ConstraintBufferObject>();
  managers = std::make_shared<Graphics::Managers>();
}

Scene::~Scene()
{
  nodes->clear();
  qInfo() << "Destructor of Scene"
          << "Remaining managers instances" << managers.use_count();
}

void Scene::initialize()
{
  quad = std::make_shared<Graphics::ScreenQuad>(
      ":shader/pass.vert", ":shader/textureForRenderBuffer.frag");
  screenQuad = std::make_shared<Graphics::ScreenQuad>(
      ":shader/pass.vert", ":shader/combineLayers.frag");
  positionQuad = std::make_shared<Graphics::ScreenQuad>(
      ":shader/pass.vert", ":shader/positionRenderTarget.frag");
  distanceTransformQuad = std::make_shared<Graphics::ScreenQuad>(
      ":shader/pass.vert", ":shader/distanceTransform.frag");
  transparentQuad = std::make_shared<Graphics::ScreenQuad>(
      ":shader/pass.vert", ":shader/transparentOverlay.frag");

  fbo->initialize(gl, width, height);
  picker = std::make_unique<Picker>(fbo, gl, labels);
  picker->resize(width, height);
  constraintBufferObject->initialize(gl, textureMapperManager->getBufferSize(),
                                     textureMapperManager->getBufferSize());
  haBuffer =
      std::make_shared<Graphics::HABuffer>(Eigen::Vector2i(width, height));
  managers->getShaderManager()->initialize(gl, haBuffer);

  managers->getObjectManager()->initialize(gl, 128, 10000000);
  haBuffer->initialize(gl, managers);
  quad->initialize(gl, managers);
  screenQuad->initialize(gl, managers);
  positionQuad->initialize(gl, managers);
  distanceTransformQuad->initialize(gl, managers);
  transparentQuad->initialize(gl, managers);

  managers->getTextureManager()->initialize(gl, true, 8);

  textureMapperManager->createTextureMappersForLayers(fbo->getLayerCount());
  textureMapperManager->resize(width, height);
  textureMapperManager->initialize(gl, fbo, constraintBufferObject);

  auto drawer = std::make_shared<Graphics::BufferDrawer>(
      textureMapperManager->getBufferSize(),
      textureMapperManager->getBufferSize(), gl, managers->getShaderManager());

  labellingCoordinator->initialize(textureMapperManager->getBufferSize(),
                                   drawer, textureMapperManager, width, height);
}

void Scene::cleanup()
{
  labellingCoordinator->cleanup();

  textureMapperManager->cleanup();
}

void Scene::update(double frameTime, QSet<Qt::Key> keysPressed)
{
  auto camera = getCamera();

  if (camera->needsResizing())
    camera->resize(width, height);

  this->frameTime = frameTime;
  cameraControllers->update(camera, frameTime);

  frustumOptimizer.update(camera->getViewMatrix());
  camera->updateNearAndFarPlanes(frustumOptimizer.getNear(),
                                 frustumOptimizer.getFar());
  haBuffer->updateNearAndFarPlanes(frustumOptimizer.getNear(),
                                   frustumOptimizer.getFar());

  labellingCoordinator->update(frameTime, camera->getProjectionMatrix(),
                               camera->getViewMatrix(), activeLayerNumber);
}

void Scene::render()
{
  auto camera = getCamera();

  if (shouldResize)
  {
    camera->resize(width, height);
    fbo->resize(width, height);
    shouldResize = false;
  }

  glAssert(gl->glViewport(0, 0, width, height));
  glAssert(gl->glClearColor(0.0f, 0.0f, 0.0f, 0.0f));
  glAssert(gl->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));

  RenderData renderData = createRenderData();

  renderNodesWithHABufferIntoFBO(renderData);

  textureMapperManager->update();

  constraintBufferObject->bind();

  labellingCoordinator->updatePlacement();

  constraintBufferObject->unbind();

  glAssert(gl->glViewport(0, 0, width, height));

  fbo->bind();
  glAssert(gl->glDisable(GL_DEPTH_TEST));
  nodes->renderLabels(gl, managers, renderData);
  fbo->unbind();
  renderScreenQuad();

  if (showConstraintOverlay)
  {
    constraintBufferObject->bindTexture(GL_TEXTURE0);
    renderQuad(transparentQuad, Eigen::Matrix4f::Identity());
  }

  if (showBufferDebuggingViews)
    renderDebuggingViews(renderData);

  glAssert(gl->glEnable(GL_DEPTH_TEST));
}

void Scene::renderNodesWithHABufferIntoFBO(const RenderData &renderData)
{
  fbo->bind();
  glAssert(gl->glViewport(0, 0, width, height));
  glAssert(gl->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));

  haBuffer->clearAndPrepare(managers);

  nodes->render(gl, managers, renderData);

  managers->getObjectManager()->render(renderData);

  std::vector<float> zValues = labellingCoordinator->updateClusters();

  haBuffer->setLayerZValues(zValues);
  haBuffer->render(managers, renderData);

  picker->doPick(renderData.viewProjectionMatrix);

  fbo->unbind();
}

void Scene::renderDebuggingViews(const RenderData &renderData)
{
  for (int i = 0; i < fbo->getLayerCount(); ++i)
  {
    fbo->bindColorTexture(i, GL_TEXTURE0);
    auto transformation = Eigen::Affine3f(
        Eigen::Translation3f(Eigen::Vector3f(-0.8 + 0.4 * i, -0.4, 0)) *
        Eigen::Scaling(Eigen::Vector3f(0.2, 0.2, 1)));
    renderQuad(quad, transformation.matrix());
  }

  fbo->bindAccumulatedLayersTexture(GL_TEXTURE0);
  auto transformation =
      Eigen::Affine3f(Eigen::Translation3f(Eigen::Vector3f(
                          -0.8 + 0.4 * fbo->getLayerCount(), -0.4, 0)) *
                      Eigen::Scaling(Eigen::Vector3f(0.2, 0.2, 1)));
  renderQuad(quad, transformation.matrix());

  fbo->bindDepthTexture(GL_TEXTURE0);
  transformation =
      Eigen::Affine3f(Eigen::Translation3f(Eigen::Vector3f(-0.8, -0.8, 0)) *
                      Eigen::Scaling(Eigen::Vector3f(0.2, 0.2, 1)));
  renderQuad(quad, transformation.matrix());

  textureMapperManager->bindOcclusionTexture();
  transformation =
      Eigen::Affine3f(Eigen::Translation3f(Eigen::Vector3f(-0.4, -0.8, 0)) *
                      Eigen::Scaling(Eigen::Vector3f(0.2, 0.2, 1)));
  renderQuad(quad, transformation.matrix());

  int layerIndex = activeLayerNumber == 0 ? 0 : activeLayerNumber - 1;
  textureMapperManager->bindDistanceTransform(layerIndex);
  transformation =
      Eigen::Affine3f(Eigen::Translation3f(Eigen::Vector3f(0.0, -0.8, 0)) *
                      Eigen::Scaling(Eigen::Vector3f(0.2, 0.2, 1)));
  renderQuad(distanceTransformQuad, transformation.matrix());

  textureMapperManager->bindApollonius(layerIndex);
  transformation =
      Eigen::Affine3f(Eigen::Translation3f(Eigen::Vector3f(0.4, -0.8, 0)) *
                      Eigen::Scaling(Eigen::Vector3f(0.2, 0.2, 1)));
  renderQuad(quad, transformation.matrix());

  constraintBufferObject->bindTexture(GL_TEXTURE0);
  transformation =
      Eigen::Affine3f(Eigen::Translation3f(Eigen::Vector3f(0.8, -0.8, 0)) *
                      Eigen::Scaling(Eigen::Vector3f(0.2, 0.2, 1)));
  renderQuad(quad, transformation.matrix());
}

void Scene::renderQuad(std::shared_ptr<Graphics::ScreenQuad> quad,
                       Eigen::Matrix4f modelMatrix)
{
  RenderData renderData;
  renderData.modelMatrix = modelMatrix;

  quad->getShaderProgram()->bind();
  quad->getShaderProgram()->setUniform("textureSampler", 0);
  quad->renderImmediately(gl, managers, renderData);
}

void Scene::renderScreenQuad()
{
  if (activeLayerNumber == 0)
  {
    fbo->bindColorTexture(0, GL_TEXTURE0);
    fbo->bindColorTexture(1, GL_TEXTURE1);
    fbo->bindColorTexture(2, GL_TEXTURE2);
    fbo->bindColorTexture(3, GL_TEXTURE3);

    screenQuad->getShaderProgram()->setUniform("layer1", 0);
    screenQuad->getShaderProgram()->setUniform("layer2", 1);
    screenQuad->getShaderProgram()->setUniform("layer3", 2);
    screenQuad->getShaderProgram()->setUniform("layer4", 3);
    renderQuad(screenQuad, Eigen::Matrix4f::Identity());

    gl->glActiveTexture(GL_TEXTURE0);
  }
  else if (activeLayerNumber == 9)
  {
    fbo->bindAccumulatedLayersTexture(GL_TEXTURE0);
    renderQuad(quad, Eigen::Matrix4f::Identity());
  }
  else
  {
    fbo->bindColorTexture(activeLayerNumber - 1, GL_TEXTURE0);
    renderQuad(quad, Eigen::Matrix4f::Identity());
  }
}

void Scene::resize(int width, int height)
{
  this->width = width;
  this->height = height;

  shouldResize = true;

  labellingCoordinator->resize(width, height);
}

RenderData Scene::createRenderData()
{
  auto camera = getCamera();

  return RenderData(camera->getProjectionMatrix(), camera->getViewMatrix(),
                    camera->getPosition(), Eigen::Vector2f(width, height));
}

void Scene::pick(int id, Eigen::Vector2f position)
{
  if (picker.get())
    picker->pick(id, position);
}

void Scene::enableBufferDebuggingViews(bool enable)
{
  showBufferDebuggingViews = enable;
}

void Scene::enableConstraingOverlay(bool enable)
{
  showConstraintOverlay = enable;
}

std::shared_ptr<Camera> Scene::getCamera()
{
  return nodes->getCameraNode()->getCamera();
}

void Scene::setRenderLayer(int layerNumber)
{
  activeLayerNumber = layerNumber;
}

<commit_msg>Show saliency in debug output.<commit_after>#include "./scene.h"
#include <Eigen/Core>
#include <Eigen/Geometry>
#include <string>
#include <vector>
#include <map>
#include "./graphics/gl.h"
#include "./input/invoke_manager.h"
#include "./graphics/render_data.h"
#include "./graphics/managers.h"
#include "./graphics/volume_manager.h"
#include "./graphics/shader_program.h"
#include "./graphics/buffer_drawer.h"
#include "./camera_controllers.h"
#include "./nodes.h"
#include "./camera_node.h"
#include "./label_node.h"
#include "./eigen_qdebug.h"
#include "./utils/path_helper.h"
#include "./placement/to_gray.h"
#include "./placement/distance_transform.h"
#include "./placement/apollonius.h"
#include "./texture_mapper_manager.h"
#include "./constraint_buffer_object.h"
#include "./labelling_coordinator.h"

Scene::Scene(int layerCount, std::shared_ptr<InvokeManager> invokeManager,
             std::shared_ptr<Nodes> nodes, std::shared_ptr<Labels> labels,
             std::shared_ptr<LabellingCoordinator> labellingCoordinator,
             std::shared_ptr<TextureMapperManager> textureMapperManager)

  : nodes(nodes), labels(labels), labellingCoordinator(labellingCoordinator),
    frustumOptimizer(nodes), textureMapperManager(textureMapperManager)
{
  cameraControllers =
      std::make_shared<CameraControllers>(invokeManager, getCamera());

  fbo = std::make_shared<Graphics::FrameBufferObject>(layerCount);
  constraintBufferObject = std::make_shared<ConstraintBufferObject>();
  managers = std::make_shared<Graphics::Managers>();
}

Scene::~Scene()
{
  nodes->clear();
  qInfo() << "Destructor of Scene"
          << "Remaining managers instances" << managers.use_count();
}

void Scene::initialize()
{
  quad = std::make_shared<Graphics::ScreenQuad>(
      ":shader/pass.vert", ":shader/textureForRenderBuffer.frag");
  screenQuad = std::make_shared<Graphics::ScreenQuad>(
      ":shader/pass.vert", ":shader/combineLayers.frag");
  positionQuad = std::make_shared<Graphics::ScreenQuad>(
      ":shader/pass.vert", ":shader/positionRenderTarget.frag");
  distanceTransformQuad = std::make_shared<Graphics::ScreenQuad>(
      ":shader/pass.vert", ":shader/distanceTransform.frag");
  transparentQuad = std::make_shared<Graphics::ScreenQuad>(
      ":shader/pass.vert", ":shader/transparentOverlay.frag");

  fbo->initialize(gl, width, height);
  picker = std::make_unique<Picker>(fbo, gl, labels);
  picker->resize(width, height);
  constraintBufferObject->initialize(gl, textureMapperManager->getBufferSize(),
                                     textureMapperManager->getBufferSize());
  haBuffer =
      std::make_shared<Graphics::HABuffer>(Eigen::Vector2i(width, height));
  managers->getShaderManager()->initialize(gl, haBuffer);

  managers->getObjectManager()->initialize(gl, 128, 10000000);
  haBuffer->initialize(gl, managers);
  quad->initialize(gl, managers);
  screenQuad->initialize(gl, managers);
  positionQuad->initialize(gl, managers);
  distanceTransformQuad->initialize(gl, managers);
  transparentQuad->initialize(gl, managers);

  managers->getTextureManager()->initialize(gl, true, 8);

  textureMapperManager->createTextureMappersForLayers(fbo->getLayerCount());
  textureMapperManager->resize(width, height);
  textureMapperManager->initialize(gl, fbo, constraintBufferObject);

  auto drawer = std::make_shared<Graphics::BufferDrawer>(
      textureMapperManager->getBufferSize(),
      textureMapperManager->getBufferSize(), gl, managers->getShaderManager());

  labellingCoordinator->initialize(textureMapperManager->getBufferSize(),
                                   drawer, textureMapperManager, width, height);
}

void Scene::cleanup()
{
  labellingCoordinator->cleanup();

  textureMapperManager->cleanup();
}

void Scene::update(double frameTime, QSet<Qt::Key> keysPressed)
{
  auto camera = getCamera();

  if (camera->needsResizing())
    camera->resize(width, height);

  this->frameTime = frameTime;
  cameraControllers->update(camera, frameTime);

  frustumOptimizer.update(camera->getViewMatrix());
  camera->updateNearAndFarPlanes(frustumOptimizer.getNear(),
                                 frustumOptimizer.getFar());
  haBuffer->updateNearAndFarPlanes(frustumOptimizer.getNear(),
                                   frustumOptimizer.getFar());

  labellingCoordinator->update(frameTime, camera->getProjectionMatrix(),
                               camera->getViewMatrix(), activeLayerNumber);
}

void Scene::render()
{
  auto camera = getCamera();

  if (shouldResize)
  {
    camera->resize(width, height);
    fbo->resize(width, height);
    shouldResize = false;
  }

  glAssert(gl->glViewport(0, 0, width, height));
  glAssert(gl->glClearColor(0.0f, 0.0f, 0.0f, 0.0f));
  glAssert(gl->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));

  RenderData renderData = createRenderData();

  renderNodesWithHABufferIntoFBO(renderData);

  textureMapperManager->update();

  constraintBufferObject->bind();

  labellingCoordinator->updatePlacement();

  constraintBufferObject->unbind();

  glAssert(gl->glViewport(0, 0, width, height));

  fbo->bind();
  glAssert(gl->glDisable(GL_DEPTH_TEST));
  nodes->renderLabels(gl, managers, renderData);
  fbo->unbind();
  renderScreenQuad();

  if (showConstraintOverlay)
  {
    constraintBufferObject->bindTexture(GL_TEXTURE0);
    renderQuad(transparentQuad, Eigen::Matrix4f::Identity());
  }

  if (showBufferDebuggingViews)
    renderDebuggingViews(renderData);

  glAssert(gl->glEnable(GL_DEPTH_TEST));
}

void Scene::renderNodesWithHABufferIntoFBO(const RenderData &renderData)
{
  fbo->bind();
  glAssert(gl->glViewport(0, 0, width, height));
  glAssert(gl->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));

  haBuffer->clearAndPrepare(managers);

  nodes->render(gl, managers, renderData);

  managers->getObjectManager()->render(renderData);

  std::vector<float> zValues = labellingCoordinator->updateClusters();

  haBuffer->setLayerZValues(zValues);
  haBuffer->render(managers, renderData);

  picker->doPick(renderData.viewProjectionMatrix);

  fbo->unbind();
}

void Scene::renderDebuggingViews(const RenderData &renderData)
{
  for (int i = 0; i < fbo->getLayerCount(); ++i)
  {
    fbo->bindColorTexture(i, GL_TEXTURE0);
    auto transformation = Eigen::Affine3f(
        Eigen::Translation3f(Eigen::Vector3f(-0.8 + 0.4 * i, -0.4, 0)) *
        Eigen::Scaling(Eigen::Vector3f(0.2, 0.2, 1)));
    renderQuad(quad, transformation.matrix());
  }

  fbo->bindAccumulatedLayersTexture(GL_TEXTURE0);
  auto transformation =
      Eigen::Affine3f(Eigen::Translation3f(Eigen::Vector3f(
                          -0.8 + 0.4 * fbo->getLayerCount(), -0.4, 0)) *
                      Eigen::Scaling(Eigen::Vector3f(0.2, 0.2, 1)));
  renderQuad(quad, transformation.matrix());

  fbo->bindDepthTexture(GL_TEXTURE0);
  transformation =
      Eigen::Affine3f(Eigen::Translation3f(Eigen::Vector3f(-0.8, -0.8, 0)) *
                      Eigen::Scaling(Eigen::Vector3f(0.2, 0.2, 1)));
  renderQuad(quad, transformation.matrix());

  textureMapperManager->bindOcclusionTexture();
  transformation =
      Eigen::Affine3f(Eigen::Translation3f(Eigen::Vector3f(-0.4, -0.8, 0)) *
                      Eigen::Scaling(Eigen::Vector3f(0.2, 0.2, 1)));
  renderQuad(quad, transformation.matrix());

  int layerIndex = activeLayerNumber == 0 ? 0 : activeLayerNumber - 1;
  textureMapperManager->bindSaliencyTexture();
  transformation =
      Eigen::Affine3f(Eigen::Translation3f(Eigen::Vector3f(0.0, -0.8, 0)) *
                      Eigen::Scaling(Eigen::Vector3f(0.2, 0.2, 1)));
  renderQuad(distanceTransformQuad, transformation.matrix());

  textureMapperManager->bindApollonius(layerIndex);
  transformation =
      Eigen::Affine3f(Eigen::Translation3f(Eigen::Vector3f(0.4, -0.8, 0)) *
                      Eigen::Scaling(Eigen::Vector3f(0.2, 0.2, 1)));
  renderQuad(quad, transformation.matrix());

  constraintBufferObject->bindTexture(GL_TEXTURE0);
  transformation =
      Eigen::Affine3f(Eigen::Translation3f(Eigen::Vector3f(0.8, -0.8, 0)) *
                      Eigen::Scaling(Eigen::Vector3f(0.2, 0.2, 1)));
  renderQuad(quad, transformation.matrix());
}

void Scene::renderQuad(std::shared_ptr<Graphics::ScreenQuad> quad,
                       Eigen::Matrix4f modelMatrix)
{
  RenderData renderData;
  renderData.modelMatrix = modelMatrix;

  quad->getShaderProgram()->bind();
  quad->getShaderProgram()->setUniform("textureSampler", 0);
  quad->renderImmediately(gl, managers, renderData);
}

void Scene::renderScreenQuad()
{
  if (activeLayerNumber == 0)
  {
    fbo->bindColorTexture(0, GL_TEXTURE0);
    fbo->bindColorTexture(1, GL_TEXTURE1);
    fbo->bindColorTexture(2, GL_TEXTURE2);
    fbo->bindColorTexture(3, GL_TEXTURE3);

    screenQuad->getShaderProgram()->setUniform("layer1", 0);
    screenQuad->getShaderProgram()->setUniform("layer2", 1);
    screenQuad->getShaderProgram()->setUniform("layer3", 2);
    screenQuad->getShaderProgram()->setUniform("layer4", 3);
    renderQuad(screenQuad, Eigen::Matrix4f::Identity());

    gl->glActiveTexture(GL_TEXTURE0);
  }
  else if (activeLayerNumber == 9)
  {
    fbo->bindAccumulatedLayersTexture(GL_TEXTURE0);
    renderQuad(quad, Eigen::Matrix4f::Identity());
  }
  else
  {
    fbo->bindColorTexture(activeLayerNumber - 1, GL_TEXTURE0);
    renderQuad(quad, Eigen::Matrix4f::Identity());
  }
}

void Scene::resize(int width, int height)
{
  this->width = width;
  this->height = height;

  shouldResize = true;

  labellingCoordinator->resize(width, height);
}

RenderData Scene::createRenderData()
{
  auto camera = getCamera();

  return RenderData(camera->getProjectionMatrix(), camera->getViewMatrix(),
                    camera->getPosition(), Eigen::Vector2f(width, height));
}

void Scene::pick(int id, Eigen::Vector2f position)
{
  if (picker.get())
    picker->pick(id, position);
}

void Scene::enableBufferDebuggingViews(bool enable)
{
  showBufferDebuggingViews = enable;
}

void Scene::enableConstraingOverlay(bool enable)
{
  showConstraintOverlay = enable;
}

std::shared_ptr<Camera> Scene::getCamera()
{
  return nodes->getCameraNode()->getCamera();
}

void Scene::setRenderLayer(int layerNumber)
{
  activeLayerNumber = layerNumber;
}

<|endoftext|>


<commit_before>#pragma once

#include "debug.hpp"

#include <ostream>
#include <bitset>

namespace utki{

/**
 * @brief class representing a set of flags.
 * If you define an enumeration according to the following rules:
 * - enumeration is a 'enum class'.
 * - there is no direct assignment of values to enumeration items, i.e. values are in strict ascending order
 * - the very last item is enum_size
 *
 * For example:
 * @code
 * enum class my_enum{
 *     zeroth_item,
 *     first_item,
 *     second_item,
 *     third_item,
 *     ...
 *     enum_size
 * };
 *
 * @endcode
 * Then, the 'flags' can be used as follows:
 * @code
 * utki::flags<my_enum> fs;
 *
 * fs.set(my_enum::first_item, true).set(my_enum::third_item, true);
 *
 * if(fs.get(my_enum::first_item)){
 *     //first_item flag is set
 * }
 *
 * if(fs.get(my_enum::zeroth_item)){
 *     //Will not get here, since zeroth_item flag is not set
 * }
 *
 * @endcode
 */
template <class enum_type> class flags{
	static_assert(int(enum_type::enum_size) >= 0, "enumeration must define enum_size item");
	static_assert(unsigned(enum_type::enum_size) > 0, "enumeration must define at least one item");

	std::bitset<size_t(enum_type::enum_size)> bitset;
public:

	/**
	 * @brief Constructor.
	 * All flags are initialized to the same given value.
	 * @param initial_value - value which initializes all flags.
	 */
	flags(bool initial_value = false){
		if(initial_value){
			this->bitset.set();
		}
	}

	/**
	 * @brief Constructor.
	 * @param initially_set_flags - list of flags which will be set initially.
	 */
	flags(std::initializer_list<enum_type> initially_set_flags){
		for(auto v : initially_set_flags){
			this->bitset.set(size_t(v));
		}
	}

	/**
	 * @brief Constructor.
	 * Constructs a flags instance with only one flag set initially.
	 * @param e - flag to set.
	 */
	flags(enum_type e) :
			flags({e})
	{}

	constexpr size_t size()const noexcept{
		return this->bitset.size();
	}

	constexpr bool operator[](enum_type flag)const{
		return this->bitset[size_t(flag)];
	}

	typename std::bitset<size_t(enum_type::enum_size)>::reference operator[](enum_type flag){
		return this->bitset[size_t(flag)];
	}

	/**
	 * @brief Get value of a given flag.
	 * @param flag - flag to get value of.
	 * @return true if the flag is set.
	 * @return false otherwise.
	 */
	bool get(enum_type flag)const noexcept{
		ASSERT(flag < enum_type::enum_size)
		return this->bitset[size_t(flag)];
	}

	/**
	 * @brief Set value of a given flag.
	 * @param flag - flag to set value of.
	 * @param value - value to set.
	 * @return Reference to this Flags.
	 */
	flags& set(enum_type flag, bool value = true)noexcept{
		ASSERT(flag < enum_type::enum_size)
		this->bitset.set(size_t(flag), value);
		return *this;
	}

	/**
	 * @brief Set all flags to given value.
	 * @param value - value to set all flags to.
	 * @return Reference to this Flags.
	 */
	flags& set(bool value = true)noexcept{
		if(value){
			this->bitset.set();
		}else{
			this->bitset.reset();
		}
		return *this;
	}

	/**
	 * @brief Clear given flag.
	 * @param flag - flag to clear.
	 * @return Reference to this Flags.
	 */
	flags& clear(enum_type flag)noexcept{
		this->bitset.reset(size_t(flag));
		return *this;
	}

	/**
	 * @brief Clear all flags.
	 * @return Reference to this Flags.
	 */
	flags& clear()noexcept{
		this->bitset.reset();
		return *this;
	}

	/**
	 * @brief Check if all flags are cleared.
	 * @return true if all flags are cleared.
	 * @return false otherwise.
	 */
	bool is_clear()const noexcept{
		return this->bitset.none();
	}

	/**
	 * @brief Check if all flags are set.
	 * @return true if all flags are set.
	 * @return false otherwise.
	 */
	bool is_set()const noexcept{
		return this->bitset.all();
	}

	/**
	 * @brief Inverts all the flags.
	 * @return Reference to this Flags.
	 */
	flags& invert()noexcept{
		this->bitset.flip();
		return *this;
	}

	/**
	 * @brief Operator NOT.
	 * @return Inverted instance of Flags.
	 */
	flags operator~()const noexcept{
		return flags(*this).invert();
	}

	/**
	 * @brief Operator assignment AND.
	 * @param f - flags to perform AND operation with.
	 * @return Reference to this Flags.
	 */
	flags& operator&=(const flags& f)noexcept{
		this->bitset &= f.bitset;
		return *this;
	}

	/**
	 * @brief Operator AND.
	 * @param f - flags to perform AND operation with.
	 * @return Instance of Flags resulting from AND operation.
	 */
	flags operator&(const flags& f)const noexcept{
		return flags(*this).operator&=(f);
	}

	/**
	 * @brief Operator assignment OR.
	 * @param f - flags to perform OR operation with.
	 * @return Reference to this Flags.
	 */
	flags& operator|=(const flags& f)noexcept{
		this->bitset |= f.bitset;
		return *this;
	}

	/**
	 * @brief Operator OR.
	 * @param f - flags to perform OR operation with.
	 * @return Instance of Flags resulting from OR operation.
	 */
	flags operator|(const flags& f)const noexcept{
		return flags(*this).operator|=(f);
	}

	flags operator|(enum_type e)const noexcept{
		return flags(*this).set(e);
	}

	/**
	 * @brief Operator assignment XOR.
	 * @param f - flags to perform XOR operation with.
	 * @return Reference to this Flags.
	 */
	flags& operator^=(const flags& f)noexcept{
		this->bitset ^= f.bitset;
		return *this;
	}

	/**
	 * @brief Operator OR.
	 * @param f - flags to perform OR operation with.
	 * @return Instance of Flags resulting from OR operation.
	 */
	flags operator^(const flags& f)const noexcept{
		return flags(*this).operator^=(f);
	}

	friend std::ostream& operator<<(std::ostream& o, const flags& f){
		return o << f.bitset;
	}
};

/**
 * @brief Construct flags object.
 * @param initially_set_flags - list of flags which will be set initially.
 * @return newly created flags object.
 */
template <class T> flags<T> make_flags(std::initializer_list<T> initially_set_flags){
	return flags<T>(initially_set_flags);
}

}

template <class enum_type>
typename std::enable_if<
		std::is_enum<enum_type>::value && int(enum_type::enum_size) >= 0, // if type is enum and it has enum_size item
		utki::flags<enum_type>
	>::type
operator|(enum_type e1, enum_type e2){
	return {e1, e2};
}
<commit_msg>fix msvs build<commit_after>#pragma once

#include "debug.hpp"

#include <ostream>
#include <bitset>

namespace utki{

/**
 * @brief class representing a set of flags.
 * If you define an enumeration according to the following rules:
 * - enumeration is a 'enum class'.
 * - there is no direct assignment of values to enumeration items, i.e. values are in strict ascending order
 * - the very last item is enum_size
 *
 * For example:
 * @code
 * enum class my_enum{
 *     zeroth_item,
 *     first_item,
 *     second_item,
 *     third_item,
 *     ...
 *     enum_size
 * };
 *
 * @endcode
 * Then, the 'flags' can be used as follows:
 * @code
 * utki::flags<my_enum> fs;
 *
 * fs.set(my_enum::first_item, true).set(my_enum::third_item, true);
 *
 * if(fs.get(my_enum::first_item)){
 *     //first_item flag is set
 * }
 *
 * if(fs.get(my_enum::zeroth_item)){
 *     //Will not get here, since zeroth_item flag is not set
 * }
 *
 * @endcode
 */
template <class enum_type> class flags{
	static_assert(int(enum_type::enum_size) >= 0, "enumeration must define enum_size item");
	static_assert(unsigned(enum_type::enum_size) > 0, "enumeration must define at least one item");

	std::bitset<size_t(enum_type::enum_size)> bitset;
public:

	/**
	 * @brief Constructor.
	 * All flags are initialized to the same given value.
	 * @param initial_value - value which initializes all flags.
	 */
	flags(bool initial_value = false){
		if(initial_value){
			this->bitset.set();
		}
	}

	/**
	 * @brief Constructor.
	 * @param initially_set_flags - list of flags which will be set initially.
	 */
	flags(std::initializer_list<enum_type> initially_set_flags){
		for(auto v : initially_set_flags){
			this->bitset.set(size_t(v));
		}
	}

	/**
	 * @brief Constructor.
	 * Constructs a flags instance with only one flag set initially.
	 * @param e - flag to set.
	 */
	flags(enum_type e) :
			flags({e})
	{}

	constexpr size_t size()const noexcept{
		return this->bitset.size();
	}

	constexpr bool operator[](enum_type flag)const{
		return this->bitset[size_t(flag)];
	}

	typename std::bitset<size_t(enum_type::enum_size)>::reference operator[](enum_type flag){
		return this->bitset[size_t(flag)];
	}

	/**
	 * @brief Get value of a given flag.
	 * @param flag - flag to get value of.
	 * @return true if the flag is set.
	 * @return false otherwise.
	 */
	bool get(enum_type flag)const noexcept{
		ASSERT(flag < enum_type::enum_size)
		return this->bitset[size_t(flag)];
	}

	/**
	 * @brief Set value of a given flag.
	 * @param flag - flag to set value of.
	 * @param value - value to set.
	 * @return Reference to this Flags.
	 */
	flags& set(enum_type flag, bool value = true)noexcept{
		ASSERT(flag < enum_type::enum_size)
		this->bitset.set(size_t(flag), value);
		return *this;
	}

	/**
	 * @brief Set all flags to given value.
	 * @param value - value to set all flags to.
	 * @return Reference to this Flags.
	 */
	flags& set(bool value = true)noexcept{
		if(value){
			this->bitset.set();
		}else{
			this->bitset.reset();
		}
		return *this;
	}

	/**
	 * @brief Clear given flag.
	 * @param flag - flag to clear.
	 * @return Reference to this Flags.
	 */
	flags& clear(enum_type flag)noexcept{
		this->bitset.reset(size_t(flag));
		return *this;
	}

	/**
	 * @brief Clear all flags.
	 * @return Reference to this Flags.
	 */
	flags& clear()noexcept{
		this->bitset.reset();
		return *this;
	}

	/**
	 * @brief Check if all flags are cleared.
	 * @return true if all flags are cleared.
	 * @return false otherwise.
	 */
	bool is_clear()const noexcept{
		return this->bitset.none();
	}

	/**
	 * @brief Check if all flags are set.
	 * @return true if all flags are set.
	 * @return false otherwise.
	 */
	bool is_set()const noexcept{
		return this->bitset.all();
	}

	/**
	 * @brief Inverts all the flags.
	 * @return Reference to this Flags.
	 */
	flags& invert()noexcept{
		this->bitset.flip();
		return *this;
	}

	/**
	 * @brief Operator NOT.
	 * @return Inverted instance of Flags.
	 */
	flags operator~()const noexcept{
		return flags(*this).invert();
	}

	/**
	 * @brief Operator assignment AND.
	 * @param f - flags to perform AND operation with.
	 * @return Reference to this Flags.
	 */
	flags& operator&=(const flags& f)noexcept{
		this->bitset &= f.bitset;
		return *this;
	}

	/**
	 * @brief Operator AND.
	 * @param f - flags to perform AND operation with.
	 * @return Instance of Flags resulting from AND operation.
	 */
	flags operator&(const flags& f)const noexcept{
		return flags(*this).operator&=(f);
	}

	/**
	 * @brief Operator assignment OR.
	 * @param f - flags to perform OR operation with.
	 * @return Reference to this Flags.
	 */
	flags& operator|=(const flags& f)noexcept{
		this->bitset |= f.bitset;
		return *this;
	}

	/**
	 * @brief Operator OR.
	 * @param f - flags to perform OR operation with.
	 * @return Instance of Flags resulting from OR operation.
	 */
	flags operator|(const flags& f)const noexcept{
		return flags(*this).operator|=(f);
	}

	flags operator|(enum_type e)const noexcept{
		return flags(*this).set(e);
	}

	/**
	 * @brief Operator assignment XOR.
	 * @param f - flags to perform XOR operation with.
	 * @return Reference to this Flags.
	 */
	flags& operator^=(const flags& f)noexcept{
		this->bitset ^= f.bitset;
		return *this;
	}

	/**
	 * @brief Operator OR.
	 * @param f - flags to perform OR operation with.
	 * @return Instance of Flags resulting from OR operation.
	 */
	flags operator^(const flags& f)const noexcept{
		return flags(*this).operator^=(f);
	}

	friend std::ostream& operator<<(std::ostream& o, const flags& f){
		return o << f.bitset;
	}
};

/**
 * @brief Construct flags object.
 * @param initially_set_flags - list of flags which will be set initially.
 * @return newly created flags object.
 */
template <class T> flags<T> make_flags(std::initializer_list<T> initially_set_flags){
	return flags<T>(initially_set_flags);
}

}

template <class enum_type>
typename std::enable_if<
		std::is_enum<enum_type>::value,
		utki::flags<enum_type>
	>::type
operator|(enum_type e1, enum_type e2){
	return {e1, e2};
}
<|endoftext|>


<commit_before>#include "cinder/app/App.h"
#include "cinder/app/RendererGl.h"
#include "cinder/gl/gl.h"

#include "cinder/Capture.h"
#include "cinder/gl/Texture.h"
#include "cinder/gl/GlslProg.h"
#include "cinder/Log.h"
#include "cinder/gl/Fbo.h"
#include "cinder/gl/Shader.h"

#include "GridTexture.h"
#include "Landscape.h"
#include "IntroSequence.h"

#include "cinder/MotionManager.h"
#include "cinder/Signals.h"

using namespace ci;
using namespace ci::app;
using namespace std;

using namespace soso;

struct TouchInfo {
	TouchInfo() = default;
	TouchInfo( uint32_t iId, const vec2 &iStart, const vec2 &iPosition )
	: id( iId ),
		previous( iStart ),
		position( iPosition )
	{}

  uint32_t		id = 0;
  vec2				previous;
  vec2				position;
};

class SelfieSelfieApp : public App {
public:
	void setup() override;
	void update() override;
	void draw() override;

  void touchesBegan( TouchEvent event ) override;
  void touchesMoved( TouchEvent event ) override;
  void touchesEnded( TouchEvent event ) override;

	void updateCamera();
	void showLandscape();

private:
	CameraPersp				camera;
  CaptureRef				capture;

  GridTextureRef		gridTexture;
  Landscape					landscape;
	gl::BatchRef			cameraImage;
	IntroSequence			introduction;

  vector<TouchInfo> touches;
  ci::vec3					cameraOffset;
	float							cameraVelocity = 0.0f;

  bool							drawDebug = false;

	ci::signals::Connection	cameraUpdateConnection;
};

void SelfieSelfieApp::setup()
{
  CI_LOG_I("Setting up selfie_x_selfie");

  MotionManager::enable();

	introduction.setup( getAssetPath( "5" ) );
	introduction.setFinishFn( [this] { showLandscape(); } );
	cameraUpdateConnection = getSignalUpdate().connect( [this] { updateCamera(); } );
	cameraUpdateConnection.disable();

  GLint size;
  glGetIntegerv( GL_MAX_TEXTURE_SIZE, &size );
  CI_LOG_I( "Max texture size: " << size );

  auto target = vec3( 5, 0, 0 );
  camera.lookAt( vec3( 0 ), target, vec3( 0, 1, 0 ) );
  camera.setPerspective( 80, getWindowAspectRatio(), 0.1f, 50.0f );

  try {
    CI_LOG_I( "Initializing hardware camera." );
    auto front_facing_camera = ([] {
      auto &devices = Capture::getDevices();
      auto first_device = devices.front();
      for( auto device : devices ) {
        if( device->isFrontFacing() ) {
          return device;
        }
      }
      return first_device;
    }());

		#if defined(CINDER_ANDROID)
			capture = Capture::create( 640, 480, front_facing_camera );
		#else
    	capture = Capture::create( 480, 360, front_facing_camera );
    #endif
    capture->start();

    CI_LOG_I( "Creating Grid Texture" );
    gridTexture = make_shared<GridTexture>( ivec2( 320, 240 ), 12 );

    CI_LOG_I( "Setting up landscape geometry." );
    landscape.setup();
    landscape.setTextureUnits( 0, 1 );
    landscape.setGridSize( gridTexture->getGridDimensions() );
  }
  catch( ci::Exception &exc ) {
    CI_LOG_E( "Error using device camera: " << exc.what() );
  }

  auto err = gl::getError();
  if( err ) {
    CI_LOG_E( "Post-Setup gl error: " << gl::getErrorString(err) );
  }
}

void SelfieSelfieApp::touchesBegan( TouchEvent event )
{
  for( auto &t : event.getTouches() ) {
    touches.emplace_back( t.getId(), t.getPos(), t.getPos() );
  }

  if( touches.size() == 4 ) {
    drawDebug = ! drawDebug;
  }
	if( touches.size() == 3 ) {
		if( cameraUpdateConnection.isEnabled() ) {
			cameraUpdateConnection.disable();
		}
		else {
			cameraUpdateConnection.enable();
		}
	}
}

void SelfieSelfieApp::touchesMoved( TouchEvent event )
{
  for( auto &t : event.getTouches() ) {
    for( auto &s : touches ) {
      if( s.id == t.getId() ) {
				s.previous = s.position;
        s.position = t.getPos();
      }
    }
  }
}

void SelfieSelfieApp::touchesEnded( TouchEvent event )
{
  touches.erase( std::remove_if( touches.begin(), touches.end(), [&event] (const TouchInfo &s) {
    for( auto &t : event.getTouches() ) {
      if (t.getId() == s.id) {
        return true;
      }
    }
    return false;
  }), touches.end() );
}

void SelfieSelfieApp::showLandscape()
{
	cameraUpdateConnection.enable();
}

void SelfieSelfieApp::update()
{
  if( capture && capture->checkNewFrame() ) {
    gridTexture->update( *capture->getSurface() );

    auto err = gl::getError();
    if( err ) {
      CI_LOG_E( "Texture copy gl error: " << gl::getErrorString(err) );
    }
  }
}

void SelfieSelfieApp::updateCamera()
{
	if( touches.size() == 1 )
	{
		const auto forward = ([] {
			auto gravity = MotionManager::getGravityDirection();
			if( abs( gravity.x ) > abs( gravity.y ) ) {
				auto x = copysign( 1.0f, gravity.x );
				return vec3( x, 0, 0 );
			}
			else {
				auto y = copysign( 1.0f, gravity.y );
				return vec3( 0, - y, 0 );
			}
		}());

		auto &touch = touches.front();
		auto delta = vec3( touch.position - touch.previous, 0 );
		touch.previous = touch.position;

		auto amount = length( delta );
		auto dir = dot( normalize(delta), forward );

		if( isfinite( amount ) && isfinite( dir ) ) {
			cameraVelocity += amount * dir;
		}
	}

	auto ray = camera.getViewDirection();
	cameraOffset += ray * cameraVelocity * 0.0025f;
	cameraVelocity *= 0.86f;

	auto l = length(cameraOffset);
	auto maximum = 2.7f;
	if( l > maximum ) {
		cameraOffset *= (maximum / l);
	}
	camera.setEyePoint( cameraOffset );

	#if defined(CINDER_COCOA_TOUCH)
  if( MotionManager::isDataAvailable() ) {
    auto r = MotionManager::getRotation();
    camera.setOrientation( r );
  }
  #else
		auto r = MotionManager::getRotation();
    camera.setOrientation( r );
  #endif
}

void SelfieSelfieApp::draw()
{
	gl::clear( Color( 0, 0, 0 ) );

  {
    gl::enableDepthRead();
    gl::enableDepthWrite();
		gl::ScopedGlslProg prog( gl::getStockShader( gl::ShaderDef().texture(gridTexture->getTexture()->getTarget()) ) );

    gl::ScopedTextureBind tex0( gridTexture->getTexture(), 0 );
    gl::ScopedTextureBind tex1( gridTexture->getBlurredTexture(), 1 );
    gl::ScopedMatrices matrices;
    gl::setMatrices( camera );

		landscape.draw( gridTexture->getCurrentIndex() );

		auto mat = translate( vec3( 0, -4.0f, 0 ) );
		auto dims = vec2(gridTexture->getCellDimensions()) / gridTexture->getGridSize();
		auto offset = vec2(gridTexture->getIndexOffset( gridTexture->getCellDimensions(), gridTexture->getCurrentIndex() )) / gridTexture->getGridSize();
		auto rect = Rectf( -1.0f, -1.0f, 1.0f, 1.0f ).scaled( vec2( 1.333f, 1.0f ) ).scaled( 0.2f );
		auto half_pi = (float) M_PI / 2.0f;
		auto xf1 = translate( vec3( - 4.0f, 0.0f, 0.0f ) ) * rotate( - half_pi, vec3( 1, 0, 0 ) ) * rotate( half_pi, vec3( 0, 1, 0 ) );
		auto xf2 = translate( vec3( 4.0f, 0.0f, 0.0f ) ) * rotate( half_pi, vec3( 1, 0, 0 ) ) * rotate( - half_pi, vec3( 0, 1, 0 ) );

		if( false )
		{
			gl::ScopedModelMatrix m;
			gl::multModelMatrix( xf1 );
			gl::drawSolidRect( rect, offset, offset + dims );
		}

		{
			gl::ScopedModelMatrix m;
			gl::multModelMatrix( xf2 );
			gl::drawSolidRect( rect, offset, offset + dims );
		}

  }

  gl::disableDepthRead();

  if( drawDebug && gridTexture )
  {
    gl::setMatricesWindow( getWindowSize() );

    auto rect = Rectf(gridTexture->getTexture()->getBounds());
    auto window_rect = Rectf(getWindowBounds());
    auto window_rect_a = window_rect.scaled( vec2( 0.5f ) );
    auto window_rect_b = window_rect_a + vec2( window_rect_a.getWidth(), 0 );
    gl::draw( gridTexture->getTexture(), rect.getCenteredFit( window_rect_a, false ) );
    gl::draw( gridTexture->getBlurredTexture(), rect.getCenteredFit( window_rect_b, false ) );
  }

  /*
  // For confirming version changes, draw a different colored dot.
  gl::ScopedColor color( Color( 0.0f, 0.0f, 1.0f ) );
  gl::drawSolidCircle( vec2( 20.0f ), 10.0f );
  //*/

  auto err = gl::getError();
  if( err ) {
    CI_LOG_E( "Draw gl error: " << gl::getErrorString(err) );
  }
}

inline void prepareSettings( app::App::Settings *iSettings )
{
  iSettings->setMultiTouchEnabled();
}

CINDER_APP( SelfieSelfieApp, RendererGl, &prepareSettings )
<commit_msg>Replaced signal pausing with quat slerp.<commit_after>#include "cinder/app/App.h"
#include "cinder/app/RendererGl.h"
#include "cinder/gl/gl.h"

#include "cinder/Capture.h"
#include "cinder/gl/Texture.h"
#include "cinder/gl/GlslProg.h"
#include "cinder/Log.h"
#include "cinder/gl/Fbo.h"
#include "cinder/gl/Shader.h"

#include "GridTexture.h"
#include "Landscape.h"
#include "IntroSequence.h"

#include "cinder/MotionManager.h"
#include "cinder/Timeline.h"

using namespace ci;
using namespace ci::app;
using namespace std;

using namespace soso;

struct TouchInfo {
	TouchInfo() = default;
	TouchInfo( uint32_t iId, const vec2 &iStart, const vec2 &iPosition )
	: id( iId ),
		previous( iStart ),
		position( iPosition )
	{}

  uint32_t		id = 0;
  vec2				previous;
  vec2				position;
};

class SelfieSelfieApp : public App {
public:
	void setup() override;
	void update() override;
	void draw() override;

  void touchesBegan( TouchEvent event ) override;
  void touchesMoved( TouchEvent event ) override;
  void touchesEnded( TouchEvent event ) override;

	void updateCamera();
	void showLandscape();

private:
	CameraPersp				camera;
  CaptureRef				capture;

  GridTextureRef		gridTexture;
  Landscape					landscape;
	gl::BatchRef			cameraImage;
	IntroSequence			introduction;

  vector<TouchInfo> touches;
  ci::vec3					cameraOffset;
	float							cameraVelocity = 0.0f;

  bool							drawDebug = false;

	ci::Anim<float>		cameraWeight = 0.0f;
	quat							startOrientation;
};

void SelfieSelfieApp::setup()
{
  CI_LOG_I("Setting up selfie_x_selfie");

  MotionManager::enable();

  GLint size;
  glGetIntegerv( GL_MAX_TEXTURE_SIZE, &size );
  CI_LOG_I( "Max texture size: " << size );

  auto target = vec3( 5, 0, 0 );
  camera.lookAt( vec3( 0 ), target, vec3( 0, 1, 0 ) );
  camera.setPerspective( 80, getWindowAspectRatio(), 0.1f, 50.0f );
	startOrientation = camera.getOrientation();

  try {
    CI_LOG_I( "Initializing hardware camera." );
    auto front_facing_camera = ([] {
      auto &devices = Capture::getDevices();
      auto first_device = devices.front();
      for( auto device : devices ) {
        if( device->isFrontFacing() ) {
          return device;
        }
      }
      return first_device;
    }());

		#if defined(CINDER_ANDROID)
			capture = Capture::create( 640, 480, front_facing_camera );
		#else
    	capture = Capture::create( 480, 360, front_facing_camera );
    #endif
    capture->start();

    CI_LOG_I( "Creating Grid Texture" );
    gridTexture = make_shared<GridTexture>( ivec2( 320, 240 ), 12 );

    CI_LOG_I( "Setting up landscape geometry." );
    landscape.setup();
    landscape.setTextureUnits( 0, 1 );
    landscape.setGridSize( gridTexture->getGridDimensions() );
  }
  catch( ci::Exception &exc ) {
    CI_LOG_E( "Error using device camera: " << exc.what() );
  }

  auto err = gl::getError();
  if( err ) {
    CI_LOG_E( "Post-Setup gl error: " << gl::getErrorString(err) );
  }

	introduction.setup( getAssetPath( "5" ) );
	introduction.setFinishFn( [this] { showLandscape(); } );
	showLandscape();
}

void SelfieSelfieApp::touchesBegan( TouchEvent event )
{
  for( auto &t : event.getTouches() ) {
    touches.emplace_back( t.getId(), t.getPos(), t.getPos() );
  }

  if( touches.size() == 4 ) {
    drawDebug = ! drawDebug;
  }
}

void SelfieSelfieApp::touchesMoved( TouchEvent event )
{
  for( auto &t : event.getTouches() ) {
    for( auto &s : touches ) {
      if( s.id == t.getId() ) {
				s.previous = s.position;
        s.position = t.getPos();
      }
    }
  }
}

void SelfieSelfieApp::touchesEnded( TouchEvent event )
{
  touches.erase( std::remove_if( touches.begin(), touches.end(), [&event] (const TouchInfo &s) {
    for( auto &t : event.getTouches() ) {
      if (t.getId() == s.id) {
        return true;
      }
    }
    return false;
  }), touches.end() );
}

void SelfieSelfieApp::showLandscape()
{
	// Enable looking around with the gyro
	timeline().apply( &cameraWeight, 1.0f, 1.33f ).easeFn( EaseInOutCubic() ).delay( getElapsedSeconds() + 3.0f );
}

void SelfieSelfieApp::update()
{
	updateCamera();

  if( capture && capture->checkNewFrame() ) {
    gridTexture->update( *capture->getSurface() );

    auto err = gl::getError();
    if( err ) {
      CI_LOG_E( "Texture copy gl error: " << gl::getErrorString(err) );
    }
  }
}

void SelfieSelfieApp::updateCamera()
{
	if( touches.size() == 1 )
	{
		const auto forward = ([] {
			auto gravity = MotionManager::getGravityDirection();
			if( abs( gravity.x ) > abs( gravity.y ) ) {
				auto x = copysign( 1.0f, gravity.x );
				return vec3( x, 0, 0 );
			}
			else {
				auto y = copysign( 1.0f, gravity.y );
				return vec3( 0, - y, 0 );
			}
		}());

		auto &touch = touches.front();
		auto delta = vec3( touch.position - touch.previous, 0 );
		touch.previous = touch.position;

		auto amount = length( delta );
		auto dir = dot( normalize(delta), forward );

		if( isfinite( amount ) && isfinite( dir ) ) {
			cameraVelocity += amount * dir;
		}
	}

	auto ray = camera.getViewDirection();
	cameraOffset += ray * cameraVelocity * 0.0025f;
	cameraVelocity *= 0.86f;

	auto l = length(cameraOffset);
	auto maximum = 2.7f;
	if( l > maximum ) {
		cameraOffset *= (maximum / l);
	}
	camera.setEyePoint( cameraOffset );

	auto r = glm::slerp( startOrientation, MotionManager::getRotation(), cameraWeight.value() );
	camera.setOrientation( r );
}

void SelfieSelfieApp::draw()
{
	gl::clear( Color( 0, 0, 0 ) );

  {
    gl::enableDepthRead();
    gl::enableDepthWrite();
		gl::ScopedGlslProg prog( gl::getStockShader( gl::ShaderDef().texture(gridTexture->getTexture()->getTarget()) ) );

    gl::ScopedTextureBind tex0( gridTexture->getTexture(), 0 );
    gl::ScopedTextureBind tex1( gridTexture->getBlurredTexture(), 1 );
    gl::ScopedMatrices matrices;
    gl::setMatrices( camera );

		landscape.draw( gridTexture->getCurrentIndex() );

		auto mat = translate( vec3( 0, -4.0f, 0 ) );
		auto dims = vec2(gridTexture->getCellDimensions()) / gridTexture->getGridSize();
		auto offset = vec2(gridTexture->getIndexOffset( gridTexture->getCellDimensions(), gridTexture->getCurrentIndex() )) / gridTexture->getGridSize();
		auto rect = Rectf( -1.0f, -1.0f, 1.0f, 1.0f ).scaled( vec2( 1.333f, 1.0f ) ).scaled( 0.2f );
		auto half_pi = (float) M_PI / 2.0f;
		auto xf1 = translate( vec3( - 4.0f, 0.0f, 0.0f ) ) * rotate( - half_pi, vec3( 1, 0, 0 ) ) * rotate( half_pi, vec3( 0, 1, 0 ) );
		auto xf2 = translate( vec3( 4.0f, 0.0f, 0.0f ) ) * rotate( half_pi, vec3( 1, 0, 0 ) ) * rotate( - half_pi, vec3( 0, 1, 0 ) );

		if( false )
		{
			gl::ScopedModelMatrix m;
			gl::multModelMatrix( xf1 );
			gl::drawSolidRect( rect, offset, offset + dims );
		}

		{
			gl::ScopedModelMatrix m;
			gl::multModelMatrix( xf2 );
			gl::drawSolidRect( rect, offset, offset + dims );
		}

  }

  gl::disableDepthRead();

  if( drawDebug && gridTexture )
  {
    gl::setMatricesWindow( getWindowSize() );

    auto rect = Rectf(gridTexture->getTexture()->getBounds());
    auto window_rect = Rectf(getWindowBounds());
    auto window_rect_a = window_rect.scaled( vec2( 0.5f ) );
    auto window_rect_b = window_rect_a + vec2( window_rect_a.getWidth(), 0 );
    gl::draw( gridTexture->getTexture(), rect.getCenteredFit( window_rect_a, false ) );
    gl::draw( gridTexture->getBlurredTexture(), rect.getCenteredFit( window_rect_b, false ) );
  }

  /*
  // For confirming version changes, draw a different colored dot.
  gl::ScopedColor color( Color( 0.0f, 0.0f, 1.0f ) );
  gl::drawSolidCircle( vec2( 20.0f ), 10.0f );
  //*/

  auto err = gl::getError();
  if( err ) {
    CI_LOG_E( "Draw gl error: " << gl::getErrorString(err) );
  }
}

inline void prepareSettings( app::App::Settings *iSettings )
{
  iSettings->setMultiTouchEnabled();
}

CINDER_APP( SelfieSelfieApp, RendererGl, &prepareSettings )
<|endoftext|>


<commit_before>#include "ObjectStore.hpp"
#include "conf/conf.hpp"
#include <functional>
#include <iostream>
#include <sstream>

#define NUM_APP_ARGS (1)

int main(int argc, char** argv) {
    if((argc < (NUM_APP_ARGS + 1)) || ((argc > (NUM_APP_ARGS + 1)) && strcmp("--", argv[argc - NUM_APP_ARGS - 1]))) {
        std::cerr << "Usage: " << argv[0] << " [ derecho-config-list -- ] <aio|bio>" << std::endl;
        return -1;
    }

    bool use_aio = false;
    if(strcmp("aio", argv[argc - NUM_APP_ARGS]) == 0) {
        use_aio = true;
    } else if(strcmp("bio", argv[1]) != 0) {
        std::cerr << "unrecognized argument:" << argv[argc - NUM_APP_ARGS] << ". Using bio (blocking io) instead." << std::endl;
    }

    derecho::Conf::initialize(argc, argv);
    std::cout << "Starting object store service..." << std::endl;
    // oss - objectstore service
    auto& oss = objectstore::IObjectStoreService::getObjectStoreService(argc, argv,
                                                                        [&](const objectstore::OID& oid, const objectstore::Object& object) {
                                                                            std::cout << "watcher: " << oid << "->" << object << std::endl;
                                                                        });
    // print some message
    std::cout << "Object store service started. \n\tIs replica:" << std::boolalpha << oss.isReplica()
              << "\n\tUsing aio API:" << use_aio
              << std::noboolalpha << "." << std::endl;

    bool bNextCommand = true;  // waiting for the next command.

    // prepare the commandline tool:
    std::map<std::string, std::pair<std::string, std::function<bool(std::string&)>>> commands = {
            {"put",  // command
             {
                     "put <oid> <string>",  // help info
                     [&oss, use_aio](std::string args) -> bool {
                         std::istringstream ss(args);
                         std::string oid, odata;
                         ss >> oid >> odata;
                         objectstore::Object object(std::stol(oid), odata.c_str(), odata.length() + 1);
                         try {
                             if(use_aio) {
                                 // asynchronous api
                                 derecho::rpc::QueryResults<persistent::version_t> results = oss.aio_put(object);
                                 decltype(results)::ReplyMap& replies = results.get();
                                 for(auto& reply_pair : replies) {
                                     std::cout << reply_pair.first << reply_pair.second.get() << std::endl;
                                 }
                             } else {
                                 // synchronous api
                                 std::cout << "bio put:" << std::boolalpha << oss.bio_put(object)
                                           << std::noboolalpha << std::endl;
                             }
                         } catch(...) {
                             return false;
                         }
                         return true;
                     }}},  // put
            {
                    "get",  // command
                    {
                            "get <oid> [version]",  // help info
                            [&oss](std::string& args) -> bool {
                                char *argcopy = strdup(args.c_str());
                                char *token = std::strtok(argcopy, " ");
                                uint64_t oid = std::stol(token);
                                version_t ver = INVALID_VERSION;
                                if (token = std::strtok(NULL, " ")) {
                                    ver = std::stol(token);
                                }
                                try {
                                    objectstore::Object obj = oss.bio_get(oid,ver);
                                    std::cout << obj << std::endl;
                                } catch(...) {
                                    free(argcopy);
                                    return false;
                                }
                                free(argcopy);
                                return true;
                            }}},
            {"remove",  // command
             {
                     "remove <oid>",  // help info
                     [&oss](std::string& args) -> bool {
                         try {
                             return oss.bio_remove(std::stol(args));
                         } catch(...) {
                             return false;
                         }
                     }}},
            {"leave",  // command
             {
                     "leave",  // help info
                     [&oss, &bNextCommand](std::string&) -> bool {
                         oss.leave();
                         bNextCommand = false;
                         return true;
                     }}}};

    std::function<void()> help = [commands]() {
        std::cout << "Commands:" << std::endl;
        for(auto& cmd_entry : commands) {
            std::cout << "\t" << cmd_entry.second.first << std::endl;
        }
    };

    help();
    // main command loop
    while(bNextCommand) {
        std::string line;
        std::cout << "cmd>";
        std::getline(std::cin, line, '\n');
        std::string::size_type first_space_pos = line.find(' ');
        std::string command;
        std::string arguments;
        if(first_space_pos == std::string::npos) {
            command = line;
        } else {
            command = line.substr(0, first_space_pos);
            arguments = line.substr(first_space_pos + 1);
        }
        if(commands.find(command) == commands.end()) {
            help();
        } else {
            bool bRet = commands[command].second(arguments);
            std::cout << "Result:" << std::boolalpha << bRet << std::noboolalpha
                      << std::endl;
        }
    }
    return 0;
}
<commit_msg>minor bugfix to objectstore tester.<commit_after>#include "ObjectStore.hpp"
#include "conf/conf.hpp"
#include <functional>
#include <iostream>
#include <sstream>

#define NUM_APP_ARGS (1)

int main(int argc, char** argv) {
    if((argc < (NUM_APP_ARGS + 1)) || ((argc > (NUM_APP_ARGS + 1)) && strcmp("--", argv[argc - NUM_APP_ARGS - 1]))) {
        std::cerr << "Usage: " << argv[0] << " [ derecho-config-list -- ] <aio|bio>" << std::endl;
        return -1;
    }

    bool use_aio = false;
    if(strcmp("aio", argv[argc - NUM_APP_ARGS]) == 0) {
        use_aio = true;
    } else if(strcmp("bio", argv[1]) != 0) {
        std::cerr << "unrecognized argument:" << argv[argc - NUM_APP_ARGS] << ". Using bio (blocking io) instead." << std::endl;
    }

    derecho::Conf::initialize(argc, argv);
    std::cout << "Starting object store service..." << std::endl;
    // oss - objectstore service
    auto& oss = objectstore::IObjectStoreService::getObjectStoreService(argc, argv,
                                                                        [&](const objectstore::OID& oid, const objectstore::Object& object) {
                                                                            std::cout << "watcher: " << oid << "->" << object << std::endl;
                                                                        });
    // print some message
    std::cout << "Object store service started. \n\tIs replica:" << std::boolalpha << oss.isReplica()
              << "\n\tUsing aio API:" << use_aio
              << std::noboolalpha << "." << std::endl;

    bool bNextCommand = true;  // waiting for the next command.

    // prepare the commandline tool:
    std::map<std::string, std::pair<std::string, std::function<bool(std::string&)>>> commands = {
            {"put",  // command
             {
                     "put <oid> <string>",  // help info
                     [&oss, use_aio](std::string args) -> bool {
                         std::istringstream ss(args);
                         std::string oid, odata;
                         ss >> oid >> odata;
                         objectstore::Object object(std::stol(oid), odata.c_str(), odata.length() + 1);
                         try {
                             if(use_aio) {
                                 // asynchronous api
                                 derecho::rpc::QueryResults<persistent::version_t> results = oss.aio_put(object);
                                 decltype(results)::ReplyMap& replies = results.get();
                                 std::cout << "aio returns:" << std::endl;
                                 for(auto& reply_pair : replies) {
                                     std::cout << reply_pair.first << ":" << reply_pair.second.get() << std::endl;
                                 }
                             } else {
                                 // synchronous api
                                 std::cout << "version:" << oss.bio_put(object) << std::endl;
                             }
                         } catch(...) {
                             return false;
                         }
                         return true;
                     }}},  // put
            {"get",        // command
             {
                     "get <oid> [version]",  // help info
                     [&oss, use_aio](std::string& args) -> bool {
                         char* argcopy = strdup(args.c_str());
                         char* token = std::strtok(argcopy, " ");
                         uint64_t oid = std::stol(token);
                         version_t ver = INVALID_VERSION;
                         if((token = std::strtok(nullptr, " ")) != nullptr) {
                             ver = std::stol(token);
                         }
                         try {
                             if(use_aio) {
                                 // asynchronous api
                                 derecho::rpc::QueryResults<const objectstore::Object> results = oss.aio_get(oid, ver);
                                 decltype(results)::ReplyMap& replies = results.get();
                                 std::cout << "aio returns:" << std::endl;
                                 for(auto& reply_pair : replies) {
                                     std::cout << reply_pair.first << ":" << reply_pair.second.get() << std::endl;
                                 }
                             } else {
                                 // synchronous api
                                 objectstore::Object obj = oss.bio_get(oid, ver);
                                 std::cout << obj << std::endl;
                             }
                         } catch(...) {
                             free(argcopy);
                             return false;
                         }
                         free(argcopy);
                         return true;
                     }}},
            {"remove",  // command
             {
                     "remove <oid>",  // help info
                     [&oss, use_aio](std::string& args) -> bool {
                         try {
                             if(use_aio) {
                                 // asynchronous api
                                 derecho::rpc::QueryResults<version_t> results = oss.aio_remove(std::stol(args));
                                 decltype(results)::ReplyMap& replies = results.get();
                                 std::cout << "aio returns:" << std::endl;
                                 for(auto& reply_pair : replies) {
                                     std::cout << reply_pair.first << ":" << reply_pair.second.get() << std::endl;
                                 }
                             } else {
                                 version_t ver = oss.bio_remove(std::stol(args));
                                 std::cout << "version:" << ver << std::endl;
                             }
                         } catch(...) {
                             return false;
                         }
                         return true;
                     }}},
            {"leave",  // command
             {
                     "leave",  // help info
                     [&oss, &bNextCommand](std::string&) -> bool {
                         oss.leave();
                         bNextCommand = false;
                         return true;
                     }}}};

    std::function<void()> help = [commands]() {
        std::cout << "Commands:" << std::endl;
        for(auto& cmd_entry : commands) {
            std::cout << "\t" << cmd_entry.second.first << std::endl;
        }
    };

    help();
    // main command loop
    while(bNextCommand) {
        std::string line;
        std::cout << "cmd>";
        std::getline(std::cin, line, '\n');
        std::string::size_type first_space_pos = line.find(' ');
        std::string command;
        std::string arguments;
        if(first_space_pos == std::string::npos) {
            command = line;
        } else {
            command = line.substr(0, first_space_pos);
            arguments = line.substr(first_space_pos + 1);
        }
        if(commands.find(command) == commands.end()) {
            help();
        } else {
            bool bRet = commands[command].second(arguments);
            std::cout << "Result:" << std::boolalpha << bRet << std::noboolalpha
                      << std::endl;
        }
    }
    return 0;
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011-2013.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "FunctionContext.hpp"
#include "GlobalContext.hpp"
#include "Variable.hpp"

#include "mtac/Argument.hpp"
#include "mtac/local_cse.hpp"
#include "mtac/Function.hpp"
#include "mtac/Quadruple.hpp"
#include "mtac/Utils.hpp"

using namespace eddic;

namespace {

struct expression {
    std::size_t uid;
    mtac::Argument arg1;
    mtac::Argument arg2;
    mtac::Operator op;
    std::shared_ptr<Variable> tmp;
    std::shared_ptr<const Type> type;

    expression(std::size_t uid, mtac::Argument arg1, mtac::Argument arg2, mtac::Operator op, std::shared_ptr<Variable> tmp, std::shared_ptr<const Type> type) : uid(uid), arg1(arg1), arg2(arg2), op(op), tmp(tmp), type(type) {
        //Nothing
    }
};

bool is_interesting(mtac::Quadruple& quadruple){
    if(quadruple.op == mtac::Operator::DOT){
        auto var = boost::get<std::shared_ptr<Variable>>(*quadruple.arg1);

        return !var->type()->is_pointer();
    }

    if(boost::get<std::shared_ptr<Variable>>(&*quadruple.arg1)){
        return true;
    }

    if(boost::get<std::shared_ptr<Variable>>(&*quadruple.arg2)){
        return true;
    }

    return false;
}

bool are_equivalent(mtac::Quadruple& quadruple, expression& exp){
    if(exp.op == quadruple.op && exp.type == quadruple.result->type()){
        if(exp.arg1 == *quadruple.arg1 && exp.arg2 == *quadruple.arg2){
            return true;
        } else if(mtac::is_distributive(quadruple.op) && exp.arg1 == *quadruple.arg2 && exp.arg2 == *quadruple.arg1){
            return true;
        }
    }

    return false;
}

}

bool mtac::local_cse::operator()(mtac::Function& function){
    bool optimized = false;

    for(auto& block : function){
        auto it = block->statements.begin();

        std::vector<expression> expressions;

        while(it != block->statements.end()){
            auto& quadruple = *it;

            if(mtac::is_expression(quadruple.op) && is_interesting(quadruple)){
                bool found = false;

                for(auto& exp : expressions){
                    if(are_equivalent(quadruple, exp)){
                        found = true;

                        function.context->global()->stats().inc_counter("local_cse");

                        optimized = true;

                        mtac::Operator op;
                        if(exp.op == mtac::Operator::DOT){
                            op = mtac::Operator::ASSIGN;
                        } else if(exp.op <= mtac::Operator::ADD && exp.op <= mtac::Operator::MOD){
                            op = mtac::Operator::ASSIGN;
                        } else if(exp.op <= mtac::Operator::FADD && exp.op <= mtac::Operator::FDIV){
                            op = mtac::Operator::FASSIGN;
                        }

                        if(!exp.tmp){
                            auto tmp = function.context->new_temporary(exp.type);
                            exp.tmp = tmp;

                            auto current_uid = quadruple.uid();

                            quadruple.op = op;
                            quadruple.arg1 = tmp;
                            quadruple.arg2.reset();

                            auto old_it = block->statements.begin();
                            while(old_it->uid() != exp.uid){
                                ++old_it;
                            }

                            old_it->op = op;
                            old_it->arg1 = tmp;
                            old_it->arg2.reset();

                            block->statements.insert(old_it, mtac::Quadruple(tmp, exp.arg1, exp.op, exp.arg2));

                            it = block->statements.begin();
                            while(it->uid() != current_uid){
                                ++it;
                            }
                        } else {
                            quadruple.op = op;
                            quadruple.arg1 = exp.tmp;
                            quadruple.arg2.reset();
                        }

                        break;
                    }
                }

                if(!found){
                    expressions.emplace_back(quadruple.uid(), *quadruple.arg1, *quadruple.arg2, quadruple.op,
                            nullptr, quadruple.result->type());
                }
            }

            if(mtac::erase_result(quadruple.op)){
                auto eit = iterate(expressions);

                while(eit.has_next()){
                    auto& expression = *eit;

                    if(auto* ptr = boost::get<std::shared_ptr<Variable>>(&expression.arg1)){
                        if(quadruple.result == *ptr){
                            eit.erase();
                            continue;
                        }
                    }

                    if(auto* ptr = boost::get<std::shared_ptr<Variable>>(&expression.arg2)){
                        if(quadruple.result == *ptr){
                            eit.erase();
                            continue;
                        }
                    }

                    ++eit;
                }
            }

            ++it;
        }
    }

    return optimized;
}
<commit_msg>DOT_ASSIGN can modify the state of the variable<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011-2013.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "FunctionContext.hpp"
#include "GlobalContext.hpp"
#include "Variable.hpp"

#include "mtac/Argument.hpp"
#include "mtac/local_cse.hpp"
#include "mtac/Function.hpp"
#include "mtac/Quadruple.hpp"
#include "mtac/Utils.hpp"

using namespace eddic;

namespace {

struct expression {
    std::size_t uid;
    mtac::Argument arg1;
    mtac::Argument arg2;
    mtac::Operator op;
    std::shared_ptr<Variable> tmp;
    std::shared_ptr<const Type> type;

    expression(std::size_t uid, mtac::Argument arg1, mtac::Argument arg2, mtac::Operator op, std::shared_ptr<Variable> tmp, std::shared_ptr<const Type> type) : uid(uid), arg1(arg1), arg2(arg2), op(op), tmp(tmp), type(type) {
        //Nothing
    }
};

bool is_interesting(mtac::Quadruple& quadruple){
    if(quadruple.op == mtac::Operator::DOT){
        auto var = boost::get<std::shared_ptr<Variable>>(*quadruple.arg1);

        return !var->type()->is_pointer();
    }

    if(boost::get<std::shared_ptr<Variable>>(&*quadruple.arg1)){
        return true;
    }

    if(boost::get<std::shared_ptr<Variable>>(&*quadruple.arg2)){
        return true;
    }

    return false;
}

bool are_equivalent(mtac::Quadruple& quadruple, expression& exp){
    if(exp.op == quadruple.op && exp.type == quadruple.result->type()){
        if(exp.arg1 == *quadruple.arg1 && exp.arg2 == *quadruple.arg2){
            return true;
        } else if(mtac::is_distributive(quadruple.op) && exp.arg1 == *quadruple.arg2 && exp.arg2 == *quadruple.arg1){
            return true;
        }
    }

    return false;
}

}

bool mtac::local_cse::operator()(mtac::Function& function){
    bool optimized = false;

    for(auto& block : function){
        auto it = block->statements.begin();

        std::vector<expression> expressions;

        while(it != block->statements.end()){
            auto& quadruple = *it;

            if(mtac::is_expression(quadruple.op) && is_interesting(quadruple)){
                bool found = false;

                for(auto& exp : expressions){
                    if(are_equivalent(quadruple, exp)){
                        found = true;

                        function.context->global()->stats().inc_counter("local_cse");

                        optimized = true;

                        mtac::Operator op;
                        if(exp.op == mtac::Operator::DOT){
                            op = mtac::Operator::ASSIGN;
                        } else if(exp.op <= mtac::Operator::ADD && exp.op <= mtac::Operator::MOD){
                            op = mtac::Operator::ASSIGN;
                        } else if(exp.op <= mtac::Operator::FADD && exp.op <= mtac::Operator::FDIV){
                            op = mtac::Operator::FASSIGN;
                        }

                        if(!exp.tmp){
                            auto tmp = function.context->new_temporary(exp.type);
                            exp.tmp = tmp;

                            auto current_uid = quadruple.uid();

                            quadruple.op = op;
                            quadruple.arg1 = tmp;
                            quadruple.arg2.reset();

                            auto old_it = block->statements.begin();
                            while(old_it->uid() != exp.uid){
                                ++old_it;
                            }

                            old_it->op = op;
                            old_it->arg1 = tmp;
                            old_it->arg2.reset();

                            block->statements.insert(old_it, mtac::Quadruple(tmp, exp.arg1, exp.op, exp.arg2));

                            it = block->statements.begin();
                            while(it->uid() != current_uid){
                                ++it;
                            }
                        } else {
                            quadruple.op = op;
                            quadruple.arg1 = exp.tmp;
                            quadruple.arg2.reset();
                        }

                        break;
                    }
                }

                if(!found){
                    expressions.emplace_back(quadruple.uid(), *quadruple.arg1, *quadruple.arg2, quadruple.op,
                            nullptr, quadruple.result->type());
                }
            }

            auto op = quadruple.op;
            if(mtac::erase_result(op) || op == mtac::Operator::DOT_ASSIGN || op == mtac::Operator::DOT_FASSIGN || op == mtac::Operator::DOT_PASSIGN){
                auto eit = iterate(expressions);

                while(eit.has_next()){
                    auto& expression = *eit;

                    if(auto* ptr = boost::get<std::shared_ptr<Variable>>(&expression.arg1)){
                        if(quadruple.result == *ptr){
                            eit.erase();
                            continue;
                        }
                    }

                    if(auto* ptr = boost::get<std::shared_ptr<Variable>>(&expression.arg2)){
                        if(quadruple.result == *ptr){
                            eit.erase();
                            continue;
                        }
                    }

                    ++eit;
                }
            }

            ++it;
        }
    }

    return optimized;
}
<|endoftext|>


<commit_before>#include "defs.h"
#include "search.h"
#include "eval.h"
#include "movegen.h"
#include "transptable.h"
#include <string>
#include <algorithm>
#include <time.h>
#include <iostream>
#include <functional>

Search::Search(const Board& board, bool logUci) {
  _logUci = logUci;
  _board = board;
  _bestScore = 0;
}

void Search::perform(int depth) {
  _rootMax(_board, depth);

  if (_logUci) {
    _logUciInfo(_pv, depth, _bestMove, _bestScore, _nodes);
  }
}

void Search::_logUciInfo(const MoveList& pv, int depth, Move bestMove, int bestScore, int nodes) {
  std::string pvString;
  for(auto move : pv) {
    pvString += move.getNotation() + " ";
  }

  std::string scoreString;
  if (bestScore == INF) {
    scoreString = "mate " + std::to_string(pv.size());
  } else if (_bestScore == -INF) {
    scoreString = "mate -" + std::to_string(pv.size());
  } else {
    scoreString = "cp " + std::to_string(bestScore);
  }

  std::cout << "info depth " + std::to_string(depth) + " ";
  std::cout << "nodes " + std::to_string(nodes) + " ";
  std::cout << "score " + scoreString + " ";
  std::cout << "pv " + pvString;
  std::cout << std::endl;
}

Move Search::getBestMove() {
  return _bestMove;
}

int Search::getBestScore() {
  return _bestScore;
}

void Search::_rootMax(const Board& board, int depth) {
  MoveGen movegen(board);
  MoveList legalMoves = movegen.getLegalMoves();
  _scoreMoves(board, legalMoves);
  _sortMovesByValue(legalMoves);

  _nodes = 0;

  _pv = MoveList();
  MoveList pv;

  int alpha = -INF;
  int beta = INF;

  int currScore;

  Move bestMove;
  Board movedBoard;
  for (auto move : legalMoves) {
    movedBoard = board;
    movedBoard.doMove(move);

    currScore = -_negaMax(movedBoard, depth-1, -beta, -alpha, pv);

    if (currScore > alpha) {
      bestMove = move;
      alpha = currScore;

      MoveList newMoves;
      newMoves.push_back(move);

      for (auto move : pv) {
        newMoves.push_back(move);
      }
      _pv = newMoves;

      // Break if we've found a checkmate
      if (currScore == INF) {
        break;
      }
    }
  }

  // If we couldn't find a path other than checkmate, just pick the first legal move
  if (bestMove.getFlags() & Move::NULL_MOVE) {
    bestMove = legalMoves.at(0);
  }

  TranspTableEntry ttEntry(alpha, depth, TranspTableEntry::EXACT, bestMove);
  _tt.set(board.getZKey(), ttEntry);

  _bestMove = bestMove;
  _bestScore = alpha;
}

void Search::_scoreMoves(const Board& board, MoveList& moveList) {
  const TranspTableEntry* ttEntry = _tt.getEntry(board.getZKey());
  Move pvMove;
  if (ttEntry) {
    pvMove = ttEntry->getBestMove();
  }

  for (auto &move : moveList) {
    Board tempBoard = board;
    tempBoard.doMove(move);

    // PV move always first
    if (move == pvMove) {
      move.setValue(INF);
      continue;
    }

    // Transposition table lookups considered second (dynamic move ordering)
    const TranspTableEntry *ttEntry = _tt.getEntry(tempBoard.getZKey());
    if (ttEntry && ((ttEntry->getFlag() == TranspTableEntry::EXACT) || (ttEntry->getFlag() == TranspTableEntry::LOWER_BOUND))) {
      // Score is negated since score is for opponent
      move.setValue(-ttEntry->getScore());
    } else {
      // Static move ordering (considers promotions and MVV/LVA captures)
      bool hasStaticTraits = move.getFlags() & (Move::PROMOTION | Move::CAPTURE);
      int value = 0;
      if (move.getFlags() & Move::PROMOTION) {
        value += Eval::getMaterialValue(move.getPromotionPieceType()) - Eval::getMaterialValue(PAWN);
      }
      if (move.getFlags() & Move::CAPTURE) {
        value += Eval::getMaterialValue(move.getCapturedPieceType()) - Eval::getMaterialValue(move.getPieceType());
      }

      if (hasStaticTraits) {
        move.setValue(value);
      } else {
        move.setValue(-INF);
      }
    }
  }
}

void Search::_scoreMovesQsearch(MoveList& moveList) {
  for (auto &move : moveList) {
    if (move.getFlags() & Move::CAPTURE) {
      move.setValue(Eval::getMaterialValue(move.getCapturedPieceType()) - Eval::getMaterialValue(move.getPieceType()));
    } else {
      move.setValue(-INF);
    }
  }
  _sortMovesByValue(moveList);
}

void Search::_sortMovesByValue(MoveList& moveList) {
  std::sort(moveList.begin(), moveList.end(),
    std::bind(&Search::_compareMovesValue, this, std::placeholders::_1, std::placeholders::_2));
}

bool Search::_compareMovesValue(Move a, Move b) {
  return a.getValue() > b.getValue();
}

int Search::_negaMax(const Board& board, int depth, int alpha, int beta, MoveList &ppv) {
  int alphaOrig = alpha;

  const TranspTableEntry* ttEntry = _tt.getEntry(board.getZKey());
  // Check transposition table cache
  if (ttEntry && (ttEntry->getDepth() >= depth)) {
    switch(ttEntry->getFlag()) {
      case TranspTable::EXACT:
        return ttEntry->getScore();
      case TranspTable::UPPER_BOUND:
        beta = std::min(beta, ttEntry->getScore());
        break;
      case TranspTable::LOWER_BOUND:
        alpha = std::max(alpha, ttEntry->getScore());
        break;
    }

    if (alpha >= beta) {
      return ttEntry->getScore();
    }
  }

  // Transposition table lookups are inconclusive, generate moves and recurse
  MoveGen movegen(board);
  MoveList legalMoves = movegen.getLegalMoves();

  // Check for checkmate and stalemate
  if (legalMoves.size() == 0) {
    ppv.clear();
    int score = board.colorIsInCheck(board.getActivePlayer()) ? -INF : 0; // -INF = checkmate, 0 = stalemate (draw)
    return score;
  }

  // Eval if depth is 0
  if (depth == 0) {
    ppv.clear();
    return _qSearch(board, alpha, beta);
  }

  MoveList pv;
  _scoreMoves(board, legalMoves);
  _sortMovesByValue(legalMoves);

  Move bestMove;
  Board movedBoard;
  for (auto move : legalMoves) {
    movedBoard = board;
    movedBoard.doMove(move);

    int score = -_negaMax(movedBoard, depth-1, -beta, -alpha, pv);

    if (score >= beta) {
      TranspTableEntry newTTEntry(score, depth, TranspTableEntry::LOWER_BOUND, move);
      _tt.set(board.getZKey(), newTTEntry);
      return beta;
    }

    // Check if alpha raised (new best move)
    if (score > alpha) {
      alpha = score;
      bestMove = move;
      // Copy PV data (if alpha raised then we're on a new PV node)
      MoveList newMoves;
      newMoves.push_back(move);
      for (auto move : pv) {
        newMoves.push_back(move);
      }
      ppv = newMoves;
    }
  }

  // Store bestScore in transposition table
  TranspTableEntry::Flag flag;
  if (alpha <= alphaOrig) {
    flag = TranspTableEntry::UPPER_BOUND;
  } else {
    flag = TranspTableEntry::EXACT;
  }
  TranspTableEntry newTTEntry(alpha, depth, flag, bestMove);
  _tt.set(board.getZKey(), newTTEntry);

  return alpha;
}

int Search::_qSearch(const Board& board, int alpha, int beta) {
  MoveGen movegen(board);
  MoveList legalMoves = movegen.getLegalMoves();

  // Check for checkmate / stalemate
  if (legalMoves.size() == 0) {
    if (board.colorIsInCheck(board.getActivePlayer())) { // Checkmate
      return -INF;
    } else { // Stalemate
      return 0;
    }
  }

  _scoreMovesQsearch(legalMoves);
  _sortMovesByValue(legalMoves);

  int standPat = Eval(board, board.getActivePlayer()).getScore();
  _nodes ++;

  // If node is quiet, just return eval
  if (!(legalMoves.at(0).getFlags() & Move::CAPTURE)) {
    return standPat;
  }

  if (standPat >= beta) {
    return beta;
  }
  if (alpha < standPat) {
    alpha = standPat;
  }

  Board movedBoard;
  for (auto move : legalMoves) {
    if ((move.getFlags() & Move::CAPTURE) == 0) {
      break;
    }

    movedBoard = board;
    movedBoard.doMove(move);

    int score = -_qSearch(movedBoard, -beta, -alpha);

    if (score >= beta) {
      return beta;
    }
    if (score > alpha) {
      alpha = score;
    }
  }
  return alpha;
}
<commit_msg>Don't crash on searching from checkmate<commit_after>#include "defs.h"
#include "search.h"
#include "eval.h"
#include "movegen.h"
#include "transptable.h"
#include <string>
#include <algorithm>
#include <time.h>
#include <iostream>
#include <functional>

Search::Search(const Board& board, bool logUci) {
  _logUci = logUci;
  _board = board;
  _bestScore = 0;
}

void Search::perform(int depth) {
  _rootMax(_board, depth);

  if (_logUci) {
    _logUciInfo(_pv, depth, _bestMove, _bestScore, _nodes);
  }
}

void Search::_logUciInfo(const MoveList& pv, int depth, Move bestMove, int bestScore, int nodes) {
  std::string pvString;
  for(auto move : pv) {
    pvString += move.getNotation() + " ";
  }

  std::string scoreString;
  if (bestScore == INF) {
    scoreString = "mate " + std::to_string(pv.size());
  } else if (_bestScore == -INF) {
    scoreString = "mate -" + std::to_string(pv.size());
  } else {
    scoreString = "cp " + std::to_string(bestScore);
  }

  std::cout << "info depth " + std::to_string(depth) + " ";
  std::cout << "nodes " + std::to_string(nodes) + " ";
  std::cout << "score " + scoreString + " ";
  std::cout << "pv " + pvString;
  std::cout << std::endl;
}

Move Search::getBestMove() {
  return _bestMove;
}

int Search::getBestScore() {
  return _bestScore;
}

void Search::_rootMax(const Board& board, int depth) {
  MoveGen movegen(board);
  MoveList legalMoves = movegen.getLegalMoves();
  _nodes = 0;

  // If no legal moves are avaliable, just return, setting bestmove to a null move
  if (legalMoves.size() == 0) {
    _bestMove = Move();
    _bestScore = -INF;
    return;
  }

  _scoreMoves(board, legalMoves);
  _sortMovesByValue(legalMoves);

  _pv = MoveList();
  MoveList pv;

  int alpha = -INF;
  int beta = INF;

  int currScore;

  Move bestMove;
  Board movedBoard;
  for (auto move : legalMoves) {
    movedBoard = board;
    movedBoard.doMove(move);

    currScore = -_negaMax(movedBoard, depth-1, -beta, -alpha, pv);

    // If the current score is better than alpha, or this is the first move in the loop
    if (currScore > alpha || (alpha == -INF)) {
      bestMove = move;
      alpha = currScore;

      MoveList newMoves;
      newMoves.push_back(move);

      for (auto move : pv) {
        newMoves.push_back(move);
      }
      _pv = newMoves;

      // Break if we've found a checkmate
      if (currScore == INF) {
        break;
      }
    }
  }

  TranspTableEntry ttEntry(alpha, depth, TranspTableEntry::EXACT, bestMove);
  _tt.set(board.getZKey(), ttEntry);

  _bestMove = bestMove;
  _bestScore = alpha;
}

void Search::_scoreMoves(const Board& board, MoveList& moveList) {
  const TranspTableEntry* ttEntry = _tt.getEntry(board.getZKey());
  Move pvMove;
  if (ttEntry) {
    pvMove = ttEntry->getBestMove();
  }

  for (auto &move : moveList) {
    Board tempBoard = board;
    tempBoard.doMove(move);

    // PV move always first
    if (move == pvMove) {
      move.setValue(INF);
      continue;
    }

    // Transposition table lookups considered second (dynamic move ordering)
    const TranspTableEntry *ttEntry = _tt.getEntry(tempBoard.getZKey());
    if (ttEntry && ((ttEntry->getFlag() == TranspTableEntry::EXACT) || (ttEntry->getFlag() == TranspTableEntry::LOWER_BOUND))) {
      // Score is negated since score is for opponent
      move.setValue(-ttEntry->getScore());
    } else {
      // Static move ordering (considers promotions and MVV/LVA captures)
      bool hasStaticTraits = move.getFlags() & (Move::PROMOTION | Move::CAPTURE);
      int value = 0;
      if (move.getFlags() & Move::PROMOTION) {
        value += Eval::getMaterialValue(move.getPromotionPieceType()) - Eval::getMaterialValue(PAWN);
      }
      if (move.getFlags() & Move::CAPTURE) {
        value += Eval::getMaterialValue(move.getCapturedPieceType()) - Eval::getMaterialValue(move.getPieceType());
      }

      if (hasStaticTraits) {
        move.setValue(value);
      } else {
        move.setValue(-INF);
      }
    }
  }
}

void Search::_scoreMovesQsearch(MoveList& moveList) {
  for (auto &move : moveList) {
    if (move.getFlags() & Move::CAPTURE) {
      move.setValue(Eval::getMaterialValue(move.getCapturedPieceType()) - Eval::getMaterialValue(move.getPieceType()));
    } else {
      move.setValue(-INF);
    }
  }
  _sortMovesByValue(moveList);
}

void Search::_sortMovesByValue(MoveList& moveList) {
  std::sort(moveList.begin(), moveList.end(),
    std::bind(&Search::_compareMovesValue, this, std::placeholders::_1, std::placeholders::_2));
}

bool Search::_compareMovesValue(Move a, Move b) {
  return a.getValue() > b.getValue();
}

int Search::_negaMax(const Board& board, int depth, int alpha, int beta, MoveList &ppv) {
  int alphaOrig = alpha;

  const TranspTableEntry* ttEntry = _tt.getEntry(board.getZKey());
  // Check transposition table cache
  if (ttEntry && (ttEntry->getDepth() >= depth)) {
    switch(ttEntry->getFlag()) {
      case TranspTable::EXACT:
        return ttEntry->getScore();
      case TranspTable::UPPER_BOUND:
        beta = std::min(beta, ttEntry->getScore());
        break;
      case TranspTable::LOWER_BOUND:
        alpha = std::max(alpha, ttEntry->getScore());
        break;
    }

    if (alpha >= beta) {
      return ttEntry->getScore();
    }
  }

  // Transposition table lookups are inconclusive, generate moves and recurse
  MoveGen movegen(board);
  MoveList legalMoves = movegen.getLegalMoves();

  // Check for checkmate and stalemate
  if (legalMoves.size() == 0) {
    ppv.clear();
    int score = board.colorIsInCheck(board.getActivePlayer()) ? -INF : 0; // -INF = checkmate, 0 = stalemate (draw)
    return score;
  }

  // Eval if depth is 0
  if (depth == 0) {
    ppv.clear();
    return _qSearch(board, alpha, beta);
  }

  MoveList pv;
  _scoreMoves(board, legalMoves);
  _sortMovesByValue(legalMoves);

  Move bestMove;
  Board movedBoard;
  for (auto move : legalMoves) {
    movedBoard = board;
    movedBoard.doMove(move);

    int score = -_negaMax(movedBoard, depth-1, -beta, -alpha, pv);

    if (score >= beta) {
      TranspTableEntry newTTEntry(score, depth, TranspTableEntry::LOWER_BOUND, move);
      _tt.set(board.getZKey(), newTTEntry);
      return beta;
    }

    // Check if alpha raised (new best move)
    if (score > alpha) {
      alpha = score;
      bestMove = move;
      // Copy PV data (if alpha raised then we're on a new PV node)
      MoveList newMoves;
      newMoves.push_back(move);
      for (auto move : pv) {
        newMoves.push_back(move);
      }
      ppv = newMoves;
    }
  }

  // Store bestScore in transposition table
  TranspTableEntry::Flag flag;
  if (alpha <= alphaOrig) {
    flag = TranspTableEntry::UPPER_BOUND;
  } else {
    flag = TranspTableEntry::EXACT;
  }
  TranspTableEntry newTTEntry(alpha, depth, flag, bestMove);
  _tt.set(board.getZKey(), newTTEntry);

  return alpha;
}

int Search::_qSearch(const Board& board, int alpha, int beta) {
  MoveGen movegen(board);
  MoveList legalMoves = movegen.getLegalMoves();

  // Check for checkmate / stalemate
  if (legalMoves.size() == 0) {
    if (board.colorIsInCheck(board.getActivePlayer())) { // Checkmate
      return -INF;
    } else { // Stalemate
      return 0;
    }
  }

  _scoreMovesQsearch(legalMoves);
  _sortMovesByValue(legalMoves);

  int standPat = Eval(board, board.getActivePlayer()).getScore();
  _nodes ++;

  // If node is quiet, just return eval
  if (!(legalMoves.at(0).getFlags() & Move::CAPTURE)) {
    return standPat;
  }

  if (standPat >= beta) {
    return beta;
  }
  if (alpha < standPat) {
    alpha = standPat;
  }

  Board movedBoard;
  for (auto move : legalMoves) {
    if ((move.getFlags() & Move::CAPTURE) == 0) {
      break;
    }

    movedBoard = board;
    movedBoard.doMove(move);

    int score = -_qSearch(movedBoard, -beta, -alpha);

    if (score >= beta) {
      return beta;
    }
    if (score > alpha) {
      alpha = score;
    }
  }
  return alpha;
}
<|endoftext|>


<commit_before>#include <iostream>
#include "server_net.h"
#include "tclap/CmdLine.h"
#include "logging.h"
#include "csv_reader.h"
#include "radius_server.h"
#include <windows.h>

const std::string LOGGER_NAME = "server";

using radius::RadiusServer;
using radius::packets::Packet;

void serverLoop(RadiusServer &radiusServer) {

    /*while (1) {
      radius::sendData(radius::receiveData());
      }*/
    Packet iPacket = radius::receiveData();

    radiusServer.recvPacket(iPacket);
}

BOOL WINAPI consoleHandler(DWORD signal) {

    if (signal == CTRL_C_EVENT)
        radius::stopServer();

    return TRUE;
}

int main(int argc, char **argv) {
    using namespace TCLAP;
    using namespace std;
    try {

        CmdLine cmd("RADIUS Server with EAP-MD5", ' ');

        ValueArg<string> logpathArg(
            "l", "log", "The path where the log file shall be written. "
                        "Default: server.log",
            false, "server.log", "path\\to\\log.log");
        cmd.add(logpathArg);

        ValueArg<string> dbArg(
            "d", "database", "The path to the plain text file with user data. "
                             "Default: users.txt",
            false, ".\\users.txt", "path\\to\\db.csv");
        cmd.add(dbArg);

        ValueArg<string> secretArg("s", "secret", "The secret shared with NAS",
                                   true, "", "string");
        cmd.add(secretArg);

        ValueArg<int> portArg("p", "port", "Binded port", true, -1, "number");
        cmd.add(portArg);

        ValueArg<string> ipArg("a", "address", "Binded IP address", true, "",
                               "IP");

        cmd.add(ipArg);

        SwitchArg verboseSwitch("v", "verbose", "Run in the verbose mode",
                                false);
        cmd.add(verboseSwitch);

        cmd.parse(argc, argv);

        int port = portArg.getValue();
        string ip = ipArg.getValue();
        string secret = secretArg.getValue();
        string logpath = logpathArg.getValue();
        radius::initLogger(logpath, LOGGER_NAME);

        bool verbose = verboseSwitch.getValue();

        if (verbose) {
            spdlog::set_level(spdlog::level::trace);
        }

        auto logger = spdlog::get(LOGGER_NAME);

        string dbpath = dbArg.getValue();

        radius::startServer(ip.c_str(), port);
        radius::RadiusServer radiusServer(radius::readCsvFile(dbpath), secret,
                                          logger);

        if (!SetConsoleCtrlHandler(consoleHandler, TRUE)) {
            logger->error() << "Could not set control handler!";
            radius::stopServer();
            return 1;
        }

        logger->info() << "Started server";
        serverLoop(radiusServer);

    } catch (CmdLineParseException &ce) {
        cerr << "error: " << ce.error() << ce.argId() << endl;
    }
}
<commit_msg>server sending<commit_after>#include <iostream>
#include "server_net.h"
#include "tclap/CmdLine.h"
#include "logging.h"
#include "csv_reader.h"
#include "radius_server.h"
#include <windows.h>

const std::string LOGGER_NAME = "server";

using radius::RadiusServer;
using radius::packets::Packet;

void serverLoop(RadiusServer &radiusServer) {

    while (1) {
        Packet iPacket = radius::receiveData();
        std::vector<Packet>packets = radiusServer.recvPacket(iPacket);
        for(int i=0;i<packets.size();i++){
            radius::sendData(packets[i]);
        }
    }

}

BOOL WINAPI consoleHandler(DWORD signal) {

    if (signal == CTRL_C_EVENT)
        radius::stopServer();

    return TRUE;
}

int main(int argc, char **argv) {
    using namespace TCLAP;
    using namespace std;
    try {

        CmdLine cmd("RADIUS Server with EAP-MD5", ' ');

        ValueArg<string> logpathArg(
            "l", "log", "The path where the log file shall be written. "
                        "Default: server.log",
            false, "server.log", "path\\to\\log.log");
        cmd.add(logpathArg);

        ValueArg<string> dbArg(
            "d", "database", "The path to the plain text file with user data. "
                             "Default: users.txt",
            false, ".\\users.txt", "path\\to\\db.csv");
        cmd.add(dbArg);

        ValueArg<string> secretArg("s", "secret", "The secret shared with NAS",
                                   true, "", "string");
        cmd.add(secretArg);

        ValueArg<int> portArg("p", "port", "Binded port", true, -1, "number");
        cmd.add(portArg);

        ValueArg<string> ipArg("a", "address", "Binded IP address", true, "",
                               "IP");

        cmd.add(ipArg);

        SwitchArg verboseSwitch("v", "verbose", "Run in the verbose mode",
                                false);
        cmd.add(verboseSwitch);

        cmd.parse(argc, argv);

        int port = portArg.getValue();
        string ip = ipArg.getValue();
        string secret = secretArg.getValue();
        string logpath = logpathArg.getValue();
        radius::initLogger(logpath, LOGGER_NAME);

        bool verbose = verboseSwitch.getValue();

        if (verbose) {
            spdlog::set_level(spdlog::level::trace);
        }

        auto logger = spdlog::get(LOGGER_NAME);

        string dbpath = dbArg.getValue();

        radius::startServer(ip.c_str(), port);
        radius::RadiusServer radiusServer(radius::readCsvFile(dbpath), secret,
                                          logger);

        if (!SetConsoleCtrlHandler(consoleHandler, TRUE)) {
            logger->error() << "Could not set control handler!";
            radius::stopServer();
            return 1;
        }

        logger->info() << "Started server";
        serverLoop(radiusServer);

    } catch (CmdLineParseException &ce) {
        cerr << "error: " << ce.error() << ce.argId() << endl;
    }
}
<|endoftext|>


<commit_before>#include "ResourceManager.h"
#include <string>
#include <vector>
#ifdef __MACH__
#include <CoreFoundation/CoreFoundation.h>
#endif

namespace ResourceManager
{

namespace Internal
{

std::vector<std::string> searchPaths;
std::string userDirectoryPath;

bool FileExists ( const std::string& path )
{
	FILE* fp = fopen(path.c_str(), "rb");
	if (fp)
		fclose(fp);
	return fp != NULL;
}

}

using namespace Internal;

// utility function for reading from a RWops in full
void* ReadFull ( size_t* length, SDL_RWops* ops, int autoclose )
{
	size_t len = SDL_RWseek(ops, 0, SEEK_END);
	*length = len;
	SDL_RWseek(ops, 0, SEEK_SET);
	void* buffer = malloc(len);
	SDL_RWread(ops, buffer, 1, len);
	if (autoclose)
		SDL_RWclose(ops);
	return buffer;
}

SDL_RWops* OpenFile ( const std::string& name )
{
	for (std::vector<std::string>::iterator iter = searchPaths.begin(); iter != searchPaths.end(); iter++)
	{
		std::string fullPath = (*iter) + '/' + name;
		if (FileExists(fullPath))
		{
			return SDL_RWFromFile(fullPath.c_str(), "r");
		}
	}
	return NULL;
}

void WriteFile ( const std::string& name, const void* data, size_t len )
{
	std::string path = userDirectoryPath + '/' + name;
	FILE* fp = fopen(path.c_str(), "rb");
	assert(fp);
	fwrite(data, 1, len, fp);
	fclose(fp);
}

void Init ()
{
	searchPaths.clear();
#ifdef __MACH__
	char systemDirectory[1024];
	char userDirectory[1024];
	sprintf(userDirectory, "%s/Library/Application Support/Xsera", getenv("HOME"));
	CFBundleRef mainBundle = CFBundleGetMainBundle();
	CFURLRef resourcePath = CFBundleCopyResourcesDirectoryURL(mainBundle);
	CFURLGetFileSystemRepresentation(resourcePath, 1, (Uint8*)systemDirectory, sizeof(systemDirectory));
	CFRelease(resourcePath);
	searchPaths.push_back(systemDirectory);
	searchPaths.push_back(userDirectory);
	userDirectoryPath = userDirectory;
#endif
}

}
<commit_msg>Fixup to ResourceManager::OpenFile for empty parameters<commit_after>#include "ResourceManager.h"
#include <string>
#include <vector>
#ifdef __MACH__
#include <CoreFoundation/CoreFoundation.h>
#endif

namespace ResourceManager
{

namespace Internal
{

std::vector<std::string> searchPaths;
std::string userDirectoryPath;

bool FileExists ( const std::string& path )
{
	FILE* fp = fopen(path.c_str(), "rb");
	if (fp)
		fclose(fp);
	return fp != NULL;
}

}

using namespace Internal;

// utility function for reading from a RWops in full
void* ReadFull ( size_t* length, SDL_RWops* ops, int autoclose )
{
	size_t len = SDL_RWseek(ops, 0, SEEK_END);
	*length = len;
	SDL_RWseek(ops, 0, SEEK_SET);
	void* buffer = malloc(len);
	SDL_RWread(ops, buffer, 1, len);
	if (autoclose)
		SDL_RWclose(ops);
	return buffer;
}

SDL_RWops* OpenFile ( const std::string& name )
{
	if (name == "")
		return NULL;
	for (std::vector<std::string>::iterator iter = searchPaths.begin(); iter != searchPaths.end(); iter++)
	{
		std::string fullPath = (*iter) + '/' + name;
		if (FileExists(fullPath))
		{
			printf("[ResourceManager] loaded file %s\n", name.c_str());
			return SDL_RWFromFile(fullPath.c_str(), "r");
		}
	}
	return NULL;
}

void WriteFile ( const std::string& name, const void* data, size_t len )
{
	std::string path = userDirectoryPath + '/' + name;
	FILE* fp = fopen(path.c_str(), "rb");
	assert(fp);
	fwrite(data, 1, len, fp);
	fclose(fp);
}

void Init ()
{
	searchPaths.clear();
#ifdef __MACH__
	char systemDirectory[1024];
	char userDirectory[1024];
	sprintf(userDirectory, "%s/Library/Application Support/Xsera", getenv("HOME"));
	CFBundleRef mainBundle = CFBundleGetMainBundle();
	CFURLRef resourcePath = CFBundleCopyResourcesDirectoryURL(mainBundle);
	CFURLGetFileSystemRepresentation(resourcePath, 1, (Uint8*)systemDirectory, sizeof(systemDirectory));
	CFRelease(resourcePath);
	searchPaths.push_back(systemDirectory);
	searchPaths.push_back(userDirectory);
	userDirectoryPath = userDirectory;
#endif
}

}
<|endoftext|>