<commit_before>/* GG is a GUI for SDL and OpenGL.
   Copyright (C) 2007 T. Zachary Laine

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

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

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

   If you do not wish to comply with the terms of the LGPL please
   contact the author as other terms are available for a fee.

   Zach Laine
   whatwasthataddress@hotmail.com */

#include <GG/Ogre/OgreGUI.h>

#include <GG/EventPump.h>

#include <OgreDataStream.h>
#include <OgreRenderSystem.h>
#include <OgreRenderWindow.h>
#include <OgreRoot.h>

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#include <GL/gl.h>
#include <GG/glext.h>
#else
#include <GL/glx.h>
#endif

using namespace GG;

namespace {
    struct CleanQuit {};

    class OgreModalEventPump : public ModalEventPump
    {
    public:
        OgreModalEventPump(const bool& done) : ModalEventPump(done) {}
        virtual void operator()()
            {
                GUI* gui = GUI::GetGUI();
                EventPumpState& state = State();
                Ogre::Root& root = Ogre::Root::getSingleton();
                while (!m_done) {
                    Ogre::WindowEventUtilities::messagePump();
                    LoopBody(gui, state, true, false);
                    gui->HandleSystemEvents();
                    if (!root.renderOneFrame())
                        break;
                }
            }
    };
}

OgreGUI::OgreGUI(Ogre::RenderWindow* window, const std::string& config_filename/* = ""*/) :
    GUI(""),
    m_window(window),
    m_timer(),
    m_config_file_data()
{
    m_window->addListener(this);
    Ogre::WindowEventUtilities::addWindowEventListener(m_window, this);
    EnableMouseButtonDownRepeat(250, 15);

    std::ifstream ifs(config_filename.c_str());
    if (ifs) {
        Ogre::FileStreamDataStream file_stream(&ifs, false);
        m_config_file_data.bind(new Ogre::MemoryDataStream(file_stream));
    }
}

OgreGUI::~OgreGUI()
{
    Ogre::WindowEventUtilities::removeWindowEventListener(m_window, this);
    m_window->removeListener(this);
}

boost::shared_ptr<ModalEventPump> OgreGUI::CreateModalEventPump(bool& done)
{ return boost::shared_ptr<ModalEventPump>(new OgreModalEventPump(done)); }

int OgreGUI::Ticks() const
{ return m_timer.getMilliseconds(); }

int OgreGUI::AppWidth() const
{ return m_window->getWidth(); }

int OgreGUI::AppHeight() const
{ return m_window->getHeight(); }

const Ogre::SharedPtr<Ogre::DataStream>& OgreGUI::ConfigFileStream() const
{ return m_config_file_data; }

void OgreGUI::Exit(int code)
{
    if (code == 0)
        throw CleanQuit();
    else
        std::exit(code);
}

OgreGUI* OgreGUI::GetGUI()
{ return dynamic_cast<OgreGUI*>(GUI::GetGUI()); }

void OgreGUI::RenderBegin() {}
void OgreGUI::RenderEnd() {}

void OgreGUI::Run()
{
    Ogre::Root& root = Ogre::Root::getSingleton();
    Ogre::RenderSystem* active_renderer = root.getRenderSystem();
    assert(active_renderer);
    active_renderer->_initRenderTargets();
    root.clearEventTimes();
    try {
        while (1) {
            Ogre::WindowEventUtilities::messagePump();
            HandleSystemEvents();
            if (!root.renderOneFrame())
                break;
        }
    } catch (const CleanQuit&) {}
}

void OgreGUI::HandleSystemEvents()
{ HandleSystemEventsSignal(); }

void OgreGUI::Enter2DMode()
{
    glPushAttrib(GL_ALL_ATTRIB_BITS);
    glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);

	using namespace Ogre;

    Ogre::RenderSystem* render_system = Ogre::Root::getSingleton().getRenderSystem();

    // set-up matrices
    render_system->_setWorldMatrix(Matrix4::IDENTITY);
    render_system->_setViewMatrix(Matrix4::IDENTITY);
    render_system->_setProjectionMatrix(Matrix4::IDENTITY);

    glOrtho(0.0, AppWidth(), AppHeight(), 0.0, 0.0, AppWidth());

    // initialise render settings
    render_system->setLightingEnabled(false);
    render_system->_setDepthBufferParams(false, false);
    render_system->_setCullingMode(CULL_NONE);
    render_system->_setFog(FOG_NONE);
    render_system->_setColourBufferWriteEnabled(true, true, true, true);
    render_system->unbindGpuProgram(GPT_FRAGMENT_PROGRAM);
    render_system->unbindGpuProgram(GPT_VERTEX_PROGRAM);
    render_system->setShadingType(SO_GOURAUD);
    render_system->_setPolygonMode(PM_SOLID);

    Ogre::LayerBlendModeEx colour_blend_mode;
    colour_blend_mode.blendType = Ogre::LBT_COLOUR;
    colour_blend_mode.source1 = Ogre::LBS_TEXTURE;
    colour_blend_mode.source2 = Ogre::LBS_DIFFUSE;
    colour_blend_mode.operation = Ogre::LBX_MODULATE;
    Ogre::LayerBlendModeEx alpha_blend_mode;
    alpha_blend_mode.blendType = Ogre::LBT_ALPHA;
    alpha_blend_mode.source1 = Ogre::LBS_TEXTURE;
    alpha_blend_mode.source2 = Ogre::LBS_DIFFUSE;
    alpha_blend_mode.operation = Ogre::LBX_MODULATE;
    Ogre::TextureUnitState::UVWAddressingMode uvw_address_mode;
    uvw_address_mode.u = Ogre::TextureUnitState::TAM_CLAMP;
    uvw_address_mode.v = Ogre::TextureUnitState::TAM_CLAMP;
    uvw_address_mode.w = Ogre::TextureUnitState::TAM_CLAMP;

    // initialise texture settings
    render_system->_setTextureCoordCalculation(0, TEXCALC_NONE);
    render_system->_setTextureCoordSet(0, 0);
    render_system->_setTextureUnitFiltering(0, FO_LINEAR, FO_LINEAR, FO_POINT);
    render_system->_setTextureAddressingMode(0, uvw_address_mode);
    render_system->_setTextureMatrix(0, Matrix4::IDENTITY);
    render_system->_setAlphaRejectSettings(CMPF_ALWAYS_PASS, 0);
    render_system->_setTextureBlendMode(0, colour_blend_mode);
    render_system->_setTextureBlendMode(0, alpha_blend_mode);
    render_system->_disableTextureUnitsFrom(0);

    // enable alpha blending
    render_system->_setSceneBlending(SBF_SOURCE_ALPHA, SBF_ONE_MINUS_SOURCE_ALPHA);

    typedef void (*BindBufferARBFn)(GLenum, GLuint);
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
    BindBufferARBFn glBindBufferARB = (BindBufferARBFn)wglGetProcAddress("glBindBufferARB");
#else
    BindBufferARBFn glBindBufferARB = (BindBufferARBFn)glXGetProcAddress((const GLubyte* )"glBindBufferARB");
#endif
    if (glBindBufferARB) {
        glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
        glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
    }

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
    glDisableClientState(GL_INDEX_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_FOG_COORDINATE_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisableClientState(GL_EDGE_FLAG_ARRAY);
}

void OgreGUI::Exit2DMode()
{
    glPopClientAttrib();
    glPopAttrib();
}

void OgreGUI::postRenderTargetUpdate(const Ogre::RenderTargetEvent& event)
{ Render(); }

void OgreGUI::windowResized(Ogre::RenderWindow* window)
{
    if (window == m_window) {
        unsigned int width, height, depth;
        int left, top;
        window->getMetrics(width, height, depth, left, top);
        WindowResizedSignal(width, height);
    }
}

void OgreGUI::windowClosed(Ogre::RenderWindow* window)
{
    if (window == m_window) {
        WindowClosedSignal();
        Exit(0);
    }
}
<commit_msg>Reimplemented OgreGUI::Run() in using OgreModalEventPump, in order to ensure that all the appropriate per-frame actions are being performed (e.g. FPS tracking and governing).<commit_after>/* GG is a GUI for SDL and OpenGL.
   Copyright (C) 2007 T. Zachary Laine

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

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

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

   If you do not wish to comply with the terms of the LGPL please
   contact the author as other terms are available for a fee.

   Zach Laine
   whatwasthataddress@hotmail.com */

#include <GG/Ogre/OgreGUI.h>

#include <GG/EventPump.h>

#include <OgreDataStream.h>
#include <OgreRenderSystem.h>
#include <OgreRenderWindow.h>
#include <OgreRoot.h>

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#include <GL/gl.h>
#include <GG/glext.h>
#else
#include <GL/glx.h>
#endif

using namespace GG;

namespace {
    struct CleanQuit {};

    class OgreModalEventPump : public ModalEventPump
    {
    public:
        OgreModalEventPump(const bool& done) : ModalEventPump(done) {}
        virtual void operator()()
            {
                GUI* gui = GUI::GetGUI();
                EventPumpState& state = State();
                Ogre::Root& root = Ogre::Root::getSingleton();
                while (!m_done) {
                    Ogre::WindowEventUtilities::messagePump();
                    LoopBody(gui, state, true, false);
                    gui->HandleSystemEvents();
                    if (!root.renderOneFrame())
                        break;
                }
            }
    };
}

OgreGUI::OgreGUI(Ogre::RenderWindow* window, const std::string& config_filename/* = ""*/) :
    GUI(""),
    m_window(window),
    m_timer(),
    m_config_file_data()
{
    m_window->addListener(this);
    Ogre::WindowEventUtilities::addWindowEventListener(m_window, this);
    EnableMouseButtonDownRepeat(250, 15);

    std::ifstream ifs(config_filename.c_str());
    if (ifs) {
        Ogre::FileStreamDataStream file_stream(&ifs, false);
        m_config_file_data.bind(new Ogre::MemoryDataStream(file_stream));
    }
}

OgreGUI::~OgreGUI()
{
    Ogre::WindowEventUtilities::removeWindowEventListener(m_window, this);
    m_window->removeListener(this);
}

boost::shared_ptr<ModalEventPump> OgreGUI::CreateModalEventPump(bool& done)
{ return boost::shared_ptr<ModalEventPump>(new OgreModalEventPump(done)); }

int OgreGUI::Ticks() const
{ return m_timer.getMilliseconds(); }

int OgreGUI::AppWidth() const
{ return m_window->getWidth(); }

int OgreGUI::AppHeight() const
{ return m_window->getHeight(); }

const Ogre::SharedPtr<Ogre::DataStream>& OgreGUI::ConfigFileStream() const
{ return m_config_file_data; }

void OgreGUI::Exit(int code)
{
    if (code == 0)
        throw CleanQuit();
    else
        std::exit(code);
}

OgreGUI* OgreGUI::GetGUI()
{ return dynamic_cast<OgreGUI*>(GUI::GetGUI()); }

void OgreGUI::RenderBegin() {}
void OgreGUI::RenderEnd() {}

void OgreGUI::Run()
{
    Ogre::Root& root = Ogre::Root::getSingleton();
    Ogre::RenderSystem* active_renderer = root.getRenderSystem();
    assert(active_renderer);
    active_renderer->_initRenderTargets();
    root.clearEventTimes();
    try {
        bool done = false;
        OgreModalEventPump pump(done);
        pump();
    } catch (const CleanQuit&) {}
}

void OgreGUI::HandleSystemEvents()
{ HandleSystemEventsSignal(); }

