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

#include "xwalk/application/common/installer/package_installer_tizen.h"

#include <sys/types.h>
#include <pwd.h>
#include <unistd.h>
#include <pkgmgr/pkgmgr_parser.h>
#include <algorithm>
#include <map>
#include <string>

#include "base/file_util.h"
#include "base/files/file_enumerator.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/command_line.h"
#include "base/process/launch.h"
#include "third_party/libxml/chromium/libxml_utils.h"
#include "xwalk/application/common/application_data.h"
#include "xwalk/application/common/application_manifest_constants.h"
#include "xwalk/application/common/manifest_handlers/tizen_application_handler.h"
#include "xwalk/application/common/manifest_handlers/tizen_metadata_handler.h"
#include "xwalk/application/common/application_storage.h"
#include "xwalk/application/common/installer/tizen/packageinfo_constants.h"
#include "xwalk/application/common/id_util.h"
#include "xwalk/runtime/common/xwalk_paths.h"

namespace info = xwalk::application_packageinfo_constants;

namespace {

namespace widget_keys = xwalk::application_widget_keys;

const base::FilePath kPkgHelper("/usr/bin/xwalk-pkg-helper");

const base::FilePath kXWalkLauncherBinary("/usr/bin/xwalk-launcher");

const base::FilePath kDefaultIcon(
    "/usr/share/icons/default/small/crosswalk.png");

const std::string kServicePrefix("xwalk-service.");
const std::string kAppIdPrefix("xwalk.");

class FileDeleter {
 public:
  FileDeleter(const base::FilePath& path, bool recursive)
      : path_(path),
        recursive_(recursive) {}

  ~FileDeleter() {
    if (path_.empty())
      return;

    base::DeleteFile(path_, recursive_);
  }

  void Dismiss() {
    path_.clear();
  }

 private:
  base::FilePath path_;
  bool recursive_;
};

void WriteMetaDataElement(
    XmlWriter& writer, // NOLINT
    xwalk::application::TizenMetaDataInfo* info) {
  if (!info)
    return;

  const std::map<std::string, std::string>& metadata = info->metadata();
  std::map<std::string, std::string>::const_iterator it;
  for (it = metadata.begin(); it != metadata.end(); ++it) {
    writer.StartElement("metadata");
    writer.AddAttribute("key", it->first);
    writer.AddAttribute("value", it->second);
    writer.EndElement();
  }
}

// For xpk, package_id => [crosswalk_32bytes_app_id]
// For wgt, package_id => [tizen_wrt_10bytes_package_id]
std::string GetTizenPackageId(
    xwalk::application::ApplicationData* application) {
  if (application->GetPackageType() == xwalk::application::Package::XPK)
    return application->ID();

  const xwalk::application::TizenApplicationInfo* tizen_app_info =
      static_cast<xwalk::application::TizenApplicationInfo*>(
          application->GetManifestData(widget_keys::kTizenApplicationKey));
  return tizen_app_info->package();
}

bool GeneratePkgInfoXml(xwalk::application::ApplicationData* application,
                        const std::string& icon_name,
                        const base::FilePath& app_dir,
                        const base::FilePath& xml_path) {
  if (!base::PathExists(app_dir) &&
      !base::CreateDirectory(app_dir))
    return false;

  std::string package_id = GetTizenPackageId(application);
  std::string tizen_app_id = GetTizenAppId(application);

  base::FilePath execute_path =
      app_dir.AppendASCII("bin/").AppendASCII(tizen_app_id);
  std::string stripped_name = application->Name();

  FILE* file = base::OpenFile(xml_path, "w");

  XmlWriter xml_writer;
  xml_writer.StartWriting();
  xml_writer.StartElement("manifest");
  xml_writer.AddAttribute("xmlns", "http://tizen.org/ns/packages");
  xml_writer.AddAttribute("package", package_id);
  xml_writer.AddAttribute("version", application->VersionString());
  xml_writer.WriteElement("label", application->Name());
  xml_writer.WriteElement("description", application->Description());

  xml_writer.StartElement("ui-application");
  xml_writer.AddAttribute("appid",
      xwalk::application::RawAppIdToAppIdForTizenPkgmgrDB(tizen_app_id));
  xml_writer.AddAttribute("exec", execute_path.MaybeAsASCII());
  xml_writer.AddAttribute("type", "c++app");
  xml_writer.AddAttribute("taskmanage", "true");
  xml_writer.WriteElement("label", application->Name());

  xwalk::application::TizenMetaDataInfo* info =
      static_cast<xwalk::application::TizenMetaDataInfo*>(
      application->GetManifestData(widget_keys::kTizenMetaDataKey));
  WriteMetaDataElement(xml_writer, info);

  if (icon_name.empty())
    xml_writer.WriteElement("icon", info::kDefaultIconName);
  else
    xml_writer.WriteElement("icon", kServicePrefix + package_id + ".png");
  xml_writer.EndElement();  // Ends "ui-application"

  xml_writer.EndElement();  // Ends "manifest" element.
  xml_writer.StopWriting();

  base::WriteFile(xml_path,
                  xml_writer.GetWrittenString().c_str(),
                  xml_writer.GetWrittenString().size());

  base::CloseFile(file);
  LOG(INFO) << "Converting manifest.json into "
            << xml_path.BaseName().MaybeAsASCII()
            << " for installation. [DONE]";
  return true;
}

bool CreateAppSymbolicLink(const base::FilePath& app_dir,
                           const std::string& tizen_app_id) {
  base::FilePath execute_path =
      app_dir.AppendASCII("bin/").AppendASCII(tizen_app_id);

  if (!base::CreateDirectory(execute_path.DirName())) {
    LOG(ERROR) << "Could not create directory '"
               << execute_path.DirName().value() << "'.";
    return false;
  }

  if (!base::CreateSymbolicLink(kXWalkLauncherBinary, execute_path)) {
    LOG(ERROR) << "Could not create symbolic link to launcher from '"
               << execute_path.value() << "'.";
    return false;
  }
  return true;
}

}  // namespace

namespace xwalk {
namespace application {

PackageInstallerTizen::PackageInstallerTizen(ApplicationStorage* storage)
    : PackageInstaller(storage) {
}

bool PackageInstallerTizen::PlatformInstall(ApplicationData* app_data) {
  std::string app_id(app_data->ID());
  base::FilePath data_dir;
  CHECK(PathService::Get(xwalk::DIR_DATA_PATH, &data_dir));

  std::string tizen_app_id = GetTizenAppId(app_data);
  base::FilePath app_dir =
      data_dir.AppendASCII(info::kAppDir).AppendASCII(app_id);
  base::FilePath xml_path = data_dir.AppendASCII(info::kAppDir).AppendASCII(
      app_id + std::string(info::kXmlExtension));

  std::string icon_name;
  if (!app_data->GetManifest()->GetString(info::kIconKey, &icon_name)) {
    LOG(WARNING) << "'icon' not included in manifest";
  }
  // This will clean everything inside '<data dir>/<app id>'.
  FileDeleter app_dir_cleaner(app_dir, true);

  if (!GeneratePkgInfoXml(app_data, icon_name, app_dir, xml_path)) {
    LOG(ERROR) << "Failed to create XML metadata file '"
               << xml_path.value() << "'.";
    return false;
  }

  if (!CreateAppSymbolicLink(app_dir, tizen_app_id)) {
    LOG(ERROR) << "Failed to create symbolic link for " << app_id;
    return false;
  }

  base::FilePath icon =
      icon_name.empty() ? kDefaultIcon : app_dir.AppendASCII(icon_name);

  CommandLine cmdline(kPkgHelper);
  cmdline.AppendSwitch("--install");
  cmdline.AppendArg(app_id);
  cmdline.AppendArgPath(xml_path);
  cmdline.AppendArgPath(icon);

  int exit_code;
  std::string output;

  if (!base::GetAppOutputWithExitCode(cmdline, &output, &exit_code)) {
    LOG(ERROR) << "Could not launch the installation helper process.";
    return false;
  }

  if (exit_code != 0) {
    LOG(ERROR) << "Could not install application: "
               << output << " (" << exit_code << ")";
    return false;
  }

  app_dir_cleaner.Dismiss();

  return true;
}

bool PackageInstallerTizen::PlatformUninstall(ApplicationData* app_data) {
  bool result = true;
  std::string app_id(app_data->ID());
  base::FilePath data_dir;
  CHECK(PathService::Get(xwalk::DIR_DATA_PATH, &data_dir));

  CommandLine cmdline(kPkgHelper);
  cmdline.AppendSwitch("--uninstall");
  cmdline.AppendArg(app_id);

  int exit_code;
  std::string output;

  if (!base::GetAppOutputWithExitCode(cmdline, &output, &exit_code)) {
    LOG(ERROR) << "Could not launch installer helper";
    result = false;
  }

  if (exit_code != 0) {
    LOG(ERROR) << "Could not uninstall application: "
               << output << " (" << exit_code << ")";
    result = false;
  }

  base::FilePath app_dir =
      data_dir.AppendASCII(info::kAppDir).AppendASCII(app_id);
  if (!base::DeleteFile(app_dir, true)) {
    LOG(ERROR) << "Could not remove directory '" << app_dir.value() << "'";
    result = false;
  }

  base::FilePath xml_path = data_dir.AppendASCII(
      app_id + std::string(info::kXmlExtension));
  if (!base::DeleteFile(xml_path, false)) {
    LOG(ERROR) << "Could not remove file '" << xml_path.value() << "'";
    result = false;
  }

  return result;
}

bool PackageInstallerTizen::PlatformUpdate(ApplicationData* app_data) {
  std::string app_id(app_data->ID());
  base::FilePath data_dir;
  CHECK(PathService::Get(xwalk::DIR_DATA_PATH, &data_dir));

  std::string tizen_app_id = GetTizenAppId(app_data);
  base::FilePath app_dir =
      data_dir.AppendASCII(info::kAppDir).AppendASCII(app_id);
  base::FilePath new_xml_path = data_dir.AppendASCII(info::kAppDir).AppendASCII(
      app_id + ".new" + std::string(info::kXmlExtension));

  std::string icon_name;
  if (!app_data->GetManifest()->GetString(info::kIconKey, &icon_name)) {
    LOG(WARNING) << "'icon' not included in manifest";
  }
  // This will clean everything inside '<data dir>/<app id>' and the new XML.
  FileDeleter app_dir_cleaner(app_dir, true);
  FileDeleter new_xml_cleaner(new_xml_path, true);

  if (!GeneratePkgInfoXml(app_data, icon_name, app_dir, new_xml_path)) {
    LOG(ERROR) << "Could not create new XML metadata file '"
               << new_xml_path.value() << "'.";
    return false;
  }

  if (!CreateAppSymbolicLink(app_dir, tizen_app_id))
    return false;

  base::FilePath icon =
      icon_name.empty() ? kDefaultIcon : app_dir.AppendASCII(icon_name);

  CommandLine cmdline(kPkgHelper);
  cmdline.AppendSwitch("--update");
  cmdline.AppendArg(app_id);
  cmdline.AppendArgPath(new_xml_path);
  cmdline.AppendArgPath(icon);

  int exit_code;
  std::string output;

  if (!base::GetAppOutputWithExitCode(cmdline, &output, &exit_code)) {
    LOG(ERROR) << "Could not launch installer helper";
    return false;
  }

  if (exit_code != 0) {
    LOG(ERROR) << "Could not update application: "
               << output << " (" << exit_code << ")";
    return false;
  }

  base::FilePath old_xml_path = data_dir.AppendASCII(info::kAppDir).AppendASCII(
      app_id + std::string(info::kXmlExtension));
  base::Move(new_xml_path, old_xml_path);
  app_dir_cleaner.Dismiss();
  return true;
}

}  // namespace application
}  // namespace xwalk
<commit_msg> [TIZEN] WebApp are installed with wrong application Type<commit_after>// Copyright (c) 2014 Intel Corporation. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "xwalk/application/common/installer/package_installer_tizen.h"

#include <sys/types.h>
#include <pwd.h>
#include <unistd.h>
#include <pkgmgr/pkgmgr_parser.h>
#include <algorithm>
#include <map>
#include <string>

#include "base/file_util.h"
#include "base/files/file_enumerator.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/command_line.h"
#include "base/process/launch.h"
#include "third_party/libxml/chromium/libxml_utils.h"
#include "xwalk/application/common/application_data.h"
#include "xwalk/application/common/application_manifest_constants.h"
#include "xwalk/application/common/manifest_handlers/tizen_application_handler.h"
#include "xwalk/application/common/manifest_handlers/tizen_metadata_handler.h"
#include "xwalk/application/common/application_storage.h"
#include "xwalk/application/common/installer/tizen/packageinfo_constants.h"
#include "xwalk/application/common/id_util.h"
#include "xwalk/runtime/common/xwalk_paths.h"

