<commit_before>/*
 Copyright (c) 2016, Ford Motor Company
 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.

 Neither the name of the Ford Motor Company nor the names of its contributors
 may be used to endorse or promote products derived from this software
 without specific prior written permission.

 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 "application_manager/event_engine/event_dispatcher_impl.h"
#include "interfaces/HMI_API.h"
#include "application_manager/event_engine/event_observer.h"
#include <algorithm>

namespace application_manager {
namespace event_engine {
using namespace sync_primitives;

EventDispatcherImpl::EventDispatcherImpl()
    : state_lock_(false), observer_lock_(true), observers_event_() {}

EventDispatcherImpl::~EventDispatcherImpl() {}

void EventDispatcherImpl::raise_event(const Event& event) {
  {
    AutoLock auto_lock(state_lock_);
    // check if event is notification
    if (hmi_apis::messageType::notification == event.smart_object_type()) {
      const uint32_t notification_correlation_id = 0;
      observers_ = observers_event_[event.id()][notification_correlation_id];
    }

    if (hmi_apis::messageType::response == event.smart_object_type() ||
        hmi_apis::messageType::error_response == event.smart_object_type()) {
      observers_ =
          observers_event_[event.id()][event.smart_object_correlation_id()];
    }
  }

  // Call observers
  EventObserver* temp;
  while (!observers_.empty()) {
    AutoLock auto_lock(observer_lock_);
    temp = *observers_.begin();
    observers_.erase(observers_.begin());
    temp->on_event(event);
  }
}

void EventDispatcherImpl::add_observer(const Event::EventID& event_id,
                                       int32_t hmi_correlation_id,
                                       EventObserver& observer) {
  AutoLock auto_lock(state_lock_);
  observers_event_[event_id][hmi_correlation_id].push_back(&observer);
}

struct IdCheckFunctor {
  IdCheckFunctor(const unsigned long id) : target_id(id) {}

  bool operator()(const EventObserver* obs) const {
    return (obs->id() == target_id);
  }

 private:
  const unsigned long target_id;
};

void EventDispatcherImpl::remove_observer(const Event::EventID& event_id,
                                          EventObserver& observer) {
  remove_observer_from_vector(observer);
  AutoLock auto_lock(state_lock_);
  ObserversMap::iterator it = observers_event_[event_id].begin();

  for (; observers_event_[event_id].end() != it; ++it) {
    ObserverVector& obs_vec = it->second;
    const ObserverVector::iterator obs_vec_it = obs_vec.end();
    obs_vec.erase(
        std::remove_if(
            obs_vec.begin(), obs_vec_it, IdCheckFunctor(observer.id())),
        obs_vec_it);
  }
}

void EventDispatcherImpl::remove_observer(EventObserver& observer) {
  remove_observer_from_vector(observer);
  EventObserverMap::iterator event_map = observers_event_.begin();

  for (; observers_event_.end() != event_map; ++event_map) {
    remove_observer(event_map->first, observer);
  }
}

void EventDispatcherImpl::remove_observer_from_vector(EventObserver& observer) {
  AutoLock auto_lock(observer_lock_);

  observers_.erase(
      std::remove_if(
          observers_.begin(), observers_.end(), IdCheckFunctor(observer.id())),
      observers_.end());
}

}  // namespace event_engine
}  // namespace application_manager
<commit_msg>Fix/issue 1737 (#1739)<commit_after>/*
 Copyright (c) 2016, Ford Motor Company
 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.

 Neither the name of the Ford Motor Company nor the names of its contributors
 may be used to endorse or promote products derived from this software
 without specific prior written permission.

 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 "application_manager/event_engine/event_dispatcher_impl.h"
#include "interfaces/HMI_API.h"
#include "application_manager/event_engine/event_observer.h"
#include <algorithm>

namespace application_manager {
namespace event_engine {
using namespace sync_primitives;

EventDispatcherImpl::EventDispatcherImpl()
    : state_lock_(false), observer_lock_(true), observers_event_() {}

EventDispatcherImpl::~EventDispatcherImpl() {}

void EventDispatcherImpl::raise_event(const Event& event) {
  {
    AutoLock auto_lock(state_lock_);
    // check if event is notification
    if (hmi_apis::messageType::notification == event.smart_object_type()) {
      const uint32_t notification_correlation_id = 0;
      observers_ = observers_event_[event.id()][notification_correlation_id];
    }

    if (hmi_apis::messageType::response == event.smart_object_type() ||
        hmi_apis::messageType::error_response == event.smart_object_type()) {
      observers_ =
          observers_event_[event.id()][event.smart_object_correlation_id()];
    }
  }

  // Call observers
  EventObserver* temp;
  while (!observers_.empty()) {
    observer_lock_.Acquire();
    temp = *observers_.begin();
    observers_.erase(observers_.begin());
    observer_lock_.Release();
    temp->on_event(event);
  }
}

void EventDispatcherImpl::add_observer(const Event::EventID& event_id,
                                       int32_t hmi_correlation_id,
                                       EventObserver& observer) {
  AutoLock auto_lock(state_lock_);
  observers_event_[event_id][hmi_correlation_id].push_back(&observer);
}

struct IdCheckFunctor {
  IdCheckFunctor(const unsigned long id) : target_id(id) {}

  bool operator()(const EventObserver* obs) const {
    return (obs->id() == target_id);
  }

 private:
  const unsigned long target_id;
};

void EventDispatcherImpl::remove_observer(const Event::EventID& event_id,
                                          EventObserver& observer) {
  remove_observer_from_vector(observer);
  AutoLock auto_lock(state_lock_);
  ObserversMap::iterator it = observers_event_[event_id].begin();

  for (; observers_event_[event_id].end() != it; ++it) {
    ObserverVector& obs_vec = it->second;
    const ObserverVector::iterator obs_vec_it = obs_vec.end();
    obs_vec.erase(
        std::remove_if(
            obs_vec.begin(), obs_vec_it, IdCheckFunctor(observer.id())),
        obs_vec_it);
  }
}

void EventDispatcherImpl::remove_observer(EventObserver& observer) {
  remove_observer_from_vector(observer);
  EventObserverMap::iterator event_map = observers_event_.begin();

  for (; observers_event_.end() != event_map; ++event_map) {
    remove_observer(event_map->first, observer);
  }
}

void EventDispatcherImpl::remove_observer_from_vector(EventObserver& observer) {
  AutoLock auto_lock(observer_lock_);

  observers_.erase(
      std::remove_if(
          observers_.begin(), observers_.end(), IdCheckFunctor(observer.id())),
      observers_.end());
}

}  // namespace event_engine
}  // namespace application_manager
<|endoftext|>


<commit_before>#include "node.h"
#include <jni.h>

#include "node_jni.h"

namespace node
{
  /** I decided to pass a single concatenated jstring instead of an array of strings from java */
  JNIEXPORT jint JNICALL Java_NodeJNI_start(JNIEnv *env, jobject obj, jint argc, jobjectArray argv) {

    int stringCount = env->GetArrayLength(stringArray);

    for (int i=0; i<stringCount; i++) {
        jstring string = (jstring) GetObjectArrayElement(env, stringArray, i);
        const char *rawString = GetStringUTFChars(env, string, 0);
        // Don't forget to call `ReleaseStringUTFChars` when you're done.
    }

    const jbyte *str;
    str = (*env)->GetStringUTFChars(env, argv, str);

    // capture exit result
    int returnValue = node::Start((int) argc, argv);

    // prevent memory leaks
    for (int i=0; i<stringCount; i++) {
      (*env)->ReleaseStringUTFChars(env, argv, str);
    }

    return returnValue;
  }
}

<commit_msg>last hurdle, convert const char* (jbyte) to char*, so main will accept the 2nd param<commit_after>#include "node.h"
#include <jni.h>
#include <string>
#include <iostream>

#include "node_jni.h"

union charunion {
  char *chr;
  const char* cchr;
};

/**
 * TODO I can't decide on snake, camel case or C-style abbrev.
 */
namespace node
{
  /** I decided to pass a single concatenated jstring instead of an array of strings from java */
  JNIEXPORT jint JNICALL Java_NodeJNI_start(JNIEnv *env, jobject obj, jint jni_argc, jobjectArray jni_argv) {

    int len = env->GetArrayLength(jni_argv); // should be equal to argc

    const char** argv = new const char*[len];
    jstring* jstringArr = new jstring[len];

    // machine value type conversion, wow, gotta love high-level abstractions...
    for (int i=0; i<len; i++) {
        jstringArr[i] = (jstring) env->GetObjectArrayElement(jni_argv, i);
        argv[i] = env->GetStringUTFChars(jstringArr[i], 0);
    }

    // capture exit result
    int returnValue = node::Start((int) jni_argc, argv);
    // TODO jint is a typedef for long on an arm 64 and endianness? Phrack it. Just cast.
    // figure out macros later

    for (int i=0; i<len; i++) {
      // debug, TODO redirect stdout to android Log
      std::cout << std::string(argv[i]);

      // prevent memory leaks
      env->ReleaseStringUTFChars(jstringArr[i], argv[i]);
    }

    // deallocate arrays
    delete argv;
    delete jstringArr;

    return returnValue;
  }
}

<|endoftext|>


<commit_before><commit_msg>tdf#90694 reset group area listeners when splitting group<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (c) 2017 Dariusz Stojaczyk. All Rights Reserved.
 * The following source code is released under an MIT-style license,
 * that can be found in the LICENSE file.
 */

#include <cmath>

#include "Application.h"
#include "util/os.h"
#include "util/log.h"
#include "window/Window.h"

#ifndef SIMULATION
#define RENDER_CALL(X) X
#else
#define RENDER_CALL(X)
#endif

static int convertSDLButtonId(int id) {
    return (int) std::round(std::log((double) id) / std::log(2.0)) + 1;
}

#ifdef USES_SDL
static Input::TouchPoint::State convertSDLEventId(uint32_t id) {
    switch (id) {
        case SDL_MOUSEBUTTONDOWN:
            return Input::TouchPoint::State::PRESS;
        case SDL_MOUSEBUTTONUP:
            return Input::TouchPoint::State::RELEASE;
        default:
            return Input::TouchPoint::State::REPEAT;
    }
}
#endif // USES_SDL

Application::Application(ApplicationContext &context,
                         WindowManager &windowManager)
    : m_windowManager(windowManager),
#ifndef SIMULATION
      m_renderer(context, m_windowManager),
#endif
      m_newWindow(m_windowManager.getWindow(0)) {

    context.init(this);

#ifndef SIMULATION
    if (!m_renderer.initialized()) {
        Log::error("Couldn't initialize RenderManager.");
        return;
    }
#endif

    switchWindow();

    /* if not called right now, first call in
     game loop would return a very huge value */
    m_timer.delta();
    m_running = true;
}

void Application::reinit() {
    m_inputManager.reload();
    m_window->reload();
    RENDER_CALL(
        if (m_renderer.switchWindow(*m_window) != 0) {
            Log::error("Couldn't reinit window.");
            m_running = false;
        });

    /* if not called right now, first call in
     game loop would return a very huge value */
    m_timer.delta();
}

void Application::update() {
    if (m_newWindow) {
        switchWindow();
        m_newWindow = nullptr;
    }

    m_window->tick(m_timer.delta());
    RENDER_CALL(m_renderer.render());
    handleEvents();
    m_inputManager.tick(*m_window);
}

void Application::resize(uint32_t width, uint32_t height) {
    RENDER_CALL(m_renderer.resize(width, height));
    m_window->reload();
}

void Application::handleClick(int button, Input::TouchPoint::State state,
                              float x, float y) {
    m_inputManager.handleClick(button, state, x, y);
}

void Application::handleEvents() {
#ifdef USES_SDL
    SDL_Event event;
    while (SDL_PollEvent(&event) != 0) {
        switch (event.type) {
            case SDL_QUIT:
                m_running = false;
                break;
            case SDL_WINDOWEVENT:
                if (event.window.event == SDL_WINDOWEVENT_RESIZED ||
                    event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
                    resize((uint32_t) event.window.data1,
                           (uint32_t) event.window.data2);
                }
                break;
            case SDL_KEYDOWN:
            case SDL_KEYUP:
                m_inputManager.handleKeypress(&event);
                break;
            case SDL_MOUSEBUTTONDOWN:
            case SDL_MOUSEBUTTONUP:
            case SDL_MOUSEMOTION: {
                int button = convertSDLButtonId(event.button.button);
                if (button >= 0 && button < 5) {
                    int x, y;
                    SDL_GetMouseState(&x, &y);
                    handleClick(button, convertSDLEventId(event.type), x, y);
                }
                break;
            }
            default:
                break;
        }
    }
#endif // USES_SDL
}

bool Application::running() const {
    return m_running;
}

void Application::switchWindow() {
    if (m_newWindow == nullptr) {
        m_running = false;
    } else {
        m_window = m_newWindow;
        m_newWindow = nullptr;
        m_window->reload();
        RENDER_CALL(
            if (m_renderer.switchWindow(*m_window) != 0) {
                m_running = false;
            });
    }
}

#ifdef DEF_ANDROID

#include <jni.h>

std::unique_ptr<Application> application;
bool initialized = false;

