<commit_before>/* ecppc.cpp
 * Copyright (C) 2003-2005 Tommi Maekitalo
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include "tnt/ecppc/ecppc.h"
#include "tnt/ecppc/generator.h"
#include "tnt/ecppc/dependencygenerator.h"
#include <tnt/mimedb.h>
#include <fstream>
#include <sstream>
#include <functional>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "config.h"
#include <cxxtools/loginit.h>
#include <cxxtools/log.h>

log_define("tntnet.ecppc")

namespace tnt
{
  namespace ecppc
  {
    Ecppc::Ecppc(int& argc, char* argv[])
      : requestname(cxxtools::Arg<std::string>(argc, argv, 'n')),
        ofile(cxxtools::Arg<std::string>(argc, argv, 'o')),
        odir(cxxtools::Arg<std::string>(argc, argv, 'O')),
        mimetype(argc, argv, 'm'),
        mimedb(argc, argv, "--mimetypes", "/etc/mime.types"),
        binary(argc, argv, 'b'),
        multibinary(argc, argv, 'b'),
        componentclass(argc, argv, 'C'),
        compress(argc, argv, 'z'),
        verbose(argc, argv, 'v'),
        debug(argc, argv, 'd'),
        trace(argc, argv, 't'),
        generateDependencies(argc, argv, 'M'),
        generateHeader(argc, argv, 'h'),
        disableLinenumbers(argc, argv, 'L')
    {
      while (true)
      {
        cxxtools::Arg<const char*> include(argc, argv, 'I', 0);
        if (!include.isSet())
          break;
        includes.push_back(include.getValue());
      }

      if (argc < 2 || argv[1][0] == '-')
        throw Usage(argv[0]);
      inputfile = argv[1];
      std::copy(argv + 1, argv + argc, std::inserter(inputfiles, inputfiles.end()));

      if (debug)
        log_init_debug();
      else
        log_init();
    }

    int Ecppc::run()
    {
      // requestname from inputfilename
      if (requestname.empty())
      {
        if (multibinary)
        {
          std::cerr << "warning: no requestname passed (with -n) - using \"images\"" << std::endl;
          requestname = "images";

          if (ofile.empty())
            ofile = requestname;
        }
        else
        {
          std::string input = inputfile;
          std::string::size_type pos_dot = input.find_last_of(".");
          std::string::size_type pos_slash = input.find_last_of("\\/");
          if (pos_dot != std::string::npos)
          {
            if (pos_slash == std::string::npos)
              requestname = input.substr(0, pos_dot);
            else if (pos_slash < pos_dot)
              requestname = input.substr(pos_slash + 1, pos_dot - pos_slash - 1);

            if (ofile.empty())
              ofile = input.substr(0, pos_dot);

            extname = input.substr(pos_dot);
          }
          else
          {
            requestname = input;
          }

          if (requestname.empty())
          {
            std::cerr << "cannot derive classname from filename. Use -n" << std::endl;
            return -1;
          }
        }
      }

      if (generateDependencies)
        return runDependencies();
      else
        return runGenerator();
    }

    int Ecppc::runGenerator()
    {
      // strip cpp-extension from outputfilename
      if (ofile.size() == ofile.rfind(".cpp") + 4)
        ofile = ofile.substr(0, ofile.size() - 4);

      // create generator
      tnt::ecppc::Generator generator(requestname);

      // initialize
      generator.setDebug(trace);
      generator.enableLinenumbers(!disableLinenumbers);
      Bodypart::enableLinenumbers(!disableLinenumbers);

      if (mimetype.isSet())
        generator.setMimetype(mimetype);
      else if (!extname.empty() && !multibinary)
      {
        tnt::MimeDb db(mimedb);
        std::string mimeType = db.getMimetype(extname);
        if (mimeType.empty())
          std::cerr << "warning: no mimetype set" << std::endl;
        else
          generator.setMimetype(mimeType);
      }

      generator.setCompress(compress);

      if (componentclass.isSet())
        generator.setComponentclass(componentclass);

      std::string obase = odir;
      if (!obase.empty())
        obase += '/';
      obase += ofile;

      //
      // parse sourcefile
      //

      if (multibinary)
      {
        tnt::MimeDb mimeDb;
        if (!mimetype.isSet())
          mimeDb.read(mimedb);

        for (inputfiles_type::const_iterator it = inputfiles.begin();
             it != inputfiles.end(); ++it)
        {
          std::string inputfile = *it;

          struct stat st;
          if (stat(inputfile.c_str(), &st) != 0)
            throw std::runtime_error("can't stat " + inputfile);

          std::ifstream in(inputfile.c_str());
          if (!in)
            throw std::runtime_error("can't read " + inputfile);

          std::ostringstream content;
          content << in.rdbuf();

          std::string mime;
          if (mimetype.isSet())
            mime = mimetype;
          else
          {
            mime = mimeDb.getMimetype(inputfile);
            if (mime.empty())
              std::cerr << "warning: no mimetype found for \"" << inputfile << '"' << std::endl;
          }

          // strip path
          std::string::size_type p;
          if ((p = inputfile.find_last_of('/')) != std::string::npos)
            inputfile.erase(0, p + 1);

          generator.addImage(inputfile, content.str(), mime, st.st_ctime);
        }
      }
      else
      {
        std::ifstream in(inputfile);
        if (binary)
        {
          std::ostringstream html;
          html << in.rdbuf();
          generator.onHtml(html.str());
          generator.setRawMode();

          struct stat st;
          if (stat(inputfile, &st) == 0)
            generator.setLastModifiedTime(st.st_ctime);
        }
        else
          runParser(in, generator);
      }

      //
      // generate Code
      //
      if (generateHeader)
      {
        if (verbose)
          std::cout << "generate " << obase << ".h" << std::endl;
        std::ofstream hout((obase + ".h").c_str());
        generator.getHeader(hout, ofile + ".h");
        hout.close();

        if (!hout)
          throw std::runtime_error("error writing file \"" + ofile + ".h\"");

        if (verbose)
          std::cout << "generate " << obase << ".cpp" << std::endl;
        std::ofstream sout((obase + ".cpp").c_str());
        generator.getCpp(sout, ofile + ".cpp");
        sout.close();

        if (!sout)
          throw std::runtime_error("error writing file \"" + ofile + ".cpp\"");
      }
      else
      {
        if (verbose)
          std::cout << "generate " << obase << ".cpp" << std::endl;
        std::ofstream sout((obase + ".cpp").c_str());
        generator.getCppWoHeader(sout, ofile + ".cpp");
        sout.close();

        if (!sout)
          throw std::runtime_error("error writing file \"" + ofile + ".cpp\"");
      }

      return 0;
    }

    int Ecppc::runDependencies()
    {
      tnt::ecppc::Dependencygenerator generator(requestname, inputfile);
      std::ifstream in(inputfile);
      if (!binary)
        runParser(in, generator);

      if (ofile.empty())
        generator.getDependencies(std::cout, generateHeader);
      else
      {
        std::ofstream out(ofile.c_str());
        generator.getDependencies(out, generateHeader);
      }

      return 0;
    }

    void Ecppc::runParser(std::istream& in, tnt::ecpp::ParseHandler& handler)
    {
      // create parser
      tnt::ecpp::Parser parser(handler, inputfile);

      // initialize parser
      for (includes_type::const_iterator it = includes.begin();
           it != includes.end(); ++it)
        parser.addInclude(*it);

      // call parser
      parser.parse(in);
    }

    Usage::Usage(const char* progname)
    {
      std::ostringstream o;
      o << PACKAGE_STRING "\n\n"
           "ecppc-compiler\n\n"
           "usage: " << progname << " [options] ecpp-source\n\n"
           "  -o filename      outputfile\n"
           "  -n name          classname\n"
           "  -I dir           include-directory\n"
           "  -m type          Mimetype\n"
           "  --mimetypes file read mimetypes from file (default /etc/mime.types)\n"
           "  -b               binary\n"
           "  -bb              generate multibinary component\n"
           "  -z               compress constant data\n"
           "  -v               verbose\n"
           "  -t               generate traces\n"
           "  -M               generate dependency for Makefile\n"
           "  -h               generate separate header-file\n"
           "  -L               disable generation of #line-directives\n";
      msg = o.str();
    }
  }
}

int main(int argc, char* argv[])
{
  std::ios::sync_with_stdio(false);

  try
  {
    tnt::ecppc::Ecppc app(argc, argv);
    return app.run();
  }
  catch(const std::exception& e)
  {
    std::cerr << e.what() << std::endl;
    return 1;
  }
}
<commit_msg>don't warn about unknown mime-type for ecpp-files<commit_after>/* ecppc.cpp
 * Copyright (C) 2003-2005 Tommi Maekitalo
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include "tnt/ecppc/ecppc.h"
#include "tnt/ecppc/generator.h"
#include "tnt/ecppc/dependencygenerator.h"
#include <tnt/mimedb.h>
#include <fstream>
#include <sstream>
#include <functional>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "config.h"
#include <cxxtools/loginit.h>
#include <cxxtools/log.h>

log_define("tntnet.ecppc")

namespace tnt
{
  namespace ecppc
  {
    Ecppc::Ecppc(int& argc, char* argv[])
      : requestname(cxxtools::Arg<std::string>(argc, argv, 'n')),
        ofile(cxxtools::Arg<std::string>(argc, argv, 'o')),
        odir(cxxtools::Arg<std::string>(argc, argv, 'O')),
        mimetype(argc, argv, 'm'),
        mimedb(argc, argv, "--mimetypes", "/etc/mime.types"),
        binary(argc, argv, 'b'),
        multibinary(argc, argv, 'b'),
        componentclass(argc, argv, 'C'),
        compress(argc, argv, 'z'),
        verbose(argc, argv, 'v'),
        debug(argc, argv, 'd'),
        trace(argc, argv, 't'),
        generateDependencies(argc, argv, 'M'),
        generateHeader(argc, argv, 'h'),
        disableLinenumbers(argc, argv, 'L')
    {
      while (true)
      {
        cxxtools::Arg<const char*> include(argc, argv, 'I', 0);
        if (!include.isSet())
          break;
        includes.push_back(include.getValue());
      }

      if (argc < 2 || argv[1][0] == '-')
        throw Usage(argv[0]);
      inputfile = argv[1];
      std::copy(argv + 1, argv + argc, std::inserter(inputfiles, inputfiles.end()));

      if (debug)
        log_init_debug();
      else
        log_init();
    }

    int Ecppc::run()
    {
      // requestname from inputfilename
      if (requestname.empty())
      {
        if (multibinary)
        {
          std::cerr << "warning: no requestname passed (with -n) - using \"images\"" << std::endl;
          requestname = "images";

          if (ofile.empty())
            ofile = requestname;
        }
        else
        {
          std::string input = inputfile;
          std::string::size_type pos_dot = input.find_last_of(".");
          std::string::size_type pos_slash = input.find_last_of("\\/");
          if (pos_dot != std::string::npos)
          {
            if (pos_slash == std::string::npos)
              requestname = input.substr(0, pos_dot);
            else if (pos_slash < pos_dot)
              requestname = input.substr(pos_slash + 1, pos_dot - pos_slash - 1);

            if (ofile.empty())
              ofile = input.substr(0, pos_dot);

            extname = input.substr(pos_dot + 1);
          }
          else
          {
            requestname = input;
          }

          if (requestname.empty())
          {
            std::cerr << "cannot derive classname from filename. Use -n" << std::endl;
            return -1;
          }
        }
      }

      if (generateDependencies)
        return runDependencies();
      else
        return runGenerator();
    }

    int Ecppc::runGenerator()
    {
      // strip cpp-extension from outputfilename
      if (ofile.size() == ofile.rfind(".cpp") + 4)
        ofile = ofile.substr(0, ofile.size() - 4);

      // create generator
      tnt::ecppc::Generator generator(requestname);

      // initialize
      generator.setDebug(trace);
      generator.enableLinenumbers(!disableLinenumbers);
      Bodypart::enableLinenumbers(!disableLinenumbers);

      if (mimetype.isSet())
        generator.setMimetype(mimetype);
      else if (!extname.empty() && !multibinary)
      {
        tnt::MimeDb db(mimedb);
        std::string mimeType = db.getMimetype(extname);
        if (mimeType.empty())
        {
          if (extname != "ecpp")
            std::cerr << "warning: unknown mimetype" << std::endl;
        }
        else
          generator.setMimetype(mimeType);
      }

      generator.setCompress(compress);

      if (componentclass.isSet())
        generator.setComponentclass(componentclass);

      std::string obase = odir;
      if (!obase.empty())
        obase += '/';
      obase += ofile;

      //
      // parse sourcefile
      //

      if (multibinary)
      {
        tnt::MimeDb mimeDb;
        if (!mimetype.isSet())
          mimeDb.read(mimedb);

        for (inputfiles_type::const_iterator it = inputfiles.begin();
             it != inputfiles.end(); ++it)
        {
          std::string inputfile = *it;

          struct stat st;
          if (stat(inputfile.c_str(), &st) != 0)
            throw std::runtime_error("can't stat " + inputfile);

          std::ifstream in(inputfile.c_str());
          if (!in)
            throw std::runtime_error("can't read " + inputfile);

          std::ostringstream content;
          content << in.rdbuf();

          std::string mime;
          if (mimetype.isSet())
            mime = mimetype;
          else
          {
            mime = mimeDb.getMimetype(inputfile);
            if (mime.empty())
              std::cerr << "warning: no mimetype found for \"" << inputfile << '"' << std::endl;
          }

          // strip path
          std::string::size_type p;
          if ((p = inputfile.find_last_of('/')) != std::string::npos)
            inputfile.erase(0, p + 1);

          generator.addImage(inputfile, content.str(), mime, st.st_ctime);
        }
      }
      else
      {
        std::ifstream in(inputfile);
        if (binary)
        {
          std::ostringstream html;
          html << in.rdbuf();
          generator.onHtml(html.str());
          generator.setRawMode();

          struct stat st;
          if (stat(inputfile, &st) == 0)
            generator.setLastModifiedTime(st.st_ctime);
        }
        else
          runParser(in, generator);
      }

      //
      // generate Code
      //
      if (generateHeader)
      {
        if (verbose)
          std::cout << "generate " << obase << ".h" << std::endl;
        std::ofstream hout((obase + ".h").c_str());
        generator.getHeader(hout, ofile + ".h");
        hout.close();

        if (!hout)
          throw std::runtime_error("error writing file \"" + ofile + ".h\"");

        if (verbose)
          std::cout << "generate " << obase << ".cpp" << std::endl;
        std::ofstream sout((obase + ".cpp").c_str());
        generator.getCpp(sout, ofile + ".cpp");
        sout.close();

        if (!sout)
          throw std::runtime_error("error writing file \"" + ofile + ".cpp\"");
      }
      else
      {
        if (verbose)
          std::cout << "generate " << obase << ".cpp" << std::endl;
        std::ofstream sout((obase + ".cpp").c_str());
        generator.getCppWoHeader(sout, ofile + ".cpp");
        sout.close();

        if (!sout)
          throw std::runtime_error("error writing file \"" + ofile + ".cpp\"");
      }

      return 0;
    }

    int Ecppc::runDependencies()
    {
      tnt::ecppc::Dependencygenerator generator(requestname, inputfile);
      std::ifstream in(inputfile);
      if (!binary)
        runParser(in, generator);

      if (ofile.empty())
        generator.getDependencies(std::cout, generateHeader);
      else
      {
        std::ofstream out(ofile.c_str());
        generator.getDependencies(out, generateHeader);
      }

      return 0;
    }

    void Ecppc::runParser(std::istream& in, tnt::ecpp::ParseHandler& handler)
    {
      // create parser
      tnt::ecpp::Parser parser(handler, inputfile);

      // initialize parser
      for (includes_type::const_iterator it = includes.begin();
           it != includes.end(); ++it)
        parser.addInclude(*it);

      // call parser
      parser.parse(in);
    }

    Usage::Usage(const char* progname)
    {
      std::ostringstream o;
      o << PACKAGE_STRING "\n\n"
           "ecppc-compiler\n\n"
           "usage: " << progname << " [options] ecpp-source\n\n"
           "  -o filename      outputfile\n"
           "  -n name          classname\n"
           "  -I dir           include-directory\n"
           "  -m type          Mimetype\n"
           "  --mimetypes file read mimetypes from file (default /etc/mime.types)\n"
           "  -b               binary\n"
           "  -bb              generate multibinary component\n"
           "  -z               compress constant data\n"
           "  -v               verbose\n"
           "  -t               generate traces\n"
           "  -M               generate dependency for Makefile\n"
           "  -h               generate separate header-file\n"
           "  -L               disable generation of #line-directives\n";
      msg = o.str();
    }
  }
}

int main(int argc, char* argv[])
{
  std::ios::sync_with_stdio(false);

  try
  {
    tnt::ecppc::Ecppc app(argc, argv);
    return app.run();
  }
  catch(const std::exception& e)
  {
    std::cerr << e.what() << std::endl;
    return 1;
  }
}
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
/**
 *
 *  This program illustrates the use of Geometric objects
 *
 */