namespace info = xwalk::application_packageinfo_constants;

namespace {

namespace widget_keys = xwalk::application_widget_keys;

const base::FilePath kPkgHelper("/usr/bin/xwalk-pkg-helper");

const base::FilePath kXWalkLauncherBinary("/usr/bin/xwalk-launcher");

const base::FilePath kDefaultIcon(
    "/usr/share/icons/default/small/crosswalk.png");

const std::string kServicePrefix("xwalk-service.");
const std::string kAppIdPrefix("xwalk.");

class FileDeleter {
 public:
  FileDeleter(const base::FilePath& path, bool recursive)
      : path_(path),
        recursive_(recursive) {}

  ~FileDeleter() {
    if (path_.empty())
      return;

    base::DeleteFile(path_, recursive_);
  }

  void Dismiss() {
    path_.clear();
  }

 private:
  base::FilePath path_;
  bool recursive_;
};

void WriteMetaDataElement(
    XmlWriter& writer, // NOLINT
    xwalk::application::TizenMetaDataInfo* info) {
  if (!info)
    return;

  const std::map<std::string, std::string>& metadata = info->metadata();
  std::map<std::string, std::string>::const_iterator it;
  for (it = metadata.begin(); it != metadata.end(); ++it) {
    writer.StartElement("metadata");
    writer.AddAttribute("key", it->first);
    writer.AddAttribute("value", it->second);
    writer.EndElement();
  }
}

// For xpk, package_id => [crosswalk_32bytes_app_id]
// For wgt, package_id => [tizen_wrt_10bytes_package_id]
std::string GetTizenPackageId(
    xwalk::application::ApplicationData* application) {
  if (application->GetPackageType() == xwalk::application::Package::XPK)
    return application->ID();

  const xwalk::application::TizenApplicationInfo* tizen_app_info =
      static_cast<xwalk::application::TizenApplicationInfo*>(
          application->GetManifestData(widget_keys::kTizenApplicationKey));
  return tizen_app_info->package();
}

bool GeneratePkgInfoXml(xwalk::application::ApplicationData* application,
                        const std::string& icon_name,
                        const base::FilePath& app_dir,
                        const base::FilePath& xml_path) {
  if (!base::PathExists(app_dir) &&
      !base::CreateDirectory(app_dir))
    return false;

  std::string package_id = GetTizenPackageId(application);
  std::string tizen_app_id = GetTizenAppId(application);

  base::FilePath execute_path =
      app_dir.AppendASCII("bin/").AppendASCII(tizen_app_id);
  std::string stripped_name = application->Name();

  FILE* file = base::OpenFile(xml_path, "w");

  XmlWriter xml_writer;
  xml_writer.StartWriting();
  xml_writer.StartElement("manifest");
  xml_writer.AddAttribute("xmlns", "http://tizen.org/ns/packages");
  xml_writer.AddAttribute("package", package_id);
  xml_writer.AddAttribute("version", application->VersionString());
  xml_writer.WriteElement("label", application->Name());
  xml_writer.WriteElement("description", application->Description());

  xml_writer.StartElement("ui-application");
  xml_writer.AddAttribute("appid",
      xwalk::application::RawAppIdToAppIdForTizenPkgmgrDB(tizen_app_id));
  xml_writer.AddAttribute("exec", execute_path.MaybeAsASCII());
  xml_writer.AddAttribute("type", "webapp");
  xml_writer.AddAttribute("taskmanage", "true");
  xml_writer.WriteElement("label", application->Name());

  xwalk::application::TizenMetaDataInfo* info =
      static_cast<xwalk::application::TizenMetaDataInfo*>(
      application->GetManifestData(widget_keys::kTizenMetaDataKey));
  WriteMetaDataElement(xml_writer, info);

  if (icon_name.empty())
    xml_writer.WriteElement("icon", info::kDefaultIconName);
  else
    xml_writer.WriteElement("icon", kServicePrefix + package_id + ".png");
  xml_writer.EndElement();  // Ends "ui-application"

  xml_writer.EndElement();  // Ends "manifest" element.
  xml_writer.StopWriting();

  base::WriteFile(xml_path,
                  xml_writer.GetWrittenString().c_str(),
                  xml_writer.GetWrittenString().size());

  base::CloseFile(file);
  LOG(INFO) << "Converting manifest.json into "
            << xml_path.BaseName().MaybeAsASCII()
            << " for installation. [DONE]";
  return true;
}

bool CreateAppSymbolicLink(const base::FilePath& app_dir,
                           const std::string& tizen_app_id) {
  base::FilePath execute_path =
      app_dir.AppendASCII("bin/").AppendASCII(tizen_app_id);

  if (!base::CreateDirectory(execute_path.DirName())) {
    LOG(ERROR) << "Could not create directory '"
               << execute_path.DirName().value() << "'.";
    return false;
  }

  if (!base::CreateSymbolicLink(kXWalkLauncherBinary, execute_path)) {
    LOG(ERROR) << "Could not create symbolic link to launcher from '"
               << execute_path.value() << "'.";
    return false;
  }
  return true;
}

}  // namespace

namespace xwalk {
namespace application {

PackageInstallerTizen::PackageInstallerTizen(ApplicationStorage* storage)
    : PackageInstaller(storage) {
}

bool PackageInstallerTizen::PlatformInstall(ApplicationData* app_data) {
  std::string app_id(app_data->ID());
  base::FilePath data_dir;
  CHECK(PathService::Get(xwalk::DIR_DATA_PATH, &data_dir));

  std::string tizen_app_id = GetTizenAppId(app_data);
  base::FilePath app_dir =
      data_dir.AppendASCII(info::kAppDir).AppendASCII(app_id);
  base::FilePath xml_path = data_dir.AppendASCII(info::kAppDir).AppendASCII(
      app_id + std::string(info::kXmlExtension));

  std::string icon_name;
  if (!app_data->GetManifest()->GetString(info::kIconKey, &icon_name)) {
    LOG(WARNING) << "'icon' not included in manifest";
  }
  // This will clean everything inside '<data dir>/<app id>'.
  FileDeleter app_dir_cleaner(app_dir, true);

  if (!GeneratePkgInfoXml(app_data, icon_name, app_dir, xml_path)) {
    LOG(ERROR) << "Failed to create XML metadata file '"
               << xml_path.value() << "'.";
    return false;
  }

  if (!CreateAppSymbolicLink(app_dir, tizen_app_id)) {
    LOG(ERROR) << "Failed to create symbolic link for " << app_id;
    return false;
  }

  base::FilePath icon =
      icon_name.empty() ? kDefaultIcon : app_dir.AppendASCII(icon_name);

  CommandLine cmdline(kPkgHelper);
  cmdline.AppendSwitch("--install");
  cmdline.AppendArg(app_id);
  cmdline.AppendArgPath(xml_path);
  cmdline.AppendArgPath(icon);

  int exit_code;
  std::string output;

  if (!base::GetAppOutputWithExitCode(cmdline, &output, &exit_code)) {
    LOG(ERROR) << "Could not launch the installation helper process.";
    return false;
  }

  if (exit_code != 0) {
    LOG(ERROR) << "Could not install application: "
               << output << " (" << exit_code << ")";
    return false;
  }

  app_dir_cleaner.Dismiss();

  return true;
}

bool PackageInstallerTizen::PlatformUninstall(ApplicationData* app_data) {
  bool result = true;
  std::string app_id(app_data->ID());
  base::FilePath data_dir;
  CHECK(PathService::Get(xwalk::DIR_DATA_PATH, &data_dir));

  CommandLine cmdline(kPkgHelper);
  cmdline.AppendSwitch("--uninstall");
  cmdline.AppendArg(app_id);

  int exit_code;
  std::string output;

  if (!base::GetAppOutputWithExitCode(cmdline, &output, &exit_code)) {
    LOG(ERROR) << "Could not launch installer helper";
    result = false;
  }

  if (exit_code != 0) {
    LOG(ERROR) << "Could not uninstall application: "
               << output << " (" << exit_code << ")";
    result = false;
  }

  base::FilePath app_dir =
      data_dir.AppendASCII(info::kAppDir).AppendASCII(app_id);
  if (!base::DeleteFile(app_dir, true)) {
    LOG(ERROR) << "Could not remove directory '" << app_dir.value() << "'";
    result = false;
  }

  base::FilePath xml_path = data_dir.AppendASCII(
      app_id + std::string(info::kXmlExtension));
  if (!base::DeleteFile(xml_path, false)) {
    LOG(ERROR) << "Could not remove file '" << xml_path.value() << "'";
    result = false;
  }

  return result;
}

bool PackageInstallerTizen::PlatformUpdate(ApplicationData* app_data) {
  std::string app_id(app_data->ID());
  base::FilePath data_dir;
  CHECK(PathService::Get(xwalk::DIR_DATA_PATH, &data_dir));

  std::string tizen_app_id = GetTizenAppId(app_data);
  base::FilePath app_dir =
      data_dir.AppendASCII(info::kAppDir).AppendASCII(app_id);
  base::FilePath new_xml_path = data_dir.AppendASCII(info::kAppDir).AppendASCII(
      app_id + ".new" + std::string(info::kXmlExtension));

  std::string icon_name;
  if (!app_data->GetManifest()->GetString(info::kIconKey, &icon_name)) {
    LOG(WARNING) << "'icon' not included in manifest";
  }
  // This will clean everything inside '<data dir>/<app id>' and the new XML.
  FileDeleter app_dir_cleaner(app_dir, true);
  FileDeleter new_xml_cleaner(new_xml_path, true);

  if (!GeneratePkgInfoXml(app_data, icon_name, app_dir, new_xml_path)) {
    LOG(ERROR) << "Could not create new XML metadata file '"
               << new_xml_path.value() << "'.";
    return false;
  }

  if (!CreateAppSymbolicLink(app_dir, tizen_app_id))
    return false;

  base::FilePath icon =
      icon_name.empty() ? kDefaultIcon : app_dir.AppendASCII(icon_name);

  CommandLine cmdline(kPkgHelper);
  cmdline.AppendSwitch("--update");
  cmdline.AppendArg(app_id);
  cmdline.AppendArgPath(new_xml_path);
  cmdline.AppendArgPath(icon);

  int exit_code;
  std::string output;

  if (!base::GetAppOutputWithExitCode(cmdline, &output, &exit_code)) {
    LOG(ERROR) << "Could not launch installer helper";
    return false;
  }

  if (exit_code != 0) {
    LOG(ERROR) << "Could not update application: "
               << output << " (" << exit_code << ")";
    return false;
  }

  base::FilePath old_xml_path = data_dir.AppendASCII(info::kAppDir).AppendASCII(
      app_id + std::string(info::kXmlExtension));
  base::Move(new_xml_path, old_xml_path);
  app_dir_cleaner.Dismiss();
  return true;
}

}  // namespace application
}  // namespace xwalk
<|endoftext|>


<commit_before>/****************************************************************************

    unicode.hpp - Utility functions for encoding and decoding UTF-8 strings

    Copyright (C) 2006-2007 Lars Luthman <lars.luthman@gmail.com>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 01222-1307  USA

****************************************************************************/

#ifndef UNICODE_HPP
#define UNICODE_HPP

#include <iostream>
#include <string>
#include <utility>

using namespace std;
using namespace boost::spirit::classic;

