<commit_before>// This file is part of the dune-hdd project:
//   http://users.dune-project.org/projects/dune-hdd
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_HDD_LINEARELLIPTIC_PROBLEMS_DEFAULT_HH
#define DUNE_HDD_LINEARELLIPTIC_PROBLEMS_DEFAULT_HH

#include <memory>

#if HAVE_ALUGRID
# include <dune/stuff/common/disable_warnings.hh>
#   include <dune/grid/alugrid.hh>
# include <dune/stuff/common/reenable_warnings.hh>
#endif

#include <dune/stuff/common/string.hh>
#include <dune/stuff/common/configuration.hh>
#include <dune/stuff/functions/constant.hh>
#include <dune/stuff/functions/expression.hh>

#include <dune/pymor/functions.hh>
#include <dune/pymor/functions/default.hh>

#include "interfaces.hh"

namespace Dune {
namespace HDD {
namespace LinearElliptic {
namespace Problems {

template< class EntityImp, class DomainFieldImp, int domainDim, class RangeFieldImp, int rangeDim >
class Default
  : public ProblemInterface< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim >
{
protected:
  typedef ProblemInterface< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim > BaseType;
public:
  typedef Default< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim > ThisType;

  using typename BaseType::EntityType;
  using typename BaseType::DomainFieldType;
  using BaseType::dimDomain;
  using typename BaseType::RangeFieldType;
  using BaseType::dimRange;

  using typename BaseType::DiffusionFactorType;
  using typename BaseType::DiffusionTensorType;
  using typename BaseType::FunctionType;

  typedef typename DiffusionFactorType::NonparametricType NonparametricDiffusionFactorType;
  typedef typename DiffusionTensorType::NonparametricType NonparametricDiffusionTensorType;
  typedef typename FunctionType::NonparametricType NonparametricFunctionType;

private:
  typedef Pymor::Functions::NonparametricDefault
      < EntityType, DomainFieldType, dimDomain, RangeFieldType, 1 >                    DiffusionFactorWrapperType;
  typedef Pymor::Functions::NonparametricDefault
      < EntityType, DomainFieldType, dimDomain, RangeFieldType, dimDomain, dimDomain > DiffusiontensorWrapperType;
  typedef Pymor::Functions::NonparametricDefault
      < EntityType, DomainFieldType, dimDomain, RangeFieldType, dimRange >             FunctionWrapperType;

public:
  static const bool available = false;

  static std::string static_id()
  {
    return BaseType::static_id() + ".default";
  }

  static Stuff::Common::Configuration default_config(const std::string sub_name = "")
  {
    Stuff::Common::Configuration config;
    // diffusion factor
    typedef Pymor::Functions::Checkerboard< EntityType, DomainFieldType, dimDomain, RangeFieldType, 1 >
        CheckerBoardFunctionType;
    config.add(CheckerBoardFunctionType::default_config(), "diffusion_factor");
    config["diffusion_factor.parameter_name"] = "diffusion_factor";
    config["diffusion_factor.name"] = "diffusion_factor";
    config["diffusion_factor.type"] = CheckerBoardFunctionType::static_id();
    // diffusion tensor
    typedef Stuff::Functions::Constant< EntityType, DomainFieldType, dimDomain, RangeFieldType, dimDomain, dimDomain >
        ConstantFunctionType;
    config.add(ConstantFunctionType::default_config(), "diffusion_tensor");
    config["diffusion_tensor.name"] = "diffusion_tensor";
    config["diffusion_tensor.type"] = ConstantFunctionType::static_id();
    // force
    typedef Stuff::Functions::Expression< EntityType, DomainFieldType, dimDomain, RangeFieldType, dimRange >
        ExpressionFunctionType;
    config["force.variable"] = "x";
    config["force.expression"] = "1.0";
    config["force.order"] = "0";
    config["force.name"] = "force";
    config["force.type"] = ExpressionFunctionType::static_id();
    // dirichlet values
    config["dirichlet.variable"] = "x";
    config["dirichlet.expression"] = "0.1*x[0]";
    config["dirichlet.order"] = "1";
    config["dirichlet.name"] = "dirichlet";
    config["dirichlet.type"] = ExpressionFunctionType::static_id();
    // neumann values
    config["neumann.variable"] = "x";
    config["neumann.expression"] = "1.0";
    config["neumann.order"] = "0";
    config["neumann.name"] = "neumann";
    config["neumann.type"] = ExpressionFunctionType::static_id();
    if (sub_name.empty())
      return config;
    else {
      Stuff::Common::Configuration tmp;
      tmp.add(config, sub_name);
      return tmp;
    }
  } // ... default_config(...)

  static std::unique_ptr< ThisType > create(const Stuff::Common::Configuration config = default_config(),
                                            const std::string sub_name = static_id())
  {
    const Stuff::Common::Configuration cfg = config.has_sub(sub_name) ? config.sub(sub_name) : config;
    return std::unique_ptr< ThisType >(new ThisType(create_scalar_function("diffusion_factor", cfg),
                                                    create_matrix_function("diffusion_tensor", cfg),
                                                    create_vector_function("force", cfg),
                                                    create_vector_function("dirichlet", cfg),
                                                    create_vector_function("neumann", cfg)));
  } // ... create(...)

  Default(const std::shared_ptr< const NonparametricDiffusionFactorType >& diff_fac,
          const std::shared_ptr< const NonparametricDiffusionTensorType >& diff_ten,
          const std::shared_ptr< const NonparametricFunctionType >& forc,
          const std::shared_ptr< const NonparametricFunctionType >& dir,
          const std::shared_ptr< const NonparametricFunctionType >& neum)
    : diffusion_factor_(std::make_shared< DiffusionFactorWrapperType >(diff_fac))
    , diffusion_tensor_(std::make_shared< DiffusiontensorWrapperType >(diff_ten))
    , force_(std::make_shared< FunctionWrapperType >(forc))
    , dirichlet_(std::make_shared< FunctionWrapperType >(dir))
    , neumann_(std::make_shared< FunctionWrapperType >(neum))
  {}

  Default(const std::shared_ptr< const DiffusionFactorType >& diff_fac,
          const std::shared_ptr< const DiffusionTensorType >& diff_ten,
          const std::shared_ptr< const FunctionType >& forc,
          const std::shared_ptr< const FunctionType >& dir,
          const std::shared_ptr< const FunctionType >& neum)
    : diffusion_factor_(diff_fac)
    , diffusion_tensor_(diff_ten)
    , force_(forc)
    , dirichlet_(dir)
    , neumann_(neum)
  {
    update_parameter_dependency();
  }

  Default(const ThisType& other)
    : diffusion_factor_(other.diffusion_factor_)
    , diffusion_tensor_(other.diffusion_tensor_)
    , force_(other.force_)
    , dirichlet_(other.dirichlet_)
    , neumann_(other.neumann_)
  {
    update_parameter_dependency();
  }

  ThisType& operator=(const ThisType& other) = delete;

  virtual std::string type() const override
  {
    return BaseType::static_id() + ".default";
  }

  virtual const std::shared_ptr< const DiffusionFactorType >& diffusion_factor() const override
  {
    return diffusion_factor_;
  }

  virtual const std::shared_ptr< const DiffusionTensorType >& diffusion_tensor() const override
  {
    return diffusion_tensor_;
  }

  virtual const std::shared_ptr< const FunctionType >& force() const override
  {
    return force_;
  }

  virtual const std::shared_ptr< const FunctionType >& dirichlet() const override
  {
    return dirichlet_;
  }

  virtual const std::shared_ptr< const FunctionType >& neumann() const override
  {
    return neumann_;
  }

protected:
      static std::shared_ptr< Pymor::AffinelyDecomposableFunctionInterface< EntityType, DomainFieldType, dimDomain, RangeFieldType, 1, 1 > >
  create_scalar_function(const std::string& id,
                  const Stuff::Common::Configuration& config)
  {
    typedef Stuff::Functions::Expression< EntityType, DomainFieldType, dimDomain, RangeFieldType, 1, 1 >
        ExpressionFunctionType;
    typedef Pymor::AffinelyDecomposableFunctionsProvider< EntityType, DomainFieldType, dimDomain, RangeFieldType, 1, 1 >
        FunctionsProvider;
    const Stuff::Common::Configuration cfg = config.sub(id);
    const std::string type = cfg.get("type", ExpressionFunctionType::static_id());
    return FunctionsProvider::create(type, cfg);
  } // ... create_scalar_function(...)

      static std::shared_ptr< Pymor::AffinelyDecomposableFunctionInterface< EntityType, DomainFieldType, dimDomain, RangeFieldType, dimRange, 1 > >
  create_vector_function(const std::string& id,
                  const Stuff::Common::Configuration& config)
  {
    typedef Stuff::Functions::Expression< EntityType, DomainFieldType, dimDomain, RangeFieldType, dimRange, 1 >
        ExpressionFunctionType;
    typedef Pymor::AffinelyDecomposableFunctionsProvider< EntityType, DomainFieldType, dimDomain, RangeFieldType, dimRange, 1 >
        FunctionsProvider;
    const Stuff::Common::Configuration cfg = config.sub(id);
    const std::string type = cfg.get("type", ExpressionFunctionType::static_id());
    return FunctionsProvider::create(type, cfg);
  } // ... create_vector_function(...)

      static std::shared_ptr< Pymor::AffinelyDecomposableFunctionInterface< EntityType, DomainFieldType, dimDomain, RangeFieldType, dimDomain, dimDomain > >
  create_matrix_function(const std::string& id, const Stuff::Common::Configuration& config)
  {
    typedef Stuff::Functions::Constant< EntityType, DomainFieldType, dimDomain, RangeFieldType, dimDomain, dimDomain >
        ConstantFunctionType;
    typedef Pymor::AffinelyDecomposableFunctionsProvider< EntityType, DomainFieldType, dimDomain, RangeFieldType, dimDomain, dimDomain >
        FunctionsProvider;
    const Stuff::Common::Configuration cfg = config.sub(id);
    const std::string type = cfg.get("type", ConstantFunctionType::static_id());
    return FunctionsProvider::create(type, cfg);
  } // ... create_matrix_function(...)

  void update_parameter_dependency()
  {
    this->inherit_parameter_type(diffusion_factor_->parameter_type(), "diffusion_factor");
    this->inherit_parameter_type(diffusion_tensor_->parameter_type(), "diffusion_tensor");
    this->inherit_parameter_type(force_->parameter_type(),     "force");
    this->inherit_parameter_type(dirichlet_->parameter_type(), "dirichlet");
    this->inherit_parameter_type(neumann_->parameter_type(),   "neumann");
  } // ... update_parameter_dependency()

  std::shared_ptr< const DiffusionFactorType > diffusion_factor_;
  std::shared_ptr< const DiffusionTensorType > diffusion_tensor_;
  std::shared_ptr< const FunctionType > force_;
  std::shared_ptr< const FunctionType > dirichlet_;
  std::shared_ptr< const FunctionType > neumann_;
}; // class Default

} // namespace Problems
} // namespace LinearElliptic
} // namespace HDD
} // namespace Dune

#endif // DUNE_HDD_LINEARELLIPTIC_PROBLEMS_DEFAULT_HH
<commit_msg>[linearelliptic.problems.default] make available for the provider<commit_after>// This file is part of the dune-hdd project:
//   http://users.dune-project.org/projects/dune-hdd
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_HDD_LINEARELLIPTIC_PROBLEMS_DEFAULT_HH
#define DUNE_HDD_LINEARELLIPTIC_PROBLEMS_DEFAULT_HH

#include <memory>

#if HAVE_ALUGRID
# include <dune/stuff/common/disable_warnings.hh>
#   include <dune/grid/alugrid.hh>
# include <dune/stuff/common/reenable_warnings.hh>
#endif

#include <dune/stuff/common/string.hh>
#include <dune/stuff/common/configuration.hh>
#include <dune/stuff/functions/constant.hh>
#include <dune/stuff/functions/expression.hh>

#include <dune/pymor/functions.hh>
#include <dune/pymor/functions/default.hh>

#include "interfaces.hh"

