// ------------------------------------------
PyObject *InputServiceBinder::setInputMapped(PyObject *self, PyObject *args) {
    __PYTHON_EXCEPTION_GUARD_BEGIN_;
    InputServicePtr o;

    if (!python_cast<InputServicePtr>(self, &msType, &o))
        __PY_CONVERR_RET;

    PyObject *mapped;

    if (PyArg_ParseTuple(args, "O", &mapped)) {
        bool cmap;

        if (!TypeInfo<bool>::fromPyObject(mapped, cmap))
            __PY_BADPARMS_RET;

        o->setInputMode(cmap ? IM_MAPPED : IM_DIRECT);

        __PY_NONE_RET;
    } else {
        PyErr_SetString(PyExc_TypeError, "Expected a bool parameter!");
        return NULL;
    }

    __PYTHON_EXCEPTION_GUARD_END_;
}
// ------------------------------------------
PyObject *InputServiceBinder::unregisterCommandTrap(PyObject *self,
                                                    PyObject *args) {
    __PYTHON_EXCEPTION_GUARD_BEGIN_;
    InputServicePtr o;

    if (!python_cast<InputServicePtr>(self, &msType, &o))
        __PY_CONVERR_RET;

    char *name;

    if (PyArg_ParseTuple(args, "s", &name)) {
        o->unregisterCommandTrap(name);

        __PY_NONE_RET;
    } else {
        PyErr_SetString(PyExc_TypeError, "Expected a string parameter!");
        return NULL;
    }

    __PYTHON_EXCEPTION_GUARD_END_;
}
// ------------------------------------------
PyObject *InputServiceBinder::setBindContext(PyObject *self, PyObject *args) {
    __PYTHON_EXCEPTION_GUARD_BEGIN_;
    PyObject *result = NULL;
    InputServicePtr o;

    if (!python_cast<InputServicePtr>(self, &msType, &o))
        __PY_CONVERR_RET;

    char *name;

    if (PyArg_ParseTuple(args, "s", &name)) {
        o->setBindContext(name);

        __PY_NONE_RET;
    } else {
        PyErr_SetString(PyExc_TypeError, "Expected a string parameter!");
    }

    return result;
    __PYTHON_EXCEPTION_GUARD_END_;
}
// ------------------------------------------
PyObject *InputServiceBinder::command(PyObject *self, PyObject *args) {
    __PYTHON_EXCEPTION_GUARD_BEGIN_;
    PyObject *result = NULL;
    InputServicePtr o;

    if (!python_cast<InputServicePtr>(self, &msType, &o))
        __PY_CONVERR_RET;

    char *command;

    if (PyArg_ParseTuple(args, "s", &command)) {
        std::string Command = command;
        o->processCommand(Command);

        __PY_NONE_RET;
    } else {
        PyErr_SetString(PyExc_TypeError, "Expected a string parameter!");
    }

    return result;
    __PYTHON_EXCEPTION_GUARD_END_;
}
// ------------------------------------------
PyObject *InputServiceBinder::registerCommandTrap(PyObject *self,
                                                  PyObject *args) {
    __PYTHON_EXCEPTION_GUARD_BEGIN_;
    PyObject *result = NULL;
    InputServicePtr o;

    if (!python_cast<InputServicePtr>(self, &msType, &o))
        __PY_CONVERR_RET;

    char *name;
    PyObject *callable;

    if (PyArg_ParseTuple(args, "sO", &name, &callable)) {
        try {
            // call the is to register the command trap
            Object cb(callable);

            using std::placeholders::_1;
            o->registerCommandTrap(
                name,
                std::bind(&call_python_callback<InputEventMsg, PythonInputMessageConverter>,
                          std::move(cb), _1));

            __PY_NONE_RET;
        } catch (const BasicException &) {
            PyErr_SetString(
                PyExc_TypeError,
                "Error setting a callback, is the given argument a callable?");
            return NULL;
        }
    } else {
        PyErr_SetString(PyExc_TypeError,
                        "Expected a string and callable parameters!");
    }

    return result;
    __PYTHON_EXCEPTION_GUARD_END_;
}
	void GamePlayState::start() {
		LOG_INFO("GamePlayState: Starting");
		PropertyServicePtr ps = GET_SERVICE(PropertyService);
		Property* posPG = ps->getProperty("Position");

		InputServicePtr inputSrv = GET_SERVICE(InputService);
		inputSrv->processCommand("bind ` show_console");

		if (posPG == NULL)
			OPDE_EXCEPT("Could not get Position property. Not defined. Fatal", "GamePlayState::start");

		LOG_DEBUG("Starting Point object id : %d", StartingPointObjID);

		DVariant spoint;
		posPG->get(StartingPointObjID, "position", spoint);

		// Medsci1.mis position with some damn bad performance under GL
		//Vector3 StartingPoint(-8.41809, -163.39, 1.3465);
		Vector3 StartingPoint(0,0,0);

		if (spoint.type() == DVariant::DV_VECTOR)
			StartingPoint = spoint.toVector();

		LOG_DEBUG("Starting Point position : %f %f %f", StartingPoint.x, StartingPoint.y, StartingPoint.z);

		mSceneMgr = mRoot->getSceneManager( "DarkSceneManager" );
		RenderServicePtr renderSrv = GET_SERVICE(RenderService);

		mCamera = renderSrv->getDefaultCamera();
		mViewport = renderSrv->getDefaultViewport();
		mWindow = renderSrv->getRenderWindow();

		mSceneMgr->clearSpecialCaseRenderQueues();
		mSceneMgr->setSpecialCaseRenderQueueMode(SceneManager::SCRQM_EXCLUDE);

		mCamera->setNearClipDistance(0.5);
		mCamera->setFarClipDistance(4000);

		// Also change position, and set Quake-type orientation
		ViewPoint vp = mSceneMgr->getSuggestedViewpoint(true);
		mCamera->setPosition(vp.position);

		if (StartingPointObjID != 0)
			mCamera->setPosition(StartingPoint);

		mCamera->pitch(Degree(90));
		mCamera->rotate(vp.orientation);

		// Don't yaw along variable axis, causes leaning
		mCamera->setFixedYawAxis(true, Vector3::UNIT_Z);

		// Medsci1.mis Direction with some damn bad performance (in combination with the pos above)
		// mCamera->setDirection(-0.398078, 0.825408, -0.400297);

		// Thiefy FOV
		mCamera->setFOVy(Degree(60)); //  * mCamera->getAspectRatio()

		if (mConfigService->hasParam("debug")) {
			if (mConfigService->getParam("debug") == true) {
				// debug overlay
				mDebugOverlay->show();

				// Portal stats overlay
				mPortalOverlay->show();

				mDebug = true;
			}
		}

		// hidden as default
		// mConsole->setActive(false);

		mWindow->resetStatistics();

		mToLoadScreen = false;
	/*
		mDrawService = GET_SERVICE(DrawService);

		mCamera->setPosition(0,10,-15);
		mCamera->lookAt(0,0,30);
		mCamera->setNearClipDistance(0.5f);
		mSceneMgr->setAmbientLight(ColourValue(1, 1, 1));

		TextureAtlas* ta = mDrawService->createAtlas();
		TextureAtlas* ta1 = mDrawService->createAtlas();

		DrawSource* ds = ta->createDrawSource("access.pcx", "General");
		// testing what happens when a font is loaded (e.g. where it segv's)
		mDrawService->setFontPalette(Ogre::ManualFonFileLoader::ePT_PCX, "fontpal.pcx", "General");
		FontDrawSource* fds = mDrawService->loadFont(ta, "fonts/MAINFONT.FON" , "General");
		FontDrawSource* fds1 = mDrawService->loadFont(ta, "fonts/MAINAA.FON" , "General");
		FontDrawSource* fds2 = mDrawService->loadFont(ta, "fonts/keyfonta.FON" , "General");

		ta->build();
		ta1->build();

		RenderedLabel* rl = mDrawService->createRenderedLabel(fds, "OpenDarkEngine test");

		mRl1 = mDrawService->createRenderedLabel(fds, "TEST 2");
		mRl2 = mDrawService->createRenderedLabel(fds, "ONLY VISIBLE IN CLIPPED AREA\nThis text is a multiline text that is only to be seen\nif inside a clipping rectangle that it is set to be\nviewed through.");

		ClipRect cr = mDrawService->getClipRect(150, 300, 150, 176);
		mRl2->setClipRect(cr);

		RenderedImage* ri = mDrawService->createRenderedImage(ds);
		ri->setPosition(100, 250);



		rl->setPosition(250, 100);
		mRl1->setPosition(0, 0);
		mRl2->setPosition(0, 12);
		rl->setZOrder(2);
		mRl2->setZOrder(2);
		mRl2->setZOrder(2);

		DrawSheet* dsh = mDrawService->createSheet("GameScreen");

		dsh->addDrawOperation(ri);
		dsh->addDrawOperation(rl);
		dsh->addDrawOperation(mRl1);
		dsh->addDrawOperation(mRl2);

		dsh->setVisible(true);

		mSceneMgr->getRootSceneNode()->attachObject(dsh);
		mDrawService->setActiveSheet(dsh);
	*/
		LOG_INFO("GamePlayState: Started");
	}