<commit_before>/*
For more information, please see: http://software.sci.utah.edu

The MIT License

Copyright (c) 2012 Scientific Computing and Imaging Institute,
University of Utah.

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

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

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

Author            : Moritz Dannhauer
Last modification : March 16 2014
ToDo: Padding is always enabled because of exit() in cleaver lib
*/

///TODO: fix include path to remove Externals/ part

#include <Externals/cleaver/lib/FloatField.h>
#include <Externals/cleaver/lib/vec3.h>
#include <Externals/cleaver/lib/BoundingBox.h>
#include <Externals/cleaver/lib/Cleaver.h>
#include <Externals/cleaver/lib/InverseField.h>
#include <Externals/cleaver/lib/PaddedVolume.h>
#include <Externals/cleaver/lib/Volume.h>
#include <Core/Algorithms/Base/AlgorithmPreconditions.h>
#include <Core/Algorithms/Field/InterfaceWithCleaverAlgorithm.h>
#include <Core/Algorithms/Base/AlgorithmVariableNames.h>
#include <Core/GeometryPrimitives/Vector.h>
#include <Core/Datatypes/Legacy/Field/Field.h>
#include <Core/Datatypes/Legacy/Field/VField.h>
#include <Core/Datatypes/Legacy/Field/VMesh.h>
#include <Core/Datatypes/Legacy/Field/FieldInformation.h>
#include <iostream>
#include <Core/GeometryPrimitives/Point.h>
#include <Core/Utils/StringUtil.h>
#include <boost/scoped_ptr.hpp>
#include <Core/Logging/Log.h>
#include <Core/Math/MiscMath.h>

using namespace SCIRun::Core::Algorithms;
using namespace SCIRun::Core::Algorithms::Fields;
using namespace SCIRun::Core::Geometry;
using namespace SCIRun;
using namespace SCIRun::Core;
using namespace SCIRun::Core::Logging;

AlgorithmParameterName InterfaceWithCleaverAlgorithm::Verbose("VerboseCheckBox");
AlgorithmParameterName InterfaceWithCleaverAlgorithm::Padding("PaddingCheckBox");
AlgorithmParameterName InterfaceWithCleaverAlgorithm::VolumeScalingOption("VolumeScalingOption");
AlgorithmParameterName InterfaceWithCleaverAlgorithm::VolumeScalingX("VolumeScalingSpinBox_X");
AlgorithmParameterName InterfaceWithCleaverAlgorithm::VolumeScalingY("VolumeScalingSpinBox_Y");
AlgorithmParameterName InterfaceWithCleaverAlgorithm::VolumeScalingZ("VolumeScalingSpinBox_Z");

InterfaceWithCleaverAlgorithm::InterfaceWithCleaverAlgorithm()
{
  addParameter(Verbose,true);
  addParameter(Padding,true);
  add_option(VolumeScalingOption, "Relative size", "Absolute size|Relative size|None");
  addParameter(VolumeScalingX,1.0);
  addParameter(VolumeScalingY,1.0);
  addParameter(VolumeScalingZ,1.0);
}

boost::shared_ptr<Cleaver::ScalarField> InterfaceWithCleaverAlgorithm::makeCleaverFieldFromLatVol(FieldHandle field )
{
  VMesh*  vmesh   = field->vmesh();
  VField* vfield = field->vfield();
  VMesh::dimension_type dims;
  vmesh->get_dimensions( dims );

  float* ptr = static_cast<float*>(vfield->fdata_pointer());

  auto cleaverField = boost::make_shared<Cleaver::FloatField>(dims[0], dims[1], dims[2], ptr);
  Cleaver::BoundingBox bb(Cleaver::vec3::zero, Cleaver::vec3(dims[0],dims[1],dims[2]));
  cleaverField->setBounds(bb);
  const Transform &transform = vmesh->get_transform();

  int x_spacing=fabs(transform.get_mat_val(0,0)), y_spacing=fabs(transform.get_mat_val(1,1)), z_spacing=fabs(transform.get_mat_val(2,2));
  if (IsNan(x_spacing)) x_spacing=1;
  if (IsNan(y_spacing)) y_spacing=1;
  if (IsNan(z_spacing)) z_spacing=1;

  cleaverField->setScale(Cleaver::vec3(x_spacing,y_spacing,z_spacing));

  return cleaverField;
}

FieldHandle InterfaceWithCleaverAlgorithm::run(const std::vector<FieldHandle>& input) const
{
  FieldHandle output;
  std::vector<FieldHandle> inputs;
  std::copy_if(input.begin(), input.end(), std::back_inserter(inputs), [](FieldHandle f) { return f; });

  if (inputs.empty())
  {
    THROW_ALGORITHM_INPUT_ERROR(" No input fields given ");
    return FieldHandle();
  }
  if (inputs.size()<2)
  {
    THROW_ALGORITHM_INPUT_ERROR(" At least 2 indicator functions stored as float values are needed to run cleaver! " );
    return FieldHandle();
  }

  std::vector<boost::shared_ptr<Cleaver::ScalarField>> fields;

  VMesh::dimension_type dims; int x=0,y=0,z=0;
  for (size_t p=0; p<inputs.size(); p++)
  {
    FieldHandle input = inputs[p];
    VMesh*  imesh1   = input->vmesh();

    if( !imesh1->is_structuredmesh() )
    {
      THROW_ALGORITHM_INPUT_ERROR("needs to be structured mesh!");
    }
    else
    {
      VField* vfield1 = input->vfield();
      if (!vfield1->is_scalar())
      {
        THROW_ALGORITHM_INPUT_ERROR("values at the node needs to be scalar!");
        return FieldHandle();
      }

      imesh1->get_dimensions( dims );
      if (p==0)
      {
        x=dims[0]; y=dims[1]; z=dims[2];
        if (x<1 || y<1 || z<1)
        {
          THROW_ALGORITHM_INPUT_ERROR(" Size of input fields should be non-zero !");
        }
      }
      else
      {
        if ( dims[0]!=x || dims[1]!=y || dims[2]!=z)
        {
          THROW_ALGORITHM_INPUT_ERROR(" Size of input fields is inconsistent !");
        }
      }

      if (dims.size()!=3)
      {
        THROW_ALGORITHM_INPUT_ERROR("need a three dimensional indicator function");
        return FieldHandle();
      }

      //0 = constant, 1 = linear
       if (1 != vfield1->basis_order())
       {
        THROW_ALGORITHM_INPUT_ERROR("Input data need to be defined on input mesh nodes.");
       }

      if (vfield1->is_float())
      {
        float* ptr = static_cast<float*>(vfield1->fdata_pointer());
	if (ptr)
        {
          fields.push_back(makeCleaverFieldFromLatVol(input));
        }
        else
        {
          THROW_ALGORITHM_INPUT_ERROR(" float field is NULL pointer");
          return FieldHandle();
        }
      } else
      {
       THROW_ALGORITHM_INPUT_ERROR(" Input field needs to be a structured mesh (best would be a LatVol) with float values defnied on mesh nodes. ");
      }

    }

  }

  std::cout << "Input Dimensions: " << dims[0] << " x " << dims[1] << " x " << dims[2] << std::endl;
  boost::shared_ptr<Cleaver::Volume> volume(new Cleaver::Volume(toVectorOfRawPointers(fields)));

  const double xScale = get(VolumeScalingX).toDouble();
  const double yScale = get(VolumeScalingY).toDouble();
  const double zScale = get(VolumeScalingZ).toDouble();

  if (xScale > 0 && yScale > 0 && zScale > 0)
  {
    const std::string scaling = get_option(VolumeScalingOption);
    if ("Absolute size" == scaling)
    {
      volume->setSize(xScale, yScale,zScale);
    }
    else if ("Relative size" == scaling)
    {
      double newX = xScale*volume->size().x;
      double newY = yScale*volume->size().y;
      double newZ = zScale*volume->size().z;
      volume->setSize(newX, newY, newZ);
    }
    else // None
    {
      volume->setSize(dims[0],dims[1],dims[2]);
    }
  }
  else
  {
    THROW_ALGORITHM_INPUT_ERROR(" Invalid Scaling. Use Input sizes.");
  }

  /// Padding is now optional!
  boost::shared_ptr<Cleaver::AbstractVolume> paddedVolume(volume);
  const bool verbose = get(Verbose).toBool();
  const bool pad = get(Padding).toBool();
  if (pad)
    paddedVolume.reset(new Cleaver::PaddedVolume(volume.get()));

  if (pad)
    std::cout << "Creating Mesh with Volume Size " << paddedVolume->size().toString() << std::endl;
       else
          std::cout << "Creating Mesh with Volume Size " << volume->size().toString() << std::endl;

  boost::scoped_ptr<Cleaver::TetMesh> mesh(Cleaver::createMeshFromVolume(paddedVolume.get(), verbose));

  auto nr_of_tets  = mesh->tets.size();
  auto nr_of_verts = mesh->verts.size();

  if (nr_of_tets==0 || nr_of_verts==0)
  {
    THROW_ALGORITHM_INPUT_ERROR(" Number of resulting tetrahedral nodes or elements is 0. If you disabled padding enable it and execute again. ");
  }

  FieldInformation fi("TetVolMesh",0,"double");   ///create output field

  output = CreateField(fi);
  auto omesh = output->vmesh();
  auto ofield = output->vfield();

  omesh->node_reserve(nr_of_verts);
  omesh->elem_reserve(nr_of_tets);

  for (auto i=0; i<nr_of_verts; i++)
  {
    omesh->add_point(Point(mesh->verts[i]->pos().x,mesh->verts[i]->pos().y,mesh->verts[i]->pos().z));
  }

  VMesh::Node::array_type vdata;
  vdata.resize(4);
  std::vector<double> values(nr_of_tets);

  for (auto i=0; i<nr_of_tets; i++)
  {
    vdata[0]=mesh->tets[i]->verts[0]->tm_v_index;
    vdata[1]=mesh->tets[i]->verts[1]->tm_v_index;
    vdata[2]=mesh->tets[i]->verts[2]->tm_v_index;
    vdata[3]=mesh->tets[i]->verts[3]->tm_v_index;
    omesh->add_elem(vdata);
    auto mat_label = mesh->tets[i]->mat_label;
    values[i]=mat_label;
  }
  ofield->resize_values();
  ofield->set_values(values);
  mesh->computeAngles();
  std::ostringstream ostr1;
  ostr1 << "Number of tetrahedral elements:" << nr_of_tets <<  std::endl;
  ostr1 << "Number of tetrahedral nodes:" << nr_of_verts << std::endl;
  ostr1 << "Worst Angle (min):" <<  mesh->min_angle << std::endl;
  ostr1 << "Worst Angle (max):" <<  mesh->max_angle << std::endl;
  ostr1 << "Volume:" << volume->size().toString() << std::endl;

  remark(ostr1.str());

  return output;
}

AlgorithmOutput InterfaceWithCleaverAlgorithm::run_generic(const AlgorithmInput& input) const
{
  auto inputfields = input.getList<Field>(Variables::InputFields);

  FieldHandle output_fld = run(inputfields);
  if ( !output_fld )
    THROW_ALGORITHM_PROCESSING_ERROR("Null returned on legacy run call.");

  AlgorithmOutput output;
  output[Variables::OutputField] = output_fld;
  return output;
}
<commit_msg>Bug fixed reported by Jess Tate.<commit_after>/*
For more information, please see: http://software.sci.utah.edu

The MIT License

Copyright (c) 2012 Scientific Computing and Imaging Institute,
University of Utah.

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

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

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

Author            : Moritz Dannhauer
Last modification : March 16 2014
ToDo: Padding is always enabled because of exit() in cleaver lib
*/

///TODO: fix include path to remove Externals/ part

#include <Externals/cleaver/lib/FloatField.h>
#include <Externals/cleaver/lib/vec3.h>
#include <Externals/cleaver/lib/BoundingBox.h>
#include <Externals/cleaver/lib/Cleaver.h>
#include <Externals/cleaver/lib/InverseField.h>
#include <Externals/cleaver/lib/PaddedVolume.h>
#include <Externals/cleaver/lib/Volume.h>
#include <Core/Algorithms/Base/AlgorithmPreconditions.h>
#include <Core/Algorithms/Field/InterfaceWithCleaverAlgorithm.h>
#include <Core/Algorithms/Base/AlgorithmVariableNames.h>
#include <Core/GeometryPrimitives/Vector.h>
#include <Core/Datatypes/Legacy/Field/Field.h>
#include <Core/Datatypes/Legacy/Field/VField.h>
#include <Core/Datatypes/Legacy/Field/VMesh.h>
#include <Core/Datatypes/Legacy/Field/FieldInformation.h>
#include <iostream>
#include <Core/GeometryPrimitives/Point.h>
#include <Core/Utils/StringUtil.h>
#include <boost/scoped_ptr.hpp>
#include <Core/Logging/Log.h>
#include <Core/Math/MiscMath.h>

using namespace SCIRun::Core::Algorithms;
using namespace SCIRun::Core::Algorithms::Fields;
using namespace SCIRun::Core::Geometry;
using namespace SCIRun;
using namespace SCIRun::Core;
using namespace SCIRun::Core::Logging;

