<commit_before>// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp

#include <NDK/Application.hpp>
#include <Nazara/Core/Log.hpp>
#include <regex>

#ifndef NDK_SERVER
#include <NDK/Components/CameraComponent.hpp>
#include <NDK/Components/GraphicsComponent.hpp>
#include <NDK/Components/NodeComponent.hpp>
#include <NDK/Systems/RenderSystem.hpp>
#include <NDK/LuaAPI.hpp>
#include <Nazara/Graphics/ForwardRenderTechnique.hpp>
#include <Nazara/Utility/SimpleTextDrawer.hpp>
#endif

namespace Ndk
{
	/*!
	* \ingroup NDK
	* \class Ndk::Application
	* \brief NDK class that represents the application, it offers a set of tools to ease the development
	*/

	/*!
	* \brief Constructs an Application object with command-line arguments
	*
	* Pass the argc and argv arguments from the main function.
	*
	* Command-line arguments can be retrieved by application methods
	*
	* This calls Sdk::Initialize()
	*
	* \remark Only one Application instance can exist at a time
	*/
	Application::Application(int argc, char* argv[]) :
	Application()
	{
		std::regex optionRegex(R"(-(\w+))");
		std::regex valueRegex(R"(-(\w+)\s*=\s*(.+))");

		std::smatch results;

		for (int i = 1; i < argc; ++i)
		{
			std::string argument(argv[i]);
			if (std::regex_match(argument, results, valueRegex))
			{
				Nz::String key(results[1].str());
				Nz::String value(results[2].str());

				m_parameters[key.ToLower()] = value;
				NazaraDebug("Registred parameter from command-line: " + key.ToLower() + "=" + value);
			}
			else if (std::regex_match(argument, results, optionRegex))
			{
				Nz::String option(results[1].str());

				m_options.insert(option);
				NazaraDebug("Registred option from command-line: " + option);
			}
			else
				NazaraWarning("Ignored command-line argument #" + Nz::String::Number(i) + " \"" + argument + '"');
		}

		#ifndef NDK_SERVER
		if (HasOption("console"))
			EnableConsole(true);

		if (HasOption("fpscounter"))
			EnableFPSCounter(true);
		#endif
	}

	/*!
	* \brief Runs the application by updating worlds, taking care about windows, ...
	*/
	bool Application::Run()
	{
		#ifndef NDK_SERVER
		bool hasAtLeastOneActiveWindow = false;

		auto it = m_windows.begin();
		while (it != m_windows.end())
		{
			Nz::Window& window = *it->window;

			window.ProcessEvents();

			if (!window.IsOpen(true))
			{
				it = m_windows.erase(it);
				continue;
			}

			hasAtLeastOneActiveWindow = true;

			++it;
		}

		if (m_exitOnClosedWindows && !hasAtLeastOneActiveWindow)
			return false;
		#endif

		if (m_shouldQuit)
			return false;

		m_updateTime = m_updateClock.Restart() / 1'000'000.f;

		for (World& world : m_worlds)
			world.Update(m_updateTime);

		#ifndef NDK_SERVER
		for (WindowInfo& info : m_windows)
		{
			if (!info.overlayWorld)
				continue;

			if (info.fpsCounter)
			{
				FPSCounterOverlay& fpsCounter = *info.fpsCounter;

				fpsCounter.frameCount++;

				fpsCounter.elapsedTime += m_updateTime;
				if (fpsCounter.elapsedTime >= 1.f)
				{
					fpsCounter.sprite->Update(Nz::SimpleTextDrawer::Draw("FPS: " + Nz::String::Number(fpsCounter.frameCount), 36));
					fpsCounter.frameCount = 0;
					fpsCounter.elapsedTime = 0.f;
				}
			}

			info.overlayWorld->Update(m_updateTime);
		}
		#endif

		return true;
	}

	#ifndef NDK_SERVER
	void Application::SetupConsole(WindowInfo& info)
	{
		std::unique_ptr<ConsoleOverlay> overlay = std::make_unique<ConsoleOverlay>();

		Nz::Vector2ui windowDimensions;
		if (info.window->IsValid())
			windowDimensions = info.window->GetSize();
		else
			windowDimensions.MakeZero();

		overlay->console = info.canvas->Add<Console>(overlay->lua);

		Console& consoleRef = *overlay->console;
		consoleRef.SetSize({float(windowDimensions.x), windowDimensions.y / 4.f});
		consoleRef.Show(false);

		// Redirect logs toward the console
		overlay->logSlot.Connect(Nz::Log::OnLogWrite, [&consoleRef] (const Nz::String& str)
		{
			consoleRef.AddLine(str);
		});

		overlay->lua.LoadLibraries();
		LuaAPI::RegisterClasses(overlay->lua);

		// Override "print" function to add a line in the console
		overlay->lua.PushFunction([&consoleRef] (Nz::LuaState& state)
		{
			Nz::StringStream stream;

			unsigned int argCount = state.GetStackTop();
			state.GetGlobal("tostring");
			for (unsigned int i = 1; i <= argCount; ++i)
			{
				state.PushValue(-1); // tostring function
				state.PushValue(i);  // argument
				state.Call(1, 1);

				std::size_t length;
				const char* str = state.CheckString(-1, &length);
				if (i > 1)
					stream << '\t';

				stream << Nz::String(str, length);
				state.Pop(1);
			}

			consoleRef.AddLine(stream);
			return 0;
		});
		overlay->lua.SetGlobal("print");

		// Define a few base variables to allow our interface to interact with the application
		overlay->lua.PushGlobal("Application", Ndk::Application::Instance());
		overlay->lua.PushGlobal("Console", consoleRef.CreateHandle());

		// Setup a few event callback to handle the console
		Nz::EventHandler& eventHandler = info.window->GetEventHandler();

		/*overlay->eventSlot.Connect(eventHandler.OnEvent, [&consoleRef] (const Nz::EventHandler*, const Nz::WindowEvent& event)
		{
			if (consoleRef.IsVisible())
				consoleRef.SendEvent(event);
		});*/

		overlay->keyPressedSlot.Connect(eventHandler.OnKeyPressed, [&consoleRef] (const Nz::EventHandler*, const Nz::WindowEvent::KeyEvent& event)
		{
			if (event.code == Nz::Keyboard::F9)
				consoleRef.Show(!consoleRef.IsVisible());
		});

		overlay->resizedSlot.Connect(info.renderTarget->OnRenderTargetSizeChange, [&consoleRef] (const Nz::RenderTarget* renderTarget)
		{
			Nz::Vector2ui size = renderTarget->GetSize();
			consoleRef.SetSize({float(size.x), size.y / 4.f});
		});

		info.console = std::move(overlay);
	}

	void Application::SetupFPSCounter(WindowInfo& info)
	{
		std::unique_ptr<FPSCounterOverlay> fpsCounter = std::make_unique<FPSCounterOverlay>();
		fpsCounter->sprite = Nz::TextSprite::New();

		fpsCounter->entity = info.overlayWorld->CreateEntity();
		fpsCounter->entity->AddComponent<NodeComponent>();
		fpsCounter->entity->AddComponent<GraphicsComponent>().Attach(fpsCounter->sprite);

		info.fpsCounter = std::move(fpsCounter);
	}

	void Application::SetupOverlay(WindowInfo& info)
	{
		info.overlayWorld = std::make_unique<World>(false); //< No default system

		if (info.window->IsValid())
			info.canvas = std::make_unique<Canvas>(info.overlayWorld->CreateHandle(), info.window->GetEventHandler(), info.window->GetCursorController().CreateHandle());

		RenderSystem& renderSystem = info.overlayWorld->AddSystem<RenderSystem>();
		renderSystem.ChangeRenderTechnique<Nz::ForwardRenderTechnique>();
		renderSystem.SetDefaultBackground(nullptr);
		renderSystem.SetGlobalUp(Nz::Vector3f::Down());

		EntityHandle viewer = info.overlayWorld->CreateEntity();
		CameraComponent& camComponent = viewer->AddComponent<CameraComponent>();
		viewer->AddComponent<NodeComponent>();

		camComponent.SetProjectionType(Nz::ProjectionType_Orthogonal);
		camComponent.SetTarget(info.renderTarget);
	}
	#endif

	Application* Application::s_application = nullptr;
}
<commit_msg>Sdk/Application: Give/clear console focus when enabling/disabling it<commit_after>// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp

#include <NDK/Application.hpp>
#include <Nazara/Core/Log.hpp>
#include <regex>

#ifndef NDK_SERVER
#include <NDK/Components/CameraComponent.hpp>
#include <NDK/Components/GraphicsComponent.hpp>
#include <NDK/Components/NodeComponent.hpp>
#include <NDK/Systems/RenderSystem.hpp>
#include <NDK/LuaAPI.hpp>
#include <Nazara/Graphics/ForwardRenderTechnique.hpp>
#include <Nazara/Utility/SimpleTextDrawer.hpp>
#endif

namespace Ndk
{
	/*!
	* \ingroup NDK
	* \class Ndk::Application
	* \brief NDK class that represents the application, it offers a set of tools to ease the development
	*/

	/*!
	* \brief Constructs an Application object with command-line arguments
	*
	* Pass the argc and argv arguments from the main function.
	*
	* Command-line arguments can be retrieved by application methods
	*
	* This calls Sdk::Initialize()
	*
	* \remark Only one Application instance can exist at a time
	*/
	Application::Application(int argc, char* argv[]) :
	Application()
	{
		std::regex optionRegex(R"(-(\w+))");
		std::regex valueRegex(R"(-(\w+)\s*=\s*(.+))");

		std::smatch results;

		for (int i = 1; i < argc; ++i)
		{
			std::string argument(argv[i]);
			if (std::regex_match(argument, results, valueRegex))
			{
				Nz::String key(results[1].str());
				Nz::String value(results[2].str());

				m_parameters[key.ToLower()] = value;
				NazaraDebug("Registred parameter from command-line: " + key.ToLower() + "=" + value);
			}
			else if (std::regex_match(argument, results, optionRegex))
			{
				Nz::String option(results[1].str());

				m_options.insert(option);
				NazaraDebug("Registred option from command-line: " + option);
			}
			else
				NazaraWarning("Ignored command-line argument #" + Nz::String::Number(i) + " \"" + argument + '"');
		}

		#ifndef NDK_SERVER
		if (HasOption("console"))
			EnableConsole(true);

		if (HasOption("fpscounter"))
			EnableFPSCounter(true);
		#endif
	}

	/*!
	* \brief Runs the application by updating worlds, taking care about windows, ...
	*/
	bool Application::Run()
	{
		#ifndef NDK_SERVER
		bool hasAtLeastOneActiveWindow = false;

		auto it = m_windows.begin();
		while (it != m_windows.end())
		{
			Nz::Window& window = *it->window;

			window.ProcessEvents();

			if (!window.IsOpen(true))
			{
				it = m_windows.erase(it);
				continue;
			}

			hasAtLeastOneActiveWindow = true;

			++it;
		}

		if (m_exitOnClosedWindows && !hasAtLeastOneActiveWindow)
			return false;
		#endif

		if (m_shouldQuit)
			return false;

		m_updateTime = m_updateClock.Restart() / 1'000'000.f;

		for (World& world : m_worlds)
			world.Update(m_updateTime);

		#ifndef NDK_SERVER
		for (WindowInfo& info : m_windows)
		{
			if (!info.overlayWorld)
				continue;

			if (info.fpsCounter)
			{
				FPSCounterOverlay& fpsCounter = *info.fpsCounter;

				fpsCounter.frameCount++;

				fpsCounter.elapsedTime += m_updateTime;
				if (fpsCounter.elapsedTime >= 1.f)
				{
					fpsCounter.sprite->Update(Nz::SimpleTextDrawer::Draw("FPS: " + Nz::String::Number(fpsCounter.frameCount), 36));
					fpsCounter.frameCount = 0;
					fpsCounter.elapsedTime = 0.f;
				}
			}

			info.overlayWorld->Update(m_updateTime);
		}
		#endif

		return true;
	}

