<commit_before>/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * WdmReader.cpp
 *
 *  Created on: Nov 1, 2018
 *      Author: Jason Wang
 */

#include "WdmReader.h"
#include "WdmReader.tcc"

#include "adios2/helper/adiosFunctions.h" // CSVToVector
#include "adios2/toolkit/transport/file/FileFStream.h"

#include <iostream>

#include <zmq.h>

namespace adios2
{
namespace core
{
namespace engine
{

WdmReader::WdmReader(IO &io, const std::string &name, const Mode mode,
                     MPI_Comm mpiComm)
: Engine("WdmReader", io, name, mode, mpiComm),
  m_DataManSerializer(helper::IsRowMajor(io.m_HostLanguage), true,
                      helper::IsLittleEndian()),
  m_RepliedMetadata(std::make_shared<std::vector<char>>())
{
    m_DataTransport = std::make_shared<transportman::StagingMan>(
        mpiComm, Mode::Read, m_Timeout, 1e9);
    m_MetadataTransport = std::make_shared<transportman::StagingMan>(
        mpiComm, Mode::Read, m_Timeout, 1e8);
    m_EndMessage = " in call to IO Open WdmReader " + m_Name + "\n";
    MPI_Comm_rank(mpiComm, &m_MpiRank);
    Init();
    if (m_Verbosity >= 5)
    {
        std::cout << "Staging Reader " << m_MpiRank << " Open(" << m_Name
                  << ") in constructor." << std::endl;
    }
}

WdmReader::~WdmReader()
{
    m_MetadataTransport = nullptr;
    m_DataTransport = nullptr;
    if (m_Verbosity >= 5)
    {
        std::cout << "Staging Reader " << m_MpiRank << " destructor on "
                  << m_Name << "\n";
    }
}

StepStatus WdmReader::BeginStepIterator(StepMode stepMode,
                                        format::DmvVecPtr &vars)
{
    if (not m_AttributesSet)
    {
        RequestMetadata(-3);
        m_DataManSerializer.GetAttributes(m_IO);
        m_AttributesSet = true;
    }

    RequestMetadata();
    m_MetaDataMap = m_DataManSerializer.GetMetaData();

    size_t maxStep = std::numeric_limits<size_t>::min();
    size_t minStep = std::numeric_limits<size_t>::max();

    for (auto &i : m_MetaDataMap)
    {
        if (i.first > maxStep)
        {
            maxStep = i.first;
        }
        if (i.first < minStep)
        {
            minStep = i.first;
        }
    }

    if (stepMode == StepMode::NextAvailable)
    {
        if (m_CurrentStep < minStep)
        {
            m_CurrentStep = minStep;
        }
        if (m_CurrentStep > maxStep)
        {
            return StepStatus::NotReady;
        }
    }
    else if (stepMode == StepMode::LatestAvailable)
    {
        m_CurrentStep = maxStep;
    }
    else
    {
        throw(std::invalid_argument(
            "[WdmReader::BeginStep] Step mode is not supported!"));
    }

    auto currentStepIt = m_MetaDataMap.find(m_CurrentStep);
    if (currentStepIt == m_MetaDataMap.end())
    {
        for (int64_t step = m_CurrentStep + 1; step <= maxStep; ++step)
        {
            auto currentStepIt = m_MetaDataMap.find(step);
            if (currentStepIt != m_MetaDataMap.end())
            {
                m_CurrentStep = step;
                vars = currentStepIt->second;
                break;
            }
        }
    }
    else
    {
        vars = currentStepIt->second;
    }

    if (vars == nullptr)
    {
        return StepStatus::NotReady;
    }
}

StepStatus WdmReader::BeginStep(const StepMode stepMode,
                                const float timeoutSeconds)
{

    Log(5,
        "WdmReader::BeginStep() start. Last step " +
            std::to_string(m_CurrentStep),
        true, true);

    ++m_CurrentStep;

    format::DmvVecPtr vars = nullptr;

    auto startTime = std::chrono::system_clock::now();

    while (vars == nullptr)
    {
        if (BeginStepIterator(stepMode, vars) == StepStatus::OK)
        {
            m_RetryTimes = 0;
            break;
        }
        auto nowTime = std::chrono::system_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::seconds>(
            nowTime - startTime);
        if (duration.count() > timeoutSeconds && timeoutSeconds >= 0)
        {
            Log(5,
                "WdmReader::BeginStep() returned EndOfStream because of "
                "timeout.",
                true, true);
            return StepStatus::EndOfStream;
        }
    }

    for (const auto &i : *vars)
    {
        if (i.step == m_CurrentStep)
        {
            if (i.type == "compound")
            {
                throw("Compound type is not supported yet.");
            }
#define declare_type(T)                                                        \
    else if (i.type == helper::GetType<T>())                                   \
    {                                                                          \
        CheckIOVariable<T>(i.name, i.shape, i.start, i.count);                 \
    }
            ADIOS2_FOREACH_STDTYPE_1ARG(declare_type)
#undef declare_type
            else
            {
                throw("Unknown type caught in "
                      "DataManReader::BeginStepSubscribe.");
            }
        }
    }

    Log(5,
        "WdmReader::BeginStep() start. Last step " +
            std::to_string(m_CurrentStep),
        true, true);

    m_RetryTimes = 0;
    return StepStatus::OK;
}

void WdmReader::PerformGets()
{

    Log(5, "WdmReader::PerformGets() begin", true, true);

    auto requests = m_DataManSerializer.GetDeferredRequest();

    if (m_Verbosity >= 10)
    {
        Log(10, "WdmReader::PerformGets() processing deferred requests ", true,
            true);
        for (const auto &i : *requests)
        {
            std::cout << i.first << ": ";
            for (auto j : *i.second)
            {
                std::cout << j;
            }
            std::cout << std::endl;
        }
    }

    for (const auto &i : *requests)
    {
        auto reply = m_DataTransport->Request(*i.second, i.first);
        if (reply->empty())
        {
            Log(1,
                "Lost connection to writer. Data for the final step is "
                "corrupted!",
                true, true);
            m_ConnectionLost = true;
            return;
        }
        if (reply->size() <= 16)
        {
            std::string msg = "Step " + std::to_string(m_CurrentStep) +
                              " received empty data package from writer " +
                              i.first +
                              ". This may be caused by a network failure.";
            if (m_Tolerance)
            {
                Log(1, msg, true, true);
            }
            else
            {
                throw(std::runtime_error(msg));
            }
        }
        else
        {
            Log(6,
                "WdmReader::PerformGets() put reply of size " +
                    std::to_string(reply->size()) + " into serializer",
                true, true);
            m_DataManSerializer.PutPack(reply);
        }
    }

    auto varsVec = m_MetaDataMap.find(m_CurrentStep);
    if (varsVec == m_MetaDataMap.end())
    {
        return;
    }
    if (varsVec->second == nullptr)
    {
        return;
    }

    for (const auto &req : m_DeferredRequests)
    {
        if (req.type == "compound")
        {
            throw("Compound type is not supported yet.");
        }
#define declare_type(T)                                                        \
    else if (req.type == helper::GetType<T>())                                 \
    {                                                                          \
        m_DataManSerializer.GetVar(reinterpret_cast<T *>(req.data),            \
                                   req.variable, req.start, req.count,         \
                                   req.step);                                  \
        Log(6,                                                                 \
            "WdmReader::PerformGets() get variable " + req.variable +          \
                " from serializer",                                            \
            true, true);                                                       \
    }
        ADIOS2_FOREACH_STDTYPE_1ARG(declare_type)
#undef declare_type
    }

    m_DeferredRequests.clear();

    Log(5, "WdmReader::PerformGets() end", true, true);
}

size_t WdmReader::CurrentStep() const { return m_CurrentStep; }

void WdmReader::EndStep()
{
    Log(5, "WdmReader::EndStep() start. Step " + std::to_string(m_CurrentStep),
        true, true);

    PerformGets();
    m_DataManSerializer.Erase(CurrentStep(), true);

    Log(5, "WdmReader::EndStep() end. Step " + std::to_string(m_CurrentStep),
        true, true);
}

// PRIVATE

#define declare_type(T)                                                        \
    void WdmReader::DoGetSync(Variable<T> &variable, T *data)                  \
    {                                                                          \
        GetSyncCommon(variable, data);                                         \
    }                                                                          \
    void WdmReader::DoGetDeferred(Variable<T> &variable, T *data)              \
    {                                                                          \
        GetDeferredCommon(variable, data);                                     \
    }                                                                          \
    std::map<size_t, std::vector<typename Variable<T>::Info>>                  \
    WdmReader::DoAllStepsBlocksInfo(const Variable<T> &variable) const         \
    {                                                                          \
        return AllStepsBlocksInfoCommon(variable);                             \
    }                                                                          \
    std::vector<typename Variable<T>::Info> WdmReader::DoBlocksInfo(           \
        const Variable<T> &variable, const size_t step) const                  \
    {                                                                          \
        return BlocksInfoCommon(variable, step);                               \
    }
ADIOS2_FOREACH_STDTYPE_1ARG(declare_type)
#undef declare_type

void WdmReader::Init()
{
    srand(time(NULL));
    InitParameters();
    helper::HandshakeReader(m_MPIComm, m_AppID, m_FullAddresses, m_Name);
}

void WdmReader::InitParameters()
{
    for (const auto &pair : m_IO.m_Parameters)
    {
        std::string key(pair.first);
        std::transform(key.begin(), key.end(), key.begin(), ::tolower);

        std::string value(pair.second);
        std::transform(value.begin(), value.end(), value.begin(), ::tolower);

        if (key == "verbose")
        {
            m_Verbosity = std::stoi(value);
        }
    }
}

void WdmReader::InitTransports() {}

void WdmReader::RequestMetadata(int64_t step)
{
    format::VecPtr reply = std::make_shared<std::vector<char>>();
    if (m_MpiRank == 0)
    {
        std::vector<char> request(2 * sizeof(int64_t));
        reinterpret_cast<int64_t *>(request.data())[0] = m_AppID;
        reinterpret_cast<int64_t *>(request.data())[1] = step;
        std::string address = m_FullAddresses[rand() % m_FullAddresses.size()];
        reply = m_MetadataTransport->Request(request, address);
    }
    m_DataManSerializer.PutAggregatedMetadata(reply, m_MPIComm);
}

void WdmReader::DoClose(const int transportIndex)
{
    if (m_Verbosity >= 5)
    {
        std::cout << "Staging Reader " << m_MpiRank << " Close(" << m_Name
                  << ")\n";
    }
}

void WdmReader::Log(const int level, const std::string &message, const bool mpi,
                    const bool endline)
{
    if (m_Verbosity >= level)
    {
        if (mpi)
        {
            std::cout << "[Rank " << m_MpiRank << "] ";
        }
        std::cout << message;
        if (endline)
        {
            std::cout << std::endl;
        }
    }
}

} // end namespace engine
} // end namespace core
} // end namespace adios2
<commit_msg>fixed other step modes for wdm<commit_after>/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * WdmReader.cpp
 *
 *  Created on: Nov 1, 2018
 *      Author: Jason Wang
 */

#include "WdmReader.h"
#include "WdmReader.tcc"

#include "adios2/helper/adiosFunctions.h" // CSVToVector
#include "adios2/toolkit/transport/file/FileFStream.h"

#include <iostream>

#include <zmq.h>