namespace Dune {
namespace HDD {
namespace LinearElliptic {
namespace Problems {

template< class EntityImp, class DomainFieldImp, int domainDim, class RangeFieldImp, int rangeDim >
class Default
  : public ProblemInterface< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim >
{
protected:
  typedef ProblemInterface< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim > BaseType;
public:
  typedef Default< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim > ThisType;

  using typename BaseType::EntityType;
  using typename BaseType::DomainFieldType;
  using BaseType::dimDomain;
  using typename BaseType::RangeFieldType;
  using BaseType::dimRange;

  using typename BaseType::DiffusionFactorType;
  using typename BaseType::DiffusionTensorType;
  using typename BaseType::FunctionType;

  typedef typename DiffusionFactorType::NonparametricType NonparametricDiffusionFactorType;
  typedef typename DiffusionTensorType::NonparametricType NonparametricDiffusionTensorType;
  typedef typename FunctionType::NonparametricType NonparametricFunctionType;

private:
  typedef Pymor::Functions::NonparametricDefault
      < EntityType, DomainFieldType, dimDomain, RangeFieldType, 1 >                    DiffusionFactorWrapperType;
  typedef Pymor::Functions::NonparametricDefault
      < EntityType, DomainFieldType, dimDomain, RangeFieldType, dimDomain, dimDomain > DiffusiontensorWrapperType;
  typedef Pymor::Functions::NonparametricDefault
      < EntityType, DomainFieldType, dimDomain, RangeFieldType, dimRange >             FunctionWrapperType;

public:
  static const bool available = true;

  static std::string static_id()
  {
    return BaseType::static_id() + ".default";
  }

  static Stuff::Common::Configuration default_config(const std::string sub_name = "")
  {
    Stuff::Common::Configuration config;
    // diffusion factor
    typedef Pymor::Functions::Checkerboard< EntityType, DomainFieldType, dimDomain, RangeFieldType, 1 >
        CheckerBoardFunctionType;
    config.add(CheckerBoardFunctionType::default_config(), "diffusion_factor");
    config["diffusion_factor.parameter_name"] = "diffusion_factor";
    config["diffusion_factor.name"] = "diffusion_factor";
    config["diffusion_factor.type"] = CheckerBoardFunctionType::static_id();
    // diffusion tensor
    typedef Stuff::Functions::Constant< EntityType, DomainFieldType, dimDomain, RangeFieldType, dimDomain, dimDomain >
        ConstantFunctionType;
    config.add(ConstantFunctionType::default_config(), "diffusion_tensor");
    config["diffusion_tensor.name"] = "diffusion_tensor";
    config["diffusion_tensor.type"] = ConstantFunctionType::static_id();
    // force
    typedef Stuff::Functions::Expression< EntityType, DomainFieldType, dimDomain, RangeFieldType, dimRange >
        ExpressionFunctionType;
    config["force.variable"] = "x";
    config["force.expression"] = "1.0";
    config["force.order"] = "0";
    config["force.name"] = "force";
    config["force.type"] = ExpressionFunctionType::static_id();
    // dirichlet values
    config["dirichlet.variable"] = "x";
    config["dirichlet.expression"] = "0.1*x[0]";
    config["dirichlet.order"] = "1";
    config["dirichlet.name"] = "dirichlet";
    config["dirichlet.type"] = ExpressionFunctionType::static_id();
    // neumann values
    config["neumann.variable"] = "x";
    config["neumann.expression"] = "1.0";
    config["neumann.order"] = "0";
    config["neumann.name"] = "neumann";
    config["neumann.type"] = ExpressionFunctionType::static_id();
    if (sub_name.empty())
      return config;
    else {
      Stuff::Common::Configuration tmp;
      tmp.add(config, sub_name);
      return tmp;
    }
  } // ... default_config(...)

  static std::unique_ptr< ThisType > create(const Stuff::Common::Configuration config = default_config(),
                                            const std::string sub_name = static_id())
  {
    const Stuff::Common::Configuration cfg = config.has_sub(sub_name) ? config.sub(sub_name) : config;
    return std::unique_ptr< ThisType >(new ThisType(create_scalar_function("diffusion_factor", cfg),
                                                    create_matrix_function("diffusion_tensor", cfg),
                                                    create_vector_function("force", cfg),
                                                    create_vector_function("dirichlet", cfg),
                                                    create_vector_function("neumann", cfg)));
  } // ... create(...)

  Default(const std::shared_ptr< const NonparametricDiffusionFactorType >& diff_fac,
          const std::shared_ptr< const NonparametricDiffusionTensorType >& diff_ten,
          const std::shared_ptr< const NonparametricFunctionType >& forc,
          const std::shared_ptr< const NonparametricFunctionType >& dir,
          const std::shared_ptr< const NonparametricFunctionType >& neum)
    : diffusion_factor_(std::make_shared< DiffusionFactorWrapperType >(diff_fac))
    , diffusion_tensor_(std::make_shared< DiffusiontensorWrapperType >(diff_ten))
    , force_(std::make_shared< FunctionWrapperType >(forc))
    , dirichlet_(std::make_shared< FunctionWrapperType >(dir))
    , neumann_(std::make_shared< FunctionWrapperType >(neum))
  {}

  Default(const std::shared_ptr< const DiffusionFactorType >& diff_fac,
          const std::shared_ptr< const DiffusionTensorType >& diff_ten,
          const std::shared_ptr< const FunctionType >& forc,
          const std::shared_ptr< const FunctionType >& dir,
          const std::shared_ptr< const FunctionType >& neum)
    : diffusion_factor_(diff_fac)
    , diffusion_tensor_(diff_ten)
    , force_(forc)
    , dirichlet_(dir)
    , neumann_(neum)
  {
    update_parameter_dependency();
  }

  Default(const ThisType& other)
    : diffusion_factor_(other.diffusion_factor_)
    , diffusion_tensor_(other.diffusion_tensor_)
    , force_(other.force_)
    , dirichlet_(other.dirichlet_)
    , neumann_(other.neumann_)
  {
    update_parameter_dependency();
  }

  ThisType& operator=(const ThisType& other) = delete;

  virtual std::string type() const override
  {
    return BaseType::static_id() + ".default";
  }

  virtual const std::shared_ptr< const DiffusionFactorType >& diffusion_factor() const override
  {
    return diffusion_factor_;
  }

  virtual const std::shared_ptr< const DiffusionTensorType >& diffusion_tensor() const override
  {
    return diffusion_tensor_;
  }

  virtual const std::shared_ptr< const FunctionType >& force() const override
  {
    return force_;
  }

  virtual const std::shared_ptr< const FunctionType >& dirichlet() const override
  {
    return dirichlet_;
  }

  virtual const std::shared_ptr< const FunctionType >& neumann() const override
  {
    return neumann_;
  }

protected:
      static std::shared_ptr< Pymor::AffinelyDecomposableFunctionInterface< EntityType, DomainFieldType, dimDomain, RangeFieldType, 1, 1 > >
  create_scalar_function(const std::string& id,
                  const Stuff::Common::Configuration& config)
  {
    typedef Stuff::Functions::Expression< EntityType, DomainFieldType, dimDomain, RangeFieldType, 1, 1 >
        ExpressionFunctionType;
    typedef Pymor::AffinelyDecomposableFunctionsProvider< EntityType, DomainFieldType, dimDomain, RangeFieldType, 1, 1 >
        FunctionsProvider;
    const Stuff::Common::Configuration cfg = config.sub(id);
    const std::string type = cfg.get("type", ExpressionFunctionType::static_id());
    return FunctionsProvider::create(type, cfg);
  } // ... create_scalar_function(...)

      static std::shared_ptr< Pymor::AffinelyDecomposableFunctionInterface< EntityType, DomainFieldType, dimDomain, RangeFieldType, dimRange, 1 > >
  create_vector_function(const std::string& id,
                  const Stuff::Common::Configuration& config)
  {
    typedef Stuff::Functions::Expression< EntityType, DomainFieldType, dimDomain, RangeFieldType, dimRange, 1 >
        ExpressionFunctionType;
    typedef Pymor::AffinelyDecomposableFunctionsProvider< EntityType, DomainFieldType, dimDomain, RangeFieldType, dimRange, 1 >
        FunctionsProvider;
    const Stuff::Common::Configuration cfg = config.sub(id);
    const std::string type = cfg.get("type", ExpressionFunctionType::static_id());
    return FunctionsProvider::create(type, cfg);
  } // ... create_vector_function(...)

      static std::shared_ptr< Pymor::AffinelyDecomposableFunctionInterface< EntityType, DomainFieldType, dimDomain, RangeFieldType, dimDomain, dimDomain > >
  create_matrix_function(const std::string& id, const Stuff::Common::Configuration& config)
  {
    typedef Stuff::Functions::Constant< EntityType, DomainFieldType, dimDomain, RangeFieldType, dimDomain, dimDomain >
        ConstantFunctionType;
    typedef Pymor::AffinelyDecomposableFunctionsProvider< EntityType, DomainFieldType, dimDomain, RangeFieldType, dimDomain, dimDomain >
        FunctionsProvider;
    const Stuff::Common::Configuration cfg = config.sub(id);
    const std::string type = cfg.get("type", ConstantFunctionType::static_id());
    return FunctionsProvider::create(type, cfg);
  } // ... create_matrix_function(...)

  void update_parameter_dependency()
  {
    this->inherit_parameter_type(diffusion_factor_->parameter_type(), "diffusion_factor");
    this->inherit_parameter_type(diffusion_tensor_->parameter_type(), "diffusion_tensor");
    this->inherit_parameter_type(force_->parameter_type(),     "force");
    this->inherit_parameter_type(dirichlet_->parameter_type(), "dirichlet");
    this->inherit_parameter_type(neumann_->parameter_type(),   "neumann");
  } // ... update_parameter_dependency()

  std::shared_ptr< const DiffusionFactorType > diffusion_factor_;
  std::shared_ptr< const DiffusionTensorType > diffusion_tensor_;
  std::shared_ptr< const FunctionType > force_;
  std::shared_ptr< const FunctionType > dirichlet_;
  std::shared_ptr< const FunctionType > neumann_;
}; // class Default

} // namespace Problems
} // namespace LinearElliptic
} // namespace HDD
} // namespace Dune

#endif // DUNE_HDD_LINEARELLIPTIC_PROBLEMS_DEFAULT_HH
<|endoftext|>


<commit_before>// Copyright (c) 2009-2012, Andre Caron (andre.l.caron@gmail.com)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <w32/string.hpp>
#include <w32/astring.hpp>
#include <w32/Error.hpp>
#include <algorithm>
#include <iostream>
#include <limits>
#include <cstring>

namespace {

        // Allocate a string and automatically terminate it.
    template<typename T>
    T * allocate ( ::DWORD size )
    {
        T *const result = new T[size+1];
        result[size] = T(0);
        return (result);
    }

        // Returns the number of characters to allocate.
    template<typename T>
    ::DWORD count ( const T * value )
    {
        if ( value == 0 ) {
            return (0);
        }
        static const T terminator(0);
        ::DWORD result = 0;
        for ( ; (*value != terminator); ++value ) {
            ++result;
        }
        return (result);
    }

        // Allocate a fresh copy of a string.
    template<typename T>
    T * duplicate ( ::DWORD size, const T * value )
    {
        T *const result = allocate<T>(size);
        ::memcpy(result, value, sizeof(T)*size);
        return (result);
    }

        // Request the number of characters to allocate.
    ::DWORD count ( ::UINT codepage, const char * value )
    {
        const int result = ::MultiByteToWideChar
            (codepage, 0, value, -1, 0, 0);
        if ( result == 0 ) {
            const ::DWORD error = ::GetLastError();
            UNCHECKED_WIN32C_ERROR(MultiByteToWideChar,error);
        }
        return (result);
    }

        // Codepage is source encoding!
    ::WCHAR * decode ( ::UINT codepage, ::DWORD size, const char * value )
    {
        ::WCHAR *const data = allocate<::WCHAR>(size);
        const int result = ::MultiByteToWideChar(codepage,0,value,-1,data,size+1);
        if ( result == 0 ) {
            const ::DWORD error = ::GetLastError();
            UNCHECKED_WIN32C_ERROR(MultiByteToWideChar,error);
        }
        return (data);
    }

}

