<commit_before>#include "Zenderer/Network/Socket.hpp"

using namespace zen;
using util::CLog;
using util::LogMode;
using net::CSocket;

bool CSocket::s_init = false;

bool CSocket::InitializeLibrary()
{
    if(s_init) return true;

#ifdef _WIN32
    WSADATA Data;
    if(WSAStartup(MAKEWORD(2, 0), &Data) != 0)
    {
        return (s_init = false);
    }
#endif  // _WIN32
    return (s_init = true);
}

bool CSocket::Init(const string_t& host, const string_t& port)
{
    addrinfo hints;
    addrinfo* tmp;

    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_DGRAM;
    hints.ai_flags = AI_PASSIVE ? host.empty() : 0;

    if(m_Type == SocketType::TCP)
        hints.ai_socktype = SOCK_STREAM;

    else if(m_Type == SocketType::RAW)
        hints.ai_socktype = SOCK_RAW;

    if(getaddrinfo(host.empty() ? nullptr : host.c_str(),
                   port.empty() ? nullptr : port.c_str(),
                   &hints, &tmp) != 0)
    {
        return false;
    }

    addrinfo* result = tmp;
    for( ; result != nullptr; result = result->ai_next)
    {
        if((m_socket = socket(result->ai_family,
                              result->ai_socktype,
                              result->ai_protocol)) == -1)
        {
            continue;
        }

        this->SetSocketOption(SOL_SOCKET, SO_REUSEADDR, true);

        if(bind(m_socket, result->ai_addr, result->ai_addrlen) == -1)
        {
            this->Destroy();
            continue;
        }
    }

    freeaddrinfo(tmp);
    return m_socket != -1;
}

bool CSocket::Destroy()
{
    if(m_socket == -1) return false;
#ifdef _WIN32
    closesocket(m_socket);
#else
    close(m_socket);
#endif // _WIN32
    return (m_socket = -1);
}

string_t CSocket::RecvFrom(const size_t size, string_t& address,
                           string_t& port)
{
    if(m_socket <= 0) return "";

    address = "";
    sockaddr_in addr;
    int addrlen = sizeof(addr);
    char* buffer = new char[size];

    int bytes = recvfrom(m_socket, buffer, size, 0,
                         (sockaddr*)&addr, &addrlen);
    if(bytes == -1)
    {
        delete[] buffer;
        return string_t("");
    }

    address = CSocket::GetAddress(addr);
    std::stringstream ss;
    ss << ntohs(addr.sin_port);
    port = ss.str();

    string_t ret(buffer, bytes);
    delete[] buffer;

#ifdef ZEN_DEBUG_BUILD
    CLog& Log = CLog::GetEngineLog();
    Log << Log.SetMode(LogMode::ZEN_DEBUG) << Log.SetSystem("Network")
        << "Received '" << ret << "' from " << address << ':'
        << port << '.' << CLog::endl;
#endif  // ZEN_DEBUG_BUILD

    return ret;
}

int CSocket::SendTo(const std::string& addr, const std::string& port,
                    const std::string& data)
{
    if(m_socket < 0 || m_Type == SocketType::TCP) return -1;

#ifdef ZEN_DEBUG_BUILD
    CLog& Log = CLog::GetEngineLog();
    Log << Log.SetMode(LogMode::ZEN_DEBUG) << Log.SetSystem("Network")
        << "Sending '" << data << "' to " << addr << ':' << port
        << '.' << CLog::endl;
#endif  // ZEN_DEBUG_BUILD

    sockaddr_in sock;
    sock.sin_family = AF_INET;
    sock.sin_port   = htons(std::stoi(port));
    sock.sin_addr   = this->GetAddress(addr);
    return sendto(m_socket, data.c_str(), data.size(), 0,
                 (sockaddr*)&sock, sizeof(sock));
}

int CSocket::SendBroadcast(const string_t& message, const string_t& port)
{
    if(m_Type != SocketType::UDP)
    {
        m_Log << m_Log.SetSystem("Network")
              << m_Log.SetMode(LogMode::ZEN_ERROR)
              << "Broadcasting is only for UDP packets." << CLog::endl;
        return -1;
    }

    this->SetSocketOption(SOL_SOCKET, SO_BROADCAST, true);
    int b = this->SendTo("255.255.255.255", port, message);
    this->SetSocketOption(SOL_SOCKET, SO_BROADCAST, false);
    return b;
}

bool CSocket::Ping()
{
    ZEN_ASSERTM(false, "not implemented");
    return false;
}

bool CSocket::SetSocketOption(const int type, const int option,
                              const bool flag)
{
    if(m_socket < 0) return false;
    char set = flag ? 1 : 0;
    return setsockopt(m_socket, type, option, &set, sizeof set) == 0;
}

bool CSocket::SetNonblocking(const bool flag)
{
    if(m_socket < 0) return false;

#ifdef _WIN32
    unsigned long set = flag ? 1 : 0;
    return ioctlsocket(m_socket, FIONBIO, &set) == 0;
#else
    int set = flag ? 1 : 0;
    return fcntl(m_socket, F_SETFL, O_NONBLOCK, &set) == 0;
#endif
}

int CSocket::GetError() const
{
#ifdef _WIN32
    return WSAGetLastError();
#else
    return errno;
#endif // _WIN32
}

string_t CSocket::GetAddress(sockaddr_in& addr)
{
    // We would like to support Windows XP and above.
#ifdef _WIN32
    return string_t(inet_ntoa(addr.sin_addr));
#else
    char ip[INET_ADDRSTRLEN] = {0};
    inet_ntop(AF_INET, &(addr.sin_addr), ip, INET_ADDRSTRLEN);
    return string_t(ip);
#endif // _WIN32
}

in_addr CSocket::GetAddress(const std::string& ip)
{
    in_addr s;

    // We would like to support Windows XP and above.
#ifdef _WIN32
    s.S_un.S_addr = inet_addr(ip.c_str());
#else
    inet_pton(AF_INET, ip.c_str(), &s);
#endif // _WIN32

    return s;
}

<commit_msg>Use zen::string_t in sockets.<commit_after>#include "Zenderer/Network/Socket.hpp"

using namespace zen;
using util::CLog;
using util::LogMode;
using net::CSocket;

bool CSocket::s_init = false;

bool CSocket::InitializeLibrary()
{
    if(s_init) return true;

#ifdef _WIN32
    WSADATA Data;
    if(WSAStartup(MAKEWORD(2, 0), &Data) != 0)
    {
        return (s_init = false);
    }
#endif  // _WIN32
    return (s_init = true);
}

bool CSocket::Init(const string_t& host, const string_t& port)
{
    addrinfo hints;
    addrinfo* tmp;

    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_DGRAM;
    hints.ai_flags = AI_PASSIVE ? host.empty() : 0;

    if(m_Type == SocketType::TCP)
        hints.ai_socktype = SOCK_STREAM;

    else if(m_Type == SocketType::RAW)
        hints.ai_socktype = SOCK_RAW;

    if(getaddrinfo(host.empty() ? nullptr : host.c_str(),
                   port.empty() ? nullptr : port.c_str(),
                   &hints, &tmp) != 0)
    {
        return false;
    }

    addrinfo* result = tmp;
    for( ; result != nullptr; result = result->ai_next)
    {
        if((m_socket = socket(result->ai_family,
                              result->ai_socktype,
                              result->ai_protocol)) == -1)
        {
            continue;
        }

        this->SetSocketOption(SOL_SOCKET, SO_REUSEADDR, true);

        if(bind(m_socket, result->ai_addr, result->ai_addrlen) == -1)
        {
            this->Destroy();
            continue;
        }
    }

    freeaddrinfo(tmp);
    return m_socket != -1;
}

bool CSocket::Destroy()
{
    if(m_socket == -1) return false;
#ifdef _WIN32
    closesocket(m_socket);
#else
    close(m_socket);
#endif // _WIN32
    return (m_socket = -1);
}

string_t CSocket::RecvFrom(const size_t size, string_t& address,
                           string_t& port)
{
    if(m_socket <= 0) return "";

    address = "";
    sockaddr_in addr;
    int addrlen = sizeof(addr);
    char* buffer = new char[size];

    int bytes = recvfrom(m_socket, buffer, size, 0,
                         (sockaddr*)&addr, &addrlen);
    if(bytes == -1)
    {
        delete[] buffer;
        return string_t("");
    }

    address = CSocket::GetAddress(addr);
    std::stringstream ss;
    ss << ntohs(addr.sin_port);
    port = ss.str();

    string_t ret(buffer, bytes);
    delete[] buffer;

#ifdef ZEN_DEBUG_BUILD
    CLog& Log = CLog::GetEngineLog();
    Log << Log.SetMode(LogMode::ZEN_DEBUG) << Log.SetSystem("Network")
        << "Received '" << ret << "' from " << address << ':'
        << port << '.' << CLog::endl;
#endif  // ZEN_DEBUG_BUILD

    return ret;
}

int CSocket::SendTo(const string_t& addr, const string_t& port,
                    const string_t& data)
{
    if(m_socket < 0 || m_Type == SocketType::TCP) return -1;

#ifdef ZEN_DEBUG_BUILD
    CLog& Log = CLog::GetEngineLog();
    Log << Log.SetMode(LogMode::ZEN_DEBUG) << Log.SetSystem("Network")
        << "Sending '" << data << "' to " << addr << ':' << port
        << '.' << CLog::endl;
#endif  // ZEN_DEBUG_BUILD

    sockaddr_in sock;
    sock.sin_family = AF_INET;
    sock.sin_port   = htons(std::stoi(port));
    sock.sin_addr   = this->GetAddress(addr);
    return sendto(m_socket, data.c_str(), data.size(), 0,
                 (sockaddr*)&sock, sizeof(sock));
}

int CSocket::SendBroadcast(const string_t& message, const string_t& port)
{
    if(m_Type != SocketType::UDP)
    {
        m_Log << m_Log.SetSystem("Network")
              << m_Log.SetMode(LogMode::ZEN_ERROR)
              << "Broadcasting is only for UDP packets." << CLog::endl;
        return -1;
    }

    this->SetSocketOption(SOL_SOCKET, SO_BROADCAST, true);
    int b = this->SendTo("255.255.255.255", port, message);
    this->SetSocketOption(SOL_SOCKET, SO_BROADCAST, false);
    return b;
}

bool CSocket::Ping()
{
    ZEN_ASSERTM(false, "not implemented");
    return false;
}