AlgorithmParameterName InterfaceWithCleaverAlgorithm::Verbose("VerboseCheckBox");
AlgorithmParameterName InterfaceWithCleaverAlgorithm::Padding("PaddingCheckBox");
AlgorithmParameterName InterfaceWithCleaverAlgorithm::VolumeScalingOption("VolumeScalingOption");
AlgorithmParameterName InterfaceWithCleaverAlgorithm::VolumeScalingX("VolumeScalingSpinBox_X");
AlgorithmParameterName InterfaceWithCleaverAlgorithm::VolumeScalingY("VolumeScalingSpinBox_Y");
AlgorithmParameterName InterfaceWithCleaverAlgorithm::VolumeScalingZ("VolumeScalingSpinBox_Z");

InterfaceWithCleaverAlgorithm::InterfaceWithCleaverAlgorithm()
{
  addParameter(Verbose,true);
  addParameter(Padding,true);
  add_option(VolumeScalingOption, "Relative size", "Absolute size|Relative size|None");
  addParameter(VolumeScalingX,1.0);
  addParameter(VolumeScalingY,1.0);
  addParameter(VolumeScalingZ,1.0);
}

boost::shared_ptr<Cleaver::ScalarField> InterfaceWithCleaverAlgorithm::makeCleaverFieldFromLatVol(FieldHandle field )
{
  VMesh*  vmesh   = field->vmesh();
  VField* vfield = field->vfield();
  VMesh::dimension_type dims;
  vmesh->get_dimensions( dims );

  float* ptr = static_cast<float*>(vfield->fdata_pointer());

  auto cleaverField = boost::make_shared<Cleaver::FloatField>(dims[0], dims[1], dims[2], ptr);
  Cleaver::BoundingBox bb(Cleaver::vec3::zero, Cleaver::vec3(dims[0],dims[1],dims[2]));
  cleaverField->setBounds(bb);
  const Transform &transform = vmesh->get_transform();

  int x_spacing=fabs(transform.get_mat_val(0,0)), y_spacing=fabs(transform.get_mat_val(1,1)), z_spacing=fabs(transform.get_mat_val(2,2));

  if (IsNan(x_spacing) || x_spacing<=0) x_spacing=1; /// dont allow negative or zero scaling of the bounding box
  if (IsNan(y_spacing) || y_spacing<=0) y_spacing=1;
  if (IsNan(z_spacing) || z_spacing<=0) z_spacing=1;

  cleaverField->setScale(Cleaver::vec3(x_spacing,y_spacing,z_spacing));

  return cleaverField;
}

FieldHandle InterfaceWithCleaverAlgorithm::run(const std::vector<FieldHandle>& input) const
{
  FieldHandle output;
  std::vector<FieldHandle> inputs;
  std::copy_if(input.begin(), input.end(), std::back_inserter(inputs), [](FieldHandle f) { return f; });

  if (inputs.empty())
  {
    THROW_ALGORITHM_INPUT_ERROR(" No input fields given ");
    return FieldHandle();
  }
  if (inputs.size()<2)
  {
    THROW_ALGORITHM_INPUT_ERROR(" At least 2 indicator functions stored as float values are needed to run cleaver! " );
    return FieldHandle();
  }

  std::ostringstream ostr0;
  ostr0 << "Generally: Insides and outsides of materials (to be meshed) need to be defined as positive and negative (e.g. surface distance) values across all module inputs. The zero crossings represents material boundaries." << std::endl;
  remark(ostr0.str());

  std::vector<boost::shared_ptr<Cleaver::ScalarField>> fields;

  VMesh::dimension_type dims; int x=0,y=0,z=0;
  for (size_t p=0; p<inputs.size(); p++)
  {
    FieldHandle input = inputs[p];
    VMesh*  imesh1   = input->vmesh();

    if( !imesh1->is_structuredmesh() )
    {
      THROW_ALGORITHM_INPUT_ERROR("needs to be structured mesh!");
    }
    else
    {
      VField* vfield1 = input->vfield();
      if (!vfield1->is_scalar())
      {
        THROW_ALGORITHM_INPUT_ERROR("values at the node needs to be scalar!");
        return FieldHandle();
      }

      imesh1->get_dimensions( dims );
      if (p==0)
      {
        x=dims[0]; y=dims[1]; z=dims[2];
        if (x<1 || y<1 || z<1)
        {
          THROW_ALGORITHM_INPUT_ERROR(" Size of input fields should be non-zero !");
        }
      }
      else
      {
        if ( dims[0]!=x || dims[1]!=y || dims[2]!=z)
        {
          THROW_ALGORITHM_INPUT_ERROR(" Size of input fields is inconsistent !");
        }
      }

      if (dims.size()!=3)
      {
        THROW_ALGORITHM_INPUT_ERROR("need a three dimensional indicator function");
        return FieldHandle();
      }

      //0 = constant, 1 = linear
       if (1 != vfield1->basis_order())
       {
        THROW_ALGORITHM_INPUT_ERROR("Input data need to be defined on input mesh nodes.");
       }

      if (vfield1->is_float())
      {
        float* ptr = static_cast<float*>(vfield1->fdata_pointer());
	if (ptr)
        {
          fields.push_back(makeCleaverFieldFromLatVol(input));
        }
        else
        {
          THROW_ALGORITHM_INPUT_ERROR(" float field is NULL pointer");
          return FieldHandle();
        }
      } else
      {
       THROW_ALGORITHM_INPUT_ERROR(" Input field needs to be a structured mesh (best would be a LatVol) with float values defnied on mesh nodes. ");
      }

    }

  }

  boost::shared_ptr<Cleaver::Volume> volume(new Cleaver::Volume(toVectorOfRawPointers(fields)));

  const double xScale = get(VolumeScalingX).toDouble();
  const double yScale = get(VolumeScalingY).toDouble();
  const double zScale = get(VolumeScalingZ).toDouble();

  if (xScale > 0 && yScale > 0 && zScale > 0)
  {
    const std::string scaling = get_option(VolumeScalingOption);
    if ("Absolute size" == scaling)
    {
      volume->setSize(xScale, yScale, zScale);
    }
    else if ("Relative size" == scaling)
    {
      double newX = xScale*volume->size().x;
      double newY = yScale*volume->size().y;
      double newZ = zScale*volume->size().z;
      volume->setSize(newX, newY, newZ);
    }
    else // None
    {
      volume->setSize(dims[0],dims[1],dims[2]);
      std::ostringstream ostr1,ostr2;
      ostr1 << "Scaling 'None' .... using " << "Scaling " << dims[0] << "x" << dims[1] << "x" << dims[2] << std::endl;
      remark(ostr1.str());
    }
  }
  else
  {
    THROW_ALGORITHM_INPUT_ERROR(" Invalid Scaling. Use Input sizes.");
  }

  /// Padding is now optional!
  boost::shared_ptr<Cleaver::AbstractVolume> paddedVolume(volume);
  const bool verbose = get(Verbose).toBool();
  const bool pad = get(Padding).toBool();

  if (pad)
  {
    paddedVolume.reset(new Cleaver::PaddedVolume(volume.get()));
  }

  if (verbose)
  {
   std::cout << "Input Dimensions: " << dims[0] << " x " << dims[1] << " x " << dims[2] << std::endl;
   if (pad)
    std::cout << "Padded Mesh with Volume Size " << paddedVolume->size().toString() << std::endl;
       else
          std::cout << "Creating Mesh with Volume Size " << volume->size().toString() << std::endl;
  }

  boost::scoped_ptr<Cleaver::TetMesh> mesh(Cleaver::createMeshFromVolume(pad ? paddedVolume.get() : volume.get(), verbose));

  auto nr_of_tets  = mesh->tets.size();
  auto nr_of_verts = mesh->verts.size();

  if (nr_of_tets==0 || nr_of_verts==0)
  {
    THROW_ALGORITHM_INPUT_ERROR(" Number of resulting tetrahedral nodes or elements is 0. If you disabled padding enable it and execute again. ");
  }

  FieldInformation fi("TetVolMesh",0,"double");   ///create output field

  output = CreateField(fi);
  auto omesh = output->vmesh();
  auto ofield = output->vfield();

  omesh->node_reserve(nr_of_verts);
  omesh->elem_reserve(nr_of_tets);

  for (auto i=0; i<nr_of_verts; i++)
  {
    omesh->add_point(Point(mesh->verts[i]->pos().x,mesh->verts[i]->pos().y,mesh->verts[i]->pos().z));
  }

  VMesh::Node::array_type vdata;
  vdata.resize(4);
  std::vector<double> values(nr_of_tets);

  for (auto i=0; i<nr_of_tets; i++)
  {
    vdata[0]=mesh->tets[i]->verts[0]->tm_v_index;
    vdata[1]=mesh->tets[i]->verts[1]->tm_v_index;
    vdata[2]=mesh->tets[i]->verts[2]->tm_v_index;
    vdata[3]=mesh->tets[i]->verts[3]->tm_v_index;
    omesh->add_elem(vdata);
    auto mat_label = mesh->tets[i]->mat_label;
    values[i]=mat_label;
  }
  ofield->resize_values();
  ofield->set_values(values);
  mesh->computeAngles();

  std::ostringstream ostr1,ostr2;
  ostr1 << "(nodes, elements, dims) - (" << nr_of_verts << " , " << nr_of_tets << " , " << volume->size().toString() << ")" << std::endl;
  ostr2 << "(min angle, max angle) - (" <<  mesh->min_angle << " , " << mesh->max_angle << ")" << std::endl;

  remark(ostr1.str());
  remark(ostr2.str());

  return output;
}

AlgorithmOutput InterfaceWithCleaverAlgorithm::run_generic(const AlgorithmInput& input) const
{
  auto inputfields = input.getList<Field>(Variables::InputFields);

  FieldHandle output_fld = run(inputfields);
  if ( !output_fld )
    THROW_ALGORITHM_PROCESSING_ERROR("Null returned on legacy run call.");

  AlgorithmOutput output;
  output[Variables::OutputField] = output_fld;
  return output;
}
<|endoftext|>


<commit_before>/*
 * SEGS - Super Entity Game Server
 * http://www.segs.io/
 * Copyright (c) 2006 - 2018 SEGS Team (see AUTHORS.md)
 * This software is licensed under the terms of the 3-clause BSD License. See LICENSE.md for details.
 */

/*!
 * @addtogroup BinConverter Projects/CoX/Utilities/BinConverter
 * @{
 */

#include "Common/GameData/DataStorage.h"
#include "Common/GameData/attrib_definitions.h"
#include "Common/GameData/attrib_serializers.h"
#include "Common/GameData/bodypart_serializers.h"
#include "Common/GameData/costume_definitions.h"
#include "Common/GameData/costume_serializers.h"
#include "Common/GameData/map_definitions.h"
#include "Common/GameData/map_serializers.h"
#include "Common/GameData/scenegraph_definitions.h"
#include "Common/GameData/scenegraph_serializers.h"
#include "Common/GameData/shop_definitions.h"
#include "Common/GameData/shop_serializers.h"
#include "Common/GameData/power_definitions.h"
#include "Common/GameData/power_serializers.h"
#include "Common/GameData/npc_definitions.h"
#include "Common/GameData/npc_serializers.h"
#include "Common/GameData/trick_definitions.h"
#include "Common/GameData/trick_serializers.h"
#include "Common/GameData/fx_definitions.h"
#include "Common/GameData/fx_serializers.h"
#include "Common/GameData/charclass_definitions.h"
#include "Common/GameData/charclass_serializers.h"
#include "Common/GameData/def_serializers.h"
#include "Common/GameData/other_definitions.h"
#include "Common/GameData/origin_definitions.h"
#include "serialization_common.h"
#include "Common/GameData/particlesys_serializers.h"
#include "Common/GameData/particle_definitions.h"

#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
#include <QtCore/QMap>