namespace w32 {

    const string::size_type string::npos =
        std::numeric_limits< string::size_type >::max();

    string::string ()
        : mySize(0),
          myData(::duplicate(mySize, L""))
    {
    }

    string::string ( const char * other, Codepage encoding )
        : mySize(::count(other)),
          myData(::decode(encoding, mySize, other))
    {
    }

    string::string ( const char * other, size_type size, Codepage encoding )
        : mySize(size),
          myData(::decode(encoding, mySize, other))
    {
    }

    string::string ( const astring& other )
        : mySize(other.size()),
          myData(decode(other.encoding(), mySize, other.data()))
    {
    }

    string::string ( const std::string& other, Codepage encoding )
        : mySize(other.size()),
          myData(::decode(encoding, mySize, other.data()))
    {
    }

    string::string ( const_pointer other )
        : mySize(count(other)),
          myData(duplicate(mySize,other))
    {
    }

    string::string ( const_pointer other, size_type size )
        : mySize(size),
          myData(duplicate(mySize,other))
    {
    }
    string::string ( const box& value )
        : mySize(value.size()),
          myData(value.data())
    {
    }

    string::string ( size_type size, char_type filler )
        : mySize(size),
          myData(::allocate<wchar_t>(size))
    {
        std::fill(begin(), end(), filler);
    }

    string::string ( const string& other )
        : mySize(other.size()),
          myData(duplicate(mySize,other.data()))
    {
    }

    string::~string ()
    {
        delete [] myData;
        myData = 0;
        mySize = 0;
    }

    string::size_type string::size() const
    {
        return (mySize);
    }

    string::size_type string::length() const
    {
        return (mySize);
    }

    bool string::empty () const
    {
        return (size() == 0);
    }

    string::pointer string::data ()
    {
        return (myData);
    }

    string::const_pointer string::data () const
    {
        return (myData);
    }

    string::pointer string::c_str ()
    {
        return (myData);
    }

    string::const_pointer string::c_str () const
    {
        return (myData);
    }

    void string::erase ( iterator begin, iterator end )
    {
            // Copy trailing characters.
        end = std::copy(end, myData+mySize, begin);

            // Terminate string.
        myData[mySize = (end-myData)] = L'\0';
    }

    void string::resize ( size_type length, wchar_t filler )
    {
            // Don't reallocate when not required to.
        if ( length <= size() ) {
            erase(begin()+size(), end());
        }
        else {
            string other(length, filler);
            std::copy(begin(), end(), other.begin());
            swap(other);
        }
    }

    void string::clear ()
    {
        erase(begin(), end());
    }

    string string::substr ( size_type offset, size_type length ) const
    {
        offset = std::min(offset,        size());
        length = std::min(offset+length, size());
        return (string(data()+offset, length));
    }

    string::iterator string::begin ()
    {
        return (data());
    }

    string::iterator string::end ()
    {
        return (data() + size());
    }

    string::const_iterator string::begin () const
    {
        return (data());
    }

    string::const_iterator string::end () const
    {
        return (data() + size());
    }

    void string::swap ( string& other )
    {
        std::swap(mySize,other.mySize);
        std::swap(myData,other.myData);
    }

    string& string::operator= ( const string& other )
    {
        string copy(other);
        copy.swap(*this);
        return (*this);
    }

    string& string::operator= ( const_pointer other )
    {
        string copy(other);
        copy.swap(*this);
        return (*this);
    }

    string& string::operator= ( const std::wstring& other )
    {
        string copy(other.c_str());
        copy.swap(*this);
        return (*this);
    }

    bool string::operator== ( const string& rhs ) const
    {
        return (std::wcscmp(data(), rhs.data()) == 0);
    }

    bool string::operator!= ( const string& rhs ) const
    {
        return (std::wcscmp(data(), rhs.data()) != 0);
    }

    bool string::operator< ( const string& rhs ) const
    {
        return (std::wcscmp(data(), rhs.data()) < 0);
    }

    bool string::operator<= ( const string& rhs ) const
    {
        return (std::wcscmp(data(), rhs.data()) <= 0);
    }

    bool string::operator> ( const string& rhs ) const
    {
        return (std::wcscmp(data(), rhs.data()) > 0);
    }

    bool string::operator>= ( const string& rhs ) const
    {
        return (std::wcscmp(data(), rhs.data()) >= 0);
    }

    string& string::operator+= ( const string& rhs )
    {
        if ( length() == 0 ) {
            return ((*this) = rhs);
        }
        string result(length() + rhs.length());
        std::copy(rhs.begin(), rhs.end(),
            std::copy(begin(), end(), result.begin()));
        result.swap(*this);
        return (*this);
    }

    string string::operator+ ( const string& rhs ) const
    {
        string result(*this);
        result += rhs;
        return (result);
    }

    string& string::operator+= ( wchar_t rhs )
    {
        resize(1+size());
        (*this)[size()-1] = rhs;
        return (*this);
    }

    string string::operator+ ( wchar_t rhs ) const
    {
        string result(*this);
        result += rhs;
        return (result);
    }

    string operator+ ( const wchar_t * lhs, const string& rhs )
    {
        return (string(lhs) + rhs);
    }

    std::wostream& operator<< ( std::wostream& out, const string& value )
    {
        return (out << value.data());
    }

    string::box::box ( pointer data )
        : mySize(std::wcslen(data)), myData(data)
    {
    }

    string::box::box ( pointer data, size_type size )
        : mySize(size), myData(data)
    {
    }

    string::size_type string::box::size() const
    {
        return (mySize);
    }

    string::pointer string::box::data () const
    {
        return (myData);
    }

}
<commit_msg>Fixes decoded string length.<commit_after>// Copyright (c) 2009-2012, Andre Caron (andre.l.caron@gmail.com)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <w32/string.hpp>
#include <w32/astring.hpp>
#include <w32/Error.hpp>
#include <algorithm>
#include <iostream>
#include <limits>
#include <cstring>

namespace {

        // Allocate a string and automatically terminate it.
    template<typename T>
    T * allocate ( ::DWORD size )
    {
        T *const result = new T[size+1];
        result[size] = T(0);
        return (result);
    }

        // Returns the number of characters to allocate.
    template<typename T>
    ::DWORD count ( const T * value )
    {
        if ( value == 0 ) {
            return (0);
        }
        static const T terminator(0);
        ::DWORD result = 0;
        for ( ; (*value != terminator); ++value ) {
            ++result;
        }
        return (result);
    }

        // Allocate a fresh copy of a string.
    template<typename T>
    T * duplicate ( ::DWORD size, const T * value )
    {
        T *const result = allocate<T>(size);
        ::memcpy(result, value, sizeof(T)*size);
        return (result);
    }

        // Request the number of characters to allocate.
    ::DWORD count ( ::UINT codepage, const char * value )
    {
        const int result = ::MultiByteToWideChar
            (codepage, 0, value, -1, 0, 0);
        if ( result == 0 ) {
            const ::DWORD error = ::GetLastError();
            UNCHECKED_WIN32C_ERROR(MultiByteToWideChar,error);
        }
        return (result);
    }

        // Codepage is source encoding!
    ::WCHAR * decode ( ::UINT codepage, ::DWORD& size, const char * value )
    {
        ::WCHAR *const data = allocate<::WCHAR>(size);
        const int result = ::MultiByteToWideChar
            (codepage, 0, value, -1, data, size+1);
        if ( result == 0 ) {
            const ::DWORD error = ::GetLastError();
            UNCHECKED_WIN32C_ERROR(MultiByteToWideChar,error);
        }
        // The decoded string doesn't forcibly have the same number of code
        // points as the encoded string.  For example, in UTf-8, "LATIN SMALL
        // LETTER E WITH ACUTE" is encoded as (0xC3, 0xA9) by is encoded as a
        // single (0x00e9) in UTF-16, effecively reducing the string length by
        // 1 codepoint.  Keep the freshly computed string length :-)
        size = result-1; // (don't count trailing terminator).
        return (data);
    }

}

namespace w32 {

    const string::size_type string::npos =
        std::numeric_limits< string::size_type >::max();

    string::string ()
        : mySize(0),
          myData(::duplicate(mySize, L""))
    {
    }

    string::string ( const char * other, Codepage encoding )
        : mySize(::count(other)),
          myData(::decode(encoding, mySize, other))
    {
    }

    string::string ( const char * other, size_type size, Codepage encoding )
        : mySize(size),
          myData(::decode(encoding, mySize, other))
    {
    }

    string::string ( const astring& other )
        : mySize(other.size()),
          myData(decode(other.encoding(), mySize, other.data()))
    {
    }

    string::string ( const std::string& other, Codepage encoding )
        : mySize(other.size()),
          myData(::decode(encoding, mySize, other.data()))
    {
    }

    string::string ( const_pointer other )
        : mySize(count(other)),
          myData(duplicate(mySize,other))
    {
    }

    string::string ( const_pointer other, size_type size )
        : mySize(size),
          myData(duplicate(mySize,other))
    {
    }
    string::string ( const box& value )
        : mySize(value.size()),
          myData(value.data())
    {
    }

    string::string ( size_type size, char_type filler )
        : mySize(size),
          myData(::allocate<wchar_t>(size))
    {
        std::fill(begin(), end(), filler);
    }

    string::string ( const string& other )
        : mySize(other.size()),
          myData(duplicate(mySize,other.data()))
    {
    }

    string::~string ()
    {
        delete [] myData;
        myData = 0;
        mySize = 0;
    }

    string::size_type string::size() const
    {
        return (mySize);
    }

    string::size_type string::length() const
    {
        return (mySize);
    }

    bool string::empty () const
    {
        return (size() == 0);
    }

    string::pointer string::data ()
    {
        return (myData);
    }

    string::const_pointer string::data () const
    {
        return (myData);
    }

    string::pointer string::c_str ()
    {
        return (myData);
    }

    string::const_pointer string::c_str () const
    {
        return (myData);
    }

    void string::erase ( iterator begin, iterator end )
    {
            // Copy trailing characters.
        end = std::copy(end, myData+mySize, begin);

            // Terminate string.
        myData[mySize = (end-myData)] = L'\0';
    }

    void string::resize ( size_type length, wchar_t filler )
    {
            // Don't reallocate when not required to.
        if ( length <= size() ) {
            erase(begin()+size(), end());
        }
        else {
            string other(length, filler);
            std::copy(begin(), end(), other.begin());
            swap(other);
        }
    }

    void string::clear ()
    {
        erase(begin(), end());
    }

    string string::substr ( size_type offset, size_type length ) const
    {
        offset = std::min(offset,        size());
        length = std::min(offset+length, size());
        return (string(data()+offset, length));
    }

    string::iterator string::begin ()
    {
        return (data());
    }

    string::iterator string::end ()
    {
        return (data() + size());
    }

    string::const_iterator string::begin () const
    {
        return (data());
    }

    string::const_iterator string::end () const
    {
        return (data() + size());
    }

    void string::swap ( string& other )
    {
        std::swap(mySize,other.mySize);
        std::swap(myData,other.myData);
    }

    string& string::operator= ( const string& other )
    {
        string copy(other);
        copy.swap(*this);
        return (*this);
    }

    string& string::operator= ( const_pointer other )
    {
        string copy(other);
        copy.swap(*this);
        return (*this);
    }

    string& string::operator= ( const std::wstring& other )
    {
        string copy(other.c_str());
        copy.swap(*this);
        return (*this);
    }

    bool string::operator== ( const string& rhs ) const
    {
        return (std::wcscmp(data(), rhs.data()) == 0);
    }

    bool string::operator!= ( const string& rhs ) const
    {
        return (std::wcscmp(data(), rhs.data()) != 0);
    }

    bool string::operator< ( const string& rhs ) const
    {
        return (std::wcscmp(data(), rhs.data()) < 0);
    }

    bool string::operator<= ( const string& rhs ) const
    {
        return (std::wcscmp(data(), rhs.data()) <= 0);
    }

