Exemplo n.º 1
0
void
plUpdatePad(CControllerState *state)
{
	if(currentPad >= numPads)
		return;

	int n = currentPad;
//	printf("joy: %s\n", glfwGetJoystickName(GLFW_JOYSTICK_1+n));
	int count;
	const float *axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1+n, &count);
	state->leftX = axes[0] * 32767;
	state->leftY = axes[1] * 32767;
	state->rightX = axes[2] * 32767;
	state->rightY = axes[3] * 32767;
	const unsigned char *buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_1+n, &count);
	state->triangle   = buttons[12];
	state->circle     = buttons[13];
	state->cross      = buttons[14];
	state->square     = buttons[15];
	state->l1         = buttons[10];
	state->l2         = buttons[8];
	state->leftshock  = buttons[1];
	state->r1         = buttons[11];
	state->r2         = buttons[9];
	state->rightshock = buttons[2];
	state->select     = buttons[0];
	state->start      = buttons[3];
	state->up         = buttons[4];
	state->right      = buttons[5];
	state->down       = buttons[6];
	state->left       = buttons[7];
}
Exemplo n.º 2
0
		void draw() override {
			ImVec4 clear_color = ImColor(114, 144, 154);
			static float f = 0.0f;
			// ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.5);
			// ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.8, 0, 0, 0.5));
			ImGui::Begin("Test Window");
			ImGui::SetWindowSize(ImVec2(200, 400), ImGuiSetCond_Always);

			int count;
			const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1, &count);

			ImGui::Text(glfwGetJoystickName(GLFW_JOYSTICK_1));

			for(int i = 0; i < count; i++) {
				joyAx[i] = axes[i];
				char joyname[30];
				sprintf(joyname, "Axis %d", i);
            	ImGui::SliderFloat(joyname, &joyAx[i], -1.0f, 1.0f);
			}

            ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);

            ImGui::End();
            // ImGui::PopStyleColor();
		};