void OgreGUI::Enter2DMode()
{
    glPushAttrib(GL_ALL_ATTRIB_BITS);
    glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);

	using namespace Ogre;

    Ogre::RenderSystem* render_system = Ogre::Root::getSingleton().getRenderSystem();

    // set-up matrices
    render_system->_setWorldMatrix(Matrix4::IDENTITY);
    render_system->_setViewMatrix(Matrix4::IDENTITY);
    render_system->_setProjectionMatrix(Matrix4::IDENTITY);

    glOrtho(0.0, AppWidth(), AppHeight(), 0.0, 0.0, AppWidth());

    // initialise render settings
    render_system->setLightingEnabled(false);
    render_system->_setDepthBufferParams(false, false);
    render_system->_setCullingMode(CULL_NONE);
    render_system->_setFog(FOG_NONE);
    render_system->_setColourBufferWriteEnabled(true, true, true, true);
    render_system->unbindGpuProgram(GPT_FRAGMENT_PROGRAM);
    render_system->unbindGpuProgram(GPT_VERTEX_PROGRAM);
    render_system->setShadingType(SO_GOURAUD);
    render_system->_setPolygonMode(PM_SOLID);

    Ogre::LayerBlendModeEx colour_blend_mode;
    colour_blend_mode.blendType = Ogre::LBT_COLOUR;
    colour_blend_mode.source1 = Ogre::LBS_TEXTURE;
    colour_blend_mode.source2 = Ogre::LBS_DIFFUSE;
    colour_blend_mode.operation = Ogre::LBX_MODULATE;
    Ogre::LayerBlendModeEx alpha_blend_mode;
    alpha_blend_mode.blendType = Ogre::LBT_ALPHA;
    alpha_blend_mode.source1 = Ogre::LBS_TEXTURE;
    alpha_blend_mode.source2 = Ogre::LBS_DIFFUSE;
    alpha_blend_mode.operation = Ogre::LBX_MODULATE;
    Ogre::TextureUnitState::UVWAddressingMode uvw_address_mode;
    uvw_address_mode.u = Ogre::TextureUnitState::TAM_CLAMP;
    uvw_address_mode.v = Ogre::TextureUnitState::TAM_CLAMP;
    uvw_address_mode.w = Ogre::TextureUnitState::TAM_CLAMP;

    // initialise texture settings
    render_system->_setTextureCoordCalculation(0, TEXCALC_NONE);
    render_system->_setTextureCoordSet(0, 0);
    render_system->_setTextureUnitFiltering(0, FO_LINEAR, FO_LINEAR, FO_POINT);
    render_system->_setTextureAddressingMode(0, uvw_address_mode);
    render_system->_setTextureMatrix(0, Matrix4::IDENTITY);
    render_system->_setAlphaRejectSettings(CMPF_ALWAYS_PASS, 0);
    render_system->_setTextureBlendMode(0, colour_blend_mode);
    render_system->_setTextureBlendMode(0, alpha_blend_mode);
    render_system->_disableTextureUnitsFrom(0);

    // enable alpha blending
    render_system->_setSceneBlending(SBF_SOURCE_ALPHA, SBF_ONE_MINUS_SOURCE_ALPHA);

    typedef void (*BindBufferARBFn)(GLenum, GLuint);
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
    BindBufferARBFn glBindBufferARB = (BindBufferARBFn)wglGetProcAddress("glBindBufferARB");
#else
    BindBufferARBFn glBindBufferARB = (BindBufferARBFn)glXGetProcAddress((const GLubyte* )"glBindBufferARB");
#endif
    if (glBindBufferARB) {
        glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
        glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
    }

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
    glDisableClientState(GL_INDEX_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_FOG_COORDINATE_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisableClientState(GL_EDGE_FLAG_ARRAY);
}

void OgreGUI::Exit2DMode()
{
    glPopClientAttrib();
    glPopAttrib();
}

void OgreGUI::postRenderTargetUpdate(const Ogre::RenderTargetEvent& event)
{ Render(); }

void OgreGUI::windowResized(Ogre::RenderWindow* window)
{
    if (window == m_window) {
        unsigned int width, height, depth;
        int left, top;
        window->getMetrics(width, height, depth, left, top);
        WindowResizedSignal(width, height);
    }
}

void OgreGUI::windowClosed(Ogre::RenderWindow* window)
{
    if (window == m_window) {
        WindowClosedSignal();
        Exit(0);
    }
}
<|endoftext|>


<commit_before>/**
 * @file
 * @author Jason Lingle
 * @date 2012.02.03
 * @brief Contains the NetworkGeraet class
 */
#ifndef NETWORK_GERAET_HXX_
#define NETWORK_GERAET_HXX_

#include "antenna.hxx"
#include "network_connection.hxx"

/**
 * Defines the interface common to all input network Geräte.
 */
class InputNetworkGeraet: public AObject {
public:
  /**
   * Notifies the InputNetworkGeraet that it has received a packet.
   * @param seq the sequence number of the packet
   * @param data the payload of the packet, excluding sequence and channel
   * numbers
   * @param len the length of the payload
   */
  virtual void receive(NetworkConnection::seq_t seq,
                       const byte* data, unsigned len)
  throw() = 0;

  /**
   * Updates the InputNetworkGeraet based on elapsed time.
   *
   * The default does nothing.
   * @param et the time, in milliseconds, since the previous call to update()
   */
  virtual void update(unsigned et) throw() { }
};

/**
 * Defines the interface common to all output network Geräte.
 */
class OutputNetworkGeraet: public AObject {
protected:
  /**
   * The output channel to write to.
   */
  NetworkConnection::channel channel;
public:
  /**
   * Updates the OutputNetworkGeraet based on elapsed time.
   *
   * The default does nothing.
   * @param et the time, in milliseconds, since the previous call to update()
   */
  virtual void update(unsigned et) throw() { }
};
#endif /* NETWORK_GERAET_HXX_ */
<commit_msg>Add setChannel() function to OutputNetworkGeraet.<commit_after>/**
 * @file
 * @author Jason Lingle
 * @date 2012.02.03
 * @brief Contains the NetworkGeraet class
 */
#ifndef NETWORK_GERAET_HXX_
#define NETWORK_GERAET_HXX_

#include "antenna.hxx"
#include "network_connection.hxx"

/**
 * Defines the interface common to all input network Geräte.
 */
class InputNetworkGeraet: public AObject {
public:
  /**
   * Notifies the InputNetworkGeraet that it has received a packet.
   * @param seq the sequence number of the packet
   * @param data the payload of the packet, excluding sequence and channel
   * numbers
   * @param len the length of the payload
   */
  virtual void receive(NetworkConnection::seq_t seq,
                       const byte* data, unsigned len)
  throw() = 0;

  /**
   * Updates the InputNetworkGeraet based on elapsed time.
   *
   * The default does nothing.
   * @param et the time, in milliseconds, since the previous call to update()
   */
  virtual void update(unsigned et) throw() { }
};

/**
 * Defines the interface common to all output network Geräte.
 */
class OutputNetworkGeraet: public AObject {
protected:
  /**
   * The output channel to write to.
   */
  NetworkConnection::channel channel;
public:
  /**
   * Updates the OutputNetworkGeraet based on elapsed time.
   *
   * The default does nothing.
   * @param et the time, in milliseconds, since the previous call to update()
   */
  virtual void update(unsigned et) throw() { }

  /**
   * Sets the channel the Gerät outputs to.
   */
  void setChannel(NetworkConnection::channel chan) throw() {
    channel = chan;
  }
};
#endif /* NETWORK_GERAET_HXX_ */
<|endoftext|>


<commit_before>#include "Memory.h"

#include <vector>
#include <iostream>
#include <iomanip>
#include <cstdint>
#include <cassert>

#include <llvm/IR/GlobalVariable.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/IntrinsicInst.h>

#include "Type.h"
#include "Runtime.h"
#include "GasMeter.h"
#include "Endianness.h"
#include "RuntimeManager.h"

namespace dev
{
namespace eth
{
namespace jit
{

Memory::Memory(RuntimeManager& _runtimeManager, GasMeter& _gasMeter):
	RuntimeHelper(_runtimeManager),  // TODO: RuntimeHelper not needed
	m_gasMeter(_gasMeter)
{
	llvm::Type* resizeArgs[] = {Type::RuntimePtr, Type::WordPtr};
	m_resize = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, resizeArgs, false), llvm::Function::ExternalLinkage, "mem_resize", getModule());
	llvm::AttrBuilder attrBuilder;
	attrBuilder.addAttribute(llvm::Attribute::NoAlias).addAttribute(llvm::Attribute::NoCapture).addAttribute(llvm::Attribute::NonNull).addAttribute(llvm::Attribute::ReadOnly);
	m_resize->setAttributes(llvm::AttributeSet::get(m_resize->getContext(), 1, attrBuilder));

	m_require = createRequireFunc(_gasMeter);
	m_loadWord = createFunc(false, Type::Word, _gasMeter);
	m_storeWord = createFunc(true, Type::Word, _gasMeter);
	m_storeByte = createFunc(true, Type::Byte,  _gasMeter);
}

llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter)
{
	llvm::Type* argTypes[] = {Type::RuntimePtr, Type::Word, Type::Word};
	auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Void, argTypes, false), llvm::Function::PrivateLinkage, "mem.require", getModule());
	auto rt = func->arg_begin();
	rt->setName("rt");
	auto offset = rt->getNextNode();
	offset->setName("offset");
	auto size = offset->getNextNode();
	size->setName("size");

	auto preBB = llvm::BasicBlock::Create(func->getContext(), "Pre", func);
	auto checkBB = llvm::BasicBlock::Create(func->getContext(), "Check", func);
	auto resizeBB = llvm::BasicBlock::Create(func->getContext(), "Resize", func);
	auto returnBB = llvm::BasicBlock::Create(func->getContext(), "Return", func);

	InsertPointGuard guard(m_builder); // Restores insert point at function exit

	// BB "Pre": Ignore checks with size 0
	m_builder.SetInsertPoint(preBB);
	auto sizeIsZero = m_builder.CreateICmpEQ(size, Constant::get(0));
	m_builder.CreateCondBr(sizeIsZero, returnBB, checkBB);

	// BB "Check"
	m_builder.SetInsertPoint(checkBB);
	auto uaddWO = llvm::Intrinsic::getDeclaration(getModule(), llvm::Intrinsic::uadd_with_overflow, Type::Word);
	auto uaddRes = m_builder.CreateCall2(uaddWO, offset, size, "res");
	auto sizeRequired = m_builder.CreateExtractValue(uaddRes, 0, "sizeReq");
	auto overflow1 = m_builder.CreateExtractValue(uaddRes, 1, "overflow1");
	auto rtPtr = getRuntimeManager().getRuntimePtr();
	auto sizePtr = m_builder.CreateStructGEP(rtPtr, 4);
	auto currSize = m_builder.CreateLoad(sizePtr, "currSize");
	auto tooSmall = m_builder.CreateICmpULE(currSize, sizeRequired, "tooSmall");
	auto resizeNeeded = m_builder.CreateOr(tooSmall, overflow1, "resizeNeeded");
	m_builder.CreateCondBr(resizeNeeded, resizeBB, returnBB); // OPT branch weights?

	// BB "Resize"
	m_builder.SetInsertPoint(resizeBB);
	// Check gas first
	uaddRes = m_builder.CreateCall2(uaddWO, sizeRequired, Constant::get(31), "res");
	auto wordsRequired = m_builder.CreateExtractValue(uaddRes, 0);
	auto overflow2 = m_builder.CreateExtractValue(uaddRes, 1, "overflow2");
	auto overflow = m_builder.CreateOr(overflow1, overflow2, "overflow");
	wordsRequired = m_builder.CreateSelect(overflow, Constant::get(-1), wordsRequired);
	wordsRequired = m_builder.CreateUDiv(wordsRequired, Constant::get(32), "wordsReq");
	sizeRequired = m_builder.CreateMul(wordsRequired, Constant::get(32), "roundedSizeReq");
	auto words = m_builder.CreateUDiv(currSize, Constant::get(32), "words");	// size is always 32*k
	auto newWords = m_builder.CreateSub(wordsRequired, words, "addtionalWords");
	_gasMeter.countMemory(newWords);
	// Resize
	m_builder.CreateStore(sizeRequired, sizePtr);
	auto newData = m_builder.CreateCall2(m_resize, rt, sizePtr, "newData");
	auto dataPtr = m_builder.CreateStructGEP(rtPtr, 3);
	m_builder.CreateStore(newData, dataPtr);
	m_builder.CreateBr(returnBB);

	// BB "Return"
	m_builder.SetInsertPoint(returnBB);
	m_builder.CreateRetVoid();
	return func;
}

llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, GasMeter&)
{
	auto isWord = _valueType == Type::Word;

	llvm::Type* storeArgs[] = {Type::RuntimePtr, Type::Word, _valueType};
	llvm::Type* loadArgs[] = {Type::RuntimePtr, Type::Word};
	auto name = _isStore ? isWord ? "mstore" : "mstore8" : "mload";
	auto funcType = _isStore ? llvm::FunctionType::get(Type::Void, storeArgs, false) : llvm::FunctionType::get(Type::Word, loadArgs, false);
	auto func = llvm::Function::Create(funcType, llvm::Function::PrivateLinkage, name, getModule());

	InsertPointGuard guard(m_builder); // Restores insert point at function exit

	m_builder.SetInsertPoint(llvm::BasicBlock::Create(func->getContext(), {}, func));
	auto rt = func->arg_begin();
	rt->setName("rt");
	auto index = rt->getNextNode();
	index->setName("index");

	auto valueSize = _valueType->getPrimitiveSizeInBits() / 8;
	this->require(index, Constant::get(valueSize));
	auto ptr = getBytePtr(index);
	if (isWord)
		ptr = m_builder.CreateBitCast(ptr, Type::WordPtr, "wordPtr");
	if (_isStore)
	{
		llvm::Value* value = index->getNextNode();
		value->setName("value");
		if (isWord)
			value = Endianness::toBE(m_builder, value);
		m_builder.CreateStore(value, ptr);
		m_builder.CreateRetVoid();
	}
	else
	{
		llvm::Value* ret = m_builder.CreateLoad(ptr);
		ret = Endianness::toNative(m_builder, ret);
		m_builder.CreateRet(ret);
	}

	return func;
}