extern "C" {
    JNIEXPORT void JNICALL Java_darsto_spooky_JniBridge_init(JNIEnv *env, jobject obj);
    JNIEXPORT void JNICALL Java_darsto_spooky_JniBridge_resize(JNIEnv *env, jobject obj, jint width, jint height);
    JNIEXPORT void JNICALL Java_darsto_spooky_JniBridge_tick(JNIEnv *env, jobject obj);
    JNIEXPORT void JNICALL Java_darsto_spooky_JniBridge_handleTouch(JNIEnv *env, jobject obj, jint i, jint action, jfloat x, jfloat y);
}

JNIEXPORT void JNICALL Java_darsto_spooky_JniBridge_init(JNIEnv *, jobject) {
    if (!application) {
        application = std::make_unique<Application>();
    } else {
        application->reinit();
    }
}

JNIEXPORT void JNICALL Java_darsto_spooky_JniBridge_resize(JNIEnv *, jobject, jint width, jint height) {
    application->resize((uint32_t) width, (uint32_t) height);
}

JNIEXPORT void JNICALL Java_darsto_spooky_JniBridge_tick(JNIEnv *env, jobject obj) {
    application->update();
    if (!application->running()) {
        jclass cls = env->GetObjectClass(obj);
        jmethodID mid = env->GetMethodID(cls, "exit", "()V");
        if (mid != 0) {
            env->CallVoidMethod(obj, mid);
        }
    }
}

JNIEXPORT void JNICALL Java_darsto_spooky_JniBridge_handleTouch(JNIEnv *, jobject, jint i,  jint action, jfloat x, jfloat y) {
    application->handleClick(i, static_cast<Input::TouchPoint::State>(action), x, y);
}

#endif // DEF_ANDROID

#undef RENDER_CALL<commit_msg>Wrap convertSDLButtonId in USES_SDL ifdef<commit_after>/*
 * Copyright (c) 2017 Dariusz Stojaczyk. All Rights Reserved.
 * The following source code is released under an MIT-style license,
 * that can be found in the LICENSE file.
 */

#include <cmath>

#include "Application.h"
#include "util/os.h"
#include "util/log.h"
#include "window/Window.h"

#ifndef SIMULATION
#define RENDER_CALL(X) X
#else
#define RENDER_CALL(X)
#endif

#ifdef USES_SDL
static int convertSDLButtonId(int id) {
    return (int) std::round(std::log((double) id) / std::log(2.0)) + 1;
}

static Input::TouchPoint::State convertSDLEventId(uint32_t id) {
    switch (id) {
        case SDL_MOUSEBUTTONDOWN:
            return Input::TouchPoint::State::PRESS;
        case SDL_MOUSEBUTTONUP:
            return Input::TouchPoint::State::RELEASE;
        default:
            return Input::TouchPoint::State::REPEAT;
    }
}
#endif // USES_SDL

Application::Application(ApplicationContext &context,
                         WindowManager &windowManager)
    : m_windowManager(windowManager),
#ifndef SIMULATION
      m_renderer(context, m_windowManager),
#endif
      m_newWindow(m_windowManager.getWindow(0)) {

    context.init(this);

#ifndef SIMULATION
    if (!m_renderer.initialized()) {
        Log::error("Couldn't initialize RenderManager.");
        return;
    }
#endif

    switchWindow();

    /* if not called right now, first call in
     game loop would return a very huge value */
    m_timer.delta();
    m_running = true;
}

void Application::reinit() {
    m_inputManager.reload();
    m_window->reload();
    RENDER_CALL(
        if (m_renderer.switchWindow(*m_window) != 0) {
            Log::error("Couldn't reinit window.");
            m_running = false;
        });

    /* if not called right now, first call in
     game loop would return a very huge value */
    m_timer.delta();
}

void Application::update() {
    if (m_newWindow) {
        switchWindow();
        m_newWindow = nullptr;
    }

    m_window->tick(m_timer.delta());
    RENDER_CALL(m_renderer.render());
    handleEvents();
    m_inputManager.tick(*m_window);
}

void Application::resize(uint32_t width, uint32_t height) {
    RENDER_CALL(m_renderer.resize(width, height));
    m_window->reload();
}

void Application::handleClick(int button, Input::TouchPoint::State state,
                              float x, float y) {
    m_inputManager.handleClick(button, state, x, y);
}

void Application::handleEvents() {
#ifdef USES_SDL
    SDL_Event event;
    while (SDL_PollEvent(&event) != 0) {
        switch (event.type) {
            case SDL_QUIT:
                m_running = false;
                break;
            case SDL_WINDOWEVENT:
                if (event.window.event == SDL_WINDOWEVENT_RESIZED ||
                    event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
                    resize((uint32_t) event.window.data1,
                           (uint32_t) event.window.data2);
                }
                break;
            case SDL_KEYDOWN:
            case SDL_KEYUP:
                m_inputManager.handleKeypress(&event);
                break;
            case SDL_MOUSEBUTTONDOWN:
            case SDL_MOUSEBUTTONUP:
            case SDL_MOUSEMOTION: {
                int button = convertSDLButtonId(event.button.button);
                if (button >= 0 && button < 5) {
                    int x, y;
                    SDL_GetMouseState(&x, &y);
                    handleClick(button, convertSDLEventId(event.type), x, y);
                }
                break;
            }
            default:
                break;
        }
    }
#endif // USES_SDL
}

bool Application::running() const {
    return m_running;
}

void Application::switchWindow() {
    if (m_newWindow == nullptr) {
        m_running = false;
    } else {
        m_window = m_newWindow;
        m_newWindow = nullptr;
        m_window->reload();
        RENDER_CALL(
            if (m_renderer.switchWindow(*m_window) != 0) {
                m_running = false;
            });
    }
}

#ifdef DEF_ANDROID

#include <jni.h>

std::unique_ptr<Application> application;
bool initialized = false;

extern "C" {
    JNIEXPORT void JNICALL Java_darsto_spooky_JniBridge_init(JNIEnv *env, jobject obj);
    JNIEXPORT void JNICALL Java_darsto_spooky_JniBridge_resize(JNIEnv *env, jobject obj, jint width, jint height);
    JNIEXPORT void JNICALL Java_darsto_spooky_JniBridge_tick(JNIEnv *env, jobject obj);
    JNIEXPORT void JNICALL Java_darsto_spooky_JniBridge_handleTouch(JNIEnv *env, jobject obj, jint i, jint action, jfloat x, jfloat y);
}

JNIEXPORT void JNICALL Java_darsto_spooky_JniBridge_init(JNIEnv *, jobject) {
    if (!application) {
        application = std::make_unique<Application>();
    } else {
        application->reinit();
    }
}

JNIEXPORT void JNICALL Java_darsto_spooky_JniBridge_resize(JNIEnv *, jobject, jint width, jint height) {
    application->resize((uint32_t) width, (uint32_t) height);
}

JNIEXPORT void JNICALL Java_darsto_spooky_JniBridge_tick(JNIEnv *env, jobject obj) {
    application->update();
    if (!application->running()) {
        jclass cls = env->GetObjectClass(obj);
        jmethodID mid = env->GetMethodID(cls, "exit", "()V");
        if (mid != 0) {
            env->CallVoidMethod(obj, mid);
        }
    }
}

JNIEXPORT void JNICALL Java_darsto_spooky_JniBridge_handleTouch(JNIEnv *, jobject, jint i,  jint action, jfloat x, jfloat y) {
    application->handleClick(i, static_cast<Input::TouchPoint::State>(action), x, y);
}

#endif // DEF_ANDROID

#undef RENDER_CALL<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015 Luke San Antonio
 * All rights reserved.
 */
#include "driver.h"
#include "mesh.h"
#include "texture.h"
#include "shader.h"

#include "common.h"

#include "../../common/color.h"
#include "../../common/log.h"

#include "../../common/debugging.h"
#ifdef GAME_DEBUGGING_ENABLED
#define CAST_PTR dynamic_cast
#else
#define CAST_PTR reinterpret_cast
#endif

namespace redc
{
  namespace gfx
  {
    namespace gl
    {
      Driver::Driver(Vec<int> size) noexcept : IDriver(size)
      {
        glViewport(0, 0, size.x, size.y);
        glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
        glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE,
                            GL_ZERO);

        glEnable(GL_FRAMEBUFFER_SRGB);

        depth_test(true);
        write_depth(true);
      }
      Driver::~Driver() noexcept
      {
        glUseProgram(0);
      }

      std::unique_ptr<Shader> Driver::make_shader_repr() noexcept
      {
        return std::make_unique<GL_Shader>(*this);
      }
      void Driver::use_shader(Shader& s, bool force) noexcept
      {
        if(&s == cur_shader_ && !force) return;

        auto shader_ptr = CAST_PTR<GL_Shader*>(&s);
        REDC_ASSERT_MSG(shader_ptr, "Shader not made with this driver;"
                        " something is very wrong.");

        shader_ptr->use();
        cur_shader_ = shader_ptr;
      }
      Shader* Driver::active_shader() const noexcept
      {
        return cur_shader_;
      }

      std::unique_ptr<IMesh> Driver::make_mesh_repr() noexcept
      {
        // Make it and forget about it, we'll just use a dynamic cast for
        // simplicity.
        return std::make_unique<GL_Mesh>(*this);
      }
      void Driver::bind_mesh(IMesh& mesh, bool force) noexcept
      {
        if(&mesh == cur_mesh_ && !force) return;

        auto gl_mesh = CAST_PTR<GL_Mesh*>(&mesh);
        REDC_ASSERT_MSG(gl_mesh, "Mesh not made with this driver; something is"
                        " very wrong.");

        gl_mesh->bind();
        cur_mesh_ = gl_mesh;
      }

      std::unique_ptr<Texture> Driver::make_texture_repr() noexcept
      {
        // build n' forget.
        return std::make_unique<GL_Texture>();
      }
      void Driver::bind_texture(Texture& tex, unsigned int loc) noexcept
      {
        auto gl_tex = CAST_PTR<GL_Texture*>(&tex);
        REDC_ASSERT_MSG(gl_tex, "Texture not made with this driver; something"
                        " is very wrong.");
        gl_tex->bind(loc);
      }

      void Driver::set_clear_color(Color const& c) noexcept
      {
        glClearColor(c.r / (float) 0xff, c.g / (float) 0xff,
                     c.b / (float) 0xff, 1.0);
      }
      void Driver::set_clear_depth(float f) noexcept
      {
        glClearDepth(f);
      }

      void Driver::clear() noexcept
      {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
      }
      void Driver::clear_color() noexcept
      {
        glClear(GL_COLOR_BUFFER_BIT);
      }
      void Driver::clear_depth() noexcept
      {
        glClear(GL_DEPTH_BUFFER_BIT);
      }
      void Driver::depth_test(bool enable) noexcept
      {
        if(enable) glEnable(GL_DEPTH_TEST);
        else glDisable(GL_DEPTH_TEST);
      }
      void Driver::write_depth(bool enable) noexcept
      {
        glDepthMask(enable);
      }
      void Driver::blending(bool enable) noexcept
      {
        if(enable) glEnable(GL_BLEND);
        else glDisable(GL_BLEND);
      }
      void Driver::face_culling(bool enable) noexcept
      {
        if(enable) glEnable(GL_CULL_FACE);
        else glDisable(GL_CULL_FACE);
      }
      void Driver::cull_side(Cull_Side side) noexcept
      {
        switch(side)
        {
        case Cull_Side::Front:
          glCullFace(GL_FRONT);
          break;
        case Cull_Side::Back:
          glCullFace(GL_BACK);
          break;
        default:
          break;
        }
      }
      float Driver::read_pixel(Framebuffer fb, Vec<int> pt) noexcept
      {
        auto f = get_gl_pixel_format(fb);

        float ret;
        glReadPixels(pt.x, window_extents().y - pt.y, 1, 1, f, GL_FLOAT, &ret);
        return ret;
      }
      void Driver::check_error() noexcept
      {
        if(glGetError() == GL_INVALID_OPERATION)
        {
          log_e("OpenGL: Invalid operation");
        }
      }
    }
  }
}
<commit_msg>Use color alpha in Driver::set_clear_color<commit_after>/*
 * Copyright (C) 2015 Luke San Antonio
 * All rights reserved.
 */
#include "driver.h"
#include "mesh.h"
#include "texture.h"
#include "shader.h"

#include "common.h"

#include "../../common/color.h"
#include "../../common/log.h"

#include "../../common/debugging.h"
#ifdef GAME_DEBUGGING_ENABLED
#define CAST_PTR dynamic_cast
#else
#define CAST_PTR reinterpret_cast
#endif

namespace redc
{
  namespace gfx
  {
    namespace gl
    {
      Driver::Driver(Vec<int> size) noexcept : IDriver(size)
      {
        glViewport(0, 0, size.x, size.y);
        glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
        glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE,
                            GL_ZERO);

        glEnable(GL_FRAMEBUFFER_SRGB);

        depth_test(true);
        write_depth(true);
      }
      Driver::~Driver() noexcept
      {
        glUseProgram(0);
      }