Exemplo n.º 3
0
///@brief Check all available joysticks for an Xbox Controller
/// and store its idx in g_joystickIdx.
/// Unfortunately, this operation is too time-consuming to call every frame
/// in a VR app. The workaround is to call it on key press, space or 'G'.
void FindPreferredJoystick()
{
    g_joystickIdx = -1;
    for (int i = GLFW_JOYSTICK_1; i <= GLFW_JOYSTICK_LAST; ++i)
    {
        if (GL_FALSE == glfwJoystickPresent(i))
            continue;

        const char* pJoyName = glfwGetJoystickName(i);
        if (pJoyName == NULL)
            continue;

        int numAxes = 0;
        int numButtons = 0;
        glfwGetJoystickAxes(i, &numAxes);
        glfwGetJoystickButtons(i, &numButtons);
        LOG_INFO("Glfw found Joystick #%d: %s w/ %d axes, %d buttons", i, pJoyName, numAxes, numButtons);

        // Take an educated guess that this is an Xbox controller - glfw's
        // id string says "Microsoft PC Joystick" for most gamepad types.
        ///@todo Why does GLFW on Linux return a different, more descriptive string?
        if (numAxes == 5 && numButtons == 14)
        {
            g_joystickIdx = i;
            return;
        }
    }
}
Exemplo n.º 4
0
void joystick()
{
    static char s_lastButtons[256] = { 0 };

    ///@todo Handle multiple joysticks

    ///@todo Do these calls take time? We can move them out if so
    int joyStick1Present = GL_FALSE;
    joyStick1Present = glfwJoystickPresent(g_joystickIdx);
    if (joyStick1Present != GL_TRUE)
    {
        if (g_joystickIdx == -1)
            return;
    }

    // Poll joystick
    int numAxes = 0;
    const float* pAxisStates = glfwGetJoystickAxes(g_joystickIdx, &numAxes);
    int numButtons = 0;
    const unsigned char* pButtonStates = glfwGetJoystickButtons(g_joystickIdx, &numButtons);

    // Take an educated guess that this is an Xbox controller - glfw's
    // id string says "Microsoft PC Joystick" for most gamepad types.
    ///@todo Why does GLFW on Linux return a different, more descriptive string?
    if (numAxes == 5 && numButtons == 14)
    {
        joystick_XboxController(g_joystickIdx, pAxisStates, numAxes, pButtonStates, numButtons, s_lastButtons);
    }
    memcpy(s_lastButtons, pButtonStates, numButtons);
}
Exemplo n.º 5
0
void Window::
pollGamepads()
{
    // NB: GLFW limitation limits operation to a single window
    Window* window = main_window_.get();
    if (window != nullptr && window->controller_ != nullptr) {
        for (int i=0; i<MAX_GAMEPADS; ++i) {
            // NB: data is copied into newState object to minimize changes when
            // porting from GLFW2 to GLFW3
            int num_glfw_axes = 0;
            const float* axes = glfwGetJoystickAxes(i, &num_glfw_axes);
            int num_axes = num_glfw_axes < MAX_GAMEPAD_AXES
                               ? num_glfw_axes : MAX_GAMEPAD_AXES;
            int num_glfw_buttons = 0;
            const unsigned char*
                buttons = glfwGetJoystickButtons(i, &num_glfw_buttons);
            int num_buttons = num_glfw_buttons < MAX_GAMEPAD_BUTTONS
                ? num_glfw_buttons : MAX_GAMEPAD_BUTTONS;
            GamepadState newState;
            newState.present = glfwJoystickPresent(i) == GL_TRUE;
            for (int j=0; j<num_axes; ++j) {
                newState.axis[j] = axes[j];
            }
            for (int j=0; j<num_buttons; ++j) {
                newState.button[j] = buttons[j];
            }
            if (newState.present != gamepad_state_[i].present) {
                window->controller_->
                    windowControlGamepadPresenceChanged(window->shared_from_this(),
                    i,
                    newState.present);
            }
            // a few hacks to standardize results from a Microsoft Gamepad
            newState.axis[1] = -newState.axis[1];
            newState.axis[3] = -newState.axis[3];
            newState.axis[7] = newState.axis[2] < 0.f ? -newState.axis[2] : 0.f;
            newState.axis[2] = newState.axis[2] > 0.f ? newState.axis[2] : 0.f;
            // TODO: dpad seems to be missing
            for (int j=0; j<num_axes; ++j) {
                if (newState.axis[j] != gamepad_state_[i].axis[j]) {
                    window->controller_->
                      windowControlGamepadAxisMoved(window->shared_from_this(),
                                                    i,
                                                    j,
                                                    newState.axis[j]);
                }
            }
            for (int j=0; j<num_buttons; ++j) {
                if (newState.button[j] != gamepad_state_[i].button[j]) {
                    window->controller_->windowControlGamepadButtonChanged(
                                            window->shared_from_this(),
                                            i,
                                            j,
                                            newState.button[j] == GLFW_PRESS);
                }
            }
            gamepad_state_[i] = newState;
        }
    }
}
Exemplo n.º 6
0
void RawController::update(){
	// Update buttons flags.
	const float * rawAxes = glfwGetJoystickAxes(_id, &_rawAxesCount);
	const unsigned char * rawButtons = glfwGetJoystickButtons(_id, &_rawButtonsCount);
	
	if(_rawAxesCount != int(allAxes.size())){
		allAxes.resize(_rawAxesCount);
	}
	if(_rawButtonsCount != int(allButtons.size())){
		allButtons.resize(_rawButtonsCount);
	}
	
	for(int aid = 0; aid < _rawAxesCount; ++aid){
		allAxes[aid] = rawAxes[aid];
	}
	
	for(int bid = 0; bid < _rawButtonsCount; ++bid){
		const bool pressed = (rawButtons[bid] == GLFW_PRESS);
		if(pressed){
			if(allButtons[bid].pressed){
				// Already pressed.
				allButtons[bid].first = false;
			} else {
				allButtons[bid].pressed = true;
				allButtons[bid].first = true;
			}
		} else {
			allButtons[bid].pressed = false;
			allButtons[bid].first = false;
		}
	}
	
}
Exemplo n.º 7
0
// Joysticks
void VogueWindow::UpdateJoySticks()
{
	for (int i = 0; i < sizeof(m_joysticks) / sizeof(Joystick); i++)
	{
		Joystick* j = m_joysticks + i;

		if (glfwJoystickPresent(GLFW_JOYSTICK_1 + i))
		{
			const float* axes;
			const unsigned char* buttons;
			int axis_count, button_count;

			free(j->m_name);
			j->m_name = strdup(glfwGetJoystickName(GLFW_JOYSTICK_1 + i));

			axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1 + i, &axis_count);
			if (axis_count != j->m_axisCount)
			{
				j->m_axisCount = axis_count;
				j->m_axes = (float*)realloc(j->m_axes, j->m_axisCount * sizeof(float));
			}

			memcpy(j->m_axes, axes, axis_count * sizeof(float));

			buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_1 + i, &button_count);
			if (button_count != j->m_buttonCount)
			{
				j->m_buttonCount = button_count;
				j->m_buttons = (unsigned char*)realloc(j->m_buttons, j->m_buttonCount);
			}

			memcpy(j->m_buttons, buttons, button_count * sizeof(unsigned char));

			if (!j->m_present)
			{
				printf("\nFound joystick %i named \'%s\' with %i axes, %i buttons\n",
					i + 1, j->m_name, j->m_axisCount, j->m_buttonCount);

				m_joystickCount++;
			}

			j->m_present = GL_TRUE;
		}
		else
		{
			if (j->m_present)
			{
				printf("\nLost joystick %i named \'%s\'\n", i + 1, j->m_name);

				free(j->m_name);
				free(j->m_axes);
				free(j->m_buttons);
				memset(j, 0, sizeof(Joystick));

				m_joystickCount--;
			}
		}
	}
}
Exemplo n.º 8
0
static void refresh_joysticks(void)
{
    int i;

    for (i = 0;  i < sizeof(joysticks) / sizeof(Joystick);  i++)
    {
        Joystick* j = joysticks + i;

        if (glfwGetJoystickParam(GLFW_JOYSTICK_1 + i, GLFW_PRESENT))
        {
            int axis_count, button_count;

            free(j->name);
            j->name = strdup(glfwGetJoystickName(GLFW_JOYSTICK_1 + i));

            axis_count = glfwGetJoystickParam(GLFW_JOYSTICK_1 + i, GLFW_AXES);
            if (axis_count != j->axis_count)
            {
                j->axis_count = axis_count;
                j->axes = realloc(j->axes, j->axis_count * sizeof(float));
            }

            glfwGetJoystickAxes(GLFW_JOYSTICK_1 + i, j->axes, j->axis_count);

            button_count = glfwGetJoystickParam(GLFW_JOYSTICK_1 + i, GLFW_BUTTONS);
            if (button_count != j->button_count)
            {
                j->button_count = button_count;
                j->buttons = realloc(j->buttons, j->button_count);
            }

            glfwGetJoystickButtons(GLFW_JOYSTICK_1 + i, j->buttons, j->button_count);

            if (!j->present)
            {
                printf("Found joystick %i named \'%s\' with %i axes, %i buttons\n",
                       i + 1, j->name, j->axis_count, j->button_count);

                joystick_count++;
            }

            j->present = GL_TRUE;
        }
        else
        {
            if (j->present)
            {
                printf("Lost joystick %i named \'%s\'\n", i + 1, j->name);

                free(j->name);
                free(j->axes);
                free(j->buttons);
                memset(j, 0, sizeof(Joystick));

                joystick_count--;
            }
        }
    }
}
Exemplo n.º 9
0
bool Controller::getRightStickDown()
{
	if (!controllerPresent())
		return false;
	int count = 0;
	const float* axes = glfwGetJoystickAxes(0, &count);
	return axes[3] > 0.25;
}
Exemplo n.º 10
0
bool Controller::getRightTrigger()
{
	if (!controllerPresent())
		return false;
	int count = 0;
	const float* axes = glfwGetJoystickAxes(0, &count);
	return axes[2] < -0.25;
}
Exemplo n.º 11
0
bool Controller::getLeftStickLeft()
{
	if (!controllerPresent())
		return false;
	int count = 0;
	const float* axes = glfwGetJoystickAxes(0, &count);
	return axes[0] < -0.25;
}
Exemplo n.º 12
0
void ImGui_ImplGlfw_NewFrame()
{
    ImGuiIO& io = ImGui::GetIO();
    IM_ASSERT(io.Fonts->IsBuilt());     // Font atlas needs to be built, call renderer _NewFrame() function e.g. ImGui_ImplOpenGL3_NewFrame() 

    // Setup display size
    int w, h;
    int display_w, display_h;
    w = Global.iWindowWidth;
    h = Global.iWindowHeight;
    display_w = w;
    display_h = h;
    io.DisplaySize = ImVec2((float)w, (float)h);
    io.DisplayFramebufferScale = ImVec2(w > 0 ? ((float)display_w / w) : 0, h > 0 ? ((float)display_h / h) : 0);

    // Setup time step
    double current_time = glfwGetTime();
    io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f/60.0f);
    g_Time = current_time;

    ImGui_ImplGlfw_UpdateMousePosAndButtons();
    ImGui_ImplGlfw_UpdateMouseCursor();

    // Gamepad navigation mapping [BETA]
    memset(io.NavInputs, 0, sizeof(io.NavInputs));
    if (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad)
    {
        // Update gamepad inputs
        #define MAP_BUTTON(NAV_NO, BUTTON_NO)       { if (buttons_count > BUTTON_NO && buttons[BUTTON_NO] == GLFW_PRESS) io.NavInputs[NAV_NO] = 1.0f; }
        #define MAP_ANALOG(NAV_NO, AXIS_NO, V0, V1) { float v = (axes_count > AXIS_NO) ? axes[AXIS_NO] : V0; v = (v - V0) / (V1 - V0); if (v > 1.0f) v = 1.0f; if (io.NavInputs[NAV_NO] < v) io.NavInputs[NAV_NO] = v; }
        int axes_count = 0, buttons_count = 0;
        const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1, &axes_count);
        const unsigned char* buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_1, &buttons_count);
        MAP_BUTTON(ImGuiNavInput_Activate,   0);     // Cross / A
        MAP_BUTTON(ImGuiNavInput_Cancel,     1);     // Circle / B
        MAP_BUTTON(ImGuiNavInput_Menu,       2);     // Square / X
        MAP_BUTTON(ImGuiNavInput_Input,      3);     // Triangle / Y
        MAP_BUTTON(ImGuiNavInput_DpadLeft,   13);    // D-Pad Left
        MAP_BUTTON(ImGuiNavInput_DpadRight,  11);    // D-Pad Right
        MAP_BUTTON(ImGuiNavInput_DpadUp,     10);    // D-Pad Up
        MAP_BUTTON(ImGuiNavInput_DpadDown,   12);    // D-Pad Down
        MAP_BUTTON(ImGuiNavInput_FocusPrev,  4);     // L1 / LB
        MAP_BUTTON(ImGuiNavInput_FocusNext,  5);     // R1 / RB
        MAP_BUTTON(ImGuiNavInput_TweakSlow,  4);     // L1 / LB
        MAP_BUTTON(ImGuiNavInput_TweakFast,  5);     // R1 / RB
        MAP_ANALOG(ImGuiNavInput_LStickLeft, 0,  -0.3f,  -0.9f);
        MAP_ANALOG(ImGuiNavInput_LStickRight,0,  +0.3f,  +0.9f);
        MAP_ANALOG(ImGuiNavInput_LStickUp,   1,  +0.3f,  +0.9f);
        MAP_ANALOG(ImGuiNavInput_LStickDown, 1,  -0.3f,  -0.9f);
        #undef MAP_BUTTON
        #undef MAP_ANALOG
        if (axes_count > 0 && buttons_count > 0)
            io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
        else
            io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
    }
}
Exemplo n.º 13
0
				void update() {
					_prev_buttons.resize(_buttons_count, 0);
					for (int i = 0; i < _buttons_count; i++) {
						_prev_buttons[i] = _buttons[i];
					}
					
					_buttons = glfwGetJoystickButtons(_joy, &_buttons_count);
					_axes = glfwGetJoystickAxes(_joy, &_axes_count);
				}