	#ifndef NDK_SERVER
	void Application::SetupConsole(WindowInfo& info)
	{
		std::unique_ptr<ConsoleOverlay> overlay = std::make_unique<ConsoleOverlay>();

		Nz::Vector2ui windowDimensions;
		if (info.window->IsValid())
			windowDimensions = info.window->GetSize();
		else
			windowDimensions.MakeZero();

		overlay->console = info.canvas->Add<Console>(overlay->lua);

		Console& consoleRef = *overlay->console;
		consoleRef.SetSize({float(windowDimensions.x), windowDimensions.y / 4.f});
		consoleRef.Show(false);

		// Redirect logs toward the console
		overlay->logSlot.Connect(Nz::Log::OnLogWrite, [&consoleRef] (const Nz::String& str)
		{
			consoleRef.AddLine(str);
		});

		overlay->lua.LoadLibraries();
		LuaAPI::RegisterClasses(overlay->lua);

		// Override "print" function to add a line in the console
		overlay->lua.PushFunction([&consoleRef] (Nz::LuaState& state)
		{
			Nz::StringStream stream;

			unsigned int argCount = state.GetStackTop();
			state.GetGlobal("tostring");
			for (unsigned int i = 1; i <= argCount; ++i)
			{
				state.PushValue(-1); // tostring function
				state.PushValue(i);  // argument
				state.Call(1, 1);

				std::size_t length;
				const char* str = state.CheckString(-1, &length);
				if (i > 1)
					stream << '\t';

				stream << Nz::String(str, length);
				state.Pop(1);
			}

			consoleRef.AddLine(stream);
			return 0;
		});
		overlay->lua.SetGlobal("print");

		// Define a few base variables to allow our interface to interact with the application
		overlay->lua.PushGlobal("Application", Ndk::Application::Instance());
		overlay->lua.PushGlobal("Console", consoleRef.CreateHandle());

		// Setup a few event callback to handle the console
		Nz::EventHandler& eventHandler = info.window->GetEventHandler();

		/*overlay->eventSlot.Connect(eventHandler.OnEvent, [&consoleRef] (const Nz::EventHandler*, const Nz::WindowEvent& event)
		{
			if (consoleRef.IsVisible())
				consoleRef.SendEvent(event);
		});*/

		overlay->keyPressedSlot.Connect(eventHandler.OnKeyPressed, [&consoleRef] (const Nz::EventHandler*, const Nz::WindowEvent::KeyEvent& event)
		{
			if (event.code == Nz::Keyboard::F9)
			{
				// Toggle console visibility and focus
				if (consoleRef.IsVisible())
				{
					consoleRef.ClearFocus();
					consoleRef.Show(false);
				}
				else
				{
					consoleRef.Show(true);
					consoleRef.SetFocus();
				}
			}
		});

		overlay->resizedSlot.Connect(info.renderTarget->OnRenderTargetSizeChange, [&consoleRef] (const Nz::RenderTarget* renderTarget)
		{
			Nz::Vector2ui size = renderTarget->GetSize();
			consoleRef.SetSize({float(size.x), size.y / 4.f});
		});

		info.console = std::move(overlay);
	}

	void Application::SetupFPSCounter(WindowInfo& info)
	{
		std::unique_ptr<FPSCounterOverlay> fpsCounter = std::make_unique<FPSCounterOverlay>();
		fpsCounter->sprite = Nz::TextSprite::New();

		fpsCounter->entity = info.overlayWorld->CreateEntity();
		fpsCounter->entity->AddComponent<NodeComponent>();
		fpsCounter->entity->AddComponent<GraphicsComponent>().Attach(fpsCounter->sprite);

		info.fpsCounter = std::move(fpsCounter);
	}

	void Application::SetupOverlay(WindowInfo& info)
	{
		info.overlayWorld = std::make_unique<World>(false); //< No default system

		if (info.window->IsValid())
			info.canvas = std::make_unique<Canvas>(info.overlayWorld->CreateHandle(), info.window->GetEventHandler(), info.window->GetCursorController().CreateHandle());

		RenderSystem& renderSystem = info.overlayWorld->AddSystem<RenderSystem>();
		renderSystem.ChangeRenderTechnique<Nz::ForwardRenderTechnique>();
		renderSystem.SetDefaultBackground(nullptr);
		renderSystem.SetGlobalUp(Nz::Vector3f::Down());

		EntityHandle viewer = info.overlayWorld->CreateEntity();
		CameraComponent& camComponent = viewer->AddComponent<CameraComponent>();
		viewer->AddComponent<NodeComponent>();

		camComponent.SetProjectionType(Nz::ProjectionType_Orthogonal);
		camComponent.SetTarget(info.renderTarget);
	}
	#endif

	Application* Application::s_application = nullptr;
}
<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

#include "TVirtualMC.h"
#include "TParticle.h"

#include "AliTrackReference.h"
#include <Riostream.h>

//
// Track Reference object is created every time particle is
// crossing detector bounds. The object is created by Step Manager
//
// The class stores the following informations:
// track label,
// track position: X,Y,X
// track momentum px, py, pz
// track length and time of fligth: both in cm
// status bits from Monte Carlo
//

ClassImp(AliTrackReference)

//_______________________________________________________________________
 AliTrackReference::AliTrackReference():
   TObject(),
   fTrack(0),
   fX(0),
   fY(0),
   fZ(0),
   fPx(0),
   fPy(0),
   fPz(0),
   fLength(0),
   fTime(0),
   fUserId(0),
   fDetectorId(-999)
{
  //
  // Default constructor
  // Creates empty object

  for(Int_t i=0; i<16; i++) ResetBit(BIT(i));
}

AliTrackReference::AliTrackReference(const AliTrackReference &tr) :
  TObject(),
  fTrack(tr.fTrack),
  fX(tr.fX),
  fY(tr.fY),
  fZ(tr.fZ),
  fPx(tr.fPx),
  fPy(tr.fPy),
  fPz(tr.fPz),
  fLength(tr.fLength),
  fTime(tr.fTime),
  fUserId(tr.fUserId),
  fDetectorId(tr.fDetectorId)
{
    // Copy Constructor
}

//_______________________________________________________________________
AliTrackReference::AliTrackReference(Int_t label, Int_t id) :
  TObject(),
  fTrack(label),
  fX(0),
  fY(0),
  fZ(0),
  fPx(0),
  fPy(0),
  fPz(0),
  fLength(gMC->TrackLength()),
  fTime(gMC->TrackTime()),
  fUserId(0),
  fDetectorId(id)
{
  //
  // Create Reference object out of label and
  // data in TVirtualMC object
  //
  // Creates an object and fill all parameters
  // from data in VirtualMC
  //
  // Sylwester Radomski, (S.Radomski@gsi.de)
  // GSI, Jan 31, 2003
  //

  Double_t vec[4];

  gMC->TrackPosition(vec[0],vec[1],vec[2]);

  fX = vec[0];
  fY = vec[1];
  fZ = vec[2];

  gMC->TrackMomentum(vec[0],vec[1],vec[2],vec[3]);

  fPx = vec[0];
  fPy = vec[1];
  fPz = vec[2];

  // Set Up status code
  // Copy Bits from virtual MC

  for(Int_t i=0; i<16; i++) ResetBit(BIT(i));

  SetBit(BIT(0), gMC->IsNewTrack());
  SetBit(BIT(1), gMC->IsTrackAlive());
  SetBit(BIT(2), gMC->IsTrackDisappeared());
  SetBit(BIT(3), gMC->IsTrackEntering());
  SetBit(BIT(4), gMC->IsTrackExiting());
  SetBit(BIT(5), gMC->IsTrackInside());
  SetBit(BIT(6), gMC->IsTrackOut());
  SetBit(BIT(7), gMC->IsTrackStop());
  //
  // This particle has to be kept

}
/*
AliExternalTrackParam * AliTrackReference::MakeTrack(const AliTrackReference *ref, Double_t mass)
{
  //
  // Make dummy track from the track reference
  // negative mass means opposite charge
  //
  Double_t xx[5];
  Double_t cc[15];
  for (Int_t i=0;i<15;i++) cc[i]=0;
  Double_t x = ref->X(), y = ref->Y(), z = ref->Z();
  Double_t alpha = TMath::ATan2(y,x);
  Double_t xr = TMath::Sqrt(x*x+y*y);
  xx[0] = ref->LocalY();
  xx[1] = z;
  xx[3] = ref->Pz()/ref->Pt();
  xx[4] = 1./ref->Pt();
  if (mass<0) xx[4]*=-1.;  // negative mass - negative direction
  Double_t alphap = TMath::ATan2(ref->Py(),ref->Px())-alpha;
  if (alphap> TMath::Pi()) alphap-=TMath::Pi();
  if (alphap<-TMath::Pi()) alphap+=TMath::Pi();
  xx[2] = TMath::Sin(alphap);

  AliExternalTrackParam * track = new  AliExternalTrackParam(xr,alpha,xx,cc);
  return track;
}
*/
//_______________________________________________________________________
void
AliTrackReference::Print(Option_t* /*opt*/) const
{
  cout << Form("Label %d P=%7.2f (PX,PY,PZ)=(%7.2f,%7.2f,%7.2f) (X,Y,Z)=(%7.2f,%7.2f,%7.2f)"
               " Length=%7.2f Time=%7.2f UserId=%d",
               Label(),P(),Px(),Py(),Pz(),X(),Y(),Z(),GetLength(),GetTime()) << endl;
}

<commit_msg>bug fix #48587 Artur Szostak <aszostak><commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

#include "TVirtualMC.h"
#include "TParticle.h"

#include "AliTrackReference.h"
#include <Riostream.h>

//
// Track Reference object is created every time particle is
// crossing detector bounds. The object is created by Step Manager
//
// The class stores the following informations:
// track label,
// track position: X,Y,X
// track momentum px, py, pz
// track length and time of fligth: both in cm
// status bits from Monte Carlo
//

ClassImp(AliTrackReference)

//_______________________________________________________________________
 AliTrackReference::AliTrackReference():
   TObject(),
   fTrack(0),
   fX(0),
   fY(0),
   fZ(0),
   fPx(0),
   fPy(0),
   fPz(0),
   fLength(0),
   fTime(0),
   fUserId(0),
   fDetectorId(-999)
{
  //
  // Default constructor
  // Creates empty object

  for(Int_t i=0; i<16; i++) ResetBit(BIT(i));
}

AliTrackReference::AliTrackReference(const AliTrackReference &tr) :
  TObject(),
  fTrack(tr.fTrack),
  fX(tr.fX),
  fY(tr.fY),
  fZ(tr.fZ),
  fPx(tr.fPx),
  fPy(tr.fPy),
  fPz(tr.fPz),
  fLength(tr.fLength),
  fTime(tr.fTime),
  fUserId(tr.fUserId),
  fDetectorId(tr.fDetectorId)
{
    // Copy Constructor
}