namespace adios2
{
namespace core
{
namespace engine
{

WdmReader::WdmReader(IO &io, const std::string &name, const Mode mode,
                     MPI_Comm mpiComm)
: Engine("WdmReader", io, name, mode, mpiComm),
  m_DataManSerializer(helper::IsRowMajor(io.m_HostLanguage), true,
                      helper::IsLittleEndian()),
  m_RepliedMetadata(std::make_shared<std::vector<char>>())
{
    m_DataTransport = std::make_shared<transportman::StagingMan>(
        mpiComm, Mode::Read, m_Timeout, 1e9);
    m_MetadataTransport = std::make_shared<transportman::StagingMan>(
        mpiComm, Mode::Read, m_Timeout, 1e8);
    m_EndMessage = " in call to IO Open WdmReader " + m_Name + "\n";
    MPI_Comm_rank(mpiComm, &m_MpiRank);
    Init();
    if (m_Verbosity >= 5)
    {
        std::cout << "Staging Reader " << m_MpiRank << " Open(" << m_Name
                  << ") in constructor." << std::endl;
    }
}

WdmReader::~WdmReader()
{
    m_MetadataTransport = nullptr;
    m_DataTransport = nullptr;
    if (m_Verbosity >= 5)
    {
        std::cout << "Staging Reader " << m_MpiRank << " destructor on "
                  << m_Name << "\n";
    }
}

StepStatus WdmReader::BeginStepIterator(StepMode stepMode,
                                        format::DmvVecPtr &vars)
{
    if (not m_AttributesSet)
    {
        RequestMetadata(-3);
        m_DataManSerializer.GetAttributes(m_IO);
        m_AttributesSet = true;
    }

    RequestMetadata();
    m_MetaDataMap = m_DataManSerializer.GetMetaData();

    size_t maxStep = std::numeric_limits<size_t>::min();
    size_t minStep = std::numeric_limits<size_t>::max();

    for (auto &i : m_MetaDataMap)
    {
        if (i.first > maxStep)
        {
            maxStep = i.first;
        }
        if (i.first < minStep)
        {
            minStep = i.first;
        }
    }

    if (stepMode == StepMode::NextAvailable)
    {
        if (m_CurrentStep < minStep)
        {
            m_CurrentStep = minStep;
        }
        if (m_CurrentStep > maxStep)
        {
            return StepStatus::NotReady;
        }
    }
    else if (stepMode == StepMode::LatestAvailable)
    {
        m_CurrentStep = maxStep;
    }
    else
    {
        throw(std::invalid_argument(
            "[WdmReader::BeginStep] Step mode is not supported!"));
    }

    auto currentStepIt = m_MetaDataMap.find(m_CurrentStep);
    if (currentStepIt == m_MetaDataMap.end())
    {
        for (int64_t step = m_CurrentStep + 1; step <= maxStep; ++step)
        {
            auto currentStepIt = m_MetaDataMap.find(step);
            if (currentStepIt != m_MetaDataMap.end())
            {
                m_CurrentStep = step;
                vars = currentStepIt->second;
                break;
            }
        }
    }
    else
    {
        vars = currentStepIt->second;
    }

    if (vars == nullptr)
    {
        return StepStatus::NotReady;
    }
}

StepStatus WdmReader::BeginStep(const StepMode stepMode,
                                const float timeoutSeconds)
{

    Log(5,
        "WdmReader::BeginStep() start. Last step " +
            std::to_string(m_CurrentStep),
        true, true);

    ++m_CurrentStep;

    format::DmvVecPtr vars = nullptr;

    auto startTime = std::chrono::system_clock::now();

    while (vars == nullptr)
    {
        auto stepStatus = BeginStepIterator(stepMode, vars);
        if (stepStatus == StepStatus::OK)
        {
            m_RetryTimes = 0;
            break;
        }
        else if (stepStatus == StepStatus::EndOfStream)
        {
            return StepStatus::EndOfStream;
        }
        if (timeoutSeconds >= 0)
        {
            auto nowTime = std::chrono::system_clock::now();
            auto duration = std::chrono::duration_cast<std::chrono::seconds>(
                nowTime - startTime);
            if (duration.count() > timeoutSeconds)
            {
                Log(5,
                    "WdmReader::BeginStep() returned EndOfStream because of "
                    "timeout.",
                    true, true);
                return StepStatus::EndOfStream;
            }
            else
            {
                Log(5, "WdmReader::BeginStep() returned NotReady.", true, true);
                return StepStatus::NotReady;
            }
        }
    }

    for (const auto &i : *vars)
    {
        if (i.step == m_CurrentStep)
        {
            if (i.type == "compound")
            {
                throw("Compound type is not supported yet.");
            }
#define declare_type(T)                                                        \
    else if (i.type == helper::GetType<T>())                                   \
    {                                                                          \
        CheckIOVariable<T>(i.name, i.shape, i.start, i.count);                 \
    }
            ADIOS2_FOREACH_STDTYPE_1ARG(declare_type)
#undef declare_type
            else
            {
                throw("Unknown type caught in "
                      "DataManReader::BeginStepSubscribe.");
            }
        }
    }

    Log(5,
        "WdmReader::BeginStep() start. Last step " +
            std::to_string(m_CurrentStep),
        true, true);

    m_RetryTimes = 0;
    return StepStatus::OK;
}

void WdmReader::PerformGets()
{

    Log(5, "WdmReader::PerformGets() begin", true, true);

    auto requests = m_DataManSerializer.GetDeferredRequest();

    if (m_Verbosity >= 10)
    {
        Log(10, "WdmReader::PerformGets() processing deferred requests ", true,
            true);
        for (const auto &i : *requests)
        {
            std::cout << i.first << ": ";
            for (auto j : *i.second)
            {
                std::cout << j;
            }
            std::cout << std::endl;
        }
    }

    for (const auto &i : *requests)
    {
        auto reply = m_DataTransport->Request(*i.second, i.first);
        if (reply->empty())
        {
            Log(1,
                "Lost connection to writer. Data for the final step is "
                "corrupted!",
                true, true);
            m_ConnectionLost = true;
            return;
        }
        if (reply->size() <= 16)
        {
            std::string msg = "Step " + std::to_string(m_CurrentStep) +
                              " received empty data package from writer " +
                              i.first +
                              ". This may be caused by a network failure.";
            if (m_Tolerance)
            {
                Log(1, msg, true, true);
            }
            else
            {
                throw(std::runtime_error(msg));
            }
        }
        else
        {
            Log(6,
                "WdmReader::PerformGets() put reply of size " +
                    std::to_string(reply->size()) + " into serializer",
                true, true);
            m_DataManSerializer.PutPack(reply);
        }
    }

    auto varsVec = m_MetaDataMap.find(m_CurrentStep);
    if (varsVec == m_MetaDataMap.end())
    {
        return;
    }
    if (varsVec->second == nullptr)
    {
        return;
    }

    for (const auto &req : m_DeferredRequests)
    {
        if (req.type == "compound")
        {
            throw("Compound type is not supported yet.");
        }
#define declare_type(T)                                                        \
    else if (req.type == helper::GetType<T>())                                 \
    {                                                                          \
        m_DataManSerializer.GetVar(reinterpret_cast<T *>(req.data),            \
                                   req.variable, req.start, req.count,         \
                                   req.step);                                  \
        Log(6,                                                                 \
            "WdmReader::PerformGets() get variable " + req.variable +          \
                " from serializer",                                            \
            true, true);                                                       \
    }
        ADIOS2_FOREACH_STDTYPE_1ARG(declare_type)
#undef declare_type
    }

    m_DeferredRequests.clear();

    Log(5, "WdmReader::PerformGets() end", true, true);
}

size_t WdmReader::CurrentStep() const { return m_CurrentStep; }

void WdmReader::EndStep()
{
    Log(5, "WdmReader::EndStep() start. Step " + std::to_string(m_CurrentStep),
        true, true);

    PerformGets();
    m_DataManSerializer.Erase(CurrentStep(), true);

    Log(5, "WdmReader::EndStep() end. Step " + std::to_string(m_CurrentStep),
        true, true);
}

// PRIVATE

#define declare_type(T)                                                        \
    void WdmReader::DoGetSync(Variable<T> &variable, T *data)                  \
    {                                                                          \
        GetSyncCommon(variable, data);                                         \
    }                                                                          \
    void WdmReader::DoGetDeferred(Variable<T> &variable, T *data)              \
    {                                                                          \
        GetDeferredCommon(variable, data);                                     \
    }                                                                          \
    std::map<size_t, std::vector<typename Variable<T>::Info>>                  \
    WdmReader::DoAllStepsBlocksInfo(const Variable<T> &variable) const         \
    {                                                                          \
        return AllStepsBlocksInfoCommon(variable);                             \
    }                                                                          \
    std::vector<typename Variable<T>::Info> WdmReader::DoBlocksInfo(           \
        const Variable<T> &variable, const size_t step) const                  \
    {                                                                          \
        return BlocksInfoCommon(variable, step);                               \
    }
ADIOS2_FOREACH_STDTYPE_1ARG(declare_type)
#undef declare_type

void WdmReader::Init()
{
    srand(time(NULL));
    InitParameters();
    helper::HandshakeReader(m_MPIComm, m_AppID, m_FullAddresses, m_Name);
}

void WdmReader::InitParameters()
{
    for (const auto &pair : m_IO.m_Parameters)
    {
        std::string key(pair.first);
        std::transform(key.begin(), key.end(), key.begin(), ::tolower);

        std::string value(pair.second);
        std::transform(value.begin(), value.end(), value.begin(), ::tolower);

        if (key == "verbose")
        {
            m_Verbosity = std::stoi(value);
        }
    }
}

void WdmReader::InitTransports() {}

void WdmReader::RequestMetadata(int64_t step)
{
    format::VecPtr reply = std::make_shared<std::vector<char>>();
    if (m_MpiRank == 0)
    {
        std::vector<char> request(2 * sizeof(int64_t));
        reinterpret_cast<int64_t *>(request.data())[0] = m_AppID;
        reinterpret_cast<int64_t *>(request.data())[1] = step;
        std::string address = m_FullAddresses[rand() % m_FullAddresses.size()];
        reply = m_MetadataTransport->Request(request, address);
    }
    m_DataManSerializer.PutAggregatedMetadata(reply, m_MPIComm);
}

void WdmReader::DoClose(const int transportIndex)
{
    if (m_Verbosity >= 5)
    {
        std::cout << "Staging Reader " << m_MpiRank << " Close(" << m_Name
                  << ")\n";
    }
}

void WdmReader::Log(const int level, const std::string &message, const bool mpi,
                    const bool endline)
{
    if (m_Verbosity >= level)
    {
        if (mpi)
        {
            std::cout << "[Rank " << m_MpiRank << "] ";
        }
        std::cout << message;
        if (endline)
        {
            std::cout << std::endl;
        }
    }
}

} // end namespace engine
} // end namespace core
} // end namespace adios2
<|endoftext|>


<commit_before>#include "game/ui/battle/battleprestart.h"
#include "forms/form.h"
#include "forms/graphic.h"
#include "forms/graphicbutton.h"
#include "forms/label.h"
#include "forms/ui.h"
#include "framework/apocresources/cursor.h"
#include "framework/data.h"
#include "framework/event.h"
#include "framework/font.h"
#include "framework/framework.h"
#include "framework/keycodes.h"
#include "game/state/gamestate.h"
#include "game/state/rules/battle/battlecommonimagelist.h"
#include "game/state/shared/aequipment.h"
#include "game/state/shared/agent.h"
#include "game/ui/components/controlgenerator.h"
#include "game/ui/general/aequipscreen.h"
#include "game/ui/general/agentsheet.h"
#include "game/ui/general/loadingscreen.h"
#include "game/ui/tileview/battleview.h"
#include <cmath>