namespace {
enum BinType {
    eInvalid,
    eLevelsDebts,
    eCombineChances,
    eBoostEffectiveness,
    eParticleSystems,
    eEntityOrigins,
    eEntityClasses,
    eShops,
    eShopItems,
    eShopDepts,
    eSequencers,
    eTailorCosts,
    eCostumeSets,
    eBodyParts,
    ePaletteSets,
    eGroupEmblems,
    eZones,
    eAttribNames,
    eSceneGraph,
    eTrickDefinitions,
    ePowerDefinitions,
    eNpcDefinitions,
    eFxBehavior_Definitions,
    eFxInfo_Definitions,
};

const QHash<uint32_t,BinType> knownSerializers = {
    {levelsdebts_i0_requiredCrc         , eLevelsDebts},
    {combining_i0_requiredCrc           , eCombineChances},
    {boosteffectiveness_i0_requiredCrc  , eBoostEffectiveness},
    {particlesystems_i0_requiredCrc     , eParticleSystems},
    {shoplist_i0_requiredCrc            , eShops},
    {shopitems_i0_requiredCrc           , eShopItems},
    {shopdepts_i0_requiredCrc           , eShopDepts},
//    {seqencerlist_i0_requiredCrc        , eSequencers},
    {tailorcosts_i0_requiredCrc         , eTailorCosts},
    {costumesets_i0_requiredCrc         , eCostumeSets},
    {bodyparts_i0_requiredCrc           , eBodyParts},
    {palette_i0_requiredCrc             , ePaletteSets},
    {geoset_i0_requiredCrc              , eGroupEmblems },
    {zones_i0_requiredCrc               , eZones},
    {attribnames_i0_requiredCrc         , eAttribNames},
    {scenegraph_i0_2_requiredCrc        , eSceneGraph},
    {tricks_i0_requiredCrc              , eTrickDefinitions},
    {tricks_i2_requiredCrc              , eTrickDefinitions},
    {charclass_i0_requiredCrc           , eEntityClasses},
    {origins_i0_requiredCrc             , eEntityOrigins},
    {powers_i0_requiredCrc              , ePowerDefinitions},
    {npccostumesets_i0_requiredCrc      , eNpcDefinitions},
    {fxbehaviors_i0_requiredCrc         , eFxBehavior_Definitions},
    {fxinfos_i0_requiredCrc             , eFxInfo_Definitions},
};

BinType getLoader(const QString &fname)
{
    QFile fl(fname);
    if(!fl.exists() || !fl.open(QFile::ReadOnly)) {
        qDebug() << "Cannot open file:" << fname;
        return eInvalid;
    }
    if(fl.size()<12 || fl.read(8) != "CrypticS") {
        qDebug() << "File "<<fname<<"is missing magic 'CrypticS' string";
        return eInvalid;
    }
    uint32_t template_hash;
    fl.read((char *)&template_hash,sizeof(template_hash));
    return knownSerializers.value(template_hash,eInvalid);
}

template<class T>
T * doLoad(BinStore *bs) {
    T *res = new T;
    if(!loadFrom(bs,res)) {
        delete res;
        res = nullptr;
    }
    return res;
}

template<class T>
T * doLoadRef(BinStore *bs) {
    T *res = new T {};
    if(!loadFrom(bs,*res)) {
        delete res;
        res = nullptr;
    }
    return res;
}

template<class T>
bool doConvert(T *src_struct,const QString &fname,bool text_format=false)
{
    saveTo(*src_struct,fname,text_format);
    delete src_struct;
    return false;
}

void showSupportedBinTypes()
{
    qDebug()<<"Currently supported file types ";
    qDebug()<<"   I0<"<<QString::number(levelsdebts_i0_requiredCrc,16)<<"> Experience data - 'experience.bin'";
    qDebug()<<"   I0<"<<QString::number(particlesystems_i0_requiredCrc,16)<<"> Particle system definitions - 'particles.bin'";
    qDebug()<<"   I0<"<<QString::number(shoplist_i0_requiredCrc,16)<<"> Shops data - 'stores.bin'";
    qDebug()<<"   I0<"<<QString::number(shopitems_i0_requiredCrc,16)<<"> Shops items- 'items.bin'";
    qDebug()<<"   I0<"<<QString::number(shopdepts_i0_requiredCrc,16)<<"> Shop department names data - 'depts.bin'";
    qDebug()<<"   I0<"<<QString::number(attribnames_i0_requiredCrc,16)<<"> Attrib definitions - 'attrib_names.bin'";
    qDebug()<<"   I0<"<<QString::number(tailorcosts_i0_requiredCrc,16)<<"> Tailoring cost data - 'tailorcost.bin'";
    qDebug()<<"   I0<"<<QString::number(costumesets_i0_requiredCrc,16)<<"> Costume part data - 'costume.bin'";
    qDebug()<<"   I0<"<<QString::number(bodyparts_i0_requiredCrc,16)<<"> Body part data - 'BodyParts.bin'";
    qDebug()<<"   I0<"<<QString::number(geoset_i0_requiredCrc,16)<<"> Supergroup emblem data - 'supergroupEmblems.bin'";
    qDebug()<<"   I0<"<<QString::number(palette_i0_requiredCrc,16)<<"> Color palette data - 'supergroupColors.bin'";
    qDebug()<<"   I0-2<"<<QString::number(scenegraph_i0_2_requiredCrc,16)<<"> Scene graph - 'geobin/*'";
    qDebug()<<"   I0<"<<QString::number(tricks_i0_requiredCrc,16)<<"> Trick definitions- 'tricks.bin'";
    qDebug()<<"   I2<"<<QString::number(tricks_i2_requiredCrc,16)<<"> Trick definitions- 'tricks.bin'";
    qDebug()<<"   I0<"<<QString::number(charclass_i0_requiredCrc,16)<<"> Entity class definitions- 'classes.bin' or 'villain_classes.bin'";
    qDebug()<<"   I0<"<<QString::number(origins_i0_requiredCrc,16)<<"> Entity origin definitions- 'origins.bin' or 'villain_origins.bin'";
    qDebug()<<"   I0<"<<QString::number(powers_i0_requiredCrc,16)<<"> Power definitions- 'powers.bin'";
    qDebug()<<"   I0<"<<QString::number(npccostumesets_i0_requiredCrc,16)<<"> NPC definitions - 'VillainCostume.bin'";
    qDebug()<<"   I0<"<<QString::number(fxbehaviors_i0_requiredCrc,16)<<"> FxBehavior definitions - 'behaviors.bin'";
    qDebug()<<"   I0<"<<QString::number(fxinfos_i0_requiredCrc,16)<<"> FxInfo definitions - 'fxinfo.bin'";
    qDebug()<<"Numbers in brackets are file CRCs - bytes 8 to 13 in the bin.";
}
} // end of anonymous namespace

int main(int argc,char **argv)
{
    QCoreApplication app(argc,argv);
    if(app.arguments().size()<2) {
        showSupportedBinTypes();
        return -1;
    }
    BinType bin_type = getLoader(app.arguments()[1]);
    if(bin_type==eInvalid) {
        qCritical() << "Unhandled bin file type";
        showSupportedBinTypes();
        return -1;
    }
    BinStore binfile;
    binfile.open(argv[1],0);
    QString target_basename=QFileInfo(argv[1]).baseName();
    bool json_output=true;

    try // handle possible cereal::RapidJSONException
    {
      if(app.arguments().size()>2)
          json_output = app.arguments()[2].toInt()!=0;

      switch(bin_type)
      {
          case eLevelsDebts:    doConvert(doLoadRef<LevelExpAndDebt>(&binfile),target_basename,json_output); break;
          case eCombineChances: doConvert(doLoadRef<Parse_Combining>(&binfile),target_basename,json_output); break;
          case eBoostEffectiveness: doConvert(doLoadRef<Parse_Effectiveness>(&binfile),target_basename,json_output); break;
          case eParticleSystems:doConvert(doLoad<Parse_AllPSystems>(&binfile),target_basename,json_output); break;
          case eShops:        doConvert(doLoadRef<AllShops_Data>(&binfile),target_basename,json_output); break;
          case eShopItems:    doConvert(doLoad<AllShopItems_Data>(&binfile),target_basename,json_output); break;
          case eShopDepts:    doConvert(doLoad<AllShopDepts_Data>(&binfile),target_basename,json_output); break;
//        case eSequencers:   doConvert(doLoad<SequencerList>(&binfile),target_basename,json_output); break;
          case eTailorCosts:  doConvert(doLoad<AllTailorCosts_Data>(&binfile),target_basename,json_output); break;
          case eCostumeSets:  doConvert(doLoad<CostumeSet_Data>(&binfile),target_basename,json_output); break;
          case eBodyParts:    doConvert(doLoad<AllBodyParts_Data>(&binfile),target_basename,json_output); break;
          case eGroupEmblems: doConvert(doLoad<GeoSet_Data>(&binfile),target_basename,json_output); break;
          case ePaletteSets:  doConvert(doLoad<Pallette_Data>(&binfile),target_basename,json_output); break;
          case eZones:        doConvert(doLoadRef<AllMaps_Data>(&binfile),target_basename,json_output); break;
          case eAttribNames:  doConvert(doLoadRef<AttribNames_Data>(&binfile),target_basename,json_output); break;
          case eSceneGraph:   doConvert(doLoadRef<SceneGraph_Data>(&binfile),target_basename,json_output); break;
          case eTrickDefinitions: doConvert(doLoad<AllTricks_Data>(&binfile),target_basename,json_output); break;
          case eEntityClasses: doConvert(doLoadRef<Parse_AllCharClasses>(&binfile),target_basename,json_output); break;
          case eEntityOrigins: doConvert(doLoadRef<Parse_AllOrigins>(&binfile),target_basename,json_output); break;
          case ePowerDefinitions: doConvert(doLoadRef<AllPowerCategories>(&binfile),target_basename,json_output); break;
          case eNpcDefinitions: doConvert(doLoadRef<AllNpcs_Data>(&binfile),target_basename,json_output); break;
          case eFxBehavior_Definitions: doConvert(doLoadRef<Fx_AllBehaviors>(&binfile),target_basename,json_output); break;
          case eFxInfo_Definitions: doConvert(doLoadRef<Fx_AllInfos>(&binfile),target_basename,json_output); break;
          default:
              break;
      }
    }
    catch(cereal::RapidJSONException &e)
    {
        qWarning() << e.what();
        return -1;
    }
    catch(std::exception &e)
    {
      qCritical() << e.what();
      return -1;
    }

    return 0;
}

//! @}
<commit_msg>Add an option to lookup npc index by name.<commit_after>/*
 * SEGS - Super Entity Game Server
 * http://www.segs.io/
 * Copyright (c) 2006 - 2018 SEGS Team (see AUTHORS.md)
 * This software is licensed under the terms of the 3-clause BSD License. See LICENSE.md for details.
 */

/*!
 * @addtogroup BinConverter Projects/CoX/Utilities/BinConverter
 * @{
 */

#include "Common/GameData/DataStorage.h"
#include "Common/GameData/attrib_definitions.h"
#include "Common/GameData/attrib_serializers.h"
#include "Common/GameData/bodypart_serializers.h"
#include "Common/GameData/costume_definitions.h"
#include "Common/GameData/costume_serializers.h"
#include "Common/GameData/map_definitions.h"
#include "Common/GameData/map_serializers.h"
#include "Common/GameData/scenegraph_definitions.h"
#include "Common/GameData/scenegraph_serializers.h"
#include "Common/GameData/shop_definitions.h"
#include "Common/GameData/shop_serializers.h"
#include "Common/GameData/power_definitions.h"
#include "Common/GameData/power_serializers.h"
#include "Common/GameData/npc_definitions.h"
#include "Common/GameData/npc_serializers.h"
#include "Common/GameData/trick_definitions.h"
#include "Common/GameData/trick_serializers.h"
#include "Common/GameData/fx_definitions.h"
#include "Common/GameData/fx_serializers.h"
#include "Common/GameData/charclass_definitions.h"
#include "Common/GameData/charclass_serializers.h"
#include "Common/GameData/def_serializers.h"
#include "Common/GameData/other_definitions.h"
#include "Common/GameData/origin_definitions.h"
#include "serialization_common.h"
#include "Common/GameData/particlesys_serializers.h"
#include "Common/GameData/particle_definitions.h"

#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
#include <QtCore/QMap>