    bool string::operator> ( const string& rhs ) const
    {
        return (std::wcscmp(data(), rhs.data()) > 0);
    }

    bool string::operator>= ( const string& rhs ) const
    {
        return (std::wcscmp(data(), rhs.data()) >= 0);
    }

    string& string::operator+= ( const string& rhs )
    {
        if ( length() == 0 ) {
            return ((*this) = rhs);
        }
        string result(length() + rhs.length());
        std::copy(rhs.begin(), rhs.end(),
                  std::copy(begin(), end(), result.begin()));
        result.swap(*this);
        return (*this);
    }

    string string::operator+ ( const string& rhs ) const
    {
        string result(*this);
        result += rhs;
        return (result);
    }

    string& string::operator+= ( wchar_t rhs )
    {
        resize(1+size());
        (*this)[size()-1] = rhs;
        return (*this);
    }

    string string::operator+ ( wchar_t rhs ) const
    {
        string result(*this);
        result += rhs;
        return (result);
    }

    string operator+ ( const wchar_t * lhs, const string& rhs )
    {
        return (string(lhs) + rhs);
    }

    std::wostream& operator<< ( std::wostream& out, const string& value )
    {
        return (out << value.data());
    }

    string::box::box ( pointer data )
        : mySize(std::wcslen(data)), myData(data)
    {
    }

    string::box::box ( pointer data, size_type size )
        : mySize(size), myData(data)
    {
    }

    string::size_type string::box::size() const
    {
        return (mySize);
    }

    string::pointer string::box::data () const
    {
        return (myData);
    }

}
<|endoftext|>


<commit_before><commit_msg>make CreateNextObject a member<commit_after><|endoftext|>


<commit_before>#include "PSNode.h"
#include "ParticleSystem.h"

#include <ps_3d.h>
#include <ps_3d_sprite.h>
#include <ps_3d_buffer.h>
#include <shaderlab.h>

#include <ee/SpriteRenderer.h>

#include <time.h>
#include <assert.h>

namespace eparticle3d
{

PSNode* PSNode::m_instance = NULL;

PSNode* PSNode::Instance()
{
	if (!m_instance) {
		m_instance = new PSNode();
	}
	return m_instance;
}

PSNode::PSNode()
	: m_time(0)
{
	Init();

	ee::SceneNodeMgr::Instance()->Add(this);
}

bool PSNode::Update(const s2::RenderParams& params, float dt)
{
	UpdateTime();
	return p3d_buffer_update(GetTime());
}

void PSNode::Draw() const
{
	p3d_buffer_draw(0, 0, 1);
}

void PSNode::BufferClear()
{
	p3d_buffer_clear();
}

void PSNode::UpdateTime()
{
	static clock_t last = 0;
	if (last == 0) {
		last = clock();
	} else {
		clock_t curr = clock();
		if (curr != last) {
			float dt = (float)(curr - last) / CLOCKS_PER_SEC;
			m_time += dt;
			last = curr;
		}
	}
}

static void
blend_func(int blend)
{
	sl::RenderContext* ctx = sl::ShaderMgr::Instance()->GetContext();
	switch (blend)
	{
	case s2::FBM_NULL:
		ctx->SetBlend(2, 6);		// BLEND_GL_ONE, BLEND_GL_ONE_MINUS_SRC_ALPHA
		ctx->SetBlendEquation(0);	// BLEND_FUNC_ADD
		break;
	case s2::FBM_ADD:
		ctx->SetBlend(2, 2);		// BLEND_GL_ONE, BLEND_GL_ONE
		ctx->SetBlendEquation(0);	// BLEND_FUNC_ADD
		break;
	case s2::FBM_SUBTRACT:
		ctx->SetBlend(2, 6);		// BLEND_GL_ONE, BLEND_GL_ONE_MINUS_SRC_ALPHA
		ctx->SetBlendEquation(1);	// BLEND_FUNC_SUBTRACT
		break;
	}
}

static void
render_func(void* sym, float* mat, float x, float y, float angle, float scale,
            struct ps_color* mul_col, struct ps_color* add_col, const void* ud)
{
	assert(ud);
	const RenderParams* rp = (static_cast<const RenderParams*>(ud));

	ee::Symbol* ee_sym = static_cast<ee::Symbol*>(sym);

	s2::RenderParams params;

	params.color.mul.r = mul_col->r;
	params.color.mul.g = mul_col->g;
	params.color.mul.b = mul_col->b;
	params.color.mul.a = mul_col->a;

	params.color.add.r = add_col->r;
	params.color.add.g = add_col->g;
	params.color.add.b = add_col->b;
	params.color.add.a = add_col->a;

	params.color.mul = params.color.mul * rp->ct.mul;
	params.color.add = params.color.add + rp->ct.add;

	// todo color trans

	if (rp->p3d && rp->p3d->local_mode_draw) {
		params.mt = rp->mat;
	} else {
		sm::mat4 _mat;
		_mat.x[0] = mat[0];
		_mat.x[1] = mat[1];
		_mat.x[4] = mat[2];
		_mat.x[5] = mat[3];
		_mat.x[12]= mat[4];
		_mat.x[13]= mat[5];
		params.mt = _mat * rp->mat;
	}

	ee::SpriteRenderer::Draw(ee_sym, params, sm::vec2(x, y), angle, scale, scale, 0, 0);

	// todo bind
	// 	if (p->bind_ps) {
	// 		sm::mat4 _mt;
	// 		_mt.translate(p->pos.x, p->pos.y);
	// 		Draw(p->bind_ps, _mt, recorder);
	// 	}

	// todo record
	// 	AnimRecorder* curr_record = m_anim_recorder ? m_anim_recorder : recorder;
	// 	if (curr_record) {
	// 		sm::vec2 fixed = _mt * pos;
	// 		curr_record->AddItem(sym->GetFilepath(), fixed.x, fixed.y, p->angle, s, mul_col, add_col);
	// 	}
}

static void
add_func(p3d_particle* p, void* ud)
{
//  	ParticleSystem* ps = (ParticleSystem*)ud;
//  	const sm::vec2& pos = ps->GetPosition();
//  	p->init_pos.x = pos.x;
//  	p->init_pos.y = pos.y;
}

static void
remove_func(p3d_particle* p, void* ud)
{
	ParticleSystem* ps = (ParticleSystem*)ud;
	if (ps) {
		ps->RemoveFromInvertRecord(p);
	}
}

static void
update_srt_func(void* params, float x, float y, float scale) {
	RenderParams* rp = static_cast<RenderParams*>(params);
	rp->mat.Translate(x, y, 0);
	rp->mat.Scale(scale, scale, 1);
}

static void
buf_remove_func(struct p3d_sprite* spr) {
}

static void
create_draw_params_func(struct p3d_sprite* spr) {
	RenderParams* rp = new RenderParams;
	rp->p3d = spr;
	spr->draw_params = rp;
}

void
release_draw_params_func(struct p3d_sprite* spr) {
	RenderParams* rp = static_cast<RenderParams*>(spr->draw_params);
	delete rp;
	spr->draw_params = NULL;
}

void PSNode::Init()
{
	p3d_init();
	p3d_regist_cb(blend_func, render_func, add_func, remove_func);
	p3d_buffer_init(update_srt_func, buf_remove_func);
	p3d_sprite_init(create_draw_params_func, release_draw_params_func);
}

}<commit_msg>[FIXED] fast blend<commit_after>#include "PSNode.h"
#include "ParticleSystem.h"

#include <ps_3d.h>
#include <ps_3d_sprite.h>
#include <ps_3d_buffer.h>
#include <shaderlab.h>

#include <ee/SpriteRenderer.h>

#include <time.h>
#include <assert.h>

namespace eparticle3d
{

PSNode* PSNode::m_instance = NULL;

PSNode* PSNode::Instance()
{
	if (!m_instance) {
		m_instance = new PSNode();
	}
	return m_instance;
}

PSNode::PSNode()
	: m_time(0)
{
	Init();

	ee::SceneNodeMgr::Instance()->Add(this);
}

bool PSNode::Update(const s2::RenderParams& params, float dt)
{
	UpdateTime();
	return p3d_buffer_update(GetTime());
}

void PSNode::Draw() const
{
	p3d_buffer_draw(0, 0, 1);
}

void PSNode::BufferClear()
{
	p3d_buffer_clear();
}

void PSNode::UpdateTime()
{
	static clock_t last = 0;
	if (last == 0) {
		last = clock();
	} else {
		clock_t curr = clock();
		if (curr != last) {
			float dt = (float)(curr - last) / CLOCKS_PER_SEC;
			m_time += dt;
			last = curr;
		}
	}
}

static void
blend_begin_func(int blend)
{
	sl::RenderContext* ctx = sl::ShaderMgr::Instance()->GetContext();
	switch (blend)
	{
	case s2::FBM_NULL:
		ctx->SetBlend(2, 6);		// BLEND_GL_ONE, BLEND_GL_ONE_MINUS_SRC_ALPHA
		ctx->SetBlendEquation(0);	// BLEND_FUNC_ADD
		break;
	case s2::FBM_ADD:
		ctx->SetBlend(2, 2);		// BLEND_GL_ONE, BLEND_GL_ONE
		ctx->SetBlendEquation(0);	// BLEND_FUNC_ADD
		break;
	case s2::FBM_SUBTRACT:
		ctx->SetBlend(2, 6);		// BLEND_GL_ONE, BLEND_GL_ONE_MINUS_SRC_ALPHA
		ctx->SetBlendEquation(1);	// BLEND_FUNC_SUBTRACT
		break;
	}
}

static void
blend_end_func()
{
	sl::RenderContext* ctx = sl::ShaderMgr::Instance()->GetContext();
	ctx->SetBlend(2, 6);		// BLEND_GL_ONE, BLEND_GL_ONE_MINUS_SRC_ALPHA
	ctx->SetBlendEquation(0);	// BLEND_FUNC_ADD
}

static void
render_func(void* sym, float* mat, float x, float y, float angle, float scale,
            struct ps_color* mul_col, struct ps_color* add_col, const void* ud)
{
	assert(ud);
	const RenderParams* rp = (static_cast<const RenderParams*>(ud));

	ee::Symbol* ee_sym = static_cast<ee::Symbol*>(sym);

	s2::RenderParams params;

	params.color.mul.r = mul_col->r;
	params.color.mul.g = mul_col->g;
	params.color.mul.b = mul_col->b;
	params.color.mul.a = mul_col->a;

	params.color.add.r = add_col->r;
	params.color.add.g = add_col->g;
	params.color.add.b = add_col->b;
	params.color.add.a = add_col->a;

	params.color.mul = params.color.mul * rp->ct.mul;
	params.color.add = params.color.add + rp->ct.add;

	// todo color trans

	if (rp->p3d && rp->p3d->local_mode_draw) {
		params.mt = rp->mat;
	} else {
		sm::mat4 _mat;
		_mat.x[0] = mat[0];
		_mat.x[1] = mat[1];
		_mat.x[4] = mat[2];
		_mat.x[5] = mat[3];
		_mat.x[12]= mat[4];
		_mat.x[13]= mat[5];
		params.mt = _mat * rp->mat;
	}

	ee::SpriteRenderer::Draw(ee_sym, params, sm::vec2(x, y), angle, scale, scale, 0, 0);

	// todo bind
	// 	if (p->bind_ps) {
	// 		sm::mat4 _mt;
	// 		_mt.translate(p->pos.x, p->pos.y);
	// 		Draw(p->bind_ps, _mt, recorder);
	// 	}