namespace OpenApoc
{

std::shared_future<void> enterBattle(sp<GameState> state)
{
	auto loadTask =
	    fw().threadPoolEnqueue([state]() -> void { Battle::enterBattle(*state.get()); });

	return loadTask;
}

void BattlePreStart::displayAgent(sp<Agent> agent)
{
	if (!agent)
	{
		return;
	}

	AgentSheet(formAgentStats)
	    .display(*agent, bigUnitRanks, state->current_battle->mode == Battle::Mode::TurnBased);
	formAgentStats->setVisible(true);

	auto rHand = agent->getFirstItemInSlot(EquipmentSlotType::RightHand);
	auto lHand = agent->getFirstItemInSlot(EquipmentSlotType::LeftHand);
	menuform->findControlTyped<Graphic>("RIGHT_HAND")
	    ->setImage(rHand ? rHand->type->equipscreen_sprite : nullptr);
	menuform->findControlTyped<Graphic>("LEFT_HAND")
	    ->setImage(lHand ? lHand->type->equipscreen_sprite : nullptr);
}
BattlePreStart::BattlePreStart(sp<GameState> state)
    : Stage(), menuform(ui().getForm("battle/prestart")), TOP_LEFT({302, 80}), state(state)
{

	menuform->findControlTyped<GraphicButton>("BUTTON_EQUIP")
	    ->addCallback(FormEventType::ButtonClick, [state](Event *) {
		    fw().stageQueueCommand({StageCmd::Command::PUSH, mksp<AEquipScreen>(state)});
	    });
	formAgentStats = menuform->findControlTyped<Form>("AGENT_STATS_VIEW");
	formAgentStats->setVisible(false);
	menuform->findControlTyped<GraphicButton>("BUTTON_OK")
	    ->addCallback(FormEventType::ButtonClick, [this, state](Event *) {
		    auto gameState = this->state;

		    fw().stageQueueCommand({StageCmd::Command::PUSH,
		                            mksp<LoadingScreen>(
		                                gameState, enterBattle(gameState),
		                                [gameState]() { return mksp<BattleView>(gameState); },
		                                this->state->battle_common_image_list->loadingImage, 1)});
	    });

	for (int i = 12; i <= 18; i++)
	{
		bigUnitRanks.push_back(
		    fw().data->loadImage(format("PCK:xcom3/tacdata/tacbut.pck:xcom3/tacdata/"
		                                "tacbut.tab:%d:xcom3/tacdata/tactical.pal",
		                                i)));
	}
}

void BattlePreStart::updateAgents()
{
	selectedAgent = nullptr;
	agents.clear();
	// Create agent controls
	for (auto &u : state->current_battle->units)
	{
		if (u.second->owner != state->current_battle->currentPlayer)
		{
			continue;
		}
		if (!u.second->agent->type->allowsDirectControl)
		{
			continue;
		}
		if (u.second->squadNumber == -1)
		{
			continue;
		}
		agents.insert(
		    mksp<AgentIcon>(u.second->agent,
		                    ControlGenerator::createAgentControl(*state, u.second->agent,
		                                                         UnitSelectionState::Unselected),
		                    ControlGenerator::createAgentControl(
		                        *state, u.second->agent, UnitSelectionState::FirstSelected)));
	}

	// Position agent controls
	for (auto &a : agents)
	{
		a->setLocation(menuform->Location + TOP_LEFT +
		               Vec2<int>{a->agent->unit->squadPosition * SHIFT_X,
		                         a->agent->unit->squadNumber * SHIFT_Y});
		a->update();
	}

	if (lastSelectedAgent)
	{
		displayAgent(lastSelectedAgent);
	}
}

void BattlePreStart::begin()
{
	updateAgents();
	displayAgent(nullptr);
}

void BattlePreStart::pause()
{
	if (draggedAgent)
	{
		draggedAgent->agent->unit->assignToSquad(*state->current_battle, draggedOrigin);
		draggedAgent = nullptr;
	}
}

void BattlePreStart::resume() { updateAgents(); }

void BattlePreStart::finish() {}

void BattlePreStart::eventOccurred(Event *e)
{
	menuform->eventOccured(e);
	if (e->type() == EVENT_KEY_DOWN)
	{
		if (e->keyboard().KeyCode == SDLK_RETURN || e->keyboard().KeyCode == SDLK_ESCAPE)
		{
			menuform->findControl("BUTTON_OK")->click();
			return;
		}
		if (e->keyboard().KeyCode == SDLK_SPACE)
		{
			menuform->findControl("BUTTON_EQUIP")->click();
			return;
		}
	}
	if (e->type() == EVENT_MOUSE_MOVE)
	{
		Vec2<int> mousePos{e->mouse().X, e->mouse().Y};

		selectedAgent = nullptr;
		draggedMoved = true;
		for (auto &a : agents)
		{
			auto &c = *a->normalControl;
			if (mousePos.x >= c.Location.x && mousePos.y >= c.Location.y &&
			    mousePos.x < c.Location.x + c.Size.x && mousePos.y < c.Location.y + c.Size.y)
			{
				selectedAgent = a;
				lastSelectedAgent = selectedAgent->agent;
				displayAgent(lastSelectedAgent);
				break;
			}
		}
	}
	if (e->type() == EVENT_MOUSE_DOWN && !draggedAgent)
	{
		if (selectedAgent)
		{
			draggedAgent = selectedAgent;
			draggedOrigin = draggedAgent->agent->unit->squadNumber;
			draggedAgent->agent->unit->removeFromSquad(*state->current_battle);
			draggedAgentOffset =
			    draggedAgent->normalControl->Location - Vec2<int>{e->mouse().X, e->mouse().Y};
			draggedMoved = false;
			updateAgents();
		}
	}
	if (e->type() == EVENT_MOUSE_UP && draggedAgent)
	{
		Vec2<int> mousePos{e->mouse().X, e->mouse().Y};
		mousePos -= menuform->Location;

		if (selectedAgent)
		{
			int num = selectedAgent->agent->unit->squadNumber;
			int pos = selectedAgent->agent->unit->squadPosition;
			selectedAgent->agent->unit->removeFromSquad(*state->current_battle);
			draggedAgent->agent->unit->assignToSquad(*state->current_battle, num, pos);
			selectedAgent->agent->unit->assignToSquad(*state->current_battle, draggedOrigin);
		}
		else
		{
			int newSquad = -1;
			for (int i = 0; i < 6; i++)
			{
				if (mousePos.x >= TOP_LEFT.x - ROW_HEADER && mousePos.x < TOP_LEFT.x + ROW_WIDTH &&
				    mousePos.y >= TOP_LEFT.y + i * SHIFT_Y &&
				    mousePos.y < TOP_LEFT.y + i * SHIFT_Y + ROW_HEIGHT)
				{
					newSquad = i;
					break;
				}
			}
			if (newSquad == -1 ||
			    !draggedAgent->agent->unit->assignToSquad(*state->current_battle, newSquad))
			{
				draggedAgent->agent->unit->assignToSquad(*state->current_battle, draggedOrigin);
			}
		}

		updateAgents();
		if (!draggedMoved)
		{
			fw().stageQueueCommand(
			    {StageCmd::Command::PUSH, mksp<AEquipScreen>(state, draggedAgent->agent)});
		}
		draggedAgent = nullptr;
	}
}

void BattlePreStart::update() { menuform->update(); }

void BattlePreStart::render()
{
	menuform->render();

	for (auto &c : agents)
	{
		if (c == selectedAgent)
		{
			c->selectedControl->render();
		}
		else
		{
			c->normalControl->render();
		}
	}
	if (draggedAgent)
	{
		Vec2<int> agentPos = fw().getCursor().getPosition() + draggedAgentOffset;
		draggedAgent->setLocation(agentPos);
		draggedAgent->selectedControl->render();
	}
}

bool BattlePreStart::isTransition() { return false; }

void BattlePreStart::AgentIcon::setLocation(Vec2<int> pos)
{
	normalControl->Location = pos;
	selectedControl->Location = pos;
}

void BattlePreStart::AgentIcon::update()
{
	normalControl->update();
	selectedControl->update();
}

BattlePreStart::AgentIcon::AgentIcon(sp<Agent> agent, sp<Control> normalControl,
                                     sp<Control> selectedControl)
    : agent(agent), normalControl(normalControl), selectedControl(selectedControl)
{
}

}; // namespace OpenApoc
<commit_msg>Reorder BattlePrestart constructor to match declaration<commit_after>#include "game/ui/battle/battleprestart.h"
#include "forms/form.h"
#include "forms/graphic.h"
#include "forms/graphicbutton.h"
#include "forms/label.h"
#include "forms/ui.h"
#include "framework/apocresources/cursor.h"
#include "framework/data.h"
#include "framework/event.h"
#include "framework/font.h"
#include "framework/framework.h"
#include "framework/keycodes.h"
#include "game/state/gamestate.h"
#include "game/state/rules/battle/battlecommonimagelist.h"
#include "game/state/shared/aequipment.h"
#include "game/state/shared/agent.h"
#include "game/ui/components/controlgenerator.h"
#include "game/ui/general/aequipscreen.h"
#include "game/ui/general/agentsheet.h"
#include "game/ui/general/loadingscreen.h"
#include "game/ui/tileview/battleview.h"
#include <cmath>

namespace OpenApoc
{

std::shared_future<void> enterBattle(sp<GameState> state)
{
	auto loadTask =
	    fw().threadPoolEnqueue([state]() -> void { Battle::enterBattle(*state.get()); });

	return loadTask;
}

void BattlePreStart::displayAgent(sp<Agent> agent)
{
	if (!agent)
	{
		return;
	}

	AgentSheet(formAgentStats)
	    .display(*agent, bigUnitRanks, state->current_battle->mode == Battle::Mode::TurnBased);
	formAgentStats->setVisible(true);

	auto rHand = agent->getFirstItemInSlot(EquipmentSlotType::RightHand);
	auto lHand = agent->getFirstItemInSlot(EquipmentSlotType::LeftHand);
	menuform->findControlTyped<Graphic>("RIGHT_HAND")
	    ->setImage(rHand ? rHand->type->equipscreen_sprite : nullptr);
	menuform->findControlTyped<Graphic>("LEFT_HAND")
	    ->setImage(lHand ? lHand->type->equipscreen_sprite : nullptr);
}
BattlePreStart::BattlePreStart(sp<GameState> state)
    : Stage(), TOP_LEFT({302, 80}), menuform(ui().getForm("battle/prestart")), state(state)
{

	menuform->findControlTyped<GraphicButton>("BUTTON_EQUIP")
	    ->addCallback(FormEventType::ButtonClick, [state](Event *) {
		    fw().stageQueueCommand({StageCmd::Command::PUSH, mksp<AEquipScreen>(state)});
	    });
	formAgentStats = menuform->findControlTyped<Form>("AGENT_STATS_VIEW");
	formAgentStats->setVisible(false);
	menuform->findControlTyped<GraphicButton>("BUTTON_OK")
	    ->addCallback(FormEventType::ButtonClick, [this, state](Event *) {
		    auto gameState = this->state;

		    fw().stageQueueCommand({StageCmd::Command::PUSH,
		                            mksp<LoadingScreen>(
		                                gameState, enterBattle(gameState),
		                                [gameState]() { return mksp<BattleView>(gameState); },
		                                this->state->battle_common_image_list->loadingImage, 1)});
	    });

	for (int i = 12; i <= 18; i++)
	{
		bigUnitRanks.push_back(
		    fw().data->loadImage(format("PCK:xcom3/tacdata/tacbut.pck:xcom3/tacdata/"
		                                "tacbut.tab:%d:xcom3/tacdata/tactical.pal",
		                                i)));
	}
}

void BattlePreStart::updateAgents()
{
	selectedAgent = nullptr;
	agents.clear();
	// Create agent controls
	for (auto &u : state->current_battle->units)
	{
		if (u.second->owner != state->current_battle->currentPlayer)
		{
			continue;
		}
		if (!u.second->agent->type->allowsDirectControl)
		{
			continue;
		}
		if (u.second->squadNumber == -1)
		{
			continue;
		}
		agents.insert(
		    mksp<AgentIcon>(u.second->agent,
		                    ControlGenerator::createAgentControl(*state, u.second->agent,
		                                                         UnitSelectionState::Unselected),
		                    ControlGenerator::createAgentControl(
		                        *state, u.second->agent, UnitSelectionState::FirstSelected)));
	}

	// Position agent controls
	for (auto &a : agents)
	{
		a->setLocation(menuform->Location + TOP_LEFT +
		               Vec2<int>{a->agent->unit->squadPosition * SHIFT_X,
		                         a->agent->unit->squadNumber * SHIFT_Y});
		a->update();
	}

	if (lastSelectedAgent)
	{
		displayAgent(lastSelectedAgent);
	}
}

void BattlePreStart::begin()
{
	updateAgents();
	displayAgent(nullptr);
}

void BattlePreStart::pause()
{
	if (draggedAgent)
	{
		draggedAgent->agent->unit->assignToSquad(*state->current_battle, draggedOrigin);
		draggedAgent = nullptr;
	}
}

void BattlePreStart::resume() { updateAgents(); }

void BattlePreStart::finish() {}

void BattlePreStart::eventOccurred(Event *e)
{
	menuform->eventOccured(e);
	if (e->type() == EVENT_KEY_DOWN)
	{
		if (e->keyboard().KeyCode == SDLK_RETURN || e->keyboard().KeyCode == SDLK_ESCAPE)
		{
			menuform->findControl("BUTTON_OK")->click();
			return;
		}
		if (e->keyboard().KeyCode == SDLK_SPACE)
		{
			menuform->findControl("BUTTON_EQUIP")->click();
			return;
		}
	}
	if (e->type() == EVENT_MOUSE_MOVE)
	{
		Vec2<int> mousePos{e->mouse().X, e->mouse().Y};

		selectedAgent = nullptr;
		draggedMoved = true;
		for (auto &a : agents)
		{
			auto &c = *a->normalControl;
			if (mousePos.x >= c.Location.x && mousePos.y >= c.Location.y &&
			    mousePos.x < c.Location.x + c.Size.x && mousePos.y < c.Location.y + c.Size.y)
			{
				selectedAgent = a;
				lastSelectedAgent = selectedAgent->agent;
				displayAgent(lastSelectedAgent);
				break;
			}
		}
	}
	if (e->type() == EVENT_MOUSE_DOWN && !draggedAgent)
	{
		if (selectedAgent)
		{
			draggedAgent = selectedAgent;
			draggedOrigin = draggedAgent->agent->unit->squadNumber;
			draggedAgent->agent->unit->removeFromSquad(*state->current_battle);
			draggedAgentOffset =
			    draggedAgent->normalControl->Location - Vec2<int>{e->mouse().X, e->mouse().Y};
			draggedMoved = false;
			updateAgents();
		}
	}
	if (e->type() == EVENT_MOUSE_UP && draggedAgent)
	{
		Vec2<int> mousePos{e->mouse().X, e->mouse().Y};
		mousePos -= menuform->Location;

		if (selectedAgent)
		{
			int num = selectedAgent->agent->unit->squadNumber;
			int pos = selectedAgent->agent->unit->squadPosition;
			selectedAgent->agent->unit->removeFromSquad(*state->current_battle);
			draggedAgent->agent->unit->assignToSquad(*state->current_battle, num, pos);
			selectedAgent->agent->unit->assignToSquad(*state->current_battle, draggedOrigin);
		}
		else
		{
			int newSquad = -1;
			for (int i = 0; i < 6; i++)
			{
				if (mousePos.x >= TOP_LEFT.x - ROW_HEADER && mousePos.x < TOP_LEFT.x + ROW_WIDTH &&
				    mousePos.y >= TOP_LEFT.y + i * SHIFT_Y &&
				    mousePos.y < TOP_LEFT.y + i * SHIFT_Y + ROW_HEIGHT)
				{
					newSquad = i;
					break;
				}
			}
			if (newSquad == -1 ||
			    !draggedAgent->agent->unit->assignToSquad(*state->current_battle, newSquad))
			{
				draggedAgent->agent->unit->assignToSquad(*state->current_battle, draggedOrigin);
			}
		}

		updateAgents();
		if (!draggedMoved)
		{
			fw().stageQueueCommand(
			    {StageCmd::Command::PUSH, mksp<AEquipScreen>(state, draggedAgent->agent)});
		}
		draggedAgent = nullptr;
	}
}

void BattlePreStart::update() { menuform->update(); }

void BattlePreStart::render()
{
	menuform->render();

	for (auto &c : agents)
	{
		if (c == selectedAgent)
		{
			c->selectedControl->render();
		}
		else
		{
			c->normalControl->render();
		}
	}
	if (draggedAgent)
	{
		Vec2<int> agentPos = fw().getCursor().getPosition() + draggedAgentOffset;
		draggedAgent->setLocation(agentPos);
		draggedAgent->selectedControl->render();
	}
}

bool BattlePreStart::isTransition() { return false; }

void BattlePreStart::AgentIcon::setLocation(Vec2<int> pos)
{
	normalControl->Location = pos;
	selectedControl->Location = pos;
}

void BattlePreStart::AgentIcon::update()
{
	normalControl->update();
	selectedControl->update();
}

BattlePreStart::AgentIcon::AgentIcon(sp<Agent> agent, sp<Control> normalControl,
                                     sp<Control> selectedControl)
    : agent(agent), normalControl(normalControl), selectedControl(selectedControl)
{
}

}; // namespace OpenApoc
<|endoftext|>


