예제 #1
0
void eventloop(void (*expose)(), void (*resize)(), void (*buttonpress)())
/* This is the main event loop */
{
   for(;;){
/* get events, use first to display text and graphics */
      XNextEvent(display, &report);
      switch  (report.type)
      {
         case Expose: handleExpose(expose); break;
         case ConfigureNotify: handleResize(resize);break;
         case ButtonPress: (*buttonpress)(); break;
         case KeyPress:
           /*****************************
           -- user stuff here for key press in window---
           e.g. exit program (note that, typing q in window exits)
           ******************************/
            XUnloadFont(display, font_info->fid);
            XFreeGC(display, drawgc);
            XCloseDisplay(display);
         default:
        /* all events selected by StructureNotifyMask
         * except ConfigureNotify are thrown away here,
         * since nothing is done with them */
            break;
      }
   }
}
예제 #2
0
bool PlaceableWindowProxy::eventFilter(QObject *, QEvent *event)
{
  // This should never happen, but doesn't hurt to be defensive.
  if (!target_)
  {
    return false;
  }

  if (!visible_)
  {
    return false;
  }

  switch (event->type())
  {
  case QEvent::MouseButtonPress:
    return handleMousePress(static_cast<QMouseEvent*>(event));
  case QEvent::MouseButtonRelease:
    return handleMouseRelease(static_cast<QMouseEvent*>(event));
  case QEvent::MouseMove:
    return handleMouseMove(static_cast<QMouseEvent*>(event));
  case QEvent::Resize:
    return handleResize(static_cast<QResizeEvent*>(event));
  default:
    return false;
  }
}
예제 #3
0
  bool InputHandler::handleWindowEvent(EventDispatcher* sender, const Event& e)
  {
    const WindowEvent& event = static_cast<const WindowEvent&>(e);
    if(event.handle != mHandle)
    {
      return true;
    }

    handleResize(event.width, event.height);
    return true;
  }