      std::unique_ptr<Shader> Driver::make_shader_repr() noexcept
      {
        return std::make_unique<GL_Shader>(*this);
      }
      void Driver::use_shader(Shader& s, bool force) noexcept
      {
        if(&s == cur_shader_ && !force) return;

        auto shader_ptr = CAST_PTR<GL_Shader*>(&s);
        REDC_ASSERT_MSG(shader_ptr, "Shader not made with this driver;"
                        " something is very wrong.");

        shader_ptr->use();
        cur_shader_ = shader_ptr;
      }
      Shader* Driver::active_shader() const noexcept
      {
        return cur_shader_;
      }

      std::unique_ptr<IMesh> Driver::make_mesh_repr() noexcept
      {
        // Make it and forget about it, we'll just use a dynamic cast for
        // simplicity.
        return std::make_unique<GL_Mesh>(*this);
      }
      void Driver::bind_mesh(IMesh& mesh, bool force) noexcept
      {
        if(&mesh == cur_mesh_ && !force) return;

        auto gl_mesh = CAST_PTR<GL_Mesh*>(&mesh);
        REDC_ASSERT_MSG(gl_mesh, "Mesh not made with this driver; something is"
                        " very wrong.");

        gl_mesh->bind();
        cur_mesh_ = gl_mesh;
      }

      std::unique_ptr<Texture> Driver::make_texture_repr() noexcept
      {
        // build n' forget.
        return std::make_unique<GL_Texture>();
      }
      void Driver::bind_texture(Texture& tex, unsigned int loc) noexcept
      {
        auto gl_tex = CAST_PTR<GL_Texture*>(&tex);
        REDC_ASSERT_MSG(gl_tex, "Texture not made with this driver; something"
                        " is very wrong.");
        gl_tex->bind(loc);
      }

      void Driver::set_clear_color(Color const& c) noexcept
      {
        glClearColor(c.r / (float) 0xff, c.g / (float) 0xff,
                     c.b / (float) 0xff, c.a / (float) 0xff);
      }
      void Driver::set_clear_depth(float f) noexcept
      {
        glClearDepth(f);
      }

      void Driver::clear() noexcept
      {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
      }
      void Driver::clear_color() noexcept
      {
        glClear(GL_COLOR_BUFFER_BIT);
      }
      void Driver::clear_depth() noexcept
      {
        glClear(GL_DEPTH_BUFFER_BIT);
      }
      void Driver::depth_test(bool enable) noexcept
      {
        if(enable) glEnable(GL_DEPTH_TEST);
        else glDisable(GL_DEPTH_TEST);
      }
      void Driver::write_depth(bool enable) noexcept
      {
        glDepthMask(enable);
      }
      void Driver::blending(bool enable) noexcept
      {
        if(enable) glEnable(GL_BLEND);
        else glDisable(GL_BLEND);
      }
      void Driver::face_culling(bool enable) noexcept
      {
        if(enable) glEnable(GL_CULL_FACE);
        else glDisable(GL_CULL_FACE);
      }
      void Driver::cull_side(Cull_Side side) noexcept
      {
        switch(side)
        {
        case Cull_Side::Front:
          glCullFace(GL_FRONT);
          break;
        case Cull_Side::Back:
          glCullFace(GL_BACK);
          break;
        default:
          break;
        }
      }
      float Driver::read_pixel(Framebuffer fb, Vec<int> pt) noexcept
      {
        auto f = get_gl_pixel_format(fb);

        float ret;
        glReadPixels(pt.x, window_extents().y - pt.y, 1, 1, f, GL_FLOAT, &ret);
        return ret;
      }
      void Driver::check_error() noexcept
      {
        if(glGetError() == GL_INVALID_OPERATION)
        {
          log_e("OpenGL: Invalid operation");
        }
      }
    }
  }
}
<|endoftext|>


<commit_before>// Filename: dtoolbase.cxx
// Created by:  drose (12Sep00)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license.  You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////

#include "dtoolbase.h"

#ifndef NDEBUG

void *default_operator_new(size_t size) {
  return malloc(size);
}

void default_operator_delete(void *ptr) {
  free(ptr);
}

// We absolutely depend on the static initialization of these pointers
// to happen at load time, before any static constructors are called.
void *(*global_operator_new)(size_t size) = &default_operator_new;
void (*global_operator_delete)(void *ptr) = &default_operator_delete;

#endif  // NDEBUG
<commit_msg>abort when malloc fails<commit_after>// Filename: dtoolbase.cxx
// Created by:  drose (12Sep00)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license.  You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////

#include "dtoolbase.h"

#ifndef NDEBUG

void *default_operator_new(size_t size) {
  void *ptr = malloc(size);
  if (ptr == (void *)NULL) {
    cerr << "Out of memory!\n";
    abort();
  }
  return ptr;
}

void default_operator_delete(void *ptr) {
  free(ptr);
}

// We absolutely depend on the static initialization of these pointers
// to happen at load time, before any static constructors are called.
void *(*global_operator_new)(size_t size) = &default_operator_new;
void (*global_operator_delete)(void *ptr) = &default_operator_delete;

#endif  // NDEBUG
<|endoftext|>


<commit_before>
#include "../Flare.h"
#include "FlareBombComponent.h"
#include "FlareBomb.h"

/*----------------------------------------------------
	Constructor
----------------------------------------------------*/

AFlareBomb::AFlareBomb(const class FObjectInitializer& PCIP) : Super(PCIP)
{
	FLOG("AFlareBomb");
	// Mesh data
	BombComp = PCIP.CreateDefaultSubobject<UFlareBombComponent>(this, TEXT("Root"));
	BombComp->bTraceComplexOnMove = true;
	BombComp->LDMaxDrawDistance = 100000; // 1km*/
	BombComp->SetSimulatePhysics(true);
	BombComp->SetLinearDamping(0);
	BombComp->SetAngularDamping(0);
	RootComponent = BombComp;

	SetActorEnableCollision(false);
	// Settings
	PrimaryActorTick.bCanEverTick = true;
}

/*----------------------------------------------------
	Gameplay
----------------------------------------------------*/

void AFlareBomb::PostInitializeComponents()
{
	Super::PostInitializeComponents();
}

void AFlareBomb::Initialize(const FFlareBombSave* Data, UFlareWeapon* Weapon)
{
	ParentWeapon = Weapon;
	WeaponDescription = Weapon->GetDescription();

	// Get the power from description
	if (WeaponDescription)
	{
		FFlareSpacecraftComponentSave ComponentData;
		ComponentData.ComponentIdentifier = WeaponDescription->Identifier;
		BombComp->Initialize(&ComponentData, Weapon->GetSpacecraft()->GetCompany(), Weapon->GetSpacecraft(), false);

		DamageSound = WeaponDescription->WeaponCharacteristics.DamageSound;

		ExplosionEffectTemplate = WeaponDescription->WeaponCharacteristics.ExplosionEffect;
		ExplosionEffectMaterial = WeaponDescription->WeaponCharacteristics.GunCharacteristics.ExplosionMaterial;

	}

	SetActorScale3D(ParentWeapon->GetSpacecraft()->GetActorScale3D());

	if (Data)
	{
		BombData = *Data;
	}
	else
	{
		BombData.Activated = false;
		BombData.Dropped = false;
		BombData.LifeTime = 0;
		BombData.DropParentDistance = 0;
	}

	if (BombData.Activated)
	{
		SetActorEnableCollision(true);
	}
}

void AFlareBomb::NotifyHit(class UPrimitiveComponent* MyComp, class AActor* Other, class UPrimitiveComponent* OtherComp, bool bSelfMoved, FVector HitLocation, FVector HitNormal, FVector NormalImpulse, const FHitResult& Hit)
{
	Super::ReceiveHit(MyComp, Other, OtherComp, bSelfMoved, HitLocation, HitNormal, NormalImpulse, Hit);
	FLOG("AFlareBomb Hit");

	if (Other && OtherComp)
	{
		if (Other == ParentWeapon->GetSpacecraft())
		{
			// Avoid auto hit
			return;
		}

		AFlareBomb* BombCandidate = Cast<AFlareBomb>(Other);
		if (BombCandidate)
		{
			// Avoid bomb hit
			return;
		}

		// Spawn penetration effect
		if (ExplosionEffectTemplate)
		{
		UGameplayStatics::SpawnEmitterAttached(
			ExplosionEffectTemplate,
			OtherComp,
			NAME_None,
			HitLocation,
			HitNormal.Rotation(),
			EAttachLocation::KeepWorldPosition,
			true);
		}

		//TODO Explosion radius

		AFlareSpacecraft* Spacecraft = Cast<AFlareSpacecraft>(Other);
		if (Spacecraft)
		{
			Spacecraft->GetDamageSystem()->ApplyDamage(WeaponDescription->WeaponCharacteristics.ExplosionPower , WeaponDescription->WeaponCharacteristics.AmmoDamageRadius, HitLocation);

			float ImpulseForce = 3000 * WeaponDescription->WeaponCharacteristics.ExplosionPower * WeaponDescription->WeaponCharacteristics.AmmoDamageRadius;

			FVector ImpulseDirection = (HitLocation - GetActorLocation()).GetUnsafeNormal();

			// Physics impulse
			Spacecraft->Airframe->AddImpulseAtLocation( ImpulseForce * ImpulseDirection, HitLocation);

			// Play sound
			AFlareSpacecraftPawn* ShipBase = Cast<AFlareSpacecraftPawn>(Spacecraft);
			if (ShipBase && ShipBase->IsLocallyControlled())
			{
				UGameplayStatics::PlaySoundAtLocation(GetWorld(), DamageSound, HitLocation, 1, 1);
			}
		}

		UFlareSpacecraftComponent* ShipComponent = Cast<UFlareSpacecraftComponent>(OtherComp);
		// Spawn impact decal
		if (ShipComponent && ShipComponent->IsVisibleByPlayer() && ExplosionEffectMaterial)
		{
			// FX data
			float DecalSize = FMath::FRandRange(60, 90);

			UDecalComponent* Decal = UGameplayStatics::SpawnDecalAttached(
				ExplosionEffectMaterial,
				DecalSize * FVector(1, 1, 1),
				ShipComponent,
				NAME_None,
				HitLocation,
				HitNormal.Rotation(),
				EAttachLocation::KeepWorldPosition);

			// Instanciate and configure the decal material
			UMaterialInterface* DecalMaterial = Decal->GetMaterial(0);
			UMaterialInstanceDynamic* DecalMaterialInst = UMaterialInstanceDynamic::Create(DecalMaterial, GetWorld());
			if (DecalMaterialInst)
			{
				DecalMaterialInst->SetScalarParameterValue("RandomParameter", FMath::FRandRange(1, 0));
				Decal->SetMaterial(0, DecalMaterialInst);
			}
		}

		Destroy();
	}

}

void AFlareBomb::Drop()
{
	FLOG("AFlareBomb Drop");
	DetachRootComponentFromParent(true);

	FVector FrontVector = BombComp->ComponentToWorld.TransformVector(FVector(1,0,0));

	// Spin to stabilize
	BombComp->SetPhysicsAngularVelocity(FrontVector * WeaponDescription->WeaponCharacteristics.BombCharacteristics.DropAngularVelocity);
	BombComp->SetPhysicsLinearVelocity(ParentWeapon->GetSpacecraft()->Airframe->GetPhysicsLinearVelocity() + FrontVector * WeaponDescription->WeaponCharacteristics.BombCharacteristics.DropLinearVelocity * 100);

	BombData.DropParentDistance = GetParentDistance();
	BombData.Dropped = true;
	BombData.LifeTime = 0;

}

void AFlareBomb::Tick(float DeltaSeconds)
{
	Super::Tick(DeltaSeconds);

	if (BombData.Dropped && !BombData.Activated)
	{
		if (GetParentDistance() > BombData.DropParentDistance + WeaponDescription->WeaponCharacteristics.BombCharacteristics.ActivationDistance*100)
		{
			// Activate after few centimeters
			SetActorEnableCollision(true);
			BombData.Activated = true;
		}
	}

	if (BombData.Dropped && BombData.Activated)
	{
		BombData.LifeTime += DeltaSeconds;
	}

	AFlarePlayerController* PC = Cast<AFlarePlayerController>(GetWorld()->GetFirstPlayerController());
	if (PC)
	{
		AFlareSpacecraft* PlayerShip = PC->GetShipPawn();
		if (PlayerShip)
		{
			float Distance = (GetActorLocation() - PlayerShip->GetActorLocation()).Size();
			if (Distance > 500000 && BombData.LifeTime > 30)
			{
				// 5 km and 30s
				Destroy();
			}
		}
	}

}

float AFlareBomb::GetParentDistance() const
{
	return (ParentWeapon->GetComponentLocation() - GetActorLocation()).Size();
}

FFlareBombSave* AFlareBomb::Save()
{
	// Physical data
	BombData.Location = GetActorLocation();
	BombData.Rotation = GetActorRotation();
	BombData.LinearVelocity = BombComp->GetPhysicsLinearVelocity();
	BombData.AngularVelocity = BombComp->GetPhysicsAngularVelocity();

	BombData.ParentSpacecraft = ParentWeapon->GetSpacecraft()->GetName();
	BombData.WeaponSlotIdentifier = ParentWeapon->SlotIdentifier;

	return &BombData;
}
<commit_msg>Fix strange bomb crash<commit_after>
#include "../Flare.h"
#include "FlareBombComponent.h"
#include "FlareBomb.h"