//_______________________________________________________________________
AliTrackReference::AliTrackReference(Int_t label, Int_t id) :
  TObject(),
  fTrack(label),
  fX(0),
  fY(0),
  fZ(0),
  fPx(0),
  fPy(0),
  fPz(0),
  fLength(gMC->TrackLength()),
  fTime(gMC->TrackTime()),
  fUserId(0),
  fDetectorId(id)
{
  //
  // Create Reference object out of label and
  // data in TVirtualMC object
  //
  // Creates an object and fill all parameters
  // from data in VirtualMC
  //
  // Sylwester Radomski, (S.Radomski@gsi.de)
  // GSI, Jan 31, 2003
  //

  Double_t vec[4];

  gMC->TrackPosition(vec[0],vec[1],vec[2]);

  fX = vec[0];
  fY = vec[1];
  fZ = vec[2];

  gMC->TrackMomentum(vec[0],vec[1],vec[2],vec[3]);

  fPx = vec[0];
  fPy = vec[1];
  fPz = vec[2];

  // Set Up status code
  // Copy Bits from virtual MC

  for(Int_t i=0; i<16; i++) ResetBit(BIT(i));

  SetBit(BIT(0), gMC->IsNewTrack());
  SetBit(BIT(1), gMC->IsTrackAlive());
  SetBit(BIT(2), gMC->IsTrackDisappeared());
  SetBit(BIT(3), gMC->IsTrackEntering());
  SetBit(BIT(4), gMC->IsTrackExiting());
  SetBit(BIT(5), gMC->IsTrackInside());
  SetBit(BIT(6), gMC->IsTrackOut());
  SetBit(BIT(7), gMC->IsTrackStop());
  //
  // This particle has to be kept

}
/*
AliExternalTrackParam * AliTrackReference::MakeTrack(const AliTrackReference *ref, Double_t mass)
{
  //
  // Make dummy track from the track reference
  // negative mass means opposite charge
  //
  Double_t xx[5];
  Double_t cc[15];
  for (Int_t i=0;i<15;i++) cc[i]=0;
  Double_t x = ref->X(), y = ref->Y(), z = ref->Z();
  Double_t alpha = TMath::ATan2(y,x);
  Double_t xr = TMath::Sqrt(x*x+y*y);
  xx[0] = ref->LocalY();
  xx[1] = z;
  xx[3] = ref->Pz()/ref->Pt();
  xx[4] = 1./ref->Pt();
  if (mass<0) xx[4]*=-1.;  // negative mass - negative direction
  Double_t alphap = TMath::ATan2(ref->Py(),ref->Px())-alpha;
  if (alphap> TMath::Pi()) alphap-=TMath::Pi();
  if (alphap<-TMath::Pi()) alphap+=TMath::Pi();
  xx[2] = TMath::Sin(alphap);

  AliExternalTrackParam * track = new  AliExternalTrackParam(xr,alpha,xx,cc);
  return track;
}
*/
//_______________________________________________________________________
void
AliTrackReference::Print(Option_t* /*opt*/) const
{
  cout << Form("Label %d P=%7.2f (PX,PY,PZ)=(%7.2f,%7.2f,%7.2f) (X,Y,Z)=(%7.2f,%7.2f,%7.2f)"
               " Length=%7.2f Time=%7.2f UserId=%d",
	       Label(),P(),Px(),Py(),Pz(),X(),Y(),Z(),GetLength(),GetTime(),UserId()) << endl;
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: addonstoolbarwrapper.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: obo $ $Date: 2004-07-06 16:52:08 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef __FRAMEWORK_UIELEMENT_ADDONSTOOLBARWRAPPER_HXX_
#define __FRAMEWORK_UIELEMENT_ADDONSTOOLBARWRAPPER_HXX_

//_________________________________________________________________________________________________________________
//  my own includes
//_________________________________________________________________________________________________________________

#ifndef __FRAMEWORK_HELPER_UIELEMENTWRAPPERBASE_HXX_
#include <helper/uielementwrapperbase.hxx>
#endif

//_________________________________________________________________________________________________________________
//  interface includes
//_________________________________________________________________________________________________________________

#ifndef _COM_SUN_STAR_FRAME_XFRAME_HPP_
#include <com/sun/star/frame/XFrame.hpp>
#endif

#ifndef _COM_SUN_STAR_LANG_XCOMPONENT_HPP_
#include <com/sun/star/lang/XComponent.hpp>
#endif

#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif

//_________________________________________________________________________________________________________________
//  other includes
//_________________________________________________________________________________________________________________

namespace framework
{

class AddonsToolBarManager;
class AddonsToolBarWrapper : public UIElementWrapperBase
{
    public:
        AddonsToolBarWrapper( const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& xServiceManager );
        virtual ~AddonsToolBarWrapper();

        // XComponent
        virtual void SAL_CALL dispose() throw (::com::sun::star::uno::RuntimeException);

        // XInitialization
        virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);

        // XUIElement
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL getRealInterface() throw (::com::sun::star::uno::RuntimeException);

    //-------------------------------------------------------------------------------------------------------------
    //  protected methods
    //-------------------------------------------------------------------------------------------------------------
    private:
        com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >                             m_xServiceManager;
        com::sun::star::uno::Reference< com::sun::star::lang::XComponent >                                       m_xToolBarManager;
        com::sun::star::uno::Reference< com::sun::star::awt::XWindow >                                           m_xToolBarWindow;
        com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue > > m_aConfigData;
};

}

#endif // __FRAMEWORK_UIELEMENT_ADDONSTOOLBARWRAPPER_HXX_
<commit_msg>INTEGRATION: CWS ooo19126 (1.2.288); FILE MERGED 2005/09/05 13:05:30 rt 1.2.288.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: addonstoolbarwrapper.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 00:41:58 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *
 ************************************************************************/

#ifndef __FRAMEWORK_UIELEMENT_ADDONSTOOLBARWRAPPER_HXX_
#define __FRAMEWORK_UIELEMENT_ADDONSTOOLBARWRAPPER_HXX_

//_________________________________________________________________________________________________________________
//  my own includes
//_________________________________________________________________________________________________________________

#ifndef __FRAMEWORK_HELPER_UIELEMENTWRAPPERBASE_HXX_
#include <helper/uielementwrapperbase.hxx>
#endif

//_________________________________________________________________________________________________________________
//  interface includes
//_________________________________________________________________________________________________________________

#ifndef _COM_SUN_STAR_FRAME_XFRAME_HPP_
#include <com/sun/star/frame/XFrame.hpp>
#endif

#ifndef _COM_SUN_STAR_LANG_XCOMPONENT_HPP_
#include <com/sun/star/lang/XComponent.hpp>
#endif

#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif

//_________________________________________________________________________________________________________________
//  other includes
//_________________________________________________________________________________________________________________

namespace framework
{

class AddonsToolBarManager;
class AddonsToolBarWrapper : public UIElementWrapperBase
{
    public:
        AddonsToolBarWrapper( const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& xServiceManager );
        virtual ~AddonsToolBarWrapper();

        // XComponent
        virtual void SAL_CALL dispose() throw (::com::sun::star::uno::RuntimeException);

        // XInitialization
        virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);

        // XUIElement
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL getRealInterface() throw (::com::sun::star::uno::RuntimeException);

    //-------------------------------------------------------------------------------------------------------------
    //  protected methods
    //-------------------------------------------------------------------------------------------------------------
    private:
        com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >                             m_xServiceManager;
        com::sun::star::uno::Reference< com::sun::star::lang::XComponent >                                       m_xToolBarManager;
        com::sun::star::uno::Reference< com::sun::star::awt::XWindow >                                           m_xToolBarWindow;
        com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue > > m_aConfigData;
};

}

#endif // __FRAMEWORK_UIELEMENT_ADDONSTOOLBARWRAPPER_HXX_
<|endoftext|>


<commit_before>// VoxEngine.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "Frames.h"
#include "GameSystem.h"
#include "InterfaceGlobals.h"
#include "OS.h"

SDL_Renderer* displayRenderer;

//A variable which at runtime can be used to figure out what version is running
int OpenglVersion;

//This should be encapsualted in a class, but... here it is
//returns NULL if that context couldn't be constructed
SDL_Window* BuildSDLContext(int openglMajorVersion, int openglMinorVersion, float requiredGLSLVersion);

//Game entry point
int main(int argc, char** argv)
{
	SDL_Init(SDL_INIT_VIDEO);

	SDL_Window * displayWindow = NULL;

#ifndef __MOBILE__
	//Build us a state of the art context
	displayWindow = BuildSDLContext(3,1,1.4);
	OpenglVersion = 31;
#endif
	//If that fails, try for something less state of the art
	if (displayWindow == NULL) {
		displayWindow = BuildSDLContext(2,0,1.1);
		OpenglVersion = 20;
	}

	if (displayWindow == NULL) {
		cout << "Failed to open any opengl context on this device. Your device is too out dated, sorry.\n";
		SDL_Quit();
		return -5;
	}

	/* Create our opengl context and attach it to our window */
	SDL_GL_CreateContext(displayWindow);

	//Start GLEW for windows/linux/OSX
#ifndef __MOBILE__
	glewExperimental = GL_TRUE;
	GLenum res = glewInit();
	if (res != GLEW_OK) {
		cout << glewGetString(GLEW_VERSION) << ", Error: " << glewGetErrorString(res) << "\n";
		return -1;
	}

	//Copied from some glue initiation code
	fprintf(stdout, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));

	if (GLEW_VERSION_3_1)
		cout << "Glew says opengl 3.1 is supported\n";

#endif

	//Setup sensible basics for opengl
	glEnable ( GL_DEPTH_TEST );
	glDepthFunc(GL_LEQUAL);
	glClearColor(.5,.5,.5,1.0);

	//Enable basic alpha blending
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	//re-enable for performance reasons after voxel system complete
	glDisable(GL_CULL_FACE);

	//Attempt to enable vsync (fails on mobile)
	SDL_GL_SetSwapInterval(1);

	//Initialze the dialog constants
	VisualInterface.init();
	//Populate the list of game systems
	Frames::BuildSystemList();

	bool continueGameLoop = true;
	//The game loop begins
	while (continueGameLoop) {
		//Determine the width,height of the draw frame
		//also used for unscaling touch events
		int width, height;
		SDL_GetWindowSize(displayWindow,&width,&height);
		vector<InputEvent> eventQueue;

		//You can poll up to 20 events per frame
		//we don't want to take all day though
		for (int i = 0; i < 20; i++) {
			//Poll for events
			SDL_Event event;
			int eventPolled = SDL_PollEvent(&event);

			if (eventPolled) {
				//Convert sdl event to InputEvent
				switch (event.type) {
				case SDL_KEYDOWN:
					eventQueue.push_back(InputEvent(InputEvent::KeyboardDown,OS::Now(),event.key.keysym.sym));
					break;
				case SDL_KEYUP:
					eventQueue.push_back(InputEvent(InputEvent::KeyboardUp,OS::Now(),event.key.keysym.sym));
					break;
				case SDL_MOUSEBUTTONDOWN:
					eventQueue.push_back(InputEvent(InputEvent::MouseDown,OS::Now(),(float)event.button.x,(float)event.button.y));
					break;
				case SDL_MOUSEBUTTONUP:
					eventQueue.push_back(InputEvent(InputEvent::MouseUp,OS::Now(),(float)event.button.x,(float)event.button.y));
					break;
				case SDL_MOUSEMOTION:
					eventQueue.push_back(InputEvent(InputEvent::MouseMove,OS::Now(),(float)event.motion.x,(float)event.motion.y));
					break;
				case SDL_FINGERMOTION:
					//cout << "MOVED: " << event.tfinger.x << "," << event.tfinger.y << "\n";
					eventQueue.push_back(InputEvent(InputEvent::MouseMove,OS::Now(),event.tfinger.x*width,event.tfinger.y*height));
					break;
				case SDL_FINGERUP:
					eventQueue.push_back(InputEvent(InputEvent::MouseUp,OS::Now(),event.tfinger.x*width,event.tfinger.y*height));
					break;
				case SDL_FINGERDOWN:
					eventQueue.push_back(InputEvent(InputEvent::MouseDown,OS::Now(),event.tfinger.x*width,event.tfinger.y*height));
					break;
				case SDL_QUIT:
					//Stops the next iteration of the game loop
					continueGameLoop = false;
					break;
				}
			}
			else
				//No more events
				break;
		}

		//Update the frame simulation (very broken)
		CurrentSystem->Update(0,0,eventQueue);
		//Run the frame draw
		glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
		//Draw
		CurrentSystem->Draw((double)width,(double)height);

		/* Swap our back buffer to the front */
		SDL_GL_SwapWindow(displayWindow);

		//Update the current system
		Frames::UpdateAliveFrame();
	}

	SDL_Quit();

	return 0;
}

//returns NULL if that context couldn't be constructed
SDL_Window* BuildSDLContext(int openglMajorVersion, int openglMinorVersion, float requiredGLSLVersion) {
	//FROM: http://www.opengl.org/wiki/Tutorial1:_Creating_a_Cross_Platform_OpenGL_3.2_Context_in_SDL_(C_/_SDL)
	//First try opengl 3.3
	/* Request opengl 3.3 context.
	 * SDL doesn't have the ability to choose which profile at this time of writing,
	 * but it should default to the core profile */
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, openglMajorVersion);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, openglMinorVersion);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);

	/* Turn on double buffering with a 24bit Z buffer.
	 * You may need to change this to 16 or 32 for your system */
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);

	SDL_Window* displayWindow;

	SDL_RendererInfo displayRendererInfo;
	SDL_CreateWindowAndRenderer(800, 600, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN, &displayWindow, &displayRenderer);
	SDL_GetRendererInfo(displayRenderer, &displayRendererInfo);
	/*TODO: Check that we have OpenGL */
	if ((displayRendererInfo.flags & SDL_RENDERER_ACCELERATED) == 0 ||
		(displayRendererInfo.flags & SDL_RENDERER_TARGETTEXTURE) == 0) {
		cout << "Failed to build context with opengl version: " << openglMajorVersion << "." << openglMinorVersion << "\n";
		SDL_DestroyWindow(displayWindow);
		return NULL;
	}
	else
		cout << "Built context with opengl version: " << openglMajorVersion << "." << openglMinorVersion << "\n";

    //Get glsl version
    float version = atof((char*)glGetString(GL_SHADING_LANGUAGE_VERSION));
    cout << "Detected GLSL version: " << version << "\n";
    if (version <= requiredGLSLVersion) {
        //Fail out, you go tthe opengl version you needed, but not glsl version
        cout << "GLSL version is insufficient for this opengl context (needs at least " << requiredGLSLVersion << ")\n";
		SDL_DestroyWindow(displayWindow);
		return NULL;
    }
	return displayWindow;
}<commit_msg>Fixed a bug which happens when the GLSL version fails to be detected.<commit_after>// VoxEngine.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "Frames.h"
#include "GameSystem.h"
#include "InterfaceGlobals.h"
#include "OS.h"