#include "itkMath.h"
#include "itkCovariantVector.h"
#include <iostream>

  // Dimension & Type
  const     unsigned int    N = 3;
  typedef   double          ValueType;

  //  Vector type
  typedef    itk::CovariantVector< ValueType, N >    VectorType;

//-------------------------
//
//   Main code
//
//-------------------------
int itkCovariantVectorGeometryTest(int, char* [] )
{

  VectorType va;
  va[0] = 1.0;
  va[1] = 2.0;
  va[2] = 7.0;

  std::cout << "va = { 1.0, 2.0, 7.0 } = ";
  std::cout << va << std::endl;

  VectorType vb;

  vb[0] = 1.0;
  vb[1] = 3.0;
  vb[2] = 5.0;

  std::cout << "vb = (1,3,5)   = ";
  std::cout << vb << std::endl;

  VectorType   vc  =  vb - va;
  std::cout << "vc  =  vb - va  = ";
  std::cout << vc << std::endl;

  VectorType   vd  =  va * 5.0;
  std::cout << "vd  =  va * 5.0 = ";
  std::cout << vd << std::endl;

  VectorType   ve  =  vd / 5.0;
  std::cout << "ve  =  vd * 5.0 = ";
  std::cout << ve << std::endl;

  vd += va;
  std::cout << "vd  +=  va      = ";
  std::cout << vd << std::endl;

  ve -= vb;
  std::cout << "ve  -=  vb      = ";
  std::cout << ve << std::endl;

  VectorType   vh  =  vb;
  std::cout << "vh   =  vb      = ";
  std::cout << vh << std::endl;

  VectorType   vg( va );
  std::cout << "vg( va )        = ";
  std::cout << vg << std::endl;

  ValueType norm2 = vg.GetSquaredNorm();
  std::cout << "vg squared norm = ";
  std::cout << norm2 << std::endl;

  ValueType norm  = vg.GetNorm();
  std::cout << "vg norm = ";
  std::cout << norm << std::endl;

  // Test for vnl interface

  // Test the no const version that returns an vnl_vector_ref
  vnl_vector_ref< ValueType > vnlVector = va.GetVnlVector();
  {
    std::cout << "vnl_vector_ref = va ";
    for( unsigned int i=0; i<N; i++ )
    {
      std::cout << vnlVector[i] << ", ";
    }
    std::cout << std::endl;

    std::cout << "vnl_vector_ref.begin() = va.Begin()";
    std::cout << std::endl;
    std::cout << vnlVector.begin() << " = ";
    std::cout << va.Begin() << std::endl;
  }

  // Test the const version that returns an vnl_vector
  const VectorType vf(va);
  vnl_vector<ValueType> vnlVector2 = vf.GetVnlVector();
  {
    std::cout << "vnl_vector = va ";
    for( unsigned int i=0; i<N; i++ )
    {
      std::cout << vnlVector2[i] << ", ";
    }
    std::cout << std::endl;

    std::cout << "vnl_vector.begin() != vf.Begin()";
    std::cout << std::endl;
    std::cout << vnlVector2.begin() << " = ";
    std::cout << vf.Begin() << std::endl;
  }

  // Test for CastFrom() method
  {
  std::cout << "Test for CastFrom() method... ";

  const float tolerance = 1e-7;

  //  CovariantVector Classes
  typedef    itk::CovariantVector<  double, N >    DoubleCovariantVectorType;
  typedef    itk::CovariantVector<  float , N >    FloatCovariantVectorType;

  DoubleCovariantVectorType dp;
  dp[0] = 1.0;
  dp[1] = 1.7;
  dp[2] = 1.9;

  FloatCovariantVectorType fp;
  fp[0] = 0.0;
  fp[1] = 0.0;
  fp[2] = 0.0;

  fp.CastFrom( dp );

  std::cout << std::endl;
  for(unsigned int i=0; i<N; i++)
    {
    FloatCovariantVectorType::ValueType val =
        static_cast< FloatCovariantVectorType::ValueType >( dp[i] );

//   std::cout << val   << std::endl;
//   std::cout << fp[i] << std::endl;

    const float diff = vnl_math_abs( val - fp[i] );
    std::cout << "difference = " << diff << std::endl;
    if( vnl_math_abs ( val - fp[i] ) > tolerance )
      {
        std::cout << "Test failed at component " << i << std::endl;
        return EXIT_FAILURE;
      }
    }

  std::cout << " PASSED ! " << std::endl;

  }

  // Test the inner products
  {
    typedef itk::Vector<double, 3>           ContravariantVectorType;
    typedef itk::CovariantVector<double, 3>  CovariantVectorType;

    ContravariantVectorType contravariant;
    contravariant[0] = 1.0;
    contravariant[1] = 2.0;
    contravariant[2] = -7.0;

    CovariantVectorType covariant;
    covariant[0] = 1.0;
    covariant[1] = 3.0;
    covariant[2] = 5.0;

    const double expectedValue = -28.0;

    if( !itk::Math::FloatAlmostEqual( expectedValue, covariant * contravariant ) ||
        !itk::Math::FloatAlmostEqual( expectedValue, contravariant * covariant ) )
        {
        std::cerr << "Error in inner product computation." << std::endl;
        return EXIT_FAILURE;
        }
  }

  // Test the Cross products
  {
    typedef itk::Vector<double, 3>           ContravariantVectorType;
    typedef itk::CovariantVector<double, 3>  CovariantVectorType;

    ContravariantVectorType vaa;
    ContravariantVectorType vbb;

    vaa[0] = 1.0;
    vaa[1] = 0.0;
    vaa[2] = 0.0;

    vbb[0] = 0.0;
    vbb[1] = 1.0;
    vbb[2] = 0.0;

    CovariantVectorType normal;

    itk::CrossProduct( normal, vaa, vbb );

    CovariantVectorType expectedNormal;

    expectedNormal[0] = 0.0;
    expectedNormal[1] = 0.0;
    expectedNormal[2] = 1.0;

    if( !itk::Math::FloatAlmostEqual( normal[0], expectedNormal[0] ) ||
        !itk::Math::FloatAlmostEqual( normal[1], expectedNormal[1] ) ||
        !itk::Math::FloatAlmostEqual( normal[2], expectedNormal[2] ) )
      {
      std::cerr << "Error in CrossProduct computation." << std::endl;
      return EXIT_FAILURE;
      }

  }
  //
  // test that the ComponentType is present
  {
  typedef itk::CovariantVector<double, 3>  CovariantVectorType;
  CovariantVectorType::ComponentType comp(1.0);
  double x(1.0);
  if(sizeof(comp) != sizeof(double))
    {
    std::cerr << "error -- CovariantVectorType::ComponentType size != sizeof(double)"
              << std::endl;
    return EXIT_FAILURE;
    }
  char *compp = reinterpret_cast<char *>(&comp);
  char *xp = reinterpret_cast<char *>(&x);
  for(unsigned i = 0; i < sizeof(CovariantVectorType::ComponentType); i++)
    {
    if(compp[i] != xp[i])
      {
      std::cerr << "error -- bit pattern for CovariantVectorType::ComponentType doesn't match "
                << " double with same value" << std::endl;
      }
    }
  }
  return EXIT_SUCCESS;
}
<commit_msg>COMP: Improve scoping in CovariantVectorGeometryTest.<commit_after>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
/**
 *
 *  This program illustrates the use of Geometric objects
 *
 */

#include "itkMath.h"
#include "itkCovariantVector.h"
#include <iostream>