llvm::Value* Memory::loadWord(llvm::Value* _addr)
{
	return createCall(m_loadWord, {getRuntimeManager().getRuntimePtr(), _addr});
}

void Memory::storeWord(llvm::Value* _addr, llvm::Value* _word)
{
	createCall(m_storeWord, {getRuntimeManager().getRuntimePtr(), _addr, _word});
}

void Memory::storeByte(llvm::Value* _addr, llvm::Value* _word)
{
	auto byte = m_builder.CreateTrunc(_word, Type::Byte, "byte");
	createCall(m_storeByte, {getRuntimeManager().getRuntimePtr(), _addr, byte});
}

llvm::Value* Memory::getData()
{
	auto rtPtr = getRuntimeManager().getRuntimePtr();
	auto dataPtr = m_builder.CreateStructGEP(rtPtr, 3);
	return m_builder.CreateLoad(dataPtr, "data");
}

llvm::Value* Memory::getSize()
{
	auto rtPtr = getRuntimeManager().getRuntimePtr();
	auto sizePtr = m_builder.CreateStructGEP(rtPtr, 4);
	return m_builder.CreateLoad(sizePtr, "size");
}

llvm::Value* Memory::getBytePtr(llvm::Value* _index)
{
	return m_builder.CreateGEP(getData(), _index, "ptr");
}

void Memory::require(llvm::Value* _offset, llvm::Value* _size)
{
	createCall(m_require, {getRuntimeManager().getRuntimePtr(), _offset, _size});
}

void Memory::copyBytes(llvm::Value* _srcPtr, llvm::Value* _srcSize, llvm::Value* _srcIdx,
					   llvm::Value* _destMemIdx, llvm::Value* _reqBytes)
{
	require(_destMemIdx, _reqBytes);

	// Additional copy cost
	// TODO: This round ups to 32 happens in many places
	auto copyWords = m_builder.CreateUDiv(m_builder.CreateAdd(_reqBytes, Constant::get(31)), Constant::get(32));
	m_gasMeter.countCopy(copyWords);

	// Algorithm:
	// isOutsideData = idx256 >= size256
	// idx64  = trunc idx256
	// size64 = trunc size256
	// dataLeftSize = size64 - idx64  // safe if not isOutsideData
	// reqBytes64 = trunc _reqBytes   // require() handles large values
	// bytesToCopy0 = select(reqBytes64 > dataLeftSize, dataSizeLeft, reqBytes64)  // min
	// bytesToCopy = select(isOutsideData, 0, bytesToCopy0)

	auto isOutsideData = m_builder.CreateICmpUGE(_srcIdx, _srcSize);
	auto idx64 = m_builder.CreateTrunc(_srcIdx, Type::lowPrecision);
	auto size64 = m_builder.CreateTrunc(_srcSize, Type::lowPrecision);
	auto dataLeftSize = m_builder.CreateNUWSub(size64, idx64);
	auto reqBytes64 = m_builder.CreateTrunc(_reqBytes, Type::lowPrecision);
	auto outOfBound = m_builder.CreateICmpUGT(reqBytes64, dataLeftSize);
	auto bytesToCopyInner = m_builder.CreateSelect(outOfBound, dataLeftSize, reqBytes64);
	auto zero64 = llvm::ConstantInt::get(Type::lowPrecision, 0);	// TODO: Cache common constants
	auto bytesToCopy = m_builder.CreateSelect(isOutsideData, zero64, bytesToCopyInner);

	auto src = m_builder.CreateGEP(_srcPtr, idx64, "src");
	auto dst = m_builder.CreateGEP(getData(), _destMemIdx, "dst");
	m_builder.CreateMemCpy(dst, src, bytesToCopy, 0);
}

}
}
}

extern "C"
{
	using namespace dev::eth::jit;

	EXPORT byte* mem_resize(Runtime* _rt, i256* _size)	// TODO: Use uint64 as size OR use realloc in LLVM IR
	{
		auto size = _size->a; // Trunc to 64-bit
		auto& memory = _rt->getMemory();
		memory.resize(size);
		return memory.data();
	}
}
<commit_msg>Fix memory index having type i256<commit_after>#include "Memory.h"

#include <vector>
#include <iostream>
#include <iomanip>
#include <cstdint>
#include <cassert>

#include <llvm/IR/GlobalVariable.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/IntrinsicInst.h>

#include "Type.h"
#include "Runtime.h"
#include "GasMeter.h"
#include "Endianness.h"
#include "RuntimeManager.h"

namespace dev
{
namespace eth
{
namespace jit
{

Memory::Memory(RuntimeManager& _runtimeManager, GasMeter& _gasMeter):
	RuntimeHelper(_runtimeManager),  // TODO: RuntimeHelper not needed
	m_gasMeter(_gasMeter)
{
	llvm::Type* resizeArgs[] = {Type::RuntimePtr, Type::WordPtr};
	m_resize = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, resizeArgs, false), llvm::Function::ExternalLinkage, "mem_resize", getModule());
	llvm::AttrBuilder attrBuilder;
	attrBuilder.addAttribute(llvm::Attribute::NoAlias).addAttribute(llvm::Attribute::NoCapture).addAttribute(llvm::Attribute::NonNull).addAttribute(llvm::Attribute::ReadOnly);
	m_resize->setAttributes(llvm::AttributeSet::get(m_resize->getContext(), 1, attrBuilder));

	m_require = createRequireFunc(_gasMeter);
	m_loadWord = createFunc(false, Type::Word, _gasMeter);
	m_storeWord = createFunc(true, Type::Word, _gasMeter);
	m_storeByte = createFunc(true, Type::Byte,  _gasMeter);
}

llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter)
{
	llvm::Type* argTypes[] = {Type::RuntimePtr, Type::Word, Type::Word};
	auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Void, argTypes, false), llvm::Function::PrivateLinkage, "mem.require", getModule());
	auto rt = func->arg_begin();
	rt->setName("rt");
	auto offset = rt->getNextNode();
	offset->setName("offset");
	auto size = offset->getNextNode();
	size->setName("size");

	auto preBB = llvm::BasicBlock::Create(func->getContext(), "Pre", func);
	auto checkBB = llvm::BasicBlock::Create(func->getContext(), "Check", func);
	auto resizeBB = llvm::BasicBlock::Create(func->getContext(), "Resize", func);
	auto returnBB = llvm::BasicBlock::Create(func->getContext(), "Return", func);

	InsertPointGuard guard(m_builder); // Restores insert point at function exit

	// BB "Pre": Ignore checks with size 0
	m_builder.SetInsertPoint(preBB);
	auto sizeIsZero = m_builder.CreateICmpEQ(size, Constant::get(0));
	m_builder.CreateCondBr(sizeIsZero, returnBB, checkBB);

	// BB "Check"
	m_builder.SetInsertPoint(checkBB);
	auto uaddWO = llvm::Intrinsic::getDeclaration(getModule(), llvm::Intrinsic::uadd_with_overflow, Type::Word);
	auto uaddRes = m_builder.CreateCall2(uaddWO, offset, size, "res");
	auto sizeRequired = m_builder.CreateExtractValue(uaddRes, 0, "sizeReq");
	auto overflow1 = m_builder.CreateExtractValue(uaddRes, 1, "overflow1");
	auto rtPtr = getRuntimeManager().getRuntimePtr();
	auto sizePtr = m_builder.CreateStructGEP(rtPtr, 4);
	auto currSize = m_builder.CreateLoad(sizePtr, "currSize");
	auto tooSmall = m_builder.CreateICmpULE(currSize, sizeRequired, "tooSmall");
	auto resizeNeeded = m_builder.CreateOr(tooSmall, overflow1, "resizeNeeded");
	m_builder.CreateCondBr(resizeNeeded, resizeBB, returnBB); // OPT branch weights?

	// BB "Resize"
	m_builder.SetInsertPoint(resizeBB);
	// Check gas first
	uaddRes = m_builder.CreateCall2(uaddWO, sizeRequired, Constant::get(31), "res");
	auto wordsRequired = m_builder.CreateExtractValue(uaddRes, 0);
	auto overflow2 = m_builder.CreateExtractValue(uaddRes, 1, "overflow2");
	auto overflow = m_builder.CreateOr(overflow1, overflow2, "overflow");
	wordsRequired = m_builder.CreateSelect(overflow, Constant::get(-1), wordsRequired);
	wordsRequired = m_builder.CreateUDiv(wordsRequired, Constant::get(32), "wordsReq");
	sizeRequired = m_builder.CreateMul(wordsRequired, Constant::get(32), "roundedSizeReq");
	auto words = m_builder.CreateUDiv(currSize, Constant::get(32), "words");	// size is always 32*k
	auto newWords = m_builder.CreateSub(wordsRequired, words, "addtionalWords");
	_gasMeter.countMemory(newWords);
	// Resize
	m_builder.CreateStore(sizeRequired, sizePtr);
	auto newData = m_builder.CreateCall2(m_resize, rt, sizePtr, "newData");
	auto dataPtr = m_builder.CreateStructGEP(rtPtr, 3);
	m_builder.CreateStore(newData, dataPtr);
	m_builder.CreateBr(returnBB);

	// BB "Return"
	m_builder.SetInsertPoint(returnBB);
	m_builder.CreateRetVoid();
	return func;
}

llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, GasMeter&)
{
	auto isWord = _valueType == Type::Word;

	llvm::Type* storeArgs[] = {Type::RuntimePtr, Type::Word, _valueType};
	llvm::Type* loadArgs[] = {Type::RuntimePtr, Type::Word};
	auto name = _isStore ? isWord ? "mstore" : "mstore8" : "mload";
	auto funcType = _isStore ? llvm::FunctionType::get(Type::Void, storeArgs, false) : llvm::FunctionType::get(Type::Word, loadArgs, false);
	auto func = llvm::Function::Create(funcType, llvm::Function::PrivateLinkage, name, getModule());

	InsertPointGuard guard(m_builder); // Restores insert point at function exit

	m_builder.SetInsertPoint(llvm::BasicBlock::Create(func->getContext(), {}, func));
	auto rt = func->arg_begin();
	rt->setName("rt");
	auto index = rt->getNextNode();
	index->setName("index");

	auto valueSize = _valueType->getPrimitiveSizeInBits() / 8;
	this->require(index, Constant::get(valueSize));
	auto ptr = getBytePtr(index);
	if (isWord)
		ptr = m_builder.CreateBitCast(ptr, Type::WordPtr, "wordPtr");
	if (_isStore)
	{
		llvm::Value* value = index->getNextNode();
		value->setName("value");
		if (isWord)
			value = Endianness::toBE(m_builder, value);
		m_builder.CreateStore(value, ptr);
		m_builder.CreateRetVoid();
	}
	else
	{
		llvm::Value* ret = m_builder.CreateLoad(ptr);
		ret = Endianness::toNative(m_builder, ret);
		m_builder.CreateRet(ret);
	}

	return func;
}

llvm::Value* Memory::loadWord(llvm::Value* _addr)
{
	return createCall(m_loadWord, {getRuntimeManager().getRuntimePtr(), _addr});
}

void Memory::storeWord(llvm::Value* _addr, llvm::Value* _word)
{
	createCall(m_storeWord, {getRuntimeManager().getRuntimePtr(), _addr, _word});
}

void Memory::storeByte(llvm::Value* _addr, llvm::Value* _word)
{
	auto byte = m_builder.CreateTrunc(_word, Type::Byte, "byte");
	createCall(m_storeByte, {getRuntimeManager().getRuntimePtr(), _addr, byte});
}

llvm::Value* Memory::getData()
{
	auto rtPtr = getRuntimeManager().getRuntimePtr();
	auto dataPtr = m_builder.CreateStructGEP(rtPtr, 3);
	return m_builder.CreateLoad(dataPtr, "data");
}

llvm::Value* Memory::getSize()
{
	auto rtPtr = getRuntimeManager().getRuntimePtr();
	auto sizePtr = m_builder.CreateStructGEP(rtPtr, 4);
	return m_builder.CreateLoad(sizePtr, "size");
}