template <typename ScannerT>
pair<unsigned int, unsigned int> decode_utf8(ScannerT const& scan) {

  typedef typename ScannerT::iterator_t iterator_t;
  typedef typename ScannerT::value_t value_t;

  if (scan.at_end())
    return make_pair(0, 0);

  iterator_t iter(scan.first);

  value_t ch = *scan.first;

  unsigned int size;
  unsigned int codepoint = 0;

  // one byte char
  if ((unsigned char)ch < 0x80) {
    size = 1;
    codepoint = ch;
  }

  // two byte char
  else if ((unsigned char)ch >= 192 && (unsigned char)ch < 224) {
    codepoint = ((unsigned char)ch && 0x1F) << 6;
    ++iter;
    if (iter == scan.last)
      return make_pair(0, 0);
    codepoint += (unsigned char)(*iter) && 0x3F;
    size = 2;
  }

  // three byte char
  else if ((unsigned char)ch >= 224 && (unsigned char)ch < 240) {
    codepoint = ((unsigned char)ch && 0x0F) << 12;
    ++iter;
    if (iter == scan.last)
      return make_pair(0, 0);
    codepoint += ((unsigned char)(*iter) && 0x3F) << 6;
    ++iter;
    if (iter == scan.last)
      return make_pair(0, 0);
    codepoint += ((unsigned char)(*iter) && 0x3F);
    size = 3;
  }

  // four byte char
  else if ((unsigned char)ch >= 240 && (unsigned char)ch < 248) {
    codepoint = ((unsigned char)ch && 0x07) << 18;
    ++iter;
    if (iter == scan.last)
      return make_pair(0, 0);
    codepoint += ((unsigned char)(*iter) && 0x3F) << 12;
    ++iter;
    if (iter == scan.last)
      return make_pair(0, 0);
    codepoint += ((unsigned char)(*iter) && 0x3F) << 6;
    ++iter;
    if (iter == scan.last)
      return make_pair(0, 0);
    codepoint += ((unsigned char)(*iter) && 0x3F);
    size = 4;
  }

  // this is not allowed in Turtle!
  else {
    assert(!"Unexpected parse error");
  }

  return make_pair(size, codepoint);
}

class uch_p : public parser<uch_p> {
public:

  uch_p(unsigned int codepoint = 0)
    : valid(codepoint) {

  }

  unsigned int valid;

  typedef uch_p self_t;

  template <typename ScannerT> struct result {
    typedef typename match_result<ScannerT, unsigned int>::type type;
  };

  template <typename ScannerT> typename parser_result<self_t, ScannerT>::type
  parse(ScannerT const& scan) const {

    pair<unsigned int, unsigned int> p = decode_utf8(scan);

    if (p.first > 0 && p.second == valid) {
      typedef typename ScannerT::iterator_t iterator_t;
      iterator_t save = scan.first;
      for (unsigned int i = 0; i < p.first; ++i)
        ++scan.first;
      return scan.create_match(p.first, p.second, save, scan.first);
    }

    return scan.no_match();
  }

};

class urange_p : public parser<urange_p> {
public:

  urange_p(unsigned int from, unsigned int to)
    : m_from(from),
      m_to(to) {

  }

  unsigned int m_from, m_to;

  typedef urange_p self_t;

  template <typename ScannerT> struct result {
    typedef typename match_result<ScannerT, unsigned int>::type type;
  };

  template <typename ScannerT> typename parser_result<self_t, ScannerT>::type
  parse(ScannerT const& scan) const {

    pair<unsigned int, unsigned int> p = decode_utf8(scan);

    if (p.first > 0 && p.second >= m_from && p.second <= m_to) {
      typedef typename ScannerT::iterator_t iterator_t;
      iterator_t save = scan.first;
      for (unsigned int i = 0; i < p.first; ++i)
        ++scan.first;
      return scan.create_match(p.first, p.second, save, scan.first);
    }

    return scan.no_match();
  }

};

#endif
<commit_msg>Use bitwise operators for bitwise comparisons<commit_after>/****************************************************************************

    unicode.hpp - Utility functions for encoding and decoding UTF-8 strings

    Copyright (C) 2006-2007 Lars Luthman <lars.luthman@gmail.com>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 01222-1307  USA

****************************************************************************/

#ifndef UNICODE_HPP
#define UNICODE_HPP

#include <iostream>
#include <string>
#include <utility>

using namespace std;
using namespace boost::spirit::classic;

template <typename ScannerT>
pair<unsigned int, unsigned int> decode_utf8(ScannerT const& scan) {

  typedef typename ScannerT::iterator_t iterator_t;
  typedef typename ScannerT::value_t value_t;

  if (scan.at_end())
    return make_pair(0, 0);

  iterator_t iter(scan.first);

  value_t ch = *scan.first;

  unsigned int size;
  unsigned int codepoint = 0;

  // one byte char
  if ((unsigned char)ch < 0x80) {
    size = 1;
    codepoint = ch;
  }

  // two byte char
  else if ((unsigned char)ch >= 192 && (unsigned char)ch < 224) {
    codepoint = ((unsigned char)ch & 0x1F) << 6;
    ++iter;
    if (iter == scan.last)
      return make_pair(0, 0);
    codepoint += (unsigned char)(*iter) & 0x3F;
    size = 2;
  }

  // three byte char
  else if ((unsigned char)ch >= 224 && (unsigned char)ch < 240) {
    codepoint = ((unsigned char)ch & 0x0F) << 12;
    ++iter;
    if (iter == scan.last)
      return make_pair(0, 0);
    codepoint += ((unsigned char)(*iter) & 0x3F) << 6;
    ++iter;
    if (iter == scan.last)
      return make_pair(0, 0);
    codepoint += ((unsigned char)(*iter) & 0x3F);
    size = 3;
  }

  // four byte char
  else if ((unsigned char)ch >= 240 && (unsigned char)ch < 248) {
    codepoint = ((unsigned char)ch & 0x07) << 18;
    ++iter;
    if (iter == scan.last)
      return make_pair(0, 0);
    codepoint += ((unsigned char)(*iter) & 0x3F) << 12;
    ++iter;
    if (iter == scan.last)
      return make_pair(0, 0);
    codepoint += ((unsigned char)(*iter) & 0x3F) << 6;
    ++iter;
    if (iter == scan.last)
      return make_pair(0, 0);
    codepoint += ((unsigned char)(*iter) & 0x3F);
    size = 4;
  }

  // this is not allowed in Turtle!
  else {
    assert(!"Unexpected parse error");
  }

  return make_pair(size, codepoint);
}

class uch_p : public parser<uch_p> {
public:

  uch_p(unsigned int codepoint = 0)
    : valid(codepoint) {

  }

  unsigned int valid;

  typedef uch_p self_t;

  template <typename ScannerT> struct result {
    typedef typename match_result<ScannerT, unsigned int>::type type;
  };

  template <typename ScannerT> typename parser_result<self_t, ScannerT>::type
  parse(ScannerT const& scan) const {

    pair<unsigned int, unsigned int> p = decode_utf8(scan);

    if (p.first > 0 && p.second == valid) {
      typedef typename ScannerT::iterator_t iterator_t;
      iterator_t save = scan.first;
      for (unsigned int i = 0; i < p.first; ++i)
        ++scan.first;
      return scan.create_match(p.first, p.second, save, scan.first);
    }

    return scan.no_match();
  }

};

class urange_p : public parser<urange_p> {
public:

  urange_p(unsigned int from, unsigned int to)
    : m_from(from),
      m_to(to) {

  }

  unsigned int m_from, m_to;

  typedef urange_p self_t;

  template <typename ScannerT> struct result {
    typedef typename match_result<ScannerT, unsigned int>::type type;
  };

  template <typename ScannerT> typename parser_result<self_t, ScannerT>::type
  parse(ScannerT const& scan) const {

    pair<unsigned int, unsigned int> p = decode_utf8(scan);

    if (p.first > 0 && p.second >= m_from && p.second <= m_to) {
      typedef typename ScannerT::iterator_t iterator_t;
      iterator_t save = scan.first;
      for (unsigned int i = 0; i < p.first; ++i)
        ++scan.first;
      return scan.create_match(p.first, p.second, save, scan.first);
    }

    return scan.no_match();
  }

};

#endif
<|endoftext|>


<commit_before>/*************************************************************************
*                                                                       *
* Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
* All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
*                                                                       *
* This library is free software; you can redistribute it and/or         *
* modify it under the terms of EITHER:                                  *
*   (1) The GNU Lesser General Public License as published by the Free  *
*       Software Foundation; either version 2.1 of the License, or (at  *
*       your option) any later version. The text of the GNU Lesser      *
*       General Public License is included with this library in the     *
*       file LICENSE.TXT.                                               *
*   (2) The BSD-style license that is included with this library in     *
*       the file LICENSE-BSD.TXT.                                       *
*                                                                       *
* This library is distributed in the hope that it will be useful,       *
* but WITHOUT ANY WARRANTY; without even the implied warranty of        *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
* LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
*                                                                       *
*************************************************************************/

/*******************************************************************
 *                                                                 *
 * cylinder-sphere collider by Christoph Beyer (boernerb@web.de)   *
 *                                                                 *
 * In Cylinder/Sphere-collisions, there are three possibilies:     *
 * 1. collision with the cylinder's nappe                          *
 * 2. collision with one of the cylinder's disc                    *
 * 3. collision with one of the disc's border                      *
 *                                                                 *
 * This collider computes two distances (s, t) and based on them,  *
 * it decides, which collision we have.                            *
 * This collider always generates 1 (or 0, if we have no collison) *
 * contacts.                                                       *
 * It is able to "separate" cylinder and sphere in all             *
 * configurations, but it never pays attention to velocity.        *
 * So, in extrem situations, "tunneling-effect" is possible.       *
 *                                                                 *
 *******************************************************************/

#include <ode/collision.h>
#include <ode/matrix.h>
#include <ode/rotation.h>
#include <ode/odemath.h>
#include <ode/objects.h>
#include "collision_kernel.h"	// for dxGeom