int itkCovariantVectorGeometryTest(int, char* [] )
{
  // Dimension & Type
  const     unsigned int    N = 3;
  typedef   double          ValueType;

  //  Vector type
  typedef    itk::CovariantVector< ValueType, N >    VectorType;

  VectorType va;
  va[0] = 1.0;
  va[1] = 2.0;
  va[2] = 7.0;

  std::cout << "va = { 1.0, 2.0, 7.0 } = ";
  std::cout << va << std::endl;

  VectorType vb;

  vb[0] = 1.0;
  vb[1] = 3.0;
  vb[2] = 5.0;

  std::cout << "vb = (1,3,5)   = ";
  std::cout << vb << std::endl;

  VectorType   vc  =  vb - va;
  std::cout << "vc  =  vb - va  = ";
  std::cout << vc << std::endl;

  VectorType   vd  =  va * 5.0;
  std::cout << "vd  =  va * 5.0 = ";
  std::cout << vd << std::endl;

  VectorType   ve  =  vd / 5.0;
  std::cout << "ve  =  vd * 5.0 = ";
  std::cout << ve << std::endl;

  vd += va;
  std::cout << "vd  +=  va      = ";
  std::cout << vd << std::endl;

  ve -= vb;
  std::cout << "ve  -=  vb      = ";
  std::cout << ve << std::endl;

  VectorType   vh  =  vb;
  std::cout << "vh   =  vb      = ";
  std::cout << vh << std::endl;

  VectorType   vg( va );
  std::cout << "vg( va )        = ";
  std::cout << vg << std::endl;

  ValueType norm2 = vg.GetSquaredNorm();
  std::cout << "vg squared norm = ";
  std::cout << norm2 << std::endl;

  ValueType norm  = vg.GetNorm();
  std::cout << "vg norm = ";
  std::cout << norm << std::endl;

  // Test for vnl interface

  // Test the no const version that returns an vnl_vector_ref
  vnl_vector_ref< ValueType > vnlVector = va.GetVnlVector();
  {
    std::cout << "vnl_vector_ref = va ";
    for( unsigned int i=0; i<N; i++ )
    {
      std::cout << vnlVector[i] << ", ";
    }
    std::cout << std::endl;

    std::cout << "vnl_vector_ref.begin() = va.Begin()";
    std::cout << std::endl;
    std::cout << vnlVector.begin() << " = ";
    std::cout << va.Begin() << std::endl;
  }

  // Test the const version that returns an vnl_vector
  const VectorType vf(va);
  vnl_vector<ValueType> vnlVector2 = vf.GetVnlVector();
  {
    std::cout << "vnl_vector = va ";
    for( unsigned int i=0; i<N; i++ )
    {
      std::cout << vnlVector2[i] << ", ";
    }
    std::cout << std::endl;

    std::cout << "vnl_vector.begin() != vf.Begin()";
    std::cout << std::endl;
    std::cout << vnlVector2.begin() << " = ";
    std::cout << vf.Begin() << std::endl;
  }

  // Test for CastFrom() method
  {
  std::cout << "Test for CastFrom() method... ";

  const float tolerance = 1e-7;

  //  CovariantVector Classes
  typedef    itk::CovariantVector<  double, N >    DoubleCovariantVectorType;
  typedef    itk::CovariantVector<  float , N >    FloatCovariantVectorType;

  DoubleCovariantVectorType dp;
  dp[0] = 1.0;
  dp[1] = 1.7;
  dp[2] = 1.9;

  FloatCovariantVectorType fp;
  fp[0] = 0.0;
  fp[1] = 0.0;
  fp[2] = 0.0;

  fp.CastFrom( dp );

  std::cout << std::endl;
  for(unsigned int i=0; i<N; i++)
    {
    FloatCovariantVectorType::ValueType val =
        static_cast< FloatCovariantVectorType::ValueType >( dp[i] );

//   std::cout << val   << std::endl;
//   std::cout << fp[i] << std::endl;

    const float diff = vnl_math_abs( val - fp[i] );
    std::cout << "difference = " << diff << std::endl;
    if( vnl_math_abs ( val - fp[i] ) > tolerance )
      {
        std::cout << "Test failed at component " << i << std::endl;
        return EXIT_FAILURE;
      }
    }

  std::cout << " PASSED ! " << std::endl;

  }

  // Test the inner products
  {
    typedef itk::Vector<double, 3>           ContravariantVectorType;
    typedef itk::CovariantVector<double, 3>  CovariantVectorType;

    ContravariantVectorType contravariant;
    contravariant[0] = 1.0;
    contravariant[1] = 2.0;
    contravariant[2] = -7.0;

    CovariantVectorType covariant;
    covariant[0] = 1.0;
    covariant[1] = 3.0;
    covariant[2] = 5.0;

    const double expectedValue = -28.0;

    if( !itk::Math::FloatAlmostEqual( expectedValue, covariant * contravariant ) ||
        !itk::Math::FloatAlmostEqual( expectedValue, contravariant * covariant ) )
        {
        std::cerr << "Error in inner product computation." << std::endl;
        return EXIT_FAILURE;
        }
  }

  // Test the Cross products
  {
    typedef itk::Vector<double, 3>           ContravariantVectorType;
    typedef itk::CovariantVector<double, 3>  CovariantVectorType;

    ContravariantVectorType vaa;
    ContravariantVectorType vbb;

    vaa[0] = 1.0;
    vaa[1] = 0.0;
    vaa[2] = 0.0;

    vbb[0] = 0.0;
    vbb[1] = 1.0;
    vbb[2] = 0.0;

    CovariantVectorType normal;

    itk::CrossProduct( normal, vaa, vbb );

    CovariantVectorType expectedNormal;

    expectedNormal[0] = 0.0;
    expectedNormal[1] = 0.0;
    expectedNormal[2] = 1.0;

    if( !itk::Math::FloatAlmostEqual( normal[0], expectedNormal[0] ) ||
        !itk::Math::FloatAlmostEqual( normal[1], expectedNormal[1] ) ||
        !itk::Math::FloatAlmostEqual( normal[2], expectedNormal[2] ) )
      {
      std::cerr << "Error in CrossProduct computation." << std::endl;
      return EXIT_FAILURE;
      }

  }
  //
  // test that the ComponentType is present
  {
  typedef itk::CovariantVector<double, 3>  CovariantVectorType;
  CovariantVectorType::ComponentType comp(1.0);
  double x(1.0);
  if(sizeof(comp) != sizeof(double))
    {
    std::cerr << "error -- CovariantVectorType::ComponentType size != sizeof(double)"
              << std::endl;
    return EXIT_FAILURE;
    }
  char *compp = reinterpret_cast<char *>(&comp);
  char *xp = reinterpret_cast<char *>(&x);
  for(unsigned i = 0; i < sizeof(CovariantVectorType::ComponentType); i++)
    {
    if(compp[i] != xp[i])
      {
      std::cerr << "error -- bit pattern for CovariantVectorType::ComponentType doesn't match "
                << " double with same value" << std::endl;
      }
    }
  }
  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include <lua-cxx/LuaEnvironment.hpp>
#include <lua-cxx/LuaValue.hpp>
#include <lua-cxx/DirectoryModuleLoader.hpp>
#include <lua-cxx/loaders.hpp>
#include <QFile>
#include <QDir>

#include <cstdlib>

int main(int argc, char* argv[])
{
    Lua lua;

    std::string srcdir(getenv("srcdir"));

    DirectoryModuleLoader fritomodLoader;
    fritomodLoader.setRoot(QDir(QDir::home().filePath("src/fritomod/fritomod")));
    fritomodLoader.setPrefix("fritomod/");
    lua.addModuleLoader(&fritomodLoader);

    DirectoryModuleLoader rainbackLoader;
    rainbackLoader.setRoot(QDir(QString(srcdir.c_str()) + "/../src/rainback"));
    rainbackLoader.setPrefix("rainback/");
    lua.addModuleLoader(&rainbackLoader);

    lua::load_file(lua, srcdir + "/global.lua");
    lua::load_dir(lua, QDir(QString(srcdir.c_str()) + "/rainback"), true);

    QFile testRunner(QString(srcdir.c_str()) + "/tests.lua");
    return (bool)lua(testRunner) ? 0 : 1;
}
<commit_msg>Fixed an out-of-date path<commit_after>#include <lua-cxx/LuaEnvironment.hpp>
#include <lua-cxx/LuaValue.hpp>
#include <lua-cxx/DirectoryModuleLoader.hpp>
#include <lua-cxx/loaders.hpp>
#include <QFile>
#include <QDir>

#include <cstdlib>
#include <iostream>

int main(int argc, char* argv[])
{
    Lua lua;

    std::string srcdir(getenv("srcdir"));

    DirectoryModuleLoader fritomodLoader;
    fritomodLoader.setRoot(QDir(QDir::home().filePath("src/fritomod/fritomod")));
    fritomodLoader.setPrefix("fritomod/");
    lua.addModuleLoader(&fritomodLoader);

    DirectoryModuleLoader rainbackLoader;
    rainbackLoader.setRoot(QDir(QString(srcdir.c_str()) + "/../rainback"));
    rainbackLoader.setPrefix("rainback/");
    lua.addModuleLoader(&rainbackLoader);

    lua::load_file(lua, srcdir + "/global.lua");
    lua::load_dir(lua, QDir(QString(srcdir.c_str()) + "/rainback"), true);

    QFile testRunner(QString(srcdir.c_str()) + "/tests.lua");
    return (bool)lua(testRunner) ? 0 : 1;
}
<|endoftext|>


<commit_before>#include "stdafx.h"

#include "Render/DX12/Texture/TextureManagerDX12.h"

#include "Render/DX12/StateDX.h"
#include "Render/DX12/Texture/TextureDX12.h"
#include "Render/Texture/Texture.h"
#include "Render/Texture/TextureSet.h"

namespace Kioto::Renderer
{
namespace
{
constexpr uint16 MaxRenderTargetViews = 256;
constexpr uint16 MaxDepthStencilViews = 32;
}

TextureManagerDX12::TextureManagerDX12()
{
    m_textureQueue.reserve(64);
    m_textureSetUpdateQueue.reserve(256);
}

void TextureManagerDX12::RegisterTexture(Texture* texture)
{
    auto it = m_textures.find(texture->GetHandle());
    if (it != m_textures.end())
    {
        throw "Texture Already Registered";
        return;
    }

    TextureDX12* tex = new TextureDX12();
    tex->Path = StrToWstr(texture->GetAssetPath());
    tex->SetHandle(GetNewHandle());
    tex->SetDescriptor(texture->GetDescriptor());
    tex->SetIsFromMemoryAsset(texture->IsMemoryAsset());
    m_textureQueue.push_back(tex);
    texture->SetHandle(tex->GetHandle());

    m_textures[tex->GetHandle()] = tex;
}

TextureManagerDX12::~TextureManagerDX12()
{
    for (auto& tex : m_textures)
        delete tex.second;
    m_textures.clear();
}

void TextureManagerDX12::InitRtvHeap(const StateDX& state)
{
    D3D12_DESCRIPTOR_HEAP_DESC heapDescr = {};
    heapDescr.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
    heapDescr.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
    heapDescr.NumDescriptors = MaxRenderTargetViews;
    ThrowIfFailed(state.Device->CreateDescriptorHeap(&heapDescr, IID_PPV_ARGS(&m_rtvHeap)));
}

void TextureManagerDX12::InitDsvHeap(const StateDX& state)
{
    D3D12_DESCRIPTOR_HEAP_DESC heapDescr = {};
    heapDescr.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
    heapDescr.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
    heapDescr.NumDescriptors = MaxDepthStencilViews;
    ThrowIfFailed(state.Device->CreateDescriptorHeap(&heapDescr, IID_PPV_ARGS(&m_dsvHeap)));
}

void TextureManagerDX12::UpdateTextureSetHeap(const StateDX& state, const TextureSet& texSet)
{
    if (m_textureHeaps.find(texSet.GetHandle()) != m_textureHeaps.end())
        m_textureHeaps[texSet.GetHandle()].Reset();

    D3D12_DESCRIPTOR_HEAP_DESC heapDescr = {};
    heapDescr.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
    heapDescr.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
    heapDescr.NumDescriptors = texSet.GetTexturesCount();

    // [a_vorontcov] TODO: maybe reuse the same heap and overwrite descriptors?
    ThrowIfFailed(state.Device->CreateDescriptorHeap(&heapDescr, IID_PPV_ARGS(&m_textureHeaps[texSet.GetHandle()])));

    CD3DX12_CPU_DESCRIPTOR_HANDLE handle(m_textureHeaps[texSet.GetHandle()]->GetCPUDescriptorHandleForHeapStart());
    for (uint32 i = 0; i < texSet.GetTexturesCount(); ++i)
    {
        const Texture* kiotoTex = texSet.GetTexture(i);
        auto it = m_textures.find(kiotoTex->GetHandle());
        if (it == m_textures.end())
            throw "ololo";
        TextureDX12* dxTex = (*it).second;

        D3D12_SHADER_RESOURCE_VIEW_DESC texDescr = {};
        texDescr.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
        texDescr.Format = dxTex->Resource->GetDesc().Format;
        texDescr.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
        texDescr.Texture2D.MipLevels = dxTex->Resource->GetDesc().MipLevels;
        texDescr.Texture2D.MostDetailedMip = 0;
        texDescr.Texture2D.ResourceMinLODClamp = 0.0f;

        state.Device->CreateShaderResourceView(dxTex->Resource.Get(), &texDescr, handle);
        handle.Offset(state.CbvSrvUavDescriptorSize);
    }
}

ID3D12DescriptorHeap* TextureManagerDX12::GetTextureHeap(TextureSetHandle handle) const
{
    auto it = m_textureHeaps.find(handle);
    if (it != m_textureHeaps.cend())
        return it->second.Get();
    return nullptr;
}

TextureDX12* TextureManagerDX12::FindTexture(TextureHandle handle)
{
    auto it = m_textures.find(handle);
    if (it != m_textures.cend())
        return it->second;
    it = m_notOwningTextures.find(handle);
    if (it != m_notOwningTextures.cend())
        return it->second;
    return nullptr;
}

void TextureManagerDX12::RegisterTextureWithoutOwnership(TextureDX12* texture)
{
    auto it = m_notOwningTextures.find(texture->GetHandle());
    if (it != m_notOwningTextures.end())
    {
        throw "Texture Already Registered";
        return;
    }
    m_notOwningTextures[texture->GetHandle()] = texture;
}

void TextureManagerDX12::ProcessRegistationQueue(const StateDX& state)
{
    for (auto& tex : m_textureQueue)
    {
        tex->Create(state.Device.Get(), state.CommandList.Get());
        if (tex->GetIsFromMemoryAsset())
        {
            if ((tex->GetDx12TextureFlags() & D3D12_RESOURCE_FLAGS::D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET) != 0)
            {
                assert(m_rtvHeapOffsets.count(tex->GetHandle()) == 0);
                m_rtvHeapOffsets[tex->GetHandle()] = m_currentRtvOffset;

                CD3DX12_CPU_DESCRIPTOR_HANDLE handle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart());
                handle.Offset(m_currentRtvOffset);

                m_currentRtvOffset += state.RtvDescriptorSize;

                D3D12_RENDER_TARGET_VIEW_DESC texDescr = {};
                texDescr.Format = tex->Resource->GetDesc().Format;
                texDescr.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
                texDescr.Texture2D = { 0, 0 };

                state.Device->CreateRenderTargetView(tex->Resource.Get(), &texDescr, handle);
            }
            else if ((tex->GetDx12TextureFlags() & D3D12_RESOURCE_FLAGS::D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL) != 0)
            {
                assert(m_dsvHeapOffsets.count(tex->GetHandle()) == 0);
                m_dsvHeapOffsets[tex->GetHandle()] = m_currentDsvOffset;

                CD3DX12_CPU_DESCRIPTOR_HANDLE handle(m_dsvHeap->GetCPUDescriptorHandleForHeapStart());
                handle.Offset(m_currentDsvOffset);

                m_currentDsvOffset += state.DsvDescriptorSize;

                D3D12_DEPTH_STENCIL_VIEW_DESC texDescr = {};
                texDescr.Format = tex->Resource->GetDesc().Format;
                texDescr.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
                texDescr.Texture2D = { 0 };

                state.Device->CreateDepthStencilView(tex->Resource.Get(), &texDescr, handle);
            }
        }
    }
    m_textureQueue.clear();
}

void TextureManagerDX12::QueueTextureSetForUpdate(const TextureSet& texSet)
{
    if (texSet.GetHandle() == InvalidHandle)
        throw "Invalid handle";

    auto it = std::find(m_textureSetUpdateQueue.cbegin(), m_textureSetUpdateQueue.cend(), &texSet);
    if (it != m_textureSetUpdateQueue.cend())
        return;

    m_textureSetUpdateQueue.push_back(&texSet);
}

void TextureManagerDX12::ProcessTextureSetUpdates(const StateDX& state)
{
    for (auto& texSet : m_textureSetUpdateQueue)
        UpdateTextureSetHeap(state, *texSet);
    m_textureSetUpdateQueue.clear();
}

D3D12_CPU_DESCRIPTOR_HANDLE TextureManagerDX12::GetRtvHandle(TextureHandle handle) const
{
    assert(m_rtvHeapOffsets.count(handle) == 1 && "The texture is not registered as a rtv");
    CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart());
    rtvHandle.Offset(m_rtvHeapOffsets.at(handle));
    return rtvHandle;
}