SDL_Renderer* displayRenderer;

//A variable which at runtime can be used to figure out what version is running
int OpenglVersion;

//This should be encapsualted in a class, but... here it is
//returns NULL if that context couldn't be constructed
SDL_Window* BuildSDLContext(int openglMajorVersion, int openglMinorVersion, float requiredGLSLVersion);

//Game entry point
int main(int argc, char** argv)
{
	SDL_Init(SDL_INIT_VIDEO);

	SDL_Window * displayWindow = NULL;

#ifndef __MOBILE__
	//Build us a state of the art context
	displayWindow = BuildSDLContext(3,1,1.4f);
	OpenglVersion = 31;
#endif
	//If that fails, try for something less state of the art
	if (displayWindow == NULL) {
		displayWindow = BuildSDLContext(2,0,1.1f);
		OpenglVersion = 20;
	}

	if (displayWindow == NULL) {
		cout << "Failed to open any opengl context on this device. Your device is too out dated, sorry.\n";
		SDL_Quit();
		return -5;
	}

	/* Create our opengl context and attach it to our window */
	SDL_GL_CreateContext(displayWindow);

	//Start GLEW for windows/linux/OSX
#ifndef __MOBILE__
	glewExperimental = GL_TRUE;
	GLenum res = glewInit();
	if (res != GLEW_OK) {
		cout << glewGetString(GLEW_VERSION) << ", Error: " << glewGetErrorString(res) << "\n";
		return -1;
	}

	//Copied from some glue initiation code
	fprintf(stdout, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));

	if (GLEW_VERSION_3_1)
		cout << "Glew says opengl 3.1 is supported\n";

#endif

	//Setup sensible basics for opengl
	glEnable ( GL_DEPTH_TEST );
	glDepthFunc(GL_LEQUAL);
	glClearColor(.5,.5,.5,1.0);

	//Enable basic alpha blending
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	//re-enable for performance reasons after voxel system complete
	glDisable(GL_CULL_FACE);

	//Attempt to enable vsync (fails on mobile)
	SDL_GL_SetSwapInterval(1);

	//Initialze the dialog constants
	VisualInterface.init();
	//Populate the list of game systems
	Frames::BuildSystemList();

	bool continueGameLoop = true;
	//The game loop begins
	while (continueGameLoop) {
		//Determine the width,height of the draw frame
		//also used for unscaling touch events
		int width, height;
		SDL_GetWindowSize(displayWindow,&width,&height);
		vector<InputEvent> eventQueue;

		//You can poll up to 20 events per frame
		//we don't want to take all day though
		for (int i = 0; i < 20; i++) {
			//Poll for events
			SDL_Event event;
			int eventPolled = SDL_PollEvent(&event);

			if (eventPolled) {
				//Convert sdl event to InputEvent
				switch (event.type) {
				case SDL_KEYDOWN:
					eventQueue.push_back(InputEvent(InputEvent::KeyboardDown,OS::Now(),event.key.keysym.sym));
					break;
				case SDL_KEYUP:
					eventQueue.push_back(InputEvent(InputEvent::KeyboardUp,OS::Now(),event.key.keysym.sym));
					break;
				case SDL_MOUSEBUTTONDOWN:
					eventQueue.push_back(InputEvent(InputEvent::MouseDown,OS::Now(),(float)event.button.x,(float)event.button.y));
					break;
				case SDL_MOUSEBUTTONUP:
					eventQueue.push_back(InputEvent(InputEvent::MouseUp,OS::Now(),(float)event.button.x,(float)event.button.y));
					break;
				case SDL_MOUSEMOTION:
					eventQueue.push_back(InputEvent(InputEvent::MouseMove,OS::Now(),(float)event.motion.x,(float)event.motion.y));
					break;
				case SDL_FINGERMOTION:
					//cout << "MOVED: " << event.tfinger.x << "," << event.tfinger.y << "\n";
					eventQueue.push_back(InputEvent(InputEvent::MouseMove,OS::Now(),event.tfinger.x*width,event.tfinger.y*height));
					break;
				case SDL_FINGERUP:
					eventQueue.push_back(InputEvent(InputEvent::MouseUp,OS::Now(),event.tfinger.x*width,event.tfinger.y*height));
					break;
				case SDL_FINGERDOWN:
					eventQueue.push_back(InputEvent(InputEvent::MouseDown,OS::Now(),event.tfinger.x*width,event.tfinger.y*height));
					break;
				case SDL_QUIT:
					//Stops the next iteration of the game loop
					continueGameLoop = false;
					break;
				}
			}
			else
				//No more events
				break;
		}

		//Update the frame simulation (very broken)
		CurrentSystem->Update(0,0,eventQueue);
		//Run the frame draw
		glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
		//Draw
		CurrentSystem->Draw((double)width,(double)height);

		/* Swap our back buffer to the front */
		SDL_GL_SwapWindow(displayWindow);

		//Update the current system
		Frames::UpdateAliveFrame();
	}

	SDL_Quit();

	return 0;
}

//returns NULL if that context couldn't be constructed
SDL_Window* BuildSDLContext(int openglMajorVersion, int openglMinorVersion, float requiredGLSLVersion) {
	//FROM: http://www.opengl.org/wiki/Tutorial1:_Creating_a_Cross_Platform_OpenGL_3.2_Context_in_SDL_(C_/_SDL)
	//First try opengl 3.3
	/* Request opengl 3.3 context.
	 * SDL doesn't have the ability to choose which profile at this time of writing,
	 * but it should default to the core profile */
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, openglMajorVersion);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, openglMinorVersion);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);

	/* Turn on double buffering with a 24bit Z buffer.
	 * You may need to change this to 16 or 32 for your system */
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);

	SDL_Window* displayWindow;

	SDL_RendererInfo displayRendererInfo;
	SDL_CreateWindowAndRenderer(800, 600, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN, &displayWindow, &displayRenderer);
	SDL_GetRendererInfo(displayRenderer, &displayRendererInfo);
	/*TODO: Check that we have OpenGL */
	if ((displayRendererInfo.flags & SDL_RENDERER_ACCELERATED) == 0 ||
		(displayRendererInfo.flags & SDL_RENDERER_TARGETTEXTURE) == 0) {
		cout << "Failed to build context with opengl version: " << openglMajorVersion << "." << openglMinorVersion << "\n";
		SDL_DestroyWindow(displayWindow);
		return NULL;
	}
	else
		cout << "Built context with opengl version: " << openglMajorVersion << "." << openglMinorVersion << "\n";

	//Get glsl version
	char * versionString = (char*)glGetString(GL_SHADING_LANGUAGE_VERSION);
	//For some reason (I blame glew) glGetString returns NULL sometimes
	if (versionString == NULL)
		cout << "GLSL version check failed, lets just hope we have a recent enough one...\n";
	else {
		//Verify the version is correct
		float version = (float)atof(versionString);
		cout << "Detected GLSL version: " << version << "\n";
		if (version <= requiredGLSLVersion) {
			//Fail out, you go tthe opengl version you needed, but not glsl version
			cout << "GLSL version is insufficient for this opengl context (needs at least " << requiredGLSLVersion << ")\n";
			SDL_DestroyWindow(displayWindow);
			return NULL;
		}
	}

	return displayWindow;
}<|endoftext|>