int dCollideCylinderSphere(dxGeom* Cylinder, dxGeom* Sphere,
                           int flags, dContactGeom *contact, int skip)
{
	dIASSERT (skip >= (int)sizeof(dContactGeom));
	dIASSERT (Cylinder->type == dCylinderClass);
	dIASSERT (Sphere->type == dSphereClass);
	dIASSERT ((flags & NUMC_MASK) >= 1);

	unsigned char* pContactData = (unsigned char*)contact;
	int GeomCount = 0; // count of used contacts

#ifdef dSINGLE
	const dReal toleranz = 0.0001f;
#endif
#ifdef dDOUBLE
	const dReal toleranz = 0.0000001;
#endif

	// get the data from the geoms
	dReal radius, length;
	dGeomCylinderGetParams(Cylinder, &radius, &length);
    dVector3 &cylpos = Cylinder->final_posr->pos;
	const dReal* pfRot1 = dGeomGetRotation(Cylinder);

	dReal radius2;
	radius2 = dGeomSphereGetRadius(Sphere);
	const dReal* SpherePos = dGeomGetPosition(Sphere);

	// G1Pos1 is the middle of the first disc
	// G1Pos2 is the middle of the second disc
	// vDir1 is the unit direction of the cylinderaxis
	dVector3 G1Pos1, G1Pos2, vDir1;
	vDir1[0] = Cylinder->final_posr->R[2];
	vDir1[1] = Cylinder->final_posr->R[6];
	vDir1[2] = Cylinder->final_posr->R[10];

	dReal s;
	s = length * dReal(0.5); // just a precomputed factor
	G1Pos2[0] = vDir1[0] * s + cylpos[0];
	G1Pos2[1] = vDir1[1] * s + cylpos[1];
	G1Pos2[2] = vDir1[2] * s + cylpos[2];

	G1Pos1[0] = vDir1[0] * -s + cylpos[0];
	G1Pos1[1] = vDir1[1] * -s + cylpos[1];
	G1Pos1[2] = vDir1[2] * -s + cylpos[2];

	dVector3 C;
	dReal t;
	// Step 1: compute the two distances 's' and 't'
	// 's' is the distance from the first disc (in vDir1-/Zylinderaxis-direction), the disc with G1Pos1 in the middle
	s = (SpherePos[0] - G1Pos1[0]) * vDir1[0] - (G1Pos1[1] - SpherePos[1]) * vDir1[1] - (G1Pos1[2] - SpherePos[2]) * vDir1[2];
	if(s < (-radius2) || s > (length + radius2) )
	{
		// Sphere is too far away from the discs
		// no collision
		return 0;
	}

	// C is the direction from Sphere-middle to the cylinder-axis (vDir1); C is orthogonal to the cylinder-axis
	C[0] = s * vDir1[0] + G1Pos1[0] - SpherePos[0];
	C[1] = s * vDir1[1] + G1Pos1[1] - SpherePos[1];
	C[2] = s * vDir1[2] + G1Pos1[2] - SpherePos[2];
	// t is the distance from the Sphere-middle to the cylinder-axis!
	t = dReal(sqrt(C[0] * C[0] + C[1] * C[1] + C[2] * C[2]) );
	if(t > (radius + radius2) )
	{
		// Sphere is too far away from the cylinder axis!
		// no collision
		return 0;
	}

	// decide which kind of collision we have:
	if(t > radius && (s < 0 || s > length) )
	{
		// 3. collision
		if(s <= 0)
		{
			contact->depth = radius2 - dReal(sqrt( (s) * (s) + (t - radius) * (t - radius) ));
			if(contact->depth < 0)
			{
				// no collision!
				return 0;
			}
			contact->pos[0] = C[0] / t * -radius + G1Pos1[0];
			contact->pos[1] = C[1] / t * -radius + G1Pos1[1];
			contact->pos[2] = C[2] / t * -radius + G1Pos1[2];
			contact->normal[0] = (contact->pos[0] - SpherePos[0]) / (radius2 - contact->depth);
			contact->normal[1] = (contact->pos[1] - SpherePos[1]) / (radius2 - contact->depth);
			contact->normal[2] = (contact->pos[2] - SpherePos[2]) / (radius2 - contact->depth);
			contact->g1 = Cylinder;
			contact->g2 = Sphere;
			GeomCount++;
			return GeomCount;
		}
		else
		{
			// now s is bigger than length here!
			contact->depth = radius2 - dReal(sqrt( (s - length) * (s - length) + (t - radius) * (t - radius) ));
			if(contact->depth < 0)
			{
				// no collision!
				return 0;
			}
			contact->pos[0] = C[0] / t * -radius + G1Pos2[0];
			contact->pos[1] = C[1] / t * -radius + G1Pos2[1];
			contact->pos[2] = C[2] / t * -radius + G1Pos2[2];
			contact->normal[0] = (contact->pos[0] - SpherePos[0]) / (radius2 - contact->depth);
			contact->normal[1] = (contact->pos[1] - SpherePos[1]) / (radius2 - contact->depth);
			contact->normal[2] = (contact->pos[2] - SpherePos[2]) / (radius2 - contact->depth);
			contact->g1 = Cylinder;
			contact->g2 = Sphere;
			GeomCount++;
			return GeomCount;
		}
	}
	else if( (radius - t) <= s && (radius - t) <= (length - s) )
	{
		// 1. collsision
		if(t > (radius2 + toleranz))
		{
			// cylinder-axis is outside the sphere
			contact->depth = (radius2 + radius) - t;
			if(contact->depth < 0)
			{
				// should never happen, but just for safeness
				return 0;
			}
			else
			{
				C[0] /= t;
				C[1] /= t;
				C[2] /= t;
				contact->pos[0] = C[0] * radius2 + SpherePos[0];
				contact->pos[1] = C[1] * radius2 + SpherePos[1];
				contact->pos[2] = C[2] * radius2 + SpherePos[2];
				contact->normal[0] = C[0];
				contact->normal[1] = C[1];
				contact->normal[2] = C[2];
				contact->g1 = Cylinder;
				contact->g2 = Sphere;
				GeomCount++;
				return GeomCount;
			}
		}
		else
		{
			// cylinder-axis is outside of the sphere
			contact->depth = (radius2 + radius) - t;
			if(contact->depth < 0)
			{
				// should never happen, but just for safeness
				return 0;
			}
			else
			{
				contact->pos[0] = C[0] + SpherePos[0];
				contact->pos[1] = C[1] + SpherePos[1];
				contact->pos[2] = C[2] + SpherePos[2];
				contact->normal[0] = C[0] / t;
				contact->normal[1] = C[1] / t;
				contact->normal[2] = C[2] / t;
				contact->g1 = Cylinder;
				contact->g2 = Sphere;
				GeomCount++;
				return GeomCount;
			}
		}
	}
	else
	{
		// 2. collision
		if(s <= (length * dReal(0.5)) )
		{
			// collsision with the first disc
			contact->depth = s + radius2;
			if(contact->depth < 0)
			{
				// should never happen, but just for safeness
				return 0;
			}
			contact->pos[0] = radius2 * vDir1[0] + SpherePos[0];
			contact->pos[1] = radius2 * vDir1[1] + SpherePos[1];
			contact->pos[2] = radius2 * vDir1[2] + SpherePos[2];
			contact->normal[0] = vDir1[0];
			contact->normal[1] = vDir1[1];
			contact->normal[2] = vDir1[2];
			contact->g1 = Cylinder;
			contact->g2 = Sphere;
			GeomCount++;
			return GeomCount;
		}
		else
		{
			// collsision with the second disc
			contact->depth = (radius2 + length - s);
			if(contact->depth < 0)
			{
				// should never happen, but just for safeness
				return 0;
			}
			contact->pos[0] = radius2 * -vDir1[0] + SpherePos[0];
			contact->pos[1] = radius2 * -vDir1[1] + SpherePos[1];
			contact->pos[2] = radius2 * -vDir1[2] + SpherePos[2];
			contact->normal[0] = -vDir1[0];
			contact->normal[1] = -vDir1[1];
			contact->normal[2] = -vDir1[2];
			contact->g1 = Cylinder;
			contact->g2 = Sphere;
			GeomCount++;
			return GeomCount;
		}
	}
	return GeomCount;
}
<commit_msg>Cosmetic: Cosmetic: changed some inlined code to ODE utility function calls<commit_after>/*************************************************************************
*                                                                       *
* Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
* All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
*                                                                       *
* This library is free software; you can redistribute it and/or         *
* modify it under the terms of EITHER:                                  *
*   (1) The GNU Lesser General Public License as published by the Free  *
*       Software Foundation; either version 2.1 of the License, or (at  *
*       your option) any later version. The text of the GNU Lesser      *
*       General Public License is included with this library in the     *
*       file LICENSE.TXT.                                               *
*   (2) The BSD-style license that is included with this library in     *
*       the file LICENSE-BSD.TXT.                                       *
*                                                                       *
* This library is distributed in the hope that it will be useful,       *
* but WITHOUT ANY WARRANTY; without even the implied warranty of        *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
* LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
*                                                                       *
*************************************************************************/

/*******************************************************************
 *                                                                 *
 * cylinder-sphere collider by Christoph Beyer (boernerb@web.de)   *
 *                                                                 *
 * In Cylinder/Sphere-collisions, there are three possibilies:     *
 * 1. collision with the cylinder's nappe                          *
 * 2. collision with one of the cylinder's disc                    *
 * 3. collision with one of the disc's border                      *
 *                                                                 *
 * This collider computes two distances (s, t) and based on them,  *
 * it decides, which collision we have.                            *
 * This collider always generates 1 (or 0, if we have no collison) *
 * contacts.                                                       *
 * It is able to "separate" cylinder and sphere in all             *
 * configurations, but it never pays attention to velocity.        *
 * So, in extrem situations, "tunneling-effect" is possible.       *
 *                                                                 *
 *******************************************************************/

#include <ode/collision.h>
#include <ode/matrix.h>
#include <ode/rotation.h>
#include <ode/odemath.h>
#include <ode/objects.h>
#include "collision_kernel.h"	// for dxGeom
#include "collision_util.h"

int dCollideCylinderSphere(dxGeom* Cylinder, dxGeom* Sphere,
                           int flags, dContactGeom *contact, int skip)
{
	dIASSERT (skip >= (int)sizeof(dContactGeom));
	dIASSERT (Cylinder->type == dCylinderClass);
	dIASSERT (Sphere->type == dSphereClass);
	dIASSERT ((flags & NUMC_MASK) >= 1);

	unsigned char* pContactData = (unsigned char*)contact;
	int GeomCount = 0; // count of used contacts

#ifdef dSINGLE
	const dReal toleranz = 0.0001f;
#endif
#ifdef dDOUBLE
	const dReal toleranz = 0.0000001;
#endif

	// get the data from the geoms
	dReal radius, length;
	dGeomCylinderGetParams(Cylinder, &radius, &length);
    dVector3 &cylpos = Cylinder->final_posr->pos;
	const dReal* pfRot1 = dGeomGetRotation(Cylinder);

	dReal radius2;
	radius2 = dGeomSphereGetRadius(Sphere);
	const dReal* SpherePos = dGeomGetPosition(Sphere);

	// G1Pos1 is the middle of the first disc
	// G1Pos2 is the middle of the second disc
	// vDir1 is the unit direction of the cylinderaxis
	dVector3 G1Pos1, G1Pos2, vDir1;
	vDir1[0] = Cylinder->final_posr->R[2];
	vDir1[1] = Cylinder->final_posr->R[6];
	vDir1[2] = Cylinder->final_posr->R[10];

	dReal s;
	s = length * dReal(0.5); // just a precomputed factor
	G1Pos2[0] = vDir1[0] * s + cylpos[0];
	G1Pos2[1] = vDir1[1] * s + cylpos[1];
	G1Pos2[2] = vDir1[2] * s + cylpos[2];

	G1Pos1[0] = vDir1[0] * -s + cylpos[0];
	G1Pos1[1] = vDir1[1] * -s + cylpos[1];
	G1Pos1[2] = vDir1[2] * -s + cylpos[2];

	dVector3 C;
	dReal t;
	// Step 1: compute the two distances 's' and 't'
	// 's' is the distance from the first disc (in vDir1-/Zylinderaxis-direction), the disc with G1Pos1 in the middle
	s = (SpherePos[0] - G1Pos1[0]) * vDir1[0] - (G1Pos1[1] - SpherePos[1]) * vDir1[1] - (G1Pos1[2] - SpherePos[2]) * vDir1[2];
	if(s < (-radius2) || s > (length + radius2) )
	{
		// Sphere is too far away from the discs
		// no collision
		return 0;
	}

	// C is the direction from Sphere-middle to the cylinder-axis (vDir1); C is orthogonal to the cylinder-axis
	C[0] = s * vDir1[0] + G1Pos1[0] - SpherePos[0];
	C[1] = s * vDir1[1] + G1Pos1[1] - SpherePos[1];
	C[2] = s * vDir1[2] + G1Pos1[2] - SpherePos[2];
	// t is the distance from the Sphere-middle to the cylinder-axis!
	t = dVector3Length(C);
	if(t > (radius + radius2) )
	{
		// Sphere is too far away from the cylinder axis!
		// no collision
		return 0;
	}

	// decide which kind of collision we have:
	if(t > radius && (s < 0 || s > length) )
	{
		// 3. collision
		if(s <= 0)
		{
			contact->depth = radius2 - dReal(sqrt( (s) * (s) + (t - radius) * (t - radius) ));
			if(contact->depth < 0)
			{
				// no collision!
				return 0;
			}
			contact->pos[0] = C[0] / t * -radius + G1Pos1[0];
			contact->pos[1] = C[1] / t * -radius + G1Pos1[1];
			contact->pos[2] = C[2] / t * -radius + G1Pos1[2];
			contact->normal[0] = (contact->pos[0] - SpherePos[0]) / (radius2 - contact->depth);
			contact->normal[1] = (contact->pos[1] - SpherePos[1]) / (radius2 - contact->depth);
			contact->normal[2] = (contact->pos[2] - SpherePos[2]) / (radius2 - contact->depth);
			contact->g1 = Cylinder;
			contact->g2 = Sphere;
			GeomCount++;
			return GeomCount;
		}
		else
		{
			// now s is bigger than length here!
			contact->depth = radius2 - dReal(sqrt( (s - length) * (s - length) + (t - radius) * (t - radius) ));
			if(contact->depth < 0)
			{
				// no collision!
				return 0;
			}
			contact->pos[0] = C[0] / t * -radius + G1Pos2[0];
			contact->pos[1] = C[1] / t * -radius + G1Pos2[1];
			contact->pos[2] = C[2] / t * -radius + G1Pos2[2];
			contact->normal[0] = (contact->pos[0] - SpherePos[0]) / (radius2 - contact->depth);
			contact->normal[1] = (contact->pos[1] - SpherePos[1]) / (radius2 - contact->depth);
			contact->normal[2] = (contact->pos[2] - SpherePos[2]) / (radius2 - contact->depth);
			contact->g1 = Cylinder;
			contact->g2 = Sphere;
			GeomCount++;
			return GeomCount;
		}
	}
	else if( (radius - t) <= s && (radius - t) <= (length - s) )
	{
		// 1. collsision
		if(t > (radius2 + toleranz))
		{
			// cylinder-axis is outside the sphere
			contact->depth = (radius2 + radius) - t;
			if(contact->depth < 0)
			{
				// should never happen, but just for safeness
				return 0;
			}
			else
			{
				C[0] /= t;
				C[1] /= t;
				C[2] /= t;
				contact->pos[0] = C[0] * radius2 + SpherePos[0];
				contact->pos[1] = C[1] * radius2 + SpherePos[1];
				contact->pos[2] = C[2] * radius2 + SpherePos[2];
				contact->normal[0] = C[0];
				contact->normal[1] = C[1];
				contact->normal[2] = C[2];
				contact->g1 = Cylinder;
				contact->g2 = Sphere;
				GeomCount++;
				return GeomCount;
			}
		}
		else
		{
			// cylinder-axis is outside of the sphere
			contact->depth = (radius2 + radius) - t;
			if(contact->depth < 0)
			{
				// should never happen, but just for safeness
				return 0;
			}
			else
			{
				contact->pos[0] = C[0] + SpherePos[0];
				contact->pos[1] = C[1] + SpherePos[1];
				contact->pos[2] = C[2] + SpherePos[2];
				contact->normal[0] = C[0] / t;
				contact->normal[1] = C[1] / t;
				contact->normal[2] = C[2] / t;
				contact->g1 = Cylinder;
				contact->g2 = Sphere;
				GeomCount++;
				return GeomCount;
			}
		}
	}
	else
	{
		// 2. collision
		if(s <= (length * dReal(0.5)) )
		{
			// collsision with the first disc
			contact->depth = s + radius2;
			if(contact->depth < 0)
			{
				// should never happen, but just for safeness
				return 0;
			}
			contact->pos[0] = radius2 * vDir1[0] + SpherePos[0];
			contact->pos[1] = radius2 * vDir1[1] + SpherePos[1];
			contact->pos[2] = radius2 * vDir1[2] + SpherePos[2];
			contact->normal[0] = vDir1[0];
			contact->normal[1] = vDir1[1];
			contact->normal[2] = vDir1[2];
			contact->g1 = Cylinder;
			contact->g2 = Sphere;
			GeomCount++;
			return GeomCount;
		}
		else
		{
			// collsision with the second disc
			contact->depth = (radius2 + length - s);
			if(contact->depth < 0)
			{
				// should never happen, but just for safeness
				return 0;
			}
			contact->pos[0] = radius2 * -vDir1[0] + SpherePos[0];
			contact->pos[1] = radius2 * -vDir1[1] + SpherePos[1];
			contact->pos[2] = radius2 * -vDir1[2] + SpherePos[2];
			contact->normal[0] = -vDir1[0];
			contact->normal[1] = -vDir1[1];
			contact->normal[2] = -vDir1[2];
			contact->g1 = Cylinder;
			contact->g2 = Sphere;
			GeomCount++;
			return GeomCount;
		}
	}
	return GeomCount;
}
<|endoftext|>