/*----------------------------------------------------
	Constructor
----------------------------------------------------*/

AFlareBomb::AFlareBomb(const class FObjectInitializer& PCIP) : Super(PCIP)
{
	FLOG("AFlareBomb");
	// Mesh data
	BombComp = PCIP.CreateDefaultSubobject<UFlareBombComponent>(this, TEXT("Root"));
	BombComp->bTraceComplexOnMove = true;
	BombComp->LDMaxDrawDistance = 100000; // 1km*/
	BombComp->SetSimulatePhysics(true);
	BombComp->SetLinearDamping(0);
	BombComp->SetAngularDamping(0);
	RootComponent = BombComp;

	SetActorEnableCollision(false);
	// Settings
	PrimaryActorTick.bCanEverTick = true;
}

/*----------------------------------------------------
	Gameplay
----------------------------------------------------*/

void AFlareBomb::PostInitializeComponents()
{
	Super::PostInitializeComponents();
}

void AFlareBomb::Initialize(const FFlareBombSave* Data, UFlareWeapon* Weapon)
{
	ParentWeapon = Weapon;
	WeaponDescription = Weapon->GetDescription();

	// Get the power from description
	if (WeaponDescription)
	{
		FFlareSpacecraftComponentSave ComponentData;
		ComponentData.ComponentIdentifier = WeaponDescription->Identifier;
		BombComp->Initialize(&ComponentData, Weapon->GetSpacecraft()->GetCompany(), Weapon->GetSpacecraft(), false);

		DamageSound = WeaponDescription->WeaponCharacteristics.DamageSound;

		ExplosionEffectTemplate = WeaponDescription->WeaponCharacteristics.ExplosionEffect;
		ExplosionEffectMaterial = WeaponDescription->WeaponCharacteristics.GunCharacteristics.ExplosionMaterial;

	}

	SetActorScale3D(ParentWeapon->GetSpacecraft()->GetActorScale3D());

	if (Data)
	{
		BombData = *Data;
	}
	else
	{
		BombData.Activated = false;
		BombData.Dropped = false;
		BombData.LifeTime = 0;
		BombData.DropParentDistance = 0;
	}

	if (BombData.Activated)
	{
		SetActorEnableCollision(true);
	}
}

void AFlareBomb::NotifyHit(class UPrimitiveComponent* MyComp, class AActor* Other, class UPrimitiveComponent* OtherComp, bool bSelfMoved, FVector HitLocation, FVector HitNormal, FVector NormalImpulse, const FHitResult& Hit)
{
	Super::ReceiveHit(MyComp, Other, OtherComp, bSelfMoved, HitLocation, HitNormal, NormalImpulse, Hit);
	FLOG("AFlareBomb Hit");

	if (Other && OtherComp)
	{
		//TODO Investigate on NULL ParentWeapon
		if (!ParentWeapon || Other == ParentWeapon->GetSpacecraft())
		{
			// Avoid auto hit
			return;
		}

		AFlareBomb* BombCandidate = Cast<AFlareBomb>(Other);
		if (BombCandidate)
		{
			// Avoid bomb hit
			return;
		}

		// Spawn penetration effect
		if (ExplosionEffectTemplate)
		{
		UGameplayStatics::SpawnEmitterAttached(
			ExplosionEffectTemplate,
			OtherComp,
			NAME_None,
			HitLocation,
			HitNormal.Rotation(),
			EAttachLocation::KeepWorldPosition,
			true);
		}

		//TODO Explosion radius

		AFlareSpacecraft* Spacecraft = Cast<AFlareSpacecraft>(Other);
		if (Spacecraft)
		{
			Spacecraft->GetDamageSystem()->ApplyDamage(WeaponDescription->WeaponCharacteristics.ExplosionPower , WeaponDescription->WeaponCharacteristics.AmmoDamageRadius, HitLocation);

			float ImpulseForce = 3000 * WeaponDescription->WeaponCharacteristics.ExplosionPower * WeaponDescription->WeaponCharacteristics.AmmoDamageRadius;

			FVector ImpulseDirection = (HitLocation - GetActorLocation()).GetUnsafeNormal();

			// Physics impulse
			Spacecraft->Airframe->AddImpulseAtLocation( ImpulseForce * ImpulseDirection, HitLocation);

			// Play sound
			AFlareSpacecraftPawn* ShipBase = Cast<AFlareSpacecraftPawn>(Spacecraft);
			if (ShipBase && ShipBase->IsLocallyControlled())
			{
				UGameplayStatics::PlaySoundAtLocation(GetWorld(), DamageSound, HitLocation, 1, 1);
			}
		}

		UFlareSpacecraftComponent* ShipComponent = Cast<UFlareSpacecraftComponent>(OtherComp);
		// Spawn impact decal
		if (ShipComponent && ShipComponent->IsVisibleByPlayer() && ExplosionEffectMaterial)
		{
			// FX data
			float DecalSize = FMath::FRandRange(60, 90);

			UDecalComponent* Decal = UGameplayStatics::SpawnDecalAttached(
				ExplosionEffectMaterial,
				DecalSize * FVector(1, 1, 1),
				ShipComponent,
				NAME_None,
				HitLocation,
				HitNormal.Rotation(),
				EAttachLocation::KeepWorldPosition);

			// Instanciate and configure the decal material
			UMaterialInterface* DecalMaterial = Decal->GetMaterial(0);
			UMaterialInstanceDynamic* DecalMaterialInst = UMaterialInstanceDynamic::Create(DecalMaterial, GetWorld());
			if (DecalMaterialInst)
			{
				DecalMaterialInst->SetScalarParameterValue("RandomParameter", FMath::FRandRange(1, 0));
				Decal->SetMaterial(0, DecalMaterialInst);
			}
		}

		Destroy();
	}

}

void AFlareBomb::Drop()
{
	FLOG("AFlareBomb Drop");
	DetachRootComponentFromParent(true);

	FVector FrontVector = BombComp->ComponentToWorld.TransformVector(FVector(1,0,0));

	// Spin to stabilize
	BombComp->SetPhysicsAngularVelocity(FrontVector * WeaponDescription->WeaponCharacteristics.BombCharacteristics.DropAngularVelocity);
	BombComp->SetPhysicsLinearVelocity(ParentWeapon->GetSpacecraft()->Airframe->GetPhysicsLinearVelocity() + FrontVector * WeaponDescription->WeaponCharacteristics.BombCharacteristics.DropLinearVelocity * 100);

	BombData.DropParentDistance = GetParentDistance();
	BombData.Dropped = true;
	BombData.LifeTime = 0;

}

void AFlareBomb::Tick(float DeltaSeconds)
{
	Super::Tick(DeltaSeconds);

	if (BombData.Dropped && !BombData.Activated)
	{
		if (GetParentDistance() > BombData.DropParentDistance + WeaponDescription->WeaponCharacteristics.BombCharacteristics.ActivationDistance*100)
		{
			// Activate after few centimeters
			SetActorEnableCollision(true);
			BombData.Activated = true;
		}
	}

	if (BombData.Dropped && BombData.Activated)
	{
		BombData.LifeTime += DeltaSeconds;
	}

	AFlarePlayerController* PC = Cast<AFlarePlayerController>(GetWorld()->GetFirstPlayerController());
	if (PC)
	{
		AFlareSpacecraft* PlayerShip = PC->GetShipPawn();
		if (PlayerShip)
		{
			float Distance = (GetActorLocation() - PlayerShip->GetActorLocation()).Size();
			if (Distance > 500000 && BombData.LifeTime > 30)
			{
				// 5 km and 30s
				Destroy();
			}
		}
	}

}

float AFlareBomb::GetParentDistance() const
{
	return (ParentWeapon->GetComponentLocation() - GetActorLocation()).Size();
}

FFlareBombSave* AFlareBomb::Save()
{
	// Physical data
	BombData.Location = GetActorLocation();
	BombData.Rotation = GetActorRotation();
	BombData.LinearVelocity = BombComp->GetPhysicsLinearVelocity();
	BombData.AngularVelocity = BombComp->GetPhysicsAngularVelocity();

	//TODO Investigate on NULL ParentWeapon
	if(ParentWeapon)
	{
		BombData.ParentSpacecraft = ParentWeapon->GetSpacecraft()->GetName();
		BombData.WeaponSlotIdentifier = ParentWeapon->SlotIdentifier;
	}

	return &BombData;
}
<|endoftext|>


<commit_before>#include "BasketListWidget.hpp"

#include <Wt/WText>
#include <Wt/WTable>
#include <Wt/WImage>
#include <Wt/WPushButton>
#include <boost/format.hpp>
#include <sstream>
#include <boost/foreach.hpp>
#include <boost/log/trivial.hpp>
#include <boost/lexical_cast.hpp>

#include "../user/Session.hpp"
#include "../application.hpp"

BasketListWidget::BasketListWidget(ShopList shops, dbo::Query<PItem> query, bool showRemoveButtons, Wt::WContainerWidget *parent)
:Wt::WPanel(parent),
query(query),
shops(shops),
showRemoveButtons(showRemoveButtons)
{
	setCollapsible(true);
	root = new Wt::WContainerWidget();
	setCentralWidget(root);
}

void BasketListWidget::update()
{
	root->clear();
	userSums.clear();
	Session& dbSession = static_cast<ShareBuy*>(Wt::WApplication::instance())->dbSession;
	dbo::Transaction transaction(dbSession);

	PItems database_items = query; // execute query
	std::set<PItem> items(database_items.begin(),database_items.end());

	// main table
	Wt::WTable *table = new Wt::WTable(root);
	table->setHeaderCount(1);
	table->setWidth(Wt::WLength("100%"));

	table->elementAt(0, 0)->addWidget(new Wt::WText(""));
	table->elementAt(0, 1)->addWidget(new Wt::WText("Number"));
	table->elementAt(0, 2)->addWidget(new Wt::WText("Title"));
	table->elementAt(0, 3)->addWidget(new Wt::WText("Count"));
	table->elementAt(0, 4)->addWidget(new Wt::WText("Price"));
	table->elementAt(0, 5)->addWidget(new Wt::WText("Total"));

	size_t number=0;
	BOOST_FOREACH(PItem item,items)
	{
		std::cout<<"item "<<number<<"\n";
		shared_ptr<Shop> shop = (*shops)[item->shop_name];
		string imageURL = item->formatInto(shop->imageTemplate, number);
		table->elementAt(number+1,0)->addWidget(new Wt::WImage(imageURL));
		table->elementAt(number+1,1)->addWidget(new Wt::WText(item->shop_specific_id+" / "+item->shop_specific_id_2));
		table->elementAt(number+1,2)->addWidget(new Wt::WAnchor(Wt::WLink(item->url),item->title));
		table->elementAt(number+1,3)->addWidget(new Wt::WText(boost::lexical_cast<string>(item->count)));
		table->elementAt(number+1,4)->addWidget(new Wt::WText((boost::format(priceFmt) % item->price).str()));
		table->elementAt(number+1,5)->addWidget(new Wt::WText((boost::format(priceFmt) % (item->count*item->price)).str()));
		userSums[item->user]+=item->count*item->price;
		if( showRemoveButtons )
		{
			Wt::WPushButton *btn = new Wt::WPushButton("remove");
			if( item->order)
			{
				btn->clicked().connect([this, &dbSession, item](Wt::WMouseEvent event) mutable
				{
					dbo::Transaction transaction(dbSession);
					item->order.modify()->items.erase(item);
					transaction.commit();
					update();
				});
			}
			else
			{
				btn->clicked().connect([this, &dbSession, item](Wt::WMouseEvent event) mutable
				{
					dbo::Transaction transaction(dbSession);
					item.remove();
					transaction.commit();
					update();
				});
			}
			table->elementAt(number+1,6)->addWidget(btn);
		}
		number++;
	}
}

OrderOverviewForOrderer::OrderOverviewForOrderer(ShopList shops, POrder order, Wt::WContainerWidget *parent)
//:BasketListWidget(shops, "", PUser(), orderId, parent)
:BasketListWidget(shops, static_cast<ShareBuy*>(Wt::WApplication::instance())->dbSession.find<Item>().where("ordering_id = ?").bind(order.id()).orderBy("user_id"), !order->orderTime.isValid(), parent)
{
	setTitleBar(true);

	Wt::WContainerWidget *title = new Wt::WContainerWidget(titleBarWidget());
	title->addStyleClass("accordion-toggle");

	title->addWidget(new Wt::WText("Order"));

	confirmOrder = new Wt::WContainerWidget();
	confirmOrder->setInline(true);
	title->addWidget(confirmOrder);

	confirmReceive = new Wt::WContainerWidget();
	confirmReceive->setInline(true);
	title->addWidget(confirmReceive);

	if(order->orderTime.isValid())
	{
		confirmOrder->addWidget(new Wt::WText("; ordered "+order->orderTime.timeTo(Wt::WDateTime::currentDateTime())+" ago"));
		if(order->receiveTime.isValid())
		{
			confirmReceive->addWidget(new Wt::WText("; received "+order->receiveTime.timeTo(Wt::WDateTime::currentDateTime())+" ago"));
		}
		else
		{
			Wt::WPushButton *btn = new Wt::WPushButton("received");
			btn->clicked().connect(std::bind([this, order, btn]()
			{
				Session& dbSession = static_cast<ShareBuy*>(Wt::WApplication::instance())->dbSession;
				dbo::Transaction transaction(dbSession);

				order.modify()->receiveTime = Wt::WDateTime::currentDateTime();
				delete btn;
				confirmReceive->addWidget(new Wt::WText("; received "+order->receiveTime.timeTo(Wt::WDateTime::currentDateTime())+" ago"));

				update();
			}));
			title->addWidget(btn);
		}
	}
	else
	{
		Wt::WPushButton *btn = new Wt::WPushButton("confirm");
		btn->clicked().connect(std::bind([this, order, btn]()
		{
			Session& dbSession = static_cast<ShareBuy*>(Wt::WApplication::instance())->dbSession;
			dbo::Transaction transaction(dbSession);

			order.modify()->orderTime = Wt::WDateTime::currentDateTime();
			delete btn;
			confirmOrder->addWidget(new Wt::WText("; ordered "+order->orderTime.timeTo(Wt::WDateTime::currentDateTime())+" ago"));

			showRemoveButtons = false;
			update();
		}));
		title->addWidget(btn);
	}
}