<commit_before>/*
    Copyright (C) 2010-2011 Collabora Ltd.
      @author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>

    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 program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "structs.h"
#include "miniobject.h"
#include "structure.h"
#include "../QGlib/value.h"
#include <cmath>
#include <gst/gstvalue.h>
#include <gst/gstminiobject.h>
#include <gst/gstdatetime.h>

namespace QGlib {

GetTypeImpl<QDate>::operator Type() { return GST_TYPE_DATE; }
GetTypeImpl<QDateTime>::operator Type() { return GST_TYPE_DATE_TIME; }

} //namespace QGlib

namespace QGst {
namespace Private {

void registerValueVTables()
{
    struct ValueVTable_MiniObject
    {
        static void get(const QGlib::Value & value, void *data)
        {
            *reinterpret_cast<GstMiniObject**>(data) = gst_value_get_mini_object(value);
        };

        static void set(QGlib::Value & value, const void *data)
        {
            gst_value_set_mini_object(value, *reinterpret_cast<GstMiniObject* const *>(data));
        };
    };
    QGlib::Value::registerValueVTable(QGlib::GetType<MiniObject>(),
            QGlib::ValueVTable(ValueVTable_MiniObject::set, ValueVTable_MiniObject::get));

    struct ValueVTable_Fraction
    {
        static void get(const QGlib::Value & value, void *data)
        {
            reinterpret_cast<Fraction*>(data)->numerator = gst_value_get_fraction_numerator(value);
            reinterpret_cast<Fraction*>(data)->denominator = gst_value_get_fraction_denominator(value);
        };

        static void set(QGlib::Value & value, const void *data)
        {
            gst_value_set_fraction(value, reinterpret_cast<Fraction const *>(data)->numerator,
                                          reinterpret_cast<Fraction const *>(data)->denominator);
        };
    };
    QGlib::Value::registerValueVTable(QGlib::GetType<Fraction>(),
            QGlib::ValueVTable(ValueVTable_Fraction::set, ValueVTable_Fraction::get));

    struct ValueVTable_IntRange
    {
        static void get(const QGlib::Value & value, void *data)
        {
            reinterpret_cast<IntRange*>(data)->start = gst_value_get_int_range_min(value);
            reinterpret_cast<IntRange*>(data)->end = gst_value_get_int_range_max(value);
        };

        static void set(QGlib::Value & value, const void *data)
        {
            gst_value_set_int_range(value, reinterpret_cast<IntRange const *>(data)->start,
                                           reinterpret_cast<IntRange const *>(data)->end);
        };
    };
    QGlib::Value::registerValueVTable(QGlib::GetType<IntRange>(),
            QGlib::ValueVTable(ValueVTable_IntRange::set, ValueVTable_IntRange::get));

    struct ValueVTable_Int64Range
    {
        static void get(const QGlib::Value & value, void *data)
        {
            reinterpret_cast<Int64Range*>(data)->start = gst_value_get_int64_range_min(value);
            reinterpret_cast<Int64Range*>(data)->end = gst_value_get_int64_range_max(value);
        };

        static void set(QGlib::Value & value, const void *data)
        {
            gst_value_set_int64_range(value, reinterpret_cast<Int64Range const *>(data)->start,
                                             reinterpret_cast<Int64Range const *>(data)->end);
        };
    };
    QGlib::Value::registerValueVTable(QGlib::GetType<Int64Range>(),
            QGlib::ValueVTable(ValueVTable_Int64Range::set, ValueVTable_Int64Range::get));

    struct ValueVTable_DoubleRange
    {
        static void get(const QGlib::Value & value, void *data)
        {
            reinterpret_cast<DoubleRange*>(data)->start = gst_value_get_double_range_min(value);
            reinterpret_cast<DoubleRange*>(data)->end = gst_value_get_double_range_max(value);
        };

        static void set(QGlib::Value & value, const void *data)
        {
            gst_value_set_double_range(value, reinterpret_cast<DoubleRange const *>(data)->start,
                                              reinterpret_cast<DoubleRange const *>(data)->end);
        };
    };
    QGlib::Value::registerValueVTable(QGlib::GetType<DoubleRange>(),
            QGlib::ValueVTable(ValueVTable_DoubleRange::set, ValueVTable_DoubleRange::get));

    struct ValueVTable_FractionRange
    {
        static void get(const QGlib::Value & value, void *data)
        {
            reinterpret_cast<FractionRange*>(data)->start.numerator =
                gst_value_get_fraction_numerator(gst_value_get_fraction_range_min(value));
            reinterpret_cast<FractionRange*>(data)->start.denominator =
                gst_value_get_fraction_denominator(gst_value_get_fraction_range_min(value));
            reinterpret_cast<FractionRange*>(data)->end.numerator =
                gst_value_get_fraction_numerator(gst_value_get_fraction_range_max(value));
            reinterpret_cast<FractionRange*>(data)->end.denominator =
                gst_value_get_fraction_denominator(gst_value_get_fraction_range_max(value));
        };

        static void set(QGlib::Value & value, const void *data)
        {
            gst_value_set_fraction_range_full(value,
                    reinterpret_cast<FractionRange const *>(data)->start.numerator,
                    reinterpret_cast<FractionRange const *>(data)->start.denominator,
                    reinterpret_cast<FractionRange const *>(data)->end.numerator,
                    reinterpret_cast<FractionRange const *>(data)->end.denominator);
        };
    };
    QGlib::Value::registerValueVTable(QGlib::GetType<FractionRange>(),
            QGlib::ValueVTable(ValueVTable_FractionRange::set, ValueVTable_FractionRange::get));

    struct ValueVTable_Structure
    {
        static void get(const QGlib::Value & value, void *data)
        {
            *reinterpret_cast<Structure*>(data) = Structure(gst_value_get_structure(value));
        };

        static void set(QGlib::Value & value, const void *data)
        {
            gst_value_set_structure(value, *reinterpret_cast<Structure const *>(data));
        };
    };
    QGlib::Value::registerValueVTable(QGlib::GetType<Structure>(),
            QGlib::ValueVTable(ValueVTable_Structure::set, ValueVTable_Structure::get));

    struct ValueVTable_QDate
    {
        static void get(const QGlib::Value & value, void *data)
        {
            const GDate *gdate = gst_value_get_date(value);
            *reinterpret_cast<QDate*>(data) = QDate(g_date_get_year(gdate),
                                                    g_date_get_month(gdate),
                                                    g_date_get_day(gdate));
        }

        static void set(QGlib::Value & value, const void *data)
        {
            const QDate *qdate = reinterpret_cast<QDate const *>(data);
            GDate *gdate = g_date_new_dmy(qdate->day(),
                                          static_cast<GDateMonth>(qdate->month()),
                                          qdate->year());
            gst_value_set_date(value, gdate);
            g_date_free(gdate);
        }
    };
    QGlib::Value::registerValueVTable(QGlib::GetType<QDate>(),
            QGlib::ValueVTable(ValueVTable_QDate::set, ValueVTable_QDate::get));

    struct ValueVTable_QDateTime
    {
        static void get(const QGlib::Value & value, void *data)
        {
            const GstDateTime *gdatetime = static_cast<GstDateTime*>(g_value_get_boxed(value));

            QDate date = QDate(gst_date_time_get_year(gdatetime),
                               gst_date_time_get_month(gdatetime),
                               gst_date_time_get_day(gdatetime));

            /* timezone conversion */
            float tzoffset = gst_date_time_get_time_zone_offset(gdatetime);
            float hourOffset;
            float minutesOffset = std::modf(tzoffset, &hourOffset);

            int hour = gst_date_time_get_hour(gdatetime) - hourOffset;
            int minute = gst_date_time_get_minute(gdatetime) - (minutesOffset * 60);

            /* handle overflow */
            if (minute >= 60) {
                hour++;
                minute -= 60;
            } else if (minute < 0) {
                hour--;
                minute = 60 + minute;
            }

            if (hour >= 24) {
                date = date.addDays(1);
                hour -= 24;
            } else if (hour < 0) {
                date = date.addDays(-1);
                hour = 24 + hour;
            }

            QTime time = QTime(hour, minute,
                               gst_date_time_get_second(gdatetime),
                               gst_date_time_get_microsecond(gdatetime)/1000);

            *reinterpret_cast<QDateTime*>(data) = QDateTime(date, time, Qt::UTC);
        }

        static void set(QGlib::Value & value, const void *data)
        {
            QDateTime qdatetime = reinterpret_cast<QDateTime const *>(data)->toUTC();
            GstDateTime *gdatetime = gst_date_time_new(0.0f,
                qdatetime.date().year(),
                qdatetime.date().month(),
                qdatetime.date().day(),
                qdatetime.time().hour(),
                qdatetime.time().minute(),
                qdatetime.time().second() + (qdatetime.time().msec()/1000.0)
            );

            g_value_take_boxed(value, gdatetime);
        }
    };
    QGlib::Value::registerValueVTable(QGlib::GetType<QDateTime>(),
            QGlib::ValueVTable(ValueVTable_QDateTime::set, ValueVTable_QDateTime::get));
}

} //namespace Private
} //namespace QGst
<commit_msg>src/QGst/value.cpp Adjust MiniObject vtable to use the get/set_boxed functions.<commit_after>/*
    Copyright (C) 2010-2011 Collabora Ltd.
      @author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>

    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 program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "structs.h"
#include "miniobject.h"
#include "structure.h"
#include "../QGlib/value.h"
#include <cmath>
#include <gst/gstvalue.h>
#include <gst/gstminiobject.h>
#include <gst/gstdatetime.h>

namespace QGlib {

GetTypeImpl<QDate>::operator Type() { return GST_TYPE_DATE; }
GetTypeImpl<QDateTime>::operator Type() { return GST_TYPE_DATE_TIME; }

} //namespace QGlib

namespace QGst {
namespace Private {

void registerValueVTables()
{
    struct ValueVTable_MiniObject
    {
        static void get(const QGlib::Value & value, void *data)
        {
	    *reinterpret_cast<GstMiniObject **>(data) = static_cast<GstMiniObject *>(g_value_get_boxed(value));
        };

        static void set(QGlib::Value & value, const void *data)
        {
            g_value_set_boxed(value, *reinterpret_cast<GstMiniObject * const *>(data));
        };
    };
    QGlib::Value::registerValueVTable(QGlib::GetType<MiniObject>(),
            QGlib::ValueVTable(ValueVTable_MiniObject::set, ValueVTable_MiniObject::get));

    struct ValueVTable_Fraction
    {
        static void get(const QGlib::Value & value, void *data)
        {
            reinterpret_cast<Fraction*>(data)->numerator = gst_value_get_fraction_numerator(value);
            reinterpret_cast<Fraction*>(data)->denominator = gst_value_get_fraction_denominator(value);
        };

        static void set(QGlib::Value & value, const void *data)
        {
            gst_value_set_fraction(value, reinterpret_cast<Fraction const *>(data)->numerator,
                                          reinterpret_cast<Fraction const *>(data)->denominator);
        };
    };
    QGlib::Value::registerValueVTable(QGlib::GetType<Fraction>(),
            QGlib::ValueVTable(ValueVTable_Fraction::set, ValueVTable_Fraction::get));

    struct ValueVTable_IntRange
    {
        static void get(const QGlib::Value & value, void *data)
        {
            reinterpret_cast<IntRange*>(data)->start = gst_value_get_int_range_min(value);
            reinterpret_cast<IntRange*>(data)->end = gst_value_get_int_range_max(value);
        };

        static void set(QGlib::Value & value, const void *data)
        {
            gst_value_set_int_range(value, reinterpret_cast<IntRange const *>(data)->start,
                                           reinterpret_cast<IntRange const *>(data)->end);
        };
    };
    QGlib::Value::registerValueVTable(QGlib::GetType<IntRange>(),
            QGlib::ValueVTable(ValueVTable_IntRange::set, ValueVTable_IntRange::get));

    struct ValueVTable_Int64Range
    {
        static void get(const QGlib::Value & value, void *data)
        {
            reinterpret_cast<Int64Range*>(data)->start = gst_value_get_int64_range_min(value);
            reinterpret_cast<Int64Range*>(data)->end = gst_value_get_int64_range_max(value);
        };

        static void set(QGlib::Value & value, const void *data)
        {
            gst_value_set_int64_range(value, reinterpret_cast<Int64Range const *>(data)->start,
                                             reinterpret_cast<Int64Range const *>(data)->end);
        };
    };
    QGlib::Value::registerValueVTable(QGlib::GetType<Int64Range>(),
            QGlib::ValueVTable(ValueVTable_Int64Range::set, ValueVTable_Int64Range::get));

    struct ValueVTable_DoubleRange
    {
        static void get(const QGlib::Value & value, void *data)
        {
            reinterpret_cast<DoubleRange*>(data)->start = gst_value_get_double_range_min(value);
            reinterpret_cast<DoubleRange*>(data)->end = gst_value_get_double_range_max(value);
        };

        static void set(QGlib::Value & value, const void *data)
        {
            gst_value_set_double_range(value, reinterpret_cast<DoubleRange const *>(data)->start,
                                              reinterpret_cast<DoubleRange const *>(data)->end);
        };
    };
    QGlib::Value::registerValueVTable(QGlib::GetType<DoubleRange>(),
            QGlib::ValueVTable(ValueVTable_DoubleRange::set, ValueVTable_DoubleRange::get));

    struct ValueVTable_FractionRange
    {
        static void get(const QGlib::Value & value, void *data)
        {
            reinterpret_cast<FractionRange*>(data)->start.numerator =
                gst_value_get_fraction_numerator(gst_value_get_fraction_range_min(value));
            reinterpret_cast<FractionRange*>(data)->start.denominator =
                gst_value_get_fraction_denominator(gst_value_get_fraction_range_min(value));
            reinterpret_cast<FractionRange*>(data)->end.numerator =
                gst_value_get_fraction_numerator(gst_value_get_fraction_range_max(value));
            reinterpret_cast<FractionRange*>(data)->end.denominator =
                gst_value_get_fraction_denominator(gst_value_get_fraction_range_max(value));
        };

        static void set(QGlib::Value & value, const void *data)
        {
            gst_value_set_fraction_range_full(value,
                    reinterpret_cast<FractionRange const *>(data)->start.numerator,
                    reinterpret_cast<FractionRange const *>(data)->start.denominator,
                    reinterpret_cast<FractionRange const *>(data)->end.numerator,
                    reinterpret_cast<FractionRange const *>(data)->end.denominator);
        };
    };
    QGlib::Value::registerValueVTable(QGlib::GetType<FractionRange>(),
            QGlib::ValueVTable(ValueVTable_FractionRange::set, ValueVTable_FractionRange::get));

    struct ValueVTable_Structure
    {
        static void get(const QGlib::Value & value, void *data)
        {
            *reinterpret_cast<Structure*>(data) = Structure(gst_value_get_structure(value));
        };

        static void set(QGlib::Value & value, const void *data)
        {
            gst_value_set_structure(value, *reinterpret_cast<Structure const *>(data));
        };
    };
    QGlib::Value::registerValueVTable(QGlib::GetType<Structure>(),
            QGlib::ValueVTable(ValueVTable_Structure::set, ValueVTable_Structure::get));

    struct ValueVTable_QDate
    {
        static void get(const QGlib::Value & value, void *data)
        {
            const GDate *gdate = gst_value_get_date(value);
            *reinterpret_cast<QDate*>(data) = QDate(g_date_get_year(gdate),
                                                    g_date_get_month(gdate),
                                                    g_date_get_day(gdate));
        }

        static void set(QGlib::Value & value, const void *data)
        {
            const QDate *qdate = reinterpret_cast<QDate const *>(data);
            GDate *gdate = g_date_new_dmy(qdate->day(),
                                          static_cast<GDateMonth>(qdate->month()),
                                          qdate->year());
            gst_value_set_date(value, gdate);
            g_date_free(gdate);
        }
    };
    QGlib::Value::registerValueVTable(QGlib::GetType<QDate>(),
            QGlib::ValueVTable(ValueVTable_QDate::set, ValueVTable_QDate::get));

    struct ValueVTable_QDateTime
    {
        static void get(const QGlib::Value & value, void *data)
        {
            const GstDateTime *gdatetime = static_cast<GstDateTime*>(g_value_get_boxed(value));

            QDate date = QDate(gst_date_time_get_year(gdatetime),
                               gst_date_time_get_month(gdatetime),
                               gst_date_time_get_day(gdatetime));

            /* timezone conversion */
            float tzoffset = gst_date_time_get_time_zone_offset(gdatetime);
            float hourOffset;
            float minutesOffset = std::modf(tzoffset, &hourOffset);

            int hour = gst_date_time_get_hour(gdatetime) - hourOffset;
            int minute = gst_date_time_get_minute(gdatetime) - (minutesOffset * 60);

            /* handle overflow */
            if (minute >= 60) {
                hour++;
                minute -= 60;
            } else if (minute < 0) {
                hour--;
                minute = 60 + minute;
            }

            if (hour >= 24) {
                date = date.addDays(1);
                hour -= 24;
            } else if (hour < 0) {
                date = date.addDays(-1);
                hour = 24 + hour;
            }

            QTime time = QTime(hour, minute,
                               gst_date_time_get_second(gdatetime),
                               gst_date_time_get_microsecond(gdatetime)/1000);

            *reinterpret_cast<QDateTime*>(data) = QDateTime(date, time, Qt::UTC);
        }

        static void set(QGlib::Value & value, const void *data)
        {
            QDateTime qdatetime = reinterpret_cast<QDateTime const *>(data)->toUTC();
            GstDateTime *gdatetime = gst_date_time_new(0.0f,
                qdatetime.date().year(),
                qdatetime.date().month(),
                qdatetime.date().day(),
                qdatetime.time().hour(),
                qdatetime.time().minute(),
                qdatetime.time().second() + (qdatetime.time().msec()/1000.0)
            );

            g_value_take_boxed(value, gdatetime);
        }
    };
    QGlib::Value::registerValueVTable(QGlib::GetType<QDateTime>(),
            QGlib::ValueVTable(ValueVTable_QDateTime::set, ValueVTable_QDateTime::get));
}

} //namespace Private
} //namespace QGst
<|endoftext|>