namespace {
enum BinType {
    eInvalid,
    eLevelsDebts,
    eCombineChances,
    eBoostEffectiveness,
    eParticleSystems,
    eEntityOrigins,
    eEntityClasses,
    eShops,
    eShopItems,
    eShopDepts,
    eSequencers,
    eTailorCosts,
    eCostumeSets,
    eBodyParts,
    ePaletteSets,
    eGroupEmblems,
    eZones,
    eAttribNames,
    eSceneGraph,
    eTrickDefinitions,
    ePowerDefinitions,
    eNpcDefinitions,
    eFxBehavior_Definitions,
    eFxInfo_Definitions,
};

const QHash<uint32_t,BinType> knownSerializers = {
    {levelsdebts_i0_requiredCrc         , eLevelsDebts},
    {combining_i0_requiredCrc           , eCombineChances},
    {boosteffectiveness_i0_requiredCrc  , eBoostEffectiveness},
    {particlesystems_i0_requiredCrc     , eParticleSystems},
    {shoplist_i0_requiredCrc            , eShops},
    {shopitems_i0_requiredCrc           , eShopItems},
    {shopdepts_i0_requiredCrc           , eShopDepts},
//    {seqencerlist_i0_requiredCrc        , eSequencers},
    {tailorcosts_i0_requiredCrc         , eTailorCosts},
    {costumesets_i0_requiredCrc         , eCostumeSets},
    {bodyparts_i0_requiredCrc           , eBodyParts},
    {palette_i0_requiredCrc             , ePaletteSets},
    {geoset_i0_requiredCrc              , eGroupEmblems },
    {zones_i0_requiredCrc               , eZones},
    {attribnames_i0_requiredCrc         , eAttribNames},
    {scenegraph_i0_2_requiredCrc        , eSceneGraph},
    {tricks_i0_requiredCrc              , eTrickDefinitions},
    {tricks_i2_requiredCrc              , eTrickDefinitions},
    {charclass_i0_requiredCrc           , eEntityClasses},
    {origins_i0_requiredCrc             , eEntityOrigins},
    {powers_i0_requiredCrc              , ePowerDefinitions},
    {npccostumesets_i0_requiredCrc      , eNpcDefinitions},
    {fxbehaviors_i0_requiredCrc         , eFxBehavior_Definitions},
    {fxinfos_i0_requiredCrc             , eFxInfo_Definitions},
};

BinType getLoader(const QString &fname)
{
    QFile fl(fname);
    if(!fl.exists() || !fl.open(QFile::ReadOnly)) {
        qDebug() << "Cannot open file:" << fname;
        return eInvalid;
    }
    if(fl.size()<12 || fl.read(8) != "CrypticS") {
        qDebug() << "File "<<fname<<"is missing magic 'CrypticS' string";
        return eInvalid;
    }
    uint32_t template_hash;
    fl.read((char *)&template_hash,sizeof(template_hash));
    return knownSerializers.value(template_hash,eInvalid);
}

template<class T>
T * doLoad(BinStore *bs) {
    T *res = new T;
    if(!loadFrom(bs,res)) {
        delete res;
        res = nullptr;
    }
    return res;
}

template<class T>
T * doLoadRef(BinStore *bs) {
    T *res = new T {};
    if(!loadFrom(bs,*res)) {
        delete res;
        res = nullptr;
    }
    return res;
}

template<class T>
bool doConvert(T *src_struct,const QString &fname,bool text_format=false)
{
    saveTo(*src_struct,fname,text_format);
    delete src_struct;
    return false;
}

void showSupportedBinTypes()
{
    qDebug()<<"Currently supported file types ";
    qDebug()<<"   I0<"<<QString::number(levelsdebts_i0_requiredCrc,16)<<"> Experience data - 'experience.bin'";
    qDebug()<<"   I0<"<<QString::number(particlesystems_i0_requiredCrc,16)<<"> Particle system definitions - 'particles.bin'";
    qDebug()<<"   I0<"<<QString::number(shoplist_i0_requiredCrc,16)<<"> Shops data - 'stores.bin'";
    qDebug()<<"   I0<"<<QString::number(shopitems_i0_requiredCrc,16)<<"> Shops items- 'items.bin'";
    qDebug()<<"   I0<"<<QString::number(shopdepts_i0_requiredCrc,16)<<"> Shop department names data - 'depts.bin'";
    qDebug()<<"   I0<"<<QString::number(attribnames_i0_requiredCrc,16)<<"> Attrib definitions - 'attrib_names.bin'";
    qDebug()<<"   I0<"<<QString::number(tailorcosts_i0_requiredCrc,16)<<"> Tailoring cost data - 'tailorcost.bin'";
    qDebug()<<"   I0<"<<QString::number(costumesets_i0_requiredCrc,16)<<"> Costume part data - 'costume.bin'";
    qDebug()<<"   I0<"<<QString::number(bodyparts_i0_requiredCrc,16)<<"> Body part data - 'BodyParts.bin'";
    qDebug()<<"   I0<"<<QString::number(geoset_i0_requiredCrc,16)<<"> Supergroup emblem data - 'supergroupEmblems.bin'";
    qDebug()<<"   I0<"<<QString::number(palette_i0_requiredCrc,16)<<"> Color palette data - 'supergroupColors.bin'";
    qDebug()<<"   I0-2<"<<QString::number(scenegraph_i0_2_requiredCrc,16)<<"> Scene graph - 'geobin/*'";
    qDebug()<<"   I0<"<<QString::number(tricks_i0_requiredCrc,16)<<"> Trick definitions- 'tricks.bin'";
    qDebug()<<"   I2<"<<QString::number(tricks_i2_requiredCrc,16)<<"> Trick definitions- 'tricks.bin'";
    qDebug()<<"   I0<"<<QString::number(charclass_i0_requiredCrc,16)<<"> Entity class definitions- 'classes.bin' or 'villain_classes.bin'";
    qDebug()<<"   I0<"<<QString::number(origins_i0_requiredCrc,16)<<"> Entity origin definitions- 'origins.bin' or 'villain_origins.bin'";
    qDebug()<<"   I0<"<<QString::number(powers_i0_requiredCrc,16)<<"> Power definitions- 'powers.bin'";
    qDebug()<<"   I0<"<<QString::number(npccostumesets_i0_requiredCrc,16)<<"> NPC definitions - 'VillainCostume.bin'";
    qDebug()<<"   I0<"<<QString::number(fxbehaviors_i0_requiredCrc,16)<<"> FxBehavior definitions - 'behaviors.bin'";
    qDebug()<<"   I0<"<<QString::number(fxinfos_i0_requiredCrc,16)<<"> FxInfo definitions - 'fxinfo.bin'";
    qDebug()<<"Numbers in brackets are file CRCs - bytes 8 to 13 in the bin.";
}
} // end of anonymous namespace

int main(int argc,char **argv)
{
    QCoreApplication app(argc,argv);
    if(app.arguments().size()<2) {
        showSupportedBinTypes();
        return -1;
    }
    BinType bin_type = getLoader(app.arguments()[1]);
    if(bin_type==eInvalid) {
        qCritical() << "Unhandled bin file type";
        showSupportedBinTypes();
        return -1;
    }
    BinStore binfile;
    binfile.open(argv[1],0);
    QString target_basename=QFileInfo(argv[1]).baseName();
    bool json_output=true;

    try // handle possible cereal::RapidJSONException
    {
      if(app.arguments().size()>2)
          json_output = app.arguments()[2].toInt()!=0;

      switch(bin_type)
      {
          case eLevelsDebts:    doConvert(doLoadRef<LevelExpAndDebt>(&binfile),target_basename,json_output); break;
          case eCombineChances: doConvert(doLoadRef<Parse_Combining>(&binfile),target_basename,json_output); break;
          case eBoostEffectiveness: doConvert(doLoadRef<Parse_Effectiveness>(&binfile),target_basename,json_output); break;
          case eParticleSystems:doConvert(doLoad<Parse_AllPSystems>(&binfile),target_basename,json_output); break;
          case eShops:        doConvert(doLoadRef<AllShops_Data>(&binfile),target_basename,json_output); break;
          case eShopItems:    doConvert(doLoad<AllShopItems_Data>(&binfile),target_basename,json_output); break;
          case eShopDepts:    doConvert(doLoad<AllShopDepts_Data>(&binfile),target_basename,json_output); break;
//        case eSequencers:   doConvert(doLoad<SequencerList>(&binfile),target_basename,json_output); break;
          case eTailorCosts:  doConvert(doLoad<AllTailorCosts_Data>(&binfile),target_basename,json_output); break;
          case eCostumeSets:  doConvert(doLoad<CostumeSet_Data>(&binfile),target_basename,json_output); break;
          case eBodyParts:    doConvert(doLoad<AllBodyParts_Data>(&binfile),target_basename,json_output); break;
          case eGroupEmblems: doConvert(doLoad<GeoSet_Data>(&binfile),target_basename,json_output); break;
          case ePaletteSets:  doConvert(doLoad<Pallette_Data>(&binfile),target_basename,json_output); break;
          case eZones:        doConvert(doLoadRef<AllMaps_Data>(&binfile),target_basename,json_output); break;
          case eAttribNames:  doConvert(doLoadRef<AttribNames_Data>(&binfile),target_basename,json_output); break;
          case eSceneGraph:   doConvert(doLoadRef<SceneGraph_Data>(&binfile),target_basename,json_output); break;
          case eTrickDefinitions: doConvert(doLoad<AllTricks_Data>(&binfile),target_basename,json_output); break;
          case eEntityClasses: doConvert(doLoadRef<Parse_AllCharClasses>(&binfile),target_basename,json_output); break;
          case eEntityOrigins: doConvert(doLoadRef<Parse_AllOrigins>(&binfile),target_basename,json_output); break;
          case ePowerDefinitions: doConvert(doLoadRef<AllPowerCategories>(&binfile),target_basename,json_output); break;
          case eNpcDefinitions:
         {
            auto data = doLoadRef<AllNpcs_Data>(&binfile);
            if (qApp->arguments().size() > 2)
            {
                QString name_to_find = app.arguments()[2];
                std::sort(data->begin(), data->end(), [](const Parse_NPC &a, const Parse_NPC &b) -> bool {
                    return a.m_Name.compare(b.m_Name, Qt::CaseInsensitive) < 0;
                });
                auto iter = std::find_if(data->begin(), data->end(), [name_to_find](const Parse_NPC &n) -> bool {
                    if (n.m_Name == name_to_find)
                        return true;
                    return false;
                });
                qDebug() << iter - data->begin();
            } else
                doConvert(data, target_basename, json_output);
        }

          break;
          case eFxBehavior_Definitions: doConvert(doLoadRef<Fx_AllBehaviors>(&binfile),target_basename,json_output); break;
          case eFxInfo_Definitions: doConvert(doLoadRef<Fx_AllInfos>(&binfile),target_basename,json_output); break;
          default:
              break;
      }
    }
    catch(cereal::RapidJSONException &e)
    {
        qWarning() << e.what();
        return -1;
    }
    catch(std::exception &e)
    {
      qCritical() << e.what();
      return -1;
    }

    return 0;
}

//! @}
<|endoftext|>


<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
// Copyright (c) 2014 Francois Beaune, The appleseedhq Organization
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "dictionary.h"

// appleseed.foundation headers.
#include "foundation/utility/foreach.h"

// Standard headers.
#include <cassert>
#include <map>

using namespace std;

namespace foundation
{

typedef map<string, string> StringMap;
typedef map<string, Dictionary> DictionaryMap;

//
// StringDictionary::const_iterator class implementation.
//

struct StringDictionary::const_iterator::Impl
{
    StringMap::const_iterator m_it;
};

StringDictionary::const_iterator::const_iterator()
  : impl(new Impl())
{
}

StringDictionary::const_iterator::const_iterator(const const_iterator& rhs)
  : impl(new Impl(*rhs.impl))
{
}

StringDictionary::const_iterator::~const_iterator()
{
    delete impl;
}

StringDictionary::const_iterator& StringDictionary::const_iterator::operator=(const const_iterator& rhs)
{
    *impl = *rhs.impl;
    return *this;
}

bool StringDictionary::const_iterator::operator==(const const_iterator& rhs) const
{
    return impl->m_it == rhs.impl->m_it;
}

bool StringDictionary::const_iterator::operator!=(const const_iterator& rhs) const
{
    return impl->m_it != rhs.impl->m_it;
}

StringDictionary::const_iterator& StringDictionary::const_iterator::operator++()
{
    ++impl->m_it;
    return *this;
}

StringDictionary::const_iterator& StringDictionary::const_iterator::operator--()
{
    --impl->m_it;
    return *this;
}

const StringDictionary::const_iterator::value_type& StringDictionary::const_iterator::operator*() const
{
    return *this;
}

const char* StringDictionary::const_iterator::name() const
{
    return impl->m_it->first.c_str();
}

const char* StringDictionary::const_iterator::value() const
{
    return impl->m_it->second.c_str();
}

//
// StringDictionary class implementation.
//

struct StringDictionary::Impl
{
    StringMap m_strings;
};

StringDictionary::StringDictionary()
  : impl(new Impl())
{
}

StringDictionary::StringDictionary(const StringDictionary& rhs)
  : impl(new Impl(*rhs.impl))
{
}

StringDictionary::~StringDictionary()
{
    delete impl;
}

StringDictionary& StringDictionary::operator=(const StringDictionary& rhs)
{
    *impl = *rhs.impl;
    return *this;
}

bool StringDictionary::operator==(const StringDictionary& rhs) const
{
    if (size() != rhs.size())
        return false;

    for (
        StringMap::const_iterator it = impl->m_strings.begin(), rhs_it = rhs.impl->m_strings.begin();
        it != impl->m_strings.end();
        ++it, ++rhs_it)
    {
        if (it->first != rhs_it->first || it->second != rhs_it->second)
            return false;
    }

    return true;
}

bool StringDictionary::operator!=(const StringDictionary& rhs) const
{
    return !(*this == rhs);
}

size_t StringDictionary::size() const
{
    return impl->m_strings.size();
}

bool StringDictionary::empty() const
{
    return impl->m_strings.empty();
}

void StringDictionary::clear()
{
    impl->m_strings.clear();
}

StringDictionary& StringDictionary::insert(const char* key, const char* value)
{
    assert(key);
    assert(value);

    impl->m_strings[key] = value;

    return *this;
}

bool StringDictionary::exist(const char* key) const
{
    assert(key);

    return impl->m_strings.find(key) != impl->m_strings.end();
}

const char* StringDictionary::get(const char* key) const
{
    assert(key);

    const StringMap::const_iterator i = impl->m_strings.find(key);

    if (i == impl->m_strings.end())
        throw ExceptionDictionaryItemNotFound(key);

    return i->second.c_str();
}

StringDictionary& StringDictionary::remove(const char* key)
{
    assert(key);

    const StringMap::iterator i = impl->m_strings.find(key);

    if (i != impl->m_strings.end())
        impl->m_strings.erase(i);

    return *this;
}

StringDictionary::const_iterator StringDictionary::begin() const
{
    const_iterator it;
    it.impl->m_it = impl->m_strings.begin();
    return it;
}

StringDictionary::const_iterator StringDictionary::end() const
{
    const_iterator it;
    it.impl->m_it = impl->m_strings.end();
    return it;
}

//
// DictionaryDictionary::const_iterator class implementation.
//

struct DictionaryDictionary::const_iterator::Impl
{
    DictionaryMap::const_iterator m_it;
};

DictionaryDictionary::const_iterator::const_iterator()
  : impl(new Impl())
{
}

DictionaryDictionary::const_iterator::const_iterator(const const_iterator& rhs)
  : impl(new Impl(*rhs.impl))
{
}

DictionaryDictionary::const_iterator::~const_iterator()
{
    delete impl;
}

DictionaryDictionary::const_iterator& DictionaryDictionary::const_iterator::operator=(const const_iterator& rhs)
{
    *impl = *rhs.impl;
    return *this;
}

bool DictionaryDictionary::const_iterator::operator==(const const_iterator& rhs) const
{
    return impl->m_it == rhs.impl->m_it;
}

bool DictionaryDictionary::const_iterator::operator!=(const const_iterator& rhs) const
{
    return impl->m_it != rhs.impl->m_it;
}

DictionaryDictionary::const_iterator& DictionaryDictionary::const_iterator::operator++()
{
    ++impl->m_it;
    return *this;
}

DictionaryDictionary::const_iterator& DictionaryDictionary::const_iterator::operator--()
{
    --impl->m_it;
    return *this;
}

const DictionaryDictionary::const_iterator::value_type& DictionaryDictionary::const_iterator::operator*() const
{
    return *this;
}

const char* DictionaryDictionary::const_iterator::name() const
{
    return impl->m_it->first.c_str();
}

const Dictionary& DictionaryDictionary::const_iterator::value() const
{
    return impl->m_it->second;
}

//
// DictionaryDictionary class implementation.
//

struct DictionaryDictionary::Impl
{
    DictionaryMap m_dictionaries;
};

DictionaryDictionary::DictionaryDictionary()
  : impl(new Impl())
{
}

DictionaryDictionary::DictionaryDictionary(const DictionaryDictionary& rhs)
  : impl(new Impl(*rhs.impl))
{
}

DictionaryDictionary::~DictionaryDictionary()
{
    delete impl;
}

DictionaryDictionary& DictionaryDictionary::operator=(const DictionaryDictionary& rhs)
{
    *impl = *rhs.impl;
    return *this;
}

bool DictionaryDictionary::operator==(const DictionaryDictionary& rhs) const
{
    if (size() != rhs.size())
        return false;

    for (
        DictionaryMap::const_iterator it = impl->m_dictionaries.begin(), rhs_it = rhs.impl->m_dictionaries.begin();
        it != impl->m_dictionaries.end();
        ++it, ++rhs_it)
    {
        if (it->first != rhs_it->first || it->second != rhs_it->second)
            return false;
    }

    return true;
}

bool DictionaryDictionary::operator!=(const DictionaryDictionary& rhs) const
{
    return !(*this == rhs);
}

size_t DictionaryDictionary::size() const
{
    return impl->m_dictionaries.size();
}

bool DictionaryDictionary::empty() const
{
    return impl->m_dictionaries.empty();
}

void DictionaryDictionary::clear()
{
    impl->m_dictionaries.clear();
}

DictionaryDictionary& DictionaryDictionary::insert(const char* key, const Dictionary& value)
{
    assert(key);

    impl->m_dictionaries[key] = value;

    return *this;
}

bool DictionaryDictionary::exist(const char* key) const
{
    assert(key);

    return impl->m_dictionaries.find(key) != impl->m_dictionaries.end();
}

Dictionary& DictionaryDictionary::get(const char* key)
{
    assert(key);

    const DictionaryMap::iterator i = impl->m_dictionaries.find(key);

    if (i == impl->m_dictionaries.end())
        throw ExceptionDictionaryItemNotFound(key);

    return i->second;
}

const Dictionary& DictionaryDictionary::get(const char* key) const
{
    assert(key);

    const DictionaryMap::const_iterator i = impl->m_dictionaries.find(key);

    if (i == impl->m_dictionaries.end())
        throw ExceptionDictionaryItemNotFound(key);

    return i->second;
}

DictionaryDictionary& DictionaryDictionary::remove(const char* key)
{
    assert(key);

    const DictionaryMap::iterator i = impl->m_dictionaries.find(key);

    if (i != impl->m_dictionaries.end())
        impl->m_dictionaries.erase(i);

    return *this;
}

DictionaryDictionary::const_iterator DictionaryDictionary::begin() const
{
    const_iterator it;
    it.impl->m_it = impl->m_dictionaries.begin();
    return it;
}

DictionaryDictionary::const_iterator DictionaryDictionary::end() const
{
    const_iterator it;
    it.impl->m_it = impl->m_dictionaries.end();
    return it;
}

//
// Dictionary class implementation.
//

Dictionary& Dictionary::merge(const Dictionary& rhs)
{
    // Merge strings.
    for (const_each<StringDictionary> i = rhs.strings(); i; ++i)
        insert(i->name(), i->value());

    // Recursively merge dictionaries.
    for (const_each<DictionaryDictionary> i = rhs.dictionaries(); i; ++i)
    {
        if (dictionaries().exist(i->name()))
            dictionary(i->name()).merge(i->value());
        else insert(i->name(), i->value());
    }
}

}   // namespace foundation
<commit_msg>minor cosmetic tweak.<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
// Copyright (c) 2014 Francois Beaune, The appleseedhq Organization
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "dictionary.h"