	// todo record
	// 	AnimRecorder* curr_record = m_anim_recorder ? m_anim_recorder : recorder;
	// 	if (curr_record) {
	// 		sm::vec2 fixed = _mt * pos;
	// 		curr_record->AddItem(sym->GetFilepath(), fixed.x, fixed.y, p->angle, s, mul_col, add_col);
	// 	}
}

static void
add_func(p3d_particle* p, void* ud)
{
//  	ParticleSystem* ps = (ParticleSystem*)ud;
//  	const sm::vec2& pos = ps->GetPosition();
//  	p->init_pos.x = pos.x;
//  	p->init_pos.y = pos.y;
}

static void
remove_func(p3d_particle* p, void* ud)
{
	ParticleSystem* ps = (ParticleSystem*)ud;
	if (ps) {
		ps->RemoveFromInvertRecord(p);
	}
}

static void
update_srt_func(void* params, float x, float y, float scale) {
	RenderParams* rp = static_cast<RenderParams*>(params);
	rp->mat.Translate(x, y, 0);
	rp->mat.Scale(scale, scale, 1);
}

static void
buf_remove_func(struct p3d_sprite* spr) {
}

static void
create_draw_params_func(struct p3d_sprite* spr) {
	RenderParams* rp = new RenderParams;
	rp->p3d = spr;
	spr->draw_params = rp;
}

void
release_draw_params_func(struct p3d_sprite* spr) {
	RenderParams* rp = static_cast<RenderParams*>(spr->draw_params);
	delete rp;
	spr->draw_params = NULL;
}

void PSNode::Init()
{
	p3d_init();
	p3d_regist_cb(blend_begin_func, blend_end_func, render_func, add_func, remove_func);
	p3d_buffer_init(update_srt_func, buf_remove_func);
	p3d_sprite_init(create_draw_params_func, release_draw_params_func);
}

}<|endoftext|>


<commit_before>#include "atlas/utils/Application.hpp"
#include "atlas/utils/Scene.hpp"
#include "atlas/utils/WindowSettings.hpp"
#include "atlas/core/Log.hpp"
#include "atlas/core/Platform.hpp"
#include "atlas/core/Float.hpp"
#include "atlas/gl/ErrorCheck.hpp"

#include <vector>

namespace atlas
{
    namespace utils
    {
        struct Application::ApplicationImpl
        {
            ApplicationImpl() :
                currentWindow(nullptr)
            { }

            ~ApplicationImpl()
            { }

            void insertScene(ScenePointer scene)
            {
                sceneList.push_back(std::move(scene));
                currentScene = sceneList.size() - 1;
                sceneTicks.push_back(-1.0);
            }

            double prepareSwappedScene(size_t sceneIndex)
            {
                sceneTicks[currentScene] = glfwGetTime();
                currentScene = sceneIndex;

                int width, height;
                glfwGetFramebufferSize(currentWindow, &width, &height);
                sceneList[sceneIndex]->screenResizeEvent(width, height);

                return
                    (core::areEqual<double>(-1.0, sceneTicks[currentScene])) ?
                    0 : sceneTicks[currentScene];
            }

            void getNextScene()
            {
                if (sceneList.size() == 1)
                {
                    return;
                }

                double newTime =
                    prepareSwappedScene((currentScene + 1) % sceneList.size());
                glfwSetTime(newTime);
            }

            void getPreviousScene()
            {
                if (sceneList.size() == 1)
                {
                    return;
                }

                double newTime =
                    prepareSwappedScene((currentScene - 1) % sceneList.size());
                glfwSetTime(newTime);

                glfwSetTime(newTime);
            }

            GLFWwindow* currentWindow;
            std::vector<ScenePointer> sceneList;
            std::vector<double> sceneTicks;
            size_t currentScene;
        };

        static void mousePressCallback(GLFWwindow* window, int button,
            int action, int mods)
        {
            double x, y;
            glfwGetCursorPos(window, &x, &y);
            Application::getInstance().getCurrentScene()->mousePressEvent(
                button, action, mods, x, y);
        }

        static void mouseMoveCallback(GLFWwindow* window, double xPos,
            double yPos)
        {
            UNUSED(window);
            Application::getInstance().getCurrentScene()->mouseMoveEvent(
                xPos, yPos);
        }

        static void mouseScrollCallback(GLFWwindow* window, double xOffset,
            double yOffset)
        {
            UNUSED(window);
            Application::getInstance().getCurrentScene()->mouseScrollEvent(
                xOffset, yOffset);
        }

        static void keyPressCallback(GLFWwindow* window, int key,
            int scancode, int action, int mods)
        {
            if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
            {
                glfwSetWindowShouldClose(window, GL_TRUE);
            }
            else if (key == GLFW_KEY_TAB && action == GLFW_PRESS)
            {
                Application::getInstance().nextScene();
            }
            else if (key == GLFW_KEY_TAB && action == GLFW_PRESS &&
                mods == GLFW_KEY_LEFT_SHIFT)
            {
                Application::getInstance().previousScene();
            }
            else
            {
                Application::getInstance().getCurrentScene()->keyPressEvent(
                    key, scancode, action, mods);
            }
        }

        static void windowSizeCallback(GLFWwindow* window, int width,
            int height)
        {
            UNUSED(window);
            UNUSED(width);
            UNUSED(height);
        }

        static void frameBufferSizeCallback(GLFWwindow* window, int width,
            int height)
        {
            UNUSED(window);

            width = (width < 1) ? 1 : width;
            height = (height < 1) ? 1 : height;

            Application::getInstance().getCurrentScene()->screenResizeEvent(width, height);
        }

        static void errorCallback(int error, const char* message)
        {
            ERROR_LOG(std::to_string(error) + ":" + message);
        }

        static void windowCloseCallback(GLFWwindow* window)
        {
            if (Application::getInstance().getCurrentScene()->sceneEnded())
            {
                glfwSetWindowShouldClose(window, GL_TRUE);
            }
            else
            {
                glfwSetWindowShouldClose(window, GL_FALSE);
                glfwHideWindow(window);
            }
        }

        Application::Application() :
            mImpl(new ApplicationImpl)
        {
            glfwSetErrorCallback(errorCallback);

            if (!glfwInit())
            {
                CRITICAL_LOG("Could not initialize GLFW");
                exit(EXIT_FAILURE);
            }
        }

        Application::~Application()
        {
            if (mImpl->currentWindow)
            {
                glfwDestroyWindow(mImpl->currentWindow);
            }

            glfwTerminate();
        }

        Application& Application::getInstance()
        {
            static Application instance;
            return instance;
        }

        void Application::createWindow(WindowSettings const& settings)
        {
            if (mImpl->currentWindow != nullptr)
            {
                ERROR_LOG("Multiple windows are not suppored.");
                return;
            }

            auto context = settings.contextVersion;

            glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, std::get<0>(context));
            glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, std::get<1>(context));
            glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
            glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT,
                settings.isDebugContext);
            glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT,
                settings.isForwardCompat);

            glfwWindowHint(GLFW_MAXIMIZED, settings.isMaximized);

            GLFWmonitor* monitor = (settings.isFullscreen) ?
                glfwGetPrimaryMonitor() : NULL;

            auto size = settings.windowSize;
            mImpl->currentWindow = glfwCreateWindow(std::get<0>(size),
                std::get<1>(size), settings.title.c_str(), monitor, NULL);

            if (!mImpl->currentWindow)
            {
                glfwTerminate();
                CRITICAL_LOG("Could not create window.");
                exit(EXIT_FAILURE);
            }

            glfwMakeContextCurrent(mImpl->currentWindow);

            if (gl3wInit())
            {
                CRITICAL_LOG("Could not initialize OpenGL.");
                glfwDestroyWindow(mImpl->currentWindow);
                glfwTerminate();
                exit(EXIT_FAILURE);
            }

            if (!gl3wIsSupported(std::get<0>(context), std::get<1>(context)))
            {
                CRITICAL_LOG_V("OpenGL %d.%d is not supported.",
                    std::get<0>(context), std::get<1>(context));
                glfwDestroyWindow(mImpl->currentWindow);
                glfwTerminate();
                exit(EXIT_FAILURE);
            }

            GLint major, minor;
            glGetIntegerv(GL_MAJOR_VERSION, &major);
            glGetIntegerv(GL_MINOR_VERSION, &minor);

            INFO_LOG("Created OpenGL context " + std::to_string(major) +
                "." + std::to_string(minor));

            glfwSetKeyCallback(mImpl->currentWindow,
                keyPressCallback);
            glfwSetMouseButtonCallback(mImpl->currentWindow,
                mousePressCallback);
            glfwSetScrollCallback(mImpl->currentWindow,
                mouseScrollCallback);
            glfwSetCursorPosCallback(mImpl->currentWindow,
                mouseMoveCallback);

            glfwSetWindowSizeCallback(mImpl->currentWindow,
                windowSizeCallback);
            glfwSetFramebufferSizeCallback(mImpl->currentWindow,
                frameBufferSizeCallback);
            glfwSetWindowCloseCallback(mImpl->currentWindow,
                windowCloseCallback);

            gl::initializeGLError();

        }

        void Application::createWindow(int width, int height,
            std::string const& title, int contextVersionMajor,
            int contextVersionMinor)
        {
            createWindow(WindowSettings(title, width, height,
                contextVersionMajor, contextVersionMinor));
        }

        void Application::runApplication()
        {
            if (mImpl->currentWindow == nullptr)
            {
                WARN_LOG("Cannot run application without a window.");
                return;
            }

            if (mImpl->sceneList.empty())
            {
                WARN_LOG("Cannot run application without a scene.");
                return;
            }

            glfwShowWindow(mImpl->currentWindow);

            int width, height;
            glfwGetFramebufferSize(mImpl->currentWindow, &width, &height);
            mImpl->sceneList[mImpl->currentScene]->screenResizeEvent(
                width, height);

            glfwSetTime(0.0);
            double currentTime;

            mImpl->sceneList[mImpl->currentScene]->onSceneEnter();

            while (!glfwWindowShouldClose(mImpl->currentWindow))
            {
                currentTime = glfwGetTime();
                mImpl->sceneList[mImpl->currentScene]->updateScene(currentTime);
                mImpl->sceneList[mImpl->currentScene]->renderScene();

                glfwSwapBuffers(mImpl->currentWindow);
                glfwPollEvents();
            }

            mImpl->sceneList[mImpl->currentScene]->onSceneExit();
        }

        void Application::getCursorPosition(double* x, double *y)
        {
            glfwGetCursorPos(mImpl->currentWindow, x, y);
        }

        void Application::addScene(ScenePointer scene)
        {
            mImpl->insertScene(std::move(scene));
        }

        void Application::nextScene()
        {
            mImpl->sceneList[mImpl->currentScene]->onSceneExit();
            mImpl->getNextScene();
            mImpl->sceneList[mImpl->currentScene]->onSceneEnter();
        }

        void Application::previousScene()
        {
            mImpl->sceneList[mImpl->currentScene]->onSceneExit();
            mImpl->getPreviousScene();
            mImpl->sceneList[mImpl->currentScene]->onSceneEnter();
        }

        Scene* Application::getCurrentScene() const
        {
            return mImpl->sceneList[mImpl->currentScene].get();
        }

        GLFWwindow* Application::getCurrentWindow() const
        {
            return mImpl->currentWindow;
        }
    }
}<commit_msg>[brief] Updates to newest WindowSettings API.<commit_after>#include "atlas/utils/Application.hpp"
#include "atlas/utils/Scene.hpp"
#include "atlas/utils/WindowSettings.hpp"
#include "atlas/core/Log.hpp"
#include "atlas/core/Platform.hpp"
#include "atlas/core/Float.hpp"
#include "atlas/gl/ErrorCheck.hpp"

#include <vector>

namespace atlas
{
    namespace utils
    {
        struct Application::ApplicationImpl
        {
            ApplicationImpl() :
                currentWindow(nullptr)
            { }

            ~ApplicationImpl()
            { }

            void insertScene(ScenePointer scene)
            {
                sceneList.push_back(std::move(scene));
                currentScene = sceneList.size() - 1;
                sceneTicks.push_back(-1.0);
            }

            double prepareSwappedScene(size_t sceneIndex)
            {
                sceneTicks[currentScene] = glfwGetTime();
                currentScene = sceneIndex;

                int width, height;
                glfwGetFramebufferSize(currentWindow, &width, &height);
                sceneList[sceneIndex]->screenResizeEvent(width, height);

                return
                    (core::areEqual<double>(-1.0, sceneTicks[currentScene])) ?
                    0 : sceneTicks[currentScene];
            }

            void getNextScene()
            {
                if (sceneList.size() == 1)
                {
                    return;
                }

                double newTime =
                    prepareSwappedScene((currentScene + 1) % sceneList.size());
                glfwSetTime(newTime);
            }