Exemplo n.º 14
0
		void update(EventQueue& _eventQueue)
		{
			int numButtons, numAxes;
			const unsigned char* buttons = glfwGetJoystickButtons(m_handle.idx, &numButtons);
			const float* axes = glfwGetJoystickAxes(m_handle.idx, &numAxes);

			if (NULL == buttons || NULL == axes)
			{
				return;
			}

			if (numAxes > GamepadAxis::Count)
			{
				numAxes = GamepadAxis::Count;
			}

			if (numButtons > Key::Count - Key::GamepadA)
			{
				numButtons = Key::Count - Key::GamepadA;
			}

			WindowHandle defaultWindow = { 0 };

			for (int ii = 0; ii < numAxes; ++ii)
			{
				GamepadAxis::Enum axis = translateGamepadAxis(ii);
				int32_t value = (int32_t) (axes[ii] * 32768.f);
				if (GamepadAxis::LeftY == axis || GamepadAxis::RightY == axis)
				{
					value = -value;
				}

				if (m_axes[ii] != value)
				{
					m_axes[ii] = value;
					_eventQueue.postAxisEvent(defaultWindow
						, m_handle
						, axis
						, value);
				}
			}

			for (int ii = 0; ii < numButtons; ++ii)
			{
				Key::Enum key = translateGamepadButton(ii);
				if (m_buttons[ii] != buttons[ii])
				{
					m_buttons[ii] = buttons[ii];
					_eventQueue.postKeyEvent(defaultWindow
						, key
						, 0
						, buttons[ii] != 0);
				}
			}
		}
Exemplo n.º 15
0
bool Joystick::init(const int index_) {

        _id = index_;
        _name = glfwGetJoystickName(_id);
        _axes = glfwGetJoystickAxes(_id, &_axesNum);
        _polledButtons = glfwGetJoystickButtons(_id, &_buttonsNum);
        for (int i = 0; i < _buttonsNum; ++ i)
                _buttons.push_back(false);
        
	return true;
}
Exemplo n.º 16
0
void Joystick::update(float dt_) {
  (void)dt_;
        _axes = glfwGetJoystickAxes(_id, &_axesNum);
        _leftStick.x() = _axes[0];
        _leftStick.y() = _axes[1];
        _rightStick.x() = _axes[3];
        _rightStick.y() = _axes[4];

        _polledButtons = glfwGetJoystickButtons(_id, &_buttonsNum);
        for (int i = 0; i < _buttonsNum; ++ i)
                _buttons[i] = (_polledButtons[i] == GLFW_PRESS) ? true : false;
}
Exemplo n.º 17
0
	void Joystick_Imp::RefreshInputState()
	{

		const float* ax = glfwGetJoystickAxes(m_connectId, &m_axesCount);
		for (int i = 0; i < m_axesCount; ++i)
		{
			m_currentAxes[i] = ax[i];
		}

		const unsigned char* btns = glfwGetJoystickButtons(m_connectId, &m_buttonsCount);
		for (int i = 0; i < m_buttonsCount; ++i)
		{
			m_preButtonHit[i] = m_currentButtonHit[i];
			m_currentButtonHit[i] = (bool)btns[i];
		}
	}
Exemplo n.º 18
0
	bool Input::step()
	{
		INIT_ASSERT(Input);

		int count;

		for (unsigned i = 0; i < NUM_OF_KEYS; ++i)
		{
			keyState[i] = keyPress[i] > keyRelease[i];

			if (glfwGetKey(Window::instance().window, i) == GLFW_PRESS) keyPress[i]   = glfwGetTime();
			else														keyRelease[i] = glfwGetTime();
		}

		for (unsigned i = 0; i < NUM_OF_MOUSE_BTNS; ++i)
		{
			mouseState[i] = mousePress[i] > mouseRelease[i];

			if (glfwGetMouseButton(Window::instance().window, i) == GLFW_PRESS) mousePress[i]   = glfwGetTime();
			else																mouseRelease[i] = glfwGetTime();
		}

		for (unsigned i = 0; i < activeJoysticks; ++i)
		{
			for (unsigned j = 0; j < NUM_OF_JOY_BTNS; ++j)
			{
				joyState[i][j] = joyPress[i][j] > joyRelease[i][j];

				if (glfwGetJoystickButtons(i, &count)[j] == GLFW_PRESS) joyPress[i][j] = glfwGetTime();
				else													joyRelease[i][j] = glfwGetTime();
			}
		}

		double x, y;
		glfwGetCursorPos(Window::instance().window, &x, &y);

		mouseX = x;
		mouseY = y;

		for (unsigned i = 0; i < activeJoysticks; ++i)
			for (unsigned j = 0; j < NUM_OF_JOY_AXES; ++j)
				joyAxes[i][j] = glfwGetJoystickAxes(i, &count)[j];

		return false;
	}
Exemplo n.º 19
0
	//-----------------------------------------------------------------//
	void device::service(const bits_t& bits, const locator& poss)
	{
		bits_t b = bits;
		int joy = 0;
		if(glfwJoystickPresent(joy) == GL_TRUE) {
			int count;
			const float* axes = glfwGetJoystickAxes(joy, &count);
			for(int i = 0; i < count; ++i) {
				if(i == 1) {
					if(axes[i] > 0.5f) b.set(key::GAME_UP);
					else if(axes[i] < -0.5f) b.set(key::GAME_DOWN);
				} else if(i == 0) {
					if(axes[i] > 0.5f) b.set(key::GAME_RIGHT);
					else if(axes[i] < -0.5f) b.set(key::GAME_LEFT);
				}
			}
			const unsigned char* bl = glfwGetJoystickButtons(joy, &count);
			if(count > 16) count = 16;
			for(int i = 0; i < count; ++i) {
				if(bl[i] != 0) b.set(static_cast<key>(static_cast<int>(key::GAME_0) + i));
			}
		}

		b.set(key::STATE_CAPS_LOCK, level_.test(key::STATE_CAPS_LOCK));
		b.set(key::STATE_SCROLL_LOCK, level_.test(key::STATE_SCROLL_LOCK));
			  b.set(key::STATE_NUM_LOCK, level_.test(key::STATE_NUM_LOCK));

		positive_ =  b & ~level_;
		negative_ = ~b &  level_;

		if(positive_.test(key::CAPS_LOCK)) {
			b.flip(key::STATE_CAPS_LOCK);
		}
		if(positive_.test(key::SCROLL_LOCK)) {
			b.flip(key::STATE_SCROLL_LOCK);
		}
		if(positive_.test(key::NUM_LOCK)) {
			b.flip(key::STATE_NUM_LOCK);
		}

		level_ = b;

		locator_ = poss;
	}