// appleseed.foundation headers.
#include "foundation/utility/foreach.h"

// Standard headers.
#include <cassert>
#include <map>

using namespace std;

namespace foundation
{

typedef map<string, string> StringMap;
typedef map<string, Dictionary> DictionaryMap;

//
// StringDictionary::const_iterator class implementation.
//

struct StringDictionary::const_iterator::Impl
{
    StringMap::const_iterator m_it;
};

StringDictionary::const_iterator::const_iterator()
  : impl(new Impl())
{
}

StringDictionary::const_iterator::const_iterator(const const_iterator& rhs)
  : impl(new Impl(*rhs.impl))
{
}

StringDictionary::const_iterator::~const_iterator()
{
    delete impl;
}

StringDictionary::const_iterator& StringDictionary::const_iterator::operator=(const const_iterator& rhs)
{
    *impl = *rhs.impl;
    return *this;
}

bool StringDictionary::const_iterator::operator==(const const_iterator& rhs) const
{
    return impl->m_it == rhs.impl->m_it;
}

bool StringDictionary::const_iterator::operator!=(const const_iterator& rhs) const
{
    return impl->m_it != rhs.impl->m_it;
}

StringDictionary::const_iterator& StringDictionary::const_iterator::operator++()
{
    ++impl->m_it;
    return *this;
}

StringDictionary::const_iterator& StringDictionary::const_iterator::operator--()
{
    --impl->m_it;
    return *this;
}

const StringDictionary::const_iterator::value_type& StringDictionary::const_iterator::operator*() const
{
    return *this;
}

const char* StringDictionary::const_iterator::name() const
{
    return impl->m_it->first.c_str();
}

const char* StringDictionary::const_iterator::value() const
{
    return impl->m_it->second.c_str();
}

//
// StringDictionary class implementation.
//

struct StringDictionary::Impl
{
    StringMap m_strings;
};

StringDictionary::StringDictionary()
  : impl(new Impl())
{
}

StringDictionary::StringDictionary(const StringDictionary& rhs)
  : impl(new Impl(*rhs.impl))
{
}

StringDictionary::~StringDictionary()
{
    delete impl;
}

StringDictionary& StringDictionary::operator=(const StringDictionary& rhs)
{
    *impl = *rhs.impl;
    return *this;
}

bool StringDictionary::operator==(const StringDictionary& rhs) const
{
    if (size() != rhs.size())
        return false;

    for (
        StringMap::const_iterator it = impl->m_strings.begin(), rhs_it = rhs.impl->m_strings.begin();
        it != impl->m_strings.end();
        ++it, ++rhs_it)
    {
        if (it->first != rhs_it->first || it->second != rhs_it->second)
            return false;
    }

    return true;
}

bool StringDictionary::operator!=(const StringDictionary& rhs) const
{
    return !(*this == rhs);
}

size_t StringDictionary::size() const
{
    return impl->m_strings.size();
}

bool StringDictionary::empty() const
{
    return impl->m_strings.empty();
}

void StringDictionary::clear()
{
    impl->m_strings.clear();
}

StringDictionary& StringDictionary::insert(const char* key, const char* value)
{
    assert(key);
    assert(value);

    impl->m_strings[key] = value;

    return *this;
}

bool StringDictionary::exist(const char* key) const
{
    assert(key);

    return impl->m_strings.find(key) != impl->m_strings.end();
}

const char* StringDictionary::get(const char* key) const
{
    assert(key);

    const StringMap::const_iterator i = impl->m_strings.find(key);

    if (i == impl->m_strings.end())
        throw ExceptionDictionaryItemNotFound(key);

    return i->second.c_str();
}

StringDictionary& StringDictionary::remove(const char* key)
{
    assert(key);

    const StringMap::iterator i = impl->m_strings.find(key);

    if (i != impl->m_strings.end())
        impl->m_strings.erase(i);

    return *this;
}

StringDictionary::const_iterator StringDictionary::begin() const
{
    const_iterator it;
    it.impl->m_it = impl->m_strings.begin();
    return it;
}

StringDictionary::const_iterator StringDictionary::end() const
{
    const_iterator it;
    it.impl->m_it = impl->m_strings.end();
    return it;
}

//
// DictionaryDictionary::const_iterator class implementation.
//

struct DictionaryDictionary::const_iterator::Impl
{
    DictionaryMap::const_iterator m_it;
};

DictionaryDictionary::const_iterator::const_iterator()
  : impl(new Impl())
{
}

DictionaryDictionary::const_iterator::const_iterator(const const_iterator& rhs)
  : impl(new Impl(*rhs.impl))
{
}

DictionaryDictionary::const_iterator::~const_iterator()
{
    delete impl;
}

DictionaryDictionary::const_iterator& DictionaryDictionary::const_iterator::operator=(const const_iterator& rhs)
{
    *impl = *rhs.impl;
    return *this;
}

bool DictionaryDictionary::const_iterator::operator==(const const_iterator& rhs) const
{
    return impl->m_it == rhs.impl->m_it;
}

bool DictionaryDictionary::const_iterator::operator!=(const const_iterator& rhs) const
{
    return impl->m_it != rhs.impl->m_it;
}

DictionaryDictionary::const_iterator& DictionaryDictionary::const_iterator::operator++()
{
    ++impl->m_it;
    return *this;
}

DictionaryDictionary::const_iterator& DictionaryDictionary::const_iterator::operator--()
{
    --impl->m_it;
    return *this;
}

const DictionaryDictionary::const_iterator::value_type& DictionaryDictionary::const_iterator::operator*() const
{
    return *this;
}

const char* DictionaryDictionary::const_iterator::name() const
{
    return impl->m_it->first.c_str();
}

const Dictionary& DictionaryDictionary::const_iterator::value() const
{
    return impl->m_it->second;
}

//
// DictionaryDictionary class implementation.
//

struct DictionaryDictionary::Impl
{
    DictionaryMap m_dictionaries;
};

DictionaryDictionary::DictionaryDictionary()
  : impl(new Impl())
{
}

DictionaryDictionary::DictionaryDictionary(const DictionaryDictionary& rhs)
  : impl(new Impl(*rhs.impl))
{
}

DictionaryDictionary::~DictionaryDictionary()
{
    delete impl;
}

DictionaryDictionary& DictionaryDictionary::operator=(const DictionaryDictionary& rhs)
{
    *impl = *rhs.impl;
    return *this;
}

bool DictionaryDictionary::operator==(const DictionaryDictionary& rhs) const
{
    if (size() != rhs.size())
        return false;

    for (
        DictionaryMap::const_iterator it = impl->m_dictionaries.begin(), rhs_it = rhs.impl->m_dictionaries.begin();
        it != impl->m_dictionaries.end();
        ++it, ++rhs_it)
    {
        if (it->first != rhs_it->first || it->second != rhs_it->second)
            return false;
    }

    return true;
}

bool DictionaryDictionary::operator!=(const DictionaryDictionary& rhs) const
{
    return !(*this == rhs);
}

size_t DictionaryDictionary::size() const
{
    return impl->m_dictionaries.size();
}

bool DictionaryDictionary::empty() const
{
    return impl->m_dictionaries.empty();
}

void DictionaryDictionary::clear()
{
    impl->m_dictionaries.clear();
}

DictionaryDictionary& DictionaryDictionary::insert(const char* key, const Dictionary& value)
{
    assert(key);

    impl->m_dictionaries[key] = value;

    return *this;
}

bool DictionaryDictionary::exist(const char* key) const
{
    assert(key);

    return impl->m_dictionaries.find(key) != impl->m_dictionaries.end();
}

Dictionary& DictionaryDictionary::get(const char* key)
{
    assert(key);

    const DictionaryMap::iterator i = impl->m_dictionaries.find(key);

    if (i == impl->m_dictionaries.end())
        throw ExceptionDictionaryItemNotFound(key);

    return i->second;
}

const Dictionary& DictionaryDictionary::get(const char* key) const
{
    assert(key);

    const DictionaryMap::const_iterator i = impl->m_dictionaries.find(key);

    if (i == impl->m_dictionaries.end())
        throw ExceptionDictionaryItemNotFound(key);

    return i->second;
}

DictionaryDictionary& DictionaryDictionary::remove(const char* key)
{
    assert(key);

    const DictionaryMap::iterator i = impl->m_dictionaries.find(key);

    if (i != impl->m_dictionaries.end())
        impl->m_dictionaries.erase(i);

    return *this;
}

DictionaryDictionary::const_iterator DictionaryDictionary::begin() const
{
    const_iterator it;
    it.impl->m_it = impl->m_dictionaries.begin();
    return it;
}

DictionaryDictionary::const_iterator DictionaryDictionary::end() const
{
    const_iterator it;
    it.impl->m_it = impl->m_dictionaries.end();
    return it;
}

//
// Dictionary class implementation.
//

Dictionary& Dictionary::merge(const Dictionary& rhs)
{
    // Merge strings.
    for (const_each<StringDictionary> i = rhs.strings(); i; ++i)
        insert(i->name(), i->value());

    // Recursively merge dictionaries.
    for (const_each<DictionaryDictionary> i = rhs.dictionaries(); i; ++i)
    {
        if (dictionaries().exist(i->name()))
            dictionary(i->name()).merge(i->value());
        else insert(i->name(), i->value());
    }
}

}   // namespace foundation
<|endoftext|>