llvm::Value* Memory::getBytePtr(llvm::Value* _index)
{
	auto idx = m_builder.CreateTrunc(_index, Type::Size, "idx"); // Never allow memory index be a type bigger than i64
	return m_builder.CreateGEP(getData(), idx, "ptr");
}

void Memory::require(llvm::Value* _offset, llvm::Value* _size)
{
	createCall(m_require, {getRuntimeManager().getRuntimePtr(), _offset, _size});
}

void Memory::copyBytes(llvm::Value* _srcPtr, llvm::Value* _srcSize, llvm::Value* _srcIdx,
					   llvm::Value* _destMemIdx, llvm::Value* _reqBytes)
{
	require(_destMemIdx, _reqBytes);

	// Additional copy cost
	// TODO: This round ups to 32 happens in many places
	auto copyWords = m_builder.CreateUDiv(m_builder.CreateAdd(_reqBytes, Constant::get(31)), Constant::get(32));
	m_gasMeter.countCopy(copyWords);

	// Algorithm:
	// isOutsideData = idx256 >= size256
	// idx64  = trunc idx256
	// size64 = trunc size256
	// dataLeftSize = size64 - idx64  // safe if not isOutsideData
	// reqBytes64 = trunc _reqBytes   // require() handles large values
	// bytesToCopy0 = select(reqBytes64 > dataLeftSize, dataSizeLeft, reqBytes64)  // min
	// bytesToCopy = select(isOutsideData, 0, bytesToCopy0)

	auto isOutsideData = m_builder.CreateICmpUGE(_srcIdx, _srcSize);
	auto idx64 = m_builder.CreateTrunc(_srcIdx, Type::lowPrecision);
	auto size64 = m_builder.CreateTrunc(_srcSize, Type::lowPrecision);
	auto dataLeftSize = m_builder.CreateNUWSub(size64, idx64);
	auto reqBytes64 = m_builder.CreateTrunc(_reqBytes, Type::lowPrecision);
	auto outOfBound = m_builder.CreateICmpUGT(reqBytes64, dataLeftSize);
	auto bytesToCopyInner = m_builder.CreateSelect(outOfBound, dataLeftSize, reqBytes64);
	auto zero64 = llvm::ConstantInt::get(Type::lowPrecision, 0);	// TODO: Cache common constants
	auto bytesToCopy = m_builder.CreateSelect(isOutsideData, zero64, bytesToCopyInner);

	auto src = m_builder.CreateGEP(_srcPtr, idx64, "src");
	auto dstIdx = m_builder.CreateTrunc(_destMemIdx, Type::Size, "dstIdx"); // Never allow memory index be a type bigger than i64
	auto dst = m_builder.CreateGEP(getData(), dstIdx, "dst");
	m_builder.CreateMemCpy(dst, src, bytesToCopy, 0);
}

}
}
}

extern "C"
{
	using namespace dev::eth::jit;

	EXPORT byte* mem_resize(Runtime* _rt, i256* _size)	// TODO: Use uint64 as size OR use realloc in LLVM IR
	{
		auto size = _size->a; // Trunc to 64-bit
		auto& memory = _rt->getMemory();
		memory.resize(size);
		return memory.data();
	}
}
<|endoftext|>


<commit_before>#include "ros/ros.h"

#include "sensor_msgs/JointState.h"
#include "nav_msgs/Odometry.h"

#include <message_filters/subscriber.h>
#include <message_filters/synchronizer.h>
#include <message_filters/sync_policies/approximate_time.h>

#include <tf/transform_listener.h>
#include <tf/transform_broadcaster.h>

#include <string>
#include <utility>

// robot's index in ROS ecosystem (if multiple instances)
int robot_id = 0;

// publisher in IMU for imu message
ros::Publisher publisher;

double WHEELS_HALF_SPACING = 0;
double WHEEL_RADIUS = 0.1;

double pos_x = 0;
double pos_y = 0;
double pos_th = 0;
ros::Time last_time;

// calculates inverse kinematic value of robot heading with differencial drive
double getYaw(const double velRight, const double velLeft) {
  return WHEEL_RADIUS * (velRight - velLeft) / WHEELS_HALF_SPACING;
}

void setWheelSpacing() {
  // tf listener for calculation of wheel spacing
  tf::TransformListener listener;
  tf::StampedTransform transform;
  // get length in between wheels
  try {
    listener.waitForTransform(std::to_string(robot_id) + "/base/joint1",
                              std::to_string(robot_id) + "/base/joint0",
                              ros::Time::now(), ros::Duration(3.0));
    listener.lookupTransform(std::to_string(robot_id) + "/base/joint1",
                             std::to_string(robot_id) + "/base/joint0",
                             ros::Time(0), transform);
    WHEELS_HALF_SPACING = transform.getOrigin().absolute().getY() / 2;
    ROS_INFO("DPL: motor_controler WHEELS_HALF_SPACING: %f",
             WHEELS_HALF_SPACING);

  } catch (tf::TransformException ex) {
    ROS_ERROR("Problem with transformation between wheels: %s", ex.what());
  }
}

void odomData_cb(const sensor_msgs::JointState::ConstPtr &left_motor_msg,
                 const sensor_msgs::JointState::ConstPtr &right_motor_msg) {
  nav_msgs::Odometry odom_msg;
  double yaw;
  double x_speed;
  double dt;

  dt = (left_motor_msg->header.stamp - last_time).toSec();
  // y_speed = 0
  x_speed = WHEEL_RADIUS *
            (right_motor_msg->velocity[0] + left_motor_msg->velocity[0]) / 2;
  yaw = getYaw(right_motor_msg->velocity[0], left_motor_msg->velocity[0]);
  // move old point in 2D space to new predicted position and an angle
  pos_x += (x_speed * cos(yaw)) * dt;
  pos_y += (x_speed * sin(yaw)) * dt;
  pos_th += yaw * dt;
  geometry_msgs::Quaternion odom_quat = tf::createQuaternionMsgFromYaw(pos_th);

  // create odom msg
  odom_msg.header.frame_id = std::to_string(robot_id) + "/odom";
  odom_msg.header.stamp = last_time;
  odom_msg.pose.pose.position.x = pos_x;
  odom_msg.pose.pose.position.y = pos_y;
  odom_msg.pose.pose.orientation = odom_quat;
  odom_msg.child_frame_id = std::to_string(robot_id) + "/base_link";
  odom_msg.twist.twist.linear.x = x_speed;
  odom_msg.twist.twist.angular.z = yaw;

  // create odom frame id broadcaster to tf tree
  geometry_msgs::TransformStamped odom_trans;
  odom_trans.header.stamp = left_motor_msg->header.stamp;
  odom_trans.header.frame_id = std::to_string(robot_id) + "/odom";
  odom_trans.child_frame_id = std::to_string(robot_id) + "/base_link";
  odom_trans.transform.translation.x = pos_x;
  odom_trans.transform.translation.y = pos_y;
  odom_trans.transform.translation.z = 0.0;
  odom_trans.transform.rotation = odom_quat;

  // broadcaster of odom frame_id to /tf
  tf::TransformBroadcaster odom_broadcaster;
  odom_broadcaster.sendTransform(std::move(odom_trans));
  publisher.publish(odom_msg);

  last_time = left_motor_msg->header.stamp;
}

int main(int argc, char **argv) {
  ros::init(argc, argv, "odometryProvider");
  ros::NodeHandle n;
  n.getParam("robot_id", robot_id);
  last_time = ros::Time::now();
  setWheelSpacing();

  // subscribers to motors' states and imu
  message_filters::Subscriber<sensor_msgs::JointState> left_motor_sub(
      n, "hal/leftMotor/getState", 1000);
  message_filters::Subscriber<sensor_msgs::JointState> right_motor_sub(
      n, "hal/rightMotor/getState", 1000);

  // sync messages using approximate alghorithm
  constexpr int allowed_delay = 10;
  typedef message_filters::sync_policies::ApproximateTime<
      sensor_msgs::JointState, sensor_msgs::JointState> OdomSyncPolicy;
  message_filters::Synchronizer<OdomSyncPolicy> odom_processor(
      OdomSyncPolicy(allowed_delay), left_motor_sub, right_motor_sub);
  odom_processor.registerCallback(odomData_cb);

  // publish fused message
  publisher = n.advertise<nav_msgs::Odometry>("odom", 1000);

  ROS_INFO("DPL: imuProvider initialized");

  // runs event loop
  ros::spin();

  return 0;
}
<commit_msg>fix odometry rotations and y coordinate calc<commit_after>#include "ros/ros.h"

#include "sensor_msgs/JointState.h"
#include "nav_msgs/Odometry.h"

#include <message_filters/subscriber.h>
#include <message_filters/synchronizer.h>
#include <message_filters/sync_policies/approximate_time.h>

#include <tf/transform_listener.h>
#include <tf/transform_broadcaster.h>

#include <string>
#include <utility>

// robot's index in ROS ecosystem (if multiple instances)
int robot_id = 0;

// publisher in IMU for imu message
ros::Publisher publisher;

double WHEELS_HALF_SPACING = 0;
double WHEEL_RADIUS = 0.1;

double pos_x = 0;
double pos_y = 0;
double pos_th = 0;
ros::Time last_time;

// calculates inverse kinematic value of robot heading with differencial drive
double getYaw(const double velRight, const double velLeft) {
  return WHEEL_RADIUS * (velRight - velLeft) / (2*WHEELS_HALF_SPACING);
}

void setWheelSpacing() {
  // tf listener for calculation of wheel spacing
  tf::TransformListener listener;
  tf::StampedTransform transform;
  // get length in between wheels
  try {
    listener.waitForTransform(std::to_string(robot_id) + "/base/joint1",
                              std::to_string(robot_id) + "/base/joint0",
                              ros::Time::now(), ros::Duration(3.0));
    listener.lookupTransform(std::to_string(robot_id) + "/base/joint1",
                             std::to_string(robot_id) + "/base/joint0",
                             ros::Time(0), transform);
    WHEELS_HALF_SPACING = transform.getOrigin().absolute().getY() / 2;
    ROS_INFO("DPL: motor_controler WHEELS_HALF_SPACING: %f",
             WHEELS_HALF_SPACING);

  } catch (tf::TransformException ex) {
    ROS_ERROR("Problem with transformation between wheels: %s", ex.what());
  }
}

void odomData_cb(const sensor_msgs::JointState::ConstPtr &left_motor_msg,
                 const sensor_msgs::JointState::ConstPtr &right_motor_msg) {
  nav_msgs::Odometry odom_msg;
  double yaw;
  double x_speed;
  double dt;

  dt = (left_motor_msg->header.stamp - last_time).toSec();
  // y_speed = 0
  x_speed = WHEEL_RADIUS *
            (right_motor_msg->velocity[0] + left_motor_msg->velocity[0]) / 2;
  yaw = getYaw(right_motor_msg->velocity[0], left_motor_msg->velocity[0]);
  // move old point in 2D space to new predicted position and an angle
  pos_x += (x_speed * cos(pos_th)) * dt;
  pos_y += (x_speed * sin(pos_th)) * dt;
  pos_th += yaw * dt;
  geometry_msgs::Quaternion odom_quat = tf::createQuaternionMsgFromYaw(pos_th);

  // create odom msg
  odom_msg.header.frame_id = std::to_string(robot_id) + "/odom";
  odom_msg.header.stamp = last_time;
  odom_msg.pose.pose.position.x = pos_x;
  odom_msg.pose.pose.position.y = pos_y;
  odom_msg.pose.pose.orientation = odom_quat;
  odom_msg.child_frame_id = std::to_string(robot_id) + "/base_link";
  odom_msg.twist.twist.linear.x = x_speed;
  odom_msg.twist.twist.angular.z = yaw;

  // create odom frame id broadcaster to tf tree
  geometry_msgs::TransformStamped odom_trans;
  odom_trans.header.stamp = left_motor_msg->header.stamp;
  odom_trans.header.frame_id = std::to_string(robot_id) + "/odom";
  odom_trans.child_frame_id = std::to_string(robot_id) + "/base_link";
  odom_trans.transform.translation.x = pos_x;
  odom_trans.transform.translation.y = pos_y;
  odom_trans.transform.translation.z = 0.0;
  odom_trans.transform.rotation = odom_quat;

  // broadcaster of odom frame_id to /tf
  tf::TransformBroadcaster odom_broadcaster;
  odom_broadcaster.sendTransform(std::move(odom_trans));
  publisher.publish(odom_msg);

  last_time = left_motor_msg->header.stamp;
}