bool CSocket::SetSocketOption(const int type, const int option,
                              const bool flag)
{
    if(m_socket < 0) return false;
    char set = flag ? 1 : 0;
    return setsockopt(m_socket, type, option, &set, sizeof set) == 0;
}

bool CSocket::SetNonblocking(const bool flag)
{
    if(m_socket < 0) return false;

#ifdef _WIN32
    unsigned long set = flag ? 1 : 0;
    return ioctlsocket(m_socket, FIONBIO, &set) == 0;
#else
    int set = flag ? 1 : 0;
    return fcntl(m_socket, F_SETFL, O_NONBLOCK, &set) == 0;
#endif
}

int CSocket::GetError() const
{
#ifdef _WIN32
    return WSAGetLastError();
#else
    return errno;
#endif // _WIN32
}

string_t CSocket::GetAddress(sockaddr_in& addr)
{
    // We would like to support Windows XP and above.
#ifdef _WIN32
    return string_t(inet_ntoa(addr.sin_addr));
#else
    char ip[INET_ADDRSTRLEN] = {0};
    inet_ntop(AF_INET, &(addr.sin_addr), ip, INET_ADDRSTRLEN);
    return string_t(ip);
#endif // _WIN32
}

in_addr CSocket::GetAddress(const string_t& ip)
{
    in_addr s;

    // We would like to support Windows XP and above.
#ifdef _WIN32
    s.S_un.S_addr = inet_addr(ip.c_str());
#else
    inet_pton(AF_INET, ip.c_str(), &s);
#endif // _WIN32

    return s;
}

<|endoftext|>


<commit_before>#include <hayai/hayai.hpp>
#include <string>
#include <iostream>
#include <sstream>
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <uuid/uuid.h>

#include "include/factory/logging_interface.h"
#include "include/factory/http_interface.h"
#include "include/factory.h"

//----------------------------------------------------------------------------//
//--------------------------------Globals-------------------------------------//
//----------------------------------------------------------------------------//

char *POSTURL;
char *PUTURL;
char *GETURL;
char *DELETEURL;

HttpInterface *http;

//----------------------------------------------------------------------------//
//------------------------------Benchmarks------------------------------------//
//----------------------------------------------------------------------------//

BENCHMARK(HTTP, Get, 10, 100)
{

  //Clear the return string
  write_data.clear();

  //Send the request
  std::string success = http->get(GETURL, 5);
  if (!success.empty())
  {
    //We now have the full response
    logging->error("Get Request Failed");
  }
  else
  {
    logging->debug("Retrieved:");
    logging->debug(write_data);
  }

}

BENCHMARK(HTTP, Put, 10, 100)
{

  //Clear the return string
  write_data.clear();

  //Send the request
  std::string success = http->put(PUTURL, "123", 5);

}

BENCHMARK(HTTP, Post, 10, 100)
{

  //Clear the return string
  write_data.clear();

  //Send the request
  std::string success = http->post(POSTURL, "CLYMAN", 5);

}

BENCHMARK(HTTP, Delete, 10, 100)
{

  //Clear the return string
  write_data.clear();

  //Send the request
  bool std::string = http->del(DELETEURL, 5);

}

//----------------------------------------------------------------------------//
//------------------------------Main Method-----------------------------------//
//----------------------------------------------------------------------------//

int main()
{

  //Variables to store URL's
  std::string post = "http://httpbin.org/post";
  std::string put = "http://httpbin.org/put";
  std::string get = "http://httpbin.org/get";
  std::string del = "http://httpbin.org/delete";

  POSTURL = new char[post.length() + 1];
  PUTURL = new char[put.length() + 1];
  GETURL = new char[get.length() + 1];
  DELETEURL = new char[del.length() + 1];

  strcpy(POSTURL, post.c_str());
  strcpy(PUTURL, put.c_str());
  strcpy(GETURL, get.c_str());
  strcpy(DELETEURL, del.c_str());

ServiceComponentFactory factory;

//Read the Logging Configuration File
std::string initFileName = "test/log4cpp_test.properties";
logging = factory.get_logging_interface( initFileName );
//logging = new Logger(initFileName);

//Set up internal variables
logging->info("Internal Logging Intialized");

//Set up UUID Generator
http = factory.get_http_interface();
//uuid = new uuidAdmin;
logging->info("HTTP Outbound Interface Created");

//------------------------------Run Tests-------------------------------------//
//----------------------------------------------------------------------------//

hayai::ConsoleOutputter consoleOutputter;

hayai::Benchmarker::AddOutputter(consoleOutputter);
hayai::Benchmarker::RunAllTests();

//-------------------------Post-Test Teardown---------------------------------//
//----------------------------------------------------------------------------//

delete http;
delete logging;

return 0;

}
<commit_msg>Couchbase Updates to bring onto Universal Callback Interface<commit_after>#include <hayai/hayai.hpp>
#include <string>
#include <iostream>
#include <sstream>
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <uuid/uuid.h>

#include "include/factory/logging_interface.h"
#include "include/factory/http_interface.h"
#include "include/factory.h"

//----------------------------------------------------------------------------//
//--------------------------------Globals-------------------------------------//
//----------------------------------------------------------------------------//

char *POSTURL;
char *PUTURL;
char *GETURL;
char *DELETEURL;

HttpInterface *http;

//----------------------------------------------------------------------------//
//------------------------------Benchmarks------------------------------------//
//----------------------------------------------------------------------------//

BENCHMARK(HTTP, Get, 10, 100)
{

  //Clear the return string
  write_data.clear();

  //Send the request
  bool success = http->get(GETURL, 5);
  if (!success)
  {
    //We now have the full response
    logging->error("Get Request Failed");
  }
  else
  {
    logging->debug("Retrieved:");
    logging->debug(write_data);
  }

}

BENCHMARK(HTTP, Put, 10, 100)
{

  //Clear the return string
  write_data.clear();

  //Send the request
  bool success = http->put(PUTURL, "123", 5);

}

BENCHMARK(HTTP, Post, 10, 100)
{

  //Clear the return string
  write_data.clear();

  //Send the request
  bool success = http->post(POSTURL, "CLYMAN", 5);

}

BENCHMARK(HTTP, Delete, 10, 100)
{

  //Clear the return string
  write_data.clear();

  //Send the request
  bool success = http->del(DELETEURL, 5);

}

//----------------------------------------------------------------------------//
//------------------------------Main Method-----------------------------------//
//----------------------------------------------------------------------------//

int main()
{

  //Variables to store URL's
  std::string post = "http://httpbin.org/post";
  std::string put = "http://httpbin.org/put";
  std::string get = "http://httpbin.org/get";
  std::string del = "http://httpbin.org/delete";

  POSTURL = new char[post.length() + 1];
  PUTURL = new char[put.length() + 1];
  GETURL = new char[get.length() + 1];
  DELETEURL = new char[del.length() + 1];

  strcpy(POSTURL, post.c_str());
  strcpy(PUTURL, put.c_str());
  strcpy(GETURL, get.c_str());
  strcpy(DELETEURL, del.c_str());

ServiceComponentFactory factory;

//Read the Logging Configuration File
std::string initFileName = "test/log4cpp_test.properties";
logging = factory.get_logging_interface( initFileName );
//logging = new Logger(initFileName);

//Set up internal variables
logging->info("Internal Logging Intialized");

//Set up UUID Generator
http = factory.get_http_interface();
//uuid = new uuidAdmin;
logging->info("HTTP Outbound Interface Created");

//------------------------------Run Tests-------------------------------------//
//----------------------------------------------------------------------------//

hayai::ConsoleOutputter consoleOutputter;

hayai::Benchmarker::AddOutputter(consoleOutputter);
hayai::Benchmarker::RunAllTests();

//-------------------------Post-Test Teardown---------------------------------//
//----------------------------------------------------------------------------//

delete http;
delete logging;

return 0;

}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
 *
 * This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
 *
 * Use of this source code is governed by MIT license that can be found in the
 * LICENSE file in the root of the source tree. All contributing project authors
 * may be found in the AUTHORS file in the root of the source tree.
 */

#if defined(ENABLE_RTPPROXY)
#include "RtpSession.h"
#include "RtpSelector.h"
#include "Network/TcpServer.h"
namespace mediakit{

const string RtpSession::kStreamID = "stream_id";

void RtpSession::attachServer(const TcpServer &server) {
    _stream_id = const_cast<TcpServer &>(server)[kStreamID];
}

RtpSession::RtpSession(const Socket::Ptr &sock) : TcpSession(sock) {
    DebugP(this);
    socklen_t addr_len = sizeof(addr);
    getpeername(sock->rawFD(), &addr, &addr_len);
}
RtpSession::~RtpSession() {
    DebugP(this);
    if(_process){
        RtpSelector::Instance().delProcess(_stream_id,_process.get());
    }
}

void RtpSession::onRecv(const Buffer::Ptr &data) {
    try {
        RtpSplitter::input(data->data(), data->size());
    } catch (SockException &ex) {
        shutdown(ex);
    } catch (std::exception &ex) {
        shutdown(SockException(Err_other, ex.what()));
    }
}

void RtpSession::onError(const SockException &err) {
    WarnL << _stream_id << " " << err.what();
}

void RtpSession::onManager() {
    if(_process && !_process->alive()){
        shutdown(SockException(Err_timeout, "receive rtp timeout"));
    }

    if(!_process && _ticker.createdTime() > 10 * 1000){
        shutdown(SockException(Err_timeout, "illegal connection"));
    }
}

void RtpSession::onRtpPacket(const char *data, uint64_t len) {
    if (!_process) {
        uint32_t ssrc;
        if (!RtpSelector::getSSRC(data, len, ssrc)) {
            return;
        }
        if (_stream_id.empty()) {
            //未指定流id就使用ssrc为流id
            _stream_id = printSSRC(ssrc);
        }
        //tcp情况下，一个tcp链接只可能是一路流，不需要通过多个ssrc来区分，所以不需要频繁getProcess
        _process = RtpSelector::Instance().getProcess(_stream_id, true);
        _process->setListener(dynamic_pointer_cast<RtpSession>(shared_from_this()));
    }
    _process->inputRtp(getSock(), data, len, &addr);
    _ticker.resetTime();
}

bool RtpSession::close(MediaSource &sender, bool force) {
    //此回调在其他线程触发
    if(!_process || (!force && _process->totalReaderCount())){
        return false;
    }
    string err = StrPrinter << "close media:" << sender.getSchema() << "/" << sender.getVhost() << "/" << sender.getApp() << "/" << sender.getId() << " " << force;
    safeShutdown(SockException(Err_shutdown,err));
    return true;
}

int RtpSession::totalReaderCount(MediaSource &sender) {
    //此回调在其他线程触发
    return _process ? _process->totalReaderCount() : sender.totalReaderCount();
}

}//namespace mediakit
#endif//defined(ENABLE_RTPPROXY)<commit_msg>tcp情况下，rtp长度不得超过2K，防止发送端存在缓存覆盖的bug<commit_after>/*
 * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
 *
 * This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
 *
 * Use of this source code is governed by MIT license that can be found in the
 * LICENSE file in the root of the source tree. All contributing project authors
 * may be found in the AUTHORS file in the root of the source tree.
 */