<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
// Copyright (c) 2014-2015 Francois Beaune, The appleseedhq Organization
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// appleseed.renderer headers.
#include "renderer/modeling/frame/frame.h"
#include "renderer/utility/paramarray.h"

// appleseed.foundation headers.
#include "foundation/image/color.h"
#include "foundation/image/pixel.h"
#include "foundation/image/tile.h"
#include "foundation/utility/autoreleaseptr.h"
#include "foundation/utility/benchmark.h"

// Standard headers.
#include <memory>

using namespace foundation;
using namespace renderer;
using namespace std;

BENCHMARK_SUITE(Renderer_Modeling_Frame)
{
    struct Fixture
    {
        auto_release_ptr<Frame> m_frame;
        auto_ptr<Tile>          m_tile;

        Fixture()
          : m_frame(
                FrameFactory::create("frame",
                    ParamArray()
                        .insert("resolution", "1280 720")
                        .insert("tile_size", "32 32")
                        .insert("pixel_format", "float")
                        .insert("color_space", "srgb")))
          , m_tile(new Tile(32, 32, 4, PixelFormatFloat))
        {
            m_tile->clear(Color4f(0.8f, -0.3f, 0.6f, 0.5f));
        }
    };

    BENCHMARK_CASE_F(TransformToOutputColorSpace_GivenTile_AndFrameColorSpaceIsSRGB, Fixture)
    {
        m_frame->transform_to_output_color_space(*m_tile.get());
    }
}
<commit_msg>added unit benchmark.<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
// Copyright (c) 2014-2015 Francois Beaune, The appleseedhq Organization
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// appleseed.renderer headers.
#include "renderer/modeling/frame/frame.h"
#include "renderer/utility/paramarray.h"

// appleseed.foundation headers.
#include "foundation/image/color.h"
#include "foundation/image/pixel.h"
#include "foundation/image/tile.h"
#include "foundation/utility/autoreleaseptr.h"
#include "foundation/utility/benchmark.h"

// Standard headers.
#include <memory>

using namespace foundation;
using namespace renderer;
using namespace std;

BENCHMARK_SUITE(Renderer_Modeling_Frame)
{
    template <PixelFormat pf>
    struct Fixture
    {
        auto_release_ptr<Frame> m_frame;
        auto_ptr<Tile>          m_tile;

        Fixture()
          : m_frame(
                FrameFactory::create("frame",
                    ParamArray()
                        .insert("resolution", "1280 720")
                        .insert("tile_size", "32 32")
                        .insert("pixel_format", "float")
                        .insert("color_space", "srgb")))
          , m_tile(new Tile(32, 32, 4, pf))
        {
            m_tile->clear(Color4f(0.8f, -0.3f, 0.6f, 0.5f));
        }
    };

    BENCHMARK_CASE_F(TransformToOutputColorSpace_GivenTileWithFloatPixels_AndFrameColorSpaceIsSRGB, Fixture<PixelFormatFloat>)
    {
        m_frame->transform_to_output_color_space(*m_tile.get());
    }

    BENCHMARK_CASE_F(TransformToOutputColorSpace_GivenTileWithHalfPixels_AndFrameColorSpaceIsSRGB, Fixture<PixelFormatHalf>)
    {
        m_frame->transform_to_output_color_space(*m_tile.get());
    }
}
<|endoftext|>


<commit_before>
#include "../../Flare.h"
#include "FlareMainOverlay.h"

#include "../../Game/FlareGameUserSettings.h"
#include "../../Player/FlareHUD.h"
#include "../../Player/FlareMenuManager.h"

#include "Runtime/Engine/Classes/Engine/UserInterfaceSettings.h"
#include "Runtime/Engine/Classes/Engine/RendererSettings.h"

#define LOCTEXT_NAMESPACE "FlareMainOverlay"

/*----------------------------------------------------
	Construct
----------------------------------------------------*/

void SFlareMainOverlay::Construct(const FArguments& InArgs)
{
	// Data
	MenuManager = InArgs._MenuManager;
	const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();
	TitleButtonWidth = 2.0f;
	TitleButtonHeight = AFlareMenuManager::GetMainOverlayHeight() / (float)(Theme.ButtonHeight);

	// Create the layout
	ChildSlot
	.VAlign(VAlign_Top)
	.HAlign(HAlign_Fill)
	[
		SAssignNew(Background, SBackgroundBlur)
		.BlurRadius(30)
		.BlurStrength(10)
		.HAlign(HAlign_Fill)
		.VAlign(VAlign_Fill)
		.Padding(FMargin(0))
		[
			SNew(SBorder)
			.HAlign(HAlign_Fill)
			.VAlign(VAlign_Fill)
			.Padding(FMargin(0))
			.BorderImage(FFlareStyleSet::Get().GetBrush("/Brushes/SB_Black"))
			.BorderBackgroundColor(FLinearColor(1, 1, 1, 0.7f))
			[
				SNew(SVerticalBox)

				+ SVerticalBox::Slot()
				.AutoHeight()
				.HAlign(HAlign_Fill)
				.VAlign(VAlign_Fill)
				[
					SAssignNew(MenuList, SHorizontalBox)

					// Title
					+ SHorizontalBox::Slot()
					.AutoWidth()
					[
						SNew(SBox)
						.HAlign(HAlign_Fill)
						.WidthOverride(0.625 * Theme.ContentWidth)
						[
							SNew(SHorizontalBox)

							// Title icon
							+ SHorizontalBox::Slot()
							.AutoWidth()
							.VAlign(VAlign_Center)
							[
								SNew(SImage)
								.Image(this, &SFlareMainOverlay::GetCurrentMenuIcon)
							]

							// Title text
							+ SHorizontalBox::Slot()
							.VAlign(VAlign_Center)
							.AutoWidth()
							[
								SNew(SVerticalBox)

								+ SVerticalBox::Slot()
								.AutoHeight()
								.Padding(Theme.SmallContentPadding)
								[
									SNew(STextBlock)
									.TextStyle(&Theme.TitleFont)
									.Text(this, &SFlareMainOverlay::GetCurrentMenuName)
								]

								+ SVerticalBox::Slot()
								.AutoHeight()
								.Padding(Theme.SmallContentPadding)
								[
									SNew(STextBlock)
									.TextStyle(&Theme.TextFont)
									.Text(this, &SFlareMainOverlay::GetPlayerInfo)
								]
							]
						]
					]
				]

				// Bottom border
				+ SVerticalBox::Slot()
				.AutoHeight()
				.HAlign(HAlign_Fill)
				[
					SAssignNew(Border, SImage)
					.Image(&Theme.NearInvisibleBrush)
				]
			]
		]
	];

	// Add general gameplay menus
	AddMenuLink(EFlareMenu::MENU_Ship);
	AddMenuLink(EFlareMenu::MENU_Sector);
	AddMenuLink(EFlareMenu::MENU_Orbit);
	AddMenuLink(EFlareMenu::MENU_Leaderboard);
	AddMenuLink(EFlareMenu::MENU_Company);
	AddMenuLink(EFlareMenu::MENU_Fleet);
	AddMenuLink(EFlareMenu::MENU_Quest);
	AddMenuLink(EFlareMenu::MENU_Main);

	// Settings
	TSharedPtr<SFlareButton> SettingsButton;
	MenuList->AddSlot()
	.HAlign(HAlign_Right)
	[
		SAssignNew(SettingsButton, SFlareButton)
		.Width(TitleButtonWidth)
		.Height(TitleButtonHeight)
		.Transparent(true)
		.OnClicked(this, &SFlareMainOverlay::OnOpenMenu, EFlareMenu::MENU_Settings)
	];
	SetupMenuLink(SettingsButton,
		AFlareMenuManager::GetMenuIcon(EFlareMenu::MENU_Settings),
		AFlareMenuManager::GetMenuName(EFlareMenu::MENU_Settings),
		AFlareMenuManager::GetMenuKey(EFlareMenu::MENU_Settings),
		false);

	// Back, exit
	TSharedPtr<SFlareButton> BackButton;
	TSharedPtr<SFlareButton> ExitButton;
	MenuList->AddSlot()
	.AutoWidth()
	.HAlign(HAlign_Right)
	[
		SNew(SVerticalBox)

		// Back button
		+ SVerticalBox::Slot()
		.AutoHeight()
		[
			SAssignNew(BackButton, SFlareButton)
			.Width(TitleButtonWidth)
			.Height(TitleButtonHeight / 2)
			.Transparent(true)
			.OnClicked(this, &SFlareMainOverlay::OnBack)
			.IsDisabled(this, &SFlareMainOverlay::IsBackDisabled)
		]

		// Exit button
		+ SVerticalBox::Slot()
		.AutoHeight()
		[
			SAssignNew(ExitButton, SFlareButton)
			.Width(TitleButtonWidth)
			.Height(TitleButtonHeight / 2)
			.Transparent(true)
			.OnClicked(this, &SFlareMainOverlay::OnCloseMenu)
			.IsDisabled(this, &SFlareMainOverlay::IsCloseDisabled)
		]
	];

	// Back, exit config
	SetupMenuLink(BackButton, FFlareStyleSet::GetIcon("Back"), FText(), FString(), true);
	ExitButton->GetContainer()->SetHAlign(HAlign_Center);
	ExitButton->GetContainer()->SetVAlign(VAlign_Fill);
	ExitButton->GetContainer()->SetPadding(FMargin(0, 5));
	ExitButton->GetContainer()->SetContent(
		SNew(SVerticalBox)

		// Icon
		+ SVerticalBox::Slot()
		.AutoHeight()
		.HAlign(HAlign_Center)
		[
			SNew(SBox)
			.WidthOverride(64)
			.HeightOverride(64)
			[
				SNew(SImage)
				.Image(this, &SFlareMainOverlay::GetCloseIcon)
			]
		]);

	// Init
	Close();
}

void SFlareMainOverlay::AddMenuLink(EFlareMenu::Type Menu)
{
	TSharedPtr<SFlareButton> Button;

	// Create button
	MenuList->AddSlot()
	.AutoWidth()
	.HAlign(HAlign_Right)
	[
		SAssignNew(Button, SFlareButton)
		.Width(TitleButtonWidth)
		.Height(TitleButtonHeight)
		.Transparent(true)
		.OnClicked(this, &SFlareMainOverlay::OnOpenMenu, Menu)
		.Visibility(this, &SFlareMainOverlay::GetGameButtonVisibility)
	];

	// Fill button contents
	SetupMenuLink(Button,
		AFlareMenuManager::GetMenuIcon(Menu),
		AFlareMenuManager::GetMenuName(Menu),
		AFlareMenuManager::GetMenuKey(Menu),
		false);
}

void SFlareMainOverlay::SetupMenuLink(TSharedPtr<SFlareButton> Button, const FSlateBrush* Icon, FText Text, FString Key, bool Small)
{
	const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();

	Button->GetContainer()->SetHAlign(HAlign_Center);
	Button->GetContainer()->SetVAlign(VAlign_Fill);
	Button->GetContainer()->SetPadding(FMargin(0, Small ? 5 : 25));

	Button->GetContainer()->SetContent(
		SNew(SVerticalBox)

		// Icon
		+ SVerticalBox::Slot()
		.AutoHeight()
		.HAlign(HAlign_Center)
		[
			SNew(SBox)
			.WidthOverride(64)
			.HeightOverride(64)
			[
				SNew(SImage)
				.Image(Icon)
			]
		]

		// Text
		+ SVerticalBox::Slot()
		.AutoHeight()
		.HAlign(HAlign_Center)
		[
			SNew(STextBlock)
			.TextStyle(&Theme.SmallFont)
			.Text(Text)
		]

		// Shortcut
		+ SVerticalBox::Slot()
		.AutoHeight()
		.HAlign(HAlign_Center)
		[
			SNew(STextBlock)
			.TextStyle(&Theme.SmallFont)
			.Text(FText::Format(LOCTEXT("ShortcutKeyFormat", "({0})"), FText::FromString(Key)))
		]
	);
}

/*----------------------------------------------------
	Interaction
----------------------------------------------------*/

void SFlareMainOverlay::Open()
{
	IsOverlayVisible = true;
	Background->SetVisibility(EVisibility::Visible);
}

void SFlareMainOverlay::Close()
{
	IsOverlayVisible = false;
	Background->SetVisibility(EVisibility::Hidden);
}

bool SFlareMainOverlay::IsOpen() const
{
	return IsOverlayVisible;
}

/*----------------------------------------------------
	Callbacks
----------------------------------------------------*/

void SFlareMainOverlay::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime)
{
	SCompoundWidget::Tick(AllottedGeometry, InCurrentTime, InDeltaTime);

	// Get 2D position
	FVector2D MousePosition = MenuManager->GetPC()->GetMousePosition();
	FVector2D ViewportSize = FVector2D(GEngine->GameViewport->Viewport->GetSizeXY());
	float ViewportScale = GetDefault<UUserInterfaceSettings>(UUserInterfaceSettings::StaticClass())->GetDPIScaleBasedOnSize(FIntPoint(ViewportSize.X, ViewportSize.Y));

	// Visibility check
	float Height = AFlareMenuManager::GetMainOverlayHeight() + 2.0f;
	if (!IsOverlayVisible || (MousePosition.Y / ViewportScale) > Height)
	{
		SetVisibility(EVisibility::HitTestInvisible);
	}
	else
	{
		SetVisibility(EVisibility::Visible);
	}
}