<commit_before>#include <FreeRTOS.h>
#include <task.h>

#include <xXx/os/arduinotask.hpp>
#include <xXx/utils/logging.hpp>

#include "gpio.hpp"
#include "radiotask.hpp"

using namespace xXx;

static char buffer[] = "Lorem ipsum dolor sit amet, con";

RadioTask::RadioTask(nRF24L01P &nRF24L01_1, nRF24L01P &nRF24L01_2)
    : ArduinoTask(1024, 1), _nRF24L01_1(nRF24L01_1), _nRF24L01_2(nRF24L01_2),
      _txQueue{Queue<uint8_t>(256)}, _rxQueue0{Queue<uint8_t>(256)} {}

RadioTask::~RadioTask() {}

void RadioTask::setup() {
    vTaskDelay(100 / portTICK_PERIOD_MS);

    _nRF24L01_1.init();
    _nRF24L01_2.init();

    _nRF24L01_1.powerUp();
    _nRF24L01_2.powerUp();

    vTaskDelay(5 / portTICK_PERIOD_MS);

    _nRF24L01_1.configureTxPipe(_txQueue);
    _nRF24L01_2.configureRxPipe(0, _rxQueue0);

    _nRF24L01_1.enterTxMode();
    _nRF24L01_2.enterRxMode();
}

void RadioTask::loop() {
    LOG("StackHighWaterMark: %d", uxTaskGetStackHighWaterMark(_handle));

    _nRF24L01_1.send((uint8_t *)buffer, sizeof(buffer));

    // _nRF24L01_1.update();
    // _nRF24L01_2.update();

    int foo = _rxQueue0.usedSlots();

    if (foo) {
        uint8_t buffer[foo];

        for (int i = 0; i < foo; ++i) {
            _rxQueue0.dequeue(buffer[i]);
        }

        LOG("%.*s", foo, buffer);
    }

    vTaskDelay(100 / portTICK_PERIOD_MS);
}
<commit_msg>Transmit counter detect package loss<commit_after>#include <FreeRTOS.h>
#include <task.h>

#include <xXx/os/arduinotask.hpp>
#include <xXx/utils/logging.hpp>

#include "gpio.hpp"
#include "radiotask.hpp"

using namespace xXx;

static uint8_t buffer[32];
static uint32_t counter = 0;

RadioTask::RadioTask(nRF24L01P &nRF24L01_1, nRF24L01P &nRF24L01_2)
    : ArduinoTask(1024, 1), _nRF24L01_1(nRF24L01_1), _nRF24L01_2(nRF24L01_2),
      _txQueue{Queue<uint8_t>(256)}, _rxQueue0{Queue<uint8_t>(256)} {}

RadioTask::~RadioTask() {}

void RadioTask::setup() {
    vTaskDelay(100 / portTICK_PERIOD_MS);

    _nRF24L01_1.init();
    _nRF24L01_2.init();

    _nRF24L01_1.powerUp();
    _nRF24L01_2.powerUp();

    vTaskDelay(5 / portTICK_PERIOD_MS);

    _nRF24L01_1.configureTxPipe(_txQueue);
    _nRF24L01_2.configureRxPipe(0, _rxQueue0);

    _nRF24L01_1.enterTxMode();
    _nRF24L01_2.enterRxMode();
}

void RadioTask::loop() {
    // LOG("StackHighWaterMark: %d", uxTaskGetStackHighWaterMark(_handle));

    uint8_t length = snprintf((char *)buffer, sizeof(buffer), "%d", counter++);

    if (_txQueue.freeSlots() >= length) {
        for (int i = 0; i < length; ++i) {
            _txQueue.enqueue(buffer[i]);
        }
    }

    int foo = _rxQueue0.usedSlots();

    if (foo) {
        uint8_t buffer[foo];

        for (int i = 0; i < foo; ++i) {
            _rxQueue0.dequeue(buffer[i]);
        }

        LOG("%.*s", foo, buffer);
    }

    _nRF24L01_1.update();
    _nRF24L01_2.update();

    vTaskDelay(100 / portTICK_PERIOD_MS);
}
<|endoftext|>


<commit_before>
//(*InternalHeaders(AnalysisLogs)
#include <wx/intl.h>
#include <wx/string.h>
//*)

#include "AnalysisLogs.h"
extern double Withstanded;
double actualTimeline=0;

extern DamageAnalysisFrame *Frame;

extern heroUnit *heroTemp;
extern heroUnit *heroAttTemp;

extern hero_Defender Defender;
extern hero_Attacker Attacker;

double InDamageNoReductPerCycleTMP, InDamagePerCycleTMP, InDamagePerCycleCrit, InDamageMagicPerCycleTMP, InDamagePrev, InDamageBase, InDamage, InDamageRaw, InDamageMagic, InDamageNoReduct, aps, singleAttackTime, currAps, currSingleAttackTime, InDamagePerCycle, InDamageMagicPerCycle, InDamageNoReductPerCycle;
double timeElapsed, timeLethalStrike;
unsigned totalHitsActual, lethalHit, WhiteDmg;
int DefendercurrMaxHP;

int DoDoubleHit, GreenDmg;

std::pair<int,int> *critTMPPair;

extern std::vector<double> magicResistanceBuffer;
extern std::vector<basic_effect *> attackEffects;
extern std::vector<basic_effect *> defenceEffects;
extern std::vector<effect_critical_damage *> critEffects;
extern std::vector<effect_block_damage *> shieldBlockEffects;

//(*IdInit(AnalysisLogs)
const long AnalysisLogs::ID_RICHTEXTCTRL1 = wxNewId();
const long AnalysisLogs::ID_BUTTON1 = wxNewId();
const long AnalysisLogs::ID_PANEL1 = wxNewId();
//*)

BEGIN_EVENT_TABLE(AnalysisLogs,wxFrame)
	//(*EventTable(AnalysisLogs)
	//*)
END_EVENT_TABLE()