<commit_before>//=============================================================================
// ■ main.cpp
//-----------------------------------------------------------------------------
//   VMGS的主程序。
//=============================================================================

#include "VMGS.hpp"

namespace VM76 {
	Shaders* shader_textured = NULL;
	Shaders* gui = NULL;
	Shaders* shader_basic = NULL;
	Res::Texture* tile_texture = NULL;

	Cube* block_pointer;
	Cube* clist[16];
	TiledMap* map;

	glm::mat4 gui_2d_projection;

	int hand_id = 1;

	Axis* axe;

	Object* obj = new Object();

	void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
		#define PRESS(n) key == n && action == GLFW_PRESS
		if (PRESS(GLFW_KEY_A)) obj->move(glm::vec3(-1.0, 0.0, 0.0));
		if (PRESS(GLFW_KEY_D)) obj->move(glm::vec3(1.0, 0.0, 0.0));
		if (PRESS(GLFW_KEY_W)) obj->move(glm::vec3(0.0, 0.0, -1.0));
		if (PRESS(GLFW_KEY_S)) obj->move(glm::vec3(0.0, 0.0, 1.0));
		if (PRESS(GLFW_KEY_UP)) obj->move(glm::vec3(0.0, 1.0, 0.0));
		if (PRESS(GLFW_KEY_DOWN)) obj->move(glm::vec3(0.0, -1.0, 0.0));

		if (PRESS(GLFW_KEY_0)) hand_id = 0;
		if (PRESS(GLFW_KEY_0)) hand_id = 0;
		if (PRESS(GLFW_KEY_1)) hand_id = 1;
		if (PRESS(GLFW_KEY_2)) hand_id = 2;
		if (PRESS(GLFW_KEY_3)) hand_id = 3;
		if (PRESS(GLFW_KEY_4)) hand_id = 4;
		if (PRESS(GLFW_KEY_5)) hand_id = 5;
		if (PRESS(GLFW_KEY_6)) hand_id = 6;
		if (PRESS(GLFW_KEY_7)) hand_id = 7;
		if (PRESS(GLFW_KEY_8)) hand_id = 8;
		if (PRESS(GLFW_KEY_9)) hand_id = 9;

		if (PRESS(GLFW_KEY_SPACE)) {
			Audio::play_sound("../Media/soft-ping.ogg", false);
			map->tiles[map->calcTileIndex(obj->pos)].tid = 2;
			map->bake_tiles();
		}
		#undef PRESS
	}

	void loop() {
		do {
			::main_draw_start();
			update_control();

			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

			glEnable(GL_BLEND);
			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

			shader_textured->use();

			// Setup uniforms
			shader_textured->set_float("brightness", VMDE->state.brightness);
			shader_textured->set_texture("colortex0", tile_texture, 0);

			// Textured blocks rendering
			shader_textured->ProjectionView(projection, view);
			map->render();

			// Setup uniforms
			// Non textured rendering
			shader_basic->use();
			shader_textured->ProjectionView(projection, view);
			block_pointer->mat[0] = obj->transform();
			block_pointer->update_instance(1);
			block_pointer->render();

			axe->render();

			// GUI rendering
			gui->use();
			gui->set_texture("atlastex", tile_texture, 0);
			gui->ProjectionView(gui_2d_projection, glm::mat4(1.0));
			glDisable(GL_DEPTH_TEST);
			if (hand_id > 0)
				clist[hand_id - 1]->render();
			glEnable(GL_DEPTH_TEST);

			::main_draw_end();
		} while (!VMDE->done);
	}

	void start_game() {
		::init_engine(860, 540, "VM / 76");
		init_control();

		tile_texture = new Res::Texture("../Media/terrain.png");

		shader_textured = Shaders::CreateFromFile("../Media/shaders/gbuffers_textured.vsh", "../Media/shaders/gbuffers_textured.fsh");
		shader_basic = Shaders::CreateFromFile("../Media/shaders/gbuffers_basic.vsh", "../Media/shaders/gbuffers_basic.fsh");
		gui = Shaders::CreateFromFile("../Media/shaders/gui.vsh", "../Media/shaders/gui.fsh");
		float aspectRatio = float(VMDE->width) / float(VMDE->height);
		gui_2d_projection = glm::ortho(0.0, 1.0 * aspectRatio, 0.0, 1.0, -1.0, 1.0);

		projection = glm::perspective(1.3f, float(VMDE->width) / float(VMDE->height), 0.1f, 1000.0f);
		view = glm::lookAt(glm::vec3(0.0, 2.6, 0.0), glm::vec3(0.0, 0.0, 0.0), glm::vec3(0.0, 1.0, 0.0));

		// GL settings initialize
		glFrontFace(GL_CCW);
		glEnable(GL_CULL_FACE);

		glEnable(GL_DEPTH_TEST);
		glDepthFunc(GL_LEQUAL);

		glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
		glDepthRange(0.0f, 1.0f);
		glClearDepth(1.0f);
		glDepthMask(GL_TRUE);

		block_pointer = new Cube(1);
		// Set up hand block indicator's matrix
		glm::mat4 block_display = glm::translate(glm::mat4(1.0), glm::vec3(0.02, 0.06, 0.2));
		block_display = glm::scale(block_display, glm::vec3(0.1f));
		block_display = glm::rotate(block_display, Util::PIf / 4.0f, glm::vec3(1.0, 0.0, 0.0));
		block_display = glm::rotate(block_display, Util::PIf / 4.0f, glm::vec3(0.0, 1.0, 0.0));
		for (int i = 0; i < 16; i++) {
			clist[i] = new Cube(i);
			clist[i]->mat[0] = block_display;
			clist[i]->update_instance(1);
		}
		axe = new Axis();
		map = new TiledMap(16, 16, 16, glm::vec3(0.0));
		block_pointer->obj->data.mat_c = 1;
		glfwSetKeyCallback(window, key_callback);

		loop();
		terminate();
	}

	void terminate() {
		log("starting to terminate");
		terminate_engine();
		VMDE_Dispose(tile_texture);
		VMDE_Dispose(block_pointer);
		for (int i = 0; i < 16; i++) VMDE_Dispose(clist[i]);
		VMDE_Dispose(map);
		log("terminated successfully");
	}
}

int main() {
	log("Hello! This is VM76. Nice to meet you!");
	VM76::start_game();
}
<commit_msg>随心所欲地放置方块！<commit_after>//=============================================================================
// ■ main.cpp
//-----------------------------------------------------------------------------
//   VMGS的主程序。
//=============================================================================

#include "VMGS.hpp"

namespace VM76 {
	Shaders* shader_textured = NULL;
	Shaders* gui = NULL;
	Shaders* shader_basic = NULL;
	Res::Texture* tile_texture = NULL;

	Cube* block_pointer;
	Cube* clist[16];
	TiledMap* map;

	glm::mat4 gui_2d_projection;

	int hand_id = 1;

	Axis* axe;

	Object* obj = new Object();

	void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
		#define PRESS(n) key == n && action == GLFW_PRESS
		if (PRESS(GLFW_KEY_A)) obj->move(glm::vec3(-1.0, 0.0, 0.0));
		if (PRESS(GLFW_KEY_D)) obj->move(glm::vec3(1.0, 0.0, 0.0));
		if (PRESS(GLFW_KEY_W)) obj->move(glm::vec3(0.0, 0.0, -1.0));
		if (PRESS(GLFW_KEY_S)) obj->move(glm::vec3(0.0, 0.0, 1.0));
		if (PRESS(GLFW_KEY_UP)) obj->move(glm::vec3(0.0, 1.0, 0.0));
		if (PRESS(GLFW_KEY_DOWN)) obj->move(glm::vec3(0.0, -1.0, 0.0));

		if (PRESS(GLFW_KEY_0)) hand_id = 0;
		if (PRESS(GLFW_KEY_0)) hand_id = 0;
		if (PRESS(GLFW_KEY_1)) hand_id = 1;
		if (PRESS(GLFW_KEY_2)) hand_id = 2;
		if (PRESS(GLFW_KEY_3)) hand_id = 3;
		if (PRESS(GLFW_KEY_4)) hand_id = 4;
		if (PRESS(GLFW_KEY_5)) hand_id = 5;
		if (PRESS(GLFW_KEY_6)) hand_id = 6;
		if (PRESS(GLFW_KEY_7)) hand_id = 7;
		if (PRESS(GLFW_KEY_8)) hand_id = 8;
		if (PRESS(GLFW_KEY_9)) hand_id = 9;