            void getPreviousScene()
            {
                if (sceneList.size() == 1)
                {
                    return;
                }

                double newTime =
                    prepareSwappedScene((currentScene - 1) % sceneList.size());
                glfwSetTime(newTime);

                glfwSetTime(newTime);
            }

            GLFWwindow* currentWindow;
            std::vector<ScenePointer> sceneList;
            std::vector<double> sceneTicks;
            size_t currentScene;
        };

        static void mousePressCallback(GLFWwindow* window, int button,
            int action, int mods)
        {
            double x, y;
            glfwGetCursorPos(window, &x, &y);
            Application::getInstance().getCurrentScene()->mousePressEvent(
                button, action, mods, x, y);
        }

        static void mouseMoveCallback(GLFWwindow* window, double xPos,
            double yPos)
        {
            UNUSED(window);
            Application::getInstance().getCurrentScene()->mouseMoveEvent(
                xPos, yPos);
        }

        static void mouseScrollCallback(GLFWwindow* window, double xOffset,
            double yOffset)
        {
            UNUSED(window);
            Application::getInstance().getCurrentScene()->mouseScrollEvent(
                xOffset, yOffset);
        }

        static void keyPressCallback(GLFWwindow* window, int key,
            int scancode, int action, int mods)
        {
            if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
            {
                glfwSetWindowShouldClose(window, GL_TRUE);
            }
            else if (key == GLFW_KEY_TAB && action == GLFW_PRESS)
            {
                Application::getInstance().nextScene();
            }
            else if (key == GLFW_KEY_TAB && action == GLFW_PRESS &&
                mods == GLFW_KEY_LEFT_SHIFT)
            {
                Application::getInstance().previousScene();
            }
            else
            {
                Application::getInstance().getCurrentScene()->keyPressEvent(
                    key, scancode, action, mods);
            }
        }

        static void windowSizeCallback(GLFWwindow* window, int width,
            int height)
        {
            UNUSED(window);
            UNUSED(width);
            UNUSED(height);
        }

        static void frameBufferSizeCallback(GLFWwindow* window, int width,
            int height)
        {
            UNUSED(window);

            width = (width < 1) ? 1 : width;
            height = (height < 1) ? 1 : height;

            Application::getInstance().getCurrentScene()->screenResizeEvent(width, height);
        }

        static void errorCallback(int error, const char* message)
        {
            ERROR_LOG(std::to_string(error) + ":" + message);
        }

        static void windowCloseCallback(GLFWwindow* window)
        {
            if (Application::getInstance().getCurrentScene()->sceneEnded())
            {
                glfwSetWindowShouldClose(window, GL_TRUE);
            }
            else
            {
                glfwSetWindowShouldClose(window, GL_FALSE);
                glfwHideWindow(window);
            }
        }

        Application::Application() :
            mImpl(new ApplicationImpl)
        {
            glfwSetErrorCallback(errorCallback);

            if (!glfwInit())
            {
                CRITICAL_LOG("Could not initialize GLFW");
                exit(EXIT_FAILURE);
            }
        }

        Application::~Application()
        {
            if (mImpl->currentWindow)
            {
                glfwDestroyWindow(mImpl->currentWindow);
            }

            glfwTerminate();
        }

        Application& Application::getInstance()
        {
            static Application instance;
            return instance;
        }

        void Application::createWindow(WindowSettings const& settings)
        {
            if (mImpl->currentWindow != nullptr)
            {
                ERROR_LOG("Multiple windows are not suppored.");
                return;
            }

            auto context = settings.contextVersion;

            glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, std::get<0>(context));
            glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, std::get<1>(context));
            glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
            glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT,
                settings.isDebugContext);
            glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT,
                settings.isForwardCompat);

            glfwWindowHint(GLFW_MAXIMIZED, settings.isMaximized);
            glfwWindowHint(GLFW_RESIZABLE, settings.isResizeable);

            GLFWmonitor* monitor = (settings.isFullscreen) ?
                glfwGetPrimaryMonitor() : NULL;

            auto size = settings.windowSize;
            mImpl->currentWindow = glfwCreateWindow(std::get<0>(size),
                std::get<1>(size), settings.title.c_str(), monitor, NULL);

            if (!mImpl->currentWindow)
            {
                glfwTerminate();
                CRITICAL_LOG("Could not create window.");
                exit(EXIT_FAILURE);
            }

            glfwMakeContextCurrent(mImpl->currentWindow);

            if (gl3wInit())
            {
                CRITICAL_LOG("Could not initialize OpenGL.");
                glfwDestroyWindow(mImpl->currentWindow);
                glfwTerminate();
                exit(EXIT_FAILURE);
            }

            if (!gl3wIsSupported(std::get<0>(context), std::get<1>(context)))
            {
                CRITICAL_LOG_V("OpenGL %d.%d is not supported.",
                    std::get<0>(context), std::get<1>(context));
                glfwDestroyWindow(mImpl->currentWindow);
                glfwTerminate();
                exit(EXIT_FAILURE);
            }

            GLint major, minor;
            glGetIntegerv(GL_MAJOR_VERSION, &major);
            glGetIntegerv(GL_MINOR_VERSION, &minor);

            INFO_LOG("Created OpenGL context " + std::to_string(major) +
                "." + std::to_string(minor));

            glfwSetKeyCallback(mImpl->currentWindow,
                keyPressCallback);
            glfwSetMouseButtonCallback(mImpl->currentWindow,
                mousePressCallback);
            glfwSetScrollCallback(mImpl->currentWindow,
                mouseScrollCallback);
            glfwSetCursorPosCallback(mImpl->currentWindow,
                mouseMoveCallback);

            glfwSetWindowSizeCallback(mImpl->currentWindow,
                windowSizeCallback);
            glfwSetFramebufferSizeCallback(mImpl->currentWindow,
                frameBufferSizeCallback);
            glfwSetWindowCloseCallback(mImpl->currentWindow,
                windowCloseCallback);

            gl::initializeGLError();

        }

        void Application::createWindow(int width, int height,
            std::string const& title, int contextVersionMajor,
            int contextVersionMinor)
        {
            createWindow(WindowSettings(title, width, height,
                contextVersionMajor, contextVersionMinor));
        }

        void Application::runApplication()
        {
            if (mImpl->currentWindow == nullptr)
            {
                WARN_LOG("Cannot run application without a window.");
                return;
            }

            if (mImpl->sceneList.empty())
            {
                WARN_LOG("Cannot run application without a scene.");
                return;
            }

            glfwShowWindow(mImpl->currentWindow);

            int width, height;
            glfwGetFramebufferSize(mImpl->currentWindow, &width, &height);
            mImpl->sceneList[mImpl->currentScene]->screenResizeEvent(
                width, height);

            glfwSetTime(0.0);
            double currentTime;

            mImpl->sceneList[mImpl->currentScene]->onSceneEnter();

            while (!glfwWindowShouldClose(mImpl->currentWindow))
            {
                currentTime = glfwGetTime();
                mImpl->sceneList[mImpl->currentScene]->updateScene(currentTime);
                mImpl->sceneList[mImpl->currentScene]->renderScene();

                glfwSwapBuffers(mImpl->currentWindow);
                glfwPollEvents();
            }

            mImpl->sceneList[mImpl->currentScene]->onSceneExit();
        }

        void Application::getCursorPosition(double* x, double *y)
        {
            glfwGetCursorPos(mImpl->currentWindow, x, y);
        }

        void Application::addScene(ScenePointer scene)
        {
            mImpl->insertScene(std::move(scene));
        }

        void Application::nextScene()
        {
            mImpl->sceneList[mImpl->currentScene]->onSceneExit();
            mImpl->getNextScene();
            mImpl->sceneList[mImpl->currentScene]->onSceneEnter();
        }

        void Application::previousScene()
        {
            mImpl->sceneList[mImpl->currentScene]->onSceneExit();
            mImpl->getPreviousScene();
            mImpl->sceneList[mImpl->currentScene]->onSceneEnter();
        }

        Scene* Application::getCurrentScene() const
        {
            return mImpl->sceneList[mImpl->currentScene].get();
        }

        GLFWwindow* Application::getCurrentWindow() const
        {
            return mImpl->currentWindow;
        }
    }
}<|endoftext|>


<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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
 *
 * 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.
 */

#include <sys/prctl.h>

#include <set>

#include <gmock/gmock.h>

#include <process/clock.hpp>
#include <process/gtest.hpp>
#include <process/reap.hpp>

#include <stout/gtest.hpp>
#include <stout/stringify.hpp>

#include "linux/perf.hpp"

using std::set;
using std::string;

using namespace process;

namespace mesos {
namespace internal {
namespace tests {

class PerfTest : public ::testing::Test {};

TEST_F(PerfTest, ROOT_Events)
{
  set<string> events;
  // Valid events.
  events.insert("cycles");
  events.insert("task-clock");
  EXPECT_TRUE(perf::valid(events));

  // Add an invalid event.
  events.insert("this-is-an-invalid-event");
  EXPECT_FALSE(perf::valid(events));
}

TEST_F(PerfTest, Parse)
{
  // uint64 and floats should be parsed.
  Try<hashmap<string, mesos::PerfStatistics> > parse =
    perf::parse("123,cycles\n0.123,task-clock");
  CHECK_SOME(parse);

  ASSERT_TRUE(parse.get().contains(""));
  mesos::PerfStatistics statistics = parse.get().get("").get();

  ASSERT_TRUE(statistics.has_cycles());
  EXPECT_EQ(123u, statistics.cycles());
  ASSERT_TRUE(statistics.has_task_clock());
  EXPECT_EQ(0.123, statistics.task_clock());

  // Parse multiple cgroups.
  parse = perf::parse("123,cycles,cgroup1\n"
                      "456,cycles,cgroup2\n"
                      "0.456,task-clock,cgroup2\n"
                      "0.123,task-clock,cgroup1");
  CHECK_SOME(parse);
  EXPECT_FALSE(parse.get().contains(""));

  ASSERT_TRUE(parse.get().contains("cgroup1"));
  statistics = parse.get().get("cgroup1").get();

  ASSERT_TRUE(statistics.has_cycles());
  EXPECT_EQ(123u, statistics.cycles());
  ASSERT_TRUE(statistics.has_task_clock());
  EXPECT_EQ(0.123, statistics.task_clock());

  ASSERT_TRUE(parse.get().contains("cgroup2"));
  statistics = parse.get().get("cgroup2").get();

  ASSERT_TRUE(statistics.has_cycles());
  EXPECT_EQ(456u, statistics.cycles());
  EXPECT_TRUE(statistics.has_task_clock());
  EXPECT_EQ(0.456, statistics.task_clock());

  // Statistics reporting <not supported> should not appear.
  parse = perf::parse("<not supported>,cycles");
  CHECK_SOME(parse);

  ASSERT_TRUE(parse.get().contains(""));
  statistics = parse.get().get("").get();
  EXPECT_FALSE(statistics.has_cycles());

  // Statistics reporting <not counted> should be zero.
  parse = perf::parse("<not counted>,cycles\n<not counted>,task-clock");
  CHECK_SOME(parse);

  ASSERT_TRUE(parse.get().contains(""));
  statistics = parse.get().get("").get();

  EXPECT_TRUE(statistics.has_cycles());
  EXPECT_EQ(0u, statistics.cycles());
  EXPECT_TRUE(statistics.has_task_clock());
  EXPECT_EQ(0.0, statistics.task_clock());

  // Check parsing fails.
  parse = perf::parse("1,cycles\ngarbage");
  EXPECT_ERROR(parse);

  parse = perf::parse("1,unknown-field");
  EXPECT_ERROR(parse);
}

TEST_F(PerfTest, ROOT_SamplePid)
{
  // TODO(idownes): Replace this with a Subprocess when it supports
  // DEATHSIG.
  // Fork a child which we'll run perf against.
  pid_t pid = fork();
  ASSERT_GE(pid, 0);

  if (pid == 0) {
    // Kill ourself if the parent dies to prevent leaking the child.
    prctl(PR_SET_PDEATHSIG, SIGKILL);

    // Spin child to consume cpu cycles.
    while (true);
  }

  // Continue in parent.
  set<string> events;
  // Hardware event.
  events.insert("cycles");
  // Software event.
  events.insert("task-clock");

  // Sample the child.
  Duration duration = Milliseconds(100);
  Future<mesos::PerfStatistics> statistics =
    perf::sample(events, pid, duration);
  AWAIT_READY(statistics);

  // Kill the child and reap it.
  Future<Option<int>> status = reap(pid);
  kill(pid, SIGKILL);
  AWAIT_READY(status);

  // Check the sample timestamp is within the last 5 seconds. This is generous
  // because there's the process reap delay in addition to the sampling
  // duration.
  ASSERT_TRUE(statistics.get().has_timestamp());
  EXPECT_GT(
      Seconds(5).secs(), Clock::now().secs() - statistics.get().timestamp());
  EXPECT_EQ(duration.secs(), statistics.get().duration());

  ASSERT_TRUE(statistics.get().has_cycles());

  // TODO(benh): Some Linux distributions (Ubuntu 14.04) fail to
  // properly sample 'cycles' with 'perf', so we don't explicitly
  // check the value here. See MESOS-3082.
  // EXPECT_LT(0u, statistics.get().cycles());

  ASSERT_TRUE(statistics.get().has_task_clock());
  EXPECT_LT(0.0, statistics.get().task_clock());
}

} // namespace tests {
} // namespace internal {
} // namespace mesos {
<commit_msg>Used -> operator for Try in perf_tests.cpp.<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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
 *
 * 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.
 */