예제 #4
0
void GameApp::handleWindowEvents()
{
	sf::Event e;
	while(window.pollEvent(e))
	{
		if(e.type == sf::Event::Closed)
			window.close();

		if(e.type == sf::Event::Resized)
		{
			handleResize();
		}
	}
}
예제 #5
0
void handleEvents(void)
/* This function can be called to handle events instead of entering
   the event loop. The calls must be frequent to ensure proper action.
*/
{
   while (XCheckMaskEvent(display, event_mask, &report))
   switch  (report.type)
   {
      case Expose: handleExpose(NULL);break;
      case ConfigureNotify: handleResize(NULL);break;
      case ButtonPress: buttonState=1;break;
      case ButtonRelease: buttonState=0;break;
      case KeyPress: lastKey=report.xkey.keycode;
      case MotionNotify:;
   }
}
예제 #6
0
void gameDialog::init(void) {
	fRenderControl.reset(new RenderControl);
	fRenderControl->Init();

	std::shared_ptr<DrawFont> gabriola18(new DrawFont);
	gabriola18->Init("textures/gabriola18");
	gScrollingMessages.Init(gabriola18);
	ChunkBlocks::InitStatic();
	maxRenderDistance = (float)Options::fgOptions.fViewingDistance;
	this->fRequestedCameraDistance = Options::fgOptions.fCameraDistance;
	if (maxRenderDistance > MAXRENDERDISTANCE) {
		// Someone tried to trick the program by editing the ini file.
		// #255 long distances are not handled very well by neither server nor client
		maxRenderDistance = MAXRENDERDISTANCE;
	}
	if (maxRenderDistance < 5.0f)
		maxRenderDistance = 5.0f;
	gMsgWindow.Init();
	gTranspShader.Init();
	fBuildingBlocks = BuildingBlocks::Make(7); // TODO: Need something more adaptive than a constant.
	fFPSsentence = gDrawFont.vsfl.genSentence();
	fInputPromptSentence = gDrawFont.vsfl.genSentence();
	fPlayerStatusSentence = gDrawFont.vsfl.genSentence();
	gMonsterDef.Init(0);
	sfCurrentGameDialog = this; // Used by callback functions.
	fShader = ChunkShader::Make(); // Singleton
	fHealthBar = HealthBar::Make(); // Singleton
	fDrawTexture = DrawTexture::Make();
	glGetFloatv(GL_VIEWPORT, &gViewport[0]);
	handleResize(gViewport[2], gViewport[3]); // Simple way to set the projection
	glEnable(GL_DEPTH_TEST);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //Set the blend function
	unsigned char b[] = { 0x03, 0x00, CMD_GET_COORDINATE }; // GET_COORDINATE
	SendMsg(b, sizeof b);

	glEnable(GL_CULL_FACE); // Always enabled by default

	glfwDisable(GLFW_KEY_REPEAT);
	glfwSetWindowSizeCallback(::handleResize);
	glfwSetMousePosCallback(handleMouseActiveMotion);
	glfwSetKeyCallback(handleKeypress);
	glfwSetCharCallback(handleCharacter);

	checkError("gameDialog::init");
}
예제 #7
0
void Engine::handleEvents()
{
    SDL_Event event;
    while(SDL_PollEvent(&event))
    {
        switch(event.type)
        {
            case SDL_QUIT:
                quit = true;
            break;
            case SDL_WINDOWEVENT_RESIZED:
                handleResize(event.window.data1, event.window.data2);
                break;
            default:
            break;
        }
    }
}
예제 #8
0
static void parseArguments(int argc, char **argv) {
	const char *hostarg = 0, *portarg = 0, *format;
	char *end;
	int opt;

	/* Program name */
	argv0 = strrchr(argv[0], '/');
	argv0 = argv0 && argv0[1] ? argv0 + 1 : *argv;


	/* Help */
	if (argc > 1 && !strcmp(argv[1], "--help")) {
		usage();
	}

	/* Some defaults */
	format = DEFAULT_FORMAT;

	/* Get opts */
	while ((opt = getopt(argc, argv, "-hbBc:f:"))!=-1) {
		switch (opt) {
		case 'h': usage();
		case 'b': D.background = 1; break;
		case 'B': D.background = 2; break;

			/* Columns */
		case 'c': {
			unsigned long c = strtoul(optarg, &end, 0);
			die_on(c < 3 || c > UINT_MAX || *end,
				   "invalid terminal width: %s", optarg);
			D.cur.columns = c;
			break;
		}

			/* Format */
		case 'f':
			format = optarg;
			break;

			/* An argument */
		case 1:
			if (!hostarg) { hostarg = optarg; break; }
			if (!portarg) { portarg = optarg; break; }
			die_on(1, "invalid argument: %s", optarg);

			/* An error */
		default:
			die_on(1, "invalid option: %c", optopt);
		}
	}


	/* Host, password and port */
	if (!hostarg) {
		hostarg = getenv("MPD_HOST");
	}
	if (!hostarg) {
		hostarg = DEFAULT_HOST;
	}
	end = strchr(hostarg, '@');
	if (end) {
		/* If '@' has been found we got host from either command line
		 * or environment and in both cases the string is
		 * modifiable. */
		*end = 0;
		D.password = hostarg;
		hostarg = end + 1;
	}
	D.host = hostarg;

	if (!portarg) {
		portarg = getenv("MPD_PORT");
	}
	if (!portarg) {
		end = strchr(hostarg, ':');
		if (end) {
			*end = 0;
			portarg = end + 1;
		}
	}
	if (!portarg) {
		D.port = DEFAULT_PORT;
	} else {
		unsigned long p = strtoul(portarg, &end, 0);
		die_on(p <= 0 || p > 0xffff || *end, "invalid port: %s", portarg);
		D.port = p;
	}


	/* Format */
	D.format = wideFromMulti(format);


	/* Columns */
#if HAVE_RESIZE
	if (!D.cur.columns) {
		handleResize(SIGWINCH);
		D.cur.columns = D.width;
	}
#endif
	if (!D.cur.columns) {
		end = getenv("COLUMNS");
		if (end) {
			unsigned long c = strtoul(end, &end, 0);
			if (c >= 3 && c <= UINT_MAX && !*end) {
				D.cur.columns = c;
			}
		}
	}
	if (!D.cur.columns) {
		D.cur.columns = DEFAULT_COLUMNS;
	}
	D.width = D.cur.columns;
}
예제 #9
0
void GameState_Setup::onSwitch(){
    handleResize();
}
void SFNetworkView::initialize( HWND H)
{
	Handle = H;
	handleResize();
}
void opening(XInfo &xinfo)
{
	char *filename[31];
	filename[0] = (char *)"bitmap/open/open0.xbm";
	filename[1] = (char *)"bitmap/open/open1.xbm";
	filename[2] = (char *)"bitmap/open/open2.xbm";
	filename[3] = (char *)"bitmap/open/open3.xbm";
	filename[4] = (char *)"bitmap/open/open4.xbm";
	filename[5] = (char *)"bitmap/open/open5.xbm";
	filename[6] = (char *)"bitmap/open/open6.xbm";
	filename[7] = (char *)"bitmap/open/open7.xbm";
	filename[8] = (char *)"bitmap/open/open8.xbm";
	filename[9] = (char *)"bitmap/open/open9.xbm";
	filename[10] = (char *)"bitmap/open/open10.xbm";
	filename[11] = (char *)"bitmap/open/open11.xbm";
	filename[12] = (char *)"bitmap/open/open12.xbm";
	filename[13] = (char *)"bitmap/open/open13.xbm";
	filename[14] = (char *)"bitmap/open/open14.xbm";
	filename[15] = (char *)"bitmap/open/open15.xbm";
	filename[16] = (char *)"bitmap/open/open16.xbm";
	filename[17] = (char *)"bitmap/open/open17.xbm";
	filename[18] = (char *)"bitmap/open/open18.xbm";
	filename[19] = (char *)"bitmap/open/open19.xbm";
	filename[20] = (char *)"bitmap/open/open20.xbm";
	filename[21] = (char *)"bitmap/open/open21.xbm";
	filename[22] = (char *)"bitmap/open/open22.xbm";
	filename[23] = (char *)"bitmap/open/open23.xbm";
	filename[24] = (char *)"bitmap/open/open24.xbm";
	filename[25] = (char *)"bitmap/open/open25.xbm";
	filename[26] = (char *)"bitmap/open/open26.xbm";
	filename[27] = (char *)"bitmap/open/open27.xbm";
	filename[28] = (char *)"bitmap/open/open28.xbm";
	filename[29] = (char *)"bitmap/open/open29.xbm";
	filename[30] = (char *)"bitmap/open/open30.xbm";
	filename[31] = (char *)"bitmap/open/open31.xbm";
	
	Pixmap opening[31];
	int FPS = 30;
	XEvent event;
	unsigned long lastRepaint = 0;
	int frame = 0;
	int start_huh = 0;
	int time = 60000000;
	XFillRectangle(xinfo.display, xinfo.window, xinfo.gc[0], 0, 0, 800, 600);
	
	while( start_huh == 0) {
		if (XPending(xinfo.display) > 0) {
			XNextEvent( xinfo.display, &event );
			switch( event.type ) {
				case KeyPress:
					handleKeyPress_skip(xinfo, event, start_huh);
					break;
				case ConfigureNotify:
					handleResize(xinfo, event);
					break;	
				
			}
		}
		
		// animation timing
		unsigned long end = now();
		if (frame == 31) 
		{
			//printf("set start to 1\n");
			start_huh = 1;
		}
		if (end - lastRepaint > time/FPS)
		{
			if (frame >= 16) 
				time = 90000000;
			//printf("frame is %d\n", frame);
			opening[frame] = loadbitmap(xinfo, filename[frame]);
			XCopyPlane(xinfo.display, opening[frame], xinfo.window, xinfo.gc[0],
                    0, 0, 800,600, (xinfo.current_w-800)/2, (xinfo.current_h-600)/2,1);
			
			std::string text1("PRESS 's' TO SKIP");
			XDrawImageString( xinfo.display, xinfo.window, xinfo.gc[1], (xinfo.current_w-800)/2+350, (xinfo.current_h-600)/2+550, text1.c_str(), text1.length()  );
			
			frame++;
			lastRepaint = now();
		}


		// give the system time to do other things
		if (XPending(xinfo.display) == 0) {
			usleep(time/FPS - (end - lastRepaint));
		}
	} //end while
}
예제 #12
0
 LRESULT rawHandleResize(UINT uMsg, WPARAM wParam, LPARAM lParam) {return handleResize(wParam, LOWORD(lParam), HIWORD(lParam));}