<commit_before>//
//  ZX8081.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 07/06/2017.
//  Copyright © 2017 Thomas Harte. All rights reserved.
//

#include "ZX8081.hpp"

using namespace Storage::Tape::ZX8081;

Parser::Parser() : pulse_was_high_(false), pulse_time_(0) {}

void Parser::process_pulse(Storage::Tape::Tape::Pulse pulse) {
	pulse_time_ += pulse.length;
	bool pulse_is_high = pulse.type == Storage::Tape::Tape::Pulse::High;

	if(pulse_is_high == pulse_was_high_) return;
	pulse_was_high_ = pulse_is_high;
	post_pulse();
}

void Parser::post_pulse() {
	const float expected_pulse_length = 150.0f / 1000000.0f;
	const float expected_gap_length = 1300.0f / 1000000.0f;
	float pulse_time = pulse_time_.get_float();
	pulse_time_.set_zero();

	if(pulse_time > expected_gap_length * 1.25f) {
		push_wave(WaveType::LongGap);
	}
	else if(pulse_time > expected_pulse_length * 1.25f) {
		push_wave(WaveType::Gap);
	}
	else if(pulse_time >= expected_pulse_length * 0.75f && pulse_time <= expected_pulse_length * 1.25f) {
		push_wave(WaveType::Pulse);
	}
	else {
		push_wave(WaveType::Unrecognised);
	}
}

void Parser::mark_end() {
	// Push the last thing detected, and post an 'unrecognised' to ensure
	// the queue empties out.
	post_pulse();
	push_wave(WaveType::Unrecognised);
}

void Parser::inspect_waves(const std::vector<WaveType> &waves) {
	// A long gap is a file gap.
	if(waves[0] == WaveType::LongGap) {
		push_symbol(SymbolType::FileGap, 1);
		return;
	}

	if(waves.size() >= 9) {
		size_t wave_offset = 0;
		// If the very first thing is a gap, swallow it.
		if(waves[0] == WaveType::Gap) {
			wave_offset = 1;
		}

		// Count the number of pulses at the start of this vector
		size_t number_of_pulses = 0;
		while(waves[number_of_pulses + wave_offset] == WaveType::Pulse && number_of_pulses < waves.size()) {
			number_of_pulses++;
		}

		// If those pulses were followed by a gap then they might be
		// a recognised symbol.
		if(number_of_pulses > 17 || number_of_pulses < 7) {
			push_symbol(SymbolType::Unrecognised, 1);
		}
		else if(number_of_pulses + wave_offset < waves.size() &&
			(waves[number_of_pulses + wave_offset] == WaveType::LongGap || waves[number_of_pulses + wave_offset] == WaveType::Gap)) {
			// A 1 is 18 up/down waves, a 0 is 8. But the final down will be indistinguishable from
			// the gap that follows the bit due to the simplified "high is high, everything else is low"
			// logic applied to pulse detection. So those two things will merge. Meaning we're looking for
			// 17 and/or 7 pulses.
			int gaps_to_swallow = (int)wave_offset + ((waves[number_of_pulses + wave_offset] == WaveType::Gap) ? 1 : 0);
			switch(number_of_pulses) {
				case 17:	push_symbol(SymbolType::One, 17 + gaps_to_swallow);	break;
				case 7:		push_symbol(SymbolType::Zero, 7 + gaps_to_swallow);	break;
				default:	push_symbol(SymbolType::Unrecognised, 1);			break;
			}
		}
	}
}

int Parser::get_next_byte(const std::shared_ptr<Storage::Tape::Tape> &tape) {
	int c = 8;
	int result = 0;
	while(c--) {
		if(is_at_end(tape)) return -1;
		SymbolType symbol = get_next_symbol(tape);
		if(symbol == SymbolType::FileGap) {
			return_symbol(symbol);
			return -1;
		}
		if(symbol != SymbolType::One && symbol != SymbolType::Zero) {
			return -1;
		}
		result = (result << 1) | (symbol == SymbolType::One ? 1 : 0);
	}
	return result;
}

std::shared_ptr<std::vector<uint8_t>> Parser::get_next_file_data(const std::shared_ptr<Storage::Tape::Tape> &tape) {
	if(is_at_end(tape)) return nullptr;
	SymbolType symbol = get_next_symbol(tape);
	if(symbol != SymbolType::FileGap) {
		return nullptr;
	}
	while(symbol == SymbolType::FileGap && !is_at_end(tape)) {
		symbol = get_next_symbol(tape);
	}
	if(is_at_end(tape)) return nullptr;
	return_symbol(symbol);

	std::shared_ptr<std::vector<uint8_t>> result(new std::vector<uint8_t>);
	int byte;
	while(!is_at_end(tape)) {
		byte = get_next_byte(tape);
		if(byte == -1) return result;
		result->push_back((uint8_t)byte);
	}
	return result;
}

std::shared_ptr<Storage::Data::ZX8081::File> Parser::get_next_file(const std::shared_ptr<Storage::Tape::Tape> &tape) {
	std::shared_ptr<std::vector<uint8_t>> file_data = get_next_file_data(tape);
	if(!file_data) return nullptr;
	return Storage::Data::ZX8081::FileFromData(*file_data);
}
<commit_msg>Fixed dumb out-of-bounds access error.<commit_after>//
//  ZX8081.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 07/06/2017.
//  Copyright © 2017 Thomas Harte. All rights reserved.
//

#include "ZX8081.hpp"

using namespace Storage::Tape::ZX8081;

Parser::Parser() : pulse_was_high_(false), pulse_time_(0) {}

void Parser::process_pulse(Storage::Tape::Tape::Pulse pulse) {
	pulse_time_ += pulse.length;
	bool pulse_is_high = pulse.type == Storage::Tape::Tape::Pulse::High;

	if(pulse_is_high == pulse_was_high_) return;
	pulse_was_high_ = pulse_is_high;
	post_pulse();
}

void Parser::post_pulse() {
	const float expected_pulse_length = 150.0f / 1000000.0f;
	const float expected_gap_length = 1300.0f / 1000000.0f;
	float pulse_time = pulse_time_.get_float();
	pulse_time_.set_zero();

	if(pulse_time > expected_gap_length * 1.25f) {
		push_wave(WaveType::LongGap);
	}
	else if(pulse_time > expected_pulse_length * 1.25f) {
		push_wave(WaveType::Gap);
	}
	else if(pulse_time >= expected_pulse_length * 0.75f && pulse_time <= expected_pulse_length * 1.25f) {
		push_wave(WaveType::Pulse);
	}
	else {
		push_wave(WaveType::Unrecognised);
	}
}

void Parser::mark_end() {
	// Push the last thing detected, and post an 'unrecognised' to ensure
	// the queue empties out.
	post_pulse();
	push_wave(WaveType::Unrecognised);
}

void Parser::inspect_waves(const std::vector<WaveType> &waves) {
	// A long gap is a file gap.
	if(waves[0] == WaveType::LongGap) {
		push_symbol(SymbolType::FileGap, 1);
		return;
	}

	if(waves.size() >= 9) {
		size_t wave_offset = 0;
		// If the very first thing is a gap, swallow it.
		if(waves[0] == WaveType::Gap) {
			wave_offset = 1;
		}

		// Count the number of pulses at the start of this vector
		size_t number_of_pulses = 0;
		while(number_of_pulses + wave_offset < waves.size() && waves[number_of_pulses + wave_offset] == WaveType::Pulse) {
			number_of_pulses++;
		}

		// If those pulses were followed by a gap then they might be
		// a recognised symbol.
		if(number_of_pulses > 17 || number_of_pulses < 7) {
			push_symbol(SymbolType::Unrecognised, 1);
		}
		else if(number_of_pulses + wave_offset < waves.size() &&
			(waves[number_of_pulses + wave_offset] == WaveType::LongGap || waves[number_of_pulses + wave_offset] == WaveType::Gap)) {
			// A 1 is 18 up/down waves, a 0 is 8. But the final down will be indistinguishable from
			// the gap that follows the bit due to the simplified "high is high, everything else is low"
			// logic applied to pulse detection. So those two things will merge. Meaning we're looking for
			// 17 and/or 7 pulses.
			int gaps_to_swallow = (int)wave_offset + ((waves[number_of_pulses + wave_offset] == WaveType::Gap) ? 1 : 0);
			switch(number_of_pulses) {
				case 17:	push_symbol(SymbolType::One, 17 + gaps_to_swallow);	break;
				case 7:		push_symbol(SymbolType::Zero, 7 + gaps_to_swallow);	break;
				default:	push_symbol(SymbolType::Unrecognised, 1);			break;
			}
		}
	}
}

int Parser::get_next_byte(const std::shared_ptr<Storage::Tape::Tape> &tape) {
	int c = 8;
	int result = 0;
	while(c--) {
		if(is_at_end(tape)) return -1;
		SymbolType symbol = get_next_symbol(tape);
		if(symbol == SymbolType::FileGap) {
			return_symbol(symbol);
			return -1;
		}
		if(symbol != SymbolType::One && symbol != SymbolType::Zero) {
			return -1;
		}
		result = (result << 1) | (symbol == SymbolType::One ? 1 : 0);
	}
	return result;
}

std::shared_ptr<std::vector<uint8_t>> Parser::get_next_file_data(const std::shared_ptr<Storage::Tape::Tape> &tape) {
	if(is_at_end(tape)) return nullptr;
	SymbolType symbol = get_next_symbol(tape);
	if(symbol != SymbolType::FileGap) {
		return nullptr;
	}
	while(symbol == SymbolType::FileGap && !is_at_end(tape)) {
		symbol = get_next_symbol(tape);
	}
	if(is_at_end(tape)) return nullptr;
	return_symbol(symbol);

	std::shared_ptr<std::vector<uint8_t>> result(new std::vector<uint8_t>);
	int byte;
	while(!is_at_end(tape)) {
		byte = get_next_byte(tape);
		if(byte == -1) return result;
		result->push_back((uint8_t)byte);
	}
	return result;
}

std::shared_ptr<Storage::Data::ZX8081::File> Parser::get_next_file(const std::shared_ptr<Storage::Tape::Tape> &tape) {
	std::shared_ptr<std::vector<uint8_t>> file_data = get_next_file_data(tape);
	if(!file_data) return nullptr;
	return Storage::Data::ZX8081::FileFromData(*file_data);
}
<|endoftext|>


<commit_before>#include "Rasterizer.hpp"
#include <cmath>
#include <algorithm>
#include <float.h>
#include <cstdio>
#include <cassert>
#include "stb_image.h"

using std::modf;

Rasterizer::Rasterizer(void* pixels) :
m_pixels(static_cast<unsigned*>(pixels))
{
    int n;
    m_texture = stbi_load("texture.png", &m_texx, &m_texy, &n, 3);
    m_mode = ERM_TEXTURES;
}

