Untitled

 avatar
unknown
c_cpp
10 days ago
6.0 kB
5
Indexable
#pragma once
#include <Windows.h>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdint>
#include <thread>
#include <chrono>
#include <Xinput.h>
#include <ViGEm/Client.h>

namespace ControllerAim {

    inline PVIGEM_CLIENT vigemClient = nullptr;
    inline PVIGEM_TARGET vigemTarget = nullptr;
    inline XUSB_REPORT controllerReport = { 0 };
    inline bool running = false;

    inline bool Initialize()
    {
        if (vigemClient != nullptr && vigemTarget != nullptr)
            return true;

        vigemClient = vigem_alloc();
        if (vigemClient == nullptr)
        {
            std::cerr << "Failed to allocate ViGEm client." << std::endl;
            return false;
        }

        VIGEM_ERROR ret = vigem_connect(vigemClient);
        if (!VIGEM_SUCCESS(ret))
        {
            std::cerr << "Failed to connect ViGEm client." << std::endl;
            vigem_free(vigemClient);
            vigemClient = nullptr;
            return false;
        }

        vigemTarget = vigem_target_x360_alloc();
        if (vigemTarget == nullptr)
        {
            std::cerr << "Failed to allocate virtual controller." << std::endl;
            vigem_disconnect(vigemClient);
            vigem_free(vigemClient);
            vigemClient = nullptr;
            return false;
        }

        ret = vigem_target_add(vigemClient, vigemTarget);
        if (!VIGEM_SUCCESS(ret))
        {
            std::cerr << "Failed to add virtual controller." << std::endl;
            vigem_target_free(vigemTarget);
            vigem_disconnect(vigemClient);
            vigem_free(vigemClient);
            vigemTarget = nullptr;
            vigemClient = nullptr;
            return false;
        }

        ZeroMemory(&controllerReport, sizeof(XUSB_REPORT));
        running = true;
        return true;
    }

    inline void Cleanup()
    {
        running = false;
        if (vigemClient && vigemTarget)
        {
            vigem_target_remove(vigemClient, vigemTarget);
            vigem_target_free(vigemTarget);
            vigemTarget = nullptr;
            vigem_disconnect(vigemClient);
            vigem_free(vigemClient);
            vigemClient = nullptr;
        }
    }

    inline void RunVirtualController()
    {
        if (!Initialize())
        {
            std::cerr << "Virtual controller initialization failed." << std::endl;
            return;
        }

        std::cout << "Virtual controller is running. Press CTRL+C to exit." << std::endl;
        XINPUT_STATE state;

        while (running)
        {
            ZeroMemory(&state, sizeof(XINPUT_STATE));
            DWORD dwResult = XInputGetState(0, &state);
            if (dwResult == ERROR_SUCCESS)
            {
                const XINPUT_GAMEPAD& gamepad = state.Gamepad;
                controllerReport.wButtons = gamepad.wButtons;
                controllerReport.bLeftTrigger = gamepad.bLeftTrigger;
                controllerReport.bRightTrigger = gamepad.bRightTrigger;
                controllerReport.sThumbLX = gamepad.sThumbLX;
                controllerReport.sThumbLY = gamepad.sThumbLY;
            }
            else
            {
                controllerReport.wButtons = 0;
                controllerReport.bLeftTrigger = 0;
                controllerReport.bRightTrigger = 0;
                controllerReport.sThumbLX = 0;
                controllerReport.sThumbLY = 0;
            }

            VIGEM_ERROR ret = vigem_target_x360_update(vigemClient, vigemTarget, controllerReport);
            if (!VIGEM_SUCCESS(ret))
                std::cerr << "Failed to update virtual controller." << std::endl;

            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }

        Cleanup();
    }

    /*inline void ControllerMoveRightStick(float tarx, float tary, float screenX, float screenY, int smooth)
    {
        if (!running)
        {
            if (!Initialize())
            {
                std::cerr << "Virtual controller initialization failed in ControllerMoveRightStick." << std::endl;
                return;
            }
        }

        float ScreenCenterX = screenX / 2.0f;
        float ScreenCenterY = screenY / 2.0f;
        float offsetX = 0.0f;
        float offsetY = 0.0f;

        if (tarx != 0.0f)
        {
            offsetX = (tarx > ScreenCenterX) ? -(ScreenCenterX - tarx) : tarx - ScreenCenterX;
            offsetX /= smooth;
        }

        if (tary != 0.0f)
        {
            offsetY = (tary > ScreenCenterY) ? -(ScreenCenterY - tary) : tary - ScreenCenterY;
            offsetY /= smooth;
        }

        short newRX = static_cast<short>(std::clamp(offsetX, -32768.0f, 32767.0f));
        short newRY = static_cast<short>(std::clamp(offsetY, -32768.0f, 32767.0f));

        controllerReport.sThumbRX = newRX;
        controllerReport.sThumbRY = newRY;

        VIGEM_ERROR ret = vigem_target_x360_update(vigemClient, vigemTarget, controllerReport);
        if (!VIGEM_SUCCESS(ret))
            std::cerr << "Failed to update virtual controller right stick." << std::endl;
    }*/

    inline void ControllerMoveRightStick(float tarx, float tary, float /*screenX*/, float /*screenY*/, int /*smooth*/)
    {
        const float conversionFactor = 32767.0f / 127.0f;

        short newRX = static_cast<short>(tarx * conversionFactor);
        short newRY = static_cast<short>(tary * conversionFactor);

        controllerReport.sThumbRX = newRX;
        controllerReport.sThumbRY = newRY;

        VIGEM_ERROR ret = vigem_target_x360_update(vigemClient, vigemTarget, controllerReport);
        if (!VIGEM_SUCCESS(ret))
            std::cerr << "Failed to update virtual controller right stick." << std::endl;
    }

    inline std::thread LaunchVirtualController()
    {
        return std::thread(RunVirtualController);
    }

}
Editor is loading...
Leave a Comment