		if (PRESS(GLFW_KEY_SPACE)) {
			Audio::play_sound("../Media/soft-ping.ogg", false);
			map->tiles[map->calcTileIndex(obj->pos)].tid = hand_id;
			map->bake_tiles();
		}
		#undef PRESS
	}

	void loop() {
		do {
			::main_draw_start();
			update_control();

			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

			glEnable(GL_BLEND);
			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

			shader_textured->use();

			// Setup uniforms
			shader_textured->set_float("brightness", VMDE->state.brightness);
			shader_textured->set_texture("colortex0", tile_texture, 0);

			// Textured blocks rendering
			shader_textured->ProjectionView(projection, view);
			map->render();

			// Setup uniforms
			// Non textured rendering
			shader_basic->use();
			shader_textured->ProjectionView(projection, view);
			block_pointer->mat[0] = obj->transform();
			block_pointer->update_instance(1);
			block_pointer->render();

			axe->render();

			// GUI rendering
			gui->use();
			gui->set_texture("atlastex", tile_texture, 0);
			gui->ProjectionView(gui_2d_projection, glm::mat4(1.0));
			glDisable(GL_DEPTH_TEST);
			if (hand_id > 0)
				clist[hand_id - 1]->render();
			glEnable(GL_DEPTH_TEST);

			::main_draw_end();
		} while (!VMDE->done);
	}

	void start_game() {
		::init_engine(860, 540, "VM / 76");
		init_control();

		tile_texture = new Res::Texture("../Media/terrain.png");

		shader_textured = Shaders::CreateFromFile("../Media/shaders/gbuffers_textured.vsh", "../Media/shaders/gbuffers_textured.fsh");
		shader_basic = Shaders::CreateFromFile("../Media/shaders/gbuffers_basic.vsh", "../Media/shaders/gbuffers_basic.fsh");
		gui = Shaders::CreateFromFile("../Media/shaders/gui.vsh", "../Media/shaders/gui.fsh");
		float aspectRatio = float(VMDE->width) / float(VMDE->height);
		gui_2d_projection = glm::ortho(0.0, 1.0 * aspectRatio, 0.0, 1.0, -1.0, 1.0);

		projection = glm::perspective(1.3f, float(VMDE->width) / float(VMDE->height), 0.1f, 1000.0f);
		view = glm::lookAt(glm::vec3(0.0, 2.6, 0.0), glm::vec3(0.0, 0.0, 0.0), glm::vec3(0.0, 1.0, 0.0));

		// GL settings initialize
		glFrontFace(GL_CCW);
		glEnable(GL_CULL_FACE);

		glEnable(GL_DEPTH_TEST);
		glDepthFunc(GL_LEQUAL);

		glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
		glDepthRange(0.0f, 1.0f);
		glClearDepth(1.0f);
		glDepthMask(GL_TRUE);

		block_pointer = new Cube(1);
		// Set up hand block indicator's matrix
		glm::mat4 block_display = glm::translate(glm::mat4(1.0), glm::vec3(0.02, 0.06, 0.2));
		block_display = glm::scale(block_display, glm::vec3(0.1f));
		block_display = glm::rotate(block_display, Util::PIf / 4.0f, glm::vec3(1.0, 0.0, 0.0));
		block_display = glm::rotate(block_display, Util::PIf / 4.0f, glm::vec3(0.0, 1.0, 0.0));
		for (int i = 0; i < 16; i++) {
			clist[i] = new Cube(i);
			clist[i]->mat[0] = block_display;
			clist[i]->update_instance(1);
		}
		axe = new Axis();
		map = new TiledMap(16, 16, 16, glm::vec3(0.0));
		block_pointer->obj->data.mat_c = 1;
		glfwSetKeyCallback(window, key_callback);

		loop();
		terminate();
	}

	void terminate() {
		log("starting to terminate");
		terminate_engine();
		VMDE_Dispose(tile_texture);
		VMDE_Dispose(block_pointer);
		for (int i = 0; i < 16; i++) VMDE_Dispose(clist[i]);
		VMDE_Dispose(map);
		log("terminated successfully");
	}
}

int main() {
	log("Hello! This is VM76. Nice to meet you!");
	VM76::start_game();
}
<|endoftext|>


<commit_before>#ifndef RECURSE_ROUTER_HPP
#define RECURSE_ROUTER_HPP

#include <recurse.hpp>
#include <QString>
#include <QHash>
#include <QList>
#include <QPair>
#include <QRegularExpression>

namespace Module
{
    class Router
    {
    private:
        bool m_debug = false;

        void debug(QString message)
        {
            if (m_debug)
                std::cout << "(router debug) " << message.toStdString() << std::endl;
        }

        using HTTP_Method = QList<QPair<QString, Downstream>>;

        HTTP_Method HTTP_GET;
        HTTP_Method HTTP_PUT;
        HTTP_Method HTTP_POST;
        HTTP_Method HTTP_PATCH;
        HTTP_Method HTTP_DELETE;
        HTTP_Method HTTP_HEAD;
        HTTP_Method HTTP_OPTIONS;

        QHash<QString, HTTP_Method *> methods{
            { "GET", &HTTP_GET }, { "PUT", &HTTP_PUT },
            { "POST", &HTTP_POST }, { "PATCH", &HTTP_PATCH },
            { "DELETE", &HTTP_DELETE }, { "HEAD", &HTTP_HEAD },
            { "OPTIONS", &HTTP_OPTIONS },
        };

        // https://tools.ietf.org/html/rfc3986#appendix-A
        QString path_to_regexp(QString path)
        {
            path.prepend("^");

            auto colon = path.indexOf(":");
            if (colon != -1)
            {
                auto question = path.indexOf("?", colon);
                if (question != -1)
                    // optional arguments :name?
                    path.replace(QRegularExpression("/:[A-z0-9]+\\?"),
                    "(?:/([^/]+?))?(?:/(?=$))?");
                else
                    // regular arguments :name
                    path.replace(QRegularExpression(":[A-z0-9]+"), "[^/]+?");
            }

            // catch-all argument /name/*
            auto asterix = path.indexOf("*");
            if (asterix != -1)
                path.insert(asterix, ".");

            path.append("$");

            return path;
        }

    public:
        Router()
        {
            QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
            QRegExp debug_strings("(router)");

            if (debug_strings.indexIn(env.value("DEBUG")) != -1)
                m_debug = true;
        }

        void GET(QString path, Downstream next)
        {
            HTTP_GET.append(QPair<QString, Downstream>(path, next));
        }

        void PUT(QString path, Downstream next)
        {
            HTTP_PUT.append(QPair<QString, Downstream>(path, next));
        }

        void POST(QString path, Downstream next)
        {
            HTTP_POST.append(QPair<QString, Downstream>(path, next));
        }

        void PATCH(QString path, Downstream next)
        {
            HTTP_PATCH.append(QPair<QString, Downstream>(path, next));
        }

        void HEAD(QString path, Downstream next)
        {
            HTTP_HEAD.append(QPair<QString, Downstream>(path, next));
        }

        void DELETE(QString path, Downstream next)
        {
            HTTP_DELETE.append(QPair<QString, Downstream>(path, next));
        }

        void OPTIONS(QString path, Downstream next)
        {
            HTTP_OPTIONS.append(QPair<QString, Downstream>(path, next));
        }

        void ALL(QString path, Downstream next)
        {
            GET(path, next);
            PUT(path, next);
            POST(path, next);
            PATCH(path, next);
            HEAD(path, next);
            DELETE(path, next);
            OPTIONS(path, next);
        }

        auto routes()
        {
            return [this](auto &ctx, auto next)
            {
                auto request = ctx.request;

                if (!methods.contains(request.method))
                    return next();

                auto method = *(methods[request.method]);

                auto url = request.url;
                auto query = url.query();
                auto path = url.path();

                // call first route that matches
                for (auto pair : method)
                {
                    auto key = pair.first;

                    this->debug("trying path:" + key);

                    QRegularExpression regexp(this->path_to_regexp(key));
                    if (!regexp.isValid() || !regexp.match(path).hasMatch())
                        continue;

                    this->debug("path matched");

                    // parse parameters if any
                    auto colon = key.indexOf(":");
                    if (colon)
                    {
                        // we use QStringRef so we don't allocate on search
                        auto matchString = key.midRef(colon);
                        auto pathString = path.midRef(colon);

                        auto matches = matchString.split("/");
                        auto paths = pathString.split("/");

                        // match: /hello/:id/:/name
                        // request: /hello/1/test

                        for (int i = 0; i < matches.size(); i++)
                        {
                            auto match = matches.at(i);
                            colon = match.indexOf(":");
                            if (colon == -1)
                                continue;

                            auto paramKey = match.mid(colon + 1, match.indexOf("?") - 1);
                            auto paramValue = paths.at(i);

                            ctx.request.params[paramKey.toString()] = paramValue.toString();
                        }
                    }

                    auto call = pair.second;
                    call(ctx, next);

                    return;
                }

                // call next middleware if nothing matched
                next();
            };
        }
    };
}

#endif // RECURSE_ROUTER_HPP
<commit_msg>update to include Recurse namespace<commit_after>#ifndef RECURSE_ROUTER_HPP
#define RECURSE_ROUTER_HPP

#include <recurse.hpp>
#include <QString>
#include <QHash>
#include <QList>
#include <QPair>
#include <QRegularExpression>

namespace Module
{
    class Router
    {
    private:
        bool m_debug = false;

        void debug(QString message)
        {
            if (m_debug)
                std::cout << "(router debug) " << message.toStdString() << std::endl;
        }

        using Downstream = Recurse::Downstream;
        using HTTP_Method = QList<QPair<QString, Downstream>>;

        HTTP_Method HTTP_GET;
        HTTP_Method HTTP_PUT;
        HTTP_Method HTTP_POST;
        HTTP_Method HTTP_PATCH;
        HTTP_Method HTTP_DELETE;
        HTTP_Method HTTP_HEAD;
        HTTP_Method HTTP_OPTIONS;

        QHash<QString, HTTP_Method *> methods{
            { "GET", &HTTP_GET }, { "PUT", &HTTP_PUT },
            { "POST", &HTTP_POST }, { "PATCH", &HTTP_PATCH },
            { "DELETE", &HTTP_DELETE }, { "HEAD", &HTTP_HEAD },
            { "OPTIONS", &HTTP_OPTIONS },
        };

        // https://tools.ietf.org/html/rfc3986#appendix-A
        QString path_to_regexp(QString path)
        {
            path.prepend("^");

            auto colon = path.indexOf(":");
            if (colon != -1)
            {
                auto question = path.indexOf("?", colon);
                if (question != -1)
                    // optional arguments :name?
                    path.replace(QRegularExpression("/:[A-z0-9]+\\?"),
                    "(?:/([^/]+?))?(?:/(?=$))?");
                else
                    // regular arguments :name
                    path.replace(QRegularExpression(":[A-z0-9]+"), "[^/]+?");
            }

            // catch-all argument /name/*
            auto asterix = path.indexOf("*");
            if (asterix != -1)
                path.insert(asterix, ".");

            path.append("$");

            return path;
        }

    public:
        Router()
        {
            QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
            QRegExp debug_strings("(router)");

            if (debug_strings.indexIn(env.value("DEBUG")) != -1)
                m_debug = true;
        }

        void GET(QString path, Downstream next)
        {
            HTTP_GET.append(QPair<QString, Downstream>(path, next));
        }

        void PUT(QString path, Downstream next)
        {
            HTTP_PUT.append(QPair<QString, Downstream>(path, next));
        }

        void POST(QString path, Downstream next)
        {
            HTTP_POST.append(QPair<QString, Downstream>(path, next));
        }

        void PATCH(QString path, Downstream next)
        {
            HTTP_PATCH.append(QPair<QString, Downstream>(path, next));
        }

        void HEAD(QString path, Downstream next)
        {
            HTTP_HEAD.append(QPair<QString, Downstream>(path, next));
        }

        void DELETE(QString path, Downstream next)
        {
            HTTP_DELETE.append(QPair<QString, Downstream>(path, next));
        }

        void OPTIONS(QString path, Downstream next)
        {
            HTTP_OPTIONS.append(QPair<QString, Downstream>(path, next));
        }

        void ALL(QString path, Downstream next)
        {
            GET(path, next);
            PUT(path, next);
            POST(path, next);
            PATCH(path, next);
            HEAD(path, next);
            DELETE(path, next);
            OPTIONS(path, next);
        }