AnalysisLogs::AnalysisLogs(wxWindow* parent,wxWindowID id,const wxPoint& pos,const wxSize& size)
{
	//(*Initialize(AnalysisLogs)
	wxFlexGridSizer* FlexGridSizer1;

	Create(parent, id, _("Analysis log"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE|wxFRAME_TOOL_WINDOW|wxNO_BORDER, _T("id"));
	SetClientSize(wxSize(350,350));
	Move(wxDefaultPosition);
	SetMinSize(wxSize(180,180));
	Panel1 = new wxPanel(this, ID_PANEL1, wxPoint(256,328), wxDefaultSize, wxTAB_TRAVERSAL, _T("ID_PANEL1"));
	FlexGridSizer1 = new wxFlexGridSizer(2, 0, 0, 0);
	FlexGridSizer1->AddGrowableCol(0);
	FlexGridSizer1->AddGrowableRow(0);
	RichTextCtrl1 = new wxRichTextCtrl(Panel1, ID_RICHTEXTCTRL1, _("Initializing data..."), wxDefaultPosition, wxDefaultSize, wxRE_MULTILINE|wxNO_BORDER|wxVSCROLL, wxDefaultValidator, _T("ID_RICHTEXTCTRL1"));
	wxRichTextAttr rchtxtAttr_1;
	rchtxtAttr_1.SetBulletStyle(wxTEXT_ATTR_BULLET_STYLE_ALIGN_LEFT);
	RichTextCtrl1->SetMinSize(wxSize(100,100));
	RichTextCtrl1->SetMaxSize(wxSize(0,0));
	FlexGridSizer1->Add(RichTextCtrl1, 2, wxEXPAND|wxALIGN_LEFT|wxALIGN_TOP, 1);
	Button1 = new wxButton(Panel1, ID_BUTTON1, _("Close"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON1"));
	FlexGridSizer1->Add(Button1, 1, wxALIGN_RIGHT|wxALIGN_BOTTOM, 0);
	Panel1->SetSizer(FlexGridSizer1);
	FlexGridSizer1->Fit(Panel1);
	FlexGridSizer1->SetSizeHints(Panel1);

	Connect(ID_BUTTON1,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&AnalysisLogs::OnButton1Click);
	Connect(wxID_ANY,wxEVT_CLOSE_WINDOW,(wxObjectEventFunction)&AnalysisLogs::OnClose);
	//*)
}

AnalysisLogs::~AnalysisLogs()
{
	//(*Destroy(AnalysisLogs)
	//*)
}

void AnalysisLogs::RunAnalysis()
{
RichTextCtrl1->Clear();
DamageLogFill((void *)RichTextCtrl1);
Show();
Restore();
Raise();
}

void AnalysisLogs::DamageLogFill(void *myLogTable)
{
wxRichTextCtrl *richTextPtr=static_cast<wxRichTextCtrl *>(myLogTable);
unsigned hitsI;
int totalhits;
timeElapsed=0;
timeLethalStrike=0;
double hitsD;
double tmpHPRegen, tmpMPRegen, MPBuffer, HPBuffer;
MPBuffer=0;
HPBuffer=0;
/**
Before we are able to start the analyze process, we are supposed to create both hero objects, fill their
stats if present, and cause armor\IAS\Level precalculations. All effects are highly based on stats being
self-aware and in full self control. Thats why heroData.cpp contains all the methods you may need to
control the stat setting processes. Use methods instead of changing stat variables by hand, that is
vital.
*/
Defender.fillFromUI();
Attacker.fillFromUI();
hero_Attacker tmpAttacker;
tmpAttacker=Attacker;
hero_Defender tmpDefender;
tmpDefender=Defender;
critEffects.clear();
critEffects.reserve(20);
shieldBlockEffects.clear();
shieldBlockEffects.reserve(20);
magicResistanceBuffer.clear();
magicResistanceBuffer.reserve(5);
// ___ Initializing HP and MP data
magicResistanceBuffer.push_back(Defender.magicResist);
richTextPtr->AppendText("Attacker's base damage: ");
WhiteDmg=wxAtoi(Frame->WhiteDamageInput->GetValue());
richTextPtr->AppendText(Frame->WhiteDamageInput->GetValue());
richTextPtr->AppendText("\nAttacker's bonus damage: ");
GreenDmg=wxAtoi(Frame->GreenDamageInput->GetValue());
richTextPtr->AppendText(Frame->GreenDamageInput->GetValue());
recalculateAttackSpeed();
InDamage=(double)WhiteDmg+GreenDmg;
InDamageMagicPerCycle=0;
InDamageNoReductPerCycle=0;
InDamagePerCycle=0;
InDamagePerCycleCrit=0;
//Find and destroy all the temporary effects, produced by master effects.
for (int i=attackEffects.size()-1;i!=-1;i--)
{
    if (attackEffects.at(i)->temporary==true)
    {
        delete attackEffects.at(i);
        attackEffects.erase(attackEffects.begin()+i);
    }
}
for (int i=defenceEffects.size()-1;i!=-1;i--)
{
    if (defenceEffects.at(i)->temporary==true)
    {
        delete defenceEffects.at(i);
        defenceEffects.erase(defenceEffects.begin()+i);
    }
}
for (int R=minRanks;R<=maxRanks;R++)
{
    for (unsigned f=0;f<attackEffects.size();f++)
    {
        if (!attackEffects[f]->disabled && attackEffects[f]->initRank==R)
        {
            attackEffects[f]->Init();
        }
    }
}
for (int R=minRanks;R<=maxRanks;R++)
{
    for (unsigned f=0;f<defenceEffects.size();f++)
    {
        if (!defenceEffects[f]->disabled && defenceEffects[f]->initRank==R)
        {
            defenceEffects[f]->Init();
        }
    }
}
richTextPtr->AppendText("\nAttacker's base attack time: ");
richTextPtr->AppendText(wxString::FromDouble(Attacker.BATD,2));
richTextPtr->AppendText("\nAttacker's IAS: ");
richTextPtr->AppendText(wxString::FromDouble(Attacker.IAS,0));
// ___ Attack speed+BAT evaluation
richTextPtr->AppendText(" (");
richTextPtr->AppendText(wxString::FromDouble(singleAttackTime,2));
richTextPtr->AppendText(" per second)");
totalhits=(double)aps*(wxAtoi(Frame->WithstandInput->GetValue()));
richTextPtr->AppendText("\nTotal hits: ");
richTextPtr->AppendText(wxString::Format(wxT("%i"),totalhits));
richTextPtr->BeginTextColour(wxColour(255, 0, 0));
richTextPtr->WriteText("\nAll data is approximate.");
richTextPtr->EndTextColour();
richTextPtr->WriteText(" ");
richTextPtr->AppendText("\nDamage per hit: ");
richTextPtr->AppendText(wxString::FromDouble(InDamage,0));
hitsD=InDamage*aps;
hitsI=wxAtoi(Frame->WithstandInput->GetValue());
richTextPtr->AppendText("\nDamage per second: ");
richTextPtr->AppendText(wxString::FromDouble(hitsD,0));
richTextPtr->WriteText("\n");
// ___ Double attack check
// ___ Attack emulation cycle
Withstanded=wxAtof(Frame->WithstandInput->GetValue());
InDamage=0;
InDamageMagic=0;
InDamageNoReduct=0;
InDamageRaw=0;
InDamagePrev=0;
totalHitsActual=0;
actualTimeline=singleAttackTime;
lethalHit=0;
while (actualTimeline<=Withstanded)
{
    recalculateAttackSpeed();
    currAps=aps;
    DefendercurrMaxHP=Defender.maxHP;
    currSingleAttackTime=singleAttackTime;
    InDamageBase=WhiteDmg+GreenDmg;
    InDamagePerCycle=InDamageBase;
    InDamageRaw=InDamageRaw+InDamagePerCycle;
    InDamageMagicPerCycle=0;
    InDamageNoReductPerCycle=0; // ___ Necrophos aura can go there as an effect.
    DoDoubleHit=0;
    int critOnlyOnce=0;
    for (int R=minRanks;R<=maxRanks;R++)
    {
        for (unsigned f=0;f<attackEffects.size();f++)
        {
            if (R==-2 && !critEffects.empty() && critOnlyOnce!=1)
            {
                critOnlyOnce=1;
                std::sort(critEffects.begin(),critEffects.end(),isLessThanDamage);
                TMPDamageSave();
                calcCrits(critEffects);
                TMPDamageLoad();
            }
            if (!attackEffects[f]->disabled && !attackEffects[f]->externalContinueCycle && attackEffects[f]->initRank==R)
            {
                TMPDamageSave();
                attackEffects[f]->Continue();
                TMPDamageLoad();
            }
        }
    }
    int blockOnlyOnce=0;
    for (int R=minRanks;R<=maxRanks;R++)
    {
        if (R==0 && !shieldBlockEffects.empty() && blockOnlyOnce!=1)
        {
            blockOnlyOnce=1;
            std::sort(shieldBlockEffects.begin(),shieldBlockEffects.end(),isLessThanBlock);
            calcShieldBlock(shieldBlockEffects);
        }
        for (unsigned f=0;f<defenceEffects.size();f++)
        {
            if (!defenceEffects[f]->disabled && !defenceEffects[f]->externalContinueCycle && defenceEffects[f]->initRank==R)
            {
                TMPDamageSave();
                defenceEffects[f]->Continue();
                TMPDamageLoad();
            }
        }
    }
    for (;DoDoubleHit--;)
    {
        /** During double hit emulation, all the data should be "refreshed" and relaunched,
        except the time-wise ones.
        */
        ApplyResists();
        FlushDamage();
        recalculateAttackSpeed();
        InDamageBase=WhiteDmg+GreenDmg;
        InDamagePerCycle=InDamageBase;
        InDamageRaw=InDamageRaw+InDamagePerCycle;
        InDamageMagicPerCycle=0;
        InDamageNoReductPerCycle=0; // ___ Necrophos aura can go there as an effect.
        critOnlyOnce=0;
        for (int R=minRanks;R<=maxRanks;R++)
        {
            for (unsigned j=0;j<attackEffects.size();j++)
            {
                if (R==-2 && !critEffects.empty() && critOnlyOnce!=1)
                {
                    critOnlyOnce=1;
                    std::sort(critEffects.begin(),critEffects.end(),isLessThanDamage);
                    TMPDamageSave();
                    calcCrits(critEffects);
                    TMPDamageLoad();
                }
                if (!attackEffects[j]->disabled && !attackEffects[j]->externalContinueCycle && attackEffects[j]->initRank==R)
                {
                    TMPDamageSave();
                    attackEffects[j]->DoDoubleAttack();
                    TMPDamageLoad();
                }
            }
        }
        blockOnlyOnce=0;
        for (int R=minRanks;R<=maxRanks;R++)
        {
            if (R==0 && !shieldBlockEffects.empty() && blockOnlyOnce!=1)
            {
                blockOnlyOnce=1;
                std::sort(shieldBlockEffects.begin(),shieldBlockEffects.end(),isLessThanBlock);
                calcShieldBlock(shieldBlockEffects);
            }
            for (unsigned j=0;j<defenceEffects.size();j++)
            {
                if (!defenceEffects[j]->disabled && !attackEffects[j]->externalContinueCycle && defenceEffects[j]->initRank==R)
                {
                    TMPDamageSave();
                    defenceEffects[j]->DoDoubleAttack();
                    TMPDamageLoad();
                }
            }
        }
    totalHitsActual++;
    }
    actualTimeline=actualTimeline+singleAttackTime;
    ApplyResists();
    FlushDamage();
    totalHitsActual++;
    // Health regeneration between hits
    if (Defender.HPRegen)
    {
        HPBuffer=HPBuffer+currAps*Defender.HPRegen;
        if ((Defender.HP+currAps*Defender.HPRegen)>=Defender.maxHP)
        {
            Defender.HP=Defender.maxHP;
        }
        else
        {
            Defender.HP=Defender.HP+currAps*Defender.HPRegen;
        }
    }
    // Mana regeneration between hits
    if (Defender.MPRegen || Defender.MPRegenBonus)
    {
        tmpMPRegen=(((Defender.MPRegen!=0) ? Defender.MPRegen*(1+Defender.MPRegenMultiplier) : 0)+Defender.MPRegenBonus)*currAps;
        MPBuffer=MPBuffer+tmpMPRegen;
        tmpMPRegen=trunc(MPBuffer);
        MPBuffer=MPBuffer-tmpMPRegen;
        Defender.MP=Defender.MP+tmpMPRegen;
        if (Defender.MP>Defender.maxMP)
        {
            Defender.MP=Defender.maxMP;
        }
    }
    timeElapsed=timeElapsed+currSingleAttackTime;
}
if (Defender.armor!=0)
{
// Armor reduction evaluation
    richTextPtr->AppendText("Physical damage reduction: ");
    richTextPtr->AppendText(wxString::FromDouble(getArmorReduction(),0));
    richTextPtr->AppendText("%");
}
else
{
    richTextPtr->AppendText("No physical damage reduction.");
}
if (Defender.HP<=0)
{
richTextPtr->BeginTextColour(wxColour(255, 0, 0));
richTextPtr->WriteText("\nLethal hit:");
richTextPtr->EndTextColour();
richTextPtr->WriteText(" ");
    if (lethalHit)
    {
    richTextPtr->AppendText(wxString::Format(wxT("%i"),lethalHit));
    }
    else
    {
    richTextPtr->AppendText(wxString::Format(wxT("%i"),totalHitsActual));
    }
}
richTextPtr->WriteText(" (at ");
richTextPtr->AppendText(wxString::FromDouble(timeLethalStrike,2));
richTextPtr->WriteText(" seconds)");
if (totalHitsActual>=2000 || Attacker.IAS>=1000)
{
richTextPtr->BeginTextColour(wxColour(255, 0, 0));
richTextPtr->WriteText("\nAttack rate limit is reached. Expected precision level is not guaranteed.");
richTextPtr->EndTextColour();
richTextPtr->WriteText(" ");
}
richTextPtr->AppendText("\nActual hits done: ");
richTextPtr->AppendText(wxString::Format(wxT("%i"),totalHitsActual));
richTextPtr->AppendText("\nRaw damage withstanded: ");
richTextPtr->AppendText(wxString::FromDouble(InDamageRaw,0));
richTextPtr->AppendText("\nActual damage withstanded: ");
richTextPtr->AppendText(wxString::FromDouble(InDamage+InDamageMagic+InDamageNoReduct,0));
richTextPtr->AppendText(" (during ");
richTextPtr->AppendText(wxString::FromDouble(timeElapsed,2));
richTextPtr->AppendText(" seconds)");
if (Defender.HP<0)
{
richTextPtr->AppendText("\nHealth lost after lethal hit: ");
richTextPtr->AppendText(wxString::FromDouble(Defender.HP,0));
}
else
{
richTextPtr->AppendText("\nHealth left: ");
richTextPtr->AppendText(wxString::FromDouble(Defender.HP,0));
}
richTextPtr->AppendText("\nMana left: ");
richTextPtr->AppendText(wxString::FromDouble(Defender.MP,0));
//Finalization. Post-analyze processes.
//Main objects recover from temp.
Attacker=tmpAttacker;
Defender=tmpDefender;
return;
}

void AnalysisLogs::TMPDamageSave()
{
InDamagePerCycleTMP=InDamagePerCycle;
InDamageMagicPerCycleTMP=InDamageMagicPerCycle;
InDamageNoReductPerCycleTMP=InDamageNoReductPerCycle;
return;
}

void AnalysisLogs::TMPDamageLoad()
{
//Physical damage
if (InDamagePerCycleTMP<InDamagePerCycle)
{
    InDamageRaw=InDamageRaw+(InDamagePerCycle-InDamagePerCycleTMP);
}
else if (InDamagePerCycleTMP>InDamagePerCycle)
{
    InDamageRaw=InDamageRaw-(InDamagePerCycleTMP-InDamagePerCycle);
}
//Magical damage
if (InDamageMagicPerCycleTMP<InDamageMagicPerCycle)
{
    InDamageRaw=InDamageRaw+(InDamageMagicPerCycle-InDamageMagicPerCycleTMP);
}
else if (InDamageMagicPerCycleTMP>InDamageMagicPerCycle)
{
    InDamageRaw=InDamageRaw-(InDamagePerCycleTMP-InDamageMagicPerCycle);
}
//Pure damage
if (InDamageNoReductPerCycleTMP<InDamageNoReductPerCycle)
{
    InDamageRaw=InDamageRaw+(InDamageNoReductPerCycle-InDamageNoReductPerCycleTMP);
}
else if (InDamageNoReductPerCycleTMP>InDamageNoReductPerCycle)
{
    InDamageRaw=InDamageRaw-(InDamageNoReductPerCycleTMP-InDamageNoReductPerCycle);
}
return;
}

void AnalysisLogs::FlushDamage()
{
// ___ Flush damage to InDamages
InDamageNoReduct=InDamageNoReduct+InDamageNoReductPerCycle;
InDamage=InDamage+InDamagePerCycle;
InDamageMagic=InDamageMagic+InDamageMagicPerCycle;
// ___ Check if lethal.
if (lethalHit==0)
{
    if (Defender.HP<=0)
    {
        lethalHit=totalHitsActual;
        timeLethalStrike=timeElapsed;
    }
}
Defender.HP=Defender.HP-(InDamage+InDamageMagic+InDamageNoReduct-InDamagePrev);
InDamagePrev=InDamage+InDamageMagic+InDamageNoReduct;
}

void AnalysisLogs::ApplyResists()
{
    // ___ Physical damage filter.
    if (Defender.armor>0)
    {
        InDamagePerCycle=(InDamagePerCycle/100)*(100-getArmorReduction());
    }
    else if (Defender.armor<0)
    {
        InDamagePerCycle=(InDamagePerCycle/100)*(100+abs(getArmorReduction()));
    }
    // ___ Magical damage filter.
    for (unsigned i=0;i<magicResistanceBuffer.size();i++)
    {
        InDamageMagicPerCycle=InDamageMagicPerCycle/100*(100-magicResistanceBuffer.at(i));
    }
}

void AnalysisLogs::OnClose(wxCloseEvent& event)
{
    Hide();
}

void AnalysisLogs::OnButton1Click(wxCommandEvent& event)
{
    Hide();
}

void AnalysisLogs::OnRichTextCtrl1Text(wxCommandEvent& event)
{
    event.Skip();
}

// ___ Critical hit calculations
void AnalysisLogs::calcCrits(std::vector<effect_critical_damage *> &myVector)
{
    std::pair<int,int> *critTMPPair;
    critTMPPair=new std::pair<int,int> [myVector.size()];   //creating the array
    // ___ Creating temporary array to restore original effects afterwards.
    for (int i=0;i<myVector.size();i++)
    {
        critTMPPair[i] = std::make_pair(myVector.at(i)->chance,myVector.at(i)->damage);
    }
    // ___ Socalculating crits with the same damage.
    for (int h=0;h<myVector.size();h++)
    {
        for (int z=0;z<myVector.size();z++)
        {
            if (z!=h)
            {
                if (myVector.at(h)->damage==myVector.at(z)->damage)
                {
                    if ((myVector.at(h)->chance+myVector.at(z)->chance)<=100)
                    {
                        myVector.at(h)->chance=myVector.at(h)->chance+myVector.at(z)->chance;
                    }
                    else
                    {
                        myVector.at(h)->chance=100;
                    }
                    myVector.at(z)->chance=0;
                }
            }
        }
    }
    InDamagePerCycleCrit=InDamagePerCycle;
    double currChanceOldAccum=0;
    double currChanceAccum=0;
    for (int critLVL=0;critLVL<myVector.size();critLVL++)
    {
        if (currChanceAccum!=100)
        {
            currChanceOldAccum=currChanceAccum;
            currChanceAccum=currChanceAccum+(100-currChanceAccum)/100*(double)myVector.at(critLVL)->chance;
            // ___ To calculate damage, we need to get it's part in main chance window:
            // ___ For effect with chance 20% being first in hierarchy, we'll have 80% left for other effects to use: 100%-20%=80%
            // ___ This way, we get the chance window left for other effects to utilize.
            // ___ Lets take 50% chance to be next in hierarchy, and thats how it's chance window would be calculated: 80%/100*50%=40%.
            // ___ Only 40% of that 50% effect could have a part in calculation.
            // ___ Next effect of 90% will have a part of 36%, leaving 4% for other effects with lower hierarchy to utilize.
            // ___ All crits with the same damage are stackable by percentage additively. So, if you had +50% and +50%, you'll have 100% as outcome.
            InDamagePerCycle=InDamagePerCycle+((InDamagePerCycleCrit/100*(double)myVector.at(critLVL)->damage-InDamagePerCycleCrit)/100*(currChanceAccum-currChanceOldAccum));
            if (InDamagePerCycle<0)
            {
                InDamagePerCycle=0;
            }
        }
    }
    // ___ Restoring original effect data.
    for (int i=0;i<myVector.size();i++)
    {
        myVector.at(i)->chance=critTMPPair[i].first;
        myVector.at(i)->damage=critTMPPair[i].second;
    }
    delete[] critTMPPair;
    return;
}

// ___ Block calculations
void AnalysisLogs::calcShieldBlock(std::vector<effect_block_damage *> &myVector)
{
    double currChanceOldAccum=0;
    double currChanceAccum=0;
    for (int blockLVL=0;blockLVL<myVector.size();blockLVL++)
    {
        if (currChanceAccum!=100)
        {
            currChanceOldAccum=currChanceAccum;
            currChanceAccum=currChanceAccum+(100-currChanceAccum)/100*(double)myVector.at(blockLVL)->chance;
            // ___ To calculate damage, we need to get it's part in the "Window of chances":
            // ___ For effect with chance 20% being first in hierarchy, we'll have 80% left for other effects to use: 100%-20%=80%
            // ___ TIP: As you may know, shield effects have a hierarchy. Effects with bigger "block" value are computed first.
            // ___ This way, we get the chance window left for other effects to utilize.
            // ___ Lets take 50% chance to be next in hierarchy, and thats how it's chance window would be calculated: 80%/100*50%=40%.
            // ___ Only 40% of that 50% effect could have a part in calculation.
            // ___ Next effect of 90% will have a part of 36%, leaving 4% for other effects with lower hierarchy to utilize.
            InDamagePerCycle=InDamagePerCycle-((double)myVector.at(blockLVL)->block/100*(currChanceAccum-currChanceOldAccum));
            if (InDamagePerCycle<0)
            {
                InDamagePerCycle=0;
            }
        }
    }
    return;
}

double AnalysisLogs::getArmorReduction()
{
    if (Defender.armor>0)
    {
        return ((0.06*Defender.armor)/(1+0.06*Defender.armor))*100;
    }
    else if (Defender.armor<0)
    {
        return ((0.06*Defender.armor)/(1+0.06*abs(Defender.armor)))*100;
    }
    else
    {
        return 0;
    }
}

inline void AnalysisLogs::recalculateAttackSpeed()
{
    singleAttackTime=(double)(Attacker.BATD/(Attacker.IAS/100));
    aps=1/singleAttackTime;
    return;
}
<commit_msg>Delete AnalysisLogs.cpp<commit_after><|endoftext|>


<commit_before>#include "SysControl.h"
#include "ControlsApp.h"
#include "ControlsXPad360.h"
#include "Engine.h"
#include "App.h"
#include "Engine.h"
#include "App.h"
#include "Input.h"
#include "ObjectGui.h"
#include "WidgetLabel.h"

//解决跨平台字符集兼容问题
#ifdef _WIN32
#pragma execution_character_set("utf-8")
#endif

using namespace MathLib;

class CSysControlLocal : public CSysControl
{
public:
	CSysControlLocal();
	virtual ~CSysControlLocal();

	virtual void Init();	//角色要初始化，着色器要初始化，
	virtual void Update(float ifps);
	virtual void Shutdown();

	virtual int GetState(int state);		//鼠标状态，键盘状态，人物状态，子弹状态等等。
	virtual int ClearState(int state);

	virtual float GetMouseDX();
	virtual float GetMouseDY();

	virtual void SetMouseGrab(int g);		//设置是否显示鼠标
	virtual int GetMouseGrab();			//获取鼠标状态，是显示呢还是不显示的状态。

	virtual void SetControlMode(ControlMode mode);			//控制模式
	virtual ControlMode GetControlMode() const;				//获取控制模式

private:
	void Update_Mouse(float ifps);
	void Update_Keyboard(float ifps);
	void Update_XPad360(float ifps);

	CControlsApp        *m_pControlsApp;		//控制游戏中移动
	CControlsXPad360    *m_pControlsXPad360;
	ControlMode         m_nControlMode;			//控制模式

	int                 m_nOldMouseX;			//上一个鼠标坐标X
	int                 m_nOldMouseY;			//上一个鼠标坐标Y

	CObjectGui          *m_pTest3DUI;
	CWidgetLabel        *m_pTestMessageLabel;

};

CSysControlLocal::CSysControlLocal()
{

}
CSysControlLocal::~CSysControlLocal()
{

}

void CSysControlLocal::Init()
{
	m_pControlsApp = new CControlsApp;
	m_pControlsXPad360 = new CControlsXPad360(0);

	g_Engine.pApp->SetMouseGrab(0);
	g_Engine.pApp->SetMouseShow(0);

	SetControlMode(CONTROL_KEYBORAD_MOUSE);

	m_pTest3DUI = new CObjectGui(2.0f, 1.0f, "data/core/gui/");
	m_pTest3DUI->SetMouseShow(0);
	m_pTest3DUI->SetBackground(1);
	m_pTest3DUI->SetBackgroundColor(vec4(1.0f, 0.0f, 0.0f, 1.0f));

	m_pTest3DUI->SetScreenSize(800, 400);
	m_pTest3DUI->SetControlDistance(1000.0f);
	m_pTest3DUI->CreateMaterial("gui_base");	 //show in game

	m_pTest3DUI->SetWorldTransform(Translate(0.0f, 0.0f, 2.0f) * MakeRotationFromZY(vec3(0.0f, -1.0f, 0.0f), vec3(0.0f, 0.0f, 1.0f)));

	m_pTestMessageLabel = new CWidgetLabel(m_pTest3DUI->GetGui());	//初始化文字标签
	m_pTest3DUI->GetGui()->AddChild(m_pTestMessageLabel, CGui::ALIGN_CENTER);
	m_pTestMessageLabel->SetFontColor(vec4(0.0f, 0.0f, 0.0f, 1.0f));

	m_pTestMessageLabel = new CWidgetLabel(m_pTest3DUI->GetGui());	//初始化文字标签
	m_pTest3DUI->GetGui()->AddChild(m_pTestMessageLabel, CGui::ALIGN_CENTER);
	m_pTestMessageLabel->SetFontColor(vec4(0.0f, 0.0f, 0.0f, 1.0f));

	m_pTestMessageLabel->SetFontSize(80);		//设置字体大小
	m_pTestMessageLabel->SetFontOutline(1);		//设置字体轮廓
	m_pTestMessageLabel->SetText("两个黄鹂鸣翠柳\n一行白鹭上青天\n窗含西岭千秋雪\n门泊东吴万里船");

	void CSysControlLocal::Update(float ifps)
	{
		Update_Mouse(ifps);
		Update_Keyboard(ifps);
		Update_XPad360(ifps);
	}

	m_nOldMouseX = 0;
	m_nOldMouseY = 0;
}
void CSysControlLocal::Shutdown()
{
	g_Engine.pApp->SetMouseGrab(0);
	g_Engine.pApp->SetMouseShow(0);
	delete m_pControlsApp;
	m_pControlsApp = NULL;
	delete m_pControlsXPad360;
	m_pControlsXPad360 = NULL;
	delete m_pTestMessageLabel;
	m_pTestMessageLabel = NULL;
	delete m_pTest3DUI;
	m_pTest3DUI = NULL;

}

int CSysControlLocal::GetState(int state)
{

	return m_pControlsApp->GetState(state);
}

int CSysControlLocal::ClearState(int state)
{
	return m_pControlsApp->ClearState(state);
}

float CSysControlLocal::GetMouseDX()
{
	return m_pControlsApp->GetMouseDX();
}

float CSysControlLocal::GetMouseDY()
{
	return m_pControlsApp->GetMouseDY();
}
void CSysControlLocal::SetMouseGrab(int g)
{
	g_Engine.pApp->SetMouseGrab(g);
	g_Engine.pGui->SetMouseShow(!g);
}
int CSysControlLocal::GetMouseGrab()
{
	return g_Engine.pApp->GetMouseGrab();
}

void CSysControlLocal::SetControlMode(ControlMode mode)
{
	m_nControlMode = mode;
}

CSysControl::ControlMode CSysControlLocal::GetControlMode() const
{
	return m_nControlMode;
}

CSysControl::ControlMode CSysControlLocal::GetControlMode() const
{
	return m_nControlMode;
}
void CSysControlLocal::Update_Mouse(float ifps)
{
	float dx = (g_Engine.pApp->GetMouseX() - m_nOldMouseX) * g_Engine.pControls->GetMouseSensitivity() * 0.1f;//0.1f这个数值越大，鼠标移动越快
	float dy = (g_Engine.pApp->GetMouseY() - m_nOldMouseY) * g_Engine.pControls->GetMouseSensitivity() * 0.1f;//0.1这个数值越小，鼠标移动越慢

	m_pControlsApp->SetMouseDX(dx);
	m_pControlsApp->SetMouseDY(dy);

	if (g_Engine.pApp->GetMouseGrab() && g_Engine.pApp->GetActive())
	{
		g_Engine.pApp->SetMouse(g_Engine.pApp->GetWidth() / 2, g_Engine.pApp->GetHeight() / 2);
	}

	m_nOldMouseX = g_Engine.pApp->GetMouseX();
	m_nOldMouseY = g_Engine.pApp->GetMouseY();
}

void CSysControlLocal::Update_Keyboard(float ifps)		//键盘按键响应wsad
{

	if (g_Engine.pInput->IsKeyDown('w'))
		m_pControlsApp->SetState(CControls::STATE_FORWARD, 1);
	if (g_Engine.pInput->IsKeyDown('s'))
		m_pControlsApp->SetState(CControls::STATE_BACKWARD, 1);
	if (g_Engine.pInput->IsKeyDown('a'))
		m_pControlsApp->SetState(CControls::STATE_MOVE_LEFT, 1);
	if (g_Engine.pInput->IsKeyDown('d'))
		m_pControlsApp->SetState(CControls::STATE_MOVE_RIGHT, 1);

	if (g_Engine.pInput->IsKeyUp('w'))
		m_pControlsApp->SetState(CControls::STATE_FORWARD, 0);
	else if (g_Engine.pInput->IsKeyUp('s'))
		m_pControlsApp->SetState(CControls::STATE_BACKWARD, 0);

	if (g_Engine.pInput->IsKeyUp('a'))
		m_pControlsApp->SetState(CControls::STATE_MOVE_LEFT, 0);
	else if (g_Engine.pInput->IsKeyUp('d'))
		m_pControlsApp->SetState(CControls::STATE_MOVE_RIGHT, 0);
	if (g_Engine.pInput->IsKeyDown(' '))		//空格跳跃
		m_pControlsApp->SetState(CControls::STATE_JUMP, 1);
	else
		m_pControlsApp->SetState(CControls::STATE_JUMP, 0);
}
void CSysControlLocal::Update_XPad360(float ifps)
{
	m_pControlsXPad360->UpdateEvents();
	CUtilStr strMessage;
	strMessage = CUtilStr("测试3D UI\n"),
	strMessage += CUtilStr(m_pControlsXPad360->GetName()) + "\n";

	strMessage += CUtilStr::Format("\n手柄测试\n");
	strMessage += CUtilStr::Format("LeftX:  %5.2f\n", m_pControlsXPad360->GetLeftX());
	strMessage += CUtilStr::Format("LeftY:  %5.2f\n", m_pControlsXPad360->GetLeftY());
	strMessage += CUtilStr::Format("RightX: %5.2f\n", m_pControlsXPad360->GetRightX());
	strMessage += CUtilStr::Format("RightY: %5.2f\n", m_pControlsXPad360->GetRightY());

}<commit_msg>Signed-off-by: mrlitong <litongtongxue@gmail.com><commit_after>#include "SysControl.h"
#include "ControlsApp.h"
#include "ControlsXPad360.h"
#include "Engine.h"
#include "App.h"
#include "Engine.h"
#include "App.h"
#include "Input.h"
#include "ObjectGui.h"
#include "WidgetLabel.h"

//解决跨平台字符集兼容问题
#ifdef _WIN32
#pragma execution_character_set("utf-8")
#endif

using namespace MathLib;

class CSysControlLocal : public CSysControl
{
public:
	CSysControlLocal();
	virtual ~CSysControlLocal();

	virtual void Init();	//角色要初始化，着色器要初始化，
	virtual void Update(float ifps);
	virtual void Shutdown();

	virtual int GetState(int state);		//鼠标状态，键盘状态，人物状态，子弹状态等等。
	virtual int ClearState(int state);

	virtual float GetMouseDX();
	virtual float GetMouseDY();

	virtual void SetMouseGrab(int g);		//设置是否显示鼠标
	virtual int GetMouseGrab();			//获取鼠标状态，是显示呢还是不显示的状态。

	virtual void SetControlMode(ControlMode mode);			//控制模式
	virtual ControlMode GetControlMode() const;				//获取控制模式

private:
	void Update_Mouse(float ifps);
	void Update_Keyboard(float ifps);
	void Update_XPad360(float ifps);

	CControlsApp        *m_pControlsApp;		//控制游戏中移动
	CControlsXPad360    *m_pControlsXPad360;
	ControlMode         m_nControlMode;			//控制模式

	int                 m_nOldMouseX;			//上一个鼠标坐标X
	int                 m_nOldMouseY;			//上一个鼠标坐标Y

	CObjectGui          *m_pTest3DUI;
	CWidgetLabel        *m_pTestMessageLabel;

};

CSysControlLocal::CSysControlLocal()
{

}
CSysControlLocal::~CSysControlLocal()
{

}

void CSysControlLocal::Init()
{
	m_pControlsApp = new CControlsApp;
	m_pControlsXPad360 = new CControlsXPad360(0);

	g_Engine.pApp->SetMouseGrab(0);
	g_Engine.pApp->SetMouseShow(0);

	SetControlMode(CONTROL_KEYBORAD_MOUSE);

	m_pTest3DUI = new CObjectGui(2.0f, 1.0f, "data/core/gui/");
	m_pTest3DUI->SetMouseShow(0);
	m_pTest3DUI->SetBackground(1);
	m_pTest3DUI->SetBackgroundColor(vec4(1.0f, 0.0f, 0.0f, 1.0f));

	m_pTest3DUI->SetScreenSize(800, 400);
	m_pTest3DUI->SetControlDistance(1000.0f);
	m_pTest3DUI->CreateMaterial("gui_base");	 //show in game

	m_pTest3DUI->SetWorldTransform(Translate(0.0f, 0.0f, 2.0f) * MakeRotationFromZY(vec3(0.0f, -1.0f, 0.0f), vec3(0.0f, 0.0f, 1.0f)));

	m_pTestMessageLabel = new CWidgetLabel(m_pTest3DUI->GetGui());	//初始化文字标签
	m_pTest3DUI->GetGui()->AddChild(m_pTestMessageLabel, CGui::ALIGN_CENTER);
	m_pTestMessageLabel->SetFontColor(vec4(0.0f, 0.0f, 0.0f, 1.0f));

	m_pTestMessageLabel = new CWidgetLabel(m_pTest3DUI->GetGui());	//初始化文字标签
	m_pTest3DUI->GetGui()->AddChild(m_pTestMessageLabel, CGui::ALIGN_CENTER);
	m_pTestMessageLabel->SetFontColor(vec4(0.0f, 0.0f, 0.0f, 1.0f));

	m_pTestMessageLabel->SetFontSize(80);		//设置字体大小
	m_pTestMessageLabel->SetFontOutline(1);		//设置字体轮廓
	m_pTestMessageLabel->SetText("两个黄鹂鸣翠柳\n一行白鹭上青天\n窗含西岭千秋雪\n门泊东吴万里船");

	void CSysControlLocal::Update(float ifps)
	{
		Update_Mouse(ifps);
		Update_Keyboard(ifps);
		Update_XPad360(ifps);
	}

	m_nOldMouseX = 0;
	m_nOldMouseY = 0;
}
void CSysControlLocal::Shutdown()
{
	g_Engine.pApp->SetMouseGrab(0);
	g_Engine.pApp->SetMouseShow(0);
	delete m_pControlsApp;
	m_pControlsApp = NULL;
	delete m_pControlsXPad360;
	m_pControlsXPad360 = NULL;
	delete m_pTestMessageLabel;
	m_pTestMessageLabel = NULL;
	delete m_pTest3DUI;
	m_pTest3DUI = NULL;

}

int CSysControlLocal::GetState(int state)
{

	return m_pControlsApp->GetState(state);
}

int CSysControlLocal::ClearState(int state)
{
	return m_pControlsApp->ClearState(state);
}

float CSysControlLocal::GetMouseDX()
{
	return m_pControlsApp->GetMouseDX();
}

float CSysControlLocal::GetMouseDY()
{
	return m_pControlsApp->GetMouseDY();
}
void CSysControlLocal::SetMouseGrab(int g)
{
	g_Engine.pApp->SetMouseGrab(g);
	g_Engine.pGui->SetMouseShow(!g);
}
int CSysControlLocal::GetMouseGrab()
{
	return g_Engine.pApp->GetMouseGrab();
}

void CSysControlLocal::SetControlMode(ControlMode mode)
{
	m_nControlMode = mode;
}

CSysControl::ControlMode CSysControlLocal::GetControlMode() const
{
	return m_nControlMode;
}

CSysControl::ControlMode CSysControlLocal::GetControlMode() const
{
	return m_nControlMode;
}
void CSysControlLocal::Update_Mouse(float ifps)
{
	float dx = (g_Engine.pApp->GetMouseX() - m_nOldMouseX) * g_Engine.pControls->GetMouseSensitivity() * 0.1f;//0.1f这个数值越大，鼠标移动越快
	float dy = (g_Engine.pApp->GetMouseY() - m_nOldMouseY) * g_Engine.pControls->GetMouseSensitivity() * 0.1f;//0.1这个数值越小，鼠标移动越慢

	m_pControlsApp->SetMouseDX(dx);
	m_pControlsApp->SetMouseDY(dy);

	if (g_Engine.pApp->GetMouseGrab() && g_Engine.pApp->GetActive())
	{
		g_Engine.pApp->SetMouse(g_Engine.pApp->GetWidth() / 2, g_Engine.pApp->GetHeight() / 2);
	}

	m_nOldMouseX = g_Engine.pApp->GetMouseX();
	m_nOldMouseY = g_Engine.pApp->GetMouseY();
}

void CSysControlLocal::Update_Keyboard(float ifps)		//键盘按键响应wsad
{

	if (g_Engine.pInput->IsKeyDown('w'))
		m_pControlsApp->SetState(CControls::STATE_FORWARD, 1);
	if (g_Engine.pInput->IsKeyDown('s'))
		m_pControlsApp->SetState(CControls::STATE_BACKWARD, 1);
	if (g_Engine.pInput->IsKeyDown('a'))
		m_pControlsApp->SetState(CControls::STATE_MOVE_LEFT, 1);
	if (g_Engine.pInput->IsKeyDown('d'))
		m_pControlsApp->SetState(CControls::STATE_MOVE_RIGHT, 1);

	if (g_Engine.pInput->IsKeyUp('w'))
		m_pControlsApp->SetState(CControls::STATE_FORWARD, 0);
	else if (g_Engine.pInput->IsKeyUp('s'))
		m_pControlsApp->SetState(CControls::STATE_BACKWARD, 0);

	if (g_Engine.pInput->IsKeyUp('a'))
		m_pControlsApp->SetState(CControls::STATE_MOVE_LEFT, 0);
	else if (g_Engine.pInput->IsKeyUp('d'))
		m_pControlsApp->SetState(CControls::STATE_MOVE_RIGHT, 0);
	if (g_Engine.pInput->IsKeyDown(' '))		//空格跳跃
		m_pControlsApp->SetState(CControls::STATE_JUMP, 1);
	else
		m_pControlsApp->SetState(CControls::STATE_JUMP, 0);
}
void CSysControlLocal::Update_XPad360(float ifps)
{
	m_pControlsXPad360->UpdateEvents();
	CUtilStr strMessage;
	strMessage = CUtilStr("测试3D UI\n"),
	strMessage += CUtilStr(m_pControlsXPad360->GetName()) + "\n";

	strMessage += CUtilStr::Format("\n手柄测试\n");
	strMessage += CUtilStr::Format("LeftX:  %5.2f\n", m_pControlsXPad360->GetLeftX());
	strMessage += CUtilStr::Format("LeftY:  %5.2f\n", m_pControlsXPad360->GetLeftY());
	strMessage += CUtilStr::Format("RightX: %5.2f\n", m_pControlsXPad360->GetRightX());
	strMessage += CUtilStr::Format("RightY: %5.2f\n", m_pControlsXPad360->GetRightY());
	strMessage += "\nTriggers:\n";
	strMessage += CUtilStr::Format("Left:   %5.2f\n", m_pControlsXPad360->GetLeftTrigger());
	strMessage += CUtilStr::Format("Right:  %5.2f\n", m_pControlsXPad360->GetRightTrigger());

}<|endoftext|>