#if defined(ENABLE_RTPPROXY)
#include "RtpSession.h"
#include "RtpSelector.h"
#include "Network/TcpServer.h"
namespace mediakit{

const string RtpSession::kStreamID = "stream_id";

void RtpSession::attachServer(const TcpServer &server) {
    _stream_id = const_cast<TcpServer &>(server)[kStreamID];
}

RtpSession::RtpSession(const Socket::Ptr &sock) : TcpSession(sock) {
    DebugP(this);
    socklen_t addr_len = sizeof(addr);
    getpeername(sock->rawFD(), &addr, &addr_len);
}
RtpSession::~RtpSession() {
    DebugP(this);
    if(_process){
        RtpSelector::Instance().delProcess(_stream_id,_process.get());
    }
}

void RtpSession::onRecv(const Buffer::Ptr &data) {
    try {
        RtpSplitter::input(data->data(), data->size());
    } catch (SockException &ex) {
        shutdown(ex);
    } catch (std::exception &ex) {
        shutdown(SockException(Err_other, ex.what()));
    }
}

void RtpSession::onError(const SockException &err) {
    WarnL << _stream_id << " " << err.what();
}

void RtpSession::onManager() {
    if(_process && !_process->alive()){
        shutdown(SockException(Err_timeout, "receive rtp timeout"));
    }

    if(!_process && _ticker.createdTime() > 10 * 1000){
        shutdown(SockException(Err_timeout, "illegal connection"));
    }
}

void RtpSession::onRtpPacket(const char *data, uint64_t len) {
    if (len > 1024 * 2) {
        throw SockException(Err_shutdown, "rtp包长度异常，发送端可能缓存溢出并覆盖");
    }
    if (!_process) {
        uint32_t ssrc;
        if (!RtpSelector::getSSRC(data, len, ssrc)) {
            return;
        }
        if (_stream_id.empty()) {
            //未指定流id就使用ssrc为流id
            _stream_id = printSSRC(ssrc);
        }
        //tcp情况下，一个tcp链接只可能是一路流，不需要通过多个ssrc来区分，所以不需要频繁getProcess
        _process = RtpSelector::Instance().getProcess(_stream_id, true);
        _process->setListener(dynamic_pointer_cast<RtpSession>(shared_from_this()));
    }
    _process->inputRtp(getSock(), data, len, &addr);
    _ticker.resetTime();
}

bool RtpSession::close(MediaSource &sender, bool force) {
    //此回调在其他线程触发
    if(!_process || (!force && _process->totalReaderCount())){
        return false;
    }
    string err = StrPrinter << "close media:" << sender.getSchema() << "/" << sender.getVhost() << "/" << sender.getApp() << "/" << sender.getId() << " " << force;
    safeShutdown(SockException(Err_shutdown,err));
    return true;
}

int RtpSession::totalReaderCount(MediaSource &sender) {
    //此回调在其他线程触发
    return _process ? _process->totalReaderCount() : sender.totalReaderCount();
}

}//namespace mediakit
#endif//defined(ENABLE_RTPPROXY)<|endoftext|>


<commit_before>#ifndef SIMPLEHASHCACHE_HH
#define SIMPLEHASHCACHE_HH

#define HASH_SIZE_MULTIPLIER 1.3

template <typename T>
class SimpleHashCache {
public:
  SimpleHashCache(void);
  inline bool insert(int key, T item, T *removed);
  inline bool find(int key, T *result);
  void set_max_items(int max);
  int get_num_items(void) { return num_items; }
  bool remove_last_item(T *removed);

private:
  void rehash(int new_max);
  inline int get_hash_index(int key) { return (key%hash_table_size); }

  class StoreType {
  public:
    T value;
    int key;
  };
  std::vector< StoreType > *hash_table;

  int hash_table_size;
  int num_items;
};

template<typename T>
SimpleHashCache<T>::SimpleHashCache(void)
{
  hash_table = NULL;
  hash_table_size = num_items = 0;
}

template<typename T>
void
SimpleHashCache<T>::rehash(int new_max)
{
  std::vector< StoreType > *new_hash_table = new std::vector< StoreType >;
  int new_size = (int)(HASH_SIZE_MULTIPLIER*new_max);
  new_hash_table->resize(new_size);
  for (int i = 0; i < new_size; i++)
    (*new_hash_table)[i].key = -1;
  if (hash_table != NULL)
  {
    // Copy at most new_max items
    // FIXME: Missing! We just delete the old hash.
    delete hash_table;
  }
  hash_table = new_hash_table;
  hash_table_size = new_size;
  num_items = 0;
}

// Returns true if an item is removed, in which case the removed item is
// stored to variable *removed (if it is != NULL).
template<typename T>
bool
SimpleHashCache<T>::insert(int key, T item, T *removed)
{
  int index = get_hash_index(key);
  bool rm = false;

  if ((*hash_table)[index].key != -1)
  {
    // Remove the item
    if (removed != NULL)
      *removed = (*hash_table)[index].value;
    rm = true;
  }
  else
    num_items++;
  (*hash_table)[index].value = item;
  (*hash_table)[index].key = key;
  return rm;
}

template<typename T>
bool
SimpleHashCache<T>::remove_last_item(T *removed)
{
  for (int i = 0; i < hash_table_size; i++)
  {
    if ((*hash_table)[i].key != -1)
    {
      if (removed != NULL)
        *removed = (*hash_table)[i].value;
      (*hash_table)[i].key = -1;
      num_items--;
      return true;
    }
  }
  return false;
}

template<typename T>
bool
SimpleHashCache<T>::find(int key, T *result)
{
  int index = get_hash_index(key);
  if ((*hash_table)[index].key != key)
      return false;

  *result = (*hash_table)[index].value;
  return true;
}

template<typename T>
void
SimpleHashCache<T>::set_max_items(int max)
{
  rehash(max);
}

#endif // SIMPLEHASHCACHE_HH
<commit_msg>get_hash_index() throws an exception instead of FPE signal if the hash table is empty.<commit_after>#ifndef SIMPLEHASHCACHE_HH
#define SIMPLEHASHCACHE_HH

#include <stdexcept>

#define HASH_SIZE_MULTIPLIER 1.3

template<typename T>
class SimpleHashCache
{
public:
	SimpleHashCache();
	inline bool insert(int key, T item, T *removed);
	inline bool find(int key, T *result);
	void set_max_items(int max);
	int get_num_items(void)
	{
		return num_items;
	}
	bool remove_last_item(T *removed);

private:
	void rehash(int new_max);
	int get_hash_index(int key);

	class StoreType
	{
	public:
		T value;
		int key;
	};
	std::vector<StoreType> hash_table;

	int num_items;
};

template<typename T>
SimpleHashCache<T>::SimpleHashCache()
{
	num_items = 0;
}

template<typename T>
void SimpleHashCache<T>::rehash(int new_max)
{
	int new_size = (int) (HASH_SIZE_MULTIPLIER * new_max);
	hash_table.resize(new_size);
	for (int i = 0; i < new_size; i++)
		hash_table[i].key = -1;
	num_items = 0;
}

template<typename T>
inline int SimpleHashCache<T>::get_hash_index(int key)
{
	if (hash_table.empty())
		throw std::runtime_error("SimpleHashCache::get_hash_index");
	return key % hash_table.size();
}

// Returns true if an item is removed, in which case the removed item is
// stored to variable *removed (if it is != NULL).
template<typename T>
bool SimpleHashCache<T>::insert(int key, T item, T *removed)
{
	int index = get_hash_index(key);
	bool rm = false;

	if (hash_table[index].key != -1) {
		// Remove the item
		if (removed != NULL)
			*removed = hash_table[index].value;
		rm = true;
	}
	else
		num_items++;
	hash_table[index].value = item;
	hash_table[index].key = key;
	return rm;
}

template<typename T>
bool SimpleHashCache<T>::remove_last_item(T *removed)
{
	for (int i = 0; i < hash_table.size(); i++) {
		if (hash_table[i].key != -1) {
			if (removed != NULL)
				*removed = hash_table[i].value;
			hash_table[i].key = -1;
			num_items--;
			return true;
		}
	}
	return false;
}

template<typename T>
bool SimpleHashCache<T>::find(int key, T *result)
{
	int index = get_hash_index(key);
	if (hash_table[index].key != key)
		return false;

	*result = hash_table[index].value;
	return true;
}

template<typename T>
void SimpleHashCache<T>::set_max_items(int max)
{
	rehash(max);
}

#endif // SIMPLEHASHCACHE_HH
<|endoftext|>


<commit_before>// =============================================================================
// Description: Provides an interface for the robot's arm
// Author: FRC Team 3512, Spartatroniks
// =============================================================================

#include "Arm.hpp"
#include "../MotionProfile/TrapezoidProfile.hpp"
#include "../WPILib/PIDController.hpp"

Arm::Arm() {
    m_leftArmPID = std::make_shared<PIDController>(0.f, 0.f, 0.f, 0.f, 0.f,
                                                   &m_leftArmActuator,
                                                   &m_leftArmActuator);
    m_leftArmProfile = std::make_shared<TrapezoidProfile>(m_leftArmPID,
                                                          0.0, 0.0);

    m_rightArmPID = std::make_shared<PIDController>(0.f, 0.f, 0.f, 0.f, 0.f,
                                                    &m_rightArmActuator,
                                                    &m_rightArmActuator);
    m_rightArmProfile = std::make_shared<TrapezoidProfile>(m_rightArmPID,
                                                           0.0, 0.0);

    m_leftArmHeightProfile = std::make_shared<TrapezoidProfile>(
        m_leftArmPID, 0.0, 0.0);

    m_rightArmHeightProfile = std::make_shared<TrapezoidProfile>(
        m_rightArmPID, 0.0, 0.0)
}

void Arm::SetManualArmHeight(double height) {
    m_leftArmActuator.Set(height);
}

void Arm::SetManualCarriagePosition(double position) {
    m_carriagePositionMotor.Set(position);
}

