void AdvancedBox::calculate(const Int2& parPos, const Int2& parSize, const Int2& parHotSpot, float angleDegrees, int xTopDeformation, int xBottomDeformation)
	{
		float angleRadians = angleDegrees * MathUtils::PI / 180.0f;

		data[0] = getRotatedPoint(
			parPos.x() + parSize.width() - parHotSpot.x(), parPos.y() + parSize.height() - parHotSpot.y(),
			angleRadians,
			parPos.x()/*-1*/, parPos.y(), xBottomDeformation);

		data[1] = getRotatedPoint(
			parPos.x() - parHotSpot.x(), parPos.y() + parSize.height() - parHotSpot.y(),
			angleRadians,
			parPos.x(), parPos.y(), xBottomDeformation);

		data[2] = getRotatedPoint(
			parPos.x() - parHotSpot.x(), parPos.y() - parHotSpot.y(),
			angleRadians,
			parPos.x(), parPos.y(), xTopDeformation);

		data[3] = getRotatedPoint(
			parPos.x() + parSize.width() - parHotSpot.x(), parPos.y() - parHotSpot.y(),
			angleRadians,
			parPos.x()/*-1*/, parPos.y(), xTopDeformation);

		/*PrintValue(data[0]);
		PrintValue(data[1]);
		PrintValue(data[2]);
		PrintValue(data[3]);
		Print("");*/
	}