void OrderOverviewForOrderer::update()
{
	BasketListWidget::update();

	Session& dbSession = static_cast<ShareBuy*>(Wt::WApplication::instance())->dbSession;
	dbo::Transaction transaction(dbSession);

	PItems database_items = query; // execute query
	std::set<PItem> items(database_items.begin(),database_items.end());

	// show per-user financial overview
	//if(userId == "")
	{
		double totalSum = 0.0;
		Wt::WTable *table2 = new Wt::WTable(root);
		table2->setHeaderCount(1);
		table2->setWidth(Wt::WLength("30%"));
		table2->elementAt(0, 0)->addWidget(new Wt::WText("User"));
		table2->elementAt(0, 1)->addWidget(new Wt::WText("Total"));

		size_t row=1;
		BOOST_FOREACH(auto it, userSums)
		{
			totalSum+=it.second;
			table2->elementAt(row, 0)->addWidget(new Wt::WAnchor(Wt::WLink(Wt::WLink::Type::InternalPath, "/user/profile/"+boost::lexical_cast<string>(it.first.id())),it.first->getUsername()));
			table2->elementAt(row, 1)->addWidget(new Wt::WText((boost::format(priceFmt) % it.second).str()));
			row++;
		}
		if(userSums.size()>1)
		{
			table2->elementAt(row, 0)->addWidget(new Wt::WText("Total"));
			table2->elementAt(row, 1)->addWidget(new Wt::WText((boost::format(priceFmt) % totalSum).str()));
		}
	}

	if( !(items.empty()) )
	{
		std::cerr<<"item!\n";
		auto it = items.begin();
		string itemShopName = (*it)->shop_name;
		bool ok = true;
		for(;it!=items.end();it++)
		{
			std::cerr<<"item!\n";
			if((*it)->shop_name!=itemShopName)
			{
				ok=false;
				break;
			}
		}
		if(ok)
			root->addWidget((*shops)[itemShopName]->basketAdd->getBasketAddWidget(items));
	}

}

OrderOverviewForWisher::OrderOverviewForWisher(ShopList shops, POrder order, PUser user, Wt::WContainerWidget *parent)
:BasketListWidget(shops, static_cast<ShareBuy*>(Wt::WApplication::instance())->dbSession.find<Item>().where("ordering_id = ?").bind(order.id()).where("user_id = ?").bind(user.id()), false, parent)
{
	setTitleBar(true);

	Wt::WContainerWidget *title = new Wt::WContainerWidget(titleBarWidget());
	title->addStyleClass("accordion-toggle");

	title->addWidget(new Wt::WText("Ordered by "));
	title->addWidget(new Wt::WAnchor(Wt::WLink(Wt::WLink::Type::InternalPath, "/user/profile/"+boost::lexical_cast<string>(order->user.id())),order->user->getUsername()));
	title->addWidget(new Wt::WText("; total: "));
	totalDisplay = new Wt::WText("???");
	title->addWidget(totalDisplay);

	if(order->orderTime.isValid())
	{
		title->addWidget(new Wt::WText("; ordered "+order->orderTime.timeTo(Wt::WDateTime::currentDateTime())+" ago"));
		if(order->receiveTime.isValid())
			title->addWidget(new Wt::WText("; received "+order->receiveTime.timeTo(Wt::WDateTime::currentDateTime())+" ago"));
	}
	else
		title->addWidget(new Wt::WText("; order not confirmed yet"));
}

void OrderOverviewForWisher::update()
{
	BasketListWidget::update();
	double totalSum = userSums.begin()->second; // only one entry -> use the first
	totalDisplay->setText((boost::format(priceFmt) % totalSum).str());
}

WishlistForOrderer::WishlistForOrderer(ShopList shops, string shopname, Wt::WContainerWidget *parent)
:BasketListWidget(shops, static_cast<ShareBuy*>(Wt::WApplication::instance())->dbSession.find<Item>().where("shop_name = ?").bind(shopname).where("ordering_id is null"), false, parent)
{
	setTitle("Detailed list of items");
}

void WishlistForOrderer::update()
{
	BasketListWidget::update();
}

WishlistForWisher::WishlistForWisher(ShopList shops, PUser user, Wt::WContainerWidget *parent)
:BasketListWidget(shops, static_cast<ShareBuy*>(Wt::WApplication::instance())->dbSession.find<Item>().where("user_id = ?").bind(user.id()).where("ordering_id is null"), true, parent)
{
	setTitle("Your items");
}

void WishlistForWisher::update()
{
	BasketListWidget::update();
}

/*
	dbo::Query<PItem> query = dbSession.find<Item>();
	if(user)
	{
		query.where("user_id = ?").bind(user.id());
	}
	else
		query.orderBy("user_id");
	if(orderId != "")
	{
		query.where("ordering_id = ?").bind(orderId);
	}
	if(shopName != "")
	{
		query.where("shop_name = ?").bind(shopName);
	}
	if(showOnlyOrderStatus)
	{
		if(orderStatus)
			query.where("not ordering_id is null");
		else
			query.where("ordering_id is null");
	}
	query.orderBy("user_id");
*/
<commit_msg>Eyecandy<commit_after>#include "BasketListWidget.hpp"

#include <Wt/WText>
#include <Wt/WTable>
#include <Wt/WImage>
#include <Wt/WPushButton>
#include <boost/format.hpp>
#include <sstream>
#include <boost/foreach.hpp>
#include <boost/log/trivial.hpp>
#include <boost/lexical_cast.hpp>

#include "../user/Session.hpp"
#include "../application.hpp"

BasketListWidget::BasketListWidget(ShopList shops, dbo::Query<PItem> query, bool showRemoveButtons, Wt::WContainerWidget *parent)
:Wt::WPanel(parent),
query(query),
shops(shops),
showRemoveButtons(showRemoveButtons)
{
	setCollapsible(true);
	root = new Wt::WContainerWidget();
	setCentralWidget(root);
}

void BasketListWidget::update()
{
	root->clear();
	userSums.clear();
	Session& dbSession = static_cast<ShareBuy*>(Wt::WApplication::instance())->dbSession;
	dbo::Transaction transaction(dbSession);

	PItems database_items = query; // execute query
	std::set<PItem> items(database_items.begin(),database_items.end());

	// main table
	Wt::WTable *table = new Wt::WTable(root);
	table->setHeaderCount(1);
	table->setWidth(Wt::WLength("100%"));

	table->elementAt(0, 0)->addWidget(new Wt::WText(""));
	table->elementAt(0, 1)->addWidget(new Wt::WText("Number"));
	table->elementAt(0, 2)->addWidget(new Wt::WText("Title"));
	table->elementAt(0, 3)->addWidget(new Wt::WText("Count"));
	table->elementAt(0, 4)->addWidget(new Wt::WText("Price"));
	table->elementAt(0, 5)->addWidget(new Wt::WText("Total"));

	size_t number=0;
	BOOST_FOREACH(PItem item,items)
	{
		std::cout<<"item "<<number<<"\n";
		shared_ptr<Shop> shop = (*shops)[item->shop_name];
		string imageURL = item->formatInto(shop->imageTemplate, number);
		table->elementAt(number+1,0)->addWidget(new Wt::WImage(imageURL));
		table->elementAt(number+1,1)->addWidget(new Wt::WText(item->shop_specific_id+" / "+item->shop_specific_id_2));
		table->elementAt(number+1,2)->addWidget(new Wt::WAnchor(Wt::WLink(item->url),item->title));
		table->elementAt(number+1,3)->addWidget(new Wt::WText(boost::lexical_cast<string>(item->count)));
		table->elementAt(number+1,4)->addWidget(new Wt::WText((boost::format(priceFmt) % item->price).str()));
		table->elementAt(number+1,5)->addWidget(new Wt::WText((boost::format(priceFmt) % (item->count*item->price)).str()));
		userSums[item->user]+=item->count*item->price;
		if( showRemoveButtons )
		{
			Wt::WPushButton *btn = new Wt::WPushButton("remove");
			if( item->order)
			{
				btn->clicked().connect([this, &dbSession, item](Wt::WMouseEvent event) mutable
				{
					dbo::Transaction transaction(dbSession);
					item->order.modify()->items.erase(item);
					transaction.commit();
					update();
				});
			}
			else
			{
				btn->clicked().connect([this, &dbSession, item](Wt::WMouseEvent event) mutable
				{
					dbo::Transaction transaction(dbSession);
					item.remove();
					transaction.commit();
					update();
				});
			}
			table->elementAt(number+1,6)->addWidget(btn);
		}
		number++;
	}
}

OrderOverviewForOrderer::OrderOverviewForOrderer(ShopList shops, POrder order, Wt::WContainerWidget *parent)
//:BasketListWidget(shops, "", PUser(), orderId, parent)
:BasketListWidget(shops, static_cast<ShareBuy*>(Wt::WApplication::instance())->dbSession.find<Item>().where("ordering_id = ?").bind(order.id()).orderBy("user_id"), !order->orderTime.isValid(), parent)
{
	setTitleBar(true);

	Wt::WContainerWidget *title = new Wt::WContainerWidget(titleBarWidget());
	title->addStyleClass("accordion-toggle");

	title->addWidget(new Wt::WText("Order"));

	confirmOrder = new Wt::WContainerWidget();
	confirmOrder->setInline(true);
	title->addWidget(confirmOrder);

	confirmReceive = new Wt::WContainerWidget();
	confirmReceive->setInline(true);
	title->addWidget(confirmReceive);

	if(order->orderTime.isValid())
	{
		confirmOrder->addWidget(new Wt::WText("; ordered "+order->orderTime.timeTo(Wt::WDateTime::currentDateTime())+" ago"));
		if(order->receiveTime.isValid())
		{
			confirmReceive->addWidget(new Wt::WText("; received "+order->receiveTime.timeTo(Wt::WDateTime::currentDateTime())+" ago"));
		}
		else
		{
			Wt::WPushButton *btn = new Wt::WPushButton("received");
			btn->clicked().connect(std::bind([this, order, btn]()
			{
				Session& dbSession = static_cast<ShareBuy*>(Wt::WApplication::instance())->dbSession;
				dbo::Transaction transaction(dbSession);

				order.modify()->receiveTime = Wt::WDateTime::currentDateTime();
				delete btn;
				confirmReceive->addWidget(new Wt::WText("; received "+order->receiveTime.timeTo(Wt::WDateTime::currentDateTime())+" ago"));

				update();
			}));
			title->addWidget(btn);
		}
	}
	else
	{
		Wt::WPushButton *btn = new Wt::WPushButton("confirm");
		btn->clicked().connect(std::bind([this, order, btn]()
		{
			Session& dbSession = static_cast<ShareBuy*>(Wt::WApplication::instance())->dbSession;
			dbo::Transaction transaction(dbSession);

			order.modify()->orderTime = Wt::WDateTime::currentDateTime();
			delete btn;
			confirmOrder->addWidget(new Wt::WText("; ordered "+order->orderTime.timeTo(Wt::WDateTime::currentDateTime())+" ago"));

			showRemoveButtons = false;
			update();
		}));
		title->addWidget(btn);
	}
}

void OrderOverviewForOrderer::update()
{
	BasketListWidget::update();

	Session& dbSession = static_cast<ShareBuy*>(Wt::WApplication::instance())->dbSession;
	dbo::Transaction transaction(dbSession);

	PItems database_items = query; // execute query
	std::set<PItem> items(database_items.begin(),database_items.end());

	// show per-user financial overview
	//if(userId == "")
	{
		double totalSum = 0.0;
		Wt::WTable *table2 = new Wt::WTable(root);
		table2->setHeaderCount(1);
		table2->setWidth(Wt::WLength("30%"));
		table2->elementAt(0, 0)->addWidget(new Wt::WText("User"));
		table2->elementAt(0, 1)->addWidget(new Wt::WText("Total"));

		size_t row=1;
		BOOST_FOREACH(auto it, userSums)
		{
			totalSum+=it.second;
			table2->elementAt(row, 0)->addWidget(new Wt::WAnchor(Wt::WLink(Wt::WLink::Type::InternalPath, "/user/profile/"+boost::lexical_cast<string>(it.first.id())),it.first->getUsername()));
			table2->elementAt(row, 1)->addWidget(new Wt::WText((boost::format(priceFmt) % it.second).str()));
			row++;
		}
		if(userSums.size()>1)
		{
			table2->elementAt(row, 0)->addWidget(new Wt::WText("Total"));
			table2->elementAt(row, 1)->addWidget(new Wt::WText((boost::format(priceFmt) % totalSum).str()));
		}
	}

	if( !(items.empty()) )
	{
		std::cerr<<"item!\n";
		auto it = items.begin();
		string itemShopName = (*it)->shop_name;
		bool ok = true;
		for(;it!=items.end();it++)
		{
			std::cerr<<"item!\n";
			if((*it)->shop_name!=itemShopName)
			{
				ok=false;
				break;
			}
		}
		if(ok)
			root->addWidget((*shops)[itemShopName]->basketAdd->getBasketAddWidget(items));
	}

}