D3D12_CPU_DESCRIPTOR_HANDLE TextureManagerDX12::GetDsvHandle(TextureHandle handle) const
{
    assert(m_dsvHeapOffsets.count(handle) == 1 && "The texture is not registred as a dsv");
    CD3DX12_CPU_DESCRIPTOR_HANDLE dsvHandle(m_dsvHeap->GetCPUDescriptorHandleForHeapStart());
    dsvHandle.Offset(m_dsvHeapOffsets.at(handle));
    return dsvHandle;
}

}<commit_msg>Fixed ds flag<commit_after>#include "stdafx.h"

#include "Render/DX12/Texture/TextureManagerDX12.h"

#include "Render/DX12/StateDX.h"
#include "Render/DX12/Texture/TextureDX12.h"
#include "Render/Texture/Texture.h"
#include "Render/Texture/TextureSet.h"

namespace Kioto::Renderer
{
namespace
{
constexpr uint16 MaxRenderTargetViews = 256;
constexpr uint16 MaxDepthStencilViews = 32;
}

TextureManagerDX12::TextureManagerDX12()
{
    m_textureQueue.reserve(64);
    m_textureSetUpdateQueue.reserve(256);
}

void TextureManagerDX12::RegisterTexture(Texture* texture)
{
    auto it = m_textures.find(texture->GetHandle());
    if (it != m_textures.end())
    {
        throw "Texture Already Registered";
        return;
    }

    TextureDX12* tex = new TextureDX12();
    tex->Path = StrToWstr(texture->GetAssetPath());
    tex->SetHandle(GetNewHandle());
    tex->SetDescriptor(texture->GetDescriptor());
    tex->SetIsFromMemoryAsset(texture->IsMemoryAsset());
    m_textureQueue.push_back(tex);
    texture->SetHandle(tex->GetHandle());

    m_textures[tex->GetHandle()] = tex;
}

TextureManagerDX12::~TextureManagerDX12()
{
    for (auto& tex : m_textures)
        delete tex.second;
    m_textures.clear();
}

void TextureManagerDX12::InitRtvHeap(const StateDX& state)
{
    D3D12_DESCRIPTOR_HEAP_DESC heapDescr = {};
    heapDescr.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
    heapDescr.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
    heapDescr.NumDescriptors = MaxRenderTargetViews;
    ThrowIfFailed(state.Device->CreateDescriptorHeap(&heapDescr, IID_PPV_ARGS(&m_rtvHeap)));
}

void TextureManagerDX12::InitDsvHeap(const StateDX& state)
{
    D3D12_DESCRIPTOR_HEAP_DESC heapDescr = {};
    heapDescr.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
    heapDescr.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
    heapDescr.NumDescriptors = MaxDepthStencilViews;
    ThrowIfFailed(state.Device->CreateDescriptorHeap(&heapDescr, IID_PPV_ARGS(&m_dsvHeap)));
}

void TextureManagerDX12::UpdateTextureSetHeap(const StateDX& state, const TextureSet& texSet)
{
    if (m_textureHeaps.find(texSet.GetHandle()) != m_textureHeaps.end())
        m_textureHeaps[texSet.GetHandle()].Reset();

    D3D12_DESCRIPTOR_HEAP_DESC heapDescr = {};
    heapDescr.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
    heapDescr.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
    heapDescr.NumDescriptors = texSet.GetTexturesCount();

    // [a_vorontcov] TODO: maybe reuse the same heap and overwrite descriptors?
    ThrowIfFailed(state.Device->CreateDescriptorHeap(&heapDescr, IID_PPV_ARGS(&m_textureHeaps[texSet.GetHandle()])));

    CD3DX12_CPU_DESCRIPTOR_HANDLE handle(m_textureHeaps[texSet.GetHandle()]->GetCPUDescriptorHandleForHeapStart());
    for (uint32 i = 0; i < texSet.GetTexturesCount(); ++i)
    {
        const Texture* kiotoTex = texSet.GetTexture(i);
        auto it = m_textures.find(kiotoTex->GetHandle());
        if (it == m_textures.end())
            throw "ololo";
        TextureDX12* dxTex = (*it).second;

        D3D12_SHADER_RESOURCE_VIEW_DESC texDescr = {};
        texDescr.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
        texDescr.Format = dxTex->Resource->GetDesc().Format;
        texDescr.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
        texDescr.Texture2D.MipLevels = dxTex->Resource->GetDesc().MipLevels;
        texDescr.Texture2D.MostDetailedMip = 0;
        texDescr.Texture2D.ResourceMinLODClamp = 0.0f;

        state.Device->CreateShaderResourceView(dxTex->Resource.Get(), &texDescr, handle);
        handle.Offset(state.CbvSrvUavDescriptorSize);
    }
}

ID3D12DescriptorHeap* TextureManagerDX12::GetTextureHeap(TextureSetHandle handle) const
{
    auto it = m_textureHeaps.find(handle);
    if (it != m_textureHeaps.cend())
        return it->second.Get();
    return nullptr;
}

TextureDX12* TextureManagerDX12::FindTexture(TextureHandle handle)
{
    auto it = m_textures.find(handle);
    if (it != m_textures.cend())
        return it->second;
    it = m_notOwningTextures.find(handle);
    if (it != m_notOwningTextures.cend())
        return it->second;
    return nullptr;
}

void TextureManagerDX12::RegisterTextureWithoutOwnership(TextureDX12* texture)
{
    auto it = m_notOwningTextures.find(texture->GetHandle());
    if (it != m_notOwningTextures.end())
    {
        throw "Texture Already Registered";
        return;
    }
    m_notOwningTextures[texture->GetHandle()] = texture;
}

void TextureManagerDX12::ProcessRegistationQueue(const StateDX& state)
{
    for (auto& tex : m_textureQueue)
    {
        tex->Create(state.Device.Get(), state.CommandList.Get());
        if (tex->GetIsFromMemoryAsset())
        {
            if ((tex->GetDx12TextureFlags() & D3D12_RESOURCE_FLAGS::D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET) != 0)
            {
                assert(m_rtvHeapOffsets.count(tex->GetHandle()) == 0);
                m_rtvHeapOffsets[tex->GetHandle()] = m_currentRtvOffset;

                CD3DX12_CPU_DESCRIPTOR_HANDLE handle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart());
                handle.Offset(m_currentRtvOffset);

                m_currentRtvOffset += state.RtvDescriptorSize;

                D3D12_RENDER_TARGET_VIEW_DESC texDescr = {};
                texDescr.Format = tex->Resource->GetDesc().Format;
                texDescr.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
                texDescr.Texture2D = { 0, 0 };

                state.Device->CreateRenderTargetView(tex->Resource.Get(), &texDescr, handle);
            }
            else if ((tex->GetDx12TextureFlags() & D3D12_RESOURCE_FLAGS::D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL) != 0)
            {
                assert(m_dsvHeapOffsets.count(tex->GetHandle()) == 0);
                m_dsvHeapOffsets[tex->GetHandle()] = m_currentDsvOffset;

                CD3DX12_CPU_DESCRIPTOR_HANDLE handle(m_dsvHeap->GetCPUDescriptorHandleForHeapStart());
                handle.Offset(m_currentDsvOffset);

                m_currentDsvOffset += state.DsvDescriptorSize;

                D3D12_DEPTH_STENCIL_VIEW_DESC texDescr = {};
                texDescr.Format = tex->Resource->GetDesc().Format;
                texDescr.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
                texDescr.Texture2D = { 0 };

                state.Device->CreateDepthStencilView(tex->Resource.Get(), &texDescr, handle);
            }
        }
    }
    m_textureQueue.clear();
}

void TextureManagerDX12::QueueTextureSetForUpdate(const TextureSet& texSet)
{
    if (texSet.GetHandle() == InvalidHandle)
        throw "Invalid handle";

    auto it = std::find(m_textureSetUpdateQueue.cbegin(), m_textureSetUpdateQueue.cend(), &texSet);
    if (it != m_textureSetUpdateQueue.cend())
        return;

    m_textureSetUpdateQueue.push_back(&texSet);
}

void TextureManagerDX12::ProcessTextureSetUpdates(const StateDX& state)
{
    for (auto& texSet : m_textureSetUpdateQueue)
        UpdateTextureSetHeap(state, *texSet);
    m_textureSetUpdateQueue.clear();
}

D3D12_CPU_DESCRIPTOR_HANDLE TextureManagerDX12::GetRtvHandle(TextureHandle handle) const
{
    assert(m_rtvHeapOffsets.count(handle) == 1 && "The texture is not registered as a rtv");
    CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart());
    rtvHandle.Offset(m_rtvHeapOffsets.at(handle));
    return rtvHandle;
}

D3D12_CPU_DESCRIPTOR_HANDLE TextureManagerDX12::GetDsvHandle(TextureHandle handle) const
{
    assert(m_dsvHeapOffsets.count(handle) == 1 && "The texture is not registred as a dsv");
    CD3DX12_CPU_DESCRIPTOR_HANDLE dsvHandle(m_dsvHeap->GetCPUDescriptorHandleForHeapStart());
    dsvHandle.Offset(m_dsvHeapOffsets.at(handle));
    return dsvHandle;
}

}<|endoftext|>


<commit_before>// -*- c-basic-offset: 2; related-file-name: "aggwrap.h" -*-
/*
 * @(#)$Id$
 *
 * This file is distributed under the terms in the attached LICENSE file.
 * If you do not find this file, copies can be found by writing to:
 * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300,
 * Berkeley, CA, 94704.  Attention:  Intel License Inquiry.
 * Or
 * UC Berkeley EECS Computer Science Division, 387 Soda Hall #1776,
 * Berkeley, CA,  94707. Attention: P2 Group.
 *
 */

#include "aggwrap.h"
#include "trace.h"
#include "val_int32.h"
#include "val_str.h"
#include "loop.h"

Aggwrap::Aggwrap(string name, string aggfn, int aggfield, string outputTableName)
  : Element(name, 2, 2),
    _aggfn(aggfn),
    _aggfield(aggfield),
    inner_accepting(true),
    ext_in_cb(0),
    ext_out_cb(0)
{
  numJoins = 0;
  _outputTableName = outputTableName;
  ostringstream os;
  if (aggfn == "MIN") {
    os << "min aggregation " << _aggfield;
  } else if (aggfn == "MAX") {
    os << "max aggregation " << _aggfield;
  } else if (aggfn == "COUNT") {
    os << "count aggregation " << _aggfield;
  } else {
    os << "HELP: Don't understand agg function '" << aggfn << "'";
  }
  ELEM_INFO( os.str() );
}