void AppSetup::onResizeWindow(const Int2& newSize)
{
	m_inf.windowSize = newSize;

	Float2 newSizeF = Float2((float)newSize.width(), (float)newSize.height());
	Float2 virtualSizeF = Float2((float)m_inf.virtualSize.width(), (float)m_inf.virtualSize.height());

	if (m_inf.automaticFitToWindowSize && (newSize.width() != m_inf.virtualSize.width() || newSize.height() != m_inf.virtualSize.height()))
	{
		Float2 ppp(-1.f,-1.f);
		Int2 virtualPos(-1,-1);

		float ratioW = (float)newSize.width() / (float)m_inf.virtualSize.width();
		float ratioH = (float)newSize.height() / (float)m_inf.virtualSize.height();
		if (m_inf.virtualSizeAllowRatioDeformation)
		{
			ppp = Float2(ratioW,ratioH);
			virtualPos = Int2(0,0);
		}
		else if (newSizeF.width()/newSizeF.height() > virtualSizeF.width() / virtualSizeF.height())
		{
			ppp = Float2(ratioH,ratioH);
			virtualPos = Int2((int)((newSizeF.width()-virtualSizeF.width()*ratioH)/2.f), 0);
		}
		else
		{
			ppp = Float2(ratioW,ratioW);
			virtualPos = Int2(0, (int)((newSizeF.height()-virtualSizeF.height()*ratioW)/2.f));
		}
		
		this->setPixelPerPointLowLevel(ppp, virtualPos);
	}
	else
	{
		this->setPixelPerPointLowLevel(Float2(1.f,1.f), Int2(0,0));
#if defined(USES_WINDOWS_OPENGL) || defined(USES_LINUX)
		m_openGL->setRealWindowSize(newSize);
		m_openGL->set2DMode();
#else
		// do nothing here
#endif
	}

	m_isUsingVirtualSize = (this->getPixelPerPoint() != Float2(1.f, 1.f) || this->getVirtualTopLeftCornerInWindow() != Int2(0, 0));
}
void AppSetup::manageRender()
{
	if (m_isUsingVirtualSize)
	{
		Int2 virtualPos = this->getVirtualTopLeftCornerInWindow();
		Float2 ppp = this->getPixelPerPoint();
		Int2 sizeOrtho2DWindow = this->getSizeOrtho2DWindow();

		this->setPixelPerPointLowLevel(Float2(1.f,1.f), Int2(0,0));
		
		if (m_inf.virtualSizeBorderColor.a() != 0)
		{
			if (m_inf.virtualSize.width() < sizeOrtho2DWindow.width())
			{
				Engine::instance().getScene2DMgr().drawRectangle(
					Int2(0,0), 
					Int2(virtualPos.width(), m_inf.windowSize.height()), 
					m_inf.virtualSizeBorderColor, true);
				Engine::instance().getScene2DMgr().drawRectangle(
					Int2(m_inf.windowSize.width()-virtualPos.width(), 0), 
					m_inf.windowSize,
					m_inf.virtualSizeBorderColor, true);
			}
			else if (m_inf.virtualSize.height() < sizeOrtho2DWindow.height())
			{
				Engine::instance().getScene2DMgr().drawRectangle(
					Int2(0, 0), 
					Int2(m_inf.windowSize.width(), virtualPos.height()), 
					m_inf.virtualSizeBorderColor, true);
				Engine::instance().getScene2DMgr().drawRectangle(
					Int2(0, m_inf.windowSize.height()-virtualPos.height()), 
					m_inf.windowSize,
					m_inf.virtualSizeBorderColor, true);
			}
		}
		
		this->setPixelPerPointLowLevel(ppp, virtualPos);
	}

#if defined(USES_WINDOWS_OPENGL) || defined(USES_LINUX)
	m_openGL->manageOpenGL(m_inf.windowSize);
#else

#endif
}
DesktopWindow::DesktopWindow(HINSTANCE hInstance, int nCmdShow, DesktopWindowMessageHandler* messageReceiver, bool isFullscreen, const Int2& windowSize, const std::string& windowTitle)
:m_messageReceiver(messageReceiver), m_mustBeDestroyed(false)
{
	// Register class
	WNDCLASSEX wcex;
	wcex.cbSize = sizeof(WNDCLASSEX);
	wcex.style = CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc = WndProc;
	wcex.cbClsExtra = 0;
	wcex.cbWndExtra = 0;
	wcex.hInstance = hInstance;
	wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_APPLICATION);
	wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
	wcex.hbrBackground = (HBRUSH)(5 + 1);
	wcex.lpszMenuName = nullptr;
	wcex.lpszClassName = L"TutorialWindowClass";
	wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_APPLICATION);
	if (!RegisterClassEx(&wcex))
		Assert(false);

	// Create window
	RECT rc = { 0, 0, windowSize.width(), windowSize.height() };
	AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE); ;
	HWND hwnd = CreateWindow(L"TutorialWindowClass", Utils::convertStringToWString(windowTitle).c_str(), isFullscreen ? WS_POPUP : WS_OVERLAPPEDWINDOW,
		// WS_VISIBLE | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME
		CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, nullptr, nullptr, hInstance, nullptr);
	Assert(hwnd != nullptr);

	ShowWindow(hwnd, isFullscreen ? SW_MAXIMIZE : nCmdShow);

	// resize to take into consideration the border size
	/*RECT rcClient, rcWind;
	POINT ptDiff;
	GetClientRect(hwnd, &rcClient);
	GetWindowRect(hwnd, &rcWind);
	ptDiff.x = (rcWind.right - rcWind.left) - rcClient.right;
	ptDiff.y = (rcWind.bottom - rcWind.top) - rcClient.bottom;
	MoveWindow(hwnd, rcWind.left, rcWind.top, (rc.right - rc.left) + ptDiff.x, (rc.bottom - rc.top) + ptDiff.y, TRUE);*/

	m_hwnd = hwnd;

	s_hwnds[hwnd] = this;
}
void MainClass::init()
{
	Scene2D& scene2D = Engine::instance().getScene2DMgr();

	Int2 winSize = scene2D.getWindowSize();

	Engine::instance().startRender();
	//Engine::instance().clearScreen(Color(57,155,230, 255));
	Engine::instance().getScene2DMgr().drawRectangle(Int2(0,0), winSize, Color(57,155,230, 255), true);//clearScreen(Color(57,155,230, 255));
	Bitmap* loading = new Bitmap("data/loading.png");
	Int2 bitmapPos = winSize*0.5f - loading->size()*0.5f;
	loading->draw(winSize*0.5f-loading->size()*0.5f, 1.f, Float2(1.f, 1.f));
#if defined(USES_WINDOWS8_METRO)
	Engine::instance().getScene2DMgr().drawRectangle(bitmapPos + Int2(362, 411), bitmapPos + Int2(463, 440), CoreUtils::colorWhite, true);// hide "Esc: quit"
#endif
	delete loading;
	Engine::instance().endRender();

	//-----

	m_isHelpOpened = true;

	m_help = new Sprite("data/help.png");
	m_help->setPosition(winSize*0.5f-m_help->getScaledSize()*0.5f);

	m_pressF1Help = new Sprite("data/pressf1help.png");
	m_pressF1Help->setPosition(Int2(10, winSize.height()-30));

	m_background = new Sprite("data/background.png");
	m_background->setPosition(Int2(0,0));

	m_collisionImage = new Image("data/collision.png");
	m_structure = new Bitmap("data/structure.png");

	m_structureForeground = new Bitmap("data/structure_foreground.png");

	m_engineSystem = new EngineSystem;

	m_chara = new Chara();

	m_cannon = new Cannon();

	m_clouds.push_back(new Cloud);
	m_clouds.push_back(new Cloud);
	m_clouds.push_back(new Cloud);
	m_clouds.push_back(new Cloud);

	m_burning = new Burning;
	m_waterSystem = new WaterSystem;

	m_swarm = new Swarm;

	m_gameOver = new Bitmap("data/game_over.png");
	
#if defined(USES_WINDOWS_OPENGL) || defined(USES_LINUX)
	m_music = Engine::instance().getSoundMgr().loadSound("data/sounds/opengameart_cynicmusic_battleThemeA.ogg");
#else
	m_music = Engine::instance().getSoundMgr().loadSound("data/sounds/opengameart_cynicmusic_battleThemeA.wav");
#endif
	m_music->setVolume(m_musicVolume);
	m_music->play();
}