int main(int argc, char **argv) {
  ros::init(argc, argv, "odometryProvider");
  ros::NodeHandle n;
  n.getParam("robot_id", robot_id);
  last_time = ros::Time::now();
  setWheelSpacing();

  // subscribers to motors' states and imu
  message_filters::Subscriber<sensor_msgs::JointState> left_motor_sub(
      n, "hal/leftMotor/getState", 1000);
  message_filters::Subscriber<sensor_msgs::JointState> right_motor_sub(
      n, "hal/rightMotor/getState", 1000);

  // sync messages using approximate alghorithm
  constexpr int allowed_delay = 10;
  typedef message_filters::sync_policies::ApproximateTime<
      sensor_msgs::JointState, sensor_msgs::JointState> OdomSyncPolicy;
  message_filters::Synchronizer<OdomSyncPolicy> odom_processor(
      OdomSyncPolicy(allowed_delay), left_motor_sub, right_motor_sub);
  odom_processor.registerCallback(odomData_cb);

  // publish fused message
  publisher = n.advertise<nav_msgs::Odometry>("odom", 1000);

  ROS_INFO("DPL: imuProvider initialized");

  // runs event loop
  ros::spin();

  return 0;
}
<|endoftext|>


<commit_before>// Filename: LinearSolver.C
// Created on 09 Sep 2003 by Boyce Griffith
//
// Copyright (c) 2002-2010, Boyce Griffith
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//    * Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//
//    * Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in the
//      documentation and/or other materials provided with the distribution.
//
//    * Neither the name of New York University nor the names of its
//      contributors may be used to endorse or promote products derived from
//      this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#include "LinearSolver.h"

/////////////////////////////// INCLUDES /////////////////////////////////////

#ifndef included_IBTK_config
#include <IBTK_config.h>
#define included_IBTK_config
#endif

#ifndef included_SAMRAI_config
#include <SAMRAI_config.h>
#define included_SAMRAI_config
#endif

// IBTK INCLUDES
#include <ibtk/namespaces.h>

/////////////////////////////// NAMESPACE ////////////////////////////////////

namespace IBTK
{
/////////////////////////////// STATIC ///////////////////////////////////////

/////////////////////////////// PUBLIC ///////////////////////////////////////

LinearSolver::LinearSolver(
    const std::string& object_name,
    bool homogeneous_bc)
    : GeneralSolver(object_name, homogeneous_bc),
      d_nullspace_contains_constant_vec(false),
      d_nullspace_basis_vecs(),
      d_initial_guess_nonzero(true),
      d_rel_residual_tol(1.0e-5),
      d_abs_residual_tol(1.0e-50),
      d_max_iterations(10000),
      d_current_iterations(0),
      d_current_residual_norm(std::numeric_limits<double>::quiet_NaN())
{
    // intentionally blank
    return;
}// LinearSolver()

LinearSolver::~LinearSolver()
{
    // intentionally blank
    return;
}// ~LinearSolver()

void
LinearSolver::setNullspace(
    const bool nullspace_containsconstant_vec,
    const std::vector<Pointer<SAMRAIVectorReal<NDIM,double> > >& nullspace_basis_vecs)
{
    d_nullspace_contains_constant_vec = nullspace_containsconstant_vec;
    d_nullspace_basis_vecs = nullspace_basis_vecs;
    return;
}// setNullspace

void
LinearSolver::setInitialGuessNonzero(
    bool initial_guess_nonzero)
{
    d_initial_guess_nonzero = initial_guess_nonzero;
    return;
}// setInitialGuessNonzero

bool
LinearSolver::getNullspaceContainsConstantVector() const
{
    return d_nullspace_contains_constant_vec;
}// getNullspaceContainsConstantVector

const std::vector<Pointer<SAMRAIVectorReal<NDIM,double> > >&
LinearSolver::getNullspaceBasisVectors() const
{
    return d_nullspace_basis_vecs;
}// getNullspaceBasisVectors

bool
LinearSolver::getInitialGuessNonzero() const
{
    return d_initial_guess_nonzero;
}// getInitialGuessNonzero

void
LinearSolver::setMaxIterations(
    int max_iterations)
{
    d_max_iterations = max_iterations;
    return;
}// setMaxIterations

int
LinearSolver::getMaxIterations() const
{
    return d_max_iterations;
}// getMaxIterations

void
LinearSolver::setAbsoluteTolerance(
    double abs_residual_tol)
{
    d_abs_residual_tol = abs_residual_tol;
    return;
}// setAbsoluteTolerance

double
LinearSolver::getAbsoluteTolerance() const
{
    return d_abs_residual_tol;
}// getAbsoluteTolerance

void
LinearSolver::setRelativeTolerance(
    double rel_residual_tol)
{
    d_rel_residual_tol = rel_residual_tol;
    return;
}// setRelativeTolerance

double
LinearSolver::getRelativeTolerance() const
{
    return d_rel_residual_tol;
}// getRelativeTolerance

int
LinearSolver::getNumIterations() const
{
    return d_current_iterations;
}// getNumIterations

double
LinearSolver::getResidualNorm() const
{
    return d_current_residual_norm;
}// getResidualNorm

void
LinearSolver::printClassData(
    std::ostream& stream)
{
    GeneralSolver::printClassData(stream);
    stream << "initial_guess_nonzero = " << d_initial_guess_nonzero << "\n"
           << "rel_residual_tol = " << d_rel_residual_tol << "\n"
           << "abs_residual_tol = " << d_abs_residual_tol << "\n"
           << "max_iterations = " << d_max_iterations << "\n"
           << "current_iterations = " << d_current_iterations << "\n"
           << "current_residual_norm = " << d_current_residual_norm << "\n"
           << "nullspace_contains_constant_vec = " << d_nullspace_contains_constant_vec << "\n"
           << "nullspace_basis_vecs.size() = " << d_nullspace_basis_vecs.size() << "\n";
    return;
}// printClassData

/////////////////////////////// PRIVATE //////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////

}// namespace IBTK

//////////////////////////////////////////////////////////////////////////////
<commit_msg>branch boyceg: fixed initialization order in LinearSolver.C<commit_after>// Filename: LinearSolver.C
// Created on 09 Sep 2003 by Boyce Griffith
//
// Copyright (c) 2002-2010, Boyce Griffith
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//    * Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//
//    * Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in the
//      documentation and/or other materials provided with the distribution.
//
//    * Neither the name of New York University nor the names of its
//      contributors may be used to endorse or promote products derived from
//      this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#include "LinearSolver.h"

/////////////////////////////// INCLUDES /////////////////////////////////////

#ifndef included_IBTK_config
#include <IBTK_config.h>
#define included_IBTK_config
#endif

#ifndef included_SAMRAI_config
#include <SAMRAI_config.h>
#define included_SAMRAI_config
#endif

// IBTK INCLUDES
#include <ibtk/namespaces.h>

/////////////////////////////// NAMESPACE ////////////////////////////////////

namespace IBTK
{
/////////////////////////////// STATIC ///////////////////////////////////////

/////////////////////////////// PUBLIC ///////////////////////////////////////

LinearSolver::LinearSolver(
    const std::string& object_name,
    bool homogeneous_bc)
    : GeneralSolver(object_name, homogeneous_bc),
      d_initial_guess_nonzero(true),
      d_rel_residual_tol(1.0e-5),
      d_abs_residual_tol(1.0e-50),
      d_max_iterations(10000),
      d_current_iterations(0),
      d_current_residual_norm(std::numeric_limits<double>::quiet_NaN()),
      d_nullspace_contains_constant_vec(false),
      d_nullspace_basis_vecs()
{
    // intentionally blank
    return;
}// LinearSolver()

LinearSolver::~LinearSolver()
{
    // intentionally blank
    return;
}// ~LinearSolver()

void
LinearSolver::setNullspace(
    const bool nullspace_containsconstant_vec,
    const std::vector<Pointer<SAMRAIVectorReal<NDIM,double> > >& nullspace_basis_vecs)
{
    d_nullspace_contains_constant_vec = nullspace_containsconstant_vec;
    d_nullspace_basis_vecs = nullspace_basis_vecs;
    return;
}// setNullspace

void
LinearSolver::setInitialGuessNonzero(
    bool initial_guess_nonzero)
{
    d_initial_guess_nonzero = initial_guess_nonzero;
    return;
}// setInitialGuessNonzero

bool
LinearSolver::getNullspaceContainsConstantVector() const
{
    return d_nullspace_contains_constant_vec;
}// getNullspaceContainsConstantVector

const std::vector<Pointer<SAMRAIVectorReal<NDIM,double> > >&
LinearSolver::getNullspaceBasisVectors() const
{
    return d_nullspace_basis_vecs;
}// getNullspaceBasisVectors

bool
LinearSolver::getInitialGuessNonzero() const
{
    return d_initial_guess_nonzero;
}// getInitialGuessNonzero

void
LinearSolver::setMaxIterations(
    int max_iterations)
{
    d_max_iterations = max_iterations;
    return;
}// setMaxIterations

int
LinearSolver::getMaxIterations() const
{
    return d_max_iterations;
}// getMaxIterations

void
LinearSolver::setAbsoluteTolerance(
    double abs_residual_tol)
{
    d_abs_residual_tol = abs_residual_tol;
    return;
}// setAbsoluteTolerance

double
LinearSolver::getAbsoluteTolerance() const
{
    return d_abs_residual_tol;
}// getAbsoluteTolerance

void
LinearSolver::setRelativeTolerance(
    double rel_residual_tol)
{
    d_rel_residual_tol = rel_residual_tol;
    return;
}// setRelativeTolerance

double
LinearSolver::getRelativeTolerance() const
{
    return d_rel_residual_tol;
}// getRelativeTolerance

int
LinearSolver::getNumIterations() const
{
    return d_current_iterations;
}// getNumIterations

double
LinearSolver::getResidualNorm() const
{
    return d_current_residual_norm;
}// getResidualNorm

void
LinearSolver::printClassData(
    std::ostream& stream)
{
    GeneralSolver::printClassData(stream);
    stream << "initial_guess_nonzero = " << d_initial_guess_nonzero << "\n"
           << "rel_residual_tol = " << d_rel_residual_tol << "\n"
           << "abs_residual_tol = " << d_abs_residual_tol << "\n"
           << "max_iterations = " << d_max_iterations << "\n"
           << "current_iterations = " << d_current_iterations << "\n"
           << "current_residual_norm = " << d_current_residual_norm << "\n"
           << "nullspace_contains_constant_vec = " << d_nullspace_contains_constant_vec << "\n"
           << "nullspace_basis_vecs.size() = " << d_nullspace_basis_vecs.size() << "\n";
    return;
}// printClassData

/////////////////////////////// PRIVATE //////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////

}// namespace IBTK

//////////////////////////////////////////////////////////////////////////////
<|endoftext|>


<commit_before>#include "EndScreen.h"

EndScreen::EndScreen()
{
	currentScene = endscreenNS::EXPLODE;
	D3DXMatrixIdentity(&worldMatrix);
}

EndScreen::~EndScreen()
{

}

void EndScreen::initialize(Graphics* g, Input* i, Audio* a, rapidjson::Document& doc, float* dT)
{
	D3DXVECTOR3 pos3D;
	State::initialize(g, i, a, doc, dT);
	Player temp = Player();

	graphics->camera->pointInWorld(pos3D, sqr1Pos, endscreenNS::z);
	if (temp.winner == 1)
		sqr1 = new Player(pos3D, D3DXVECTOR3(2, 2, 2), D3DXVECTOR3(1, 1, 1), D3DXVECTOR3(240, 240, 0));
	else
		sqr1 = new Player(pos3D, D3DXVECTOR3(2, 2, 2), D3DXVECTOR3(1, 1, 1), D3DXVECTOR3(0, 240, 240));
	graphics->camera->pointInWorld(pos3D, sqr2Pos, endscreenNS::z);
	if (temp.winner == 2)
		sqr2 = new Player(pos3D, D3DXVECTOR3(2, 2, 2), D3DXVECTOR3(1, 1, 1), D3DXVECTOR3(0, 240, 240));
	else
		sqr2 = new Player(pos3D, D3DXVECTOR3(2, 2, 2), D3DXVECTOR3(1, 1, 1), D3DXVECTOR3(240, 240, 0));

	sqr1->init(g, i);
	sqr2->init(g, i);
	audio->stopCue(BGMRand);
	State::initialize(g, i, a, doc, dT);
}