void Arm::SetPIDArmHeight(double height) {
}

void Arm::ReloadPID() {
}

void Arm::ResetEncoders() {
}

void Arm::UpdateState() {
}
<commit_msg>Added semicolon to Arm<commit_after>// =============================================================================
// Description: Provides an interface for the robot's arm
// Author: FRC Team 3512, Spartatroniks
// =============================================================================

#include "Arm.hpp"
#include "../MotionProfile/TrapezoidProfile.hpp"
#include "../WPILib/PIDController.hpp"

Arm::Arm() {
    m_leftArmPID = std::make_shared<PIDController>(0.f, 0.f, 0.f, 0.f, 0.f,
                                                   &m_leftArmActuator,
                                                   &m_leftArmActuator);
    m_leftArmProfile = std::make_shared<TrapezoidProfile>(m_leftArmPID,
                                                          0.0, 0.0);

    m_rightArmPID = std::make_shared<PIDController>(0.f, 0.f, 0.f, 0.f, 0.f,
                                                    &m_rightArmActuator,
                                                    &m_rightArmActuator);
    m_rightArmProfile = std::make_shared<TrapezoidProfile>(m_rightArmPID,
                                                           0.0, 0.0);

    m_leftArmHeightProfile = std::make_shared<TrapezoidProfile>(
        m_leftArmPID, 0.0, 0.0);

    m_rightArmHeightProfile = std::make_shared<TrapezoidProfile>(
        m_rightArmPID, 0.0, 0.0);
}

void Arm::SetManualArmHeight(double height) {
    m_leftArmActuator.Set(height);
}

void Arm::SetManualCarriagePosition(double position) {
    m_carriagePositionMotor.Set(position);
}

void Arm::SetPIDArmHeight(double height) {
}

void Arm::ReloadPID() {
}

void Arm::ResetEncoders() {
}

void Arm::UpdateState() {
}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "AnnEngine.hpp"
#include "AnnLogger.hpp"
using namespace Annwvyn;

AnnEngine* AnnEngine::singleton(NULL);
std::shared_ptr<AnnConsole> AnnEngine::onScreenConsole(nullptr);

AnnEngine* AnnEngine::Instance()
{
	return singleton;
}

std::string AnnEngine::getAnnwvynVersion()
{
	std::stringstream version;
	version << ANN_MAJOR << "." << ANN_MINOR << "." << ANN_PATCH;
	if (ANN_EXPERIMENTAL)
		version << "-experimental";
	return version.str();
}

void AnnEngine::startGameplayLoop()
{
	while (refresh());
}

AnnEngine::AnnEngine(const char title[], std::string hmdCommand) :
	player(nullptr),
	audioEngine(nullptr),
	eventManager(nullptr),
	levelManager(nullptr),
	filesystemManager(nullptr),
	resourceManager(nullptr),
	gameObjectManager(nullptr),
	sceneryManager(nullptr),
	renderer(nullptr),
	povNode(nullptr),
	updateTime(-1),
	canAccessSubSystems(true)
{

	if (singleton)
	{
		log("Can't create 2 instances of the engine!");
		exit(ANN_ERR_MEMORY);
	}

	std::cerr << "HMD selection from command line routine retuned : " << hmdCommand << std::endl;

	//Launching initialisation routines :
	if (hmdCommand == "OgreOculusRender"
		|| hmdCommand == "OgreDefaultRender")
	{
		renderer = std::make_shared<OgreOculusRender>(title);
	}
	///else if vive
	else if (hmdCommand == "OgreOpenVRRender")
	{
		/*MessageBox(NULL,
				   L"The Vive rendering is not implemented yet.\n"
				   L"Sorry for that. ^^\"",
				   L"Error: Vive not implemented. Yet ;-)",
				   MB_ICONERROR);
		exit(ANN_ERR_CANTHMD);*/
		renderer = std::make_shared<OgreOpenVRRender>(title);
	}
	///else if osvr
	///else if ...
	else
	{
		MessageBox(NULL,
				   L"This program can be used with multiple VR solution.\n"
				   L"The executable should be launched from the intended launcher.\n"
				   L"If you're trying to launch it by hand, please check if your command line parameter is correct!\n\n"
				   L"Available command line parameter : \n\t-oculus\n"
				   L"\t-vive\n",
				   L"Error: Cannot understand what HMD you want to use!",
				   MB_ICONERROR);
		exit(ANN_ERR_CANTHMD);
	}

	renderer->initOgreRoot("Annwvyn.log");

	srand(time(nullptr));
	singleton = this;

	player = std::make_shared< AnnPlayer>();
	renderer->initVrHmd();
	renderer->initPipeline();
	SceneManager = renderer->getSceneManager();

	renderer->showDebug(OgreVRRender::DebugMode::MONOSCOPIC);

	log("Setup Annwvyn's subsystems");

	//Element on this list will be updated in order by the engine each frame
	SubSystemList.push_back(levelManager = std::make_shared<AnnLevelManager>());
	SubSystemList.push_back(gameObjectManager = std::make_shared<AnnGameObjectManager>());

	//Physics engine needs to be declared before the event manager. But we want the physics engine to be updated after the event manager.

	/*The wanted order is
	- event happens (player input, timers...)
	- physics is ticked (stuff move)
	- audio is synced (sonds comes form where they should)
	- then the game can redraw*/

	physicsEngine = std::make_shared<AnnPhysicsEngine>(getSceneManager()->getRootSceneNode(), player, gameObjectManager->Objects, gameObjectManager->Triggers);
	SubSystemList.push_back(eventManager = std::make_shared< AnnEventManager>(renderer->getWindow()));
	SubSystemList.push_back(physicsEngine);
	SubSystemList.push_back(audioEngine = std::make_shared< AnnAudioEngine>());

	//These could be anywere
	SubSystemList.push_back(filesystemManager = std::make_shared<AnnFilesystemManager>(title));
	SubSystemList.push_back(resourceManager = std::make_shared<AnnResourceManager>());
	SubSystemList.push_back(sceneryManager = std::make_shared<AnnSceneryManager>(renderer));

	renderer->initClientHmdRendering();
	povNode = renderer->getCameraInformationNode();
	povNode->setPosition(player->getPosition() +
		AnnVect3(0.0f, player->getEyesHeight(), 0.0f));

	//This subsystem need the povNode object to be initialized. And the Resource manager because it wants a font file and an image background
	SubSystemList.push_back(onScreenConsole = std::make_shared<AnnConsole>());

	log("===================================================", false);
	log("Annwvyn Game Engine - Step into the Other World    ", false);
	log("Free/Libre Game Engine designed for Virtual Reality", false);
	log("Version : " + getAnnwvynVersion(), false);
	log("===================================================", false);
}

AnnEngine::~AnnEngine()
{
	//Some cute log messsages
	log("Game engine stopped. Subsystem are shutting down...");
	log("Good luck with the real world now! :3");
}

//All theses getter are for encapsulation purpose. Calling them directly would make verry long lines of code. Note that there's a whole bunch of macro in AnnEngine.hpp to help with that
std::shared_ptr<AnnEventManager> AnnEngine::getEventManager()
{
	return eventManager;
}

std::shared_ptr<AnnResourceManager> AnnEngine::getResourceManager()
{
	return resourceManager;
}

std::shared_ptr<AnnGameObjectManager> AnnEngine::getGameObjectManager()
{
	return gameObjectManager;
}

std::shared_ptr<AnnSceneryManager> AnnEngine::getSceneryManager()
{
	return sceneryManager;
}

std::shared_ptr<OgreVRRender> AnnEngine::getVRRenderer()
{
	return renderer;
}

std::shared_ptr<AnnLevelManager> AnnEngine::getLevelManager()
{
	return levelManager;
}

std::shared_ptr<AnnPlayer> AnnEngine::getPlayer()
{
	return player;
}

std::shared_ptr<AnnFilesystemManager> AnnEngine::getFileSystemManager()
{
	return filesystemManager;
}

std::shared_ptr<AnnAudioEngine> AnnEngine::getAudioEngine()
{
	return audioEngine;
}

std::shared_ptr<AnnPhysicsEngine> AnnEngine::getPhysicsEngine()
{
	return physicsEngine;
}

//This is static, but actually needs Ogre to be running. So be carefull
void AnnEngine::log(std::string message, bool flag)
{
	Ogre::String messageForLog;

	if (flag)
	{
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY);
		messageForLog += "Annwvyn - ";
	}
	else
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_INTENSITY);

	messageForLog += message;
	Ogre::LogManager::getSingleton().logMessage(messageForLog);
	if (onScreenConsole != nullptr)
		onScreenConsole->append(message);

	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_INTENSITY);
}

//Don't ask me why this is not part of the Physics engine. Actually it just calls something on the physics engine. Will be probably deleted in the future.
void AnnEngine::initPlayerPhysics()
{
	physicsEngine->initPlayerPhysics(povNode);
}

//Need to be redone.
bool AnnEngine::requestStop()
{
	//pres ESC to quit. Stupid but efficient. I like that.
	if (isKeyDown(OIS::KC_ESCAPE))
		return true;
	//If the user quit the App from the Oculus Home
	if (renderer->shouldQuit())
		return true;
	return false;
}

//This is the most important function of the whole project. It's the heartbeat of the game or app using this engine.
bool AnnEngine::refresh()
{
	//Get the rendering delta time (should be roughly equals to 1/desiredFramerate in seconds)
	updateTime = renderer->getUpdateTime();
	player->engineUpdate(getFrameTime());

	for (auto SubSystem : SubSystemList)
		if (!SubSystem->needUpdate()) continue; //If doen't need update, swith to the next
		else SubSystem->update();				//The "else" keyword is used to not put curly braces, by lazyness and by code style.

	//Update camera from player
	syncPov();

	//Update VR form real world
	renderer->updateTracking();

	//Update view
	renderer->renderAndSubmitFrame();

	//Don't laugh
	return !requestStop();
}

//This just move a node where the other node is. Yes I know about parenting. I had reasons to do it that way, but I forgot.
inline void AnnEngine::syncPov()
{
	povNode->setPosition(player->getPosition());
	povNode->setOrientation(player->getOrientation().toQuaternion());
}

//Bad. Don't use. Register an event listener and use the KeyEvent callback.
inline bool AnnEngine::isKeyDown(OIS::KeyCode key)
{
	if (!eventManager) return false;
	return eventManager->Keyboard->isKeyDown(key);
}

Ogre::SceneNode* AnnEngine::getCamera()
{
	return povNode;
}