#include <sys/prctl.h>

#include <set>

#include <gmock/gmock.h>

#include <process/clock.hpp>
#include <process/gtest.hpp>
#include <process/reap.hpp>

#include <stout/gtest.hpp>
#include <stout/stringify.hpp>

#include "linux/perf.hpp"

using std::set;
using std::string;

using namespace process;

namespace mesos {
namespace internal {
namespace tests {

class PerfTest : public ::testing::Test {};

TEST_F(PerfTest, ROOT_Events)
{
  set<string> events;

  // Valid events.
  events.insert("cycles");
  events.insert("task-clock");
  EXPECT_TRUE(perf::valid(events));

  // Add an invalid event.
  events.insert("this-is-an-invalid-event");
  EXPECT_FALSE(perf::valid(events));
}

TEST_F(PerfTest, Parse)
{
  // uint64 and floats should be parsed.
  Try<hashmap<string, mesos::PerfStatistics> > parse =
    perf::parse("123,cycles\n0.123,task-clock");
  CHECK_SOME(parse);

  ASSERT_TRUE(parse->contains(""));
  mesos::PerfStatistics statistics = parse->get("").get();

  ASSERT_TRUE(statistics.has_cycles());
  EXPECT_EQ(123u, statistics.cycles());
  ASSERT_TRUE(statistics.has_task_clock());
  EXPECT_EQ(0.123, statistics.task_clock());

  // Parse multiple cgroups.
  parse = perf::parse("123,cycles,cgroup1\n"
                      "456,cycles,cgroup2\n"
                      "0.456,task-clock,cgroup2\n"
                      "0.123,task-clock,cgroup1");
  CHECK_SOME(parse);
  EXPECT_FALSE(parse->contains(""));

  ASSERT_TRUE(parse->contains("cgroup1"));
  statistics = parse->get("cgroup1").get();

  ASSERT_TRUE(statistics.has_cycles());
  EXPECT_EQ(123u, statistics.cycles());
  ASSERT_TRUE(statistics.has_task_clock());
  EXPECT_EQ(0.123, statistics.task_clock());

  ASSERT_TRUE(parse->contains("cgroup2"));
  statistics = parse->get("cgroup2").get();

  ASSERT_TRUE(statistics.has_cycles());
  EXPECT_EQ(456u, statistics.cycles());
  EXPECT_TRUE(statistics.has_task_clock());
  EXPECT_EQ(0.456, statistics.task_clock());

  // Statistics reporting <not supported> should not appear.
  parse = perf::parse("<not supported>,cycles");
  CHECK_SOME(parse);

  ASSERT_TRUE(parse->contains(""));
  statistics = parse->get("").get();
  EXPECT_FALSE(statistics.has_cycles());

  // Statistics reporting <not counted> should be zero.
  parse = perf::parse("<not counted>,cycles\n<not counted>,task-clock");
  CHECK_SOME(parse);

  ASSERT_TRUE(parse->contains(""));
  statistics = parse->get("").get();

  EXPECT_TRUE(statistics.has_cycles());
  EXPECT_EQ(0u, statistics.cycles());
  EXPECT_TRUE(statistics.has_task_clock());
  EXPECT_EQ(0.0, statistics.task_clock());

  // Check parsing fails.
  parse = perf::parse("1,cycles\ngarbage");
  EXPECT_ERROR(parse);

  parse = perf::parse("1,unknown-field");
  EXPECT_ERROR(parse);
}

TEST_F(PerfTest, ROOT_SamplePid)
{
  // TODO(idownes): Replace this with a Subprocess when it supports
  // DEATHSIG.
  // Fork a child which we'll run perf against.
  pid_t pid = fork();
  ASSERT_GE(pid, 0);

  if (pid == 0) {
    // Kill ourself if the parent dies to prevent leaking the child.
    prctl(PR_SET_PDEATHSIG, SIGKILL);

    // Spin child to consume cpu cycles.
    while (true);
  }

  // Continue in parent.
  set<string> events;
  // Hardware event.
  events.insert("cycles");
  // Software event.
  events.insert("task-clock");

  // Sample the child.
  Duration duration = Milliseconds(100);
  Future<mesos::PerfStatistics> statistics =
    perf::sample(events, pid, duration);
  AWAIT_READY(statistics);

  // Kill the child and reap it.
  Future<Option<int>> status = reap(pid);
  kill(pid, SIGKILL);
  AWAIT_READY(status);

  // Check the sample timestamp is within the last 5 seconds. This is generous
  // because there's the process reap delay in addition to the sampling
  // duration.
  ASSERT_TRUE(statistics->has_timestamp());
  EXPECT_GT(
      Seconds(5).secs(), Clock::now().secs() - statistics->timestamp());
  EXPECT_EQ(duration.secs(), statistics->duration());

  ASSERT_TRUE(statistics->has_cycles());

  // TODO(benh): Some Linux distributions (Ubuntu 14.04) fail to
  // properly sample 'cycles' with 'perf', so we don't explicitly
  // check the value here. See MESOS-3082.
  // EXPECT_LT(0u, statistics->cycles());

  ASSERT_TRUE(statistics->has_task_clock());
  EXPECT_LT(0.0, statistics->task_clock());
}

} // namespace tests {
} // namespace internal {
} // namespace mesos {
<|endoftext|>


<commit_before><commit_msg>sw: fix assert on loading fdo48559-1.rtf<commit_after><|endoftext|>


<commit_before>//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

#include "ANGLEPerfTest.h"

#include "third_party/perf/perf_test.h"

#include <iostream>
#include <cassert>

ANGLEPerfTest::ANGLEPerfTest(const std::string &name, const std::string &suffix)
    : mName(name),
      mSuffix(suffix),
      mRunning(false),
      mNumFrames(0)
{
    mTimer.reset(CreateTimer());
}

void ANGLEPerfTest::run()
{
    mTimer->start();
    double prevTime = 0.0;

    while (mRunning)
    {
        double elapsedTime = mTimer->getElapsedTime();
        double deltaTime = elapsedTime - prevTime;

        ++mNumFrames;
        step(static_cast<float>(deltaTime), elapsedTime);

        if (!mRunning)
        {
            break;
        }

        prevTime = elapsedTime;
    }
}

void ANGLEPerfTest::printResult(const std::string &trace, double value, const std::string &units, bool important) const
{
    perf_test::PrintResult(mName, mSuffix, trace, value, units, important);
}

void ANGLEPerfTest::printResult(const std::string &trace, size_t value, const std::string &units, bool important) const
{
    perf_test::PrintResult(mName, mSuffix, trace, value, units, important);
}

void ANGLEPerfTest::SetUp()
{
    mRunning = true;
}

void ANGLEPerfTest::TearDown()
{
    double totalTime = mTimer->getElapsedTime();
    double averageTime = 1000.0 * totalTime / static_cast<double>(mNumFrames);

    printResult("total_time", totalTime, "s", true);
    printResult("frames", static_cast<size_t>(mNumFrames), "frames", true);
    printResult("average_time", averageTime, "ms", true);
}

std::string RenderTestParams::suffix() const
{
    switch (requestedRenderer)
    {
        case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE: return "_d3d11";
        case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE: return "_d3d9";
        default: assert(0); return "_unk";
    }
}

ANGLERenderTest::ANGLERenderTest(const std::string &name, const RenderTestParams &testParams)
    : ANGLEPerfTest(name, testParams.suffix()),
      mTestParams(testParams),
      mDrawIterations(10),
      mRunTimeSeconds(5.0)
{
}

void ANGLERenderTest::SetUp()
{
    EGLPlatformParameters platformParams(mTestParams.requestedRenderer,
                                         EGL_DONT_CARE,
                                         EGL_DONT_CARE,
                                         mTestParams.deviceType);

    mOSWindow.reset(CreateOSWindow());
    mEGLWindow.reset(new EGLWindow(mTestParams.widowWidth,
                                   mTestParams.windowHeight,
                                   mTestParams.glesMajorVersion,
                                   platformParams));

    if (!mOSWindow->initialize(mName, mEGLWindow->getWidth(), mEGLWindow->getHeight()))
    {
        FAIL() << "Failed initializing OSWindow";
        return;
    }

    if (!mEGLWindow->initializeGL(mOSWindow.get()))
    {
        FAIL() << "Failed initializing EGLWindow";
        return;
    }

    if (!initializeBenchmark())
    {
        FAIL() << "Failed initializing base perf test";
        return;
    }

    ANGLEPerfTest::SetUp();
}

void ANGLERenderTest::TearDown()
{
    ANGLEPerfTest::TearDown();

    destroyBenchmark();

    mEGLWindow->destroyGL();
    mOSWindow->destroy();
}

void ANGLERenderTest::step(float dt, double totalTime)
{
    stepBenchmark(dt, totalTime);

    // Clear events that the application did not process from this frame
    Event event;
    while (popEvent(&event))
    {
        // If the application did not catch a close event, close now
        if (event.Type == Event::EVENT_CLOSED)
        {
            mRunning = false;
        }
    }

    if (mRunning)
    {
        draw();
        mEGLWindow->swap();
        mOSWindow->messageLoop();
    }
}

void ANGLERenderTest::draw()
{
    if (mTimer->getElapsedTime() > mRunTimeSeconds)
    {
        mRunning = false;
        return;
    }

    ++mNumFrames;

    beginDrawBenchmark();

    for (unsigned int iteration = 0; iteration < mDrawIterations; ++iteration)
    {
        drawBenchmark();
    }

    endDrawBenchmark();
}

bool ANGLERenderTest::popEvent(Event *event)
{
    return mOSWindow->popEvent(event);
}

OSWindow *ANGLERenderTest::getWindow()
{
    return mOSWindow.get();
}
<commit_msg>Disable vsync for perf tests and don't report the total time.<commit_after>//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

#include "ANGLEPerfTest.h"

#include "third_party/perf/perf_test.h"

#include <iostream>
#include <cassert>

ANGLEPerfTest::ANGLEPerfTest(const std::string &name, const std::string &suffix)
    : mName(name),
      mSuffix(suffix),
      mRunning(false),
      mNumFrames(0)
{
    mTimer.reset(CreateTimer());
}

void ANGLEPerfTest::run()
{
    mTimer->start();
    double prevTime = 0.0;

    while (mRunning)
    {
        double elapsedTime = mTimer->getElapsedTime();
        double deltaTime = elapsedTime - prevTime;

        ++mNumFrames;
        step(static_cast<float>(deltaTime), elapsedTime);

        if (!mRunning)
        {
            break;
        }

        prevTime = elapsedTime;
    }
}