Rasterizer::~Rasterizer()
{
    stbi_image_free(m_texture);
}

static inline float crossProduct(float ax, float ay, float bx, float by)
{
    return ax * by - ay * bx;
}

static inline int min(int a, int b, int c)
{
    return std::min(a, std::min(b, c));
}

static inline int max(int a, int b, int c)
{
    return std::max(a, std::max(b, c));
}

static inline void sepcolor(unsigned c, int& r, int& g, int& b)
{
    r = (c >> 16) & 0xff;
    g = (c >> 8) & 0xff;
    b = (c >> 0) & 0xff;
}

static inline unsigned mix3colors(unsigned c1, float v1, unsigned c2, float v2, unsigned c3, float v3)
{
    int r1, g1, b1;
    int r2, g2, b2;
    int r3, g3, b3;
    sepcolor(c1, r1, g1, b1);
    sepcolor(c2, r2, g2, b2);
    sepcolor(c3, r3, g3, b3);
    int rf = r1 * v1 + r2 * v2 + r3 * v3;
    int gf = g1 * v1 + g2 * v2 + g3 * v3;
    int bf = b1 * v1 + b2 * v2 + b3 * v3;
    return (rf << 16) + (gf << 8) + bf;
}

static inline unsigned mul2colors(unsigned c1, unsigned c2)
{
    int r1, g1, b1;
    int r2, g2, b2;
    sepcolor(c1, r1, g1, b1);
    sepcolor(c2, r2, g2, b2);
    int rf = (r1 * r2) / 255;
    int gf = (g1 * g2) / 255;
    int bf = (b1 * b2) / 255;
    assert(0 <= rf && rf <= 255);
    assert(0 <= gf && gf <= 255);
    assert(0 <= bf && bf <= 255);
    return (rf << 16) + (gf << 8) + bf;
}

static void adjustToView(int& x1, int& y1, int& x2, int& y2)
{
    x1 = std::max(0, std::min(x1, 640 - 1));
    y1 = std::max(0, std::min(y1, 480 - 1));
    x2 = std::max(0, std::min(x2, 640 - 1));
    y2 = std::max(0, std::min(y2, 480 - 1));
}

static unsigned rgbf(float r, float g, float b)
{
    const int rf = std::max(0, std::min<int>(255, r * 255.f));
    const int gf = std::max(0, std::min<int>(255, g * 255.f));
    const int bf = std::max(0, std::min<int>(255, b * 255.f));
    return (rf << 16) + (gf << 8) + bf;
}

static float normalizeTCoords(float x)
{
    float u;
    x = modf(x, &u);
    return std::fabs(x);
}

void Rasterizer::rasterize()
{
    for(int i = 0; i < 640 * 480; ++i)
        m_depthbuffer[i] = FLT_MAX;

    for(int i = 0; i < 640 * 480; ++i)
        m_pixels[i] = 0x202020; //very dark gray

    for(int i = 0; i < (int)m_vertices.size(); i += 3)
    {
        int x1 = m_vertices[i].x;
        int y1 = m_vertices[i].y;
        unsigned c1 = m_vertices[i].color;
        float d1 = m_vertices[i].depth;
        float u1 = m_vertices[i].u / d1;
        float v1 = m_vertices[i].v / d1;
        float d1i = 1.f / m_vertices[i].depth;

        int x2 = m_vertices[i + 1].x;
        int y2 = m_vertices[i + 1].y;
        unsigned c2 = m_vertices[i + 1].color;
        float d2 = m_vertices[i + 1].depth;
        float u2 = m_vertices[i + 1].u / d2;
        float v2 = m_vertices[i + 1].v / d2;
        float d2i = 1.f / m_vertices[i + 1].depth;

        int x3 = m_vertices[i + 2].x;
        int y3 = m_vertices[i + 2].y;
        unsigned c3 = m_vertices[i + 2].color;
        float d3 = m_vertices[i + 2].depth;
        float u3 = m_vertices[i + 2].u / d3;
        float v3 = m_vertices[i + 2].v / d3;
        float d3i = 1.f / m_vertices[i + 2].depth;

        //don't render triangles that might have been incorrectly
        //casted due to being behind the camera
        if(d1 < 0.f || d2 < 0.f || d3 < 0.f)
            continue;

        int maxX = max(x1, x2, x3);
        int minX = min(x1, x2, x3);
        int maxY = max(y1, y2, y3);
        int minY = min(y1, y2, y3);

        //clip
        adjustToView(minX, minY, maxX, maxY);

        for(int x = minX; x <= maxX; ++x)
        {
            for(int y = minY; y <= maxY; ++y)
            {
                const float w2 = crossProduct(x - x1, y - y1, x3 - x1, y3 - y1) / crossProduct(x2 - x1, y2 - y1, x3 - x1, y3 - y1);
                const float w3 = crossProduct(x2 - x1, y2 - y1, x - x1, y - y1) / crossProduct(x2 - x1, y2 - y1, x3 - x1, y3 - y1);
                if((w2 >= 0) && (w3 >= 0) && (w2 + w3 <= 1))
                {
                    const float w1 = 1.f - w2 - w3;
                    const float depth = d1 * w1 + d2 * w2 + d3 * w3;
                    const float depthi = d1i * w1 + d2i * w2 + d3i * w3;
                    if(canSetPixel(x, y, depth))
                    {
                        const unsigned color = mix3colors(c1, w1, c2, w2, c3, w3);
                        const float u = normalizeTCoords(u1 * w1 + u2 * w2 + u3 * w3) / depthi;
                        const float v = normalizeTCoords(v1 * w1 + v2 * w2 + v3 * w3) / depthi;
                        const unsigned texel = getTexel(u, v);
                        switch(m_mode)
                        {
                            case ERM_COLORS:
                                setPixel(x, y, color, depth);
                                break;
                            case ERM_TEXTURES:
                                setPixel(x, y, texel, depth);
                                break;
                            case ERM_COLORS_TEXTURES:
                                setPixel(x, y, mul2colors(color, texel), depth);
                                break;
                            case ERM_UV_RED_BLUE:
                                setPixel(x, y, rgbf(u, 0.f, v), depth);
                                break;
                        }//switch m_mode
                    }//can set pixel
                }//inside
            }//for y
        }//for x
    }//for each triangle
}

void Rasterizer::clear()
{
    m_vertices.clear();
}

void Rasterizer::addVertex(int x, int y, unsigned color, float depth, float u, float v)
{
    Vertex2 vert;
    vert.x = x;
    vert.y = y;
    vert.color = color;
    vert.depth = depth;
    vert.u = u;
    vert.v = v;
    m_vertices.push_back(vert);
}

bool Rasterizer::canSetPixel(int x, int y, float depth)
{
    if(depth < 0.f)
        return false;

    assert(0 <= x && x < 640 && 0 <= y && y < 480);
    if(m_depthbuffer[x + y * 640] > depth)
        return true;

    return false;
}

void Rasterizer::setPixel(int x, int y, unsigned color, float depth)
{
    assert(0 <= x && x < 640 && 0 <= y && y < 480);
    m_pixels[x + y * 640] = color;
    m_depthbuffer[x + y * 640] = depth;
}

unsigned Rasterizer::getTexel(float u, float v) const
{
    const int x = std::max(0, std::min<int>(round(u * m_texx), m_texx - 1));
    const int y = std::max(0, std::min<int>(round(v * m_texy), m_texy - 1));
    const unsigned char * tex = &m_texture[3 * (x + m_texx * y)];
    return (tex[0] << 16) + (tex[1] << 8) + tex[2];
}

void Rasterizer::toggleRenderMode()
{
    m_mode = (m_mode + 1) % ERENDER_MODE_COUNT;
}
<commit_msg>Added perspective correct color interp too.<commit_after>#include "Rasterizer.hpp"
#include <cmath>
#include <algorithm>
#include <float.h>
#include <cstdio>
#include <cassert>
#include "stb_image.h"

using std::modf;

Rasterizer::Rasterizer(void* pixels) :
m_pixels(static_cast<unsigned*>(pixels))
{
    int n;
    m_texture = stbi_load("texture.png", &m_texx, &m_texy, &n, 3);
    m_mode = ERM_TEXTURES;
}

Rasterizer::~Rasterizer()
{
    stbi_image_free(m_texture);
}

static inline float crossProduct(float ax, float ay, float bx, float by)
{
    return ax * by - ay * bx;
}

static inline int min(int a, int b, int c)
{
    return std::min(a, std::min(b, c));
}

static inline int max(int a, int b, int c)
{
    return std::max(a, std::max(b, c));
}

static inline void sepcolor(unsigned c, int& r, int& g, int& b)
{
    r = (c >> 16) & 0xff;
    g = (c >> 8) & 0xff;
    b = (c >> 0) & 0xff;
}

static inline unsigned mix3colors(unsigned c1, float v1, unsigned c2, float v2, unsigned c3, float v3)
{
    int r1, g1, b1;
    int r2, g2, b2;
    int r3, g3, b3;
    sepcolor(c1, r1, g1, b1);
    sepcolor(c2, r2, g2, b2);
    sepcolor(c3, r3, g3, b3);
    int rf = r1 * v1 + r2 * v2 + r3 * v3;
    int gf = g1 * v1 + g2 * v2 + g3 * v3;
    int bf = b1 * v1 + b2 * v2 + b3 * v3;
    return (rf << 16) + (gf << 8) + bf;
}

static inline unsigned mul2colors(unsigned c1, unsigned c2)
{
    int r1, g1, b1;
    int r2, g2, b2;
    sepcolor(c1, r1, g1, b1);
    sepcolor(c2, r2, g2, b2);
    int rf = (r1 * r2) / 255;
    int gf = (g1 * g2) / 255;
    int bf = (b1 * b2) / 255;
    assert(0 <= rf && rf <= 255);
    assert(0 <= gf && gf <= 255);
    assert(0 <= bf && bf <= 255);
    return (rf << 16) + (gf << 8) + bf;
}

static void adjustToView(int& x1, int& y1, int& x2, int& y2)
{
    x1 = std::max(0, std::min(x1, 640 - 1));
    y1 = std::max(0, std::min(y1, 480 - 1));
    x2 = std::max(0, std::min(x2, 640 - 1));
    y2 = std::max(0, std::min(y2, 480 - 1));
}

static unsigned rgbf(float r, float g, float b)
{
    const int rf = std::max(0, std::min<int>(255, r * 255.f));
    const int gf = std::max(0, std::min<int>(255, g * 255.f));
    const int bf = std::max(0, std::min<int>(255, b * 255.f));
    return (rf << 16) + (gf << 8) + bf;
}

static float normalizeTCoords(float x)
{
    float u;
    x = modf(x, &u);
    return std::fabs(x);
}

static void decomposeColorF(unsigned c, float& r, float& g, float& b)
{
    b = (c & 0xff) / 255.f;
    c >>= 8;
    g = (c & 0xff) / 255.f;
    c >>= 8;
    r = (c & 0xff) / 255.f;
}