Ogre::SceneManager* AnnEngine::getSceneManager()
{
	return SceneManager;
}

unsigned long AnnEngine::getTimeFromStartUp()
{
	return renderer->getTimer()->getMilliseconds();
}

double AnnEngine::getTimeFromStartupSeconds()
{
	return static_cast<double>(getTimeFromStartUp()) / 1000.0;
}

//the delta time of the last frame, not the current one
double AnnEngine::getFrameTime()
{
	return updateTime;
}

//Raw position and orientaiton of the head in world space. This is usefull if you want to mess around with weird stuff. This has been bodged when I integrated a LEAP motion in that mess.
OgrePose AnnEngine::getHmdPose()
{
	if (renderer)
		return renderer->returnPose;
	return OgrePose();
}

//Because Windows and the Win32 platform sucks.
void AnnEngine::openConsole()
{
#ifdef _WIN32

	//Allocate a console for this app
	if (AllocConsole())
	{
		//put stdout on this console;
#pragma warning(disable:4996) //Okay, so for some reason, freopen is "bad" because potentially dangerous. However, since I'm passing static strings here, unless you go hack the DLL, I don't know what harm you can do.
		freopen("CONOUT$", "w", stdout);
#pragma warning(default:4996)
	}

	//Redirect cerr to cout
	std::cerr.rdbuf(std::cout.rdbuf());

	SetConsoleTitle(L"Annwyn Debug Console");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY);

#endif
}

//Well, I may make the pointer to the onScreenConsole more accessible.
void AnnEngine::toogleOnScreenConsole()
{
	if (onScreenConsole) onScreenConsole->toogle();
}

bool AnnEngine::appVisibleInHMD()
{
	if (renderer->isVisibleInHmd() == true) // why "== true" ? Because at some point it was returning an ovrBool, wich is the boolean type of the oculus SDK that doesn't cast correctly to a C++ bool. YES. I DON'T KNOW HOW THEY MANAGED TO FFFF TAHT UP.
		return true;
	return false;
}
<commit_msg>correct error in command line message<commit_after>#include "stdafx.h"
#include "AnnEngine.hpp"
#include "AnnLogger.hpp"
using namespace Annwvyn;

AnnEngine* AnnEngine::singleton(NULL);
std::shared_ptr<AnnConsole> AnnEngine::onScreenConsole(nullptr);

AnnEngine* AnnEngine::Instance()
{
	return singleton;
}

std::string AnnEngine::getAnnwvynVersion()
{
	std::stringstream version;
	version << ANN_MAJOR << "." << ANN_MINOR << "." << ANN_PATCH;
	if (ANN_EXPERIMENTAL)
		version << "-experimental";
	return version.str();
}

void AnnEngine::startGameplayLoop()
{
	while (refresh());
}

AnnEngine::AnnEngine(const char title[], std::string hmdCommand) :
	player(nullptr),
	audioEngine(nullptr),
	eventManager(nullptr),
	levelManager(nullptr),
	filesystemManager(nullptr),
	resourceManager(nullptr),
	gameObjectManager(nullptr),
	sceneryManager(nullptr),
	renderer(nullptr),
	povNode(nullptr),
	updateTime(-1),
	canAccessSubSystems(true)
{

	if (singleton)
	{
		log("Can't create 2 instances of the engine!");
		exit(ANN_ERR_MEMORY);
	}

	std::cerr << "HMD selection from command line routine retuned : " << hmdCommand << std::endl;

	//Launching initialisation routines :
	if (hmdCommand == "OgreOculusRender"
		|| hmdCommand == "OgreDefaultRender")
	{
		renderer = std::make_shared<OgreOculusRender>(title);
	}
	///else if vive
	else if (hmdCommand == "OgreOpenVRRender")
	{
		/*MessageBox(NULL,
				   L"The Vive rendering is not implemented yet.\n"
				   L"Sorry for that. ^^\"",
				   L"Error: Vive not implemented. Yet ;-)",
				   MB_ICONERROR);
		exit(ANN_ERR_CANTHMD);*/
		renderer = std::make_shared<OgreOpenVRRender>(title);
	}
	///else if osvr
	///else if ...
	else
	{
		MessageBox(NULL,
				   L"This program can be used with multiple VR solution.\n"
				   L"The executable should be launched from the intended launcher.\n"
				   L"If you're trying to launch it by hand, please check if your command line parameter is correct!\n\n"
				   L"Available command line parameter : \n\t-rift\n"
				   L"\t-vive\n",
				   L"Error: Cannot understand what HMD you want to use!",
				   MB_ICONERROR);
		exit(ANN_ERR_CANTHMD);
	}

	renderer->initOgreRoot("Annwvyn.log");

	srand(time(nullptr));
	singleton = this;

	player = std::make_shared< AnnPlayer>();
	renderer->initVrHmd();
	renderer->initPipeline();
	SceneManager = renderer->getSceneManager();

	renderer->showDebug(OgreVRRender::DebugMode::MONOSCOPIC);

	log("Setup Annwvyn's subsystems");

	//Element on this list will be updated in order by the engine each frame
	SubSystemList.push_back(levelManager = std::make_shared<AnnLevelManager>());
	SubSystemList.push_back(gameObjectManager = std::make_shared<AnnGameObjectManager>());

	//Physics engine needs to be declared before the event manager. But we want the physics engine to be updated after the event manager.

	/*The wanted order is
	- event happens (player input, timers...)
	- physics is ticked (stuff move)
	- audio is synced (sonds comes form where they should)
	- then the game can redraw*/

	physicsEngine = std::make_shared<AnnPhysicsEngine>(getSceneManager()->getRootSceneNode(), player, gameObjectManager->Objects, gameObjectManager->Triggers);
	SubSystemList.push_back(eventManager = std::make_shared< AnnEventManager>(renderer->getWindow()));
	SubSystemList.push_back(physicsEngine);
	SubSystemList.push_back(audioEngine = std::make_shared< AnnAudioEngine>());

	//These could be anywere
	SubSystemList.push_back(filesystemManager = std::make_shared<AnnFilesystemManager>(title));
	SubSystemList.push_back(resourceManager = std::make_shared<AnnResourceManager>());
	SubSystemList.push_back(sceneryManager = std::make_shared<AnnSceneryManager>(renderer));

	renderer->initClientHmdRendering();
	povNode = renderer->getCameraInformationNode();
	povNode->setPosition(player->getPosition() +
		AnnVect3(0.0f, player->getEyesHeight(), 0.0f));

	//This subsystem need the povNode object to be initialized. And the Resource manager because it wants a font file and an image background
	SubSystemList.push_back(onScreenConsole = std::make_shared<AnnConsole>());

	log("===================================================", false);
	log("Annwvyn Game Engine - Step into the Other World    ", false);
	log("Free/Libre Game Engine designed for Virtual Reality", false);
	log("Version : " + getAnnwvynVersion(), false);
	log("===================================================", false);
}

AnnEngine::~AnnEngine()
{
	//Some cute log messsages
	log("Game engine stopped. Subsystem are shutting down...");
	log("Good luck with the real world now! :3");
}

//All theses getter are for encapsulation purpose. Calling them directly would make verry long lines of code. Note that there's a whole bunch of macro in AnnEngine.hpp to help with that
std::shared_ptr<AnnEventManager> AnnEngine::getEventManager()
{
	return eventManager;
}

std::shared_ptr<AnnResourceManager> AnnEngine::getResourceManager()
{
	return resourceManager;
}

std::shared_ptr<AnnGameObjectManager> AnnEngine::getGameObjectManager()
{
	return gameObjectManager;
}

std::shared_ptr<AnnSceneryManager> AnnEngine::getSceneryManager()
{
	return sceneryManager;
}

std::shared_ptr<OgreVRRender> AnnEngine::getVRRenderer()
{
	return renderer;
}

std::shared_ptr<AnnLevelManager> AnnEngine::getLevelManager()
{
	return levelManager;
}

std::shared_ptr<AnnPlayer> AnnEngine::getPlayer()
{
	return player;
}

std::shared_ptr<AnnFilesystemManager> AnnEngine::getFileSystemManager()
{
	return filesystemManager;
}

std::shared_ptr<AnnAudioEngine> AnnEngine::getAudioEngine()
{
	return audioEngine;
}

std::shared_ptr<AnnPhysicsEngine> AnnEngine::getPhysicsEngine()
{
	return physicsEngine;
}

//This is static, but actually needs Ogre to be running. So be carefull
void AnnEngine::log(std::string message, bool flag)
{
	Ogre::String messageForLog;

	if (flag)
	{
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY);
		messageForLog += "Annwvyn - ";
	}
	else
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_INTENSITY);

	messageForLog += message;
	Ogre::LogManager::getSingleton().logMessage(messageForLog);
	if (onScreenConsole != nullptr)
		onScreenConsole->append(message);

	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_INTENSITY);
}

//Don't ask me why this is not part of the Physics engine. Actually it just calls something on the physics engine. Will be probably deleted in the future.
void AnnEngine::initPlayerPhysics()
{
	physicsEngine->initPlayerPhysics(povNode);
}

//Need to be redone.
bool AnnEngine::requestStop()
{
	//pres ESC to quit. Stupid but efficient. I like that.
	if (isKeyDown(OIS::KC_ESCAPE))
		return true;
	//If the user quit the App from the Oculus Home
	if (renderer->shouldQuit())
		return true;
	return false;
}

//This is the most important function of the whole project. It's the heartbeat of the game or app using this engine.
bool AnnEngine::refresh()
{
	//Get the rendering delta time (should be roughly equals to 1/desiredFramerate in seconds)
	updateTime = renderer->getUpdateTime();
	player->engineUpdate(getFrameTime());

	for (auto SubSystem : SubSystemList)
		if (!SubSystem->needUpdate()) continue; //If doen't need update, swith to the next
		else SubSystem->update();				//The "else" keyword is used to not put curly braces, by lazyness and by code style.

	//Update camera from player
	syncPov();

	//Update VR form real world
	renderer->updateTracking();

	//Update view
	renderer->renderAndSubmitFrame();

	//Don't laugh
	return !requestStop();
}

//This just move a node where the other node is. Yes I know about parenting. I had reasons to do it that way, but I forgot.
inline void AnnEngine::syncPov()
{
	povNode->setPosition(player->getPosition());
	povNode->setOrientation(player->getOrientation().toQuaternion());
}

//Bad. Don't use. Register an event listener and use the KeyEvent callback.
inline bool AnnEngine::isKeyDown(OIS::KeyCode key)
{
	if (!eventManager) return false;
	return eventManager->Keyboard->isKeyDown(key);
}