EVisibility SFlareMainOverlay::GetGameButtonVisibility() const
{
	if (MenuManager->GetPC()->GetShipPawn())
	{
		return EVisibility::Visible;
	}
	else if (MenuManager->GetCurrentMenu() == EFlareMenu::MENU_None
		|| MenuManager->GetCurrentMenu() == EFlareMenu::MENU_Main
		|| MenuManager->GetCurrentMenu() == EFlareMenu::MENU_NewGame
		|| MenuManager->GetCurrentMenu() == EFlareMenu::MENU_Settings
		|| MenuManager->GetCurrentMenu() == EFlareMenu::MENU_Credits
		|| MenuManager->GetCurrentMenu() == EFlareMenu::MENU_Story)
	{
		return EVisibility::Hidden;
	}
	else
	{
		return EVisibility::Visible;
	}
}

bool SFlareMainOverlay::IsBackDisabled() const
{
	return (MenuManager->HasPreviousMenu() == false);
}

bool SFlareMainOverlay::IsCloseDisabled() const
{
	if (MenuManager->GetCurrentMenu() == EFlareMenu::MENU_Main)
	{
		return false;
	}
	else if (MenuManager->GetPC()->GetShipPawn())
	{
		return false;
	}
	else
	{
		return true;
	}
}

const FSlateBrush* SFlareMainOverlay::GetCloseIcon() const
{
	if (MenuManager->GetCurrentMenu() == EFlareMenu::MENU_Main)
	{
		return FFlareStyleSet::GetIcon("Quit");
	}
	else
	{
		return FFlareStyleSet::GetIcon("Close");
	}
}

FText SFlareMainOverlay::GetCurrentMenuName() const
{
	FText Name;

	if (MenuManager->IsMenuOpen())
	{
		Name = AFlareMenuManager::GetMenuName(MenuManager->GetCurrentMenu());
	}
	else
	{
		Name = LOCTEXT("FlyingText", "Flying");
	}

	return FText::FromString(Name.ToString().ToUpper());
}

const FSlateBrush* SFlareMainOverlay::GetCurrentMenuIcon() const
{
	if (MenuManager->IsMenuOpen())
	{
		return AFlareMenuManager::GetMenuIcon(MenuManager->GetCurrentMenu());
	}
	else
	{
		return AFlareMenuManager::GetMenuIcon(EFlareMenu::MENU_Sector);
	}
}

FText SFlareMainOverlay::GetPlayerInfo() const
{
	AFlarePlayerController* PC = MenuManager->GetPC();

	if (PC->GetShipPawn())
	{
		return FText::Format(LOCTEXT("PlayerInfoFormat", "{0}\n{1} credits available"),
			PC->GetShipPawn()->GetShipStatus(),
			FText::AsNumber(PC->GetCompany()->GetMoney() / 100));
	}
	else if (MenuManager->GetCurrentMenu() == EFlareMenu::MENU_Main)
	{
		return LOCTEXT("SaveSlotHint", "Pick a save slot");
	}
	else if (MenuManager->GetCurrentMenu() == EFlareMenu::MENU_NewGame)
	{
		return LOCTEXT("NewGameHint", "Please describe your company");
	}
	else if (MenuManager->GetCurrentMenu() == EFlareMenu::MENU_Settings)
	{
		return LOCTEXT("SettingsHint", "Changes will be applied and saved");
	}
	else if (MenuManager->GetCurrentMenu() == EFlareMenu::MENU_None
		|| MenuManager->GetCurrentMenu() == EFlareMenu::MENU_Credits
		|| MenuManager->GetCurrentMenu() == EFlareMenu::MENU_Story)
	{
		return FText();
	}
	else if (!MenuManager->IsFading())
	{
		return LOCTEXT("FastForwarding", "Fast forwarding...\n");
	}

	return FText();
}

void SFlareMainOverlay::OnOpenMenu(EFlareMenu::Type Menu)
{
	MenuManager->OpenMenu(Menu);
}

void SFlareMainOverlay::OnBack()
{
	MenuManager->Back();
}

void SFlareMainOverlay::OnCloseMenu()
{
	if (MenuManager->GetCurrentMenu() == EFlareMenu::MENU_Main)
	{
		MenuManager->OpenMenu(EFlareMenu::MENU_Quit);
	}
	else if (MenuManager->IsMenuOpen())
	{
		MenuManager->CloseMenu();
	}
	else
	{
		MenuManager->CloseMainOverlay();
	}
}

#undef LOCTEXT_NAMESPACE
<commit_msg>Move main menu with the settings on the right of the main overlay<commit_after>
#include "../../Flare.h"
#include "FlareMainOverlay.h"

#include "../../Game/FlareGameUserSettings.h"
#include "../../Player/FlareHUD.h"
#include "../../Player/FlareMenuManager.h"

#include "Runtime/Engine/Classes/Engine/UserInterfaceSettings.h"
#include "Runtime/Engine/Classes/Engine/RendererSettings.h"

#define LOCTEXT_NAMESPACE "FlareMainOverlay"

/*----------------------------------------------------
	Construct
----------------------------------------------------*/

void SFlareMainOverlay::Construct(const FArguments& InArgs)
{
	// Data
	MenuManager = InArgs._MenuManager;
	const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();
	TitleButtonWidth = 2.0f;
	TitleButtonHeight = AFlareMenuManager::GetMainOverlayHeight() / (float)(Theme.ButtonHeight);

	// Create the layout
	ChildSlot
	.VAlign(VAlign_Top)
	.HAlign(HAlign_Fill)
	[
		SAssignNew(Background, SBackgroundBlur)
		.BlurRadius(30)
		.BlurStrength(10)
		.HAlign(HAlign_Fill)
		.VAlign(VAlign_Fill)
		.Padding(FMargin(0))
		[
			SNew(SBorder)
			.HAlign(HAlign_Fill)
			.VAlign(VAlign_Fill)
			.Padding(FMargin(0))
			.BorderImage(FFlareStyleSet::Get().GetBrush("/Brushes/SB_Black"))
			.BorderBackgroundColor(FLinearColor(1, 1, 1, 0.7f))
			[
				SNew(SVerticalBox)

				+ SVerticalBox::Slot()
				.AutoHeight()
				.HAlign(HAlign_Fill)
				.VAlign(VAlign_Fill)
				[
					SAssignNew(MenuList, SHorizontalBox)

					// Title
					+ SHorizontalBox::Slot()
					.AutoWidth()
					[
						SNew(SBox)
						.HAlign(HAlign_Fill)
						.WidthOverride(0.625 * Theme.ContentWidth)
						[
							SNew(SHorizontalBox)

							// Title icon
							+ SHorizontalBox::Slot()
							.AutoWidth()
							.VAlign(VAlign_Center)
							[
								SNew(SImage)
								.Image(this, &SFlareMainOverlay::GetCurrentMenuIcon)
							]

							// Title text
							+ SHorizontalBox::Slot()
							.VAlign(VAlign_Center)
							.AutoWidth()
							[
								SNew(SVerticalBox)

								+ SVerticalBox::Slot()
								.AutoHeight()
								.Padding(Theme.SmallContentPadding)
								[
									SNew(STextBlock)
									.TextStyle(&Theme.TitleFont)
									.Text(this, &SFlareMainOverlay::GetCurrentMenuName)
								]

								+ SVerticalBox::Slot()
								.AutoHeight()
								.Padding(Theme.SmallContentPadding)
								[
									SNew(STextBlock)
									.TextStyle(&Theme.TextFont)
									.Text(this, &SFlareMainOverlay::GetPlayerInfo)
								]
							]
						]
					]
				]

				// Bottom border
				+ SVerticalBox::Slot()
				.AutoHeight()
				.HAlign(HAlign_Fill)
				[
					SAssignNew(Border, SImage)
					.Image(&Theme.NearInvisibleBrush)
				]
			]
		]
	];

	// Add general gameplay menus
	AddMenuLink(EFlareMenu::MENU_Ship);
	AddMenuLink(EFlareMenu::MENU_Sector);
	AddMenuLink(EFlareMenu::MENU_Orbit);
	AddMenuLink(EFlareMenu::MENU_Leaderboard);
	AddMenuLink(EFlareMenu::MENU_Company);
	AddMenuLink(EFlareMenu::MENU_Fleet);
	AddMenuLink(EFlareMenu::MENU_Quest);

	// Main
	TSharedPtr<SFlareButton> MainButton;
	MenuList->AddSlot()
	.HAlign(HAlign_Right)
	[
		SAssignNew(MainButton, SFlareButton)
		.Width(TitleButtonWidth)
		.Height(TitleButtonHeight)
		.Transparent(true)
		.OnClicked(this, &SFlareMainOverlay::OnOpenMenu, EFlareMenu::MENU_Main)
		.Visibility(this, &SFlareMainOverlay::GetGameButtonVisibility)
	];
	SetupMenuLink(MainButton,
		AFlareMenuManager::GetMenuIcon(EFlareMenu::MENU_Main),
		AFlareMenuManager::GetMenuName(EFlareMenu::MENU_Main),
		AFlareMenuManager::GetMenuKey(EFlareMenu::MENU_Main),
		false);

	// Settings
	TSharedPtr<SFlareButton> SettingsButton;
	MenuList->AddSlot()
	.HAlign(HAlign_Right)
	.AutoWidth()
	[
		SAssignNew(SettingsButton, SFlareButton)
		.Width(TitleButtonWidth)
		.Height(TitleButtonHeight)
		.Transparent(true)
		.OnClicked(this, &SFlareMainOverlay::OnOpenMenu, EFlareMenu::MENU_Settings)
	];
	SetupMenuLink(SettingsButton,
		AFlareMenuManager::GetMenuIcon(EFlareMenu::MENU_Settings),
		AFlareMenuManager::GetMenuName(EFlareMenu::MENU_Settings),
		AFlareMenuManager::GetMenuKey(EFlareMenu::MENU_Settings),
		false);

	// Back, exit
	TSharedPtr<SFlareButton> BackButton;
	TSharedPtr<SFlareButton> ExitButton;
	MenuList->AddSlot()
	.AutoWidth()
	.HAlign(HAlign_Right)
	[
		SNew(SVerticalBox)

		// Back button
		+ SVerticalBox::Slot()
		.AutoHeight()
		[
			SAssignNew(BackButton, SFlareButton)
			.Width(TitleButtonWidth)
			.Height(TitleButtonHeight / 2)
			.Transparent(true)
			.OnClicked(this, &SFlareMainOverlay::OnBack)
			.IsDisabled(this, &SFlareMainOverlay::IsBackDisabled)
		]

		// Exit button
		+ SVerticalBox::Slot()
		.AutoHeight()
		[
			SAssignNew(ExitButton, SFlareButton)
			.Width(TitleButtonWidth)
			.Height(TitleButtonHeight / 2)
			.Transparent(true)
			.OnClicked(this, &SFlareMainOverlay::OnCloseMenu)
			.IsDisabled(this, &SFlareMainOverlay::IsCloseDisabled)
		]
	];

	// Back, exit config
	SetupMenuLink(BackButton, FFlareStyleSet::GetIcon("Back"), FText(), FString(), true);
	ExitButton->GetContainer()->SetHAlign(HAlign_Center);
	ExitButton->GetContainer()->SetVAlign(VAlign_Fill);
	ExitButton->GetContainer()->SetPadding(FMargin(0, 5));
	ExitButton->GetContainer()->SetContent(
		SNew(SVerticalBox)

		// Icon
		+ SVerticalBox::Slot()
		.AutoHeight()
		.HAlign(HAlign_Center)
		[
			SNew(SBox)
			.WidthOverride(64)
			.HeightOverride(64)
			[
				SNew(SImage)
				.Image(this, &SFlareMainOverlay::GetCloseIcon)
			]
		]);

	// Init
	Close();
}

void SFlareMainOverlay::AddMenuLink(EFlareMenu::Type Menu)
{
	TSharedPtr<SFlareButton> Button;

	// Create button
	MenuList->AddSlot()
	.AutoWidth()
	.HAlign(HAlign_Right)
	[
		SAssignNew(Button, SFlareButton)
		.Width(TitleButtonWidth)
		.Height(TitleButtonHeight)
		.Transparent(true)
		.OnClicked(this, &SFlareMainOverlay::OnOpenMenu, Menu)
		.Visibility(this, &SFlareMainOverlay::GetGameButtonVisibility)
	];

	// Fill button contents
	SetupMenuLink(Button,
		AFlareMenuManager::GetMenuIcon(Menu),
		AFlareMenuManager::GetMenuName(Menu),
		AFlareMenuManager::GetMenuKey(Menu),
		false);
}