OrderOverviewForWisher::OrderOverviewForWisher(ShopList shops, POrder order, PUser user, Wt::WContainerWidget *parent)
:BasketListWidget(shops, static_cast<ShareBuy*>(Wt::WApplication::instance())->dbSession.find<Item>().where("ordering_id = ?").bind(order.id()).where("user_id = ?").bind(user.id()), false, parent)
{
	setTitleBar(true);

	Wt::WContainerWidget *title = new Wt::WContainerWidget(titleBarWidget());
	title->addStyleClass("accordion-toggle");

	title->addWidget(new Wt::WText("Ordered by "));
	title->addWidget(new Wt::WAnchor(Wt::WLink(Wt::WLink::Type::InternalPath, "/user/profile/"+boost::lexical_cast<string>(order->user.id())),order->user->getUsername()));
	title->addWidget(new Wt::WText("; total: "));
	totalDisplay = new Wt::WText("???");
	title->addWidget(totalDisplay);

	if(order->orderTime.isValid())
	{
		title->addWidget(new Wt::WText("; ordered "+order->orderTime.timeTo(Wt::WDateTime::currentDateTime())+" ago"));
		if(order->receiveTime.isValid())
			title->addWidget(new Wt::WText("; received "+order->receiveTime.timeTo(Wt::WDateTime::currentDateTime())+" ago"));
		else
			title->addWidget(new Wt::WText("; not received yet"));
	}
	else
		title->addWidget(new Wt::WText("; order not confirmed yet"));
}

void OrderOverviewForWisher::update()
{
	BasketListWidget::update();
	double totalSum = userSums.begin()->second; // only one entry -> use the first
	totalDisplay->setText("<b>"+(boost::format(priceFmt) % totalSum).str()+"</b>");
}

WishlistForOrderer::WishlistForOrderer(ShopList shops, string shopname, Wt::WContainerWidget *parent)
:BasketListWidget(shops, static_cast<ShareBuy*>(Wt::WApplication::instance())->dbSession.find<Item>().where("shop_name = ?").bind(shopname).where("ordering_id is null"), false, parent)
{
	setTitle("Detailed list of items");
}

void WishlistForOrderer::update()
{
	BasketListWidget::update();
}

WishlistForWisher::WishlistForWisher(ShopList shops, PUser user, Wt::WContainerWidget *parent)
:BasketListWidget(shops, static_cast<ShareBuy*>(Wt::WApplication::instance())->dbSession.find<Item>().where("user_id = ?").bind(user.id()).where("ordering_id is null"), true, parent)
{
	setTitle("Your items");
}

void WishlistForWisher::update()
{
	BasketListWidget::update();
}

/*
	dbo::Query<PItem> query = dbSession.find<Item>();
	if(user)
	{
		query.where("user_id = ?").bind(user.id());
	}
	else
		query.orderBy("user_id");
	if(orderId != "")
	{
		query.where("ordering_id = ?").bind(orderId);
	}
	if(shopName != "")
	{
		query.where("shop_name = ?").bind(shopName);
	}
	if(showOnlyOrderStatus)
	{
		if(orderStatus)
			query.where("not ordering_id is null");
		else
			query.where("ordering_id is null");
	}
	query.orderBy("user_id");
*/
<|endoftext|>


<commit_before>#include "CPU.h"
#include <iostream>
#include <iomanip>
#include <functional>

typedef std::function<void(CPU* cpu)> CPUHandler;

enum RID {
	A, B, C, D, E, H, L
};
enum PID {
	AF, BC, DE, HL, SP, PC
};

uint8_t* getRegister(CPU* cpu, RID id) {
	switch (id) {
	case A: return &(cpu->AF.Single.A);
	case B: return &(cpu->BC.Single.B);
	case C: return &(cpu->BC.Single.C);
	case D: return &(cpu->DE.Single.D);
	case E: return &(cpu->DE.Single.E);
	case H: return &(cpu->HL.Single.H);
	case L: return &(cpu->HL.Single.L);
	}
	return nullptr;
}

uint16_t* getPair(CPU* cpu, PID id) {
	switch (id) {
	case AF: return &(cpu->AF.Pair);
	case BC: return &(cpu->BC.Pair);
	case DE: return &(cpu->DE.Pair);
	case HL: return &(cpu->HL.Pair);
	case SP: return &(cpu->SP);
	case PC: return &(cpu->PC);
	}
	return nullptr;
}

// Do nothing
void Nop(CPU* cpu) {
	cpu->cycles.add(1, 4);
}

// Stop or halt the processor
CPUHandler Halt(bool waitInterrupt) {
	//Todo handle waitInterrupt (for HALT)
	return [waitInterrupt](CPU *cpu) {
		// STOP takes two machine cycles
		int mcycles = waitInterrupt ? 1 : 2;

		cpu->cycles.add(mcycles, 4);
		cpu->running = false;
	};
}

// Direct Load (Register to Register)
CPUHandler LoadDirect(RID src, RID dst) {
	return [src, dst](CPU* cpu) {
		uint8_t* srcRes = getRegister(cpu, src);
		uint8_t* dstRes = getRegister(cpu, dst);
		*dstRes = *srcRes;
		cpu->cycles.add(1, 4);
	};
}

// Immediate Load (8bit constant to Register)
CPUHandler LoadImmediate(RID dst) {
	return [dst](CPU* cpu) {
		uint8_t* dstRes = getRegister(cpu, dst);
		// Get next byte
		cpu->PC++;
		uint8_t value = cpu->Read(cpu->PC);

		// Assign to register
		*dstRes = value;

		cpu->cycles.add(2, 8);
	};
}

// Increment register (8bit, immediate)
CPUHandler Increment(RID dst) {
	return [dst](CPU* cpu) {
		uint8_t* dstRes = getRegister(cpu, dst);
		dstRes++;
		cpu->Status.Single.Zero = dstRes == 0;
		cpu->Status.Single.BCD_AddSub = 0;
		cpu->Status.Single.BCD_HalfCarry = (*dstRes & 0x0f) > 9;
		cpu->cycles.add(1,4);
	};
}

// Increment register (16bit, immediate)
CPUHandler Increment(PID dst) {
	return [dst](CPU* cpu) {
		uint16_t* dstRes = getPair(cpu, dst);
		dstRes++;
		cpu->cycles.add(1,8);
	};
}

// Increment register (8bit, immediate)
CPUHandler Decrement(RID dst) {
	return [dst](CPU* cpu) {
		uint8_t* dstRes = getRegister(cpu, dst);
		dstRes--;
		cpu->Status.Single.Zero = dstRes == 0;
		cpu->Status.Single.BCD_AddSub = 1;
		cpu->Status.Single.BCD_HalfCarry = (*dstRes & 0x0f) > 9;
		cpu->cycles.add(1,4);
	};
}

// Increment register (16bit, immediate)
CPUHandler Decrement(PID dst) {
	return [dst](CPU* cpu) {
		uint16_t* dstRes = getPair(cpu, dst);
		dstRes--;
		cpu->cycles.add(1,8);
	};
}

// Unimplemented instruction
void Todo(CPU* cpu) {
	std::cout << "Unknown Opcode: " << std::setfill('0') << std::setw(2) << std::hex << (int)cpu->Read(cpu->PC) << std::endl;
}

const static CPUHandler handlers[] = {
	Nop,  // 00 NOP
	Todo, // 01
	Todo, // 02
	Increment(BC), // 03 INC BC
	Increment(B),  // 04 INC B
	Decrement(B),  // 05 DEC B
	LoadImmediate(B), // 06 LD B,d8
	Todo, // 07
	Todo, // 08
	Todo, // 09
	Todo, // 0a
	Decrement(BC), // 0b DEC BC
	Increment(C),  // 0c INC C
	Decrement(C),  // 0d DEC C
	LoadImmediate(C), // 0e LD C,d8
	Todo, // 0f
	Halt(false), // 10 STOP
	Todo, // 11
	Todo, // 12
	Increment(DE), // 13 INC DE
	Increment(D),  // 14 INC D
	Decrement(D),  // 15 DEC D
	LoadImmediate(D), // 16 LD D,d8
	Todo, // 17
	Decrement(DE), // 18 DEC DE
	Increment(E),  // 19 DEC E
	Decrement(E),  // 1a DEC E
	Todo, // 1b
	Todo, // 1c
	Todo, // 1d
	LoadImmediate(E), // 1e LD E,d8
	Todo, // 1f
	Todo, // 20
	Todo, // 21
	Todo, // 22
	Increment(HL), // 23 INC HL
	Increment(H),  // 24 INC H
	Decrement(H),  // 25 DEC H
	LoadImmediate(H), // 26 LD H,d8
	Todo, // 27
	Decrement(HL), // 28 DEC HL
	Increment(L),  // 29 INC L
	Decrement(L),  // 2a DEC L
	Todo, // 2b
	Todo, // 2c
	Todo, // 2d
	LoadImmediate(L), // 2e LD L,d8
	Todo, // 2f
	Todo, // 30
	Todo, // 31
	Todo, // 32
	Increment(SP), // 33 INC SP
	Todo, // 34
	Todo, // 35
	Todo, // 36
	Todo, // 37
	Decrement(SP), // 38 DEC SP
	Increment(A),  // 39 INC A
	Decrement(A),  // 3a DEC A
	Todo, // 3b
	Todo, // 3c
	Todo, // 3d
	LoadImmediate(A), // 3e LD A,d8
	Todo, // 3f
	LoadDirect(B, B), // 40 LD B,B
	LoadDirect(B, C), // 41 LD B,C
	LoadDirect(B, D), // 42 LD B,D
	LoadDirect(B, E), // 43 LD B,E
	LoadDirect(B, H), // 44 LD B,H
	LoadDirect(B, L), // 45 LD B,L
	Todo, // 46
	LoadDirect(B, A), // 47 LD B,A
	LoadDirect(C, B), // 48 LD C,B
	LoadDirect(C, C), // 49 LD C,C
	LoadDirect(C, D), // 4a LD C,D
	LoadDirect(C, E), // 4b LD C,E
	LoadDirect(C, H), // 4c LD C,H
	LoadDirect(C, L), // 4d LD C,L
	Todo, // 4e
	LoadDirect(C, A), // 4f LD C,A
	LoadDirect(D, B), // 50 LD D,B
	LoadDirect(D, C), // 51 LD D,C
	LoadDirect(D, D), // 52 LD D,D
	LoadDirect(D, E), // 53 LD D,E
	LoadDirect(D, H), // 54 LD D,H
	LoadDirect(D, L), // 55 LD D,L
	Todo, // 56
	LoadDirect(D, A), // 57 LD D,A
	LoadDirect(E, B), // 58 LD E,B
	LoadDirect(E, C), // 59 LD E,C
	LoadDirect(E, D), // 5a LD E,D
	LoadDirect(E, E), // 5b LD E,E
	LoadDirect(E, H), // 5c LD E,H
	LoadDirect(E, L), // 5d LD E,L
	Todo, // 5e
	LoadDirect(E, A), // 5f LD E,A
	LoadDirect(H, B), // 60 LD H,B
	LoadDirect(H, C), // 61 LD H,C
	LoadDirect(H, D), // 62 LD H,D
	LoadDirect(H, E), // 63 LD H,E
	LoadDirect(H, H), // 64 LD H,H
	LoadDirect(H, L), // 65 LD H,L
	Todo, // 66
	LoadDirect(H, A), // 67 LD H,A
	LoadDirect(L, B), // 68 LD L,B
	LoadDirect(L, C), // 69 LD L,C
	LoadDirect(L, D), // 6a LD L,D
	LoadDirect(L, E), // 6b LD L,E
	LoadDirect(L, H), // 6c LD L,H
	LoadDirect(L, L), // 6d LD L,L
	Todo, // 6e
	LoadDirect(L, A), // 6f LD L,A
	Todo, // 70
	Todo, // 71
	Todo, // 72
	Todo, // 73
	Todo, // 74
	Todo, // 75
	Halt(true), // 76 HALT
	Todo, // 77
	LoadDirect(A, B), // 78 LD A,B
	LoadDirect(A, C), // 79 LD A,C
	LoadDirect(A, D), // 7a LD A,D
	LoadDirect(A, E), // 7b LD A,E
	LoadDirect(A, H), // 7c LD A,H
	LoadDirect(A, L), // 7d LD A,L
	Todo, // 7e
	LoadDirect(A, A), // 7f LD A,A
	Todo, // 80
	Todo, // 81
	Todo, // 82
	Todo, // 83
	Todo, // 84
	Todo, // 85
	Todo, // 86
	Todo, // 87
	Todo, // 88
	Todo, // 89
	Todo, // 8a
	Todo, // 8b
	Todo, // 8c
	Todo, // 8d
	Todo, // 8e
	Todo, // 8f
	Todo, // 90
	Todo, // 91
	Todo, // 92
	Todo, // 93
	Todo, // 94
	Todo, // 95
	Todo, // 96
	Todo, // 97
	Todo, // 98
	Todo, // 99
	Todo, // 9a
	Todo, // 9b
	Todo, // 9c
	Todo, // 9d
	Todo, // 9e
	Todo, // 9f
	Todo, // a0
	Todo, // a1
	Todo, // a2
	Todo, // a3
	Todo, // a4
	Todo, // a5
	Todo, // a6
	Todo, // a7
	Todo, // a8
	Todo, // a9
	Todo, // aa
	Todo, // ab
	Todo, // ac
	Todo, // ad
	Todo, // ae
	Todo, // af
	Todo, // b0
	Todo, // b1
	Todo, // b2
	Todo, // b3
	Todo, // b4
	Todo, // b5
	Todo, // b6
	Todo, // b7
	Todo, // b8
	Todo, // b9
	Todo, // ba
	Todo, // bb
	Todo, // bc
	Todo, // bd
	Todo, // be
	Todo, // bf
	Todo, // c0
	Todo, // c1
	Todo, // c2
	Todo, // c3
	Todo, // c4
	Todo, // c5
	Todo, // c6
	Todo, // c7
	Todo, // c8
	Todo, // c9
	Todo, // ca
	Todo, // cb
	Todo, // cc
	Todo, // cd
	Todo, // ce
	Todo, // cf
	Todo, // d0
	Todo, // d1
	Todo, // d2
	Todo, // d3
	Todo, // d4
	Todo, // d5
	Todo, // d6
	Todo, // d7
	Todo, // d8
	Todo, // d9
	Todo, // da
	Todo, // db
	Todo, // dc
	Todo, // dd
	Todo, // de
	Todo, // df
	Todo, // e0
	Todo, // e1
	Todo, // e2
	Todo, // e3
	Todo, // e4
	Todo, // e5
	Todo, // e6
	Todo, // e7
	Todo, // e8
	Todo, // e9
	Todo, // ea
	Todo, // eb
	Todo, // ec
	Todo, // ed
	Todo, // ee
	Todo, // ef
	Todo, // f0
	Todo, // f1
	Todo, // f2
	Todo, // f3
	Todo, // f4
	Todo, // f5
	Todo, // f6
	Todo, // f7
	Todo, // f8
	Todo, // f9
	Todo, // fa
	Todo, // fb
	Todo, // fc
	Todo, // fd
	Todo, // fe
	Todo  // ff
};