        auto routes()
        {
            return [this](auto &ctx, auto next)
            {
                auto request = ctx.request;

                if (!methods.contains(request.method))
                    return next();

                auto method = *(methods[request.method]);

                auto url = request.url;
                auto query = url.query();
                auto path = url.path();

                // call first route that matches
                for (auto pair : method)
                {
                    auto key = pair.first;

                    this->debug("trying path:" + key);

                    QRegularExpression regexp(this->path_to_regexp(key));
                    if (!regexp.isValid() || !regexp.match(path).hasMatch())
                        continue;

                    this->debug("path matched");

                    // parse parameters if any
                    auto colon = key.indexOf(":");
                    if (colon)
                    {
                        // we use QStringRef so we don't allocate on search
                        auto matchString = key.midRef(colon);
                        auto pathString = path.midRef(colon);

                        auto matches = matchString.split("/");
                        auto paths = pathString.split("/");

                        // match: /hello/:id/:/name
                        // request: /hello/1/test

                        for (int i = 0; i < matches.size(); i++)
                        {
                            auto match = matches.at(i);
                            colon = match.indexOf(":");
                            if (colon == -1)
                                continue;

                            auto paramKey = match.mid(colon + 1, match.indexOf("?") - 1);
                            auto paramValue = paths.at(i);

                            ctx.request.params[paramKey.toString()] = paramValue.toString();
                        }
                    }

                    auto call = pair.second;
                    call(ctx, next);

                    return;
                }

                // call next middleware if nothing matched
                next();
            };
        }
    };
}

#endif // RECURSE_ROUTER_HPP
<|endoftext|>


<commit_before>#include "testApp.h"

class myUser : public ofxOpenNIUser {
public:
    void test(){
        cout << "test" << endl;
    }
};

//-- functions and properties which might be useful for recording skeletal data
//////////////////////
//ofxOpenNI.h
//////////////////////
//    bool setSkeletonProfile(XnSkeletonProfile profile);
//    XnSkeletonProfile getSkeletonProfile();
//    xn::UserGenerator& getUserGenerator();
//	xn::DepthGenerator& getDepthGenerator();
//  xn::ImageGenerator& getImageGenerator();
//xn::DepthMetaData& getDepthMetaData();
//xn::ImageMetaData& getImageMetaData();
//    ofEvent<ofxOpenNIUserEvent> userEvent;
//////////////////////
//ofxOpenNiUtils.h
//////////////////////
// enum Joint
// enum Limb
// static inline ofPoint g_worldToProjective(const ofPoint& p)
// static inline ofPoint g_projectiveToWorld(const ofPoint& p)
// static inline ofPoint worldToProjective(const XnVector3D& p, xn::DepthGenerator & g_Depth)
// inline Joint XnToOfJoint(XnSkeletonJoint type)
// inline string getXNJointAsString(XnSkeletonJoint type)
// inline string getJointAsString(Joint type)
// inline string getLimbAsString(Limb type)
// inline string getUserStatusAsString(UserStatusType type)
// inline string getCalibrationStatusAsString(XnCalibrationStatus type)
//////////////////////
//ofxOpenNiTypes.h
//////////////////////
// class ofxOpenNIJoint
//      ofPoint & getProjectivePosition()
//      ofPoint & getWorldPosition()
// class ofxOpenNILimb
//    void draw() {
//
//        ofPushStyle();
//        if(isFound()){
//            // draw in green
//            ofSetColor(0, 255, 0);
//        }else{
//            // draw in red
//            ofSetColor(255, 0, 0);
//        }
//        ofSetLineWidth(5);
//        ofLine(ofVec2f(startJoint->getProjectivePosition()),ofVec2f(endJoint->getProjectivePosition()));
//        ofPopStyle();
//    }
// inline int numJointsInside(ofxOpenNIUser & user)
//

//--------------------------------------------------------------
void testApp::setup() {

    ofSetLogLevel(OF_LOG_VERBOSE);

    openNIRecorder.setup();
    openNIRecorder.addDepthGenerator();
    openNIRecorder.addImageGenerator();
    openNIRecorder.setRegister(true);
    openNIRecorder.setMirror(true);
    openNIRecorder.addUserGenerator();
    openNIRecorder.setMaxNumUsers(2);
    openNIRecorder.start();

    openNIPlayer.setup();
    openNIPlayer.addUserGenerator();
	openNIPlayer.start();

    verdana.loadFont(ofToDataPath("verdana.ttf"), 24);
}

//--------------------------------------------------------------
void testApp::update(){
    openNIRecorder.update();
    openNIPlayer.update();
}

//--------------------------------------------------------------
void testApp::draw(){
	ofSetColor(255, 255, 255);

    ofPushMatrix();

    openNIRecorder.drawDebug(0, 0);
    openNIPlayer.drawDebug(0, 480);

    ofPushMatrix();

	ofSetColor(0, 255, 0);
	string msg = " MILLIS: " + ofToString(ofGetElapsedTimeMillis()) + " FPS: " + ofToString(ofGetFrameRate());
	verdana.drawString(msg, 20, 2 * 480 - 20);
}

//--------------------------------------------------------------
void testApp::userEvent(ofxOpenNIUserEvent & event){
    ofLogNotice() << getUserStatusAsString(event.userStatus) << "for user" << event.id << "from device" << event.deviceID;
}

//--------------------------------------------------------------
void testApp::gestureEvent(ofxOpenNIGestureEvent & event){
    ofLogNotice() << event.gestureName << getGestureStatusAsString(event.gestureStatus) << "from device" << event.deviceID << "at" << event.timestampMillis;
}

//--------------------------------------------------------------
void testApp::exit(){
    openNIRecorder.stop();
    openNIPlayer.stop();
}

//--------------------------------------------------------------
void testApp::keyPressed(int key){

    int cloudRes = -1;
    string fileName = "test_20140501_1904.oni";
    switch (key) {
        case ' ':
            if(!openNIRecorder.isRecording()){
//                openNIRecorder.startRecording(ofToDataPath("test"+ std::to_string(ofGetSystemTimeMicros()/1000)+".oni"));
                openNIRecorder.startRecording(ofToDataPath(fileName));
            }else{
                openNIRecorder.stopRecording();
            }
            break;
        case 'p':
            openNIPlayer.startPlayer(fileName);
            break;
        case '/':
            openNIPlayer.setPaused(!openNIPlayer.isPaused());
            break;
        case 'm':
            openNIPlayer.firstFrame();
            break;
        case '<':
        case ',':
            openNIPlayer.previousFrame();
            break;
        case '>':
        case '.':
            openNIPlayer.nextFrame();
            break;
        case 'x':
            openNIRecorder.stop();
            openNIPlayer.stop();
            break;
        case 't':
            openNIRecorder.toggleRegister();
            break;
    }

}

//--------------------------------------------------------------
void testApp::keyReleased(int key){

}

//--------------------------------------------------------------
void testApp::mouseMoved(int x, int y ){

}

//--------------------------------------------------------------
void testApp::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::windowResized(int w, int h){

}<commit_msg>Added in more notes about potentially useful functions for this project.<commit_after>#include "testApp.h"

class myUser : public ofxOpenNIUser {
public:
    void test(){
        cout << "test" << endl;
    }
};

//-- functions and properties which might be useful for recording skeletal data
//////////////////////
//ofxOpenNITypes.cpp
//////////////////////
//    void ofxOpenNIUser::drawSkeleton() {
//        ofPushStyle();
//        // DON'T NEED TO DRAW LIMBS ANYMORE!
//        //	for(int i = 0; i < limbs.size(); i++){
//        //		limbs[i].draw();
//        //	}
//        for(int i = 0; i < joints.size(); i++){
//            joints[i].draw();
//        }
//        ofPopStyle();
//    }
//
//    ofPixels & ofxOpenNIDepthThreshold::getDepthPixels(){
//        return depthPixels;
//    }
//
//    ofPixels & ofxOpenNIDepthThreshold::getMaskPixels(){
//        return maskPixels;
//    }
//
//////////////////////
//ofxOpenNI.cpp
//////////////////////
//    ofPixels& ofxOpenNI::getDepthPixels();
//    ofPixels& ofxOpenNI::getImagePixels();
//    xn::UserGenerator& ofxOpenNI::getUserGenerator();
//    drawSkeletons();
//    if(g_bIsDepthOn) drawDepth();
//    if(g_bIsHandsOn) drawHands();
//    if(g_bIsUserOn) drawSkeletons();
//    ofTranslate(getWidth(), 0.0f);
//    if(g_bIsImageOn || g_bIsInfraOn) drawImage();
// 	currentTrackedUsers[currentTrackedUserIDs[nID]].drawSkeleton();
//////////////////////
//ofxOpenNI.h
//////////////////////
//    bool setSkeletonProfile(XnSkeletonProfile profile);
//    XnSkeletonProfile getSkeletonProfile();
//    xn::UserGenerator& getUserGenerator();
//    xn::DepthGenerator& getDepthGenerator();
//    xn::ImageGenerator& getImageGenerator();
//    xn::DepthMetaData& getDepthMetaData();
//    xn::ImageMetaData& getImageMetaData();
//    ofEvent<ofxOpenNIUserEvent> userEvent;
//////////////////////
//ofxOpenNiUtils.h
//////////////////////
//    enum Joint
//    enum Limb
//    static inline ofPoint g_worldToProjective(const ofPoint& p)
//    static inline ofPoint g_projectiveToWorld(const ofPoint& p)
//    static inline ofPoint worldToProjective(const XnVector3D& p, xn::DepthGenerator & g_Depth)
//    inline Joint XnToOfJoint(XnSkeletonJoint type)
//    inline string getXNJointAsString(XnSkeletonJoint type)
//    inline string getJointAsString(Joint type)
//    inline string getLimbAsString(Limb type)
//    inline string getUserStatusAsString(UserStatusType type)
//    inline string getCalibrationStatusAsString(XnCalibrationStatus type)
//////////////////////
//ofxOpenNiTypes.h
//////////////////////
// class ofxOpenNIJoint
//      ofPoint & getProjectivePosition()
//      ofPoint & getWorldPosition()
// class ofxOpenNILimb
//    void draw() {
//
//        ofPushStyle();
//        if(isFound()){
//            // draw in green
//            ofSetColor(0, 255, 0);
//        }else{
//            // draw in red
//            ofSetColor(255, 0, 0);
//        }
//        ofSetLineWidth(5);
//        ofLine(ofVec2f(startJoint->getProjectivePosition()),ofVec2f(endJoint->getProjectivePosition()));
//        ofPopStyle();
//    }
// inline int numJointsInside(ofxOpenNIUser & user)
//

//--------------------------------------------------------------
void testApp::setup() {

    ofSetLogLevel(OF_LOG_VERBOSE);

    openNIRecorder.setup();
    openNIRecorder.addDepthGenerator();
    openNIRecorder.addImageGenerator();
    openNIRecorder.setRegister(true);
    openNIRecorder.setMirror(true);
    openNIRecorder.addUserGenerator();
    openNIRecorder.setMaxNumUsers(2);
    openNIRecorder.start();

    openNIPlayer.setup();
    openNIPlayer.addUserGenerator();
	openNIPlayer.start();

    verdana.loadFont(ofToDataPath("verdana.ttf"), 24);
}

//--------------------------------------------------------------
void testApp::update(){
    openNIRecorder.update();
    openNIPlayer.update();
}

//--------------------------------------------------------------
void testApp::draw(){
	ofSetColor(255, 255, 255);

    ofPushMatrix();

    openNIRecorder.drawDebug(0, 0);
    openNIPlayer.drawDebug(0, 480);

    ofPushMatrix();

	ofSetColor(0, 255, 0);
	string msg = " MILLIS: " + ofToString(ofGetElapsedTimeMillis()) + " FPS: " + ofToString(ofGetFrameRate());
	verdana.drawString(msg, 20, 2 * 480 - 20);
}

//--------------------------------------------------------------
void testApp::userEvent(ofxOpenNIUserEvent & event){
    ofLogNotice() << getUserStatusAsString(event.userStatus) << "for user" << event.id << "from device" << event.deviceID;
}

//--------------------------------------------------------------
void testApp::gestureEvent(ofxOpenNIGestureEvent & event){
    ofLogNotice() << event.gestureName << getGestureStatusAsString(event.gestureStatus) << "from device" << event.deviceID << "at" << event.timestampMillis;
}

//--------------------------------------------------------------
void testApp::exit(){
    openNIRecorder.stop();
    openNIPlayer.stop();
}