void SFlareMainOverlay::SetupMenuLink(TSharedPtr<SFlareButton> Button, const FSlateBrush* Icon, FText Text, FString Key, bool Small)
{
	const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();

	Button->GetContainer()->SetHAlign(HAlign_Center);
	Button->GetContainer()->SetVAlign(VAlign_Fill);
	Button->GetContainer()->SetPadding(FMargin(0, Small ? 5 : 25));

	Button->GetContainer()->SetContent(
		SNew(SVerticalBox)

		// Icon
		+ SVerticalBox::Slot()
		.AutoHeight()
		.HAlign(HAlign_Center)
		[
			SNew(SBox)
			.WidthOverride(64)
			.HeightOverride(64)
			[
				SNew(SImage)
				.Image(Icon)
			]
		]

		// Text
		+ SVerticalBox::Slot()
		.AutoHeight()
		.HAlign(HAlign_Center)
		[
			SNew(STextBlock)
			.TextStyle(&Theme.SmallFont)
			.Text(Text)
		]

		// Shortcut
		+ SVerticalBox::Slot()
		.AutoHeight()
		.HAlign(HAlign_Center)
		[
			SNew(STextBlock)
			.TextStyle(&Theme.SmallFont)
			.Text(FText::Format(LOCTEXT("ShortcutKeyFormat", "({0})"), FText::FromString(Key)))
		]
	);
}

/*----------------------------------------------------
	Interaction
----------------------------------------------------*/

void SFlareMainOverlay::Open()
{
	IsOverlayVisible = true;
	Background->SetVisibility(EVisibility::Visible);
}

void SFlareMainOverlay::Close()
{
	IsOverlayVisible = false;
	Background->SetVisibility(EVisibility::Hidden);
}

bool SFlareMainOverlay::IsOpen() const
{
	return IsOverlayVisible;
}

/*----------------------------------------------------
	Callbacks
----------------------------------------------------*/

void SFlareMainOverlay::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime)
{
	SCompoundWidget::Tick(AllottedGeometry, InCurrentTime, InDeltaTime);

	// Get 2D position
	FVector2D MousePosition = MenuManager->GetPC()->GetMousePosition();
	FVector2D ViewportSize = FVector2D(GEngine->GameViewport->Viewport->GetSizeXY());
	float ViewportScale = GetDefault<UUserInterfaceSettings>(UUserInterfaceSettings::StaticClass())->GetDPIScaleBasedOnSize(FIntPoint(ViewportSize.X, ViewportSize.Y));

	// Visibility check
	float Height = AFlareMenuManager::GetMainOverlayHeight() + 2.0f;
	if (!IsOverlayVisible || (MousePosition.Y / ViewportScale) > Height)
	{
		SetVisibility(EVisibility::HitTestInvisible);
	}
	else
	{
		SetVisibility(EVisibility::Visible);
	}
}

EVisibility SFlareMainOverlay::GetGameButtonVisibility() const
{
	if (MenuManager->GetPC()->GetShipPawn())
	{
		return EVisibility::Visible;
	}
	else if (MenuManager->GetCurrentMenu() == EFlareMenu::MENU_None
		|| MenuManager->GetCurrentMenu() == EFlareMenu::MENU_Main
		|| MenuManager->GetCurrentMenu() == EFlareMenu::MENU_NewGame
		|| MenuManager->GetCurrentMenu() == EFlareMenu::MENU_Settings
		|| MenuManager->GetCurrentMenu() == EFlareMenu::MENU_Credits
		|| MenuManager->GetCurrentMenu() == EFlareMenu::MENU_Story)
	{
		return EVisibility::Hidden;
	}
	else
	{
		return EVisibility::Visible;
	}
}

bool SFlareMainOverlay::IsBackDisabled() const
{
	return (MenuManager->HasPreviousMenu() == false);
}

bool SFlareMainOverlay::IsCloseDisabled() const
{
	if (MenuManager->GetCurrentMenu() == EFlareMenu::MENU_Main)
	{
		return false;
	}
	else if (MenuManager->GetPC()->GetShipPawn())
	{
		return false;
	}
	else
	{
		return true;
	}
}

const FSlateBrush* SFlareMainOverlay::GetCloseIcon() const
{
	if (MenuManager->GetCurrentMenu() == EFlareMenu::MENU_Main)
	{
		return FFlareStyleSet::GetIcon("Quit");
	}
	else
	{
		return FFlareStyleSet::GetIcon("Close");
	}
}

FText SFlareMainOverlay::GetCurrentMenuName() const
{
	FText Name;

	if (MenuManager->IsMenuOpen())
	{
		Name = AFlareMenuManager::GetMenuName(MenuManager->GetCurrentMenu());
	}
	else
	{
		Name = LOCTEXT("FlyingText", "Flying");
	}

	return FText::FromString(Name.ToString().ToUpper());
}

const FSlateBrush* SFlareMainOverlay::GetCurrentMenuIcon() const
{
	if (MenuManager->IsMenuOpen())
	{
		return AFlareMenuManager::GetMenuIcon(MenuManager->GetCurrentMenu());
	}
	else
	{
		return AFlareMenuManager::GetMenuIcon(EFlareMenu::MENU_Sector);
	}
}

FText SFlareMainOverlay::GetPlayerInfo() const
{
	AFlarePlayerController* PC = MenuManager->GetPC();

	if (PC->GetShipPawn())
	{
		return FText::Format(LOCTEXT("PlayerInfoFormat", "{0}\n{1} credits available"),
			PC->GetShipPawn()->GetShipStatus(),
			FText::AsNumber(PC->GetCompany()->GetMoney() / 100));
	}
	else if (MenuManager->GetCurrentMenu() == EFlareMenu::MENU_Main)
	{
		return LOCTEXT("SaveSlotHint", "Pick a save slot");
	}
	else if (MenuManager->GetCurrentMenu() == EFlareMenu::MENU_NewGame)
	{
		return LOCTEXT("NewGameHint", "Please describe your company");
	}
	else if (MenuManager->GetCurrentMenu() == EFlareMenu::MENU_Settings)
	{
		return LOCTEXT("SettingsHint", "Changes will be applied and saved");
	}
	else if (MenuManager->GetCurrentMenu() == EFlareMenu::MENU_None
		|| MenuManager->GetCurrentMenu() == EFlareMenu::MENU_Credits
		|| MenuManager->GetCurrentMenu() == EFlareMenu::MENU_Story)
	{
		return FText();
	}
	else if (!MenuManager->IsFading())
	{
		return LOCTEXT("FastForwarding", "Fast forwarding...\n");
	}

	return FText();
}

void SFlareMainOverlay::OnOpenMenu(EFlareMenu::Type Menu)
{
	MenuManager->OpenMenu(Menu);
}

void SFlareMainOverlay::OnBack()
{
	MenuManager->Back();
}

void SFlareMainOverlay::OnCloseMenu()
{
	if (MenuManager->GetCurrentMenu() == EFlareMenu::MENU_Main)
	{
		MenuManager->OpenMenu(EFlareMenu::MENU_Quit);
	}
	else if (MenuManager->IsMenuOpen())
	{
		MenuManager->CloseMenu();
	}
	else
	{
		MenuManager->CloseMainOverlay();
	}
}

#undef LOCTEXT_NAMESPACE
<|endoftext|>


<commit_before>#include "ScreenMenu.hpp"
#include "Config.hpp"
#include "MusicManager.hpp"
#include "SoundManager.hpp"
#include "TextureManager.hpp"
#include <iostream>

ScreenMenu::ScreenMenu( GameRef& gameRef )
    : Screen( gameRef ) {
    loadAssets();

    playButton.setPosition( WINDOW_WIDTH - playButton.getGlobalBounds().width,
                            ( WINDOW_HEIGHT - playButton.getGlobalBounds().height ) / 2 - 30 );

    creditsButton.setPosition( WINDOW_WIDTH - creditsButton.getGlobalBounds().width,
                               playButton.getGlobalBounds().top +
                                   playButton.getGlobalBounds().height );

    audioButton.setScale( sf::Vector2f( 0.25, 0.25 ) );
    audioButton.setPosition( WINDOW_WIDTH - ( audioButton.getGlobalBounds().width + 10 ),
                             WINDOW_HEIGHT - ( audioButton.getGlobalBounds().height + 10 ) );
}

void ScreenMenu::loadAssets() {
    TextureManager::add( "backgroundMenu", "menu.jpg" );
    background.setTexture( TextureManager::get( "backgroundMenu" ) );

    TextureManager::add( "playButton", "play.png", true );
    playButton.setTexture( TextureManager::get( "playButton" ) );

    TextureManager::add( "creditsButton", "credits.png", true );
    creditsButton.setTexture( TextureManager::get( "creditsButton" ) );

    TextureManager::add( "audioButtonOn", "audio_on.png", true );
    TextureManager::add( "audioButtonOff", "audio_off.png", true );
    audioButton.setTexture( TextureManager::get( "audioButtonOn" ) );

    music = &MusicManager::add( "musicMenu", "menu.ogg" );
    music->setLoop( true );

    SoundManager::add( "clickSound", "choice.ogg" );
    clickSound.setBuffer( SoundManager::get( "clickSound" ) );
}
void ScreenMenu::draw() {
    window->clear();

    window->draw( background );
    window->draw( playButton );
    window->draw( creditsButton );
    window->draw( audioButton );

    window->display();
}
void ScreenMenu::update() {
    if( *isAudioOn && music->getStatus() != sf::SoundSource::Status::Playing ) {
        music->play();
    }

    if( !*isAudioOn ) {
        audioButton.setTexture( TextureManager::get( "audioButtonOff" ) );

    } else {
        audioButton.setTexture( TextureManager::get( "audioButtonOn" ) );
    }

    while( window->pollEvent( *event ) ) {
        if( event->type == sf::Event::Closed ) {
            music->stop();
            window->close();
        }

        // TODO: Mudar o cursor quando o mouse estiver em cima de um botão (C++)
        if( inputManager->isSpriteClicked( sf::Mouse::Button::Left, audioButton ) ) {
            if( *isAudioOn ) {
                clickSound.play();
                music->pause();
            }
            *isAudioOn = !*isAudioOn;
        }

        if( inputManager->isSpriteClicked( sf::Mouse::Button::Left, playButton ) ) {
            if( *isAudioOn ) {
                clickSound.play();
            }
            music->stop();
            *nextScreen = JOGAR;
        }

        if( inputManager->isSpriteClicked( sf::Mouse::Button::Left, creditsButton ) ) {
            if( *isAudioOn ) {
                clickSound.play();
            }
            music->stop();
            *nextScreen = CREDITOS;
        }
    }

    draw();
}
<commit_msg>Chamando tela de mostrar<commit_after>#include "ScreenMenu.hpp"
#include "Config.hpp"
#include "MusicManager.hpp"
#include "SoundManager.hpp"
#include "TextureManager.hpp"
#include <iostream>

ScreenMenu::ScreenMenu( GameRef& gameRef )
    : Screen( gameRef ) {
    loadAssets();

    playButton.setPosition( WINDOW_WIDTH - playButton.getGlobalBounds().width,
                            ( WINDOW_HEIGHT - playButton.getGlobalBounds().height ) / 2 - 30 );

    creditsButton.setPosition( WINDOW_WIDTH - creditsButton.getGlobalBounds().width,
                               playButton.getGlobalBounds().top +
                                   playButton.getGlobalBounds().height );

    audioButton.setScale( sf::Vector2f( 0.25, 0.25 ) );
    audioButton.setPosition( WINDOW_WIDTH - ( audioButton.getGlobalBounds().width + 10 ),
                             WINDOW_HEIGHT - ( audioButton.getGlobalBounds().height + 10 ) );
}

void ScreenMenu::loadAssets() {
    TextureManager::add( "backgroundMenu", "menu.jpg" );
    background.setTexture( TextureManager::get( "backgroundMenu" ) );

    TextureManager::add( "playButton", "play.png", true );
    playButton.setTexture( TextureManager::get( "playButton" ) );

    TextureManager::add( "creditsButton", "credits.png", true );
    creditsButton.setTexture( TextureManager::get( "creditsButton" ) );

    TextureManager::add( "audioButtonOn", "audio_on.png", true );
    TextureManager::add( "audioButtonOff", "audio_off.png", true );
    audioButton.setTexture( TextureManager::get( "audioButtonOn" ) );

    music = &MusicManager::add( "musicMenu", "menu.ogg" );
    music->setLoop( true );

    SoundManager::add( "clickSound", "choice.ogg" );
    clickSound.setBuffer( SoundManager::get( "clickSound" ) );
}
void ScreenMenu::draw() {
    window->clear();

    window->draw( background );
    window->draw( playButton );
    window->draw( creditsButton );
    window->draw( audioButton );

    window->display();
}
void ScreenMenu::update() {
    if( *isAudioOn && music->getStatus() != sf::SoundSource::Status::Playing ) {
        music->play();
    }

    if( !*isAudioOn ) {
        audioButton.setTexture( TextureManager::get( "audioButtonOff" ) );

    } else {
        audioButton.setTexture( TextureManager::get( "audioButtonOn" ) );
    }

    while( window->pollEvent( *event ) ) {
        if( event->type == sf::Event::Closed ) {
            music->stop();
            window->close();
        }

        // TODO: Mudar o cursor quando o mouse estiver em cima de um botão (C++)
        if( inputManager->isSpriteClicked( sf::Mouse::Button::Left, audioButton ) ) {
            if( *isAudioOn ) {
                clickSound.play();
                music->pause();
            }
            *isAudioOn = !*isAudioOn;
        }

        if( inputManager->isSpriteClicked( sf::Mouse::Button::Left, playButton ) ) {
            if( *isAudioOn ) {
                clickSound.play();
            }
            music->stop();
            *nextScreen = MOSTRAR;
        }

        if( inputManager->isSpriteClicked( sf::Mouse::Button::Left, creditsButton ) ) {
            if( *isAudioOn ) {
                clickSound.play();
            }
            music->stop();
            *nextScreen = CREDITOS;
        }
    }

    draw();
}
<|endoftext|>