void EndScreen::update()
{
	if (input->getKeyState(controls.at(CONTROL_ENTER)))
	{
		nextState = stateNS::REVERT;
		pNextState = &nextState;
	}
	else
	{
		switch (currentScene)
		{
		case endscreenNS::EXPLODE:
			sqr1->velocity.x -= *deltaTime * endscreenNS::speed;
			sqr1->controlled = true;
			sqr2->velocity.x += *deltaTime * endscreenNS::speed;
			sqr2->controlled = true;
			currentScene = endscreenNS::RESPAWN;
			break;

		case endscreenNS::RESPAWN:
			if (sqr1->alive && sqr2->alive)
			{
				D3DXVECTOR3 pos3D;

				graphics->camera->pointInWorld(pos3D, sqr1Pos, endscreenNS::z);
				sqr1->pos.x = pos3D.x;
				sqr1->pos.y = pos3D.y;
				sqr1->health++;

				graphics->camera->pointInWorld(pos3D, sqr2Pos, endscreenNS::z);
				sqr2->pos.x = pos3D.x;
				sqr2->pos.y = pos3D.y;
				sqr2->health++;

				currentScene = endscreenNS::EXPLODE;
			}
			break;
		}

		graphics->camera->update(*deltaTime);
		sqr1->update(*deltaTime, qEnvironmentObj);
		sqr2->update(*deltaTime, qEnvironmentObj);

		for (int i = 0; i < qEnvironmentObj.size(); ++i)
		{
			if (qEnvironmentObj[i]->objectType == OBJECT_TYPE_QLINE) {
				QLine* temp = (QLine*)qEnvironmentObj[i];
				temp->update(*deltaTime, qEnvironmentObj);
			}
		}
	}
}

void EndScreen::render()
{
	Font f;

	f = fonts.at(fontsNS::HEADING1);

	// Set Title Screen
	if (sqr1->winner == 1)
	{
		f.print(
			GAME_WIDTH / 2 - f.getTotalWidth("GAME OVER") / 2,
			GAME_HEIGHT / 5,
			fontNS::YELLOW,
			"Player 1 wins");
	}
	else if (sqr2->winner == 2)
	{
		f.print(
			GAME_WIDTH / 2 - f.getTotalWidth("GAME OVER") / 2,
			GAME_HEIGHT / 5,
			fontNS::BLUE,
			"Player 2 wins");
	}

	// Set Fonts for Options
	f = fonts.at(fontsNS::END_SCREEN);

	f.print(
		GAME_WIDTH / 2 - f.getTotalWidth(("> Return")) / 2,
		GAME_HEIGHT / 2,
		"> Return");

	for (int i = 0; i < qEnvironmentObj.size(); i++) {
		qEnvironmentObj[i]->draw(worldMatrix);
	}
	sqr1->draw(worldMatrix);
	sqr2->draw(worldMatrix);
}<commit_msg>Fix font issue at game over screen<commit_after>#include "EndScreen.h"

EndScreen::EndScreen()
{
	currentScene = endscreenNS::EXPLODE;
	D3DXMatrixIdentity(&worldMatrix);
}

EndScreen::~EndScreen()
{

}

void EndScreen::initialize(Graphics* g, Input* i, Audio* a, rapidjson::Document& doc, float* dT)
{
	D3DXVECTOR3 pos3D;
	State::initialize(g, i, a, doc, dT);
	Player temp = Player();

	graphics->camera->pointInWorld(pos3D, sqr1Pos, endscreenNS::z);
	if (temp.winner == 1)
		sqr1 = new Player(pos3D, D3DXVECTOR3(2, 2, 2), D3DXVECTOR3(1, 1, 1), D3DXVECTOR3(240, 240, 0));
	else
		sqr1 = new Player(pos3D, D3DXVECTOR3(2, 2, 2), D3DXVECTOR3(1, 1, 1), D3DXVECTOR3(0, 240, 240));
	graphics->camera->pointInWorld(pos3D, sqr2Pos, endscreenNS::z);
	if (temp.winner == 2)
		sqr2 = new Player(pos3D, D3DXVECTOR3(2, 2, 2), D3DXVECTOR3(1, 1, 1), D3DXVECTOR3(0, 240, 240));
	else
		sqr2 = new Player(pos3D, D3DXVECTOR3(2, 2, 2), D3DXVECTOR3(1, 1, 1), D3DXVECTOR3(240, 240, 0));

	sqr1->init(g, i);
	sqr2->init(g, i);
	audio->stopCue(BGMRand);
	State::initialize(g, i, a, doc, dT);
}

void EndScreen::update()
{
	if (input->getKeyState(controls.at(CONTROL_ENTER)))
	{
		nextState = stateNS::REVERT;
		pNextState = &nextState;
	}
	else
	{
		switch (currentScene)
		{
		case endscreenNS::EXPLODE:
			sqr1->velocity.x -= *deltaTime * endscreenNS::speed;
			sqr1->controlled = true;
			sqr2->velocity.x += *deltaTime * endscreenNS::speed;
			sqr2->controlled = true;
			currentScene = endscreenNS::RESPAWN;
			break;

		case endscreenNS::RESPAWN:
			if (sqr1->alive && sqr2->alive)
			{
				D3DXVECTOR3 pos3D;

				graphics->camera->pointInWorld(pos3D, sqr1Pos, endscreenNS::z);
				sqr1->pos.x = pos3D.x;
				sqr1->pos.y = pos3D.y;
				sqr1->health++;

				graphics->camera->pointInWorld(pos3D, sqr2Pos, endscreenNS::z);
				sqr2->pos.x = pos3D.x;
				sqr2->pos.y = pos3D.y;
				sqr2->health++;

				currentScene = endscreenNS::EXPLODE;
			}
			break;
		}

		graphics->camera->update(*deltaTime);
		sqr1->update(*deltaTime, qEnvironmentObj);
		sqr2->update(*deltaTime, qEnvironmentObj);

		for (int i = 0; i < qEnvironmentObj.size(); ++i)
		{
			if (qEnvironmentObj[i]->objectType == OBJECT_TYPE_QLINE) {
				QLine* temp = (QLine*)qEnvironmentObj[i];
				temp->update(*deltaTime, qEnvironmentObj);
			}
		}
	}
}

void EndScreen::render()
{
	Font f;

	f = fonts.at(fontsNS::HEADING1);

	// Set Title Screen
	if (sqr1->winner == 1)
	{
		f.print(
			GAME_WIDTH / 2 - f.getTotalWidth("Player 1 wins") / 2,
			GAME_HEIGHT / 5,
			fontNS::YELLOW,
			"Player 1 wins");
	}
	else if (sqr2->winner == 2)
	{
		f.print(
			GAME_WIDTH / 2 - f.getTotalWidth("Player 2 wins") / 2,
			GAME_HEIGHT / 5,
			fontNS::BLUE,
			"Player 2 wins");
	}

	// Set Fonts for Options
	f = fonts.at(fontsNS::END_SCREEN);

	f.print(
		GAME_WIDTH / 2 - f.getTotalWidth(("Press Enter to Exit")) / 2,
		GAME_HEIGHT / 2,
		"Press Enter to Exit");

	for (int i = 0; i < qEnvironmentObj.size(); i++) {
		qEnvironmentObj[i]->draw(worldMatrix);
	}
	sqr1->draw(worldMatrix);
	sqr2->draw(worldMatrix);
}<|endoftext|>


<commit_before>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2006-2007 Torsten Rahn <tackat@kde.org>"
// Copyright 2007      Inge Wallin  <ingwa@kde.org>"
//

#include "QtMainWindow.h"

#include <QtCore/QSettings>
#include <QtGui/QCloseEvent>

#include <QtGui/QAction>
#include <QtGui/QLabel>
#include <QtGui/QWhatsThis>
#include <QtGui/QApplication>
#include <QtGui/QIcon>
#include <QtGui/QMenuBar>
#include <QtGui/QStatusBar>

#include <QtGui/QFileDialog>
#include <QtGui/QMessageBox>

#include <QtGui/QPrintDialog>
#include <QtGui/QPrinter>
#include <QtGui/QPainter>

#include <QtGui/QClipboard>

#include <MarbleDirs.h>
#include "lib/MarbleAboutDialog.h"

namespace
{
    const char* POSITION_STRING = "Position:";
    const char* DISTANCE_STRING = "Altitude:";
}

MainWindow::MainWindow(const QString& marbleDataPath, QWidget *parent) : QMainWindow(parent)
{
    setUpdatesEnabled( false );

    QString selectedPath = ( marbleDataPath.isEmpty() ) ? readMarbleDataPath() : marbleDataPath;
    if ( !selectedPath.isEmpty() )
        MarbleDirs::setMarbleDataPath( selectedPath );

    m_controlView = new ControlView( this );

    setWindowTitle( tr("Marble - Desktop Globe") );
    setWindowIcon( QIcon(":/icons/marble.png") );
    setCentralWidget(m_controlView);

    createActions();
    createMenus();
    createStatusBar();

    readSettings();
    setUpdatesEnabled( true );

    m_position = NOT_AVAILABLE;
    m_distance = marbleWidget()->distanceString();

    setupStatusBar();
}

void MainWindow::createActions()
 {
     m_openAct = new QAction( QIcon(":/icons/document-open.png"), tr( "&Open Map..."), this );
     m_openAct->setShortcut( tr( "Ctrl+O" ) );
     m_openAct->setStatusTip( tr( "Open a file for viewing on Marble"));
     connect( m_openAct, SIGNAL( triggered() ),
              this, SLOT( openFile() ) );

     m_exportMapAct = new QAction( QIcon(":/icons/document-save-as.png"), tr("&Export Map..."), this);
     m_exportMapAct->setShortcut(tr("Ctrl+S"));
     m_exportMapAct->setStatusTip(tr("Save a screenshot of the map"));
     connect(m_exportMapAct, SIGNAL(triggered()), this, SLOT(exportMapScreenShot()));

     m_printAct = new QAction( QIcon(":/icons/document-print.png"), tr("&Print..."), this);
     m_printAct->setShortcut(tr("Ctrl+P"));
     m_printAct->setStatusTip(tr("Print a screenshot of the map"));
     connect(m_printAct, SIGNAL(triggered()), this, SLOT(printMapScreenShot()));

     m_quitAct = new QAction( QIcon(":/icons/application-exit.png"), tr("&Quit"), this);
     m_quitAct->setShortcut(tr("Ctrl+Q"));
     m_quitAct->setStatusTip(tr("Quit the Application"));
     connect(m_quitAct, SIGNAL(triggered()), this, SLOT(close()));

     m_copyMapAct = new QAction( QIcon(":/icons/edit-copy.png"), tr("&Copy Map"), this);
     m_copyMapAct->setShortcut(tr("Ctrl+C"));
     m_copyMapAct->setStatusTip(tr("Copy a screenshot of the map"));
     connect(m_copyMapAct, SIGNAL(triggered()), this, SLOT(copyMap()));

     m_sideBarAct = new QAction( tr("Show &Navigation Panel"), this);
     m_sideBarAct->setShortcut(tr("F9"));
     m_sideBarAct->setCheckable( true );
     m_sideBarAct->setChecked( true );
     m_sideBarAct->setStatusTip(tr("Show Navigation Panel"));
     connect(m_sideBarAct, SIGNAL(triggered( bool )), this, SLOT( showSideBar( bool )));

     m_fullScreenAct = new QAction( tr("&Full Screen Mode"), this);
     m_fullScreenAct->setShortcut(tr("Ctrl+Shift+F"));
     m_fullScreenAct->setCheckable( true );
     m_fullScreenAct->setStatusTip(tr("Full Screen Mode"));
     connect(m_fullScreenAct, SIGNAL(triggered( bool )), this, SLOT( showFullScreen( bool )));

     m_statusBarAct = new QAction( tr("&Status Bar"), this);
     m_statusBarAct->setCheckable( true );
     m_statusBarAct->setStatusTip(tr("Show Status Bar"));
     connect(m_statusBarAct, SIGNAL(triggered( bool )), this, SLOT( showStatusBar( bool )));

     m_whatsThisAct = new QAction( QIcon(":/icons/help-whatsthis.png"), tr("What's &This"), this);
     m_whatsThisAct->setShortcut(tr("Shift+F1"));
     m_whatsThisAct->setStatusTip(tr("Show a detailed explanation of the action."));
     connect(m_whatsThisAct, SIGNAL(triggered()), this, SLOT(enterWhatsThis()));

     m_aboutMarbleAct = new QAction( QIcon(":/icons/marble.png"), tr("&About Marble Desktop Globe"), this);
     m_aboutMarbleAct->setStatusTip(tr("Show the application's About Box"));
     connect(m_aboutMarbleAct, SIGNAL(triggered()), this, SLOT(aboutMarble()));

     m_aboutQtAct = new QAction(tr("About &Qt"), this);
     m_aboutQtAct->setStatusTip(tr("Show the Qt library's About box"));
     connect(m_aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));

}