//
// A new tuple is coming in from outside.
//
int Aggwrap::push(int port, TuplePtr t, b_cbv cb)
{
  ostringstream os;
  os << " Push: " << port << "," << t->toString();
  ELEM_INFO( os.str() );

  // if receive the next one when previous has not finished, then keep in queue?

  // Is this the right port?
  switch (port) {
  case 0:
    ext_in_cb = cb;
    switch(aggState) {
    case 0:  // Waiting
      ELEM_INFO( " received a tuple from outside!" + t->toString());
      assert(inner_accepting);
      agg_init();
      _incomingTuple = t;
      inner_accepting = output(1)->push(t, boost::bind( &Aggwrap::int_push_cb, this ));
      break;
    case 1:
      ELEM_INFO( "FAIL: pushed when processing!");
      // Discard tuple
      break;
    case 2:
      ELEM_INFO( "FAIL: pushed when done pending");
      break;
    default:
      ostringstream os;
      os << "FAIL: weird state " << aggState;
      ELEM_INFO( os.str() );
    }
    ELEM_INFO( " Block downstream");
    return 0;
  case 1:
    switch(aggState) {
    case 0:  // Waiting
      ELEM_INFO(
	  "OOPS: unexpected result tuple when in state waiting");
      break;
    case 1:
      agg_accum(t);
      break;
    case 2:
      ELEM_INFO( "FAIL: pushed when done pending");
      break;
    default:
      ostringstream os;
      os << "FAIL: weird state " << aggState;
      ELEM_INFO( os.str());
    }
    return 1;
  default:
    assert(port < 2);
    return  0;
  }

}

//
// Callback from the inner graph when we can push more tuples.
//
void Aggwrap::int_push_cb()
{
  TRC_FN;
  inner_accepting = true;
  ostringstream os;
  os << "Callback from inner graph on successful push" << aggState;
  ELEM_INFO( os.str());
  if (aggState == 0 && ext_in_cb) {
    ELEM_INFO( "Invoke ext_in_cb");
    ext_in_cb();
    ext_in_cb = 0;
  }
}

//
// Completion callback
//
void Aggwrap::comp_cb(int jnum)
{
  TRC_FN;
  ostringstream os;
  os << "Join " << jnum << " completed.";
  ELEM_INFO( os.str());
  if (curJoin < jnum) {
    curJoin = jnum;
  }

  if (curJoin >= numJoins - 1) {
    // Presumably, we're now done.
    agg_finalize();
  }
}

//
// Getting hold of a closure for the above
//
b_cbv Aggwrap::get_comp_cb()
{
  ostringstream os;
  os << "Joins so far: " << numJoins + 1;
  ELEM_INFO( os.str());
  return boost::bind(&Aggwrap::comp_cb,this,numJoins++);
}

//
// Finally, the aggregation functions
//
void Aggwrap::agg_init() {
  TRC_FN;
  curJoin = -1;
  aggState = 1;
  if ( _aggfn == "COUNT") {
    count = 0;
  } else {
    aggResult.reset();
  }
}

void Aggwrap::agg_accum(TuplePtr t) {
  TRC_FN;
  if ( _aggfn == "COUNT") {
    count++;
    aggResult = t;
    ELEM_INFO( "After Agg accumulation: " + aggResult->toString());
    return;
  }

  if ( aggResult == NULL ) {
    aggResult = t;
    ELEM_INFO( "After Agg accumulation: " + aggResult->toString());
    return;
  }

  ELEM_INFO( "Before Agg accumulation: " + aggResult->toString());
  int cr = (*t)[_aggfield]->compareTo((*aggResult)[_aggfield]);
  if ((cr == -1 && _aggfn == "MIN") || (cr == 1 && _aggfn == "MAX")) {
    aggResult = t;
  }
  ELEM_INFO( "After Agg accumulation: " + aggResult->toString()
      + "\n " + (*t)[_aggfield]->toString() + " "
      + (*aggResult)[_aggfield]->toString());
}

void Aggwrap::agg_finalize() {
  TRC_FN;
  if (_aggfn == "COUNT") {
    if (_incomingTuple) {
      TuplePtr aggResultToRet = Tuple::mk();
      aggResultToRet->append(Val_Str::mk(_outputTableName));
      for (uint k = 0; k < _groupByFields.size(); k++) {
	/*warn << _incomingTuple->toString() << " "
	  << _groupByFields.at(k) + 1 << "\n";     */
	aggResultToRet->append((*_incomingTuple)[_groupByFields.at(k)+1]);
      }
      aggResultToRet->append(Val_Int32::mk(count));
      aggResultToRet->freeze();

      aggResult = Tuple::mk();
      aggResult->concat(aggResultToRet);
      aggResult->freeze();
    }
  }
  if (aggResult) {
    ELEM_INFO( " finalize: Pushing tuple" + aggResult->toString());
    output(0)->push(aggResult, 0);
  } else {
    ELEM_INFO( "Finalize: Alas, nothing to push");
  }
  if (ext_in_cb) {
    ELEM_INFO( "Invoke push callback for more tuples");
    // accept new tuples to be pushed in via outer regardless of any outputs
    ext_in_cb();
    ext_in_cb = 0;
  }
  aggState = 0;
}

void Aggwrap::registerGroupbyField(int field)
{
  _groupByFields.push_back(field);
  warn << "Register group by " << field << "\n";
}
<commit_msg>aggwrap count fix<commit_after>// -*- c-basic-offset: 2; related-file-name: "aggwrap.h" -*-
/*
 * @(#)$Id$
 *
 * This file is distributed under the terms in the attached LICENSE file.
 * If you do not find this file, copies can be found by writing to:
 * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300,
 * Berkeley, CA, 94704.  Attention:  Intel License Inquiry.
 * Or
 * UC Berkeley EECS Computer Science Division, 387 Soda Hall #1776,
 * Berkeley, CA,  94707. Attention: P2 Group.
 *
 */

#include "aggwrap.h"
#include "trace.h"
#include "val_int32.h"
#include "val_str.h"
#include "loop.h"

Aggwrap::Aggwrap(string name, string aggfn, int aggfield, string outputTableName)
  : Element(name, 2, 2),
    _aggfn(aggfn),
    _aggfield(aggfield),
    inner_accepting(true),
    ext_in_cb(0),
    ext_out_cb(0)
{
  numJoins = 0;
  _outputTableName = outputTableName;
  ostringstream os;
  if (aggfn == "MIN") {
    os << "min aggregation " << _aggfield;
  } else if (aggfn == "MAX") {
    os << "max aggregation " << _aggfield;
  } else if (aggfn == "COUNT") {
    os << "count aggregation " << _aggfield;
  } else {
    os << "HELP: Don't understand agg function '" << aggfn << "'";
  }
  ELEM_INFO( os.str() );
}

//
// A new tuple is coming in from outside.
//
int Aggwrap::push(int port, TuplePtr t, b_cbv cb)
{
  ostringstream os;
  os << " Push: " << port << "," << t->toString();
  ELEM_INFO( os.str() );

  // if receive the next one when previous has not finished, then keep in queue?

  // Is this the right port?
  switch (port) {
  case 0:
    ext_in_cb = cb;
    switch(aggState) {
    case 0:  // Waiting
      ELEM_INFO( " received a tuple from outside!" + t->toString());
      assert(inner_accepting);
      agg_init();
      _incomingTuple = t;
      inner_accepting = output(1)->push(t, boost::bind( &Aggwrap::int_push_cb, this ));
      break;
    case 1:
      ELEM_INFO( "FAIL: pushed when processing!");
      // Discard tuple
      break;
    case 2:
      ELEM_INFO( "FAIL: pushed when done pending");
      break;
    default:
      ostringstream os;
      os << "FAIL: weird state " << aggState;
      ELEM_INFO( os.str() );
    }
    ELEM_INFO( " Block downstream");
    return 0;
  case 1:
    switch(aggState) {
    case 0:  // Waiting
      ELEM_INFO(
	  "OOPS: unexpected result tuple when in state waiting");
      break;
    case 1:
      agg_accum(t);
      break;
    case 2:
      ELEM_INFO( "FAIL: pushed when done pending");
      break;
    default:
      ostringstream os;
      os << "FAIL: weird state " << aggState;
      ELEM_INFO( os.str());
    }
    return 1;
  default:
    assert(port < 2);
    return  0;
  }

}

//
// Callback from the inner graph when we can push more tuples.
//
void Aggwrap::int_push_cb()
{
  TRC_FN;
  inner_accepting = true;
  ostringstream os;
  os << "Callback from inner graph on successful push" << aggState;
  ELEM_INFO( os.str());
  if (aggState == 0 && ext_in_cb) {
    ELEM_INFO( "Invoke ext_in_cb");
    ext_in_cb();
    ext_in_cb = 0;
  }
}

//
// Completion callback
//
void Aggwrap::comp_cb(int jnum)
{
  TRC_FN;
  ostringstream os;
  os << "Join " << jnum << " completed.";
  ELEM_INFO( os.str());
  if (curJoin < jnum) {
    curJoin = jnum;
  }

  if (curJoin >= numJoins - 1) {
    // Presumably, we're now done.
    agg_finalize();
  }
}

//
// Getting hold of a closure for the above
//
b_cbv Aggwrap::get_comp_cb()
{
  ostringstream os;
  os << "Joins so far: " << numJoins + 1;
  ELEM_INFO( os.str());
  return boost::bind(&Aggwrap::comp_cb,this,numJoins++);
}

//
// Finally, the aggregation functions
//
void Aggwrap::agg_init() {
  TRC_FN;
  curJoin = -1;
  aggState = 1;
  if ( _aggfn == "COUNT") {
    count = 0;
  } else {
    aggResult.reset();
  }
}

void Aggwrap::agg_accum(TuplePtr t) {
  TRC_FN;
  if ( _aggfn == "COUNT") {
    count++;
    aggResult = t;
    ELEM_INFO( "After Agg accumulation: " + aggResult->toString());
    return;
  }

  if ( aggResult == NULL ) {
    aggResult = t;
    ELEM_INFO( "After Agg accumulation: " + aggResult->toString());
    return;
  }

  ELEM_INFO( "Before Agg accumulation: " + aggResult->toString());
  int cr = (*t)[_aggfield]->compareTo((*aggResult)[_aggfield]);
  if ((cr == -1 && _aggfn == "MIN") || (cr == 1 && _aggfn == "MAX")) {
    aggResult = t;
  }
  ELEM_INFO( "After Agg accumulation: " + aggResult->toString()
      + "\n " + (*t)[_aggfield]->toString() + " "
      + (*aggResult)[_aggfield]->toString());
}

void Aggwrap::agg_finalize() {
  TRC_FN;
  if (_aggfn == "COUNT") {
    if (_incomingTuple) {
      TuplePtr aggResultToRet = Tuple::mk();
      aggResultToRet->append(Val_Str::mk(_outputTableName));
      for (uint k = 0; k < _groupByFields.size(); k++) {
	/*warn << _incomingTuple->toString() << " "
	  << _groupByFields.at(k) + 1 << "\n";     */
	aggResultToRet->append((*_incomingTuple)[_groupByFields.at(k)]);
      }
      aggResultToRet->append(Val_Int32::mk(count));
      aggResultToRet->freeze();

      aggResult = Tuple::mk();
      aggResult->concat(aggResultToRet);
      aggResult->freeze();
    }
  }
  if (aggResult) {
    ELEM_INFO( " finalize: Pushing tuple" + aggResult->toString());
    output(0)->push(aggResult, 0);
  } else {
    ELEM_INFO( "Finalize: Alas, nothing to push");
  }
  if (ext_in_cb) {
    ELEM_INFO( "Invoke push callback for more tuples");
    // accept new tuples to be pushed in via outer regardless of any outputs
    ext_in_cb();
    ext_in_cb = 0;
  }
  aggState = 0;
}