Ogre::SceneNode* AnnEngine::getCamera()
{
	return povNode;
}

Ogre::SceneManager* AnnEngine::getSceneManager()
{
	return SceneManager;
}

unsigned long AnnEngine::getTimeFromStartUp()
{
	return renderer->getTimer()->getMilliseconds();
}

double AnnEngine::getTimeFromStartupSeconds()
{
	return static_cast<double>(getTimeFromStartUp()) / 1000.0;
}

//the delta time of the last frame, not the current one
double AnnEngine::getFrameTime()
{
	return updateTime;
}

//Raw position and orientaiton of the head in world space. This is usefull if you want to mess around with weird stuff. This has been bodged when I integrated a LEAP motion in that mess.
OgrePose AnnEngine::getHmdPose()
{
	if (renderer)
		return renderer->returnPose;
	return OgrePose();
}

//Because Windows and the Win32 platform sucks.
void AnnEngine::openConsole()
{
#ifdef _WIN32

	//Allocate a console for this app
	if (AllocConsole())
	{
		//put stdout on this console;
#pragma warning(disable:4996) //Okay, so for some reason, freopen is "bad" because potentially dangerous. However, since I'm passing static strings here, unless you go hack the DLL, I don't know what harm you can do.
		freopen("CONOUT$", "w", stdout);
#pragma warning(default:4996)
	}

	//Redirect cerr to cout
	std::cerr.rdbuf(std::cout.rdbuf());

	SetConsoleTitle(L"Annwyn Debug Console");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY);

#endif
}

//Well, I may make the pointer to the onScreenConsole more accessible.
void AnnEngine::toogleOnScreenConsole()
{
	if (onScreenConsole) onScreenConsole->toogle();
}

bool AnnEngine::appVisibleInHMD()
{
	if (renderer->isVisibleInHmd() == true) // why "== true" ? Because at some point it was returning an ovrBool, wich is the boolean type of the oculus SDK that doesn't cast correctly to a C++ bool. YES. I DON'T KNOW HOW THEY MANAGED TO FFFF TAHT UP.
		return true;
	return false;
}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "AnnEngine.hpp"
#include "AnnLogger.hpp"

using namespace Annwvyn;

AnnEngine* AnnEngine::singleton(NULL);

//Log is static. Therefore this has to be static too to be able to write to it.
std::shared_ptr<AnnConsole> AnnEngine::onScreenConsole(nullptr);

AnnEngine* AnnEngine::Instance()
{
	return singleton;
}

std::string AnnEngine::getAnnwvynVersion(long long int padding)
{
	std::stringstream version;
	version << ANN_MAJOR << "." << ANN_MINOR << "." << ANN_PATCH;
	if (ANN_EXPERIMENTAL)
		version << "-experimental";
	padding -= version.str().length();
	for (int i(0); i < padding; i++)
		version << " ";
	return version.str();
}

void AnnEngine::startGameplayLoop()
{
	while (refresh());
}

AnnEngine::AnnEngine(const char title[], std::string hmdCommand) :
	renderer(nullptr),
	resourceManager(nullptr),
	sceneryManager(nullptr),
	filesystemManager(nullptr),
	audioEngine(nullptr),
	eventManager(nullptr),
	physicsEngine(nullptr),
	gameObjectManager(nullptr),
	levelManager(nullptr),
	player(nullptr),
	SceneManager(nullptr),
	vrRendererPovGameplayPlacement(nullptr),
	updateTime(-1)
{
	if (singleton)
	{
		log("Can't create 2 instances of the engine!");
		exit(ANN_ERR_MEMORY);
	}

	std::cerr << "HMD selection from command line routine returned : " << hmdCommand << std::endl;

	//Select the correct OgreVRRender class to use :
	if (hmdCommand == "OgreOculusRender"
		|| hmdCommand == "OgreDefaultRender")
		renderer = std::make_shared<OgreOculusRender>(title);
	else if (hmdCommand == "OgreOpenVRRender")
		renderer = std::make_shared<OgreOpenVRRender>(title);
	else if (hmdCommand == "OgreNoVRRender")
		renderer = std::make_shared<OgreNoVRRender>(title);

	else
	{
		displayWin32ErrorMessage(L"Error: Cannot understand VR System you want to use!",
								 L"This program can be used with multiple VR solution.\n"
								 L"The executable should be launched via a dedicated launcher.\n"
								 L"If you're trying to launch it by hand, please check if your command line parameter is correct!\n\n"
								 L"Available command line parameter : \n"
								 L"\t-rift\n"
								 L"\t-vive\n"
								 L"\nIf you don't specify anything, the default system will be used (here it's the Oculus Rift)\n"
								 L"If you don't have (or can't use) VR Hardware, you can launch with -noVR.\n"
								 L"This will display the image on a simple window without attempting to talk to VR hardware"
		);
		exit(ANN_ERR_CANTHMD);
	}

	renderer->initOgreRoot("Annwvyn.log");

	//Display start banner
	log("============================================================", false);
	log("| Annwvyn Game Engine - Step into the Other World          |", false);
	log("| Free/Libre C++ Game Engine designed for Virtual Reality  |", false);
	log("|                                                          |", false);
	log("| Copyright Arthur Brainville (a.k.a. Ybalrid) 2013-2016   |", false);
	log("| Distributed under the terms of the MIT license agreement |", false);
	log("|                                                          |", false);
	log("| Visit http://annwvyn.org/ for more informations!         |", false);
	log("| Version : " + getAnnwvynVersion(61 - 13 - 1) + "|", false);
	log("============================================================", false);

	srand(time(nullptr));
	singleton = this;

	player = std::make_shared< AnnPlayer>();
	renderer->initVrHmd();
	renderer->initPipeline();
	SceneManager = renderer->getSceneManager();

	renderer->showDebug(OgreVRRender::DebugMode::RAW_BUFFER);

	log("Setup Annwvyn's subsystems");

	//Element on this list will be updated in order by the engine each frame
	SubSystemList.push_back(levelManager = std::make_shared<AnnLevelManager>());
	SubSystemList.push_back(gameObjectManager = std::make_shared<AnnGameObjectManager>());

	//Physics engine needs to be declared before the event manager. But we want the physics engine to be updated after the event manager.

	/*The wanted order is
	- event happens (player input, timers...)
	- physics is ticked (stuff move)
	- audio is synced (sounds comes form where they should)
	- then the game can redraw*/

	physicsEngine = std::make_shared<AnnPhysicsEngine>(getSceneManager()->getRootSceneNode(), player, gameObjectManager->Objects, gameObjectManager->Triggers);
	SubSystemList.push_back(eventManager = std::make_shared< AnnEventManager>(renderer->getWindow()));
	SubSystemList.push_back(physicsEngine);
	SubSystemList.push_back(audioEngine = std::make_shared< AnnAudioEngine>());

	//These could be anywhere
	SubSystemList.push_back(filesystemManager = std::make_shared<AnnFilesystemManager>(title));
	SubSystemList.push_back(resourceManager = std::make_shared<AnnResourceManager>());
	SubSystemList.push_back(sceneryManager = std::make_shared<AnnSceneryManager>(renderer));

	renderer->initClientHmdRendering();
	vrRendererPovGameplayPlacement = renderer->getCameraInformationNode();
	vrRendererPovGameplayPlacement->setPosition(player->getPosition() +
												AnnVect3(0.0f, player->getEyesHeight(), 0.0f));

											//This subsystem need the vrRendererPovGameplayPlacement object to be initialized. And the Resource manager because it wants a font file and an image background
	SubSystemList.push_back(onScreenConsole = std::make_shared<AnnConsole>());
}

AnnEngine::~AnnEngine()
{
	//Some cute log messages
	log("Game engine stopped. Subsystem are shutting down...");
	log("Good luck with the real world now! :3");
}

//All theses getter are for encapsulation purpose. Calling them directly would make very long lines of code. Note that there's a whole bunch of macro in AnnEngine.hpp to help with that
std::shared_ptr<AnnEventManager> AnnEngine::getEventManager()
{
	return eventManager;
}

std::shared_ptr<AnnResourceManager> AnnEngine::getResourceManager()
{
	return resourceManager;
}

std::shared_ptr<AnnGameObjectManager> AnnEngine::getGameObjectManager()
{
	return gameObjectManager;
}

std::shared_ptr<AnnSceneryManager> AnnEngine::getSceneryManager()
{
	return sceneryManager;
}

std::shared_ptr<OgreVRRender> AnnEngine::getVRRenderer()
{
	return renderer;
}

std::shared_ptr<AnnLevelManager> AnnEngine::getLevelManager()
{
	return levelManager;
}

std::shared_ptr<AnnPlayer> AnnEngine::getPlayer()
{
	return player;
}

std::shared_ptr<AnnFilesystemManager> AnnEngine::getFileSystemManager()
{
	return filesystemManager;
}

std::shared_ptr<AnnAudioEngine> AnnEngine::getAudioEngine()
{
	return audioEngine;
}

std::shared_ptr<AnnPhysicsEngine> AnnEngine::getPhysicsEngine()
{
	return physicsEngine;
}

//This is static, but actually needs Ogre to be running. So be careful
void AnnEngine::log(std::string message, bool flag)
{
	Ogre::String messageForLog;

	if (flag)
	{
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY);
		messageForLog += "Annwvyn - ";
	}
	else
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_INTENSITY);

	messageForLog += message;
	Ogre::LogManager::getSingleton().logMessage(messageForLog);
	if (onScreenConsole != nullptr)
		onScreenConsole->append(message);

	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_INTENSITY);
}

//Don't ask me why this is not part of the Physics engine. Actually it just calls something on the physics engine. Will be probably deleted in the future.
void AnnEngine::initPlayerPhysics()
{
	physicsEngine->initPlayerPhysics(vrRendererPovGameplayPlacement);
}

//Need to be redone.
bool AnnEngine::requestStop()
{
	//pres ESC to quit. Stupid but efficient. I like that.
	if (isKeyDown(OIS::KC_ESCAPE))
		return true;
	//If the user quit the App from the Oculus Home
	if (renderer->shouldQuit())
		return true;
	return false;
}