void MainWindow::createMenus()
{
    m_fileMenu = menuBar()->addMenu(tr("&File"));
    m_fileMenu->addAction(m_openAct);
    m_fileMenu->addAction(m_exportMapAct);
    m_fileMenu->addAction(m_printAct);
    m_fileMenu->addSeparator();
    m_fileMenu->addAction(m_quitAct);

    m_fileMenu = menuBar()->addMenu(tr("&Edit"));
    m_fileMenu->addAction(m_copyMapAct);

    m_fileMenu = menuBar()->addMenu(tr("&View"));
    m_fileMenu->addAction(m_fullScreenAct);
    m_fileMenu->addAction(m_sideBarAct);
    m_fileMenu->addSeparator();
    m_fileMenu->addAction(m_statusBarAct);

    m_helpMenu = menuBar()->addMenu(tr("&Help"));
    m_helpMenu->addAction(m_whatsThisAct);
    m_helpMenu->addSeparator();
    m_helpMenu->addAction(m_aboutMarbleAct);
    m_helpMenu->addAction(m_aboutQtAct);
}

void MainWindow::createStatusBar()
{
    statusBar()->showMessage(tr("Ready"));
    statusBar()->hide();
}

void MainWindow::exportMapScreenShot()
{
    QString fileName = QFileDialog::getSaveFileName(this, tr("Export Map"), // krazy:exclude=qclasses
                            QDir::homePath(),
                            tr("Images (*.jpg *.png)"));

    if ( !fileName.isEmpty() )
    {
        // Take the case into account where no file format is indicated
        char * format = 0;
        if ( !fileName.endsWith("png", Qt::CaseInsensitive)
           | !fileName.endsWith("jpg", Qt::CaseInsensitive) )
        {
            format = "JPG";
        }

        QPixmap mapPixmap = m_controlView->mapScreenShot();
        bool success = mapPixmap.save( fileName, format );
        if ( success == false )
        {
            QMessageBox::warning(this, tr("Marble"), // krazy:exclude=qclasses
                   tr( "An error occurred while trying to save the file.\n" ),
                   QMessageBox::Ok);
        }
    }
}

void MainWindow::printMapScreenShot()
{
    QPixmap mapPixmap = m_controlView->mapScreenShot();

    QSize printSize = mapPixmap.size();

    QPrinter printer;

    QPrintDialog printDialog( &printer, this );

    if (printDialog.exec() == QDialog::Accepted) {

        QRect mapPageRect = printer.pageRect();

        printSize.scale( ( printer.pageRect() ).size(), Qt::KeepAspectRatio );

        QPoint printTopLeft( mapPageRect.x() + mapPageRect.width() /2  - printSize.width() /2 ,
                             mapPageRect.y() + mapPageRect.height()/2  - printSize.height()/2 );

        QRect mapPrintRect( printTopLeft, printSize );

        QPainter painter( &printer );

        painter.drawPixmap( mapPrintRect, mapPixmap, mapPixmap.rect() );

    }
}

void MainWindow::showFullScreen( bool isChecked )
{
    if ( isChecked ) {
        QWidget::showFullScreen();
    }
    else {
        showNormal();
    }

    m_fullScreenAct->setChecked( isChecked ); // Sync state with the GUI
}

void MainWindow::showSideBar( bool isChecked )
{
    m_controlView->setSideBarShown( isChecked );

    m_sideBarAct->setChecked( isChecked ); // Sync state with the GUI
}

void MainWindow::copyMap()
{
    QPixmap      mapPixmap = m_controlView->mapScreenShot();
    QClipboard  *clipboard = QApplication::clipboard();

    clipboard->setPixmap( mapPixmap );
}

void MainWindow::showStatusBar( bool isChecked )
{
    if ( isChecked )
    {
        statusBar()->show();
    }
    else
    {
        statusBar()->hide();
    }

    m_statusBarAct->setChecked( isChecked ); // Sync state with the GUI
}

void MainWindow::enterWhatsThis()
{
    QWhatsThis::enterWhatsThisMode();
}

void MainWindow::aboutMarble()
{
    MarbleAboutDialog dlg(this);
    dlg.exec();
}

void MainWindow::showPosition( const QString& position )
{
    m_position = position;
    updateStatusBar();
}

void MainWindow::showDistance( const QString& distance )
{
    m_distance = distance;
    updateStatusBar();
}

void MainWindow::updateStatusBar()
{
    if ( m_positionLabel )
        m_positionLabel->setText( QString( "%1 %2" ).
        arg( tr( POSITION_STRING ) ).arg( m_position ) );

    if ( m_distanceLabel )
        m_distanceLabel->setText( QString( "%1 %2" )
        .arg( tr( DISTANCE_STRING ) ).arg( m_distance ) );
}

void MainWindow::openFile()
{
    QString fileName;
    fileName = QFileDialog::getOpenFileName(this, tr("Open File"),
                            QString(),
                            tr("All Supported Files (*.gpx *.kml);;GPS Data (*.gpx);;Google Earth KML (*.kml)"));

    if ( ! fileName.isNull() ) {
        QString extension = fileName.section( '.', -1 );

        if ( extension.compare( "gpx", Qt::CaseInsensitive ) == 0 ) {
            m_controlView->marbleWidget()->openGpxFile( fileName );
        }
        else if ( extension.compare( "kml", Qt::CaseInsensitive )
                  == 0 )
        {
            m_controlView->marbleWidget()->addPlaceMarkFile(
                                                            fileName);
        }
    }
}

void MainWindow::setupStatusBar()
{
    statusBar()->setSizeGripEnabled( true );

    m_positionLabel = new QLabel( );
    m_positionLabel->setIndent( 5 );
    QString templatePositionString =
        QString( "%1 000\xb0 00\' 00\"_, 000\xb0 00\' 00\"_" ).arg(POSITION_STRING);
    int maxPositionWidth = fontMetrics().boundingRect(templatePositionString).width()
                            + 2 * m_positionLabel->margin() + 2 * m_positionLabel->indent();
    m_positionLabel->setFixedWidth( maxPositionWidth );
    statusBar()->addPermanentWidget ( m_positionLabel );

    m_distanceLabel = new QLabel( );
    m_distanceLabel->setIndent( 5 );
    QString templateDistanceString =
        QString( "%1 00.000,0 mu" ).arg(DISTANCE_STRING);
    int maxDistanceWidth = fontMetrics().boundingRect(templateDistanceString).width()
                            + 2 * m_distanceLabel->margin() + 2 * m_distanceLabel->indent();
    m_distanceLabel->setFixedWidth( maxDistanceWidth );
    statusBar()->addPermanentWidget ( m_distanceLabel );

    connect( marbleWidget(), SIGNAL( mouseMoveGeoPosition( QString ) ),
              this, SLOT( showPosition( QString ) ) );
    connect( marbleWidget(), SIGNAL( distanceChanged( QString ) ),
              this, SLOT( showDistance( QString ) ) );

    updateStatusBar();
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    writeSettings();
    event->accept();
}

QString MainWindow::readMarbleDataPath()
{
#ifdef Q_WS_MAC
     QSettings settings("KDE.org", "Marble Desktop Globe");
#else
     QSettings settings("KDE", "Marble Desktop Globe");
#endif

     settings.beginGroup("MarbleWidget");
         QString marbleDataPath;
         marbleDataPath = settings.value("marbleDataPath", "").toString(),
     settings.endGroup();

     return marbleDataPath;
}

void MainWindow::readSettings()
{
#ifdef Q_WS_MAC
     QSettings settings("KDE.org", "Marble Desktop Globe");
#else
     QSettings settings("KDE", "Marble Desktop Globe");
#endif

     settings.beginGroup("MainWindow");
         resize(settings.value("size", QSize(640, 480)).toSize());
         move(settings.value("pos", QPoint(200, 200)).toPoint());
         showFullScreen(settings.value("fullScreen", false ).toBool());
         showSideBar(settings.value("sideBar", true ).toBool());
         showStatusBar(settings.value("statusBar", false ).toBool());
     settings.endGroup();

     settings.beginGroup("MarbleWidget");
         m_controlView->marbleWidget()->setHome(
            settings.value("homeLongitude", 9.4).toDouble(),
            settings.value("homeLatitude", 54.8).toDouble(),
            settings.value("homeZoom", 1050 ).toInt()
         );
         m_controlView->marbleWidget()->goHome();
         m_controlView->marbleWidget()->setMapTheme(
            settings.value("mapTheme", "" )
         );
         m_controlView->marbleWidget()->setProjection(
            settings.value("projection", 0 ).toInt()
         );
     settings.endGroup();
}

void MainWindow::writeSettings()
{
#ifdef Q_WS_MAC
     QSettings settings("KDE.org", "Marble Desktop Globe");
#else
     QSettings settings("KDE", "Marble Desktop Globe");
#endif

     settings.beginGroup( "MainWindow" );
         settings.setValue( "size", size() );
         settings.setValue( "pos", pos() );
         settings.setValue( "fullScreen", m_fullScreenAct->isChecked() );
         settings.setValue( "sideBar", m_sideBarAct->isChecked() );
         settings.setValue( "statusBar", m_statusBarAct->isChecked() );
     settings.endGroup();

     settings.beginGroup( "MarbleWidget" );
         double homeLon = 0;
         double homeLat = 0;
         int homeZoom = 0;
         m_controlView->marbleWidget()->home( homeLon, homeLat, homeZoom );
         QString  mapTheme = m_controlView->marbleWidget()->mapTheme();
         int      projection = (int)( m_controlView->marbleWidget()->projection() );

         settings.setValue( "homeLongitude", homeLon );
         settings.setValue( "homeLatitude",  homeLat );
         settings.setValue( "homeZoom",      homeZoom );

         settings.setValue( "mapTheme",   mapTheme );
         settings.setValue( "projection", projection );
     settings.endGroup();
}

#include "QtMainWindow.moc"
<commit_msg>- Small QVariant glitch ...<commit_after>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2006-2007 Torsten Rahn <tackat@kde.org>"
// Copyright 2007      Inge Wallin  <ingwa@kde.org>"
//

#include "QtMainWindow.h"

#include <QtCore/QSettings>
#include <QtGui/QCloseEvent>

#include <QtGui/QAction>
#include <QtGui/QLabel>
#include <QtGui/QWhatsThis>
#include <QtGui/QApplication>
#include <QtGui/QIcon>
#include <QtGui/QMenuBar>
#include <QtGui/QStatusBar>

#include <QtGui/QFileDialog>
#include <QtGui/QMessageBox>

#include <QtGui/QPrintDialog>
#include <QtGui/QPrinter>
#include <QtGui/QPainter>

#include <QtGui/QClipboard>

#include <MarbleDirs.h>
#include "lib/MarbleAboutDialog.h"

namespace
{
    const char* POSITION_STRING = "Position:";
    const char* DISTANCE_STRING = "Altitude:";
}

MainWindow::MainWindow(const QString& marbleDataPath, QWidget *parent) : QMainWindow(parent)
{
    setUpdatesEnabled( false );

    QString selectedPath = ( marbleDataPath.isEmpty() ) ? readMarbleDataPath() : marbleDataPath;
    if ( !selectedPath.isEmpty() )
        MarbleDirs::setMarbleDataPath( selectedPath );

    m_controlView = new ControlView( this );

    setWindowTitle( tr("Marble - Desktop Globe") );
    setWindowIcon( QIcon(":/icons/marble.png") );
    setCentralWidget(m_controlView);

    createActions();
    createMenus();
    createStatusBar();

    readSettings();
    setUpdatesEnabled( true );

    m_position = NOT_AVAILABLE;
    m_distance = marbleWidget()->distanceString();

    setupStatusBar();
}