void Aggwrap::registerGroupbyField(int field)
{
  _groupByFields.push_back(field);
  warn << "Register group by " << field << "\n";
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017 deipi.com LLC and contributors. All rights reserved.
 *
 * 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.
 */

#include "geospatial.h"

#include "../cast.h"

const std::unordered_map<std::string, GeoSpatial::dispatch_func> GeoSpatial::map_dispatch({
	{ GEO_LATITUDE,          &GeoSpatial::process_latitude    },
	{ GEO_LONGITUDE,         &GeoSpatial::process_longitude   },
	{ GEO_HEIGHT,            &GeoSpatial::process_height      },
	{ GEO_RADIUS,            &GeoSpatial::process_radius      },
	{ GEO_UNITS,             &GeoSpatial::process_units       },
	{ GEO_SRID,              &GeoSpatial::process_srid        },
});

GeoSpatial::GeoSpatial(const MsgPack& obj)
{
	switch (obj.getType()) {
		case MsgPack::Type::STR: {
			EWKT ewkt(obj.as_string());
			geometry = std::move(ewkt.geometry);
			return;
		}
		case MsgPack::Type::MAP: {
			const auto str_key = obj.begin()->as_string();
			switch ((Cast::Hash)xxh64::hash(str_key)) {
				case Cast::Hash::POINT:
					geometry = make_point(obj.at(str_key));
					return;
				case Cast::Hash::CIRCLE:
					geometry = make_circle(obj.at(str_key));
					return;
				case Cast::Hash::CONVEX:
					geometry = make_convex(obj.at(str_key));
					return;
				case Cast::Hash::POLYGON:
					THROW(GeoSpatialError, "Not implemented yet");
				case Cast::Hash::CHULL:
					THROW(GeoSpatialError, "Not implemented yet");
				case Cast::Hash::MULTIPOINT:
					geometry = make_multipoint(obj.at(str_key));
					return;
				case Cast::Hash::MULTICIRCLE:
					geometry = make_multicircle(obj.at(str_key));
					return;
				case Cast::Hash::MULTIPOLYGON:
				case Cast::Hash::MULTICHULL:
				case Cast::Hash::GEO_COLLECTION:
				case Cast::Hash::GEO_INTERSECTION:
					THROW(GeoSpatialError, "Not implemented yet");
				default:
					THROW(GeoSpatialError, "Unknown geometry %s", str_key.c_str());
			}
		}
		default:
			THROW(GeoSpatialError, "Object must be string or map");
	}
}

inline void
GeoSpatial::process_latitude(data_t& data, const MsgPack& latitude) {
	data.lat = &latitude;
}

inline void
GeoSpatial::process_longitude(data_t& data, const MsgPack& longitude) {
	data.lon = &longitude;
}

inline void
GeoSpatial::process_height(data_t& data, const MsgPack& height) {
	data.height = &height;
}

inline void
GeoSpatial::process_radius(data_t& data, const MsgPack& radius) {
	if (!data.has_radius) {
		THROW(GeoSpatialError, "%s applies only to %s or %s", GEO_RADIUS, RESERVED_CIRCLE, RESERVED_MULTICIRCLE);
	}
	data.radius = &radius;
}

inline void
GeoSpatial::process_units(data_t& data, const MsgPack& units)
{
	try {
		const auto str = units.as_string();
		if (str == "degrees") {
			data.units = Cartesian::Units::DEGREES;
		} else if (str == "radians") {
			data.units = Cartesian::Units::RADIANS;
		} else {
			THROW(GeoSpatialError, "%s must be \"degrees\" or \"radians\"", GEO_UNITS);
		}
	} catch (const msgpack::type_error&) {
		THROW(GeoSpatialError, "%s must be string (\"degrees\" or \"radians\")", GEO_UNITS);
	}
}

inline void
GeoSpatial::process_srid(data_t& data, const MsgPack& srid) {
	try {
		data.srid = srid.as_i64();
		if (!Cartesian::is_SRID_supported(data.srid)) {
			THROW(GeoSpatialError, "SRID = %d is not supported", data.srid);
		}
	} catch (const msgpack::type_error&) {
		THROW(GeoSpatialError, "%s must be integer", GEO_SRID);
	}
}

GeoSpatial::data_t
GeoSpatial::get_data(const MsgPack& o, bool has_radius)
{
	data_t data(has_radius);
	static const auto dit_e = map_dispatch.end();
	const auto it_e = o.end();
	for (auto it = o.begin(); it != it_e; ++it) {
		const auto str_key = it->as_string();
		const auto dit = map_dispatch.find(str_key);
		if (dit == dit_e) {
			THROW(GeoSpatialError, "%s is a invalid word", str_key.c_str());
		} else {
			(this->*dit->second)(data, it.value());
		}
	}
	return data;
}

std::unique_ptr<Point>
GeoSpatial::make_point(const MsgPack& o)
{
	if (o.is_map()) {
		const auto data = get_data(o);
		if (data.lat && data.lon) {
			try {
				return std::make_unique<Point>(Cartesian(data.lat->as_f64(), data.lon->as_f64(), data.height ? data.height->as_f64() : 0, data.units, data.srid));
			} catch (const msgpack::type_error&) {
				THROW(GeoSpatialError, "%s, %s and %s must be numeric", GEO_LATITUDE, GEO_LONGITUDE, GEO_HEIGHT);
			}
		} else {
			THROW(GeoSpatialError, "%s must contain %s and %s", RESERVED_POINT, GEO_LATITUDE, GEO_LONGITUDE);
		}
	} else {
		THROW(GeoSpatialError, "%s must be map", RESERVED_POINT);
	}
}

std::unique_ptr<Circle>
GeoSpatial::make_circle(const MsgPack& o)
{
	if (o.is_map()) {
		const auto data = get_data(o, true);
		if (data.lat && data.lon && data.radius) {
			try {
				return std::make_unique<Circle>(Cartesian(data.lat->as_f64(), data.lon->as_f64(), data.height ? data.height->as_f64() : 0, data.units, data.srid), data.radius->as_f64());
			} catch (const msgpack::type_error&) {
				THROW(GeoSpatialError, "%s, %s, %s and %s must be numeric", GEO_LATITUDE, GEO_LONGITUDE, GEO_HEIGHT, GEO_RADIUS);
			}
		} else {
			THROW(GeoSpatialError, "%s must contain %s, %s and %s", RESERVED_CIRCLE, GEO_LATITUDE, GEO_LONGITUDE, GEO_RADIUS);
		}
	} else {
		THROW(GeoSpatialError, "%s must be map", RESERVED_CIRCLE);
	}
}

std::unique_ptr<Convex>
GeoSpatial::make_convex(const MsgPack& o)
{
	if (o.is_map()) {
		const auto data = get_data(o, true);
		if (data.lat && data.lon && data.radius) {
			try {
				if (data.lat->size() == data.lon->size()) {
					if (!data.height) {
						auto convex = std::make_unique<Convex>();
						auto it = data.lon->begin();
						for (const auto& latitude : *data.lat) {
							convex->add(Circle(Cartesian(latitude.as_f64(), it->as_f64(), 0, data.units, data.srid), data.radius->as_f64()));
							++it;
						}
						return convex;
					} else if (data.lat->size() == data.height->size()) {
						auto convex = std::make_unique<Convex>();
						auto it = data.lon->begin();
						auto hit = data.height->begin();
						for (const auto& latitude : *data.lat) {
							convex->add(Circle(Cartesian(latitude.as_f64(), it->as_f64(), hit->as_f64(), data.units, data.srid), data.radius->as_f64()));
							++it;
							++hit;
						}
						return convex;
					}

				}
				THROW(GeoSpatialError, "%s, %s and %s must have the same size", GEO_LATITUDE, GEO_LONGITUDE, GEO_HEIGHT);
			} catch (const msgpack::type_error&) {
				THROW(GeoSpatialError, "%s, %s, %s and %s must be numeric", GEO_LATITUDE, GEO_LONGITUDE, GEO_HEIGHT, GEO_RADIUS);
			}
		} else {
			THROW(GeoSpatialError, "%s must contain %s, %s and %s", RESERVED_CONVEX, GEO_LATITUDE, GEO_LONGITUDE, GEO_RADIUS);
		}
	} else {
		THROW(GeoSpatialError, "%s must be map", RESERVED_CONVEX);
	}
}

std::unique_ptr<MultiPoint>
GeoSpatial::make_multipoint(const MsgPack& o)
{
	if (o.is_map()) {
		const auto data = get_data(o);
		if (data.lat && data.lon) {
			try {
				if (data.lat->size() == data.lon->size()) {
					if (!data.height) {
						auto multipoint = std::make_unique<MultiPoint>();
						auto it = data.lon->begin();
						for (const auto& latitude : *data.lat) {
							multipoint->add(Point(Cartesian(latitude.as_f64(), it->as_f64(), 0, data.units, data.srid)));
							++it;
						}
						return multipoint;
					} else if (data.lat->size() == data.height->size()) {
						auto multipoint = std::make_unique<MultiPoint>();
						auto it = data.lon->begin();
						auto hit = data.height->begin();
						for (const auto& latitude : *data.lat) {
							multipoint->add(Point(Cartesian(latitude.as_f64(), it->as_f64(), hit->as_f64(), data.units, data.srid)));
							++it;
							++hit;
						}
						return multipoint;
					}

				}
				THROW(GeoSpatialError, "%s, %s and %s must have the same size", GEO_LATITUDE, GEO_LONGITUDE, GEO_HEIGHT);
			} catch (const msgpack::type_error&) {
				THROW(GeoSpatialError, "%s, %s and %s must be numeric", GEO_LATITUDE, GEO_LONGITUDE, GEO_HEIGHT);
			}
		} else {
			THROW(GeoSpatialError, "%s must contain %s and %s", RESERVED_MULTIPOINT, GEO_LATITUDE, GEO_LONGITUDE);
		}
	} else {
		THROW(GeoSpatialError, "%s must be map", RESERVED_MULTIPOINT);
	}
}

std::unique_ptr<MultiCircle>
GeoSpatial::make_multicircle(const MsgPack& o)
{
	if (o.is_map()) {
		const auto data = get_data(o, true);
		if (data.lat && data.lon && data.radius) {
			try {
				if (data.lat->size() == data.lon->size()) {
					if (!data.height) {
						auto multicircle = std::make_unique<MultiCircle>();
						auto it = data.lon->begin();
						for (const auto& latitude : *data.lat) {
							multicircle->add(Circle(Cartesian(latitude.as_f64(), it->as_f64(), 0, data.units, data.srid), data.radius->as_f64()));
							++it;
						}
						return multicircle;
					} else if (data.lat->size() == data.height->size()) {
						auto multicircle = std::make_unique<MultiCircle>();
						auto it = data.lon->begin();
						auto hit = data.height->begin();
						for (const auto& latitude : *data.lat) {
							multicircle->add(Circle(Cartesian(latitude.as_f64(), it->as_f64(), hit->as_f64(), data.units, data.srid), data.radius->as_f64()));
							++it;
							++hit;
						}
						return multicircle;
					}

				}
				THROW(GeoSpatialError, "%s, %s and %s must have the same size", GEO_LATITUDE, GEO_LONGITUDE, GEO_HEIGHT);
			} catch (const msgpack::type_error&) {
				THROW(GeoSpatialError, "%s, %s, %s and %s must be numeric", GEO_LATITUDE, GEO_LONGITUDE, GEO_HEIGHT, GEO_RADIUS);
			}
		} else {
			THROW(GeoSpatialError, "%s must contain %s, %s and %s", RESERVED_MULTICIRCLE, GEO_LATITUDE, GEO_LONGITUDE, GEO_RADIUS);
		}
	} else {
		THROW(GeoSpatialError, "%s must be map", RESERVED_MULTICIRCLE);
	}
}
<commit_msg>Improve exception msg<commit_after>/*
 * Copyright (C) 2017 deipi.com LLC and contributors. All rights reserved.
 *
 * 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.
 */

#include "geospatial.h"

#include "../cast.h"

const std::unordered_map<std::string, GeoSpatial::dispatch_func> GeoSpatial::map_dispatch({
	{ GEO_LATITUDE,          &GeoSpatial::process_latitude    },
	{ GEO_LONGITUDE,         &GeoSpatial::process_longitude   },
	{ GEO_HEIGHT,            &GeoSpatial::process_height      },
	{ GEO_RADIUS,            &GeoSpatial::process_radius      },
	{ GEO_UNITS,             &GeoSpatial::process_units       },
	{ GEO_SRID,              &GeoSpatial::process_srid        },
});

GeoSpatial::GeoSpatial(const MsgPack& obj)
{
	switch (obj.getType()) {
		case MsgPack::Type::STR: {
			EWKT ewkt(obj.as_string());
			geometry = std::move(ewkt.geometry);
			return;
		}
		case MsgPack::Type::MAP: {
			const auto str_key = obj.begin()->as_string();
			switch ((Cast::Hash)xxh64::hash(str_key)) {
				case Cast::Hash::POINT:
					geometry = make_point(obj.at(str_key));
					return;
				case Cast::Hash::CIRCLE:
					geometry = make_circle(obj.at(str_key));
					return;
				case Cast::Hash::CONVEX:
					geometry = make_convex(obj.at(str_key));
					return;
				case Cast::Hash::POLYGON:
					THROW(GeoSpatialError, "Not implemented yet");
				case Cast::Hash::CHULL:
					THROW(GeoSpatialError, "Not implemented yet");
				case Cast::Hash::MULTIPOINT:
					geometry = make_multipoint(obj.at(str_key));
					return;
				case Cast::Hash::MULTICIRCLE:
					geometry = make_multicircle(obj.at(str_key));
					return;
				case Cast::Hash::MULTIPOLYGON:
				case Cast::Hash::MULTICHULL:
				case Cast::Hash::GEO_COLLECTION:
				case Cast::Hash::GEO_INTERSECTION:
					THROW(GeoSpatialError, "Not implemented yet");
				default:
					THROW(GeoSpatialError, "Unknown geometry %s", str_key.c_str());
			}
		}
		default:
			THROW(GeoSpatialError, "Object must be string or map");
	}
}

inline void
GeoSpatial::process_latitude(data_t& data, const MsgPack& latitude) {
	data.lat = &latitude;
}

inline void
GeoSpatial::process_longitude(data_t& data, const MsgPack& longitude) {
	data.lon = &longitude;
}

inline void
GeoSpatial::process_height(data_t& data, const MsgPack& height) {
	data.height = &height;
}

inline void
GeoSpatial::process_radius(data_t& data, const MsgPack& radius) {
	if (!data.has_radius) {
		THROW(GeoSpatialError, "%s applies only to %s or %s", GEO_RADIUS, RESERVED_CIRCLE, RESERVED_MULTICIRCLE);
	}
	data.radius = &radius;
}

inline void
GeoSpatial::process_units(data_t& data, const MsgPack& units)
{
	try {
		const auto str = units.as_string();
		if (str == "degrees") {
			data.units = Cartesian::Units::DEGREES;
		} else if (str == "radians") {
			data.units = Cartesian::Units::RADIANS;
		} else {
			THROW(GeoSpatialError, "%s must be \"degrees\" or \"radians\"", GEO_UNITS);
		}
	} catch (const msgpack::type_error&) {
		THROW(GeoSpatialError, "%s must be string (\"degrees\" or \"radians\")", GEO_UNITS);
	}
}

inline void
GeoSpatial::process_srid(data_t& data, const MsgPack& srid) {
	try {
		data.srid = srid.as_i64();
		if (!Cartesian::is_SRID_supported(data.srid)) {
			THROW(GeoSpatialError, "SRID = %d is not supported", data.srid);
		}
	} catch (const msgpack::type_error&) {
		THROW(GeoSpatialError, "%s must be integer", GEO_SRID);
	}
}

GeoSpatial::data_t
GeoSpatial::get_data(const MsgPack& o, bool has_radius)
{
	data_t data(has_radius);
	static const auto dit_e = map_dispatch.end();
	const auto it_e = o.end();
	for (auto it = o.begin(); it != it_e; ++it) {
		const auto str_key = it->as_string();
		const auto dit = map_dispatch.find(str_key);
		if (dit == dit_e) {
			THROW(GeoSpatialError, "%s is a invalid word", str_key.c_str());
		} else {
			(this->*dit->second)(data, it.value());
		}
	}
	return data;
}

std::unique_ptr<Point>
GeoSpatial::make_point(const MsgPack& o)
{
	if (o.is_map()) {
		const auto data = get_data(o);
		if (data.lat && data.lon) {
			try {
				return std::make_unique<Point>(Cartesian(data.lat->as_f64(), data.lon->as_f64(), data.height ? data.height->as_f64() : 0, data.units, data.srid));
			} catch (const msgpack::type_error&) {
				THROW(GeoSpatialError, "%s, %s and %s must be numeric", GEO_LATITUDE, GEO_LONGITUDE, GEO_HEIGHT);
			}
		} else {
			THROW(GeoSpatialError, "%s must contain %s and %s", RESERVED_POINT, GEO_LATITUDE, GEO_LONGITUDE);
		}
	} else {
		THROW(GeoSpatialError, "%s must be map", RESERVED_POINT);
	}
}

std::unique_ptr<Circle>
GeoSpatial::make_circle(const MsgPack& o)
{
	if (o.is_map()) {
		const auto data = get_data(o, true);
		if (data.lat && data.lon && data.radius) {
			try {
				return std::make_unique<Circle>(Cartesian(data.lat->as_f64(), data.lon->as_f64(), data.height ? data.height->as_f64() : 0, data.units, data.srid), data.radius->as_f64());
			} catch (const msgpack::type_error&) {
				THROW(GeoSpatialError, "%s, %s, %s and %s must be numeric", GEO_LATITUDE, GEO_LONGITUDE, GEO_HEIGHT, GEO_RADIUS);
			}
		} else {
			THROW(GeoSpatialError, "%s must contain %s, %s and %s", RESERVED_CIRCLE, GEO_LATITUDE, GEO_LONGITUDE, GEO_RADIUS);
		}
	} else {
		THROW(GeoSpatialError, "%s must be map", RESERVED_CIRCLE);
	}
}

std::unique_ptr<Convex>
GeoSpatial::make_convex(const MsgPack& o)
{
	if (o.is_map()) {
		const auto data = get_data(o, true);
		if (data.lat && data.lon && data.radius) {
			try {
				if (data.lat->size() == data.lon->size()) {
					if (!data.height) {
						auto convex = std::make_unique<Convex>();
						auto it = data.lon->begin();
						for (const auto& latitude : *data.lat) {
							convex->add(Circle(Cartesian(latitude.as_f64(), it->as_f64(), 0, data.units, data.srid), data.radius->as_f64()));
							++it;
						}
						return convex;
					} else if (data.lat->size() == data.height->size()) {
						auto convex = std::make_unique<Convex>();
						auto it = data.lon->begin();
						auto hit = data.height->begin();
						for (const auto& latitude : *data.lat) {
							convex->add(Circle(Cartesian(latitude.as_f64(), it->as_f64(), hit->as_f64(), data.units, data.srid), data.radius->as_f64()));
							++it;
							++hit;
						}
						return convex;
					}

				}
				THROW(GeoSpatialError, "%s, %s and %s must have the same size", GEO_LATITUDE, GEO_LONGITUDE, GEO_HEIGHT);
			} catch (const msgpack::type_error&) {
				THROW(GeoSpatialError, "%s, %s, %s and %s must be numeric array", GEO_LATITUDE, GEO_LONGITUDE, GEO_HEIGHT, GEO_RADIUS);
			}
		} else {
			THROW(GeoSpatialError, "%s must contain %s, %s and %s", RESERVED_CONVEX, GEO_LATITUDE, GEO_LONGITUDE, GEO_RADIUS);
		}
	} else {
		THROW(GeoSpatialError, "%s must be map", RESERVED_CONVEX);
	}
}

std::unique_ptr<MultiPoint>
GeoSpatial::make_multipoint(const MsgPack& o)
{
	if (o.is_map()) {
		const auto data = get_data(o);
		if (data.lat && data.lon) {
			try {
				if (data.lat->size() == data.lon->size()) {
					if (!data.height) {
						auto multipoint = std::make_unique<MultiPoint>();
						auto it = data.lon->begin();
						for (const auto& latitude : *data.lat) {
							multipoint->add(Point(Cartesian(latitude.as_f64(), it->as_f64(), 0, data.units, data.srid)));
							++it;
						}
						return multipoint;
					} else if (data.lat->size() == data.height->size()) {
						auto multipoint = std::make_unique<MultiPoint>();
						auto it = data.lon->begin();
						auto hit = data.height->begin();
						for (const auto& latitude : *data.lat) {
							multipoint->add(Point(Cartesian(latitude.as_f64(), it->as_f64(), hit->as_f64(), data.units, data.srid)));
							++it;
							++hit;
						}
						return multipoint;
					}

				}
				THROW(GeoSpatialError, "%s, %s and %s must have the same size", GEO_LATITUDE, GEO_LONGITUDE, GEO_HEIGHT);
			} catch (const msgpack::type_error&) {
				THROW(GeoSpatialError, "%s, %s and %s must be numeric array", GEO_LATITUDE, GEO_LONGITUDE, GEO_HEIGHT);
			}
		} else {
			THROW(GeoSpatialError, "%s must contain %s and %s", RESERVED_MULTIPOINT, GEO_LATITUDE, GEO_LONGITUDE);
		}
	} else {
		THROW(GeoSpatialError, "%s must be map", RESERVED_MULTIPOINT);
	}
}

std::unique_ptr<MultiCircle>
GeoSpatial::make_multicircle(const MsgPack& o)
{
	if (o.is_map()) {
		const auto data = get_data(o, true);
		if (data.lat && data.lon && data.radius) {
			try {
				if (data.lat->size() == data.lon->size()) {
					if (!data.height) {
						auto multicircle = std::make_unique<MultiCircle>();
						auto it = data.lon->begin();
						for (const auto& latitude : *data.lat) {
							multicircle->add(Circle(Cartesian(latitude.as_f64(), it->as_f64(), 0, data.units, data.srid), data.radius->as_f64()));
							++it;
						}
						return multicircle;
					} else if (data.lat->size() == data.height->size()) {
						auto multicircle = std::make_unique<MultiCircle>();
						auto it = data.lon->begin();
						auto hit = data.height->begin();
						for (const auto& latitude : *data.lat) {
							multicircle->add(Circle(Cartesian(latitude.as_f64(), it->as_f64(), hit->as_f64(), data.units, data.srid), data.radius->as_f64()));
							++it;
							++hit;
						}
						return multicircle;
					}

				}
				THROW(GeoSpatialError, "%s, %s and %s must have the same size", GEO_LATITUDE, GEO_LONGITUDE, GEO_HEIGHT);
			} catch (const msgpack::type_error&) {
				THROW(GeoSpatialError, "%s, %s, %s and %s must be numeric array", GEO_LATITUDE, GEO_LONGITUDE, GEO_HEIGHT, GEO_RADIUS);
			}
		} else {
			THROW(GeoSpatialError, "%s must contain %s, %s and %s", RESERVED_MULTICIRCLE, GEO_LATITUDE, GEO_LONGITUDE, GEO_RADIUS);
		}
	} else {
		THROW(GeoSpatialError, "%s must be map", RESERVED_MULTICIRCLE);
	}
}
<|endoftext|>


<commit_before>#include "SpritesheetComponent.h"
#include "../../Graphics/SpriteAnimationManager.h"
#include "../../Logger.h"
#include "../TransformComponent.h"
#include "../../Objects/Object.h"
#include "SpriteComponent.h"
#include "TextComponent.h"

namespace star
{
	SpritesheetComponent::SpritesheetComponent
		(const tstring& filePath, const tstring& spriteName,
			const tstring & spritesheet)
		: SpriteComponent(filePath, spriteName)
		, m_SpritesheetName(spritesheet)
		, m_Spritesheet()
		, m_Animations(0)
	{

	}

	SpritesheetComponent::~SpritesheetComponent()
	{
		m_Animations.clear();
	}

	void SpritesheetComponent::Update(const Context& context)
	{
		if(m_Animations.size() > 0
			&& m_Animations.front().IsPlaying())
		{
			m_Animations.front().Update(context);
			auto uvInfo = m_Animations.front().GetCurrentUV();

			SetUVCoords(uvInfo);
		}
		SpriteComponent::Update(context);
	}

	void SpritesheetComponent::Play()
	{
		if(m_Animations.size() > 0)
		{
			m_Animations.front().Play();
		}
		else
		{
			Logger::GetInstance()->Log(LogLevel::Warning,
				_T("SpritesheetComponent::Restart: There is no animation."),
				STARENGINE_LOG_TAG);
		}
	}

	void SpritesheetComponent::Restart()
	{
		if(m_Animations.size() > 0)
		{
			m_Animations.front().Replay();
		}
		else
		{
			Logger::GetInstance()->Log(LogLevel::Warning,
				_T("SpritesheetComponent::Restart: There is no animation."),
				STARENGINE_LOG_TAG);
		}
	}

	void SpritesheetComponent::Pause()
	{
		if(m_Animations.size() > 0)
		{
			m_Animations.front().Pause();
		}
		else
		{
			Logger::GetInstance()->Log(LogLevel::Warning,
				_T("SpritesheetComponent::Pause: There is no animation."),
				STARENGINE_LOG_TAG);
		}
	}

	void SpritesheetComponent::Stop()
	{
		if(m_Animations.size() > 0)
		{
			m_Animations.front().Stop();
		}
		else
		{
			Logger::GetInstance()->Log(LogLevel::Warning,
				_T("SpritesheetComponent::Stop: There is no animation."),
				STARENGINE_LOG_TAG);
		}
	}

	void SpritesheetComponent::PushAnimation(
		const tstring & animation,
		const std::function<void()> & callback
		)
	{
		auto ani = m_Spritesheet[animation];
		ani.SetCallback([&]() { PlayNextAnimation(); });
		ani.SetUserCallback(callback);
		m_Animations.push_back(ani);
	}

	void SpritesheetComponent::PlayAnimation(
		const tstring & animation,
		const std::function<void()> & callback
		)
	{
		if(m_Animations.size() > 0)
		{
			m_Animations.pop_front();
		}
		auto ani = m_Spritesheet[animation];
		ani.SetCallback([&]() { PlayNextAnimation(); });
		ani.SetUserCallback(callback);
		m_Animations.push_front(ani);
	}

	void SpritesheetComponent::PlayAnimation(
		const tstring & animation,
		int32 startFrame,
		const std::function<void()> & callback
		)
	{
		if(m_Animations.size() > 0)
		{
			m_Animations.pop_front();
		}
		auto ani = m_Spritesheet[animation];
		ani.SetCallback([&]() { PlayNextAnimation(); });
		ani.SetUserCallback(callback);
		m_Animations.push_front(ani);
		m_Animations.front().PlayAtFrame(startFrame);

	}

	bool SpritesheetComponent::PushAnimationSafe(
		const tstring & animation,
		const std::function<void()> & callback
		)
	{
		auto it = m_Spritesheet.find(animation);
		if(it != m_Spritesheet.end())
		{
			PushAnimation(animation, callback);
			return true;
		}
		Logger::GetInstance()->Log(LogLevel::Warning,
			_T("SpritesheetComponent::PushAnimationSafe: Couldn't find animation '")
			+ animation + _T("'."), STARENGINE_LOG_TAG);
		return false;
	}

	bool SpritesheetComponent::PlayAnimationSafe(
		const tstring & animation,
		const std::function<void()> & callback
		)
	{
		auto it = m_Spritesheet.find(animation);
		if(it != m_Spritesheet.end())
		{
			PlayAnimation(animation, callback);
			return true;
		}
		Logger::GetInstance()->Log(LogLevel::Warning,
			_T("SpritesheetComponent::PlayAnimationSafe: Couldn't find animation '")
			+ animation + _T("'."), STARENGINE_LOG_TAG);
		return false;
	}

	bool SpritesheetComponent::PlayAnimationSafe(
		const tstring & animation,
		int32 startFrame,
		const std::function<void()> & callback
		)
	{
		auto it = m_Spritesheet.find(animation);
		if(it != m_Spritesheet.end())
		{
			PlayAnimation(animation, startFrame, callback);
			return true;
		}
		Logger::GetInstance()->Log(LogLevel::Warning,
			_T("SpritesheetComponent::PlayAnimationSafe: Couldn't find animation '")
			+ animation + _T("'."), STARENGINE_LOG_TAG);
		return false;
	}

	void SpritesheetComponent::PlayNextAnimation()
	{
		if(m_Animations.size() > 1)
		{
			m_Animations.pop_front();
			m_Animations.front().Replay();
		}
	}

	void SpritesheetComponent::PlayNextAnimation(int32 startFrame)
	{
		if(m_Animations.size() > 1)
		{
			m_Animations.pop_front();
			m_Animations.front().PlayAtFrame(startFrame);
		}
	}

	void SpritesheetComponent::Reset()
	{
		m_Animations.clear();
	}

	void SpritesheetComponent::SetSpritesheet(const tstring & spritesheet)
	{
		m_SpritesheetName = spritesheet;
		m_Spritesheet = SpriteAnimationManager::GetInstance()->GetSpritesheet(m_SpritesheetName);
		Reset();
		PlayAnimation(m_Spritesheet.GetDefaultAnimation());
	}

	tstring SpritesheetComponent::GetCurrentAnimation() const
	{
		if(m_Animations.size() > 0)
		{
			return m_Animations.front().GetName();
		}
		return EMPTY_STRING;
	}

	int32 SpritesheetComponent::GetCurrentFrame() const
	{
		return m_Animations.size() > 0 ?
					m_Animations.front().GetCurrentFrame() : 0;
	}

	const tstring & SpritesheetComponent::GetcurrentSpritesheet() const
	{
		return m_SpritesheetName;
	}

	int32 SpritesheetComponent::GetFramesHorizontal() const
	{
		int32 nrOfFrames = m_Spritesheet.GetFramesHorizontal();
		if(nrOfFrames == 0)
		{
			Logger::GetInstance()->Log(LogLevel::Warning,
				_T("GetFramesHorizontal() -- nrOfFrames = 0!"), STARENGINE_LOG_TAG);
		}
		return nrOfFrames;
	}

	int32 SpritesheetComponent::GetFramesVertical() const
	{
		int32 nrOfFrames = m_Spritesheet.GetFramesVertical();
		if(nrOfFrames == 0)
		{
			Logger::GetInstance()->Log(LogLevel::Warning,
				_T("GetFramesVertical() -- nrOfFrames = 0!"), STARENGINE_LOG_TAG);
		}
		return nrOfFrames;
	}

	void SpritesheetComponent::InitializeComponent()
	{
		if(m_pParentObject->HasComponent<SpriteComponent>(this)
			|| m_pParentObject->HasComponent<TextComponent>(this))
		{
			Logger::GetInstance()->Log(LogLevel::Warning,
				_T("Object '") + m_pParentObject->GetName() +
				_T("': Can't add a SpritesheetComponent when \
already having a Sprite- or TextComponent."));
			m_pParentObject->RemoveComponent(this);
		}
		else
		{
			SetSpritesheet(m_SpritesheetName);
			SpriteComponent::InitializeComponent();

			m_Dimensions.x /= GetFramesHorizontal();
			m_Dimensions.y /= GetFramesVertical();
			GetTransform()->SetDimensionsSafe(m_Dimensions);

			CreateUVCoords();
			FillSpriteInfo();
		}
	}

	void SpritesheetComponent::SetCallbackAnimations( const std::function<void()> & callback )
	{
		for(auto it : m_Animations)
		{
			it.SetCallback(callback);
		}
	}

	bool SpritesheetComponent::IsPlaying()
	{
		return m_Animations.front().IsPlaying();
	}

}
<commit_msg>Hotfix spritebatch 2.11<commit_after>#include "SpritesheetComponent.h"
#include "../../Graphics/SpriteAnimationManager.h"
#include "../../Logger.h"
#include "../TransformComponent.h"
#include "../../Objects/Object.h"
#include "SpriteComponent.h"
#include "TextComponent.h"

namespace star
{
	SpritesheetComponent::SpritesheetComponent
		(const tstring& filePath, const tstring& spriteName,
			const tstring & spritesheet)
		: SpriteComponent(filePath, spriteName)
		, m_SpritesheetName(spritesheet)
		, m_Spritesheet()
		, m_Animations(0)
	{

	}

	SpritesheetComponent::~SpritesheetComponent()
	{
		m_Animations.clear();
	}

	void SpritesheetComponent::Update(const Context& context)
	{
		if(m_Animations.size() > 0
			&& m_Animations.front().IsPlaying())
		{
			m_Animations.front().Update(context);
			auto uvInfo = m_Animations.front().GetCurrentUV();

			SetUVCoords(uvInfo);
		}
		SpriteComponent::Update(context);
	}

	void SpritesheetComponent::Play()
	{
		if(m_Animations.size() > 0)
		{
			m_Animations.front().Play();
		}
		else
		{
			Logger::GetInstance()->Log(LogLevel::Warning,
				_T("SpritesheetComponent::Restart: There is no animation."),
				STARENGINE_LOG_TAG);
		}
	}

	void SpritesheetComponent::Restart()
	{
		if(m_Animations.size() > 0)
		{
			m_Animations.front().Replay();
		}
		else
		{
			Logger::GetInstance()->Log(LogLevel::Warning,
				_T("SpritesheetComponent::Restart: There is no animation."),
				STARENGINE_LOG_TAG);
		}
	}

	void SpritesheetComponent::Pause()
	{
		if(m_Animations.size() > 0)
		{
			m_Animations.front().Pause();
		}
		else
		{
			Logger::GetInstance()->Log(LogLevel::Warning,
				_T("SpritesheetComponent::Pause: There is no animation."),
				STARENGINE_LOG_TAG);
		}
	}

	void SpritesheetComponent::Stop()
	{
		if(m_Animations.size() > 0)
		{
			m_Animations.front().Stop();
		}
		else
		{
			Logger::GetInstance()->Log(LogLevel::Warning,
				_T("SpritesheetComponent::Stop: There is no animation."),
				STARENGINE_LOG_TAG);
		}
	}

	void SpritesheetComponent::PushAnimation(
		const tstring & animation,
		const std::function<void()> & callback
		)
	{
		auto ani = m_Spritesheet[animation];
		ani.SetCallback([&]() { PlayNextAnimation(); });
		ani.SetUserCallback(callback);
		m_Animations.push_back(ani);
	}

	void SpritesheetComponent::PlayAnimation(
		const tstring & animation,
		const std::function<void()> & callback
		)
	{
		if(m_Animations.size() > 0)
		{
			m_Animations.pop_front();
		}
		auto ani = m_Spritesheet[animation];
		ani.SetCallback([&]() { PlayNextAnimation(); });
		ani.SetUserCallback(callback);
		m_Animations.push_front(ani);
	}

	void SpritesheetComponent::PlayAnimation(
		const tstring & animation,
		int32 startFrame,
		const std::function<void()> & callback
		)
	{
		if(m_Animations.size() > 0)
		{
			m_Animations.pop_front();
		}
		auto ani = m_Spritesheet[animation];
		ani.SetCallback([&]() { PlayNextAnimation(); });
		ani.SetUserCallback(callback);
		m_Animations.push_front(ani);
		m_Animations.front().PlayAtFrame(startFrame);

	}

	bool SpritesheetComponent::PushAnimationSafe(
		const tstring & animation,
		const std::function<void()> & callback
		)
	{
		auto it = m_Spritesheet.find(animation);
		if(it != m_Spritesheet.end())
		{
			PushAnimation(animation, callback);
			return true;
		}
		Logger::GetInstance()->Log(LogLevel::Warning,
			_T("SpritesheetComponent::PushAnimationSafe: Couldn't find animation '")
			+ animation + _T("'."), STARENGINE_LOG_TAG);
		return false;
	}

	bool SpritesheetComponent::PlayAnimationSafe(
		const tstring & animation,
		const std::function<void()> & callback
		)
	{
		auto it = m_Spritesheet.find(animation);
		if(it != m_Spritesheet.end())
		{
			PlayAnimation(animation, callback);
			return true;
		}
		Logger::GetInstance()->Log(LogLevel::Warning,
			_T("SpritesheetComponent::PlayAnimationSafe: Couldn't find animation '")
			+ animation + _T("'."), STARENGINE_LOG_TAG);
		return false;
	}

	bool SpritesheetComponent::PlayAnimationSafe(
		const tstring & animation,
		int32 startFrame,
		const std::function<void()> & callback
		)
	{
		auto it = m_Spritesheet.find(animation);
		if(it != m_Spritesheet.end())
		{
			PlayAnimation(animation, startFrame, callback);
			return true;
		}
		Logger::GetInstance()->Log(LogLevel::Warning,
			_T("SpritesheetComponent::PlayAnimationSafe: Couldn't find animation '")
			+ animation + _T("'."), STARENGINE_LOG_TAG);
		return false;
	}

	void SpritesheetComponent::PlayNextAnimation()
	{
		if(m_Animations.size() > 1)
		{
			m_Animations.pop_front();
			m_Animations.front().Replay();
		}
	}

	void SpritesheetComponent::PlayNextAnimation(int32 startFrame)
	{
		if(m_Animations.size() > 1)
		{
			m_Animations.pop_front();
			m_Animations.front().PlayAtFrame(startFrame);
		}
	}

	void SpritesheetComponent::Reset()
	{
		m_Animations.clear();
	}

	void SpritesheetComponent::SetSpritesheet(const tstring & spritesheet)
	{
		m_SpritesheetName = spritesheet;
		m_Spritesheet = SpriteAnimationManager::GetInstance()->GetSpritesheet(m_SpritesheetName);
		Reset();
		PlayAnimation(m_Spritesheet.GetDefaultAnimation());
	}

	tstring SpritesheetComponent::GetCurrentAnimation() const
	{
		if(m_Animations.size() > 0)
		{
			return m_Animations.front().GetName();
		}
		return EMPTY_STRING;
	}

	int32 SpritesheetComponent::GetCurrentFrame() const
	{
		return m_Animations.size() > 0 ?
					m_Animations.front().GetCurrentFrame() : 0;
	}

	const tstring & SpritesheetComponent::GetcurrentSpritesheet() const
	{
		return m_SpritesheetName;
	}

	int32 SpritesheetComponent::GetFramesHorizontal() const
	{
		int32 nrOfFrames = m_Spritesheet.GetFramesHorizontal();
		if(nrOfFrames == 0)
		{
			Logger::GetInstance()->Log(LogLevel::Warning,
				_T("GetFramesHorizontal() -- nrOfFrames = 0!"), STARENGINE_LOG_TAG);
		}
		return nrOfFrames;
	}

	int32 SpritesheetComponent::GetFramesVertical() const
	{
		int32 nrOfFrames = m_Spritesheet.GetFramesVertical();
		if(nrOfFrames == 0)
		{
			Logger::GetInstance()->Log(LogLevel::Warning,
				_T("GetFramesVertical() -- nrOfFrames = 0!"), STARENGINE_LOG_TAG);
		}
		return nrOfFrames;
	}

	void SpritesheetComponent::InitializeComponent()
	{
		if(m_pParentObject->HasComponent<SpriteComponent>(this)
			|| m_pParentObject->HasComponent<TextComponent>(this))
		{
			Logger::GetInstance()->Log(LogLevel::Warning,
				_T("Object '") + m_pParentObject->GetName() +
				_T("': Can't add a SpritesheetComponent when \
already having a Sprite- or TextComponent."));
			m_pParentObject->RemoveComponent(this);
		}
		else
		{
			SetSpritesheet(m_SpritesheetName);
			SpriteComponent::InitializeComponent();

			m_WidthSegments = GetFramesHorizontal();
			m_HeightSegments = GetFramesVertical();
			m_Dimensions.x /= m_WidthSegments;
			m_Dimensions.y /= m_HeightSegments;
			GetTransform()->SetDimensionsSafe(m_Dimensions);

			CreateUVCoords();
			FillSpriteInfo();
		}
	}

	void SpritesheetComponent::SetCallbackAnimations( const std::function<void()> & callback )
	{
		for(auto it : m_Animations)
		{
			it.SetCallback(callback);
		}
	}

	bool SpritesheetComponent::IsPlaying()
	{
		return m_Animations.front().IsPlaying();
	}

}
<|endoftext|>