Exemplo n.º 20
0
// Moves/alters the camera positions based on user input
void Do_Movement()
{
    // Camera controls
    if(keys[GLFW_KEY_Z])
        camera.ProcessKeyboard(FORWARD, (GLfloat) deltaTime);
    if(keys[GLFW_KEY_S])
        camera.ProcessKeyboard(BACKWARD, (GLfloat) deltaTime);
    if(keys[GLFW_KEY_Q])
        camera.ProcessKeyboard(LEFT, (GLfloat) deltaTime);
    if(keys[GLFW_KEY_D])
        camera.ProcessKeyboard(RIGHT, (GLfloat) deltaTime);

	if(glfwJoystickPresent(0))
	{
		int nb;
		const float* tab = glfwGetJoystickAxes(0, &nb);
		camera.ProcessJoystickPad(tab[0], tab[1], tab[3], tab[4], (GLfloat) deltaTime);
	}
}
Exemplo n.º 21
0
 std::vector<JoystickState> GLFW_App::get_joystick_states() const
 {
     std::vector<JoystickState> ret;
     int count;
     for(int i = GLFW_JOYSTICK_1; i <= GLFW_JOYSTICK_LAST; i++)
     {
         if(!glfwJoystickPresent(i)) continue;
         
         const float *glfw_axis = glfwGetJoystickAxes(i, &count);
         std::vector<float> axis(glfw_axis, glfw_axis + count);
         
         const uint8_t *glfw_buttons = glfwGetJoystickButtons(i, &count);
         std::vector<uint8_t> buttons(glfw_buttons, glfw_buttons + count);
         
         std::string name(glfwGetJoystickName(i));
         ret.push_back(JoystickState(name, buttons, axis));
     }
     return ret;
 }
Exemplo n.º 22
0
static void joystick_callback(int joy, int event)
{
    if (event == GLFW_CONNECTED)
    {
        int axisCount, buttonCount;

        glfwGetJoystickAxes(joy, &axisCount);
        glfwGetJoystickButtons(joy, &buttonCount);

        printf("%08x at %0.3f: Joystick %i (%s) was connected with %i axes and %i buttons\n",
               counter++, glfwGetTime(),
               joy,
               glfwGetJoystickName(joy),
               axisCount,
               buttonCount);
    }
    else
    {
        printf("%08x at %0.3f: Joystick %i was disconnected\n",
               counter++, glfwGetTime(), joy);
    }
}
Exemplo n.º 23
0
 void Joystick::Update() {
   previous_axes = axes;
   previous_buttons = buttons;
   if (glfwJoystickPresent(joystick_id)) {
     int axis_count = 0;
     const float *axis_data = glfwGetJoystickAxes(joystick_id, &axis_count);
     CHECK_STATE(axis_count);
     CHECK_STATE(axis_data);
     for (auto i = 0; i < axis_count; ++i) {
       axes[static_cast<Axis>(i)] = axis_data[i];
     }
     int button_count = 0;
     const unsigned char *button_data = glfwGetJoystickButtons(joystick_id, &button_count);
     CHECK_STATE(button_count);
     CHECK_STATE(button_data);
     for (auto i = static_cast<int>(Button::kBegin); i < static_cast<int>(Button::kEnd); ++i) {
       buttons[static_cast<Button>(i)] = button_data[i];
     }
   }
   auto now = std::chrono::high_resolution_clock::now();
   dt = std::chrono::duration_cast<std::chrono::duration<float>>(now - last_update_time).count();
   last_update_time = now;
 }