void CPU::Execute(uint8_t opcode) {
	handlers[opcode](this);
}
<commit_msg>Added 16bit Immediate load<commit_after>#include "CPU.h"
#include <iostream>
#include <iomanip>
#include <functional>

typedef std::function<void(CPU* cpu)> CPUHandler;

enum RID {
	A, B, C, D, E, H, L
};
enum PID {
	AF, BC, DE, HL, SP, PC
};

uint8_t* getRegister(CPU* cpu, RID id) {
	switch (id) {
	case A: return &(cpu->AF.Single.A);
	case B: return &(cpu->BC.Single.B);
	case C: return &(cpu->BC.Single.C);
	case D: return &(cpu->DE.Single.D);
	case E: return &(cpu->DE.Single.E);
	case H: return &(cpu->HL.Single.H);
	case L: return &(cpu->HL.Single.L);
	}
	return nullptr;
}

uint16_t* getPair(CPU* cpu, PID id) {
	switch (id) {
	case AF: return &(cpu->AF.Pair);
	case BC: return &(cpu->BC.Pair);
	case DE: return &(cpu->DE.Pair);
	case HL: return &(cpu->HL.Pair);
	case SP: return &(cpu->SP);
	case PC: return &(cpu->PC);
	}
	return nullptr;
}

// Do nothing
void Nop(CPU* cpu) {
	cpu->cycles.add(1, 4);
}

// Stop or halt the processor
CPUHandler Halt(bool waitInterrupt) {
	//Todo handle waitInterrupt (for HALT)
	return [waitInterrupt](CPU *cpu) {
		// STOP takes two machine cycles
		int mcycles = waitInterrupt ? 1 : 2;

		cpu->cycles.add(mcycles, 4);
		cpu->running = false;
	};
}

// Direct Load (Register to Register)
CPUHandler LoadDirect(RID src, RID dst) {
	return [src, dst](CPU* cpu) {
		uint8_t* srcRes = getRegister(cpu, src);
		uint8_t* dstRes = getRegister(cpu, dst);
		*dstRes = *srcRes;
		cpu->cycles.add(1, 4);
	};
}

// Immediate Load (8bit constant to Register)
CPUHandler LoadImmediate(RID dst) {
	return [dst](CPU* cpu) {
		uint8_t* dstRes = getRegister(cpu, dst);
		// Get next byte
		uint8_t value = cpu->Read(++cpu->PC);

		// Assign to register
		*dstRes = value;

		cpu->cycles.add(2, 8);
	};
}

// Immediate Load (16bit constant to register pair)
CPUHandler LoadImmediate(PID dst) {
	return [dst](CPU* cpu) {
		uint16_t* dstRes = getPair(cpu, dst);
		// Get next bytes
		uint8_t  low  = cpu->Read(++cpu->PC);
		uint8_t  high = cpu->Read(++cpu->PC);
		uint16_t word = (high << 8) + low;

		*dstRes = word;
		cpu->cycles.add(3, 12);
	};
}

// Increment register (8bit, immediate)
CPUHandler Increment(RID dst) {
	return [dst](CPU* cpu) {
		uint8_t* dstRes = getRegister(cpu, dst);
		dstRes++;
		cpu->Status.Single.Zero = dstRes == 0;
		cpu->Status.Single.BCD_AddSub = 0;
		cpu->Status.Single.BCD_HalfCarry = (*dstRes & 0x0f) > 9;
		cpu->cycles.add(1,4);
	};
}

// Increment register (16bit, immediate)
CPUHandler Increment(PID dst) {
	return [dst](CPU* cpu) {
		uint16_t* dstRes = getPair(cpu, dst);
		dstRes++;
		cpu->cycles.add(1,8);
	};
}

// Increment register (8bit, immediate)
CPUHandler Decrement(RID dst) {
	return [dst](CPU* cpu) {
		uint8_t* dstRes = getRegister(cpu, dst);
		dstRes--;
		cpu->Status.Single.Zero = dstRes == 0;
		cpu->Status.Single.BCD_AddSub = 1;
		cpu->Status.Single.BCD_HalfCarry = (*dstRes & 0x0f) > 9;
		cpu->cycles.add(1,4);
	};
}

// Increment register (16bit, immediate)
CPUHandler Decrement(PID dst) {
	return [dst](CPU* cpu) {
		uint16_t* dstRes = getPair(cpu, dst);
		dstRes--;
		cpu->cycles.add(1,8);
	};
}

// Unimplemented instruction
void Todo(CPU* cpu) {
	std::cout << "Unknown Opcode: " << std::setfill('0') << std::setw(2) << std::hex << (int)cpu->Read(cpu->PC) << std::endl;
}

const static CPUHandler handlers[] = {
	Nop,  // 00 NOP
	LoadImmediate(BC), // 01 LD BC,d16
	Todo, // 02
	Increment(BC), // 03 INC BC
	Increment(B),  // 04 INC B
	Decrement(B),  // 05 DEC B
	LoadImmediate(B), // 06 LD B,d8
	Todo, // 07
	Todo, // 08
	Todo, // 09
	Todo, // 0a
	Decrement(BC), // 0b DEC BC
	Increment(C),  // 0c INC C
	Decrement(C),  // 0d DEC C
	LoadImmediate(C), // 0e LD C,d8
	Todo, // 0f
	Halt(false), // 10 STOP
	LoadImmediate(DE), // 11 LD DE,d16
	Todo, // 12
	Increment(DE), // 13 INC DE
	Increment(D),  // 14 INC D
	Decrement(D),  // 15 DEC D
	LoadImmediate(D), // 16 LD D,d8
	Todo, // 17
	Decrement(DE), // 18 DEC DE
	Increment(E),  // 19 DEC E
	Decrement(E),  // 1a DEC E
	Todo, // 1b
	Todo, // 1c
	Todo, // 1d
	LoadImmediate(E), // 1e LD E,d8
	Todo, // 1f
	Todo, // 20
	LoadImmediate(HL), // 21 LD HL,d16
	Todo, // 22
	Increment(HL), // 23 INC HL
	Increment(H),  // 24 INC H
	Decrement(H),  // 25 DEC H
	LoadImmediate(H), // 26 LD H,d8
	Todo, // 27
	Decrement(HL), // 28 DEC HL
	Increment(L),  // 29 INC L
	Decrement(L),  // 2a DEC L
	Todo, // 2b
	Todo, // 2c
	Todo, // 2d
	LoadImmediate(L), // 2e LD L,d8
	Todo, // 2f
	Todo, // 30
	LoadImmediate(SP), // 31 LD SP,d16
	Todo, // 32
	Increment(SP), // 33 INC SP
	Todo, // 34
	Todo, // 35
	Todo, // 36
	Todo, // 37
	Decrement(SP), // 38 DEC SP
	Increment(A),  // 39 INC A
	Decrement(A),  // 3a DEC A
	Todo, // 3b
	Todo, // 3c
	Todo, // 3d
	LoadImmediate(A), // 3e LD A,d8
	Todo, // 3f
	LoadDirect(B, B), // 40 LD B,B
	LoadDirect(B, C), // 41 LD B,C
	LoadDirect(B, D), // 42 LD B,D
	LoadDirect(B, E), // 43 LD B,E
	LoadDirect(B, H), // 44 LD B,H
	LoadDirect(B, L), // 45 LD B,L
	Todo, // 46
	LoadDirect(B, A), // 47 LD B,A
	LoadDirect(C, B), // 48 LD C,B
	LoadDirect(C, C), // 49 LD C,C
	LoadDirect(C, D), // 4a LD C,D
	LoadDirect(C, E), // 4b LD C,E
	LoadDirect(C, H), // 4c LD C,H
	LoadDirect(C, L), // 4d LD C,L
	Todo, // 4e
	LoadDirect(C, A), // 4f LD C,A
	LoadDirect(D, B), // 50 LD D,B
	LoadDirect(D, C), // 51 LD D,C
	LoadDirect(D, D), // 52 LD D,D
	LoadDirect(D, E), // 53 LD D,E
	LoadDirect(D, H), // 54 LD D,H
	LoadDirect(D, L), // 55 LD D,L
	Todo, // 56
	LoadDirect(D, A), // 57 LD D,A
	LoadDirect(E, B), // 58 LD E,B
	LoadDirect(E, C), // 59 LD E,C
	LoadDirect(E, D), // 5a LD E,D
	LoadDirect(E, E), // 5b LD E,E
	LoadDirect(E, H), // 5c LD E,H
	LoadDirect(E, L), // 5d LD E,L
	Todo, // 5e
	LoadDirect(E, A), // 5f LD E,A
	LoadDirect(H, B), // 60 LD H,B
	LoadDirect(H, C), // 61 LD H,C
	LoadDirect(H, D), // 62 LD H,D
	LoadDirect(H, E), // 63 LD H,E
	LoadDirect(H, H), // 64 LD H,H
	LoadDirect(H, L), // 65 LD H,L
	Todo, // 66
	LoadDirect(H, A), // 67 LD H,A
	LoadDirect(L, B), // 68 LD L,B
	LoadDirect(L, C), // 69 LD L,C
	LoadDirect(L, D), // 6a LD L,D
	LoadDirect(L, E), // 6b LD L,E
	LoadDirect(L, H), // 6c LD L,H
	LoadDirect(L, L), // 6d LD L,L
	Todo, // 6e
	LoadDirect(L, A), // 6f LD L,A
	Todo, // 70
	Todo, // 71
	Todo, // 72
	Todo, // 73
	Todo, // 74
	Todo, // 75
	Halt(true), // 76 HALT
	Todo, // 77
	LoadDirect(A, B), // 78 LD A,B
	LoadDirect(A, C), // 79 LD A,C
	LoadDirect(A, D), // 7a LD A,D
	LoadDirect(A, E), // 7b LD A,E
	LoadDirect(A, H), // 7c LD A,H
	LoadDirect(A, L), // 7d LD A,L
	Todo, // 7e
	LoadDirect(A, A), // 7f LD A,A
	Todo, // 80
	Todo, // 81
	Todo, // 82
	Todo, // 83
	Todo, // 84
	Todo, // 85
	Todo, // 86
	Todo, // 87
	Todo, // 88
	Todo, // 89
	Todo, // 8a
	Todo, // 8b
	Todo, // 8c
	Todo, // 8d
	Todo, // 8e
	Todo, // 8f
	Todo, // 90
	Todo, // 91
	Todo, // 92
	Todo, // 93
	Todo, // 94
	Todo, // 95
	Todo, // 96
	Todo, // 97
	Todo, // 98
	Todo, // 99
	Todo, // 9a
	Todo, // 9b
	Todo, // 9c
	Todo, // 9d
	Todo, // 9e
	Todo, // 9f
	Todo, // a0
	Todo, // a1
	Todo, // a2
	Todo, // a3
	Todo, // a4
	Todo, // a5
	Todo, // a6
	Todo, // a7
	Todo, // a8
	Todo, // a9
	Todo, // aa
	Todo, // ab
	Todo, // ac
	Todo, // ad
	Todo, // ae
	Todo, // af
	Todo, // b0
	Todo, // b1
	Todo, // b2
	Todo, // b3
	Todo, // b4
	Todo, // b5
	Todo, // b6
	Todo, // b7
	Todo, // b8
	Todo, // b9
	Todo, // ba
	Todo, // bb
	Todo, // bc
	Todo, // bd
	Todo, // be
	Todo, // bf
	Todo, // c0
	Todo, // c1
	Todo, // c2
	Todo, // c3
	Todo, // c4
	Todo, // c5
	Todo, // c6
	Todo, // c7
	Todo, // c8
	Todo, // c9
	Todo, // ca
	Todo, // cb
	Todo, // cc
	Todo, // cd
	Todo, // ce
	Todo, // cf
	Todo, // d0
	Todo, // d1
	Todo, // d2
	Todo, // d3
	Todo, // d4
	Todo, // d5
	Todo, // d6
	Todo, // d7
	Todo, // d8
	Todo, // d9
	Todo, // da
	Todo, // db
	Todo, // dc
	Todo, // dd
	Todo, // de
	Todo, // df
	Todo, // e0
	Todo, // e1
	Todo, // e2
	Todo, // e3
	Todo, // e4
	Todo, // e5
	Todo, // e6
	Todo, // e7
	Todo, // e8
	Todo, // e9
	Todo, // ea
	Todo, // eb
	Todo, // ec
	Todo, // ed
	Todo, // ee
	Todo, // ef
	Todo, // f0
	Todo, // f1
	Todo, // f2
	Todo, // f3
	Todo, // f4
	Todo, // f5
	Todo, // f6
	Todo, // f7
	Todo, // f8
	Todo, // f9
	Todo, // fa
	Todo, // fb
	Todo, // fc
	Todo, // fd
	Todo, // fe
	Todo  // ff
};