//--------------------------------------------------------------
void testApp::keyPressed(int key){

    int cloudRes = -1;
    string fileName = "test_20140501_1904.oni";
    switch (key) {
        case ' ':
            if(!openNIRecorder.isRecording()){
//                openNIRecorder.startRecording(ofToDataPath("test"+ std::to_string(ofGetSystemTimeMicros()/1000)+".oni"));
                openNIRecorder.startRecording(ofToDataPath(fileName));
            }else{
                openNIRecorder.stopRecording();
            }
            break;
        case 'p':
            openNIPlayer.startPlayer(fileName);
            break;
        case '/':
            openNIPlayer.setPaused(!openNIPlayer.isPaused());
            break;
        case 'm':
            openNIPlayer.firstFrame();
            break;
        case '<':
        case ',':
            openNIPlayer.previousFrame();
            break;
        case '>':
        case '.':
            openNIPlayer.nextFrame();
            break;
        case 'x':
            openNIRecorder.stop();
            openNIPlayer.stop();
            break;
        case 't':
            openNIRecorder.toggleRegister();
            break;
    }

}

//--------------------------------------------------------------
void testApp::keyReleased(int key){

}

//--------------------------------------------------------------
void testApp::mouseMoved(int x, int y ){

}

//--------------------------------------------------------------
void testApp::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::windowResized(int w, int h){

}<|endoftext|>


<commit_before>#include "base/logging.h"
#include "gl_state.h"
#ifdef _WIN32
#include "GL/wglew.h"
#endif

#if defined(USING_GLES2)
#if defined(ANDROID)
PFNGLALPHAFUNCQCOMPROC glAlphaFuncQCOM;
PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC eglGetSystemTimeFrequencyNV;
PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNV;
PFNGLMAPBUFFERPROC glMapBuffer;
#endif
#if !defined(IOS) && !defined(__SYMBIAN32__) && !defined(MEEGO_EDITION_HARMATTAN) && !defined(MAEMO)
PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT;
PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOES;
PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOES;
PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArraysOES;
PFNGLISVERTEXARRAYOESPROC glIsVertexArrayOES;
#endif
#endif

OpenGLState glstate;
GLExtensions gl_extensions;
std::string g_all_gl_extensions;
std::string g_all_egl_extensions;

int OpenGLState::state_count = 0;

void OpenGLState::Initialize() {
	if(initialized) return;

	Restore();

	initialized = true;
}

void OpenGLState::Restore() {
	int count = 0;
	blend.restore(); count++;
	blendEquation.restore(); count++;
	blendFuncSeparate.restore(); count++;
	blendColor.restore(); count++;

#if !defined(USING_GLES2)
	colorLogicOp.restore(); count++;
	logicOp.restore(); count++;
#endif

#ifdef ANDROID
	if (gl_extensions.QCOM_alpha_test) {
		alphaTestQCOM.restore(); count++;
		alphaFuncQCOM.restore(); count++;
	}
#endif

	scissorTest.restore(); count++;
	scissorRect.restore(); count++;

	cullFace.restore(); count++;
	cullFaceMode.restore(); count++;
	frontFace.restore(); count++;

	depthTest.restore(); count++;
	depthRange.restore(); count++;
	depthFunc.restore(); count++;
	depthWrite.restore(); count++;

	colorMask.restore(); count++;
	viewport.restore(); count++;

	stencilTest.restore(); count++;
	stencilOp.restore(); count++;
	stencilFunc.restore(); count++;

	dither.restore(); count++;

	if (count != state_count) {
		FLOG("OpenGLState::Restore is missing some states");
	}
}

// http://stackoverflow.com/questions/16147700/opengl-es-using-tegra-specific-extensions-gl-ext-texture-array

void CheckGLExtensions() {
	static bool done = false;
	if (done)
		return;
	done = true;

	memset(&gl_extensions, 0, sizeof(gl_extensions));

	const char *extString = (const char *)glGetString(GL_EXTENSIONS);
	if (extString) {
		g_all_gl_extensions = extString;
	} else {
		g_all_gl_extensions = "";
	}

#ifdef WIN32
	const char *wglString = wglGetExtensionsStringEXT();
	if (wglString) {
		gl_extensions.EXT_swap_control_tear = strstr(wglString, "WGL_EXT_swap_control_tear") != 0;
		g_all_egl_extensions = wglString;
	} else {
		g_all_egl_extensions = "";
	}
#elif !defined(USING_GLES2)
	// const char *glXString = glXQueryExtensionString();
	// gl_extensions.EXT_swap_control_tear = strstr(glXString, "GLX_EXT_swap_control_tear") != 0;
#endif

#ifdef USING_GLES2
	gl_extensions.OES_packed_depth_stencil = strstr(extString, "GL_OES_packed_depth_stencil") != 0;
	gl_extensions.OES_depth24 = strstr(extString, "GL_OES_depth24") != 0;
	gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture") != 0;
	gl_extensions.OES_mapbuffer = strstr(extString, "GL_OES_mapbuffer") != 0;
#if defined(IOS) || defined(__SYMBIAN32__) || defined(MEEGO_EDITION_HARMATTAN) || defined(MAEMO)
	gl_extensions.OES_vertex_array_object = false;
	gl_extensions.EXT_discard_framebuffer = false;
#else
	gl_extensions.OES_vertex_array_object = strstr(extString, "GL_OES_vertex_array_object") != 0;
	if (gl_extensions.OES_vertex_array_object) {
		glGenVertexArraysOES = (PFNGLGENVERTEXARRAYSOESPROC)eglGetProcAddress ( "glGenVertexArraysOES" );
		glBindVertexArrayOES = (PFNGLBINDVERTEXARRAYOESPROC)eglGetProcAddress ( "glBindVertexArrayOES" );
		glDeleteVertexArraysOES = (PFNGLDELETEVERTEXARRAYSOESPROC)eglGetProcAddress ( "glDeleteVertexArraysOES" );
		glIsVertexArrayOES = (PFNGLISVERTEXARRAYOESPROC)eglGetProcAddress ( "glIsVertexArrayOES" );
	}

	gl_extensions.EXT_discard_framebuffer = strstr(extString, "GL_EXT_discard_framebuffer") != 0;
	if (gl_extensions.EXT_discard_framebuffer) {
		glDiscardFramebufferEXT = (PFNGLDISCARDFRAMEBUFFEREXTPROC)eglGetProcAddress("glDiscardFramebufferEXT");
	}

#endif
#endif

#ifdef ANDROID
	if (gl_extensions.OES_mapbuffer) {
		glMapBuffer = (PFNGLMAPBUFFERPROC)eglGetProcAddress( "glMapBufferOES" );
	}
	gl_extensions.QCOM_binning_control = strstr(extString, "GL_QCOM_binning_control") != 0;
	gl_extensions.QCOM_alpha_test = strstr(extString, "GL_QCOM_alpha_test") != 0;
	// Load extensions that are not auto-loaded by Android.
	if (gl_extensions.QCOM_alpha_test) {
		glAlphaFuncQCOM = (PFNGLALPHAFUNCQCOMPROC)eglGetProcAddress("glAlphaFuncQCOM");
	}

	// Look for EGL extensions
	EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);

	const char *eglString = eglQueryString(display, EGL_EXTENSIONS);
	if (eglString) {
		g_all_egl_extensions = eglString;

		gl_extensions.EGL_NV_system_time = strstr(eglString, "EGL_NV_system_time") != 0;
		gl_extensions.EGL_NV_coverage_sample = strstr(eglString, "EGL_NV_coverage_sample") != 0;

		if (gl_extensions.EGL_NV_system_time) {
			eglGetSystemTimeNV = (PFNEGLGETSYSTEMTIMENVPROC) eglGetProcAddress("eglGetSystemTimeNV");
			eglGetSystemTimeFrequencyNV = (PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) eglGetProcAddress("eglGetSystemTimeFrequencyNV");
		}
	} else {
		g_all_egl_extensions = "";
	}

#endif

#ifdef USING_GLES2
	gl_extensions.FBO_ARB = true;
	gl_extensions.FBO_EXT = false;
#else
	gl_extensions.FBO_ARB = strstr(extString, "GL_ARB_framebuffer_object") != 0;
	gl_extensions.FBO_EXT = strstr(extString, "GL_EXT_framebuffer_object") != 0;
#endif
}

void OpenGLState::SetVSyncInterval(int interval) {
#ifdef _WIN32
	if( wglSwapIntervalEXT )
		wglSwapIntervalEXT(interval);
#endif
}
<commit_msg>Fix android build on non-QCOM (it failed the gstate count check).<commit_after>#include "base/logging.h"
#include "gl_state.h"
#ifdef _WIN32
#include "GL/wglew.h"
#endif

#if defined(USING_GLES2)
#if defined(ANDROID)
PFNGLALPHAFUNCQCOMPROC glAlphaFuncQCOM;
PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC eglGetSystemTimeFrequencyNV;
PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNV;
PFNGLMAPBUFFERPROC glMapBuffer;
#endif
#if !defined(IOS) && !defined(__SYMBIAN32__) && !defined(MEEGO_EDITION_HARMATTAN) && !defined(MAEMO)
PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT;
PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOES;
PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOES;
PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArraysOES;
PFNGLISVERTEXARRAYOESPROC glIsVertexArrayOES;
#endif
#endif

OpenGLState glstate;
GLExtensions gl_extensions;
std::string g_all_gl_extensions;
std::string g_all_egl_extensions;

int OpenGLState::state_count = 0;

void OpenGLState::Initialize() {
	if(initialized) return;

	Restore();

	initialized = true;
}

void OpenGLState::Restore() {
	int count = 0;
	blend.restore(); count++;
	blendEquation.restore(); count++;
	blendFuncSeparate.restore(); count++;
	blendColor.restore(); count++;

#if !defined(USING_GLES2)
	colorLogicOp.restore(); count++;
	logicOp.restore(); count++;
#endif

#ifdef ANDROID
	if (gl_extensions.QCOM_alpha_test) {
		alphaTestQCOM.restore();
	}
	count++;
	if (gl_extensions.QCOM_alpha_test) {
		alphaFuncQCOM.restore();
	}
	count++;
#endif

	scissorTest.restore(); count++;
	scissorRect.restore(); count++;

	cullFace.restore(); count++;
	cullFaceMode.restore(); count++;
	frontFace.restore(); count++;

	depthTest.restore(); count++;
	depthRange.restore(); count++;
	depthFunc.restore(); count++;
	depthWrite.restore(); count++;

	colorMask.restore(); count++;
	viewport.restore(); count++;

	stencilTest.restore(); count++;
	stencilOp.restore(); count++;
	stencilFunc.restore(); count++;

	dither.restore(); count++;

	if (count != state_count) {
		FLOG("OpenGLState::Restore is missing some states");
	}
}

// http://stackoverflow.com/questions/16147700/opengl-es-using-tegra-specific-extensions-gl-ext-texture-array