///@brief Check out what joysticks we have and select a preferred one
bool OculusAppSkeleton::initJoysticks()
{
    for (int i=GLFW_JOYSTICK_1; i<GLFW_JOYSTICK_16; ++i)
    {
        const int present = glfwJoystickPresent(i);
        if (present == GL_TRUE)
        {
            /// Nostromo:                   6 axes, 24 buttons
            /// Gravis Gamepad Pro:         2 axes, 10 buttons
            /// Generic wireless dualshock: 4 axes, 12 buttons
            /// Eliminator Aftershock:      6 axes, 10 buttons
            int numAxes = 0;
            int numButs = 0;
            glfwGetJoystickAxes(i, &numAxes);
            glfwGetJoystickButtons(i, &numButs);
            printf("Joystick %d:  %d axes, %d buttons\n", i, numAxes, numButs);

            /// This just finds the first available joystick.
            if ( (numAxes == 2) && (numButs == 10))
            {
                preferredGamepadID = i;
                swapGamepadRAxes = false;
            }
            else if ( (numAxes == 6) && (numButs == 10))
            {
                preferredGamepadID = i;
                swapGamepadRAxes = false;
            }
            else if ( (numAxes == 4) && (numButs == 12))
            {
                preferredGamepadID = i;
                swapGamepadRAxes = true;
            }
        }
    }
    return true;
}
Exemplo n.º 25
0
void Joystick::update(Step * _step){
	// handle buttons
	int buttonCount;
	const unsigned char * buttons = glfwGetJoystickButtons(id, &buttonCount);
	for(signed long int i = 0; i < buttonCount; ++i){
		if(buttons[i] == GLFW_PRESS){
			buttonDownListener(i);
		}else if(buttons[i] == GLFW_RELEASE){
			buttonUpListener(i);
		}else{
			// this part shouldn't actually fire
			buttonNullListener(i);
		}
	}
	
	// handle axes
	axesValuesPrev = axesValues;
	axesValues.clear();
	int axesCount;
	const float * axes = glfwGetJoystickAxes(id, &axesCount);
	for(signed long int i = 0; i < axesCount; ++i){
		axesValues.insert(std::pair<int, float>(i, axes[i]));
	}
}
void ofxGLFWJoystick::lookForJoysticks(){

	int n = 0;
	for(int i = 0; i < GLFW_JOYSTICK_LAST; i++){
		if(glfwJoystickPresent(i)){
			joyData[i].available = true;
			string name = string(glfwGetJoystickName(i));
			if(name != joyData[i].name){
				joyData[i].name = name;
				ofLogNotice("ofxGLFWJoystick") << "Joystick Found at index " << i << ": '" << name << "'";
				joyData[i].axisData = glfwGetJoystickAxes(i, &joyData[i].numAxis);
				joyData[i].buttonData = glfwGetJoystickButtons(i, &joyData[i].numButtons);
			}
			n++;
		}else{
			if (joyData[i].name.size()){
				ofLogNotice("ofxGLFWJoystick") << "Joystick Lost at index " << i << ": '" << joyData[i].name << "'";
			}
			joyData[i].available = false;
			joyData[i].name = "";
		}
	}
	numJoysticks = n;
}
Exemplo n.º 27
0
//
// カラーバッファを入れ替えてイベントを取り出す
//
//   ・図形の描画終了後に呼び出す
//   ・ダブルバッファリングのバッファの入れ替えを行う
//   ・キーボード操作等のイベントを取り出す
//
void Window::swapBuffers()
{
#if STEREO == OCULUS
  // ディスプレイに描く
  glBindFramebuffer(GL_FRAMEBUFFER, 0);
  glDrawBuffer(GL_BACK);

  // 隠面消去処理は行わない
  glDisable(GL_DEPTH_TEST);

  // アルファブレンディングを行わない
  glDisable(GL_BLEND);

  // 表示領域を覆う矩形
  glBindVertexArray(ocuVao);

  // Oculus Rift のレンズ補正用シェーダ
  glUseProgram(ocuProgram);

  // FBO に描画した結果を参照するテクスチャユニット
  glActiveTexture(GL_TEXTURE0);
  glUniform1i(ocuFboColorLoc, 0);

  // Oculus Rift のアスペクト比
  glUniform1f(ocuAspectLoc, ocuAspect);

  // レンズの歪みの補正係数
  glUniform4fv(lensDistortionLoc, 1, lensDistortion);

  // レンズの拡大率の補正係数
  glUniform1f(lensScaleLoc, lensScale);

  // 左目の描画
  glUniform1f(projectionCenterOffsetLoc, -projectionCenterOffset);
  glViewport(0, 0, winW, winH);
  glBindTexture(GL_TEXTURE_2D, ocuFboColor[0]);
  glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

  // 右目の描画
  glUniform1f(projectionCenterOffsetLoc, projectionCenterOffset);
  glViewport(winW, 0, winW, winH);
  glBindTexture(GL_TEXTURE_2D, ocuFboColor[1]);
  glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
#endif

#if BENCHMARK
  glEndQuery(GL_TIME_ELAPSED);
  GLint done;
  do { glGetQueryObjectiv(query, GL_QUERY_RESULT_AVAILABLE, &done); } while (!done);
  GLuint64 elapsed_time;
  glGetQueryObjectui64v(query, GL_QUERY_RESULT, &elapsed_time);
  std::cout << static_cast<double>(elapsed_time) * 0.000001 << std::endl;
#endif

  // エラーチェック
  ggError("SwapBuffers");

  // カラーバッファを入れ替える
  glfwSwapBuffers(window);

  // イベントを取り出す
  glfwPollEvents();

  // マウスの位置を調べる
  double x, y;
  glfwGetCursorPos(window, &x, &y);

  // 左ボタンドラッグ
  if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_1))
  {
    // ボリュームデータの位置を移動する
    ex -= speedScale * static_cast<GLfloat>(x - cx);
    ez -= speedScale * static_cast<GLfloat>(y - cy);
  }

  // 右ボタンドラッグ
  if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_2))
  {
    // トラックボール回転
    tb.motion(static_cast<GLfloat>(x), static_cast<GLfloat>(y));
  }

  // ゲームパッドによる操作
  if (joy >= 0)
  {
    // スティック
    int axesCount;
    const float *const axes(glfwGetJoystickAxes(joy, &axesCount));

    if (axesCount > 3 + axesOffset)
    {
      // ボリュームデータの位置を移動する
      ex -= (axes[0] - origin[0]) * axesSpeedScale;
      ez -= (axes[1] - origin[1]) * axesSpeedScale;

      // ボリュームデータを回転する
      const GLfloat dx(axes[2 + axesOffset] - origin[2]);
      const GLfloat dy(axes[3 + axesOffset] - origin[3]);
      const GLfloat l = dx * dx + dy * dy;
      if (l > 0.0f)
      {
        tb.rotate(ggRotateQuaternion(dy, dx, 0.0f, l * axesAngleScale));
      }
    }

    // ボタン
    int btnsCount;
    const unsigned char *const btns(glfwGetJoystickButtons(joy, &btnsCount));
    if (btnsCount > 3)
    {
      // 閾値を調整する
      const float t(threshold + static_cast<GLfloat>(btns[2] - btns[1]) * btnsScale);
      if (t >= 0.0f && t <= 1.0f) threshold = t;
    }

    // ボリュームデータの回転を元に戻す
    if (btnsCount > 4 && btns[4] > 0) tb.reset();
  }

#if STEREO != NONE
  // 左矢印キー操作
  if (glfwGetKey(window, GLFW_KEY_LEFT))
  {
#  if STEREO == OCULUS
    if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) || glfwGetKey(window, GLFW_KEY_RIGHT_SHIFT))
    {
      // レンズ間隔を縮小する
      projectionCenterOffset -= projectionCenterOffsetStep;
    }
    else
    {
      // 視差を縮小する
      parallax -= parallaxStep;
      updateStereoProjectionMatrix();
    }
#  else
    // 視差を縮小する
    parallax -= parallaxStep;
    updateStereoProjectionMatrix();
#  endif
  }

  // 右矢印キー操作
  if (glfwGetKey(window, GLFW_KEY_RIGHT))
  {
#  if STEREO == OCULUS
    if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) || glfwGetKey(window, GLFW_KEY_RIGHT_SHIFT))
    {
      // レンズ間隔を拡大する
      projectionCenterOffset += projectionCenterOffsetStep;
    }
    else
    {
      // 視差を拡大する
      parallax += parallaxStep;
      updateStereoProjectionMatrix();
    }
#  else
    // 視差を拡大する
    parallax += parallaxStep;
    updateStereoProjectionMatrix();
#  endif
  }

#  if STEREO == OCULUS
  // 左矢印キー操作
  if (glfwGetKey(window, GLFW_KEY_DOWN))
  {
    // レンズの拡大率の補正係数を下げる
    lensScale -= lensScaleStep;
  }

  // 右矢印キー操作
  if (glfwGetKey(window, GLFW_KEY_UP))
  {
    // レンズの拡大率の補正係数を上げる
    lensScale += lensScaleStep;
  }
#  endif
#endif
}
Exemplo n.º 28
0
//
// コンストラクタ
//
Window::Window(int width, int height, const char *title, GLFWmonitor *monitor, GLFWwindow *share)
  : window(glfwCreateWindow(width, height, title, monitor, share))
  , ex(startPosition[0])                  // カメラの x 座標
  , ey(startPosition[1])                  // カメラの y 座標
  , ez(startPosition[2])                  // カメラの z 座標
  , threshold(0.5f)                       // 閾値
  , blend(true)                           // アルファブレンディング
#if STEREO != OCULUS && STEREO != NONE
  , parallax(initialParallax)
#endif
#if STEREO != OCULUS
  , scrH(zNear * screenCenter / screenDistance)
#endif
{
  if (!window) return;

  // 現在のウィンドウを処理対象にする
  glfwMakeContextCurrent(window);

  // 作成したウィンドウに対する設定
  glfwSwapInterval(1);

  // ウィンドウのサイズ変更時に呼び出す処理の登録
  glfwSetFramebufferSizeCallback(window, resize);

  // マウスボタンを操作したときの処理
  glfwSetMouseButtonCallback(window, mouse);

  // マウスホイール操作時に呼び出す処理
  glfwSetScrollCallback(window, wheel);

  // キーボードを操作した時の処理
  glfwSetKeyCallback(window, keyboard);

  // マウスカーソルを表示する
  glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);

  // このインスタンスの this ポインタを記録しておく
  glfwSetWindowUserPointer(window, this);

  // ゲームグラフィックス特論の都合にもとづく初期化
  if (!glCreateProgram) ggInit();

  // ジョイステックの有無を調べて番号を決める
  joy = glfwJoystickPresent(count) ? count : -1;

  // スティックの中立位置を求める
  if (joy >= 0)
  {
    int axesCount;
    const float *const axes(glfwGetJoystickAxes(joy, &axesCount));

    if (axesCount > 3 + axesOffset)
    {
      // 起動直後のスティックの位置を基準にする
      origin[0] = axes[0];
      origin[1] = axes[1];
      origin[2] = axes[2 + axesOffset];
      origin[3] = axes[3 + axesOffset];
    }
  }