void MainWindow::createActions()
 {
     m_openAct = new QAction( QIcon(":/icons/document-open.png"), tr( "&Open Map..."), this );
     m_openAct->setShortcut( tr( "Ctrl+O" ) );
     m_openAct->setStatusTip( tr( "Open a file for viewing on Marble"));
     connect( m_openAct, SIGNAL( triggered() ),
              this, SLOT( openFile() ) );

     m_exportMapAct = new QAction( QIcon(":/icons/document-save-as.png"), tr("&Export Map..."), this);
     m_exportMapAct->setShortcut(tr("Ctrl+S"));
     m_exportMapAct->setStatusTip(tr("Save a screenshot of the map"));
     connect(m_exportMapAct, SIGNAL(triggered()), this, SLOT(exportMapScreenShot()));

     m_printAct = new QAction( QIcon(":/icons/document-print.png"), tr("&Print..."), this);
     m_printAct->setShortcut(tr("Ctrl+P"));
     m_printAct->setStatusTip(tr("Print a screenshot of the map"));
     connect(m_printAct, SIGNAL(triggered()), this, SLOT(printMapScreenShot()));

     m_quitAct = new QAction( QIcon(":/icons/application-exit.png"), tr("&Quit"), this);
     m_quitAct->setShortcut(tr("Ctrl+Q"));
     m_quitAct->setStatusTip(tr("Quit the Application"));
     connect(m_quitAct, SIGNAL(triggered()), this, SLOT(close()));

     m_copyMapAct = new QAction( QIcon(":/icons/edit-copy.png"), tr("&Copy Map"), this);
     m_copyMapAct->setShortcut(tr("Ctrl+C"));
     m_copyMapAct->setStatusTip(tr("Copy a screenshot of the map"));
     connect(m_copyMapAct, SIGNAL(triggered()), this, SLOT(copyMap()));

     m_sideBarAct = new QAction( tr("Show &Navigation Panel"), this);
     m_sideBarAct->setShortcut(tr("F9"));
     m_sideBarAct->setCheckable( true );
     m_sideBarAct->setChecked( true );
     m_sideBarAct->setStatusTip(tr("Show Navigation Panel"));
     connect(m_sideBarAct, SIGNAL(triggered( bool )), this, SLOT( showSideBar( bool )));

     m_fullScreenAct = new QAction( tr("&Full Screen Mode"), this);
     m_fullScreenAct->setShortcut(tr("Ctrl+Shift+F"));
     m_fullScreenAct->setCheckable( true );
     m_fullScreenAct->setStatusTip(tr("Full Screen Mode"));
     connect(m_fullScreenAct, SIGNAL(triggered( bool )), this, SLOT( showFullScreen( bool )));

     m_statusBarAct = new QAction( tr("&Status Bar"), this);
     m_statusBarAct->setCheckable( true );
     m_statusBarAct->setStatusTip(tr("Show Status Bar"));
     connect(m_statusBarAct, SIGNAL(triggered( bool )), this, SLOT( showStatusBar( bool )));

     m_whatsThisAct = new QAction( QIcon(":/icons/help-whatsthis.png"), tr("What's &This"), this);
     m_whatsThisAct->setShortcut(tr("Shift+F1"));
     m_whatsThisAct->setStatusTip(tr("Show a detailed explanation of the action."));
     connect(m_whatsThisAct, SIGNAL(triggered()), this, SLOT(enterWhatsThis()));

     m_aboutMarbleAct = new QAction( QIcon(":/icons/marble.png"), tr("&About Marble Desktop Globe"), this);
     m_aboutMarbleAct->setStatusTip(tr("Show the application's About Box"));
     connect(m_aboutMarbleAct, SIGNAL(triggered()), this, SLOT(aboutMarble()));

     m_aboutQtAct = new QAction(tr("About &Qt"), this);
     m_aboutQtAct->setStatusTip(tr("Show the Qt library's About box"));
     connect(m_aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));

}

void MainWindow::createMenus()
{
    m_fileMenu = menuBar()->addMenu(tr("&File"));
    m_fileMenu->addAction(m_openAct);
    m_fileMenu->addAction(m_exportMapAct);
    m_fileMenu->addAction(m_printAct);
    m_fileMenu->addSeparator();
    m_fileMenu->addAction(m_quitAct);

    m_fileMenu = menuBar()->addMenu(tr("&Edit"));
    m_fileMenu->addAction(m_copyMapAct);

    m_fileMenu = menuBar()->addMenu(tr("&View"));
    m_fileMenu->addAction(m_fullScreenAct);
    m_fileMenu->addAction(m_sideBarAct);
    m_fileMenu->addSeparator();
    m_fileMenu->addAction(m_statusBarAct);

    m_helpMenu = menuBar()->addMenu(tr("&Help"));
    m_helpMenu->addAction(m_whatsThisAct);
    m_helpMenu->addSeparator();
    m_helpMenu->addAction(m_aboutMarbleAct);
    m_helpMenu->addAction(m_aboutQtAct);
}

void MainWindow::createStatusBar()
{
    statusBar()->showMessage(tr("Ready"));
    statusBar()->hide();
}

void MainWindow::exportMapScreenShot()
{
    QString fileName = QFileDialog::getSaveFileName(this, tr("Export Map"), // krazy:exclude=qclasses
                            QDir::homePath(),
                            tr("Images (*.jpg *.png)"));

    if ( !fileName.isEmpty() )
    {
        // Take the case into account where no file format is indicated
        char * format = 0;
        if ( !fileName.endsWith("png", Qt::CaseInsensitive)
           | !fileName.endsWith("jpg", Qt::CaseInsensitive) )
        {
            format = "JPG";
        }

        QPixmap mapPixmap = m_controlView->mapScreenShot();
        bool success = mapPixmap.save( fileName, format );
        if ( success == false )
        {
            QMessageBox::warning(this, tr("Marble"), // krazy:exclude=qclasses
                   tr( "An error occurred while trying to save the file.\n" ),
                   QMessageBox::Ok);
        }
    }
}

void MainWindow::printMapScreenShot()
{
    QPixmap mapPixmap = m_controlView->mapScreenShot();

    QSize printSize = mapPixmap.size();

    QPrinter printer;

    QPrintDialog printDialog( &printer, this );

    if (printDialog.exec() == QDialog::Accepted) {

        QRect mapPageRect = printer.pageRect();

        printSize.scale( ( printer.pageRect() ).size(), Qt::KeepAspectRatio );

        QPoint printTopLeft( mapPageRect.x() + mapPageRect.width() /2  - printSize.width() /2 ,
                             mapPageRect.y() + mapPageRect.height()/2  - printSize.height()/2 );

        QRect mapPrintRect( printTopLeft, printSize );

        QPainter painter( &printer );

        painter.drawPixmap( mapPrintRect, mapPixmap, mapPixmap.rect() );

    }
}

void MainWindow::showFullScreen( bool isChecked )
{
    if ( isChecked ) {
        QWidget::showFullScreen();
    }
    else {
        showNormal();
    }

    m_fullScreenAct->setChecked( isChecked ); // Sync state with the GUI
}

void MainWindow::showSideBar( bool isChecked )
{
    m_controlView->setSideBarShown( isChecked );

    m_sideBarAct->setChecked( isChecked ); // Sync state with the GUI
}

void MainWindow::copyMap()
{
    QPixmap      mapPixmap = m_controlView->mapScreenShot();
    QClipboard  *clipboard = QApplication::clipboard();

    clipboard->setPixmap( mapPixmap );
}

void MainWindow::showStatusBar( bool isChecked )
{
    if ( isChecked )
    {
        statusBar()->show();
    }
    else
    {
        statusBar()->hide();
    }

    m_statusBarAct->setChecked( isChecked ); // Sync state with the GUI
}

void MainWindow::enterWhatsThis()
{
    QWhatsThis::enterWhatsThisMode();
}

void MainWindow::aboutMarble()
{
    MarbleAboutDialog dlg(this);
    dlg.exec();
}

void MainWindow::showPosition( const QString& position )
{
    m_position = position;
    updateStatusBar();
}

void MainWindow::showDistance( const QString& distance )
{
    m_distance = distance;
    updateStatusBar();
}

void MainWindow::updateStatusBar()
{
    if ( m_positionLabel )
        m_positionLabel->setText( QString( "%1 %2" ).
        arg( tr( POSITION_STRING ) ).arg( m_position ) );

    if ( m_distanceLabel )
        m_distanceLabel->setText( QString( "%1 %2" )
        .arg( tr( DISTANCE_STRING ) ).arg( m_distance ) );
}

void MainWindow::openFile()
{
    QString fileName;
    fileName = QFileDialog::getOpenFileName(this, tr("Open File"),
                            QString(),
                            tr("All Supported Files (*.gpx *.kml);;GPS Data (*.gpx);;Google Earth KML (*.kml)"));

    if ( ! fileName.isNull() ) {
        QString extension = fileName.section( '.', -1 );

        if ( extension.compare( "gpx", Qt::CaseInsensitive ) == 0 ) {
            m_controlView->marbleWidget()->openGpxFile( fileName );
        }
        else if ( extension.compare( "kml", Qt::CaseInsensitive )
                  == 0 )
        {
            m_controlView->marbleWidget()->addPlaceMarkFile(
                                                            fileName);
        }
    }
}

void MainWindow::setupStatusBar()
{
    statusBar()->setSizeGripEnabled( true );

    m_positionLabel = new QLabel( );
    m_positionLabel->setIndent( 5 );
    QString templatePositionString =
        QString( "%1 000\xb0 00\' 00\"_, 000\xb0 00\' 00\"_" ).arg(POSITION_STRING);
    int maxPositionWidth = fontMetrics().boundingRect(templatePositionString).width()
                            + 2 * m_positionLabel->margin() + 2 * m_positionLabel->indent();
    m_positionLabel->setFixedWidth( maxPositionWidth );
    statusBar()->addPermanentWidget ( m_positionLabel );

    m_distanceLabel = new QLabel( );
    m_distanceLabel->setIndent( 5 );
    QString templateDistanceString =
        QString( "%1 00.000,0 mu" ).arg(DISTANCE_STRING);
    int maxDistanceWidth = fontMetrics().boundingRect(templateDistanceString).width()
                            + 2 * m_distanceLabel->margin() + 2 * m_distanceLabel->indent();
    m_distanceLabel->setFixedWidth( maxDistanceWidth );
    statusBar()->addPermanentWidget ( m_distanceLabel );

    connect( marbleWidget(), SIGNAL( mouseMoveGeoPosition( QString ) ),
              this, SLOT( showPosition( QString ) ) );
    connect( marbleWidget(), SIGNAL( distanceChanged( QString ) ),
              this, SLOT( showDistance( QString ) ) );

    updateStatusBar();
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    writeSettings();
    event->accept();
}

QString MainWindow::readMarbleDataPath()
{
#ifdef Q_WS_MAC
     QSettings settings("KDE.org", "Marble Desktop Globe");
#else
     QSettings settings("KDE", "Marble Desktop Globe");
#endif

     settings.beginGroup("MarbleWidget");
         QString marbleDataPath;
         marbleDataPath = settings.value("marbleDataPath", "").toString(),
     settings.endGroup();

     return marbleDataPath;
}

void MainWindow::readSettings()
{
#ifdef Q_WS_MAC
     QSettings settings("KDE.org", "Marble Desktop Globe");
#else
     QSettings settings("KDE", "Marble Desktop Globe");
#endif

     settings.beginGroup("MainWindow");
         resize(settings.value("size", QSize(640, 480)).toSize());
         move(settings.value("pos", QPoint(200, 200)).toPoint());
         showFullScreen(settings.value("fullScreen", false ).toBool());
         showSideBar(settings.value("sideBar", true ).toBool());
         showStatusBar(settings.value("statusBar", false ).toBool());
     settings.endGroup();

     settings.beginGroup("MarbleWidget");
         m_controlView->marbleWidget()->setHome(
            settings.value("homeLongitude", 9.4).toDouble(),
            settings.value("homeLatitude", 54.8).toDouble(),
            settings.value("homeZoom", 1050 ).toInt()
         );
         m_controlView->marbleWidget()->goHome();
         m_controlView->marbleWidget()->setMapTheme(
            settings.value("mapTheme", "" ).toString()
         );
         m_controlView->marbleWidget()->setProjection(
            settings.value("projection", 0 ).toInt()
         );
     settings.endGroup();
}

void MainWindow::writeSettings()
{
#ifdef Q_WS_MAC
     QSettings settings("KDE.org", "Marble Desktop Globe");
#else
     QSettings settings("KDE", "Marble Desktop Globe");
#endif

     settings.beginGroup( "MainWindow" );
         settings.setValue( "size", size() );
         settings.setValue( "pos", pos() );
         settings.setValue( "fullScreen", m_fullScreenAct->isChecked() );
         settings.setValue( "sideBar", m_sideBarAct->isChecked() );
         settings.setValue( "statusBar", m_statusBarAct->isChecked() );
     settings.endGroup();

     settings.beginGroup( "MarbleWidget" );
         double homeLon = 0;
         double homeLat = 0;
         int homeZoom = 0;
         m_controlView->marbleWidget()->home( homeLon, homeLat, homeZoom );
         QString  mapTheme = m_controlView->marbleWidget()->mapTheme();
         int      projection = (int)( m_controlView->marbleWidget()->projection() );

         settings.setValue( "homeLongitude", homeLon );
         settings.setValue( "homeLatitude",  homeLat );
         settings.setValue( "homeZoom",      homeZoom );

         settings.setValue( "mapTheme",   mapTheme );
         settings.setValue( "projection", projection );
     settings.endGroup();
}

#include "QtMainWindow.moc"
<|endoftext|>