void Rasterizer::rasterize()
{
    for(int i = 0; i < 640 * 480; ++i)
        m_depthbuffer[i] = FLT_MAX;

    for(int i = 0; i < 640 * 480; ++i)
        m_pixels[i] = 0x202020; //very dark gray

    for(int i = 0; i < (int)m_vertices.size(); i += 3)
    {
        int x1 = m_vertices[i].x;
        int y1 = m_vertices[i].y;
        float r1, g1, b1;
        decomposeColorF(m_vertices[i].color, r1, g1, b1);
        float d1 = m_vertices[i].depth;
        r1 /= d1;
        g1 /= d1;
        b1 /= d1;
        float u1 = m_vertices[i].u / d1;
        float v1 = m_vertices[i].v / d1;
        float d1i = 1.f / m_vertices[i].depth;

        int x2 = m_vertices[i + 1].x;
        int y2 = m_vertices[i + 1].y;
        float r2, g2, b2;
        decomposeColorF(m_vertices[i + 1].color, r2, g2, b2);
        float d2 = m_vertices[i + 1].depth;
        r2 /= d2;
        g2 /= d2;
        b2 /= d2;
        float u2 = m_vertices[i + 1].u / d2;
        float v2 = m_vertices[i + 1].v / d2;
        float d2i = 1.f / m_vertices[i + 1].depth;

        int x3 = m_vertices[i + 2].x;
        int y3 = m_vertices[i + 2].y;
        float r3, g3, b3;
        decomposeColorF(m_vertices[i + 2].color, r3, g3, b3);
        float d3 = m_vertices[i + 2].depth;
        r3 /= d3;
        g3 /= d3;
        b3 /= d3;
        float u3 = m_vertices[i + 2].u / d3;
        float v3 = m_vertices[i + 2].v / d3;
        float d3i = 1.f / m_vertices[i + 2].depth;

        //don't render triangles that might have been incorrectly
        //casted due to being behind the camera
        if(d1 < 0.f || d2 < 0.f || d3 < 0.f)
            continue;

        int maxX = max(x1, x2, x3);
        int minX = min(x1, x2, x3);
        int maxY = max(y1, y2, y3);
        int minY = min(y1, y2, y3);

        //clip
        adjustToView(minX, minY, maxX, maxY);

        for(int x = minX; x <= maxX; ++x)
        {
            for(int y = minY; y <= maxY; ++y)
            {
                const float w2 = crossProduct(x - x1, y - y1, x3 - x1, y3 - y1) / crossProduct(x2 - x1, y2 - y1, x3 - x1, y3 - y1);
                const float w3 = crossProduct(x2 - x1, y2 - y1, x - x1, y - y1) / crossProduct(x2 - x1, y2 - y1, x3 - x1, y3 - y1);
                if((w2 >= 0) && (w3 >= 0) && (w2 + w3 <= 1))
                {
                    const float w1 = 1.f - w2 - w3;
                    const float depth = d1 * w1 + d2 * w2 + d3 * w3;
                    const float depthi = d1i * w1 + d2i * w2 + d3i * w3;
                    if(canSetPixel(x, y, depth))
                    {
                        const float r = (r1 * w1 + r2 * w2 + r3 * w3) / depthi;
                        const float g = (g1 * w1 + g2 * w2 + g3 * w3) / depthi;
                        const float b = (b1 * w1 + b2 * w2 + b3 * w3) / depthi;
                        const float u = normalizeTCoords(u1 * w1 + u2 * w2 + u3 * w3) / depthi;
                        const float v = normalizeTCoords(v1 * w1 + v2 * w2 + v3 * w3) / depthi;
                        const unsigned texel = getTexel(u, v);
                        switch(m_mode)
                        {
                            case ERM_COLORS:
                                setPixel(x, y, rgbf(r, g, b), depth);
                                break;
                            case ERM_TEXTURES:
                                setPixel(x, y, texel, depth);
                                break;
                            case ERM_COLORS_TEXTURES:
                                setPixel(x, y, mul2colors(rgbf(r, g, b), texel), depth);
                                break;
                            case ERM_UV_RED_BLUE:
                                setPixel(x, y, rgbf(u, 0.f, v), depth);
                                break;
                        }//switch m_mode
                    }//can set pixel
                }//inside
            }//for y
        }//for x
    }//for each triangle
}

void Rasterizer::clear()
{
    m_vertices.clear();
}

void Rasterizer::addVertex(int x, int y, unsigned color, float depth, float u, float v)
{
    Vertex2 vert;
    vert.x = x;
    vert.y = y;
    vert.color = color;
    vert.depth = depth;
    vert.u = u;
    vert.v = v;
    m_vertices.push_back(vert);
}

bool Rasterizer::canSetPixel(int x, int y, float depth)
{
    if(depth < 0.f)
        return false;

    assert(0 <= x && x < 640 && 0 <= y && y < 480);
    if(m_depthbuffer[x + y * 640] > depth)
        return true;

    return false;
}

void Rasterizer::setPixel(int x, int y, unsigned color, float depth)
{
    assert(0 <= x && x < 640 && 0 <= y && y < 480);
    m_pixels[x + y * 640] = color;
    m_depthbuffer[x + y * 640] = depth;
}

unsigned Rasterizer::getTexel(float u, float v) const
{
    const int x = std::max(0, std::min<int>(round(u * m_texx), m_texx - 1));
    const int y = std::max(0, std::min<int>(round(v * m_texy), m_texy - 1));
    const unsigned char * tex = &m_texture[3 * (x + m_texx * y)];
    return (tex[0] << 16) + (tex[1] << 8) + tex[2];
}

void Rasterizer::toggleRenderMode()
{
    m_mode = (m_mode + 1) % ERENDER_MODE_COUNT;
}
<|endoftext|>


<commit_before>// This is sometimes required to support the full curses API
#define _XOPEN_SOURCE
#define _XOPEN_SOURCE_EXTENDED

#ifdef __GNUC__
	// Enable printf and scanf argument checking
	#define GCC_PRINTF
	#define	GCC_SCANF
#endif

#include <curses.h>
#include <climits>
#include <cstdio>

#include <QString>

#include "lirch_constants.h"
#include "plugins/lirch_plugin.h"
#include "core/core_messages.h"

using namespace std;

template <class... args>
string strprintf(const string &format, args... a)
{
	//Thankfully, the C++ standard grabbed the definition from POSIX
	//instead of Windows, so I don't have to binary-search the correct
	//string size.
	int size=snprintf(NULL, 0, format.c_str(), a...);
	//Add padding for the terminating byte
	vector<char> s(size+1);
	//We can use sprintf instead of snprintf because we know the buffer is large enough
	sprintf(s.data(), format.c_str(), a...);
	return s.data();
}

//Same as wprintf, but handles unicode characters properly
template <class... args>
void wprintu(WINDOW *w, const string &format, args... a)
{
	string s=strprintf(format, a...);
	for (unsigned char c : s)
		waddch(w, c|(c>0x7f ? A_ALTCHARSET : 0));
}

void runplugin(plugin_pipe &p, const string &name)
{
	QString input;
	int maxx, maxy;
	getmaxyx(stdscr, maxy, maxx);
	//10000 lines of scrollback should be enough for anyone
	auto channel_output=newpad(10000, maxx);
	//Let the output scroll
	scrollok(channel_output, TRUE);
	//p.write(registration_message::create(-30000, name, "display"));
	while (true)
	{
		/*while (p.has_message())
		{
			message m=p.read();
		}*/
		wint_t key;
		int rc=get_wch(&key);
		if (rc==OK)
		{
			input.push_back(QString::fromUcs4(&key, 1));
			//add_wch(key);
			wprintw(channel_output, "%s: %x: ", QString::fromUcs4(&key, 1).toLocal8Bit().constData(), key);
			for (auto &i : QString::fromUcs4(&key, 1).toLocal8Bit())
				wprintw(channel_output, "%02x ", (unsigned char)i);
			wprintw(channel_output, ": ");
			//addch(ACS_HLINE);
			for (auto &i : QString::fromUcs4(&key, 1).toLocal8Bit())
				waddch(channel_output, (unsigned char)i|(A_ALTCHARSET*((unsigned char)i>0x7f)));
				//addch(i&~(/*A_ALTCHARSET|*/A_BLINK|A_BOLD/*|A_DIM|A_INVIS|A_PROTECT*/));
			waddch(channel_output, '\n');
		}
		else if (rc==KEY_CODE_YES)
		{
			break;
		}
		else
		{
			wprintw(channel_output, "No key pressed\n");
		}
		int x,y;
		getyx(channel_output, y, x);
		prefresh(channel_output, max(y-maxy,0), 0, 0,0,maxy-2,maxx-1);
	}
	p.write(core_quit_message::create());
}

void run(plugin_pipe p, string name)
{
	//Set the delay when hitting escape to 10 milliseconds, unless it was
	//already set.  The ESCDELAY variable is not supported in all curses
	//implementations, but should not cause problems in implementations
	//that ignore it.
	setenv("ESCDELAY", "10", 0);
	//Initialize curses
	initscr();
	//Don't buffer typed characters
	cbreak();
	//Wain no more than a tenth of a second for input
	timeout(100);
	noecho();
	//Makes enter return \r instead of \n
	nonl();
	//Flush the input buffer if an interrupt key is pressed.  This ensures
	//we don't miss keystrokes in the event of a SIGSTOP
	intrflush(stdscr, FALSE);
	//Enable keycodes
	keypad(stdscr, TRUE);
	runplugin(p, name);
	//Make sure to always restore the terminal to a sane configuration
	endwin();
	return;
}
<commit_msg>Added support for backspace and enter<commit_after>// This is sometimes required to support the full curses API
#define _XOPEN_SOURCE
#define _XOPEN_SOURCE_EXTENDED

#ifdef __GNUC__
	// Enable printf and scanf argument checking
	#define GCC_PRINTF
	#define	GCC_SCANF
#endif

#include <curses.h>
#include <climits>
#include <cstdio>

#include <QString>
#include <QTextBoundaryFinder>

#include "lirch_constants.h"
#include "plugins/lirch_plugin.h"
#include "core/core_messages.h"

inline char CTRL(char c)
{
	//Leave only the lower 5 bits, so the return value is the numeric value
	//of CTRL+key (e.g. CTRL('c') gives you 3, which is the value you get
	//when hitting ctrl-c)
	return c&0x1f;
}

using namespace std;

template <class... args>
string strprintf(const string &format, args... a)
{
	//Thankfully, the C++ standard grabbed the definition from POSIX
	//instead of Windows, so I don't have to binary-search the correct
	//string size.
	int size=snprintf(NULL, 0, format.c_str(), a...);
	//Add padding for the terminating byte
	vector<char> s(size+1);
	//We can use sprintf instead of snprintf because we know the buffer is large enough
	sprintf(s.data(), format.c_str(), a...);
	return s.data();
}

//Same as wprintf, but handles unicode characters properly
template <class... args>
void wprintu(WINDOW *w, const string &format, args... a)
{
	string s=strprintf(format, a...);
	for (unsigned char c : s)
		waddch(w, c|(c>0x7f ? A_ALTCHARSET : 0));
}

void runplugin(plugin_pipe &p, const string &name)
{
	QString input;
	int maxx, maxy;
	getmaxyx(stdscr, maxy, maxx);
	//10000 lines of scrollback should be enough for anyone
	auto channel_output=newpad(10000, maxx);
	//Let the output scroll
	scrollok(channel_output, TRUE);
	//p.write(registration_message::create(-30000, name, "display"));
	while (true)
	{
		/*while (p.has_message())
		{
			message m=p.read();
		}*/
		wint_t key;
		int rc=get_wch(&key);
		if (rc==OK)
		{
			if (key=='\r' || key=='\n')
			{
				wprintu(channel_output, "Message sent!\n");
				input="";
			}
			else
				input.push_back(QString::fromUcs4(&key, 1));
			wprintu(channel_output, "%s\n", input.toLocal8Bit().constData());
		}
		else if (rc==KEY_CODE_YES)
		{
			if (key==KEY_BACKSPACE)
			{
				QTextBoundaryFinder bounds(QTextBoundaryFinder::Grapheme, input);
				bounds.toEnd();
				int pos=bounds.toPreviousBoundary();
				if (pos!=-1)
				{
					input.remove(pos, INT_MAX);
				}
			}
			else if (key==KEY_ENTER)
			{
				wprintu(channel_output, "Message sent!\n");
				input="";
			}
			else
				break;
			wprintu(channel_output, "%s\n", input.toLocal8Bit().constData());
		}
		int x,y;
		getyx(channel_output, y, x);
		pnoutrefresh(channel_output, max(y-(maxy-1),0), 0, 0,0,maxy-2,maxx-1);
		wmove(stdscr, maxy-1,0);
		doupdate();
	}
	p.write(core_quit_message::create());
}

void run(plugin_pipe p, string name)
{
	//Set the delay when hitting escape to 10 milliseconds, unless it was
	//already set.  The ESCDELAY variable is not supported in all curses
	//implementations, but should not cause problems in implementations
	//that ignore it.
	setenv("ESCDELAY", "10", 0);
	//Initialize curses
	initscr();
	//Don't buffer typed characters
	cbreak();
	//Wain no more than a tenth of a second for input
	timeout(100);
	noecho();
	//Makes enter return \r instead of \n
	nonl();
	//Flush the input buffer if an interrupt key is pressed.  This ensures
	//we don't miss keystrokes in the event of a SIGSTOP
	intrflush(stdscr, FALSE);
	//Enable keycodes
	keypad(stdscr, TRUE);
	runplugin(p, name);
	//Make sure to always restore the terminal to a sane configuration
	endwin();
	return;
}
<|endoftext|>