#if STEREO == OCULUS
  // プログラムオブジェクト, VAO / VBO, Oculus Rift のデバイスマネージャーの作成は最初一度だけ行う
  if (count == 0)
  {
    // Oculus Rift のレンズの歪みを補正するシェーダプログラム
    ocuProgram = ggLoadShader("oculus.vert", "oculus.frag");
    ocuFboColorLoc = glGetUniformLocation(ocuProgram, "ocuFboColor");
    ocuAspectLoc = glGetUniformLocation(ocuProgram, "ocuAspect");
    projectionCenterOffsetLoc = glGetUniformLocation(ocuProgram, "projectionCenterOffset");
    lensDistortionLoc = glGetUniformLocation(ocuProgram, "lensDistortion");
    lensScaleLoc = glGetUniformLocation(ocuProgram, "lensScale");

    // Oculus Rift 表示に使う矩形
    glGenVertexArrays(1, &ocuVao);
    glBindVertexArray(ocuVao);
    glGenBuffers(1, &ocuVbo);
    glBindBuffer(GL_ARRAY_BUFFER, ocuVbo);
    static const GLfloat rect[] = { -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f };
    glBufferData(GL_ARRAY_BUFFER, sizeof rect, rect, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(0);

    // Oculus Rift のデバイスマネージャーの作成
    pManager = *DeviceManager::Create();
  }

  // Oculus Rift のデバイスマネージャーが作成できたら情報を取得する
  if (pManager
    && (pHmd = *pManager->EnumerateDevices<HMDDevice>().CreateDevice())
    && pHmd->GetDeviceInfo(&hmdInfo)
    )
  {
#  if defined(_DEBUG)
    // 取得した情報を表示する
    std::cout << hmdInfo.DisplayDeviceName << std::endl;
    std::cout << "\nResolution:"
      << hmdInfo.HResolution << ", "
      << hmdInfo.VResolution << std::endl;
    std::cout << "\nScreen size: "
      << hmdInfo.HScreenSize << ", "
      << hmdInfo.VScreenSize << std::endl;
    std::cout << "\nVertical Screen Center: "
      << hmdInfo.VScreenCenter << std::endl;
    std::cout << "\nEye to Screen Distance: "
      << hmdInfo.EyeToScreenDistance << std::endl;
    std::cout << "\nLens Separation Distance: "
      << hmdInfo.LensSeparationDistance << std::endl;
    std::cout << "\nInterpupillary Distance: "
      << hmdInfo.InterpupillaryDistance << std::endl;
    std::cout << "\nDistortion: "
      << hmdInfo.DistortionK[0] << ", "
      << hmdInfo.DistortionK[1] << ", "
      << hmdInfo.DistortionK[2] << ", "
      << hmdInfo.DistortionK[3] << std::endl;
    std::cout << std::endl;
#  endif

    // レンズの中心の画面の中心からのずれ
    projectionCenterOffset = 1.0f - 2.0f * hmdInfo.LensSeparationDistance / hmdInfo.HScreenSize;

    // スクリーンの幅と高さ
    scrW = scrH = zNear * hmdInfo.VScreenCenter / hmdInfo.EyeToScreenDistance;

    // 視差
    parallax = hmdInfo.InterpupillaryDistance * 0.5f;

    // レンズの歪みの補正係数
    lensDistortion[0] = hmdInfo.DistortionK[0];
    lensDistortion[1] = hmdInfo.DistortionK[1];
    lensDistortion[2] = hmdInfo.DistortionK[2];
    lensDistortion[3] = hmdInfo.DistortionK[3];

    // 片目の表示領域のアスペクト比
    ocuAspect = hmdInfo.HScreenSize * 0.5f / hmdInfo.VScreenSize;

    // Oculus Rift のセンサの取得
    pSensor = *pHmd->GetSensor();

    // センサーを登録する
    if (pSensor) sensorFusion.AttachToSensor(pSensor);
  }
  else
  {
    // Oculus Rift をつながずにデバッグする時の設定
    scrW = scrH = zNear * 0.0468f / 0.041f;
    parallax = 0.064f * 0.5f;
    projectionCenterOffset = 1.0f - 2.0f * 0.0635f / 0.14976f;
    lensDistortion[0] = 1.0f;
    lensDistortion[1] = 0.2f;
    lensDistortion[2] = 0.24f;
    lensDistortion[3] = 0.0f;
    ocuAspect = 0.14976f * 0.5f / 0.0936f;
    pSensor = nullptr;
  }

  // レンズの歪み補正に伴う拡大率の補正
  lensScale = 1.0f / (lensDistortion[0] + lensDistortion[1] + lensDistortion[2] + lensDistortion[3]);

  // Oculus Rift の左目用と右目用の FBO の準備
  glGenFramebuffers(2, ocuFbo);

  // Oculus Rift 表示用の FBO のデプスバッファとして使うレンダーバッファの作成
  glGenRenderbuffers(1, &ocuFboDepth);
  glBindRenderbuffer(GL_RENDERBUFFER, ocuFboDepth);
  glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, fboWidth, fboHeight);

  // Oculus Rift 表示用の FBO のカラーバッファとして使うカラーテクスチャの作成
  glGenTextures(2, ocuFboColor);
  for (int i = 0; i < 2; ++i)
  {
    // 左右の目のそれぞれの表示サイズより少し大きなテクスチャメモリの確保
    glBindTexture(GL_TEXTURE_2D, ocuFboColor[i]);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fboWidth, fboHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border);

    // 左右の目のそれぞれについて FBO を作成する
    glBindFramebuffer(GL_FRAMEBUFFER, ocuFbo[i]);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
      GL_TEXTURE_2D, ocuFboColor[i], 0);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
      GL_RENDERBUFFER, ocuFboDepth);
  }
#endif

  // 投影変換行列・ビューポートを初期化する
  resize(window, width, height);

#if BENCHMARK
  // 時間計測用の Query Object を作成する
  glGenQueries(1, &query);