void CPU::Execute(uint8_t opcode) {
	handlers[opcode](this);
}
<|endoftext|>


<commit_before><commit_msg>ajout CB opcode<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2014 Greenheart Games Pty. Ltd. All rights reserved.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include <string>

#include "nan.h"
#include "steam/steam_api.h"
#include "v8.h"

#include "greenworks_async_workers.h"

namespace {

NAN_METHOD(InitAPI) {
  NanScope();

  bool success = SteamAPI_Init();

  if (success) {
    ISteamUserStats* stream_user_stats = SteamUserStats();
    stream_user_stats->RequestCurrentStats();
  }

  NanReturnValue(NanNew(success));
}

NAN_METHOD(SaveTextToFile) {
  NanScope();

  if (args.Length() < 4) {
    NanThrowTypeError("Wrong numer of arguments, should be 4.");
    NanReturnUndefined();
  }

  std::string file_name(*(v8::String::Utf8Value(args[0])));
  std::string content(*(v8::String::Utf8Value(args[1])));
  NanCallback* successCallback = new NanCallback(args[2].As<v8::Function>());
  NanCallback* errorCallback = new NanCallback(args[3].As<v8::Function>());

  NanAsyncQueueWorker(new greenworks::FileSaveWorker(successCallback,
                                                     errorCallback,
                                                     file_name,
                                                     content));
  NanReturnUndefined();
}

NAN_METHOD(ReadTextFromFile) {
  NanScope();

  if (args.Length() < 3) {
    NanThrowTypeError("Wrong numer of arguments, should be 3.");
    NanReturnUndefined();
  }

  std::string file_name(*(v8::String::Utf8Value(args[0])));
  NanCallback* successCallback = new NanCallback(args[1].As<v8::Function>());
  NanCallback* errorCallback = new NanCallback(args[2].As<v8::Function>());

  NanAsyncQueueWorker(new greenworks::FileReadWorker(successCallback,
                                                     errorCallback,
                                                     file_name));
  NanReturnUndefined();
}

NAN_METHOD(IsCloudEnabled) {
  NanScope();
  ISteamRemoteStorage* steam_remote_storage = SteamRemoteStorage();
  NanReturnValue(NanNew<v8::Boolean>(
      steam_remote_storage->IsCloudEnabledForApp()));
}

NAN_METHOD(EnableCloud) {
  NanScope();

  if (args.Length() < 1) {
    NanThrowTypeError("Wrong numer of arguments, should be 1.");
    NanReturnUndefined();
  }
  bool enable_flag = args[0]->BooleanValue();
  SteamRemoteStorage()->SetCloudEnabledForApp(enable_flag);
  NanReturnUndefined();
}

NAN_METHOD(GetCloudQuota) {
  NanScope();

  if (args.Length() < 2) {
    NanThrowTypeError("Wrong numer of arguments, should be 2.");
    NanReturnUndefined();
  }
  NanCallback* success_callback = new NanCallback(args[0].As<v8::Function>());
  NanCallback* error_callback = new NanCallback(args[1].As<v8::Function>());
  NanAsyncQueueWorker(new greenworks::CloudQuotaGetWorker(success_callback,
                                                          error_callback));
  NanReturnUndefined();
}

NAN_METHOD(ActivateAchievement) {
  NanScope();

  if (args.Length() < 3) {
    NanThrowTypeError("Wrong numer of arguments, should be 3.");
    NanReturnUndefined();
  }
  std::string achievement = (*(v8::String::Utf8Value(args[0])));
  NanCallback* success_callback = new NanCallback(args[1].As<v8::Function>());
  NanCallback* error_callback = new NanCallback(args[2].As<v8::Function>());
  NanAsyncQueueWorker(new greenworks::ActivateAchievementWorker(
      success_callback, error_callback, achievement));
  NanReturnUndefined();
}

void init(v8::Handle<v8::Object> exports) {
  exports->Set(NanNew("initAPI"),
               NanNew<v8::FunctionTemplate>(InitAPI)->GetFunction());
  exports->Set(NanNew("saveTextToFile"),
               NanNew<v8::FunctionTemplate>(SaveTextToFile)->GetFunction());
  exports->Set(NanNew("readTextFromFile"),
               NanNew<v8::FunctionTemplate>(ReadTextFromFile)->GetFunction());
  exports->Set(NanNew("isCloudEnabled"),
               NanNew<v8::FunctionTemplate>(IsCloudEnabled)->GetFunction());
  exports->Set(NanNew("enableCloud"),
               NanNew<v8::FunctionTemplate>(EnableCloud)->GetFunction());
  exports->Set(NanNew("getCloudQuota"),
               NanNew<v8::FunctionTemplate>(GetCloudQuota)->GetFunction());
  exports->Set(NanNew("activateAchievement"),
               NanNew<v8::FunctionTemplate>(
                   ActivateAchievement)->GetFunction());
}

}  // namespace

#ifdef _WIN32
	NODE_MODULE(greenworks_win, init)
#elif __APPLE__
	NODE_MODULE(greenworks_osx, init)
#elif __linux__
  #if __x86_64__ || __ppc64__
    NODE_MODULE(greenworks_linux64, init)
  #else
    NODE_MODULE(greenworks_linux32, init)
  #endif
#endif
<commit_msg>Port greenwors.isCloudEnabledForUser API.<commit_after>// Copyright (c) 2014 Greenheart Games Pty. Ltd. All rights reserved.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include <string>

#include "nan.h"
#include "steam/steam_api.h"
#include "v8.h"

#include "greenworks_async_workers.h"

namespace {

NAN_METHOD(InitAPI) {
  NanScope();

  bool success = SteamAPI_Init();

  if (success) {
    ISteamUserStats* stream_user_stats = SteamUserStats();
    stream_user_stats->RequestCurrentStats();
  }

  NanReturnValue(NanNew(success));
}

NAN_METHOD(SaveTextToFile) {
  NanScope();

  if (args.Length() < 4) {
    NanThrowTypeError("Wrong numer of arguments, should be 4.");
    NanReturnUndefined();
  }

  std::string file_name(*(v8::String::Utf8Value(args[0])));
  std::string content(*(v8::String::Utf8Value(args[1])));
  NanCallback* successCallback = new NanCallback(args[2].As<v8::Function>());
  NanCallback* errorCallback = new NanCallback(args[3].As<v8::Function>());

  NanAsyncQueueWorker(new greenworks::FileSaveWorker(successCallback,
                                                     errorCallback,
                                                     file_name,
                                                     content));
  NanReturnUndefined();
}

NAN_METHOD(ReadTextFromFile) {
  NanScope();

  if (args.Length() < 3) {
    NanThrowTypeError("Wrong numer of arguments, should be 3.");
    NanReturnUndefined();
  }

  std::string file_name(*(v8::String::Utf8Value(args[0])));
  NanCallback* successCallback = new NanCallback(args[1].As<v8::Function>());
  NanCallback* errorCallback = new NanCallback(args[2].As<v8::Function>());

  NanAsyncQueueWorker(new greenworks::FileReadWorker(successCallback,
                                                     errorCallback,
                                                     file_name));
  NanReturnUndefined();
}

NAN_METHOD(IsCloudEnabled) {
  NanScope();
  ISteamRemoteStorage* steam_remote_storage = SteamRemoteStorage();
  NanReturnValue(NanNew<v8::Boolean>(
      steam_remote_storage->IsCloudEnabledForApp()));
}

NAN_METHOD(IsCloudEnabledForUser) {
  NanScope();
  ISteamRemoteStorage* steam_remote_storage = SteamRemoteStorage();
  NanReturnValue(NanNew<v8::Boolean>(
      steam_remote_storage->IsCloudEnabledForAccount()));
}

NAN_METHOD(EnableCloud) {
  NanScope();

  if (args.Length() < 1) {
    NanThrowTypeError("Wrong numer of arguments, should be 1.");
    NanReturnUndefined();
  }
  bool enable_flag = args[0]->BooleanValue();
  SteamRemoteStorage()->SetCloudEnabledForApp(enable_flag);
  NanReturnUndefined();
}

NAN_METHOD(GetCloudQuota) {
  NanScope();

  if (args.Length() < 2) {
    NanThrowTypeError("Wrong numer of arguments, should be 2.");
    NanReturnUndefined();
  }
  NanCallback* success_callback = new NanCallback(args[0].As<v8::Function>());
  NanCallback* error_callback = new NanCallback(args[1].As<v8::Function>());
  NanAsyncQueueWorker(new greenworks::CloudQuotaGetWorker(success_callback,
                                                          error_callback));
  NanReturnUndefined();
}

NAN_METHOD(ActivateAchievement) {
  NanScope();

  if (args.Length() < 3) {
    NanThrowTypeError("Wrong numer of arguments, should be 3.");
    NanReturnUndefined();
  }
  std::string achievement = (*(v8::String::Utf8Value(args[0])));
  NanCallback* success_callback = new NanCallback(args[1].As<v8::Function>());
  NanCallback* error_callback = new NanCallback(args[2].As<v8::Function>());
  NanAsyncQueueWorker(new greenworks::ActivateAchievementWorker(
      success_callback, error_callback, achievement));
  NanReturnUndefined();
}

void init(v8::Handle<v8::Object> exports) {
  exports->Set(NanNew("initAPI"),
               NanNew<v8::FunctionTemplate>(InitAPI)->GetFunction());
  // File related APIs.
  exports->Set(NanNew("saveTextToFile"),
               NanNew<v8::FunctionTemplate>(SaveTextToFile)->GetFunction());
  exports->Set(NanNew("readTextFromFile"),
               NanNew<v8::FunctionTemplate>(ReadTextFromFile)->GetFunction());
  // Cloud related APIs.
  exports->Set(NanNew("isCloudEnabled"),
               NanNew<v8::FunctionTemplate>(IsCloudEnabled)->GetFunction());
  exports->Set(NanNew("isCloudEnabledForUser"),
               NanNew<v8::FunctionTemplate>(
                   IsCloudEnabledForUser)->GetFunction());
  exports->Set(NanNew("enableCloud"),
               NanNew<v8::FunctionTemplate>(EnableCloud)->GetFunction());
  exports->Set(NanNew("getCloudQuota"),
               NanNew<v8::FunctionTemplate>(GetCloudQuota)->GetFunction());
  // Achievement related APIs.
  exports->Set(NanNew("activateAchievement"),
               NanNew<v8::FunctionTemplate>(
                   ActivateAchievement)->GetFunction());
}

}  // namespace

#ifdef _WIN32
	NODE_MODULE(greenworks_win, init)
#elif __APPLE__
	NODE_MODULE(greenworks_osx, init)
#elif __linux__
  #if __x86_64__ || __ppc64__
    NODE_MODULE(greenworks_linux64, init)
  #else
    NODE_MODULE(greenworks_linux32, init)
  #endif
#endif
<|endoftext|>