//This is the most important function of the whole project. It's the heartbeat of the game or app using this engine.
bool AnnEngine::refresh()
{
	//Get the rendering delta time (should be roughly equals to 1/desiredFramerate in seconds)
	updateTime = renderer->getUpdateTime();
	player->engineUpdate(getFrameTime());

	for (auto SubSystem : SubSystemList)
		if (!SubSystem->needUpdate()) continue; //If doesn't need update, switch to the next
		else SubSystem->update();				//The "else" keyword is used to not put curly braces, by laziness and by code style.

		//Update camera from player
		syncPov();

		//Update VR form real world
		renderer->updateTracking();

		//Update view
		renderer->renderAndSubmitFrame();

		//Don't laugh
		return !requestStop();
}

//This just move a node where the other node is. Yes I know about parenting. I had reasons to do it that way, but I forgot.
inline void AnnEngine::syncPov()
{
	vrRendererPovGameplayPlacement->setPosition(player->getPosition());
	vrRendererPovGameplayPlacement->setOrientation(player->getOrientation().toQuaternion());
}

//Bad. Don't use. Register an event listener and use the KeyEvent callback.
inline bool AnnEngine::isKeyDown(OIS::KeyCode key)
{
	if (!eventManager) return false;
	return eventManager->Keyboard->isKeyDown(key);
}

Ogre::SceneNode* AnnEngine::getPlayerPovNode()
{
	return vrRendererPovGameplayPlacement;
}

Ogre::SceneManager* AnnEngine::getSceneManager()
{
	return SceneManager;
}

unsigned long AnnEngine::getTimeFromStartUp()
{
	return renderer->getTimer()->getMilliseconds();
}

double AnnEngine::getTimeFromStartupSeconds()
{
	return static_cast<double>(getTimeFromStartUp()) / 1000.0;
}

//the delta time of the last frame, not the current one
double AnnEngine::getFrameTime()
{
	return updateTime;
}

//Raw position and orientation of the head in world space. This is useful if you want to mess around with weird stuff. This has been bodged when I integrated a LEAP motion in that mess.
OgrePose AnnEngine::getHmdPose()
{
	if (renderer)
		return renderer->returnPose;
	return OgrePose();
}

std::shared_ptr<AnnUserSubSystem> AnnEngine::registerUserSubSystem(std::shared_ptr<AnnUserSubSystem> userSystem)
{
	for (auto system : SubSystemList)
		if (userSystem->name == system->name)
		{
			AnnDebug() << "A subsystem with the name " << userSystem->name << "is already registered.";
			return nullptr;
		}
	SubSystemList.push_back(userSystem);
	return userSystem;
}

std::shared_ptr<AnnSubSystem> Annwvyn::AnnEngine::getSubSystemByName(std::string name)
{
	for (auto subsystem : SubSystemList)
		if (subsystem->name == name)
			return subsystem;
	return nullptr;
}

bool AnnEngine::isUserSubSystem(std::shared_ptr<AnnSubSystem> subsystem)
{
	AnnSubSystem* nakedSubSystem(subsystem.get());

	AnnUserSubSystem* result = dynamic_cast<AnnUserSubSystem*>(nakedSubSystem);
	if (result != nullptr) return true;
	return false;
}

void Annwvyn::AnnEngine::removeUserSubSystem(std::shared_ptr<AnnUserSubSystem> subsystem)
{
	SubSystemList.remove(subsystem);
}

//Because Windows and the Win32 platform sucks.
void AnnEngine::openConsole()
{
#ifdef _WIN32

	//Allocate a console for this app
	if (AllocConsole())
	{
		//put stdout on this console;
#pragma warning(disable:4996) //Okay, so for some reason, freopen is "bad" because potentially dangerous. However, since I'm passing static strings here, unless you go hack the DLL, I don't know what harm you can do.
		freopen("CONOUT$", "w", stdout);
#pragma warning(default:4996)
	}

	//Redirect cerr to cout
	std::cerr.rdbuf(std::cout.rdbuf());

	SetConsoleTitle(L"Annwvyn Debug Console");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY);

#endif
}

//Well, I may make the pointer to the onScreenConsole more accessible.
void AnnEngine::toogleOnScreenConsole()
{
	if (onScreenConsole) onScreenConsole->toggle();
}

bool AnnEngine::appVisibleInHMD()
{
	if (renderer->isVisibleInHmd())
		return true;
	return false;
}<commit_msg>Update AnnEngine.cpp<commit_after>#include "stdafx.h"
#include "AnnEngine.hpp"
#include "AnnLogger.hpp"

using namespace Annwvyn;

AnnEngine* AnnEngine::singleton(NULL);

//Log is static. Therefore this has to be static too to be able to write to it.
std::shared_ptr<AnnConsole> AnnEngine::onScreenConsole(nullptr);

AnnEngine* AnnEngine::Instance()
{
	return singleton;
}

std::string AnnEngine::getAnnwvynVersion(long long int padding)
{
	std::stringstream version;
	version << ANN_MAJOR << "." << ANN_MINOR << "." << ANN_PATCH;
	if (ANN_EXPERIMENTAL)
		version << "-experimental";
	padding -= version.str().length();
	for (int i(0); i < padding; i++)
		version << " ";
	return version.str();
}

void AnnEngine::startGameplayLoop()
{
	while (refresh());
}

AnnEngine::AnnEngine(const char title[], std::string hmdCommand) :
	renderer(nullptr),
	resourceManager(nullptr),
	sceneryManager(nullptr),
	filesystemManager(nullptr),
	audioEngine(nullptr),
	eventManager(nullptr),
	physicsEngine(nullptr),
	gameObjectManager(nullptr),
	levelManager(nullptr),
	player(nullptr),
	SceneManager(nullptr),
	vrRendererPovGameplayPlacement(nullptr),
	updateTime(-1)
{
	if (singleton)
	{
		log("Can't create 2 instances of the engine!");
		exit(ANN_ERR_MEMORY);
	}

	std::cerr << "HMD selection from command line routine returned : " << hmdCommand << std::endl;

	//Select the correct OgreVRRender class to use :
	if (hmdCommand == "OgreOculusRender"
		|| hmdCommand == "OgreDefaultRender")
		renderer = std::make_shared<OgreOculusRender>(title);
	else if (hmdCommand == "OgreOpenVRRender")
		renderer = std::make_shared<OgreOpenVRRender>(title);
	else if (hmdCommand == "OgreNoVRRender")
		renderer = std::make_shared<OgreNoVRRender>(title);

	else
	{
		displayWin32ErrorMessage(L"Error: Cannot understand VR System you want to use!",
								 L"This program can be used with multiple VR solution.\n"
								 L"The executable should be launched via a dedicated launcher.\n"
								 L"If you're trying to launch it by hand, please check if your command line parameter is correct!\n\n"
								 L"Available command line parameter : \n"
								 L"\t-rift\n"
								 L"\t-vive\n"
								 L"\nIf you don't specify anything, the default system will be used (here it's the Oculus Rift)\n"
								 L"If you don't have (or can't use) VR Hardware, you can launch with -noVR.\n"
								 L"This will display the image on a simple window without attempting to talk to VR hardware"
		);
		exit(ANN_ERR_CANTHMD);
	}

	renderer->initOgreRoot("Annwvyn.log");

	//Display start banner
	log("============================================================", false);
	log("| Annwvyn Game Engine - Step into the Other World          |", false);
	log("| Free/Libre C++ Game Engine designed for Virtual Reality  |", false);
	log("|                                                          |", false);
	log("| Copyright Arthur Brainville (a.k.a. Ybalrid) 2013-2016   |", false);
	log("| Distributed under the terms of the MIT license agreement |", false);
	log("|                                                          |", false);
	log("| Visit http://annwvyn.org/ for more informations!         |", false);
	log("| Version : " + getAnnwvynVersion(61 - 13 - 1) + "|", false);
	log("============================================================", false);

	srand(time(nullptr));
	singleton = this;

	player = std::make_shared< AnnPlayer>();
	renderer->initVrHmd();
	renderer->initPipeline();
	SceneManager = renderer->getSceneManager();

	renderer->showDebug(OgreVRRender::DebugMode::MONOSCOPIC);

	log("Setup Annwvyn's subsystems");

	//Element on this list will be updated in order by the engine each frame
	SubSystemList.push_back(levelManager = std::make_shared<AnnLevelManager>());
	SubSystemList.push_back(gameObjectManager = std::make_shared<AnnGameObjectManager>());

	//Physics engine needs to be declared before the event manager. But we want the physics engine to be updated after the event manager.

	/*The wanted order is
	- event happens (player input, timers...)
	- physics is ticked (stuff move)
	- audio is synced (sounds comes form where they should)
	- then the game can redraw*/

	physicsEngine = std::make_shared<AnnPhysicsEngine>(getSceneManager()->getRootSceneNode(), player, gameObjectManager->Objects, gameObjectManager->Triggers);
	SubSystemList.push_back(eventManager = std::make_shared< AnnEventManager>(renderer->getWindow()));
	SubSystemList.push_back(physicsEngine);
	SubSystemList.push_back(audioEngine = std::make_shared< AnnAudioEngine>());

	//These could be anywhere
	SubSystemList.push_back(filesystemManager = std::make_shared<AnnFilesystemManager>(title));
	SubSystemList.push_back(resourceManager = std::make_shared<AnnResourceManager>());
	SubSystemList.push_back(sceneryManager = std::make_shared<AnnSceneryManager>(renderer));

	renderer->initClientHmdRendering();
	vrRendererPovGameplayPlacement = renderer->getCameraInformationNode();
	vrRendererPovGameplayPlacement->setPosition(player->getPosition() +
												AnnVect3(0.0f, player->getEyesHeight(), 0.0f));

											//This subsystem need the vrRendererPovGameplayPlacement object to be initialized. And the Resource manager because it wants a font file and an image background
	SubSystemList.push_back(onScreenConsole = std::make_shared<AnnConsole>());
}

AnnEngine::~AnnEngine()
{
	//Some cute log messages
	log("Game engine stopped. Subsystem are shutting down...");
	log("Good luck with the real world now! :3");
}

//All theses getter are for encapsulation purpose. Calling them directly would make very long lines of code. Note that there's a whole bunch of macro in AnnEngine.hpp to help with that
std::shared_ptr<AnnEventManager> AnnEngine::getEventManager()
{
	return eventManager;
}

std::shared_ptr<AnnResourceManager> AnnEngine::getResourceManager()
{
	return resourceManager;
}

std::shared_ptr<AnnGameObjectManager> AnnEngine::getGameObjectManager()
{
	return gameObjectManager;
}

std::shared_ptr<AnnSceneryManager> AnnEngine::getSceneryManager()
{
	return sceneryManager;
}

std::shared_ptr<OgreVRRender> AnnEngine::getVRRenderer()
{
	return renderer;
}