/** Handles events. Returns true if handled, false otherwise.*/
bool OrbitCameraManipulator::handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa )
{
	switch( ea.getEventType() )
	{

	case osgGA::GUIEventAdapter::FRAME:
		return handleFrame( ea, aa );

	case osgGA::GUIEventAdapter::RESIZE:
		return handleResize( ea, aa );

	default:
		break;
	}

	if( ea.getHandled() )
	{
		return false;
	}

	computeRayPointer( ea, aa );

	bool handled = false;
	switch( ea.getEventType() )
	{
	case osgGA::GUIEventAdapter::MOVE:
		handled = handleMouseMove( ea, aa );
		break;

	case osgGA::GUIEventAdapter::DRAG:
		handled = handleMouseDrag( ea, aa );
		break;

	case osgGA::GUIEventAdapter::PUSH:
		handled = handleMousePush( ea, aa );
		break;

	case osgGA::GUIEventAdapter::RELEASE:
		handled = handleMouseRelease( ea, aa );
		break;

	case osgGA::GUIEventAdapter::KEYDOWN:
		handled = handleKeyDown( ea, aa );
		break;

	case osgGA::GUIEventAdapter::KEYUP:
		m_control_key_down = false;
		handled = handleKeyUp( ea, aa );
		break;

	case osgGA::GUIEventAdapter::SCROLL:
		if( _flags & PROCESS_MOUSE_WHEEL )
			handled = handleMouseWheel( ea, aa );
		else
			handled = false;
		break;

	default:
		handled = false;
	}

	return handled;
}
예제 #14
0
void GameState_Setup::getInput(){
	sf::Event event;

	while (game->mWindow.pollEvent(event)){

		switch (event.type){

		case sf::Event::MouseMoved:
			game->mousePos.x = event.mouseMove.x;
			game->mousePos.y = event.mouseMove.y;
			break;

		case sf::Event::Resized:
			handleResize();
			break;

		case sf::Event::MouseButtonPressed:
			if (event.mouseButton.button == sf::Mouse::Middle){
				middleButtonHeld = true;
				middleButtonCoords = {event.mouseButton.x, event.mouseButton.y};
			}

			else if (event.mouseButton.button == sf::Mouse::Left && drawUI){

				//If no menu item was selectedSpawnableUnit, select it

				if (selectedSpawnableUnit == nullptr){
					sf::Vector2f worldCoords{game->mWindow.mapPixelToCoords(game->mousePos, *game->currentView)};
					sf::Vector2f uiCoords{game->mWindow.mapPixelToCoords(game->mousePos, setupUI.uiView)};

					std::vector<SpawnableUnit> current{game->currentPlayer->getSpawnableUnits()};

					for (size_t i{0}; i < current.size(); ++i){
						if (uiCoords.x > current[i].left() && uiCoords.x < current[i].right()
							&&
							uiCoords.y > current[i].top() && uiCoords.y < current[i].bottom()){

							selectedSpawnableUnit = std::move(std::unique_ptr<SpawnableUnit>(new SpawnableUnit(current[i])));
							break;

						}
					}


					if (uiCoords.x >= setupUI.getButton().left() && uiCoords.x <= setupUI.getButton().right()
						&&
						uiCoords.y >= setupUI.getButton().top() && uiCoords.y <= setupUI.getButton().bottom()){

						//As long as the player has at least one non-general unit
						if (game->currentPlayer->getDeploymentPoints() <= game->currentPlayer->getMaxDeploymentPoints() - 1){
							game->currentPlayer->setReady(true);
						}

					}

					if(selectedSpawnableUnit == nullptr){
						middleButtonHeld = true;
						middleButtonCoords = {event.mouseButton.x, event.mouseButton.y};
					}
				}

				//Spawn a unit on the tile:

				else{
					sf::Vector2i mouseCoords{event.mouseButton.x, event.mouseButton.y};
					sf::Vector2i worldCoords{game->mWindow.mapPixelToCoords(mouseCoords, *game->currentView)};

					TerrainTile* terrain = game->mWorld->terrainAtPixelPos(worldCoords);

					if (terrain != nullptr){

                        if(terrain->getTerrainType() != TerrainTile::TerrainType::WATER){
                            game->currentPlayer->spawnUnit(selectedSpawnableUnit->unitID, worldCoords);
                        }

					}

					selectedSpawnableUnit = nullptr;
					break;
				}
			}


			else if (event.mouseButton.button == sf::Mouse::Right && drawUI){

				//Deselect the currently selectedSpawnableUnit icon:

				if (selectedSpawnableUnit != nullptr){
					selectedSpawnableUnit = nullptr;
					break;
				}

				//Delete a unit from a tile:

				else{
					sf::Vector2i mouseCoords{event.mouseButton.x, event.mouseButton.y};
					sf::Vector2i worldCoords{game->mWindow.mapPixelToCoords(mouseCoords, *game->currentView)};

					auto removed = game->currentPlayer->removeUnit(worldCoords);

					if(removed != nullptr){
                        game->currentPlayer->setDeploymentPoints(game->currentPlayer->getDeploymentPoints() + removed.get()->getCost());
					}

					break;
				}

			}

			break;

		case sf::Event::MouseButtonReleased:

			if (event.mouseButton.button == sf::Mouse::Middle){
				middleButtonHeld = false;
			}
			else if(event.mouseButton.button == sf::Mouse::Left){
				middleButtonHeld = false;
			}

			break;

		case sf::Event::Closed:
			game->exitGame(false);
			break;

		case sf::Event::KeyPressed:

			switch (event.key.code){

			case Key::UP_KEY:
				cameraVelocity = {0.f, -2.f};
				break;

			case Key::RIGHT_KEY:
				cameraVelocity = {2.f, 0.f};
				break;

			case Key::DOWN_KEY:
				cameraVelocity = {0.f, 2.f};
				break;

			case Key::LEFT_KEY:
				cameraVelocity = {-2.f, 0.f};
				break;

			case Key::RESETZOOM_KEY:
				game->currentView->setSize(game->mWindow.getSize().x, game->mWindow.getSize().y);
				break;

            case Key::ZOOMIN_KEY:
				game->currentView->setSize(game->currentView->getSize().x - xResolution / 10, game->currentView->getSize().y - yResolution / 10);
                break;

            case Key::ZOOMOUT_KEY:
				game->currentView->setSize(game->currentView->getSize().x + xResolution / 10, game->currentView->getSize().y + yResolution / 10);
                break;

            case sf::Keyboard::Escape:
            {
                game->setGameState(game->SetupPauseMenuState.get());
            }

            break;

			case Key::HIDE_UI_KEY:
				if (drawUI){
					drawUI = false;
				}
				else if (!drawUI){
					drawUI = true;
				}
				break;

			default: break;
			}

			break;

		case sf::Event::MouseWheelMoved:
			smoothZoom_zooming = true;
			smoothZoom_lerpFactor = 0.0085f;

			if (event.mouseWheel.delta > 0 && game->currentView->getSize().x > xResolution && game->currentView->getSize().y > yResolution){
                //zoom in
                //std::cout << game->currentView->getSize().x << ',' << game->currentView->getSize().y << std::endl;
				//game->currentView->setSize(game->currentView->getSize().x - xResolution / 12, game->currentView->getSize().y - yResolution / 12);
				smoothZoom_targetZoom = 0.8f;
			}
			else if (event.mouseWheel.delta < 0 && game->currentView->getSize().x < xResolution * 4 && game->currentView->getSize().y < yResolution * 4){
			    //zoom out
			    //std::cout << game->currentView->getSize().x << ',' << game->currentView->getSize().y << std::endl;
				//game->currentView->setSize(game->currentView->getSize().x + xResolution / 12, game->currentView->getSize().y + yResolution / 12);
				smoothZoom_targetZoom = 1.2f;
			}

			smoothZoom_currentZoom = 1.0f;
			smoothZoom_previousZoom = smoothZoom_currentZoom;

			smoothZoom_currentCenter = game->currentView->getCenter();

			if(smoothZoom_targetZoom >= 1.f){
				smoothZoom_targetCenter = game->mWindow.mapPixelToCoords(game->mousePos, *(game->currentView));
				auto dist = smoothZoom_targetCenter - smoothZoom_currentCenter;
				dist.x /= 2;
				dist.y /= 2;
				smoothZoom_targetCenter = smoothZoom_currentCenter - dist;
			}
			else{
				smoothZoom_targetCenter = game->mWindow.mapPixelToCoords(game->mousePos, *(game->currentView));
				auto dist = smoothZoom_targetCenter - smoothZoom_currentCenter;
				dist.x /= 2;
				dist.y /= 2;
				smoothZoom_targetCenter = smoothZoom_targetCenter - dist;
			}

			break;

		default: break;
		}

	}

}
예제 #15
0
void Window::handleWindowResize()
{
	//LogInfo("Resizing window to size %dx%d", settings.width, settings.height);
	handleResize();
}
예제 #16
0
/*!
  return true if the event should be removed from the queue false otherwise
*/
static
bool
handleEvent(const SDL_Event &event)
{
    switch (event.type) {
    case SDL_QUIT:
      Input::quitHandler();
      return true;
    case SDL_KEYDOWN:
    case SDL_KEYUP:
      if (!handleDevKey(event.key,0))
	if (!handleDevKey(event.key,1))
	  handleKey(event.key);
      return true;
    case SDL_MOUSEMOTION:
      //      mouseMotion.emit(event.motion);
      return true;
    case SDL_MOUSEBUTTONDOWN:
    case SDL_MOUSEBUTTONUP:
      //      mouseButton.emit(event.button);
      return true;
    case SDL_JOYAXISMOTION:
      handleJoyMotion(event.jaxis);
      return true;
    case SDL_JOYBUTTONDOWN:
    case SDL_JOYBUTTONUP:
      handleJoyButton(event.jbutton);
      return true;
    case SDL_VIDEORESIZE:
#ifndef NEED_RESIZE_HACK
      handleResize(event.resize);
      return true;
#else
      std::cerr << "got resize: "<<event.resize<<" and ";
      if (expectResize) {
	// we assume if we get the right size - this is the event we (unfortunately) produced
	if ((expected.w==event.resize.w)&&(expected.h==event.resize.h)) {
	  std::cerr << "this was the expected resize event\n";
	  expectResize=false;
	  return true;
	}else{
	  std::cerr << "this was NOT the expected resize event\n";      
	  if (eventQueue->size()>2) {
	    std::cerr << "since there are many events pending i stop waiting for this event - i assume it was lost\n";
	    expectResize=false;
	    return true;
	  }
	  return false;
	}
      }else{
	std::cerr << "we do not expect a resize event\n";
	handleResize(event.resize);
	expectResize=true;
	expected=event.resize;
	return true;
      }
#endif
    default:
      std::cerr << "Got unknown event => we drop it\n";
      return true;
    }
}
예제 #17
0
void gameDialog::HandleKeyPress(int key, int action) {
	if (fShowMainDialog && !fHideDialog && key != GLFW_KEY_ESC) {
		if (action == GLFW_PRESS) {
			dialog::DispatchKey(key);
		}
		return;
	}
	if (key >= GLFW_KEY_F1 && key <= GLFW_KEY_F25) {
		gInventory.UseObjectFunctionKey(key);
		return;
	}
	if (fEnterDebugText) {
		// Override the switch, and catch all characters.
		switch (key) {
		case GLFW_KEY_KP_ENTER:
		case GLFW_KEY_ENTER: // ENTER key
			// Done.
			if (fDebugTextLength > 0) {
				fDebugText[fDebugTextLength+3] = 0;
				const char *begin = (char *)fDebugText+3;
				const char *end = strchr(begin, ' ');
				if (end == 0)
					prevCommand = string(begin, fDebugTextLength);
				else
					prevCommand = string(begin, end-begin+1); // Including the space character
				// printf("Prev command: '%s'\n", prevCommand.c_str());
				// There is something to send. Make a proper command of it.
				fDebugText[0] = fDebugTextLength+3;
				fDebugText[1] = 0;
				fDebugText[2] = CMD_DEBUG;
				SendMsg(fDebugText, fDebugTextLength+3);
			}
			// Fall through!
		case GLFW_KEY_ESC: // Escape key, stop composing a command.
			glfwDisable(GLFW_KEY_REPEAT);
			fEnterDebugText = false;
			break;
		case GLFW_KEY_BACKSPACE: // Back space
			if (fDebugTextLength > 0) {
				if (strncmp((const char *)fDebugText+3, prevCommand.c_str(), fDebugTextLength) == 0)
					fDebugTextLength = 1; // Keep the leading '/' only
				else
					fDebugTextLength--;
			}
			this->HandleCharacter(0,0); // Update the shown string
			break;
		}
		return;
	}

	int x, y;
	glfwGetMousePos(&x, &y);
	switch (key) {
	case GLFW_KEY_KP_0:
		// if (gPlayer.fAdmin > 0)
		gToggleTesting = !gToggleTesting;
		break;
	case GLFW_KEY_ESC:
		if (fDrawMap)
			fDrawMap = false;
		else if (fShowInventory) {
			fShowInventory = false;
			gMsgWindow.SetAlternatePosition(0,0,false);
		} else {
			if (fShowMainDialog) {
				fHideDialog = !fHideDialog;
			}
			fShowMainDialog = true;
			this->ClearForDialog();
		}
		break;
	case 'C':
		if (gMode.Get() == GameMode::CONSTRUCT) { // Toggle construction mode
			gMode.Set(GameMode::GAME);
			gShowFramework = false;
		} else {
			gMode.Set(GameMode::CONSTRUCT);
		}
		if (gPlayer.fKnownPosition) {
			ChunkCoord player_cc;
			// Force the current chunk to be redrawn, adapted for construction mode
			gPlayer.GetChunkCoord(&player_cc);
			for (int dx=-1; dx<2; dx++) for (int dy=-1; dy<2; dy++) for (int dz=-1; dz < 2; dz++) {
						ChunkCoord cc = player_cc;
						cc.x += dx; cc.y += dy; cc.z += dz;
						chunk *cp = ChunkFind(&cc, true);
						cp->SetDirty(true);
					}
		}
		break;
	case GLFW_KEY_TAB:
		if (fDrawMap && gDebugOpenGL) {
			// A debug feature to iterate through various interesting bitmaps
			if (!sShowAlternateBitmap) {
				sShowAlternateBitmap = true;
				sTextureIterator = gDebugTextures.begin();
			} else
				sTextureIterator++;
			if (sTextureIterator == gDebugTextures.end()) {
				sShowAlternateBitmap = false;
			}
			break;
		}
		// Find next monster after the selected one.
		fSelectedObject = gMonsters.GetNext(fSelectedObject);
		break;
	case GLFW_KEY_LALT: // ALT key
		if (gMode.Get() == GameMode::CONSTRUCT) {
			gShowFramework = true; // Only when in construction mode
		} else if (gMode.Get() == GameMode::GAME && gPlayer.fAdmin > 0) {
			gMode.Set(GameMode::TELEPORT);
			gAdminTP = true;
		}
		break;
	case '1': // Autoattack
		if (!fSelectedObject) {
			// Find next monster after the selected one.
			fSelectedObject = gMonsters.GetNext(fSelectedObject);
		}
		if (fSelectedObject) { // Initiate attack on a monster, if any.
			unsigned char b[] = { 7, 0, CMD_ATTACK_MONSTER, 0, 0, 0, 0 };
			EncodeUint32(b+3, fSelectedObject->GetId());
			SendMsg(b, sizeof b);
		}
		break;
	case '2': { // Heal self
		unsigned char b[] = { 0x04, 0x00, CMD_PLAYER_ACTION, UserActionHeal };
		SendMsg(b, sizeof b);
		break;
	}
	case '3': { // Instant extra attack
		unsigned char b[] = { 0x04, 0x00, CMD_PLAYER_ACTION, UserActionCombAttack };
		SendMsg(b, sizeof b);
		break;
	}
	case 'I': {
		// Toggle inventory screen
		fShowInventory = !fShowInventory;
		if (!fShowInventory)
			gMsgWindow.SetAlternatePosition(0,0,false);
		break;
	}
	case 'T':
		dumpGraphicsMemoryStats();
		gShowMsgWindow = !gShowMsgWindow;
		break;
	case GLFW_KEY_KP_ENTER:
	case GLFW_KEY_ENTER: // ENTER key
		fEnterDebugText = true;
		glfwEnable(GLFW_KEY_REPEAT);
		// gDebugWindow.Add("Starting to capture debug message");
		strcpy((char *)fDebugText+3, prevCommand.c_str());
		fDebugTextLength = prevCommand.length();
		fDebugText[fDebugTextLength+3] = 0;
		this->HandleCharacter(0,0); // Update the shown string
		break;
	case GLFW_KEY_SPACE: { // space key
		unsigned char b[] = { 0x03, 0x00, CMD_JUMP };
		SendMsg(b, sizeof b);
		gSoundControl.RequestSound(SoundControl::SPlayerJump);
		break;
	}
	case 'W':
	case GLFW_KEY_UP:
		if (!fMovingFwd) {
			fMovingFwd = true;
			unsigned char b[] = { 0x03, 0x00, 10 };
			SendMsg(b, sizeof b);
			// printf("Start fwd\n");
		}
		break;
	case 'A':
	case GLFW_KEY_LEFT:
		if (!fMovingLeft) {
			fMovingLeft = true;
			unsigned char b[] = { 0x03, 0x00, 14 };
			SendMsg(b, sizeof b);
			// printf("Start left\n");
		}
		break;
	case 'S':
	case GLFW_KEY_DOWN:
		if (!fMovingBwd) {
			fMovingBwd = true;
			unsigned char b[] = { 0x03, 0x00, 12 };
			SendMsg(b, sizeof b);
			// printf("Start bwd\n");
		}
		break;
	case 'D':
	case GLFW_KEY_RIGHT:
		if (!fMovingRight) {
			fMovingRight = true;
			unsigned char b[] = { 0x03, 0x00, 16 };
			SendMsg(b, sizeof b);
			// printf("Start right\n");
		}
		break;
	case GLFW_KEY_INSERT: // Insert, closer to delete on a full keyboard
	case 'B':
		if (gMode.Get() == GameMode::CONSTRUCT) {
			this->AttachBlockToSurface(x, y);
		}

		break;
	case GLFW_KEY_DEL: // Delete
	case 'V': // Closer to B when building
		if (gMode.Get() == GameMode::CONSTRUCT) {
			ClickOnBlock(x, y);
		}
		break;
	case GLFW_KEY_KP_SUBTRACT:
		switch(fCalibrationMode) {
		case CALIB_AMBIENT:
			Options::fgOptions.fAmbientLight -= 1;
			gMsgWindow.Add("Ambient light: %f", Options::fgOptions.fAmbientLight/100.0);
			break;
		case CALIB_EXPOSURE:
			Options::fgOptions.fExposure /= 1.1f;
			gMsgWindow.Add("Exposure: %f", Options::fgOptions.fExposure);
			break;
		case CALIB_WHITE_POINT:
			Options::fgOptions.fWhitePoint /= 1.1f;
			gMsgWindow.Add("White point: %f", Options::fgOptions.fWhitePoint);
			break;
		case CALIB_NONE:
			break;
		}
		break;
	case '-': {
		maxRenderDistance -= 5.0;
		if (maxRenderDistance < 5.0f && gDebugOpenGL)
			maxRenderDistance = 5.0f;
		if (maxRenderDistance < 40.0f && !gDebugOpenGL)
			maxRenderDistance = 40.0f;
		handleResize(gViewport[2], gViewport[3]);
		gMsgWindow.Add("Viewing distance: %f m", maxRenderDistance/2);
		break;
	}
	case GLFW_KEY_KP_ADD:
		switch(fCalibrationMode) {
		case CALIB_AMBIENT:
			Options::fgOptions.fAmbientLight += 1;
			gMsgWindow.Add("Ambient light: %f", Options::fgOptions.fAmbientLight/100.0);
			break;
		case CALIB_EXPOSURE:
			Options::fgOptions.fExposure *= 1.1f;
			gMsgWindow.Add("Exposure: %f", Options::fgOptions.fExposure);
			break;
		case CALIB_WHITE_POINT:
			Options::fgOptions.fWhitePoint *= 1.1f;
			gMsgWindow.Add("White point: %f", Options::fgOptions.fWhitePoint);
			break;
		case CALIB_NONE:
			break;
		}
		break;
	case '+': {
		// #255 long distances are not handled very well by neither server nor client
		maxRenderDistance += 5.0;
		if (maxRenderDistance > MAXRENDERDISTANCE)
			maxRenderDistance = MAXRENDERDISTANCE;
		handleResize(gViewport[2], gViewport[3]);
		gMsgWindow.Add("Viewing distance: %f m", maxRenderDistance/2);
		break;
	}
	case 'M': {
		fDrawMap = !fDrawMap;
		break;
	}
	case '\'': {
		if (gPlayer.fAdmin > 0)
			fUsingTorch = !fUsingTorch;
	}
	default:
		gMsgWindow.Add("Unknown key '%d'", key);
		break;
	}
	gGameDialog.UpdateRunningStatus(false);
}