void CheckGLExtensions() {
	static bool done = false;
	if (done)
		return;
	done = true;

	memset(&gl_extensions, 0, sizeof(gl_extensions));

	const char *extString = (const char *)glGetString(GL_EXTENSIONS);
	if (extString) {
		g_all_gl_extensions = extString;
	} else {
		g_all_gl_extensions = "";
	}

#ifdef WIN32
	const char *wglString = wglGetExtensionsStringEXT();
	if (wglString) {
		gl_extensions.EXT_swap_control_tear = strstr(wglString, "WGL_EXT_swap_control_tear") != 0;
		g_all_egl_extensions = wglString;
	} else {
		g_all_egl_extensions = "";
	}
#elif !defined(USING_GLES2)
	// const char *glXString = glXQueryExtensionString();
	// gl_extensions.EXT_swap_control_tear = strstr(glXString, "GLX_EXT_swap_control_tear") != 0;
#endif

#ifdef USING_GLES2
	gl_extensions.OES_packed_depth_stencil = strstr(extString, "GL_OES_packed_depth_stencil") != 0;
	gl_extensions.OES_depth24 = strstr(extString, "GL_OES_depth24") != 0;
	gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture") != 0;
	gl_extensions.OES_mapbuffer = strstr(extString, "GL_OES_mapbuffer") != 0;
#if defined(IOS) || defined(__SYMBIAN32__) || defined(MEEGO_EDITION_HARMATTAN) || defined(MAEMO)
	gl_extensions.OES_vertex_array_object = false;
	gl_extensions.EXT_discard_framebuffer = false;
#else
	gl_extensions.OES_vertex_array_object = strstr(extString, "GL_OES_vertex_array_object") != 0;
	if (gl_extensions.OES_vertex_array_object) {
		glGenVertexArraysOES = (PFNGLGENVERTEXARRAYSOESPROC)eglGetProcAddress ( "glGenVertexArraysOES" );
		glBindVertexArrayOES = (PFNGLBINDVERTEXARRAYOESPROC)eglGetProcAddress ( "glBindVertexArrayOES" );
		glDeleteVertexArraysOES = (PFNGLDELETEVERTEXARRAYSOESPROC)eglGetProcAddress ( "glDeleteVertexArraysOES" );
		glIsVertexArrayOES = (PFNGLISVERTEXARRAYOESPROC)eglGetProcAddress ( "glIsVertexArrayOES" );
	}

	gl_extensions.EXT_discard_framebuffer = strstr(extString, "GL_EXT_discard_framebuffer") != 0;
	if (gl_extensions.EXT_discard_framebuffer) {
		glDiscardFramebufferEXT = (PFNGLDISCARDFRAMEBUFFEREXTPROC)eglGetProcAddress("glDiscardFramebufferEXT");
	}

#endif
#endif

#ifdef ANDROID
	if (gl_extensions.OES_mapbuffer) {
		glMapBuffer = (PFNGLMAPBUFFERPROC)eglGetProcAddress( "glMapBufferOES" );
	}
	gl_extensions.QCOM_binning_control = strstr(extString, "GL_QCOM_binning_control") != 0;
	gl_extensions.QCOM_alpha_test = strstr(extString, "GL_QCOM_alpha_test") != 0;
	// Load extensions that are not auto-loaded by Android.
	if (gl_extensions.QCOM_alpha_test) {
		glAlphaFuncQCOM = (PFNGLALPHAFUNCQCOMPROC)eglGetProcAddress("glAlphaFuncQCOM");
	}

	// Look for EGL extensions
	EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);

	const char *eglString = eglQueryString(display, EGL_EXTENSIONS);
	if (eglString) {
		g_all_egl_extensions = eglString;

		gl_extensions.EGL_NV_system_time = strstr(eglString, "EGL_NV_system_time") != 0;
		gl_extensions.EGL_NV_coverage_sample = strstr(eglString, "EGL_NV_coverage_sample") != 0;

		if (gl_extensions.EGL_NV_system_time) {
			eglGetSystemTimeNV = (PFNEGLGETSYSTEMTIMENVPROC) eglGetProcAddress("eglGetSystemTimeNV");
			eglGetSystemTimeFrequencyNV = (PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) eglGetProcAddress("eglGetSystemTimeFrequencyNV");
		}
	} else {
		g_all_egl_extensions = "";
	}

#endif

#ifdef USING_GLES2
	gl_extensions.FBO_ARB = true;
	gl_extensions.FBO_EXT = false;
#else
	gl_extensions.FBO_ARB = strstr(extString, "GL_ARB_framebuffer_object") != 0;
	gl_extensions.FBO_EXT = strstr(extString, "GL_EXT_framebuffer_object") != 0;
#endif
}

void OpenGLState::SetVSyncInterval(int interval) {
#ifdef _WIN32
	if( wglSwapIntervalEXT )
		wglSwapIntervalEXT(interval);
#endif
}
<|endoftext|>


<commit_before>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright 2011-2018 Dominik Charousset                                     *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#pragma once

#include <type_traits>

#include "caf/sec.hpp"
#include "caf/catch_all.hpp"
#include "caf/message_id.hpp"
#include "caf/typed_behavior.hpp"
#include "caf/system_messages.hpp"

#include "caf/detail/type_list.hpp"
#include "caf/detail/typed_actor_util.hpp"

namespace caf {

/// This helper class identifies an expected response message
/// and enables `request(...).then(...)`.
template <class Self, class Output, bool IsBlocking>
class response_handle;

/******************************************************************************
 *                                 nonblocking                                *
 ******************************************************************************/
template <class Self, class Output>
class response_handle<Self, Output, false> {
public:
  response_handle() = delete;
  response_handle(const response_handle&) = default;
  response_handle& operator=(const response_handle&) = default;

  response_handle(message_id mid, Self* self) : mid_(mid), self_(self) {
    // nop
  }

  template <class F, class E = detail::is_callable_t<F>>
  void await(F f) const {
    await_impl(f);
  }

  template <class F, class OnError,
            class E1 = detail::is_callable_t<F>,
            class E2 = detail::is_handler_for_ef<OnError, error>>
  void await(F f, OnError e) const {
    await_impl(f, e);
  }

  template <class F, class E = detail::is_callable_t<F>>
  void then(F f) const {
    then_impl(f);
  }

  template <class F, class OnError,
            class E1 = detail::is_callable_t<F>,
            class E2 = detail::is_handler_for_ef<OnError, error>>
  void then(F f, OnError e) const {
    then_impl(f, e);
  }

private:
  template <class F>
  void await_impl(F& f) const {
    static_assert(std::is_same<
                    void,
                    typename detail::get_callable_trait<F>::result_type
                  >::value,
                  "response handlers are not allowed to have a return "
                  "type other than void");
    detail::type_checker<Output, F>::check();
    self_->add_awaited_response_handler(mid_, message_handler{std::move(f)});
  }

  template <class F, class OnError>
  void await_impl(F& f, OnError& ef) const {
    static_assert(std::is_same<
                    void,
                    typename detail::get_callable_trait<F>::result_type
                  >::value,
                  "response handlers are not allowed to have a return "
                  "type other than void");
    detail::type_checker<Output, F>::check();
    self_->add_awaited_response_handler(mid_, behavior{std::move(f),
                                                       std::move(ef)});
  }

  template <class F>
  void then_impl(F& f) const {
    static_assert(std::is_same<
                    void,
                    typename detail::get_callable_trait<F>::result_type
                  >::value,
                  "response handlers are not allowed to have a return "
                  "type other than void");
    detail::type_checker<Output, F>::check();
    self_->add_multiplexed_response_handler(mid_, behavior{std::move(f)});
  }

  template <class F, class OnError>
  void then_impl(F& f, OnError& ef) const {
    static_assert(std::is_same<
                    void,
                    typename detail::get_callable_trait<F>::result_type
                  >::value,
                  "response handlers are not allowed to have a return "
                  "type other than void");
    detail::type_checker<Output, F>::check();
    self_->add_multiplexed_response_handler(mid_, behavior{std::move(f),
                                                           std::move(ef)});
  }

  message_id mid_;
  Self* self_;
};

/******************************************************************************
 *                                  blocking                                  *
 ******************************************************************************/
template <class Self, class Output>
class response_handle<Self, Output, true> {
public:
  response_handle() = delete;
  response_handle(const response_handle&) = default;
  response_handle& operator=(const response_handle&) = default;

  response_handle(message_id mid, Self* self) : mid_(mid), self_(self) {
    // nop
  }

  using error_handler = std::function<void (error&)>;

  template <class F, class OnError,
            class E = detail::is_handler_for_ef<OnError, error>>
  detail::is_callable_t<F> receive(F f, OnError ef) {
    static_assert(std::is_same<
                    void,
                    typename detail::get_callable_trait<F>::result_type
                  >::value,
                  "response handlers are not allowed to have a return "
                  "type other than void");
    detail::type_checker<Output, F>::check();
    typename Self::accept_one_cond rc;
    self_->varargs_receive(rc, mid_, std::move(f), std::move(ef));
  }

  template <class OnError, class F,
            class E = detail::is_callable_t<F>>
  detail::is_handler_for_ef<OnError, error> receive(OnError ef, F f) {
    receive(std::move(f), std::move(ef));
  }

  template <class OnError, class F,
            class E = detail::is_handler_for_ef<OnError, error>>
  void receive(OnError ef, catch_all<F> ca) {
    typename Self::accept_one_cond rc;
    self_->varargs_receive(rc, mid_, std::move(ef), std::move(ca));
  }

private:
  message_id mid_;
  Self* self_;
};

} // namespace caf

<commit_msg>Add getter for self pointer<commit_after>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright 2011-2018 Dominik Charousset                                     *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#pragma once

#include <type_traits>

#include "caf/sec.hpp"
#include "caf/catch_all.hpp"
#include "caf/message_id.hpp"
#include "caf/typed_behavior.hpp"
#include "caf/system_messages.hpp"

#include "caf/detail/type_list.hpp"
#include "caf/detail/typed_actor_util.hpp"

namespace caf {

/// This helper class identifies an expected response message
/// and enables `request(...).then(...)`.
template <class Self, class Output, bool IsBlocking>
class response_handle;

/******************************************************************************
 *                                 nonblocking                                *
 ******************************************************************************/
template <class Self, class Output>
class response_handle<Self, Output, false> {
public:
  response_handle() = delete;
  response_handle(const response_handle&) = default;
  response_handle& operator=(const response_handle&) = default;

  response_handle(message_id mid, Self* self) : mid_(mid), self_(self) {
    // nop
  }

  template <class F, class E = detail::is_callable_t<F>>
  void await(F f) const {
    await_impl(f);
  }

  template <class F, class OnError,
            class E1 = detail::is_callable_t<F>,
            class E2 = detail::is_handler_for_ef<OnError, error>>
  void await(F f, OnError e) const {
    await_impl(f, e);
  }

  template <class F, class E = detail::is_callable_t<F>>
  void then(F f) const {
    then_impl(f);
  }

  template <class F, class OnError,
            class E1 = detail::is_callable_t<F>,
            class E2 = detail::is_handler_for_ef<OnError, error>>
  void then(F f, OnError e) const {
    then_impl(f, e);
  }

  Self* self() {
    return self_;
  }

private:
  template <class F>
  void await_impl(F& f) const {
    static_assert(std::is_same<
                    void,
                    typename detail::get_callable_trait<F>::result_type
                  >::value,
                  "response handlers are not allowed to have a return "
                  "type other than void");
    detail::type_checker<Output, F>::check();
    self_->add_awaited_response_handler(mid_, message_handler{std::move(f)});
  }

  template <class F, class OnError>
  void await_impl(F& f, OnError& ef) const {
    static_assert(std::is_same<
                    void,
                    typename detail::get_callable_trait<F>::result_type
                  >::value,
                  "response handlers are not allowed to have a return "
                  "type other than void");
    detail::type_checker<Output, F>::check();
    self_->add_awaited_response_handler(mid_, behavior{std::move(f),
                                                       std::move(ef)});
  }

  template <class F>
  void then_impl(F& f) const {
    static_assert(std::is_same<
                    void,
                    typename detail::get_callable_trait<F>::result_type
                  >::value,
                  "response handlers are not allowed to have a return "
                  "type other than void");
    detail::type_checker<Output, F>::check();
    self_->add_multiplexed_response_handler(mid_, behavior{std::move(f)});
  }

  template <class F, class OnError>
  void then_impl(F& f, OnError& ef) const {
    static_assert(std::is_same<
                    void,
                    typename detail::get_callable_trait<F>::result_type
                  >::value,
                  "response handlers are not allowed to have a return "
                  "type other than void");
    detail::type_checker<Output, F>::check();
    self_->add_multiplexed_response_handler(mid_, behavior{std::move(f),
                                                           std::move(ef)});
  }

  message_id mid_;
  Self* self_;
};

/******************************************************************************
 *                                  blocking                                  *
 ******************************************************************************/
template <class Self, class Output>
class response_handle<Self, Output, true> {
public:
  response_handle() = delete;
  response_handle(const response_handle&) = default;
  response_handle& operator=(const response_handle&) = default;

  response_handle(message_id mid, Self* self) : mid_(mid), self_(self) {
    // nop
  }

  using error_handler = std::function<void (error&)>;

  template <class F, class OnError,
            class E = detail::is_handler_for_ef<OnError, error>>
  detail::is_callable_t<F> receive(F f, OnError ef) {
    static_assert(std::is_same<
                    void,
                    typename detail::get_callable_trait<F>::result_type
                  >::value,
                  "response handlers are not allowed to have a return "
                  "type other than void");
    detail::type_checker<Output, F>::check();
    typename Self::accept_one_cond rc;
    self_->varargs_receive(rc, mid_, std::move(f), std::move(ef));
  }

  template <class OnError, class F,
            class E = detail::is_callable_t<F>>
  detail::is_handler_for_ef<OnError, error> receive(OnError ef, F f) {
    receive(std::move(f), std::move(ef));
  }

  template <class OnError, class F,
            class E = detail::is_handler_for_ef<OnError, error>>
  void receive(OnError ef, catch_all<F> ca) {
    typename Self::accept_one_cond rc;
    self_->varargs_receive(rc, mid_, std::move(ef), std::move(ca));
  }

  Self* self() {
    return self_;
  }

private:
  message_id mid_;
  Self* self_;
};

} // namespace caf

<|endoftext|>