std::shared_ptr<AnnLevelManager> AnnEngine::getLevelManager()
{
	return levelManager;
}

std::shared_ptr<AnnPlayer> AnnEngine::getPlayer()
{
	return player;
}

std::shared_ptr<AnnFilesystemManager> AnnEngine::getFileSystemManager()
{
	return filesystemManager;
}

std::shared_ptr<AnnAudioEngine> AnnEngine::getAudioEngine()
{
	return audioEngine;
}

std::shared_ptr<AnnPhysicsEngine> AnnEngine::getPhysicsEngine()
{
	return physicsEngine;
}

//This is static, but actually needs Ogre to be running. So be careful
void AnnEngine::log(std::string message, bool flag)
{
	Ogre::String messageForLog;

	if (flag)
	{
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY);
		messageForLog += "Annwvyn - ";
	}
	else
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_INTENSITY);

	messageForLog += message;
	Ogre::LogManager::getSingleton().logMessage(messageForLog);
	if (onScreenConsole != nullptr)
		onScreenConsole->append(message);

	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_INTENSITY);
}

//Don't ask me why this is not part of the Physics engine. Actually it just calls something on the physics engine. Will be probably deleted in the future.
void AnnEngine::initPlayerPhysics()
{
	physicsEngine->initPlayerPhysics(vrRendererPovGameplayPlacement);
}

//Need to be redone.
bool AnnEngine::requestStop()
{
	//pres ESC to quit. Stupid but efficient. I like that.
	if (isKeyDown(OIS::KC_ESCAPE))
		return true;
	//If the user quit the App from the Oculus Home
	if (renderer->shouldQuit())
		return true;
	return false;
}

//This is the most important function of the whole project. It's the heartbeat of the game or app using this engine.
bool AnnEngine::refresh()
{
	//Get the rendering delta time (should be roughly equals to 1/desiredFramerate in seconds)
	updateTime = renderer->getUpdateTime();
	player->engineUpdate(getFrameTime());

	for (auto SubSystem : SubSystemList)
		if (!SubSystem->needUpdate()) continue; //If doesn't need update, switch to the next
		else SubSystem->update();				//The "else" keyword is used to not put curly braces, by laziness and by code style.

		//Update camera from player
		syncPov();

		//Update VR form real world
		renderer->updateTracking();

		//Update view
		renderer->renderAndSubmitFrame();

		//Don't laugh
		return !requestStop();
}

//This just move a node where the other node is. Yes I know about parenting. I had reasons to do it that way, but I forgot.
inline void AnnEngine::syncPov()
{
	vrRendererPovGameplayPlacement->setPosition(player->getPosition());
	vrRendererPovGameplayPlacement->setOrientation(player->getOrientation().toQuaternion());
}

//Bad. Don't use. Register an event listener and use the KeyEvent callback.
inline bool AnnEngine::isKeyDown(OIS::KeyCode key)
{
	if (!eventManager) return false;
	return eventManager->Keyboard->isKeyDown(key);
}

Ogre::SceneNode* AnnEngine::getPlayerPovNode()
{
	return vrRendererPovGameplayPlacement;
}

Ogre::SceneManager* AnnEngine::getSceneManager()
{
	return SceneManager;
}

unsigned long AnnEngine::getTimeFromStartUp()
{
	return renderer->getTimer()->getMilliseconds();
}

double AnnEngine::getTimeFromStartupSeconds()
{
	return static_cast<double>(getTimeFromStartUp()) / 1000.0;
}

//the delta time of the last frame, not the current one
double AnnEngine::getFrameTime()
{
	return updateTime;
}

//Raw position and orientation of the head in world space. This is useful if you want to mess around with weird stuff. This has been bodged when I integrated a LEAP motion in that mess.
OgrePose AnnEngine::getHmdPose()
{
	if (renderer)
		return renderer->returnPose;
	return OgrePose();
}

std::shared_ptr<AnnUserSubSystem> AnnEngine::registerUserSubSystem(std::shared_ptr<AnnUserSubSystem> userSystem)
{
	for (auto system : SubSystemList)
		if (userSystem->name == system->name)
		{
			AnnDebug() << "A subsystem with the name " << userSystem->name << "is already registered.";
			return nullptr;
		}
	SubSystemList.push_back(userSystem);
	return userSystem;
}

std::shared_ptr<AnnSubSystem> Annwvyn::AnnEngine::getSubSystemByName(std::string name)
{
	for (auto subsystem : SubSystemList)
		if (subsystem->name == name)
			return subsystem;
	return nullptr;
}

bool AnnEngine::isUserSubSystem(std::shared_ptr<AnnSubSystem> subsystem)
{
	AnnSubSystem* nakedSubSystem(subsystem.get());

	AnnUserSubSystem* result = dynamic_cast<AnnUserSubSystem*>(nakedSubSystem);
	if (result != nullptr) return true;
	return false;
}

void Annwvyn::AnnEngine::removeUserSubSystem(std::shared_ptr<AnnUserSubSystem> subsystem)
{
	SubSystemList.remove(subsystem);
}

//Because Windows and the Win32 platform sucks.
void AnnEngine::openConsole()
{
#ifdef _WIN32

	//Allocate a console for this app
	if (AllocConsole())
	{
		//put stdout on this console;
#pragma warning(disable:4996) //Okay, so for some reason, freopen is "bad" because potentially dangerous. However, since I'm passing static strings here, unless you go hack the DLL, I don't know what harm you can do.
		freopen("CONOUT$", "w", stdout);
#pragma warning(default:4996)
	}

	//Redirect cerr to cout
	std::cerr.rdbuf(std::cout.rdbuf());

	SetConsoleTitle(L"Annwvyn Debug Console");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY);

#endif
}

//Well, I may make the pointer to the onScreenConsole more accessible.
void AnnEngine::toogleOnScreenConsole()
{
	if (onScreenConsole) onScreenConsole->toggle();
}

bool AnnEngine::appVisibleInHMD()
{
	if (renderer->isVisibleInHmd())
		return true;
	return false;
}
<|endoftext|>


<commit_before><commit_msg>Actually play the game if not in testing mode.<commit_after><|endoftext|>


<commit_before>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright 2011-2019 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.                                      *
 ******************************************************************************/

#define CAF_SUITE ip

#include "caf/net/ip.hpp"

#include "caf/test/dsl.hpp"

#include "host_fixture.hpp"

#include "caf/ip_address.hpp"
#include "caf/ipv4_address.hpp"

using namespace caf;
using namespace caf::net;

namespace {

struct fixture : host_fixture {
  fixture() : v6_local{{0}, {0x1}} {
    v4_local = ip_address{make_ipv4_address(127, 0, 0, 1)};
    v4_any_addr = ip_address{make_ipv4_address(0, 0, 0, 0)};
  }

  bool contains(ip_address x) {
    return std::count(addrs.begin(), addrs.end(), x) > 0;
  }

  ip_address v4_any_addr;
  ip_address v6_any_addr;
  ip_address v4_local;
  ip_address v6_local;

  std::vector<ip_address> addrs;
};

} // namespace

CAF_TEST_FIXTURE_SCOPE(ip_tests, fixture)

CAF_TEST(resolve localhost) {
  addrs = ip::resolve("localhost");
  CAF_CHECK(!addrs.empty());
  CAF_CHECK(contains(v4_local) || contains(v6_local));
}

CAF_TEST(resolve any) {
  ip_address v4_any{make_ipv4_address(0, 0, 0, 0)};
  ip_address v6_any{{0}, {0}};
  auto addrs = ip::resolve("");
  CAF_CHECK(!addrs.empty());
  auto contains = [&](ip_address x) {
    return std::count(addrs.begin(), addrs.end(), x) > 0;
  };
  CAF_CHECK(contains(v4_any) || contains(v6_any));
}

CAF_TEST(local addresses) {
  CAF_MESSAGE("check: v4");
  addrs = ip::local_addresses("0.0.0.0");
  CAF_CHECK(!addrs.empty());
  CAF_CHECK(contains(v4_any_addr));
  CAF_MESSAGE("check: v6");
  addrs = ip::local_addresses("::");
  CAF_CHECK(!addrs.empty());
  CAF_CHECK(contains(v6_any_addr));
  CAF_MESSAGE("check: localhost");
  addrs = ip::local_addresses("localhost");
  CAF_CHECK(!addrs.empty());
  CAF_CHECK(contains(v4_local) || contains(v6_local));
}

CAF_TEST_FIXTURE_SCOPE_END()
<commit_msg>Split local address test cases<commit_after>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright 2011-2019 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.                                      *
 ******************************************************************************/

#define CAF_SUITE ip

#include "caf/net/ip.hpp"

#include "caf/test/dsl.hpp"

#include "host_fixture.hpp"

#include "caf/ip_address.hpp"
#include "caf/ipv4_address.hpp"

using namespace caf;
using namespace caf::net;

namespace {

struct fixture : host_fixture {
  fixture() : v6_local{{0}, {0x1}} {
    v4_local = ip_address{make_ipv4_address(127, 0, 0, 1)};
    v4_any_addr = ip_address{make_ipv4_address(0, 0, 0, 0)};
  }

  bool contains(ip_address x) {
    return std::count(addrs.begin(), addrs.end(), x) > 0;
  }

  ip_address v4_any_addr;
  ip_address v6_any_addr;
  ip_address v4_local;
  ip_address v6_local;

  std::vector<ip_address> addrs;
};

} // namespace

CAF_TEST_FIXTURE_SCOPE(ip_tests, fixture)

CAF_TEST(resolve localhost) {
  addrs = ip::resolve("localhost");
  CAF_CHECK(!addrs.empty());
  CAF_CHECK(contains(v4_local) || contains(v6_local));
}

CAF_TEST(resolve any) {
  addrs = ip::resolve("");
  CAF_CHECK(!addrs.empty());
  CAF_CHECK(contains(v4_any_addr) || contains(v6_any_addr));
}

CAF_TEST(local addresses localhost) {
  addrs = ip::local_addresses("localhost");
  CAF_CHECK(!addrs.empty());
  CAF_CHECK(contains(v4_local) || contains(v6_local));
}

CAF_TEST(local addresses any) {
  addrs = ip::local_addresses("0.0.0.0");
  auto tmp = ip::local_addresses("::");
  addrs.insert(addrs.end(), tmp.begin(), tmp.end());
  CAF_CHECK(!addrs.empty());
  CAF_CHECK(contains(v4_any_addr) || contains(v6_any_addr));
}

CAF_TEST_FIXTURE_SCOPE_END()
<|endoftext|>