#endif

  // 参照カウントを増す
  ++count;
}
Exemplo n.º 29
0
static void refresh_joysticks(void)
{
    int i;

    for (i = 0;  i < sizeof(joysticks) / sizeof(Joystick);  i++)
    {
        Joystick* j = joysticks + i;

        if (glfwJoystickPresent(GLFW_JOYSTICK_1 + i))
        {
            const float* axes;
            const unsigned char* buttons;
            int axis_count, button_count;

            free(j->name);
            j->name = strdup(glfwGetJoystickName(GLFW_JOYSTICK_1 + i));

            axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1 + i, &axis_count);
            if (axis_count != j->axis_count)
            {
                j->axis_count = axis_count;
                j->axes = realloc(j->axes, j->axis_count * sizeof(float));
            }

            memcpy(j->axes, axes, axis_count * sizeof(float));

            buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_1 + i, &button_count);
            if (button_count != j->button_count)
            {
                j->button_count = button_count;
                j->buttons = realloc(j->buttons, j->button_count);
            }

            memcpy(j->buttons, buttons, button_count * sizeof(unsigned char));

            if (!j->present)
            {
                printf("Found joystick %i named \'%s\' with %i axes, %i buttons\n",
                       i + 1, j->name, j->axis_count, j->button_count);

                joystick_count++;
            }

            j->present = GL_TRUE;
        }
        else
        {
            if (j->present)
            {
                printf("Lost joystick %i named \'%s\'\n", i + 1, j->name);

                free(j->name);
                free(j->axes);
                free(j->buttons);
                memset(j, 0, sizeof(Joystick));

                joystick_count--;
            }
        }
    }
}
Exemplo n.º 30
0
int main()
{
    setup_resources();

    config::register_var("screen_width", "1000");
    config::register_var("screen_height", "562");
    config::register_var("master_volume", "10");
    config::register_var("music_volume", "5");

    platform platform;
    if (!platform.init(config::get_var_int("screen_width"), config::get_var_int("screen_height"), "Open Horizon 7th demo"))
        return -1;

    std::vector<joystick_config> joysticks;

    for (int i = 0; glfwJoystickPresent(i); ++i)
    {
        const char *name = glfwGetJoystickName(i);

        joystick_config j;
        j.init(name);
        joysticks.push_back(j);

        int axis_count = 0, buttons_count = 0;
        glfwGetJoystickAxes(i, &axis_count);
        glfwGetJoystickButtons(i, &buttons_count);
        printf("joy%d: %s %d axis %d buttons\n", i, name, axis_count, buttons_count);
    }

    renderer::scene scene;
    sound::world sound_world;
    game::world world(scene, sound_world, scene.hud);
    game::mission game_mode_ms(world);
    game::free_flight game_mode_ff(world);
    game::deathmatch game_mode_dm(world);
    game::team_deathmatch game_mode_tdm(world);
    game::hangar hangar(scene);
    game::game_mode *active_game_mode = 0;
    game::plane_controls controls;
    game::network_client client;
    game::network_server server;

    gui::menu menu(sound_world);
    gui::menu_controls menu_controls;

    platform::key_callback kcb = std::bind(&gui::menu::on_input, &menu, std::placeholders::_1);
    platform.set_keyboard_callback(kcb);

    int mx = platform.get_mouse_x(), my = platform.get_mouse_y();
    int screen_width = platform.get_width(), screen_height = platform.get_height();
    scene.resize(screen_width, screen_height);
    scene.loading(true);
    nya_render::clear(true, true);
    scene.draw();
    platform.end_frame();

    sound_world.set_volume(config::get_var_int("master_volume") / 10.0f);
    sound_world.set_music_volume(config::get_var_int("music_volume") / 10.0f);

    menu.init();
    sound_world.set_music("BGM_menu");

    bool viewer_mode = false;
    bool is_client = false, is_server = false;

    gui::menu::on_action on_menu_action = [&](const std::string &event)
    {
        if (event == "start")
        {
            sound_world.stop_music();
            const char *music_names[] = {"BGM_ms10_08", "BGM_ms06", "BGM_ms08x", "BGM_ms11a", "BGM_ms11b", "BGM_ms12_02"};
            sound_world.set_music(music_names[rand() % (sizeof(music_names) / sizeof(music_names[0]))]);

            auto location = menu.get_var("map");
            auto plane = menu.get_var("ac");
            const int color = atoi(menu.get_var("color").c_str());

            is_client = false, is_server = false;

            scene.loading(true);
            nya_render::clear(true, true);
            scene.draw();
            platform.end_frame();
            scene.loading(false);

            auto mode = menu.get_var("mode");
            auto mp_var = menu.get_var("multiplayer");
            if (mp_var == "server")
            {
                world.set_network(&server);
                auto port = menu.get_var_int("port");
                server.open(port, config::get_var("name").c_str(), mode.c_str(), menu.get_var("map").c_str(), menu.get_var_int("max_players"));
                if (menu.get_var("mp_public") == "true")
                    game::servers_list::register_server(port);
                is_server = true;
            }
            else if (mp_var == "client")
            {
                world.set_network(&client);
                client.start();
                is_client = true;
            }

            if (mode == "ms")
            {
                active_game_mode = &game_mode_ms;
                game_mode_ms.start(plane.c_str(), color,  menu.get_var("mission").c_str());
            }
            else if (mode == "dm")
            {
                const int bots_count = (is_client || is_server) ? 0 : 11;

                active_game_mode = &game_mode_dm;
                game_mode_dm.start(plane.c_str(), color, 0, location.c_str(), bots_count);
            }
            else if (mode == "tdm")
            {
                const int bots_count = (is_client || is_server) ? 0 : 7;

                active_game_mode = &game_mode_tdm;
                game_mode_tdm.start(plane.c_str(), color, 0, location.c_str(), bots_count);
            }
            else if (mode == "ff")
            {
                active_game_mode = &game_mode_ff;
                game_mode_ff.start(plane.c_str(), color, location.c_str());
            }
        }
        else if (event == "connect")
        {
            menu.set_error("");
            client.disconnect();
            auto port = menu.get_var_int("port");
            if (client.connect(menu.get_var("address").c_str(), port))
            {
                menu.send_event("map=" + client.get_server_info().location);
                menu.send_event("mode=" + client.get_server_info().game_mode);
                menu.send_event("screen=ac_select");
            }
            else
                menu.set_error(client.get_error());
        }
        else if (event == "viewer_start")
        {
            viewer_mode = true;
            scene.camera.add_delta_rot(0.2f, 2.5f);
        }
        else if (event == "viewer_update_bg")
        {
            hangar.set_bkg(menu.get_var("bkg").c_str());
        }
        else if (event == "viewer_update_ac")
        {
            const auto dr = scene.camera.get_delta_rot();
            hangar.set_plane(menu.get_var("ac").c_str());
            scene.camera.add_delta_rot(dr.x, dr.y - 3.14f);
        }
        else if (event == "viewer_update_color")
        {
            const auto dr = scene.camera.get_delta_rot();
            const int color = atoi(menu.get_var("color").c_str());
            hangar.set_plane_color(color);
            scene.camera.add_delta_rot(dr.x, dr.y - 3.14f);
        }
        else if (event == "viewer_end")
        {
            viewer_mode = false;
            hangar.end();
        }
        else if (event == "update_volume")
        {
            sound_world.set_volume(config::get_var_int("master_volume") / 10.0f);
            sound_world.set_music_volume(config::get_var_int("music_volume") / 10.0f);
        }
        else if (event == "update_joy_config")
        {
            if (!joysticks.empty())
                joysticks.front().update_config();
        }
        else if (event == "exit")
        {
            server.close();
            client.disconnect();
            platform.terminate();
        }
        else
            printf("unknown event: %s\n", event.c_str());
    };

    menu.set_callback(on_menu_action);

    bool reset_camera = false;

    unsigned long app_time = nya_system::get_time();
    while (!platform.should_terminate())
    {
        unsigned long time = nya_system::get_time();
        int dt = int(time - app_time);

        if (dt > 1000 && !is_client && !is_server)
            dt = 1000;

        app_time = time;

        static bool speed10x = false, last_pause = false, paused = false;

        if (platform.get_width() != screen_width || platform.get_height() != screen_height)
        {
            screen_width = platform.get_width(), screen_height = platform.get_height();
            scene.resize(screen_width, screen_height);

            config::set_var("screen_width", std::to_string(screen_width));
            config::set_var("screen_height", std::to_string(screen_height));
        }

        if (!active_game_mode)
            menu.update(dt, menu_controls);

        if (active_game_mode)
        {
            if (!paused)
            {
                active_game_mode->update(speed10x ? dt * 10 : dt, controls);

                //camera - tracking enemy
                auto p = world.get_player();
                if (p && p->change_target_hold_time >= game::plane::change_target_hold_max_time && !p->targets.empty() && !p->targets.front().target.expired())
                {
                    static auto last_target = p->targets.front().target;
                    if (last_target.expired() || last_target.lock() != p->targets.front().target.lock())
                    {
                        last_target = p->targets.front().target;
                        p->change_target_hold_time = game::plane::change_target_hold_max_time;
                    }

                    auto t = p->targets.front().target.lock();
                    auto tdir = t->get_pos() - p->get_pos(); // + (t->get_vel() - p->get_vel()) * (dt * 0.001f)
                    nya_math::quat q(nya_math::vec3::forward(), tdir);
                    q = nya_math::quat::invert(p->get_rot()) * q;

                    auto da = q.get_euler();
                    scene.camera.reset_delta_rot();

                    const float k = nya_math::min((p->change_target_hold_time - game::plane::change_target_hold_max_time) / 500.0f, 1.0);

                    scene.camera.add_delta_rot(da.x * k, -da.y * k);
                    reset_camera = true;
                }
            }

            scene.draw();

            //util debug draw
            nya_render::clear(false, true);
            nya_render::set_state(nya_render::state());
            nya_render::set_modelview_matrix(nya_scene::get_camera().get_view_matrix());
            get_debug_draw().set_line_width(2.0f);
            get_debug_draw().set_point_size(3.0f);
            get_debug_draw().draw();
        }
        else
        {
            nya_render::clear(true, true);

            if (viewer_mode)
            {
                hangar.update(dt);
                scene.draw();
            }

            menu.draw(scene.ui_render);
        }

        const char *ui_ref = 0;
        //ui_ref = "ui_ref4.tga";
        if (ui_ref)
        {
            static nya_scene::texture ui_ref_texture(ui_ref);
            static std::vector<gui::rect_pair> ui_ref_rects(1);
            ui_ref_rects[0].r.w = scene.ui_render.get_width();
            ui_ref_rects[0].r.y = scene.ui_render.get_height();
            ui_ref_rects[0].r.h = -scene.ui_render.get_height();
            ui_ref_rects[0].tc.w = ui_ref_texture.get_width();
            ui_ref_rects[0].tc.h = ui_ref_texture.get_height();
            static int alpha_anim = 0;
            alpha_anim += dt;
            alpha_anim = alpha_anim % 4000;
            //alpha_anim = 1000;
            scene.ui_render.draw(ui_ref_rects, ui_ref_texture, nya_math::vec4(1.0, 1.0, 1.0, fabsf(alpha_anim / 2000.0f - 1.0)));
        }

        platform.end_frame();

        //controls

        controls = game::plane_controls();
        menu_controls = gui::menu_controls();

        if (platform.get_mouse_lbtn())
            scene.camera.add_delta_rot((platform.get_mouse_y() - my) * 0.03, (platform.get_mouse_x() - mx) * 0.03);

        if (platform.get_mouse_rbtn())
            scene.camera.add_delta_pos(0, 0, my - platform.get_mouse_y());

        mx = platform.get_mouse_x(), my = platform.get_mouse_y();

        bool pause = false;
        for (int i = 0; i < (int)joysticks.size(); ++i)
        {
            int axes_count = 0, buttons_count = 0;
            const float *axes = glfwGetJoystickAxes(i, &axes_count);
            const unsigned char *buttons = glfwGetJoystickButtons(i, &buttons_count);
            joysticks[i].update(axes, axes_count, buttons, buttons_count);
            joysticks[i].apply_controls(controls, pause);

            if (!active_game_mode)
            {
                if (i == 0 && !menu.joy_update(axes, axes_count, buttons, buttons_count))
                    joysticks[i].apply_controls(menu_controls);
            }
        }

        if (platform.get_key(GLFW_KEY_W)) controls.throttle = 1.0f;
        if (platform.get_key(GLFW_KEY_S)) controls.brake = 1.0f;
        if (platform.get_key(GLFW_KEY_A)) controls.rot.y = -1.0f;
        if (platform.get_key(GLFW_KEY_D)) controls.rot.y = 1.0f;
        if (platform.get_key(GLFW_KEY_UP)) controls.rot.x = 1.0f, menu_controls.up = true;
        if (platform.get_key(GLFW_KEY_DOWN)) controls.rot.x = -1.0f, menu_controls.down = true;
        if (platform.get_key(GLFW_KEY_LEFT)) controls.rot.z = -1.0f, menu_controls.left = true;
        if (platform.get_key(GLFW_KEY_RIGHT)) controls.rot.z = 1.0f, menu_controls.right = true;

        if (platform.get_key(GLFW_KEY_LEFT_CONTROL)) controls.mgun = true;
        if (platform.get_key(GLFW_KEY_LEFT_SHIFT)) controls.mgun = true;
        if (platform.get_key(GLFW_KEY_SPACE)) controls.missile = true, menu_controls.next = true;
        if (platform.get_key(GLFW_KEY_F)) controls.flares = true;
        if (platform.get_key(GLFW_KEY_Q)) controls.change_weapon = true;
        if (platform.get_key(GLFW_KEY_E)) controls.change_target = true;
        if (platform.get_key(GLFW_KEY_R)) controls.change_radar = true;
        if (platform.get_key(GLFW_KEY_V)) controls.change_camera = true;

        if (platform.was_pressed(GLFW_KEY_ESCAPE)) menu_controls.prev = true;
        if (platform.was_pressed(GLFW_KEY_ENTER)) menu_controls.next = true;

        if (active_game_mode)
        {
            if (((pause && pause != last_pause) || platform.was_pressed(GLFW_KEY_P)) && !is_server && !is_client)
                scene.pause(paused = !paused);
            last_pause = pause;

            bool should_stop = platform.was_pressed(GLFW_KEY_ESCAPE);
            if (is_client && !client.is_up())
                should_stop = true;
            if (is_server && !server.is_up())
                should_stop = true;

            if (should_stop)
            {
                if (paused)
                    scene.pause(paused = !paused);
                active_game_mode->end();
                active_game_mode = 0;
                server.close();
                client.disconnect();
                world.set_network(0);
                sound_world.stop_sounds();
                menu_controls.prev = false;
                if (is_client)
                    menu.send_event("screen=mp_connect");

                sound_world.set_music("BGM_menu");
            }
        }

        speed10x = platform.get_key(GLFW_KEY_RIGHT_SHIFT) && !is_client && !is_server;

        if (controls.change_camera || (reset_camera && !controls.change_target))
        {
            scene.camera.reset_delta_rot();
            reset_camera = false;
        }

        if (!joysticks.empty() && !platform.get_mouse_lbtn() && !controls.change_target)
        {
            scene.camera.reset_delta_rot();
            scene.camera.add_delta_rot(-controls.cam_rot.x * nya_math::constants::pi_2, -controls.cam_rot.y * nya_math::constants::pi);
        }

        if (platform.was_pressed(GLFW_KEY_COMMA))
            debug_variable::set(debug_variable::get() - 1);
        if (platform.was_pressed(GLFW_KEY_PERIOD))
            debug_variable::set(debug_variable::get() + 1);

        if (!active_game_mode) //force limit 60 fps in menu
        {
            int sleep_time = 1000/60 - int(nya_system::get_time() - time);
            if (sleep_time > 0)
                std::this_thread::sleep_for(std::chrono::milliseconds(sleep_time));
        }
    }

    server.close();
    client.disconnect();
    sound::release_context();
    platform.terminate();

    return 0;
}