void ANGLEPerfTest::printResult(const std::string &trace, double value, const std::string &units, bool important) const
{
    perf_test::PrintResult(mName, mSuffix, trace, value, units, important);
}

void ANGLEPerfTest::printResult(const std::string &trace, size_t value, const std::string &units, bool important) const
{
    perf_test::PrintResult(mName, mSuffix, trace, value, units, important);
}

void ANGLEPerfTest::SetUp()
{
    mRunning = true;
}

void ANGLEPerfTest::TearDown()
{
    double totalTime = mTimer->getElapsedTime();
    double averageTime = 1000.0 * totalTime / static_cast<double>(mNumFrames);

    printResult("total_time", totalTime, "s", false);
    printResult("frames", static_cast<size_t>(mNumFrames), "frames", true);
    printResult("average_time", averageTime, "ms", true);
}

std::string RenderTestParams::suffix() const
{
    switch (requestedRenderer)
    {
        case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE: return "_d3d11";
        case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE: return "_d3d9";
        default: assert(0); return "_unk";
    }
}

ANGLERenderTest::ANGLERenderTest(const std::string &name, const RenderTestParams &testParams)
    : ANGLEPerfTest(name, testParams.suffix()),
      mTestParams(testParams),
      mDrawIterations(10),
      mRunTimeSeconds(5.0)
{
}

void ANGLERenderTest::SetUp()
{
    EGLPlatformParameters platformParams(mTestParams.requestedRenderer,
                                         EGL_DONT_CARE,
                                         EGL_DONT_CARE,
                                         mTestParams.deviceType);

    mOSWindow.reset(CreateOSWindow());
    mEGLWindow.reset(new EGLWindow(mTestParams.widowWidth,
                                   mTestParams.windowHeight,
                                   mTestParams.glesMajorVersion,
                                   platformParams));
    mEGLWindow->setSwapInterval(0);

    if (!mOSWindow->initialize(mName, mEGLWindow->getWidth(), mEGLWindow->getHeight()))
    {
        FAIL() << "Failed initializing OSWindow";
        return;
    }

    if (!mEGLWindow->initializeGL(mOSWindow.get()))
    {
        FAIL() << "Failed initializing EGLWindow";
        return;
    }

    if (!initializeBenchmark())
    {
        FAIL() << "Failed initializing base perf test";
        return;
    }

    ANGLEPerfTest::SetUp();
}

void ANGLERenderTest::TearDown()
{
    ANGLEPerfTest::TearDown();

    destroyBenchmark();

    mEGLWindow->destroyGL();
    mOSWindow->destroy();
}

void ANGLERenderTest::step(float dt, double totalTime)
{
    stepBenchmark(dt, totalTime);

    // Clear events that the application did not process from this frame
    Event event;
    while (popEvent(&event))
    {
        // If the application did not catch a close event, close now
        if (event.Type == Event::EVENT_CLOSED)
        {
            mRunning = false;
        }
    }

    if (mRunning)
    {
        draw();
        mEGLWindow->swap();
        mOSWindow->messageLoop();
    }
}

void ANGLERenderTest::draw()
{
    if (mTimer->getElapsedTime() > mRunTimeSeconds)
    {
        mRunning = false;
        return;
    }

    ++mNumFrames;

    beginDrawBenchmark();

    for (unsigned int iteration = 0; iteration < mDrawIterations; ++iteration)
    {
        drawBenchmark();
    }

    endDrawBenchmark();
}

bool ANGLERenderTest::popEvent(Event *event)
{
    return mOSWindow->popEvent(event);
}

OSWindow *ANGLERenderTest::getWindow()
{
    return mOSWindow.get();
}
<|endoftext|>


<commit_before>#include "halley_editor.h"
#include "editor_root_stage.h"
#include "halley/tools/project/project.h"
#include "preferences.h"
#include "halley/core/game/environment.h"
#include "halley/tools/file/filesystem.h"
#include "halley/tools/project/project_loader.h"

using namespace Halley;

void initOpenGLPlugin(IPluginRegistry &registry);
void initSDLSystemPlugin(IPluginRegistry &registry, std::optional<String> cryptKey);
void initSDLAudioPlugin(IPluginRegistry &registry);
void initSDLInputPlugin(IPluginRegistry &registry);
void initAsioPlugin(IPluginRegistry &registry);
void initDX11Plugin(IPluginRegistry &registry);
void initMetalPlugin(IPluginRegistry &registry);

HalleyEditor::HalleyEditor()
{
}

HalleyEditor::~HalleyEditor()
{
}

int HalleyEditor::initPlugins(IPluginRegistry &registry)
{
	initSDLSystemPlugin(registry, {});
	initAsioPlugin(registry);
	initSDLAudioPlugin(registry);
	initSDLInputPlugin(registry);

#ifdef _WIN32
	initDX11Plugin(registry);
#elif __APPLE__
	initMetalPlugin(registry);
#else
	initOpenGLPlugin(registry);
#endif

	return HalleyAPIFlags::Video | HalleyAPIFlags::Audio | HalleyAPIFlags::Input | HalleyAPIFlags::Network;
}

void HalleyEditor::initResourceLocator(const Path& gamePath, const Path& assetsPath, const Path& unpackedAssetsPath, ResourceLocator& locator)
{
	locator.addFileSystem(unpackedAssetsPath);
}

String HalleyEditor::getName() const
{
	return "Halley Editor";
}

String HalleyEditor::getDataPath() const
{
	return "halley/editor";
}

bool HalleyEditor::isDevMode() const
{
	return true;
}

bool HalleyEditor::shouldCreateSeparateConsole() const
{
#ifdef _DEBUG
	return isDevMode();
#else
	return false;
#endif
}

Preferences& HalleyEditor::getPreferences()
{
	return *preferences;
}

ProjectLoader& HalleyEditor::getProjectLoader()
{
	projectLoader->setDisabledPlatforms(preferences->getDisabledPlatforms());
	return *projectLoader;
}

void HalleyEditor::init(const Environment& environment, const Vector<String>& args)
{
	rootPath = environment.getProgramPath().parentPath();

	parseArguments(args);
}

void HalleyEditor::parseArguments(const std::vector<String>& args)
{
	gotProjectPath = false;

	for (auto& arg : args) {
		if (arg.startsWith("--")) {
			std::cout << "Unknown argument \"" << arg << "\".\n";
		} else {
			if (!gotProjectPath) {
				projectPath = arg.cppStr();
				gotProjectPath = true;
			} else {
				std::cout << "Unknown argument \"" << arg << "\".\n";
			}
		}
	}
}

std::unique_ptr<Stage> HalleyEditor::startGame()
{
	auto& api = getAPI();
	preferences = std::make_unique<Preferences>();
	preferences->setEditorVersion("2021-03-06");
	preferences->loadFromFile(*api.system);

	projectLoader = std::make_unique<ProjectLoader>(api.core->getStatics(), rootPath, preferences->getDisabledPlatforms());
	std::unique_ptr<Project> project;

	if (gotProjectPath) {
		project = loadProject(Path(projectPath));
	}

	api.video->setWindow(preferences->getWindowDefinition());
	api.video->setVsync(true);
	return std::make_unique<EditorRootStage>(*this, std::move(project));
}

std::unique_ptr<Project> HalleyEditor::loadProject(Path path)
{
	auto project = projectLoader->loadProject(path);

	if (!project) {
		throw Exception("Unable to load project at " + path.string(), HalleyExceptions::Tools);
	}

	project->loadGameResources(getAPI());

	preferences->addRecent(path.string());

	return project;
}

std::unique_ptr<Project> HalleyEditor::createProject(Path path)
{
	std::unique_ptr<Project> project;

	// TODO

	if (!project) {
		throw Exception("Unable to create project at " + path.string(), HalleyExceptions::Tools);
	}

	preferences->addRecent(path.string());

	return project;
}

HalleyGame(HalleyEditor);
<commit_msg>Bump version<commit_after>#include "halley_editor.h"
#include "editor_root_stage.h"
#include "halley/tools/project/project.h"
#include "preferences.h"
#include "halley/core/game/environment.h"
#include "halley/tools/file/filesystem.h"
#include "halley/tools/project/project_loader.h"

using namespace Halley;

void initOpenGLPlugin(IPluginRegistry &registry);
void initSDLSystemPlugin(IPluginRegistry &registry, std::optional<String> cryptKey);
void initSDLAudioPlugin(IPluginRegistry &registry);
void initSDLInputPlugin(IPluginRegistry &registry);
void initAsioPlugin(IPluginRegistry &registry);
void initDX11Plugin(IPluginRegistry &registry);
void initMetalPlugin(IPluginRegistry &registry);

HalleyEditor::HalleyEditor()
{
}

HalleyEditor::~HalleyEditor()
{
}

int HalleyEditor::initPlugins(IPluginRegistry &registry)
{
	initSDLSystemPlugin(registry, {});
	initAsioPlugin(registry);
	initSDLAudioPlugin(registry);
	initSDLInputPlugin(registry);

#ifdef _WIN32
	initDX11Plugin(registry);
#elif __APPLE__
	initMetalPlugin(registry);
#else
	initOpenGLPlugin(registry);
#endif

	return HalleyAPIFlags::Video | HalleyAPIFlags::Audio | HalleyAPIFlags::Input | HalleyAPIFlags::Network;
}

void HalleyEditor::initResourceLocator(const Path& gamePath, const Path& assetsPath, const Path& unpackedAssetsPath, ResourceLocator& locator)
{
	locator.addFileSystem(unpackedAssetsPath);
}

String HalleyEditor::getName() const
{
	return "Halley Editor";
}

String HalleyEditor::getDataPath() const
{
	return "halley/editor";
}

bool HalleyEditor::isDevMode() const
{
	return true;
}

bool HalleyEditor::shouldCreateSeparateConsole() const
{
#ifdef _DEBUG
	return isDevMode();
#else
	return false;
#endif
}

Preferences& HalleyEditor::getPreferences()
{
	return *preferences;
}

ProjectLoader& HalleyEditor::getProjectLoader()
{
	projectLoader->setDisabledPlatforms(preferences->getDisabledPlatforms());
	return *projectLoader;
}

void HalleyEditor::init(const Environment& environment, const Vector<String>& args)
{
	rootPath = environment.getProgramPath().parentPath();

	parseArguments(args);
}

void HalleyEditor::parseArguments(const std::vector<String>& args)
{
	gotProjectPath = false;

	for (auto& arg : args) {
		if (arg.startsWith("--")) {
			std::cout << "Unknown argument \"" << arg << "\".\n";
		} else {
			if (!gotProjectPath) {
				projectPath = arg.cppStr();
				gotProjectPath = true;
			} else {
				std::cout << "Unknown argument \"" << arg << "\".\n";
			}
		}
	}
}

std::unique_ptr<Stage> HalleyEditor::startGame()
{
	auto& api = getAPI();
	preferences = std::make_unique<Preferences>();
	preferences->setEditorVersion("2021-03-10");
	preferences->loadFromFile(*api.system);

	projectLoader = std::make_unique<ProjectLoader>(api.core->getStatics(), rootPath, preferences->getDisabledPlatforms());
	std::unique_ptr<Project> project;

	if (gotProjectPath) {
		project = loadProject(Path(projectPath));
	}

	api.video->setWindow(preferences->getWindowDefinition());
	api.video->setVsync(true);
	return std::make_unique<EditorRootStage>(*this, std::move(project));
}

std::unique_ptr<Project> HalleyEditor::loadProject(Path path)
{
	auto project = projectLoader->loadProject(path);

	if (!project) {
		throw Exception("Unable to load project at " + path.string(), HalleyExceptions::Tools);
	}

	project->loadGameResources(getAPI());

	preferences->addRecent(path.string());

	return project;
}

std::unique_ptr<Project> HalleyEditor::createProject(Path path)
{
	std::unique_ptr<Project> project;

	// TODO

	if (!project) {
		throw Exception("Unable to create project at " + path.string(), HalleyExceptions::Tools);
	}

	preferences->addRecent(path.string());

	return project;
}

HalleyGame(HalleyEditor);
<|endoftext|>