mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-02 06:40:42 -07:00
Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 610984f40e | |||
| 1e271b7352 | |||
| 07c78caf01 | |||
| d153209d8a | |||
| 48186245fe | |||
| f7c274591a | |||
| d1a20e58b6 | |||
| 1e02c31524 | |||
| 66fab48a5b | |||
| ae06652148 | |||
| bd6c8d3f3c | |||
| e88abec2a6 | |||
| 6de8b529d2 | |||
| 7301cdaa6c | |||
| 6969dfcdd1 | |||
| edaf5a386f | |||
| 302f08dd57 | |||
| 68f5a614ef | |||
| 5db43031f2 | |||
| 873ade757a |
@@ -0,0 +1,27 @@
|
||||
on: [push, pull_request]
|
||||
name: Continuous Integration
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
fw-ci:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./src/spice2x
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Calculate commit SHA
|
||||
id: vars
|
||||
run: |
|
||||
calculatedSha=$(git rev-parse --short ${{ github.sha }})
|
||||
echo "COMMIT_SHORT_SHA=$calculatedSha" >> $GITHUB_ENV
|
||||
- name: Compile
|
||||
run: ./build_docker.sh
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: spice2x-ci-${{ env.COMMIT_SHORT_SHA }}
|
||||
path: src/spice2x/bin
|
||||
if-no-files-found: error
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
.vscode/*
|
||||
|
||||
# JetBrains IDEs
|
||||
.idea
|
||||
.idea_modules
|
||||
*.iws
|
||||
|
||||
# CMake
|
||||
cmake-build*
|
||||
|
||||
# user config
|
||||
build_all.local.sh
|
||||
build_docker.local.sh
|
||||
@@ -211,14 +211,12 @@ add_compile_definitions(
|
||||
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DACIOEMU_LOG")
|
||||
|
||||
# add project directory to include path so we can comfortably import
|
||||
include_directories(${spicetools_SOURCE_DIR})
|
||||
include_directories(${spicetools_SOURCE_DIR} ${spicetools_SOURCE_DIR}/external/imgui)
|
||||
|
||||
# add external libraries
|
||||
add_subdirectory(external/fmt EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(external/discord-rpc EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(external/hash-library EXCLUDE_FROM_ALL)
|
||||
add_compile_definitions(IMGUI_DISABLE_DEMO_WINDOWS)
|
||||
add_compile_definitions(IMGUI_DISABLE_DEBUG_TOOLS)
|
||||
add_subdirectory(external/imgui EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(external/minhook EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(external/cpu_features EXCLUDE_FROM_ALL)
|
||||
@@ -516,7 +514,6 @@ set(SOURCE_FILES ${SOURCE_FILES}
|
||||
overlay/overlay.cpp
|
||||
overlay/window.cpp
|
||||
overlay/imgui/extensions.cpp
|
||||
overlay/imgui/impl_dx9.cpp
|
||||
overlay/imgui/impl_spice.cpp
|
||||
overlay/imgui/impl_sw.cpp
|
||||
overlay/windows/acio_status_buffers.cpp
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
FROM spicetools/deps
|
||||
WORKDIR /src
|
||||
RUN chown user:user /src
|
||||
USER user
|
||||
COPY --chown=user:user --from=gitroot . /src/.git
|
||||
COPY --chown=user:user . /src/src/spice2x
|
||||
|
||||
COPY --from=gitroot . /src/.git
|
||||
COPY . /src/src/spice2x
|
||||
WORKDIR /src/src/spice2x
|
||||
CMD ["./build_all.sh"]
|
||||
|
||||
@@ -33,6 +33,11 @@ static int __cdecl ac_io_bmpu_control_1p_start_led_off() {
|
||||
if (avs::game::is_model("KDM")) {
|
||||
auto &lights = games::dea::get_lights();
|
||||
Lights::writeLight(RI_MGR, lights.at(games::dea::Lights::P1Start), 0.f);
|
||||
|
||||
// MUSECA
|
||||
} else if (avs::game::is_model("PIX")) {
|
||||
auto &lights = games::museca::get_lights();
|
||||
Lights::writeLight(RI_MGR, lights.at(games::museca::Lights::Start), 0.f);
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -44,6 +49,11 @@ static int __cdecl ac_io_bmpu_control_1p_start_led_on() {
|
||||
if (avs::game::is_model("KDM")) {
|
||||
auto &lights = games::dea::get_lights();
|
||||
Lights::writeLight(RI_MGR, lights.at(games::dea::Lights::P1Start), 1.f);
|
||||
|
||||
// MUSECA
|
||||
} else if (avs::game::is_model("PIX")) {
|
||||
auto &lights = games::museca::get_lights();
|
||||
Lights::writeLight(RI_MGR, lights.at(games::museca::Lights::Start), 1.f);
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -55,6 +65,11 @@ static int __cdecl ac_io_bmpu_control_2p_start_led_off() {
|
||||
if (avs::game::is_model("KDM")) {
|
||||
auto &lights = games::dea::get_lights();
|
||||
Lights::writeLight(RI_MGR, lights.at(games::dea::Lights::P2Start), 0.f);
|
||||
|
||||
// MUSECA
|
||||
} else if (avs::game::is_model("PIX")) {
|
||||
auto &lights = games::museca::get_lights();
|
||||
Lights::writeLight(RI_MGR, lights.at(games::museca::Lights::Keypad), 0.f);
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -66,6 +81,11 @@ static int __cdecl ac_io_bmpu_control_2p_start_led_on() {
|
||||
if (avs::game::is_model("KDM")) {
|
||||
auto &lights = games::dea::get_lights();
|
||||
Lights::writeLight(RI_MGR, lights.at(games::dea::Lights::P2Start), 1.f);
|
||||
|
||||
// MUSECA
|
||||
} else if (avs::game::is_model("PIX")) {
|
||||
auto &lights = games::museca::get_lights();
|
||||
Lights::writeLight(RI_MGR, lights.at(games::museca::Lights::Keypad), 1.f);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
Regular → Executable
+29
-27
@@ -57,7 +57,7 @@ then
|
||||
fi
|
||||
|
||||
# determine number of cores
|
||||
CORES=$(awk '/^processor\t/ {cores[$NF]++} END {print length(cores)}' /proc/cpuinfo)
|
||||
CORES=$(nproc)
|
||||
|
||||
# print information
|
||||
echo ""
|
||||
@@ -74,34 +74,36 @@ echo "Build Type: $BUILD_TYPE"
|
||||
echo "Cores: $CORES"
|
||||
echo ""
|
||||
|
||||
# 32 bit
|
||||
echo "Building 32bit targets..."
|
||||
echo "========================="
|
||||
if ((CLEAN_BUILD > 0))
|
||||
then
|
||||
rm -rf ${BUILDDIR_32}
|
||||
fi
|
||||
mkdir -p ${BUILDDIR_32}
|
||||
pushd ${BUILDDIR_32} > /dev/null
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_32} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} $OLDPWD && make -j ${CORES} ${TARGETS_32}
|
||||
popd > /dev/null
|
||||
time (
|
||||
# 32 bit
|
||||
echo "Building 32bit targets..."
|
||||
echo "========================="
|
||||
if ((CLEAN_BUILD > 0))
|
||||
then
|
||||
rm -rf ${BUILDDIR_32}
|
||||
fi
|
||||
mkdir -p ${BUILDDIR_32}
|
||||
pushd ${BUILDDIR_32} > /dev/null
|
||||
cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_32} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} $OLDPWD && ninja ${TARGETS_32}
|
||||
popd > /dev/null
|
||||
|
||||
# 64 bit
|
||||
echo ""
|
||||
echo "Building 64bit targets..."
|
||||
echo "========================="
|
||||
if ((CLEAN_BUILD > 0))
|
||||
then
|
||||
rm -rf ${BUILDDIR_64}
|
||||
fi
|
||||
mkdir -p ${BUILDDIR_64}
|
||||
pushd ${BUILDDIR_64} > /dev/null
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_64} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} $OLDPWD && make -j ${CORES} ${TARGETS_64}
|
||||
popd > /dev/null
|
||||
# 64 bit
|
||||
echo ""
|
||||
echo "Building 64bit targets..."
|
||||
echo "========================="
|
||||
if ((CLEAN_BUILD > 0))
|
||||
then
|
||||
rm -rf ${BUILDDIR_64}
|
||||
fi
|
||||
mkdir -p ${BUILDDIR_64}
|
||||
pushd ${BUILDDIR_64} > /dev/null
|
||||
cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_64} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} $OLDPWD && ninja ${TARGETS_64}
|
||||
popd > /dev/null
|
||||
|
||||
echo ""
|
||||
echo "Compilation process done :)"
|
||||
echo "==========================="
|
||||
echo ""
|
||||
echo "Compilation process done :)"
|
||||
echo "==========================="
|
||||
)
|
||||
|
||||
# generate PDBs
|
||||
if false # ((DEBUG > 0))
|
||||
|
||||
Regular → Executable
+1
-3
@@ -1,6 +1,4 @@
|
||||
#!/bin/bash
|
||||
export DOCKER_BUILDKIT=0
|
||||
|
||||
docker build --pull $PWD/external/docker -t spicetools/deps --platform linux/x86_64
|
||||
docker build --build-context gitroot=$PWD/../../.git . -t spicetools/spice:latest --no-cache
|
||||
docker run --rm -it -v $PWD/dist:/src/src/spice2x/dist -v $PWD/bin:/src/src/spice2x/bin spicetools/spice
|
||||
docker run --rm -v $PWD/dist:/src/src/spice2x/dist -v $PWD/bin:/src/src/spice2x/bin spicetools/spice
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
04/08/2025 [spice2x]
|
||||
Ensure rawinput touch is default for all games (-wintouch to override)
|
||||
Various overlay UI fixes and improvements, update ImGui library
|
||||
Add missing lights in Museca
|
||||
|
||||
03/29/2025 [spice2x]
|
||||
Add SDVX landscape mode, -forceresswap option
|
||||
Fix bugs in image scaler
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required (VERSION 3.2.0)
|
||||
cmake_minimum_required (VERSION 3.12)
|
||||
project (DiscordRPC)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
+4
-13
@@ -1,20 +1,11 @@
|
||||
FROM archlinux:base
|
||||
FROM ghcr.io/archlinux/archlinux:base-devel
|
||||
|
||||
RUN pacman --noconfirm -Syu gettext \
|
||||
base-devel \
|
||||
git \
|
||||
RUN pacman --noconfirm -Syu git \
|
||||
bash \
|
||||
zip \
|
||||
upx \
|
||||
sudo \
|
||||
binutils \
|
||||
file \
|
||||
make \
|
||||
gcc \
|
||||
fakeroot \
|
||||
diffutils \
|
||||
ninja \
|
||||
cmake \
|
||||
awk \
|
||||
unzip \
|
||||
mingw-w64-crt \
|
||||
mingw-w64-winpthreads \
|
||||
@@ -22,4 +13,4 @@ RUN pacman --noconfirm -Syu gettext \
|
||||
mingw-w64-headers \
|
||||
mingw-w64-binutils
|
||||
RUN useradd user -m && echo "ALL ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
|
||||
RUN su user -c "cd /tmp/ && git clone https://aur.archlinux.org/yay.git --depth=1 && cd yay && makepkg --noconfirm -si && yay --noconfirm -S mingw-w64-cmake"
|
||||
RUN su user -c "cd /tmp/ && git clone https://aur.archlinux.org/yay-bin.git --depth=1 && cd yay-bin && makepkg --noconfirm -si && yay --noconfirm -S mingw-w64-cmake"
|
||||
|
||||
+5
-3
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.9)
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
project(imgui CXX)
|
||||
|
||||
# dear imgui uses the C++ virtual interfaces for DirectX
|
||||
@@ -8,7 +8,8 @@ set(IMGUI_HEADERS
|
||||
imconfig.h
|
||||
imgui.h
|
||||
imgui_internal.h
|
||||
imgui_stdlib.h
|
||||
backends/imgui_impl_dx9.h
|
||||
misc/cpp/imgui_stdlib.h
|
||||
)
|
||||
set(IMGUI_SOURCES
|
||||
imgui.cpp
|
||||
@@ -16,7 +17,8 @@ set(IMGUI_SOURCES
|
||||
imgui_tables.cpp
|
||||
imgui_widgets.cpp
|
||||
imgui_demo.cpp
|
||||
imgui_stdlib.cpp
|
||||
backends/imgui_impl_dx9.cpp
|
||||
misc/cpp/imgui_stdlib.cpp
|
||||
)
|
||||
|
||||
add_library(imgui STATIC ${IMGUI_HEADERS} ${IMGUI_SOURCES})
|
||||
|
||||
Vendored
+3
-3
@@ -22,14 +22,14 @@
|
||||
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX9_RenderDrawData() in the .h file so you can call it yourself.
|
||||
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
||||
|
||||
#include "impl_dx9.h"
|
||||
#include "imgui_impl_dx9.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
// DirectX
|
||||
#include <d3d9.h>
|
||||
|
||||
#include "external/imgui/imgui.h"
|
||||
#include "imgui.h"
|
||||
|
||||
// allow std::min use
|
||||
#ifdef min
|
||||
@@ -327,7 +327,7 @@ void ImGui_ImplDX9_InvalidateDeviceObjects() {
|
||||
if (g_FontTexture) {
|
||||
g_FontTexture->Release();
|
||||
g_FontTexture = NULL;
|
||||
ImGui::GetIO().Fonts->TexID = NULL;
|
||||
ImGui::GetIO().Fonts->TexID = 0;
|
||||
} // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -11,7 +11,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "external/imgui/imgui.h"
|
||||
#include "imgui.h"
|
||||
|
||||
struct IDirect3DDevice9;
|
||||
|
||||
+33
-16
@@ -1,5 +1,5 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// COMPILE-TIME OPTIONS FOR DEAR IMGUI
|
||||
// DEAR IMGUI COMPILE-TIME OPTIONS
|
||||
// Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure.
|
||||
// You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions.
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -9,7 +9,7 @@
|
||||
// You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp
|
||||
// files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures.
|
||||
// Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts.
|
||||
// Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using.
|
||||
// Call IMGUI_CHECKVERSION() from your .cpp file to verify that the data structures your files are using are matching the ones imgui.cpp is using.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
@@ -21,27 +21,29 @@
|
||||
|
||||
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
|
||||
// Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
|
||||
// DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
|
||||
// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
|
||||
//#define IMGUI_API __declspec( dllexport )
|
||||
//#define IMGUI_API __declspec( dllimport )
|
||||
// - Windows DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
|
||||
// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
|
||||
//#define IMGUI_API __declspec(dllexport) // MSVC Windows: DLL export
|
||||
//#define IMGUI_API __declspec(dllimport) // MSVC Windows: DLL import
|
||||
//#define IMGUI_API __attribute__((visibility("default"))) // GCC/Clang: override visibility when set is hidden
|
||||
|
||||
//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names.
|
||||
//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to clean your code of obsolete function/names.
|
||||
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
//#define IMGUI_DISABLE_OBSOLETE_KEYIO // 1.87: disable legacy io.KeyMap[]+io.KeysDown[] in favor io.AddKeyEvent(). This will be folded into IMGUI_DISABLE_OBSOLETE_FUNCTIONS in a few versions.
|
||||
//#define IMGUI_DISABLE_OBSOLETE_KEYIO // 1.87+ disable legacy io.KeyMap[]+io.KeysDown[] in favor io.AddKeyEvent(). This is automatically done by IMGUI_DISABLE_OBSOLETE_FUNCTIONS.
|
||||
|
||||
//---- Disable all of Dear ImGui or don't implement standard windows/tools.
|
||||
// It is very strongly recommended to NOT disable the demo windows and debug tool during development. They are extremely useful in day to day work. Please read comments in imgui_demo.cpp.
|
||||
//#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty.
|
||||
//#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty.
|
||||
//#define IMGUI_DISABLE_DEBUG_TOOLS // Disable metrics/debugger and other debug tools: ShowMetricsWindow(), ShowDebugLogWindow() and ShowStackToolWindow() will be empty (this was called IMGUI_DISABLE_METRICS_WINDOW before 1.88).
|
||||
#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty.
|
||||
//#define IMGUI_DISABLE_DEBUG_TOOLS // Disable metrics/debugger and other debug tools: ShowMetricsWindow(), ShowDebugLogWindow() and ShowIDStackToolWindow() will be empty.
|
||||
|
||||
//---- Don't implement some functions to reduce linkage requirements.
|
||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a)
|
||||
#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW)
|
||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a)
|
||||
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime).
|
||||
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, IME).
|
||||
//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
|
||||
//#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS // Don't implement default platform_io.Platform_OpenInShellFn() handler (Win32: ShellExecute(), require shell32.lib/.a, Mac/Linux: use system("")).
|
||||
//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
|
||||
//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
|
||||
//#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
|
||||
@@ -49,8 +51,13 @@
|
||||
#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
|
||||
//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available
|
||||
|
||||
//---- Enable Test Engine / Automation features.
|
||||
//#define IMGUI_ENABLE_TEST_ENGINE // Enable imgui_test_engine hooks. Generally set automatically by include "imgui_te_config.h", see Test Engine for details.
|
||||
|
||||
//---- Include imgui_user.h at the end of imgui.h as a convenience
|
||||
// May be convenient for some users to only explicitly include vanilla imgui.h and have extra stuff included.
|
||||
//#define IMGUI_INCLUDE_IMGUI_USER_H
|
||||
//#define IMGUI_USER_H_FILENAME "my_folder/my_imgui_user.h"
|
||||
|
||||
//---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another)
|
||||
#define IMGUI_USE_BGRA_PACKED_COLOR
|
||||
@@ -58,16 +65,17 @@
|
||||
//---- Performance optimization for DX9
|
||||
#define IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT struct ImDrawVert { ImVec2 pos; float z; ImU32 col; ImVec2 uv; }
|
||||
|
||||
//---- Use 32-bit for ImWchar (default is 16-bit) to support unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
|
||||
//---- Use 32-bit for ImWchar (default is 16-bit) to support Unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
|
||||
//#define IMGUI_USE_WCHAR32
|
||||
|
||||
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
|
||||
// By default the embedded implementations are declared static and not available outside of Dear ImGui sources files.
|
||||
//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
|
||||
//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
|
||||
//#define IMGUI_STB_SPRINTF_FILENAME "my_folder/stb_sprintf.h" // only used if enabled
|
||||
//#define IMGUI_STB_SPRINTF_FILENAME "my_folder/stb_sprintf.h" // only used if IMGUI_USE_STB_SPRINTF is defined.
|
||||
//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
|
||||
//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
|
||||
//#define IMGUI_DISABLE_STB_SPRINTF_IMPLEMENTATION // only disabled if IMGUI_USE_STB_SPRINTF is defined.
|
||||
|
||||
//---- Use stb_sprintf.h for a faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined)
|
||||
// Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by stb_sprintf.h.
|
||||
@@ -78,6 +86,15 @@
|
||||
// On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'.
|
||||
//#define IMGUI_ENABLE_FREETYPE
|
||||
|
||||
//---- Use FreeType + plutosvg or lunasvg to render OpenType SVG fonts (SVGinOT)
|
||||
// Only works in combination with IMGUI_ENABLE_FREETYPE.
|
||||
// - lunasvg is currently easier to acquire/install, as e.g. it is part of vcpkg.
|
||||
// - plutosvg will support more fonts and may load them faster. It currently requires to be built manually but it is fairly easy. See misc/freetype/README for instructions.
|
||||
// - Both require headers to be available in the include path + program to be linked with the library code (not provided).
|
||||
// - (note: lunasvg implementation is based on Freetype's rsvg-port.c which is licensed under CeCILL-C Free Software License Agreement)
|
||||
//#define IMGUI_ENABLE_FREETYPE_PLUTOSVG
|
||||
//#define IMGUI_ENABLE_FREETYPE_LUNASVG
|
||||
|
||||
//---- Use stb_truetype to build and rasterize the font atlas (default)
|
||||
// The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend.
|
||||
//#define IMGUI_ENABLE_STB_TRUETYPE
|
||||
@@ -108,7 +125,7 @@
|
||||
//typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data);
|
||||
//#define ImDrawCallback MyImDrawCallback
|
||||
|
||||
//---- Debug Tools: Macro to break in Debugger
|
||||
//---- Debug Tools: Macro to break in Debugger (we provide a default implementation of this in the codebase)
|
||||
// (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.)
|
||||
//#define IM_DEBUG_BREAK IM_ASSERT(0)
|
||||
//#define IM_DEBUG_BREAK __debugbreak()
|
||||
@@ -116,10 +133,10 @@
|
||||
//---- Debug Tools: Enable slower asserts
|
||||
//#define IMGUI_DEBUG_PARANOID
|
||||
|
||||
//---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files.
|
||||
//---- Tip: You can add extra functions within the ImGui:: namespace from anywhere (e.g. your own sources/header files)
|
||||
/*
|
||||
namespace ImGui
|
||||
{
|
||||
void MyFunction(const char* name, const MyMatrix44& v);
|
||||
void MyFunction(const char* name, MyMatrix44* mtx);
|
||||
}
|
||||
*/
|
||||
|
||||
Vendored
+4651
-2301
File diff suppressed because it is too large
Load Diff
Vendored
+1497
-902
File diff suppressed because it is too large
Load Diff
+3015
-663
File diff suppressed because it is too large
Load Diff
+621
-129
File diff suppressed because it is too large
Load Diff
+938
-658
File diff suppressed because it is too large
Load Diff
+584
-235
File diff suppressed because it is too large
Load Diff
+2536
-870
File diff suppressed because it is too large
Load Diff
+139
-107
@@ -2,8 +2,11 @@
|
||||
// This is a slightly modified version of stb_textedit.h 1.14.
|
||||
// Those changes would need to be pushed into nothings/stb:
|
||||
// - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321)
|
||||
// - Fix in stb_textedit_find_charpos to handle last line (see https://github.com/ocornut/imgui/issues/6000)
|
||||
// - Fix in stb_textedit_find_charpos to handle last line (see https://github.com/ocornut/imgui/issues/6000 + #6783)
|
||||
// - Added name to struct or it may be forward declared in our code.
|
||||
// - Added UTF-8 support (see https://github.com/nothings/stb/issues/188 + https://github.com/ocornut/imgui/pull/7925)
|
||||
// Grep for [DEAR IMGUI] to find the changes.
|
||||
// - Also renamed macros used or defined outside of IMSTB_TEXTEDIT_IMPLEMENTATION block from STB_TEXTEDIT_* to IMSTB_TEXTEDIT_*
|
||||
|
||||
// stb_textedit.h - v1.14 - public domain - Sean Barrett
|
||||
// Development of this library was sponsored by RAD Game Tools
|
||||
@@ -30,7 +33,7 @@
|
||||
// DEPENDENCIES
|
||||
//
|
||||
// Uses the C runtime function 'memmove', which you can override
|
||||
// by defining STB_TEXTEDIT_memmove before the implementation.
|
||||
// by defining IMSTB_TEXTEDIT_memmove before the implementation.
|
||||
// Uses no other functions. Performs no runtime allocations.
|
||||
//
|
||||
//
|
||||
@@ -40,7 +43,7 @@
|
||||
// 1.13 (2019-02-07) fix bug in undo size management
|
||||
// 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash
|
||||
// 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield
|
||||
// 1.10 (2016-10-25) supress warnings about casting away const with -Wcast-qual
|
||||
// 1.10 (2016-10-25) suppress warnings about casting away const with -Wcast-qual
|
||||
// 1.9 (2016-08-27) customizable move-by-word
|
||||
// 1.8 (2016-04-02) better keyboard handling when mouse button is down
|
||||
// 1.7 (2015-09-13) change y range handling in case baseline is non-0
|
||||
@@ -208,6 +211,7 @@
|
||||
// int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||
// int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len)
|
||||
// void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXEDIT_KEYTYPE key)
|
||||
// void stb_textedit_text(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int text_len)
|
||||
//
|
||||
// Each of these functions potentially updates the string and updates the
|
||||
// state.
|
||||
@@ -242,7 +246,12 @@
|
||||
// various definitions like STB_TEXTEDIT_K_LEFT have the is-key-event bit
|
||||
// set, and make STB_TEXTEDIT_KEYTOCHAR check that the is-key-event bit is
|
||||
// clear. STB_TEXTEDIT_KEYTYPE defaults to int, but you can #define it to
|
||||
// anything other type you wante before including.
|
||||
// anything other type you want before including.
|
||||
// if the STB_TEXTEDIT_KEYTOTEXT function is defined, selected keys are
|
||||
// transformed into text and stb_textedit_text() is automatically called.
|
||||
//
|
||||
// text: [DEAR IMGUI] added 2024-09
|
||||
// call this to text inputs sent to the textfield.
|
||||
//
|
||||
//
|
||||
// When rendering, you can read the cursor position and selection state from
|
||||
@@ -274,8 +283,8 @@
|
||||
////
|
||||
////
|
||||
|
||||
#ifndef INCLUDE_STB_TEXTEDIT_H
|
||||
#define INCLUDE_STB_TEXTEDIT_H
|
||||
#ifndef INCLUDE_IMSTB_TEXTEDIT_H
|
||||
#define INCLUDE_IMSTB_TEXTEDIT_H
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@@ -286,38 +295,38 @@
|
||||
// and undo state.
|
||||
//
|
||||
|
||||
#ifndef STB_TEXTEDIT_UNDOSTATECOUNT
|
||||
#define STB_TEXTEDIT_UNDOSTATECOUNT 99
|
||||
#ifndef IMSTB_TEXTEDIT_UNDOSTATECOUNT
|
||||
#define IMSTB_TEXTEDIT_UNDOSTATECOUNT 99
|
||||
#endif
|
||||
#ifndef STB_TEXTEDIT_UNDOCHARCOUNT
|
||||
#define STB_TEXTEDIT_UNDOCHARCOUNT 999
|
||||
#ifndef IMSTB_TEXTEDIT_UNDOCHARCOUNT
|
||||
#define IMSTB_TEXTEDIT_UNDOCHARCOUNT 999
|
||||
#endif
|
||||
#ifndef STB_TEXTEDIT_CHARTYPE
|
||||
#define STB_TEXTEDIT_CHARTYPE int
|
||||
#ifndef IMSTB_TEXTEDIT_CHARTYPE
|
||||
#define IMSTB_TEXTEDIT_CHARTYPE int
|
||||
#endif
|
||||
#ifndef STB_TEXTEDIT_POSITIONTYPE
|
||||
#define STB_TEXTEDIT_POSITIONTYPE int
|
||||
#ifndef IMSTB_TEXTEDIT_POSITIONTYPE
|
||||
#define IMSTB_TEXTEDIT_POSITIONTYPE int
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// private data
|
||||
STB_TEXTEDIT_POSITIONTYPE where;
|
||||
STB_TEXTEDIT_POSITIONTYPE insert_length;
|
||||
STB_TEXTEDIT_POSITIONTYPE delete_length;
|
||||
IMSTB_TEXTEDIT_POSITIONTYPE where;
|
||||
IMSTB_TEXTEDIT_POSITIONTYPE insert_length;
|
||||
IMSTB_TEXTEDIT_POSITIONTYPE delete_length;
|
||||
int char_storage;
|
||||
} StbUndoRecord;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// private data
|
||||
StbUndoRecord undo_rec [STB_TEXTEDIT_UNDOSTATECOUNT];
|
||||
STB_TEXTEDIT_CHARTYPE undo_char[STB_TEXTEDIT_UNDOCHARCOUNT];
|
||||
StbUndoRecord undo_rec [IMSTB_TEXTEDIT_UNDOSTATECOUNT];
|
||||
IMSTB_TEXTEDIT_CHARTYPE undo_char[IMSTB_TEXTEDIT_UNDOCHARCOUNT];
|
||||
short undo_point, redo_point;
|
||||
int undo_char_point, redo_char_point;
|
||||
} StbUndoState;
|
||||
|
||||
typedef struct
|
||||
typedef struct STB_TexteditState
|
||||
{
|
||||
/////////////////////
|
||||
//
|
||||
@@ -371,7 +380,7 @@ typedef struct
|
||||
float ymin,ymax; // height of row above and below baseline
|
||||
int num_chars;
|
||||
} StbTexteditRow;
|
||||
#endif //INCLUDE_STB_TEXTEDIT_H
|
||||
#endif //INCLUDE_IMSTB_TEXTEDIT_H
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
@@ -384,11 +393,11 @@ typedef struct
|
||||
|
||||
// implementation isn't include-guarded, since it might have indirectly
|
||||
// included just the "header" portion
|
||||
#ifdef STB_TEXTEDIT_IMPLEMENTATION
|
||||
#ifdef IMSTB_TEXTEDIT_IMPLEMENTATION
|
||||
|
||||
#ifndef STB_TEXTEDIT_memmove
|
||||
#ifndef IMSTB_TEXTEDIT_memmove
|
||||
#include <string.h>
|
||||
#define STB_TEXTEDIT_memmove memmove
|
||||
#define IMSTB_TEXTEDIT_memmove memmove
|
||||
#endif
|
||||
|
||||
|
||||
@@ -398,7 +407,7 @@ typedef struct
|
||||
//
|
||||
|
||||
// traverse the layout to locate the nearest character to a display position
|
||||
static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y)
|
||||
static int stb_text_locate_coord(IMSTB_TEXTEDIT_STRING *str, float x, float y)
|
||||
{
|
||||
StbTexteditRow r;
|
||||
int n = STB_TEXTEDIT_STRINGLEN(str);
|
||||
@@ -437,13 +446,13 @@ static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y)
|
||||
if (x < r.x1) {
|
||||
// search characters in row for one that straddles 'x'
|
||||
prev_x = r.x0;
|
||||
for (k=0; k < r.num_chars; ++k) {
|
||||
for (k=0; k < r.num_chars; k = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, i + k) - i) {
|
||||
float w = STB_TEXTEDIT_GETWIDTH(str, i, k);
|
||||
if (x < prev_x+w) {
|
||||
if (x < prev_x+w/2)
|
||||
return k+i;
|
||||
else
|
||||
return k+i+1;
|
||||
return IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, i + k);
|
||||
}
|
||||
prev_x += w;
|
||||
}
|
||||
@@ -458,7 +467,7 @@ static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y)
|
||||
}
|
||||
|
||||
// API click: on mouse down, move the cursor to the clicked location, and reset the selection
|
||||
static void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
|
||||
static void stb_textedit_click(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
|
||||
{
|
||||
// In single-line mode, just always make y = 0. This lets the drag keep working if the mouse
|
||||
// goes off the top or bottom of the text
|
||||
@@ -476,7 +485,7 @@ static void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *stat
|
||||
}
|
||||
|
||||
// API drag: on mouse drag, move the cursor and selection endpoint to the clicked location
|
||||
static void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
|
||||
static void stb_textedit_drag(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
|
||||
{
|
||||
int p = 0;
|
||||
|
||||
@@ -502,11 +511,11 @@ static void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state
|
||||
//
|
||||
|
||||
// forward declarations
|
||||
static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state);
|
||||
static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state);
|
||||
static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length);
|
||||
static void stb_text_undo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state);
|
||||
static void stb_text_redo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state);
|
||||
static void stb_text_makeundo_delete(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length);
|
||||
static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length);
|
||||
static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length);
|
||||
static void stb_text_makeundo_replace(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -518,7 +527,7 @@ typedef struct
|
||||
|
||||
// find the x/y location of a character, and remember info about the previous row in
|
||||
// case we get a move-up event (for page up, we'll have to rescan)
|
||||
static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *str, int n, int single_line)
|
||||
static void stb_textedit_find_charpos(StbFindState *find, IMSTB_TEXTEDIT_STRING *str, int n, int single_line)
|
||||
{
|
||||
StbTexteditRow r;
|
||||
int prev_start = 0;
|
||||
@@ -549,7 +558,10 @@ static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *s
|
||||
i += r.num_chars;
|
||||
find->y += r.baseline_y_delta;
|
||||
if (i == z) // [DEAR IMGUI]
|
||||
{
|
||||
r.num_chars = 0; // [DEAR IMGUI]
|
||||
break; // [DEAR IMGUI]
|
||||
}
|
||||
}
|
||||
|
||||
find->first_char = first = i;
|
||||
@@ -559,14 +571,14 @@ static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *s
|
||||
|
||||
// now scan to find xpos
|
||||
find->x = r.x0;
|
||||
for (i=0; first+i < n; ++i)
|
||||
for (i=0; first+i < n; i = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, first + i) - first)
|
||||
find->x += STB_TEXTEDIT_GETWIDTH(str, first, i);
|
||||
}
|
||||
|
||||
#define STB_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end)
|
||||
|
||||
// make the selection/cursor state valid if client altered the string
|
||||
static void stb_textedit_clamp(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||
static void stb_textedit_clamp(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||
{
|
||||
int n = STB_TEXTEDIT_STRINGLEN(str);
|
||||
if (STB_TEXT_HAS_SELECTION(state)) {
|
||||
@@ -580,7 +592,7 @@ static void stb_textedit_clamp(STB_TEXTEDIT_STRING *str, STB_TexteditState *stat
|
||||
}
|
||||
|
||||
// delete characters while updating undo
|
||||
static void stb_textedit_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int len)
|
||||
static void stb_textedit_delete(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int len)
|
||||
{
|
||||
stb_text_makeundo_delete(str, state, where, len);
|
||||
STB_TEXTEDIT_DELETECHARS(str, where, len);
|
||||
@@ -588,7 +600,7 @@ static void stb_textedit_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *sta
|
||||
}
|
||||
|
||||
// delete the section
|
||||
static void stb_textedit_delete_selection(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||
static void stb_textedit_delete_selection(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||
{
|
||||
stb_textedit_clamp(str, state);
|
||||
if (STB_TEXT_HAS_SELECTION(state)) {
|
||||
@@ -625,7 +637,7 @@ static void stb_textedit_move_to_first(STB_TexteditState *state)
|
||||
}
|
||||
|
||||
// move cursor to last character of selection
|
||||
static void stb_textedit_move_to_last(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||
static void stb_textedit_move_to_last(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||
{
|
||||
if (STB_TEXT_HAS_SELECTION(state)) {
|
||||
stb_textedit_sortselection(state);
|
||||
@@ -636,14 +648,25 @@ static void stb_textedit_move_to_last(STB_TEXTEDIT_STRING *str, STB_TexteditStat
|
||||
}
|
||||
}
|
||||
|
||||
// [DEAR IMGUI]
|
||||
// Functions must be implemented for UTF8 support
|
||||
// Code in this file that uses those functions is modified for [DEAR IMGUI] and deviates from the original stb_textedit.
|
||||
// There is not necessarily a '[DEAR IMGUI]' at the usage sites.
|
||||
#ifndef IMSTB_TEXTEDIT_GETPREVCHARINDEX
|
||||
#define IMSTB_TEXTEDIT_GETPREVCHARINDEX(obj, idx) (idx - 1)
|
||||
#endif
|
||||
#ifndef IMSTB_TEXTEDIT_GETNEXTCHARINDEX
|
||||
#define IMSTB_TEXTEDIT_GETNEXTCHARINDEX(obj, idx) (idx + 1)
|
||||
#endif
|
||||
|
||||
#ifdef STB_TEXTEDIT_IS_SPACE
|
||||
static int is_word_boundary( STB_TEXTEDIT_STRING *str, int idx )
|
||||
static int is_word_boundary( IMSTB_TEXTEDIT_STRING *str, int idx )
|
||||
{
|
||||
return idx > 0 ? (STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str,idx-1) ) && !STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str, idx) ) ) : 1;
|
||||
}
|
||||
|
||||
#ifndef STB_TEXTEDIT_MOVEWORDLEFT
|
||||
static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *str, int c )
|
||||
static int stb_textedit_move_to_word_previous( IMSTB_TEXTEDIT_STRING *str, int c )
|
||||
{
|
||||
--c; // always move at least one character
|
||||
while( c >= 0 && !is_word_boundary( str, c ) )
|
||||
@@ -658,7 +681,7 @@ static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *str, int c )
|
||||
#endif
|
||||
|
||||
#ifndef STB_TEXTEDIT_MOVEWORDRIGHT
|
||||
static int stb_textedit_move_to_word_next( STB_TEXTEDIT_STRING *str, int c )
|
||||
static int stb_textedit_move_to_word_next( IMSTB_TEXTEDIT_STRING *str, int c )
|
||||
{
|
||||
const int len = STB_TEXTEDIT_STRINGLEN(str);
|
||||
++c; // always move at least one character
|
||||
@@ -685,7 +708,7 @@ static void stb_textedit_prep_selection_at_cursor(STB_TexteditState *state)
|
||||
}
|
||||
|
||||
// API cut: delete selection
|
||||
static int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||
static int stb_textedit_cut(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||
{
|
||||
if (STB_TEXT_HAS_SELECTION(state)) {
|
||||
stb_textedit_delete_selection(str,state); // implicitly clamps
|
||||
@@ -696,7 +719,7 @@ static int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||
}
|
||||
|
||||
// API paste: replace existing selection with passed-in text
|
||||
static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len)
|
||||
static int stb_textedit_paste_internal(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, IMSTB_TEXTEDIT_CHARTYPE *text, int len)
|
||||
{
|
||||
// if there's a selection, the paste should delete it
|
||||
stb_textedit_clamp(str, state);
|
||||
@@ -716,36 +739,44 @@ static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditSta
|
||||
#define STB_TEXTEDIT_KEYTYPE int
|
||||
#endif
|
||||
|
||||
// [DEAR IMGUI] Added stb_textedit_text(), extracted out and called by stb_textedit_key() for backward compatibility.
|
||||
static void stb_textedit_text(IMSTB_TEXTEDIT_STRING* str, STB_TexteditState* state, const IMSTB_TEXTEDIT_CHARTYPE* text, int text_len)
|
||||
{
|
||||
// can't add newline in single-line mode
|
||||
if (text[0] == '\n' && state->single_line)
|
||||
return;
|
||||
|
||||
if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) {
|
||||
stb_text_makeundo_replace(str, state, state->cursor, 1, 1);
|
||||
STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1);
|
||||
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len)) {
|
||||
state->cursor += text_len;
|
||||
state->has_preferred_x = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
stb_textedit_delete_selection(str, state); // implicitly clamps
|
||||
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len)) {
|
||||
stb_text_makeundo_insert(state, state->cursor, text_len);
|
||||
state->cursor += text_len;
|
||||
state->has_preferred_x = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// API key: process a keyboard input
|
||||
static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key)
|
||||
static void stb_textedit_key(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key)
|
||||
{
|
||||
retry:
|
||||
switch (key) {
|
||||
default: {
|
||||
#ifdef STB_TEXTEDIT_KEYTOTEXT
|
||||
int c = STB_TEXTEDIT_KEYTOTEXT(key);
|
||||
if (c > 0) {
|
||||
STB_TEXTEDIT_CHARTYPE ch = (STB_TEXTEDIT_CHARTYPE) c;
|
||||
|
||||
// can't add newline in single-line mode
|
||||
if (c == '\n' && state->single_line)
|
||||
break;
|
||||
|
||||
if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) {
|
||||
stb_text_makeundo_replace(str, state, state->cursor, 1, 1);
|
||||
STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1);
|
||||
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) {
|
||||
++state->cursor;
|
||||
state->has_preferred_x = 0;
|
||||
}
|
||||
} else {
|
||||
stb_textedit_delete_selection(str,state); // implicitly clamps
|
||||
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) {
|
||||
stb_text_makeundo_insert(state, state->cursor, 1);
|
||||
++state->cursor;
|
||||
state->has_preferred_x = 0;
|
||||
}
|
||||
}
|
||||
IMSTB_TEXTEDIT_CHARTYPE ch = (IMSTB_TEXTEDIT_CHARTYPE)c;
|
||||
stb_textedit_text(str, state, &ch, 1);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -771,7 +802,7 @@ retry:
|
||||
stb_textedit_move_to_first(state);
|
||||
else
|
||||
if (state->cursor > 0)
|
||||
--state->cursor;
|
||||
state->cursor = IMSTB_TEXTEDIT_GETPREVCHARINDEX(str, state->cursor);
|
||||
state->has_preferred_x = 0;
|
||||
break;
|
||||
|
||||
@@ -780,7 +811,7 @@ retry:
|
||||
if (STB_TEXT_HAS_SELECTION(state))
|
||||
stb_textedit_move_to_last(str, state);
|
||||
else
|
||||
++state->cursor;
|
||||
state->cursor = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor);
|
||||
stb_textedit_clamp(str, state);
|
||||
state->has_preferred_x = 0;
|
||||
break;
|
||||
@@ -790,7 +821,7 @@ retry:
|
||||
stb_textedit_prep_selection_at_cursor(state);
|
||||
// move selection left
|
||||
if (state->select_end > 0)
|
||||
--state->select_end;
|
||||
state->select_end = IMSTB_TEXTEDIT_GETPREVCHARINDEX(str, state->select_end);
|
||||
state->cursor = state->select_end;
|
||||
state->has_preferred_x = 0;
|
||||
break;
|
||||
@@ -840,7 +871,7 @@ retry:
|
||||
case STB_TEXTEDIT_K_RIGHT | STB_TEXTEDIT_K_SHIFT:
|
||||
stb_textedit_prep_selection_at_cursor(state);
|
||||
// move selection right
|
||||
++state->select_end;
|
||||
state->select_end = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->select_end);
|
||||
stb_textedit_clamp(str, state);
|
||||
state->cursor = state->select_end;
|
||||
state->has_preferred_x = 0;
|
||||
@@ -889,14 +920,14 @@ retry:
|
||||
x = row.x0;
|
||||
for (i=0; i < row.num_chars; ++i) {
|
||||
float dx = STB_TEXTEDIT_GETWIDTH(str, start, i);
|
||||
#ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE
|
||||
if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE)
|
||||
#ifdef IMSTB_TEXTEDIT_GETWIDTH_NEWLINE
|
||||
if (dx == IMSTB_TEXTEDIT_GETWIDTH_NEWLINE)
|
||||
break;
|
||||
#endif
|
||||
x += dx;
|
||||
if (x > goal_x)
|
||||
break;
|
||||
++state->cursor;
|
||||
state->cursor = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor);
|
||||
}
|
||||
stb_textedit_clamp(str, state);
|
||||
|
||||
@@ -951,14 +982,14 @@ retry:
|
||||
x = row.x0;
|
||||
for (i=0; i < row.num_chars; ++i) {
|
||||
float dx = STB_TEXTEDIT_GETWIDTH(str, find.prev_first, i);
|
||||
#ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE
|
||||
if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE)
|
||||
#ifdef IMSTB_TEXTEDIT_GETWIDTH_NEWLINE
|
||||
if (dx == IMSTB_TEXTEDIT_GETWIDTH_NEWLINE)
|
||||
break;
|
||||
#endif
|
||||
x += dx;
|
||||
if (x > goal_x)
|
||||
break;
|
||||
++state->cursor;
|
||||
state->cursor = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor);
|
||||
}
|
||||
stb_textedit_clamp(str, state);
|
||||
|
||||
@@ -986,7 +1017,7 @@ retry:
|
||||
else {
|
||||
int n = STB_TEXTEDIT_STRINGLEN(str);
|
||||
if (state->cursor < n)
|
||||
stb_textedit_delete(str, state, state->cursor, 1);
|
||||
stb_textedit_delete(str, state, state->cursor, IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor) - state->cursor);
|
||||
}
|
||||
state->has_preferred_x = 0;
|
||||
break;
|
||||
@@ -998,8 +1029,9 @@ retry:
|
||||
else {
|
||||
stb_textedit_clamp(str, state);
|
||||
if (state->cursor > 0) {
|
||||
stb_textedit_delete(str, state, state->cursor-1, 1);
|
||||
--state->cursor;
|
||||
int prev = IMSTB_TEXTEDIT_GETPREVCHARINDEX(str, state->cursor);
|
||||
stb_textedit_delete(str, state, prev, state->cursor - prev);
|
||||
state->cursor = prev;
|
||||
}
|
||||
}
|
||||
state->has_preferred_x = 0;
|
||||
@@ -1109,8 +1141,8 @@ retry:
|
||||
|
||||
static void stb_textedit_flush_redo(StbUndoState *state)
|
||||
{
|
||||
state->redo_point = STB_TEXTEDIT_UNDOSTATECOUNT;
|
||||
state->redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT;
|
||||
state->redo_point = IMSTB_TEXTEDIT_UNDOSTATECOUNT;
|
||||
state->redo_char_point = IMSTB_TEXTEDIT_UNDOCHARCOUNT;
|
||||
}
|
||||
|
||||
// discard the oldest entry in the undo list
|
||||
@@ -1122,13 +1154,13 @@ static void stb_textedit_discard_undo(StbUndoState *state)
|
||||
int n = state->undo_rec[0].insert_length, i;
|
||||
// delete n characters from all other records
|
||||
state->undo_char_point -= n;
|
||||
STB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) (state->undo_char_point*sizeof(STB_TEXTEDIT_CHARTYPE)));
|
||||
IMSTB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) (state->undo_char_point*sizeof(IMSTB_TEXTEDIT_CHARTYPE)));
|
||||
for (i=0; i < state->undo_point; ++i)
|
||||
if (state->undo_rec[i].char_storage >= 0)
|
||||
state->undo_rec[i].char_storage -= n; // @OPTIMIZE: get rid of char_storage and infer it
|
||||
}
|
||||
--state->undo_point;
|
||||
STB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) (state->undo_point*sizeof(state->undo_rec[0])));
|
||||
IMSTB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) (state->undo_point*sizeof(state->undo_rec[0])));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1138,7 +1170,7 @@ static void stb_textedit_discard_undo(StbUndoState *state)
|
||||
// fill up even though the undo buffer didn't
|
||||
static void stb_textedit_discard_redo(StbUndoState *state)
|
||||
{
|
||||
int k = STB_TEXTEDIT_UNDOSTATECOUNT-1;
|
||||
int k = IMSTB_TEXTEDIT_UNDOSTATECOUNT-1;
|
||||
|
||||
if (state->redo_point <= k) {
|
||||
// if the k'th undo state has characters, clean those up
|
||||
@@ -1146,7 +1178,7 @@ static void stb_textedit_discard_redo(StbUndoState *state)
|
||||
int n = state->undo_rec[k].insert_length, i;
|
||||
// move the remaining redo character data to the end of the buffer
|
||||
state->redo_char_point += n;
|
||||
STB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((STB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point)*sizeof(STB_TEXTEDIT_CHARTYPE)));
|
||||
IMSTB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((IMSTB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point)*sizeof(IMSTB_TEXTEDIT_CHARTYPE)));
|
||||
// adjust the position of all the other records to account for above memmove
|
||||
for (i=state->redo_point; i < k; ++i)
|
||||
if (state->undo_rec[i].char_storage >= 0)
|
||||
@@ -1154,12 +1186,12 @@ static void stb_textedit_discard_redo(StbUndoState *state)
|
||||
}
|
||||
// now move all the redo records towards the end of the buffer; the first one is at 'redo_point'
|
||||
// [DEAR IMGUI]
|
||||
size_t move_size = (size_t)((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point - 1) * sizeof(state->undo_rec[0]));
|
||||
size_t move_size = (size_t)((IMSTB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point - 1) * sizeof(state->undo_rec[0]));
|
||||
const char* buf_begin = (char*)state->undo_rec; (void)buf_begin;
|
||||
const char* buf_end = (char*)state->undo_rec + sizeof(state->undo_rec); (void)buf_end;
|
||||
IM_ASSERT(((char*)(state->undo_rec + state->redo_point)) >= buf_begin);
|
||||
IM_ASSERT(((char*)(state->undo_rec + state->redo_point + 1) + move_size) <= buf_end);
|
||||
STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point+1, state->undo_rec + state->redo_point, move_size);
|
||||
IMSTB_TEXTEDIT_memmove(state->undo_rec + state->redo_point+1, state->undo_rec + state->redo_point, move_size);
|
||||
|
||||
// now move redo_point to point to the new one
|
||||
++state->redo_point;
|
||||
@@ -1173,32 +1205,32 @@ static StbUndoRecord *stb_text_create_undo_record(StbUndoState *state, int numch
|
||||
|
||||
// if we have no free records, we have to make room, by sliding the
|
||||
// existing records down
|
||||
if (state->undo_point == STB_TEXTEDIT_UNDOSTATECOUNT)
|
||||
if (state->undo_point == IMSTB_TEXTEDIT_UNDOSTATECOUNT)
|
||||
stb_textedit_discard_undo(state);
|
||||
|
||||
// if the characters to store won't possibly fit in the buffer, we can't undo
|
||||
if (numchars > STB_TEXTEDIT_UNDOCHARCOUNT) {
|
||||
if (numchars > IMSTB_TEXTEDIT_UNDOCHARCOUNT) {
|
||||
state->undo_point = 0;
|
||||
state->undo_char_point = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// if we don't have enough free characters in the buffer, we have to make room
|
||||
while (state->undo_char_point + numchars > STB_TEXTEDIT_UNDOCHARCOUNT)
|
||||
while (state->undo_char_point + numchars > IMSTB_TEXTEDIT_UNDOCHARCOUNT)
|
||||
stb_textedit_discard_undo(state);
|
||||
|
||||
return &state->undo_rec[state->undo_point++];
|
||||
}
|
||||
|
||||
static STB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos, int insert_len, int delete_len)
|
||||
static IMSTB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos, int insert_len, int delete_len)
|
||||
{
|
||||
StbUndoRecord *r = stb_text_create_undo_record(state, insert_len);
|
||||
if (r == NULL)
|
||||
return NULL;
|
||||
|
||||
r->where = pos;
|
||||
r->insert_length = (STB_TEXTEDIT_POSITIONTYPE) insert_len;
|
||||
r->delete_length = (STB_TEXTEDIT_POSITIONTYPE) delete_len;
|
||||
r->insert_length = (IMSTB_TEXTEDIT_POSITIONTYPE) insert_len;
|
||||
r->delete_length = (IMSTB_TEXTEDIT_POSITIONTYPE) delete_len;
|
||||
|
||||
if (insert_len == 0) {
|
||||
r->char_storage = -1;
|
||||
@@ -1210,7 +1242,7 @@ static STB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos,
|
||||
}
|
||||
}
|
||||
|
||||
static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||
static void stb_text_undo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||
{
|
||||
StbUndoState *s = &state->undostate;
|
||||
StbUndoRecord u, *r;
|
||||
@@ -1237,7 +1269,7 @@ static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||
// characters stored for *undoing* don't leave room for redo
|
||||
// if the last is true, we have to bail
|
||||
|
||||
if (s->undo_char_point + u.delete_length >= STB_TEXTEDIT_UNDOCHARCOUNT) {
|
||||
if (s->undo_char_point + u.delete_length >= IMSTB_TEXTEDIT_UNDOCHARCOUNT) {
|
||||
// the undo records take up too much character space; there's no space to store the redo characters
|
||||
r->insert_length = 0;
|
||||
} else {
|
||||
@@ -1246,7 +1278,7 @@ static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||
// there's definitely room to store the characters eventually
|
||||
while (s->undo_char_point + u.delete_length > s->redo_char_point) {
|
||||
// should never happen:
|
||||
if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT)
|
||||
if (s->redo_point == IMSTB_TEXTEDIT_UNDOSTATECOUNT)
|
||||
return;
|
||||
// there's currently not enough room, so discard a redo record
|
||||
stb_textedit_discard_redo(s);
|
||||
@@ -1278,11 +1310,11 @@ static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||
s->redo_point--;
|
||||
}
|
||||
|
||||
static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||
static void stb_text_redo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||
{
|
||||
StbUndoState *s = &state->undostate;
|
||||
StbUndoRecord *u, r;
|
||||
if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT)
|
||||
if (s->redo_point == IMSTB_TEXTEDIT_UNDOSTATECOUNT)
|
||||
return;
|
||||
|
||||
// we need to do two things: apply the redo record, and create an undo record
|
||||
@@ -1334,20 +1366,20 @@ static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int le
|
||||
stb_text_createundo(&state->undostate, where, 0, length);
|
||||
}
|
||||
|
||||
static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length)
|
||||
static void stb_text_makeundo_delete(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length)
|
||||
{
|
||||
int i;
|
||||
STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, length, 0);
|
||||
IMSTB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, length, 0);
|
||||
if (p) {
|
||||
for (i=0; i < length; ++i)
|
||||
p[i] = STB_TEXTEDIT_GETCHAR(str, where+i);
|
||||
}
|
||||
}
|
||||
|
||||
static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length)
|
||||
static void stb_text_makeundo_replace(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length)
|
||||
{
|
||||
int i;
|
||||
STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, old_length, new_length);
|
||||
IMSTB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, old_length, new_length);
|
||||
if (p) {
|
||||
for (i=0; i < old_length; ++i)
|
||||
p[i] = STB_TEXTEDIT_GETCHAR(str, where+i);
|
||||
@@ -1359,8 +1391,8 @@ static void stb_textedit_clear_state(STB_TexteditState *state, int is_single_lin
|
||||
{
|
||||
state->undostate.undo_point = 0;
|
||||
state->undostate.undo_char_point = 0;
|
||||
state->undostate.redo_point = STB_TEXTEDIT_UNDOSTATECOUNT;
|
||||
state->undostate.redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT;
|
||||
state->undostate.redo_point = IMSTB_TEXTEDIT_UNDOSTATECOUNT;
|
||||
state->undostate.redo_char_point = IMSTB_TEXTEDIT_UNDOCHARCOUNT;
|
||||
state->select_end = state->select_start = 0;
|
||||
state->cursor = 0;
|
||||
state->has_preferred_x = 0;
|
||||
@@ -1383,16 +1415,16 @@ static void stb_textedit_initialize_state(STB_TexteditState *state, int is_singl
|
||||
#pragma GCC diagnostic ignored "-Wcast-qual"
|
||||
#endif
|
||||
|
||||
static int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE const *ctext, int len)
|
||||
static int stb_textedit_paste(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, IMSTB_TEXTEDIT_CHARTYPE const *ctext, int len)
|
||||
{
|
||||
return stb_textedit_paste_internal(str, state, (STB_TEXTEDIT_CHARTYPE *) ctext, len);
|
||||
return stb_textedit_paste_internal(str, state, (IMSTB_TEXTEDIT_CHARTYPE *) ctext, len);
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif//STB_TEXTEDIT_IMPLEMENTATION
|
||||
#endif//IMSTB_TEXTEDIT_IMPLEMENTATION
|
||||
|
||||
/*
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
+1
-1
@@ -656,7 +656,7 @@ STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h
|
||||
STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip);
|
||||
// If skip != 0, this tells stb_truetype to skip any codepoints for which
|
||||
// there is no corresponding glyph. If skip=0, which is the default, then
|
||||
// codepoints without a glyph recived the font's "missing character" glyph,
|
||||
// codepoints without a glyph received the font's "missing character" glyph,
|
||||
// typically an empty box by convention.
|
||||
|
||||
STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above
|
||||
|
||||
Vendored
Vendored
@@ -461,18 +461,6 @@ namespace games {
|
||||
vkey_defaults.push_back(0xFF);
|
||||
names.emplace_back("Force Exit Game");
|
||||
vkey_defaults.push_back(0xFF);
|
||||
names.emplace_back("Navigator Activate");
|
||||
vkey_defaults.push_back(0xFF);
|
||||
names.emplace_back("Navigator Cancel");
|
||||
vkey_defaults.push_back(0xFF);
|
||||
names.emplace_back("Navigator Up");
|
||||
vkey_defaults.push_back(0xFF);
|
||||
names.emplace_back("Navigator Down");
|
||||
vkey_defaults.push_back(0xFF);
|
||||
names.emplace_back("Navigator Left");
|
||||
vkey_defaults.push_back(0xFF);
|
||||
names.emplace_back("Navigator Right");
|
||||
vkey_defaults.push_back(0xFF);
|
||||
names.emplace_back("Hotkey Enable 1");
|
||||
vkey_defaults.push_back(0xFF);
|
||||
names.emplace_back("Hotkey Enable 2");
|
||||
|
||||
@@ -30,12 +30,6 @@ namespace games {
|
||||
ScreenResizeScene3,
|
||||
ScreenResizeScene4,
|
||||
SuperExit,
|
||||
NavigatorActivate,
|
||||
NavigatorCancel,
|
||||
NavigatorUp,
|
||||
NavigatorDown,
|
||||
NavigatorLeft,
|
||||
NavigatorRight,
|
||||
HotkeyEnable1,
|
||||
HotkeyEnable2,
|
||||
HotkeyToggle,
|
||||
|
||||
@@ -71,6 +71,8 @@ std::vector<Light> &games::museca::get_lights() {
|
||||
|
||||
GameAPI::Lights::sortLights(
|
||||
&lights,
|
||||
"Start",
|
||||
"Keypad",
|
||||
"Title R",
|
||||
"Title G",
|
||||
"Title B",
|
||||
|
||||
@@ -46,6 +46,8 @@ namespace games::museca {
|
||||
// all lights in correct order
|
||||
namespace Lights {
|
||||
enum {
|
||||
Start,
|
||||
Keypad,
|
||||
TitleR,
|
||||
TitleG,
|
||||
TitleB,
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace games::qma {
|
||||
touch_attach_dx_hook();
|
||||
|
||||
// cursor
|
||||
if (!is_touch_available()) {
|
||||
if (!is_touch_available("QMATouchDevice::open")) {
|
||||
ShowCursor(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ bool games::rb::ReflecBeatTouchDeviceHandle::open(LPCWSTR lpFileName) {
|
||||
}
|
||||
|
||||
// show cursor on window if mouse is used
|
||||
if (!is_touch_available()) {
|
||||
if (!is_touch_available("ReflecBeatTouchDeviceHandle::open")) {
|
||||
ShowCursor(TRUE);
|
||||
}
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ public:
|
||||
touch_attach_dx_hook();
|
||||
|
||||
// cursor
|
||||
if (!is_touch_available()) {
|
||||
if (!is_touch_available("TwTouchDevice::open")) {
|
||||
ShowCursor(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,6 +124,8 @@ std::string LOG_FILE_PATH = "";
|
||||
int LAUNCHER_ARGC = 0;
|
||||
char **LAUNCHER_ARGV = nullptr;
|
||||
std::unique_ptr<std::vector<Option>> LAUNCHER_OPTIONS;
|
||||
|
||||
std::mutex CARD_OVERRIDES_LOCK;
|
||||
std::string CARD_OVERRIDES[2];
|
||||
|
||||
// sub-systems
|
||||
@@ -217,6 +219,7 @@ int main_implementation(int argc, char *argv[]) {
|
||||
bool attach_qks = false;
|
||||
bool attach_mfg = false;
|
||||
bool attach_museca = false;
|
||||
bool show_cursor_if_no_touch = false;
|
||||
|
||||
// misc settings
|
||||
size_t user_heap_size = 0;
|
||||
@@ -743,9 +746,11 @@ int main_implementation(int argc, char *argv[]) {
|
||||
SetDllDirectoryW(MODULE_PATH.c_str());
|
||||
}
|
||||
if (options[launcher::Options::Player1Card].is_active()) {
|
||||
std::lock_guard<std::mutex> lock(CARD_OVERRIDES_LOCK);
|
||||
CARD_OVERRIDES[0] = options[launcher::Options::Player1Card].value_text();
|
||||
}
|
||||
if (options[launcher::Options::Player2Card].is_active()) {
|
||||
std::lock_guard<std::mutex> lock(CARD_OVERRIDES_LOCK);
|
||||
CARD_OVERRIDES[1] = options[launcher::Options::Player2Card].value_text();
|
||||
}
|
||||
if (options[launcher::Options::Player1PinMacro].is_active()) {
|
||||
@@ -1291,11 +1296,7 @@ int main_implementation(int argc, char *argv[]) {
|
||||
avs::game::DLL_NAME = "system.dll";
|
||||
attach_io = true;
|
||||
attach_shogikai = true;
|
||||
|
||||
// automatically show cursor when no touchscreen is available
|
||||
if (!is_touch_available()) {
|
||||
GRAPHICS_SHOW_CURSOR = true;
|
||||
}
|
||||
show_cursor_if_no_touch = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1338,12 +1339,7 @@ int main_implementation(int argc, char *argv[]) {
|
||||
|
||||
// game crash fix
|
||||
easrv_maint = false;
|
||||
|
||||
// automatically show cursor when no touchscreen is available
|
||||
if (!is_touch_available()) {
|
||||
GRAPHICS_SHOW_CURSOR = true;
|
||||
}
|
||||
|
||||
show_cursor_if_no_touch = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1458,12 +1454,7 @@ int main_implementation(int argc, char *argv[]) {
|
||||
avs::game::DLL_NAME = "nostalgia.dll";
|
||||
attach_io = true;
|
||||
attach_nostalgia = true;
|
||||
|
||||
// automatically show cursor when no touchscreen is available
|
||||
if (!is_touch_available()) {
|
||||
GRAPHICS_SHOW_CURSOR = true;
|
||||
}
|
||||
|
||||
show_cursor_if_no_touch = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1569,12 +1560,7 @@ int main_implementation(int argc, char *argv[]) {
|
||||
avs::game::DLL_NAME = "arknck.dll";
|
||||
attach_io = true;
|
||||
attach_we = true;
|
||||
|
||||
// automatically show cursor when no touchscreen is available
|
||||
if (!is_touch_available()) {
|
||||
GRAPHICS_SHOW_CURSOR = true;
|
||||
}
|
||||
|
||||
show_cursor_if_no_touch = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1607,10 +1593,7 @@ int main_implementation(int argc, char *argv[]) {
|
||||
avs::game::DLL_NAME = "kamunity.dll";
|
||||
attach_io = true;
|
||||
attach_ccj = true;
|
||||
// automatically show cursor when no touchscreen is available
|
||||
if (!is_touch_available()) {
|
||||
GRAPHICS_SHOW_CURSOR = true;
|
||||
}
|
||||
show_cursor_if_no_touch = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1619,10 +1602,7 @@ int main_implementation(int argc, char *argv[]) {
|
||||
avs::game::DLL_NAME = "kamunity.dll";
|
||||
attach_io = true;
|
||||
attach_qks = true;
|
||||
// automatically show cursor when no touchscreen is available
|
||||
if (!is_touch_available()) {
|
||||
GRAPHICS_SHOW_CURSOR = true;
|
||||
}
|
||||
show_cursor_if_no_touch = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1632,10 +1612,7 @@ int main_implementation(int argc, char *argv[]) {
|
||||
attach_io = true;
|
||||
attach_mfg = true;
|
||||
launcher::signal::USE_VEH_WORKAROUND = true;
|
||||
// automatically show cursor when no touchscreen is available
|
||||
if (!is_touch_available()) {
|
||||
GRAPHICS_SHOW_CURSOR = true;
|
||||
}
|
||||
show_cursor_if_no_touch = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1644,10 +1621,7 @@ int main_implementation(int argc, char *argv[]) {
|
||||
avs::game::DLL_NAME = "kamunity.dll";
|
||||
attach_io = true;
|
||||
attach_bc = true;
|
||||
// automatically show cursor when no touchscreen is available
|
||||
if (!is_touch_available()) {
|
||||
GRAPHICS_SHOW_CURSOR = true;
|
||||
}
|
||||
show_cursor_if_no_touch = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1843,6 +1817,11 @@ int main_implementation(int argc, char *argv[]) {
|
||||
// print devices
|
||||
RI_MGR->devices_print();
|
||||
|
||||
// for certain games, show cursor if no touch is available (must be called after RI_MGR is available)
|
||||
if (show_cursor_if_no_touch && !is_touch_available("launcher::main_implementation")) {
|
||||
GRAPHICS_SHOW_CURSOR = true;
|
||||
}
|
||||
|
||||
// cardio
|
||||
if (cardio_enabled) {
|
||||
cardio_runner_start(true);
|
||||
|
||||
@@ -186,9 +186,12 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
{
|
||||
.title = "Monitor",
|
||||
.name = "monitor",
|
||||
.desc = "Sets the display that the game will be opened in, for multiple monitors",
|
||||
.desc = "Sets the display that the game will be opened in, for multiple monitors.\n\n"
|
||||
"0 is the primary monitor, 1 is the second monitor, and so on.\n\n"
|
||||
"Not all games will respect this. Does not work at all with multi-monitor games like TDJ/UFC. "
|
||||
"Disable Full Screen Optimizations for best results",
|
||||
.type = OptionType::Integer,
|
||||
.category = "Graphics (Common)",
|
||||
.category = "Graphics (Full Screen)",
|
||||
},
|
||||
{
|
||||
.title = "Only Use One Monitor",
|
||||
@@ -212,7 +215,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.desc =
|
||||
"For full screen mode, forcibly set a custom resolution.\n\n"
|
||||
"Works great for some games, but can COMPLETELY BREAK other games - YMMV!\n\n"
|
||||
"If you are using -sdvxlandscape, put the TARGET monitor resolution in this field.\n\n"
|
||||
"If you are using -forceresswap/-sdvxlandscape, put the TARGET monitor resolution in this field.\n\n"
|
||||
"This should only be used as last resort if your GPU/monitor can't display the resolution required by the game",
|
||||
.type = OptionType::Text,
|
||||
.setting_name = "1280,720",
|
||||
@@ -2050,7 +2053,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.name = "sdvxlandscape",
|
||||
.desc =
|
||||
"Allows you to play in landscape by transposing resolution and applying image scaling.\n\n"
|
||||
"Works only for SDVX5 and above! This is identical to -forceorientation.\n\n"
|
||||
"Works only for SDVX5 and above! This is identical to -forceresswap.\n\n"
|
||||
"Will launch at 1080p by default; strongly consider combining this with -forceres option to render at monitor native resolution",
|
||||
.type = OptionType::Bool,
|
||||
.game_name = "Sound Voltex",
|
||||
|
||||
+17
-13
@@ -66,7 +66,7 @@ bool eamuse_get_card(int active_count, int unit_id, uint8_t *card) {
|
||||
if (CARD_INSERT_UID_ENABLE[index]) {
|
||||
CARD_INSERT_UID_ENABLE[index] = false;
|
||||
memcpy(card, CARD_INSERT_UID[index], 8);
|
||||
log_info("eamuse", "Inserted card from reader {}: {}", index, bin2hex(card, 8));
|
||||
log_info("eamuse", "[P{}] Inserted card from reader: {}", index+1, bin2hex(card, 8));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -83,35 +83,40 @@ bool eamuse_get_card(int active_count, int unit_id, uint8_t *card) {
|
||||
}
|
||||
|
||||
bool eamuse_get_card(const std::filesystem::path &path, uint8_t *card, int index) {
|
||||
|
||||
// do a quick copy under lock
|
||||
std::unique_lock<std::mutex> lock(CARD_OVERRIDES_LOCK);
|
||||
const auto card_override = CARD_OVERRIDES[index];
|
||||
lock.unlock();
|
||||
|
||||
// Check if card overrides are present
|
||||
if (!CARD_OVERRIDES[index].empty()) {
|
||||
if (!card_override.empty()) {
|
||||
|
||||
// Override is present
|
||||
for (int n = 0; n < 16; n++) {
|
||||
char c = CARD_OVERRIDES[index].c_str()[n];
|
||||
char c = card_override.c_str()[n];
|
||||
bool digit = c >= '0' && c <= '9';
|
||||
bool character_big = c >= 'A' && c <= 'F';
|
||||
bool character_small = c >= 'a' && c <= 'f';
|
||||
if (!digit && !character_big && !character_small) {
|
||||
log_warning("eamuse",
|
||||
"{} card override contains an invalid character sequence at byte {} (16 characters, 0-9/A-F only)",
|
||||
CARD_OVERRIDES[index], n);
|
||||
card_override, n);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Log info
|
||||
log_info("eamuse", "Inserted card override: {}", CARD_OVERRIDES[index]);
|
||||
log_info("eamuse", "[P{}] Inserted card override: {}", index+1, card_override);
|
||||
|
||||
// Card is valid, convert and set it.
|
||||
hex2bin(CARD_OVERRIDES[index].c_str(), card);
|
||||
hex2bin(card_override.c_str(), card);
|
||||
|
||||
// cache it for auto-insert
|
||||
if (AUTO_INSERT_CARD[index] && !AUTO_INSERT_CARD_CACHED[index]) {
|
||||
// always overwrite from overrides since override may have changed by user in card manager
|
||||
if (AUTO_INSERT_CARD[index]) {
|
||||
memcpy(AUTO_INSERT_CARD_CACHED_DATA[index], card, 8);
|
||||
AUTO_INSERT_CARD_CACHED[index] = true;
|
||||
log_info("eamuse", "Auto card insert - caching this card in memory: {}", CARD_OVERRIDES[index]);
|
||||
log_info("eamuse", "[P{}] Auto card insert - caching this card override in memory: {}", index+1, card_override);
|
||||
}
|
||||
|
||||
// success
|
||||
@@ -162,7 +167,7 @@ bool eamuse_get_card_from_file(const std::filesystem::path &path, uint8_t *card,
|
||||
}
|
||||
|
||||
// info
|
||||
log_info("eamuse", "Inserted {}: {}", path.string(), buffer);
|
||||
log_info("eamuse", "[P{}] Inserted {}: {}", index+1, path.string(), buffer);
|
||||
|
||||
// convert hex to bytes
|
||||
hex2bin(buffer, card);
|
||||
@@ -171,7 +176,7 @@ bool eamuse_get_card_from_file(const std::filesystem::path &path, uint8_t *card,
|
||||
if (AUTO_INSERT_CARD[index] && !AUTO_INSERT_CARD_CACHED[index]) {
|
||||
memcpy(AUTO_INSERT_CARD_CACHED_DATA[index], card, 8);
|
||||
AUTO_INSERT_CARD_CACHED[index] = true;
|
||||
log_info("eamuse", "Auto card insert - caching this card in memory: {}", buffer);
|
||||
log_info("eamuse", "[P{}] Auto card insert - caching this card from file in memory: {}", index+1, buffer);
|
||||
}
|
||||
|
||||
// success
|
||||
@@ -211,7 +216,6 @@ bool eamuse_card_insert_consume(int active_count, int unit_id) {
|
||||
if (!CARD_INSERT[index]) {
|
||||
eamuse_card_insert(index);
|
||||
// not logging anything here to prevent spam
|
||||
// log_info("eamuse", "Automatic card insert on {}/{} (-autocard)", unit_id + 1, active_count);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -223,7 +227,7 @@ bool eamuse_card_insert_consume(int active_count, int unit_id) {
|
||||
auto offset = unit_id * games::KeypadButtons::Size;
|
||||
if ((CARD_INSERT[index] && fabs(get_performance_seconds() - CARD_INSERT_TIME[index]) < CARD_INSERT_TIMEOUT)
|
||||
|| GameAPI::Buttons::getState(RI_MGR, keypad_buttons->at(games::KeypadButtons::InsertCard + offset))) {
|
||||
log_info("eamuse", "Card insert on {}/{}", unit_id + 1, active_count);
|
||||
log_info("eamuse", "[P{}] Card insert on reader (total active count: {})", unit_id+1, active_count);
|
||||
CARD_INSERT[index] = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <optional>
|
||||
#include <mutex>
|
||||
|
||||
#include "external/scard/scard.h"
|
||||
|
||||
@@ -30,6 +31,7 @@ enum eam_io_keypad_scan_code {
|
||||
EAM_IO_INSERT = 13, /* SpiceTools Extension */
|
||||
};
|
||||
|
||||
extern std::mutex CARD_OVERRIDES_LOCK;
|
||||
extern std::string CARD_OVERRIDES[2];
|
||||
extern bool AUTO_INSERT_CARD[2];
|
||||
extern float AUTO_INSERT_CARD_COOLDOWN;
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace wintouchemu {
|
||||
bool LOG_FPS = false;
|
||||
|
||||
static inline bool is_emu_enabled() {
|
||||
return FORCE || !is_touch_available() || GRAPHICS_SHOW_CURSOR;
|
||||
return FORCE || !is_touch_available("wintouchemu::is_emu_enabled") || GRAPHICS_SHOW_CURSOR;
|
||||
}
|
||||
|
||||
static decltype(GetSystemMetrics) *GetSystemMetrics_orig = nullptr;
|
||||
|
||||
@@ -39,12 +39,12 @@ namespace ImGui {
|
||||
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
|
||||
if (desc) {
|
||||
if (desc && desc[0]) {
|
||||
ImGui::TextUnformatted(desc);
|
||||
ImGui::TextUnformatted("");
|
||||
}
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.f, 1.f, 0.f, 1.f));
|
||||
if (warn) {
|
||||
if (warn && warn[0]) {
|
||||
ImGui::TextUnformatted("WARNING:");
|
||||
ImGui::TextUnformatted(warn);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "cfg/configurator.h"
|
||||
#include "games/io.h"
|
||||
#include "launcher/launcher.h"
|
||||
#include "launcher/superexit.h"
|
||||
@@ -12,6 +13,16 @@
|
||||
#include "util/logging.h"
|
||||
#include "util/utils.h"
|
||||
|
||||
#if !defined(IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS) || \
|
||||
!defined(IMGUI_DISABLE_DEFAULT_ALLOCATORS) || \
|
||||
!defined(IMGUI_USE_BGRA_PACKED_COLOR) || \
|
||||
!defined(IMGUI_HAS_VIEWPORT) || \
|
||||
!defined(IMGUI_HAS_DOCK) || \
|
||||
!defined(IMGUI_DISABLE_DEMO_WINDOWS) || \
|
||||
defined(IMGUI_DISABLE_DEBUG_TOOLS)
|
||||
#error "fix imconfig.h after updating imgui version"
|
||||
#endif
|
||||
|
||||
// state
|
||||
static HWND g_hWnd = nullptr;
|
||||
static INT64 g_Time = 0;
|
||||
@@ -42,6 +53,7 @@ bool ImGui_ImplSpice_Init(HWND hWnd) {
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors;
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos;
|
||||
io.BackendPlatformName = "imgui_impl_spice";
|
||||
io.ConfigErrorRecoveryEnableTooltip = true;
|
||||
|
||||
// keyboard mapping
|
||||
io.KeyMap[ImGuiKey_Tab] = VK_TAB;
|
||||
@@ -59,7 +71,7 @@ bool ImGui_ImplSpice_Init(HWND hWnd) {
|
||||
io.KeyMap[ImGuiKey_Space] = VK_SPACE;
|
||||
io.KeyMap[ImGuiKey_Enter] = VK_RETURN;
|
||||
io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE;
|
||||
io.KeyMap[ImGuiKey_KeyPadEnter] = VK_RETURN;
|
||||
io.KeyMap[ImGuiKey_KeypadEnter] = VK_RETURN;
|
||||
io.KeyMap[ImGuiKey_A] = 'A';
|
||||
io.KeyMap[ImGuiKey_C] = 'C';
|
||||
io.KeyMap[ImGuiKey_V] = 'V';
|
||||
@@ -349,27 +361,6 @@ void ImGui_ImplSpice_NewFrame() {
|
||||
}
|
||||
}
|
||||
|
||||
// navigator input
|
||||
auto buttons = games::get_buttons_overlay(eamuse_get_game());
|
||||
if (buttons && (!overlay::OVERLAY || overlay::OVERLAY->hotkeys_triggered())) {
|
||||
struct {
|
||||
size_t index;
|
||||
Button &btn;
|
||||
} NAV_MAPPING[] = {
|
||||
{ ImGuiNavInput_Activate, buttons->at(games::OverlayButtons::NavigatorActivate )},
|
||||
{ ImGuiNavInput_Cancel, buttons->at(games::OverlayButtons::NavigatorCancel) },
|
||||
{ ImGuiNavInput_DpadUp, buttons->at(games::OverlayButtons::NavigatorUp) },
|
||||
{ ImGuiNavInput_DpadDown, buttons->at(games::OverlayButtons::NavigatorDown) },
|
||||
{ ImGuiNavInput_DpadLeft, buttons->at(games::OverlayButtons::NavigatorLeft) },
|
||||
{ ImGuiNavInput_DpadRight, buttons->at(games::OverlayButtons::NavigatorRight) },
|
||||
};
|
||||
for (auto mapping : NAV_MAPPING) {
|
||||
if (GameAPI::Buttons::getState(RI_MGR, mapping.btn)) {
|
||||
io.NavInputs[mapping.index] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set mouse wheel
|
||||
auto mouse_diff = mouse_wheel - mouse_wheel_last;
|
||||
mouse_wheel_last = mouse_wheel;
|
||||
@@ -378,10 +369,27 @@ void ImGui_ImplSpice_NewFrame() {
|
||||
// update OS mouse position
|
||||
ImGui_ImplSpice_UpdateMousePos();
|
||||
|
||||
// update OS mouse cursor with the cursor requested by imgui
|
||||
ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor();
|
||||
if (g_LastMouseCursor != mouse_cursor) {
|
||||
g_LastMouseCursor = mouse_cursor;
|
||||
ImGui_ImplSpice_UpdateMouseCursor();
|
||||
if (cfg::CONFIGURATOR_STANDALONE) {
|
||||
// if cursor is inside the client area, always set the OS cursor to what ImGui wants
|
||||
// this is to deal with cases where mouse cursor changes outside the client rect and comes
|
||||
// back into the window
|
||||
// i'm sure there might be better ways to deal with this but this works so whatever, right?
|
||||
RECT client_rect;
|
||||
if (GetClientRect(g_hWnd, &client_rect)) {
|
||||
POINT cursor;
|
||||
if (GetCursorPos(&cursor) && ScreenToClient(g_hWnd, &cursor)) {
|
||||
if (client_rect.left < cursor.x && cursor.x < client_rect.right &&
|
||||
client_rect.top < cursor.y && cursor.y < client_rect.bottom) {
|
||||
ImGui_ImplSpice_UpdateMouseCursor();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// update OS mouse cursor with the cursor requested by imgui
|
||||
ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor();
|
||||
if (g_LastMouseCursor != mouse_cursor) {
|
||||
g_LastMouseCursor = mouse_cursor;
|
||||
ImGui_ImplSpice_UpdateMouseCursor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -678,7 +678,7 @@ void bind_imgui_painting()
|
||||
int font_width, font_height;
|
||||
io.Fonts->GetTexDataAsAlpha8(&tex_data, &font_width, &font_height);
|
||||
const auto texture = new Texture{tex_data, font_width, font_height};
|
||||
io.Fonts->TexID = texture;
|
||||
io.Fonts->TexID = reinterpret_cast<ImTextureID>(texture);
|
||||
}
|
||||
|
||||
static Stats s_stats; // TODO: pass as an argument?
|
||||
|
||||
@@ -7,14 +7,12 @@
|
||||
#include "hooks/graphics/graphics.h"
|
||||
#include "misc/eamuse.h"
|
||||
#include "touch/touch.h"
|
||||
#include "util/fileutils.h"
|
||||
#include "util/logging.h"
|
||||
#include "util/resutils.h"
|
||||
#include "build/resource.h"
|
||||
|
||||
#include "imgui/impl_dx9.h"
|
||||
#include "imgui/impl_spice.h"
|
||||
#include "imgui/impl_sw.h"
|
||||
#include "overlay/imgui/impl_dx9.h"
|
||||
#include "external/imgui/backends/imgui_impl_dx9.h"
|
||||
#include "overlay/imgui/impl_spice.h"
|
||||
#include "overlay/imgui/impl_sw.h"
|
||||
|
||||
@@ -62,6 +60,7 @@ namespace overlay {
|
||||
std::mutex OVERLAY_MUTEX;
|
||||
std::unique_ptr<overlay::SpiceOverlay> OVERLAY = nullptr;
|
||||
ImFont* DSEG_FONT = nullptr;
|
||||
bool SHOW_DEBUG_LOG_WINDOW = false;
|
||||
}
|
||||
|
||||
static void *ImGui_Alloc(size_t sz, void *user_data) {
|
||||
@@ -242,13 +241,20 @@ void overlay::SpiceOverlay::init() {
|
||||
io.UserData = this;
|
||||
io.ConfigFlags = ImGuiConfigFlags_NavEnableKeyboard
|
||||
| ImGuiConfigFlags_NavEnableGamepad
|
||||
| ImGuiConfigFlags_NavEnableSetMousePos
|
||||
| ImGuiConfigFlags_DockingEnable
|
||||
| ImGuiConfigFlags_ViewportsEnable;
|
||||
if (is_touch_available()) {
|
||||
| ImGuiConfigFlags_NavEnableSetMousePos;
|
||||
|
||||
if (!cfg::CONFIGURATOR_STANDALONE) {
|
||||
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
|
||||
}
|
||||
if (is_touch_available("SpiceOverlay::init")) {
|
||||
io.ConfigFlags |= ImGuiConfigFlags_IsTouchScreen;
|
||||
}
|
||||
|
||||
// temporarily turn this off as it can cause crashes during font load failures
|
||||
// turns back on in ImGui_ImplSpice_Init
|
||||
io.ConfigErrorRecoveryEnableTooltip = false;
|
||||
|
||||
io.MouseDrawCursor = !GRAPHICS_SHOW_CURSOR;
|
||||
|
||||
// disable config
|
||||
@@ -263,20 +269,14 @@ void overlay::SpiceOverlay::init() {
|
||||
// add fallback fonts for missing glyph ranges
|
||||
ImFontConfig config {};
|
||||
config.MergeMode = true;
|
||||
io.Fonts->AddFontFromFileTTF(R"(C:\Windows\Fonts\simsun.ttc)",
|
||||
13.0f, &config, io.Fonts->GetGlyphRangesChineseSimplifiedCommon());
|
||||
io.Fonts->AddFontFromFileTTF(R"(C:\Windows\Fonts\arial.ttf)",
|
||||
13.0f, &config, io.Fonts->GetGlyphRangesCyrillic());
|
||||
io.Fonts->AddFontFromFileTTF(R"(C:\Windows\Fonts\meiryu.ttc)",
|
||||
13.0f, &config, io.Fonts->GetGlyphRangesJapanese());
|
||||
io.Fonts->AddFontFromFileTTF(R"(C:\Windows\Fonts\meiryo.ttc)",
|
||||
13.0f, &config, io.Fonts->GetGlyphRangesJapanese());
|
||||
io.Fonts->AddFontFromFileTTF(R"(C:\Windows\Fonts\gulim.ttc)",
|
||||
13.0f, &config, io.Fonts->GetGlyphRangesKorean());
|
||||
io.Fonts->AddFontFromFileTTF(R"(C:\Windows\Fonts\cordia.ttf)",
|
||||
13.0f, &config, io.Fonts->GetGlyphRangesThai());
|
||||
io.Fonts->AddFontFromFileTTF(R"(C:\Windows\Fonts\arial.ttf)",
|
||||
13.0f, &config, io.Fonts->GetGlyphRangesVietnamese());
|
||||
|
||||
add_font("simsun.ttc", &config, io.Fonts->GetGlyphRangesChineseSimplifiedCommon());
|
||||
add_font("arial.ttc", &config, io.Fonts->GetGlyphRangesCyrillic());
|
||||
add_font("meiryu.ttc", &config, io.Fonts->GetGlyphRangesJapanese());
|
||||
add_font("meiryo.ttc", &config, io.Fonts->GetGlyphRangesJapanese());
|
||||
add_font("gulim.ttc", &config, io.Fonts->GetGlyphRangesKorean());
|
||||
add_font("cordia.ttc", &config, io.Fonts->GetGlyphRangesThai());
|
||||
add_font("arial.ttc", &config, io.Fonts->GetGlyphRangesVietnamese());
|
||||
|
||||
// add special font
|
||||
if (avs::game::is_model("LDJ")) {
|
||||
@@ -458,6 +458,10 @@ void overlay::SpiceOverlay::new_frame() {
|
||||
window->build();
|
||||
}
|
||||
|
||||
if (SHOW_DEBUG_LOG_WINDOW) {
|
||||
ImGui::ShowDebugLogWindow(&SHOW_DEBUG_LOG_WINDOW);
|
||||
}
|
||||
|
||||
// end frame
|
||||
ImGui::EndFrame();
|
||||
}
|
||||
@@ -693,3 +697,21 @@ uint32_t *overlay::SpiceOverlay::sw_get_pixel_data(int *width, int *height) {
|
||||
*height = this->pixel_data_height;
|
||||
return &this->pixel_data[0];
|
||||
}
|
||||
|
||||
void overlay::SpiceOverlay::add_font(const char* font, ImFontConfig* config, const ImWchar* glyphs) {
|
||||
CHAR fonts_dir[MAX_PATH];
|
||||
ExpandEnvironmentStringsA(R"(%SYSTEMROOT%\Fonts\)", fonts_dir, MAX_PATH);
|
||||
std::filesystem::path full_path = fonts_dir;
|
||||
full_path += font;
|
||||
|
||||
if (fileutils::file_exists(full_path)) {
|
||||
log_misc("overlay", "loading font: {}", full_path.string());
|
||||
ImGui::GetIO().Fonts->AddFontFromFileTTF(
|
||||
full_path.string().c_str(),
|
||||
13.0f,
|
||||
config,
|
||||
glyphs);
|
||||
} else {
|
||||
log_misc("overlay", "font not found: {}", full_path.string());
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ namespace overlay {
|
||||
extern bool AUTO_SHOW_KEYPAD_P2;
|
||||
extern bool USE_WM_CHAR_FOR_IMGUI_CHAR_INPUT;
|
||||
extern bool FPS_SHOULD_FLIP;
|
||||
extern bool SHOW_DEBUG_LOG_WINDOW;
|
||||
|
||||
class SpiceOverlay {
|
||||
public:
|
||||
@@ -128,6 +129,7 @@ namespace overlay {
|
||||
bool hotkey_toggle_last = false;
|
||||
|
||||
void init();
|
||||
void add_font(const char* font, ImFontConfig* config, const ImWchar* glyphs);
|
||||
};
|
||||
|
||||
// global
|
||||
|
||||
@@ -99,10 +99,9 @@ void overlay::Window::build() {
|
||||
for (auto &child : this->children) {
|
||||
child->build();
|
||||
}
|
||||
|
||||
// end window
|
||||
ImGui::End();
|
||||
}
|
||||
// end window
|
||||
ImGui::End();
|
||||
|
||||
if (this->remove_window_padding) {
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "external/imgui/imgui.h"
|
||||
#include "external/imgui/imgui_stdlib.h"
|
||||
#include "external/imgui/misc/cpp/imgui_stdlib.h"
|
||||
#include "overlay.h"
|
||||
|
||||
namespace overlay {
|
||||
|
||||
@@ -5,9 +5,11 @@
|
||||
#include "external/rapidjson/document.h"
|
||||
#include "external/rapidjson/prettywriter.h"
|
||||
#include "misc/eamuse.h"
|
||||
#include "misc/clipboard.h"
|
||||
#include "util/utils.h"
|
||||
#include "util/fileutils.h"
|
||||
#include "cfg/configurator.h"
|
||||
#include "overlay/imgui/extensions.h"
|
||||
|
||||
using namespace rapidjson;
|
||||
|
||||
@@ -31,15 +33,69 @@ namespace overlay::windows {
|
||||
if (fileutils::file_exists(this->config_path)) {
|
||||
this->config_load();
|
||||
}
|
||||
|
||||
// load -card0 / -card1
|
||||
// -card0 / -card1 override
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(CARD_OVERRIDES_LOCK);
|
||||
if (!CARD_OVERRIDES[0].empty()) {
|
||||
const CardEntry card0 = {
|
||||
.name = "P1 Default (-card0)",
|
||||
.id = CARD_OVERRIDES[0],
|
||||
.search_string = "p1 default (-card0)",
|
||||
.read_only = true,
|
||||
.color = {0.9f, 0.9f, 0.9f}
|
||||
};
|
||||
card_cmd_overrides[0].emplace(card0);
|
||||
this->loaded_card[0] = card0;
|
||||
}
|
||||
if (eamuse_get_game_keypads() > 1 && !CARD_OVERRIDES[1].empty()) {
|
||||
const CardEntry card1 = {
|
||||
.name = "P2 Default (-card1)",
|
||||
.id = CARD_OVERRIDES[1],
|
||||
.search_string = "p2 default (-card1)",
|
||||
.read_only = true,
|
||||
.color = {0.9f, 0.9f, 0.9f}
|
||||
};
|
||||
card_cmd_overrides[1].emplace(card1);
|
||||
this->loaded_card[1] = card1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CardManager::~CardManager() {
|
||||
}
|
||||
|
||||
void CardManager::build_content() {
|
||||
ImGui::SeparatorText("Selected card");
|
||||
build_card();
|
||||
ImGui::SeparatorText("Available cards");
|
||||
ImGui::TextColored(ImVec4(1, 0.7f, 0, 1), "Active card overrides");
|
||||
ImGui::SameLine();
|
||||
ImGui::HelpMarker(
|
||||
"Click to insert card now, or press Insert Card key. Auto Card Insert will also use these cards.\n\n"
|
||||
"If no override is set, pressing Insert Card will read from card0.txt / card1.txt.");
|
||||
if (ImGui::BeginTable("CardSetTable", eamuse_get_game_keypads() > 1 ? 2 : 1, ImGuiTableFlags_SizingFixedFit)) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted("Player 1");
|
||||
if (eamuse_get_game_keypads() > 1) {
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted("Player 2");
|
||||
}
|
||||
ImGui::TableNextRow();
|
||||
for (size_t i = 0; i < 2; i++) {
|
||||
if (eamuse_get_game_keypads() > (int)i) {
|
||||
ImGui::TableNextColumn();
|
||||
if (build_card(i) && this->loaded_card[i].has_value()) {
|
||||
insert_card_over_api(i, this->loaded_card[i].value());
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
ImGui::Spacing();
|
||||
ImGui::Spacing();
|
||||
|
||||
ImGui::TextColored(ImVec4(1, 0.7f, 0, 1), "Available cards");
|
||||
build_card_list();
|
||||
ImGui::Separator();
|
||||
ImGui::Spacing();
|
||||
@@ -48,44 +104,13 @@ namespace overlay::windows {
|
||||
build_card_editor();
|
||||
}
|
||||
|
||||
void CardManager::build_card() {
|
||||
ImGui::BeginDisabled(this->current_card == nullptr);
|
||||
// insert P1 button
|
||||
if (ImGui::Button("Insert P1")) {
|
||||
const auto card = this->current_card;
|
||||
uint8_t card_bin[8];
|
||||
if (card && card->id.length() == 16 && hex2bin(card->id.c_str(), card_bin)) {
|
||||
eamuse_card_insert(0, card_bin);
|
||||
}
|
||||
}
|
||||
|
||||
// insert P2 button
|
||||
if (eamuse_get_game_keypads() > 1) {
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Insert P2")) {
|
||||
const auto card = this->current_card;
|
||||
uint8_t card_bin[8];
|
||||
if (card && card->id.length() == 16 && hex2bin(card->id.c_str(), card_bin)) {
|
||||
eamuse_card_insert(1, card_bin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// edit selected card
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Edit Card")) {
|
||||
open_card_editor();
|
||||
}
|
||||
|
||||
ImGui::EndDisabled();
|
||||
|
||||
ImGui::Spacing();
|
||||
|
||||
// card ui
|
||||
if (this->current_card) {
|
||||
const auto card = this->current_card;
|
||||
const ImVec4 color(card->color[0], card->color[1], card->color[2], 1.f);
|
||||
float bg_luminance = (0.299f * card->color[0] + 0.587 * card->color[1] + 0.114 * card->color[2]);
|
||||
bool CardManager::build_card(int reader) {
|
||||
ImGui::PushID(reader);
|
||||
bool clicked = false;
|
||||
if (this->loaded_card[reader].has_value()) {
|
||||
const auto &card = this->loaded_card[reader].value();
|
||||
const ImVec4 color(card.color[0], card.color[1], card.color[2], 1.f);
|
||||
float bg_luminance = (0.299f * card.color[0] + 0.587 * card.color[1] + 0.114 * card.color[2]);
|
||||
|
||||
// text color
|
||||
ImVec4 text_color;
|
||||
@@ -101,22 +126,25 @@ namespace overlay::windows {
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, text_color);
|
||||
if (ImGui::Button(fmt::format(
|
||||
" {} \n {} {} {} {} ",
|
||||
card->name.empty() ? "<blank>" : card->name.substr(0, 19),
|
||||
card->id.substr(0, 4).c_str(),
|
||||
card->id.substr(4, 4).c_str(),
|
||||
card->id.substr(8, 4).c_str(),
|
||||
card->id.substr(12, 4).c_str()
|
||||
card.name.empty() ? "<blank>" : card.name.substr(0, 19),
|
||||
card.id.substr(0, 4).c_str(),
|
||||
card.id.substr(4, 4).c_str(),
|
||||
card.id.substr(8, 4).c_str(),
|
||||
card.id.substr(12, 4).c_str()
|
||||
).c_str())) {
|
||||
|
||||
open_card_editor();
|
||||
clicked = true;
|
||||
}
|
||||
ImGui::PopStyleColor(4);
|
||||
} else {
|
||||
ImGui::BeginDisabled();
|
||||
ImGui::Button(" <No card> \n xxxx xxxx xxxx xxxx ");
|
||||
ImGui::Button(" (No override set) \n"
|
||||
" xxxx xxxx xxxx xxxx ");
|
||||
ImGui::EndDisabled();
|
||||
ImGui::PopStyleColor(4);
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
return clicked;
|
||||
}
|
||||
|
||||
void CardManager::open_card_editor() {
|
||||
@@ -140,13 +168,18 @@ namespace overlay::windows {
|
||||
this->card_buffer,
|
||||
std::size(this->card_buffer),
|
||||
ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase);
|
||||
ImGui::EndDisabled();
|
||||
if (this->current_card == nullptr) {
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Generate")) {
|
||||
generate_ea_card(this->card_buffer);
|
||||
}
|
||||
} else {
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Copy")) {
|
||||
clipboard::copy_text(this->current_card->id);
|
||||
}
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
// name field
|
||||
ImGui::InputTextWithHint("Card Name", "Main Card",
|
||||
@@ -171,6 +204,18 @@ namespace overlay::windows {
|
||||
this->current_card->color[1] = this->color_buffer[1];
|
||||
this->current_card->color[2] = this->color_buffer[2];
|
||||
generate_search_string(this->current_card);
|
||||
|
||||
// ensure loaded cards are kept up to date
|
||||
// note: does not handle cases where multiple cards have the same ID
|
||||
for (size_t i = 0; i < 2; i++) {
|
||||
if (this->loaded_card[i].has_value() &&
|
||||
!this->loaded_card[i].value().read_only &&
|
||||
this->loaded_card[i].value().id == this->current_card->id) {
|
||||
this->loaded_card[i] = *this->current_card;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// create a new card
|
||||
CardEntry card {
|
||||
@@ -211,14 +256,54 @@ namespace overlay::windows {
|
||||
}
|
||||
}
|
||||
|
||||
void CardManager::build_card_selectable(CardEntry &card) {
|
||||
// generate card name
|
||||
std::string card_name = "";
|
||||
if (card.id.length() == 16) {
|
||||
card_name += card.id.substr(0, 4);
|
||||
card_name += " ";
|
||||
card_name += card.id.substr(4, 4);
|
||||
card_name += " ";
|
||||
card_name += card.id.substr(8, 4);
|
||||
card_name += " ";
|
||||
card_name += card.id.substr(12, 4);
|
||||
} else {
|
||||
card_name += card.id;
|
||||
}
|
||||
if (!card.name.empty()) {
|
||||
card_name += " - ";
|
||||
card_name += card.name;
|
||||
}
|
||||
|
||||
ImGui::PushID(&card);
|
||||
|
||||
// color button
|
||||
ImVec4 color(card.color[0], card.color[1], card.color[2], 1.f);
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, color);
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, color);
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, color);
|
||||
ImGui::SmallButton(" ");
|
||||
ImGui::PopStyleColor(3);
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
// selectable item
|
||||
if (ImGui::Selectable(card_name.c_str(), this->current_card == &card)) {
|
||||
this->current_card = &card;
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
void CardManager::build_card_list() {
|
||||
|
||||
// search for card
|
||||
//
|
||||
// setting ImGuiInputTextFlags_CallbackCharFilter and pressing escape doesn't cause below
|
||||
// to return true, making it necessary to provide a callback...
|
||||
ImGui::SetNextItemWidth(220);
|
||||
ImGui::SetNextItemWidth(240);
|
||||
if (ImGui::InputTextWithHint("", "Type here to search..", &this->search_filter)) {
|
||||
this->current_card = nullptr;
|
||||
this->search_filter_in_lower_case = strtolower(this->search_filter);
|
||||
}
|
||||
if (!this->search_filter.empty()) {
|
||||
@@ -227,11 +312,49 @@ namespace overlay::windows {
|
||||
this->search_filter.clear();
|
||||
this->search_filter_in_lower_case.clear();
|
||||
}
|
||||
} else {
|
||||
ImGui::SameLine();
|
||||
|
||||
// move selected up/down the list
|
||||
ImGui::BeginDisabled(this->current_card == nullptr);
|
||||
}
|
||||
|
||||
// toolbar
|
||||
|
||||
// set card as p1/p2
|
||||
for (size_t i = 0; i < 2; i++) {
|
||||
if (eamuse_get_game_keypads() > (int)i) {
|
||||
if (i != 0) {
|
||||
ImGui::SameLine();
|
||||
}
|
||||
ImGui::PushID(i);
|
||||
ImGui::BeginDisabled(this->current_card == nullptr);
|
||||
if (ImGui::Button(i == 0 ? "Load P1" : "Load P2") && this->current_card) {
|
||||
this->loaded_card[i] = *this->current_card;
|
||||
log_info(
|
||||
"cardmanager",
|
||||
"[P{}] update override and insert card: {} ({})",
|
||||
i+1,
|
||||
this->current_card->id,
|
||||
this->current_card->name
|
||||
);
|
||||
|
||||
// update override
|
||||
std::lock_guard<std::mutex> lock(CARD_OVERRIDES_LOCK);
|
||||
CARD_OVERRIDES[i] = this->current_card->id;
|
||||
|
||||
// insert card over api
|
||||
insert_card_over_api(i, this->loaded_card[i].value());
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
ImGui::PopID();
|
||||
}
|
||||
}
|
||||
|
||||
// edit selected card
|
||||
ImGui::SameLine();
|
||||
ImGui::BeginDisabled(this->current_card == nullptr || this->current_card->read_only);
|
||||
if (ImGui::Button("Edit")) {
|
||||
open_card_editor();
|
||||
}
|
||||
|
||||
// move selected up/down the list
|
||||
if (this->search_filter.empty()) {
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Move Up")) {
|
||||
for (auto it = this->cards.begin(); it != this->cards.end(); ++it) {
|
||||
@@ -254,60 +377,37 @@ namespace overlay::windows {
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
ImGui::Spacing();
|
||||
|
||||
// cards list
|
||||
// use all available vertical space, minus height of buttons, minus separator
|
||||
// use all available vertical space, minus height footer (a row of buttons and separator)
|
||||
if (ImGui::BeginChild(
|
||||
"cards",
|
||||
ImVec2(0, ImGui::GetContentRegionAvail().y - ImGui::GetFrameHeightWithSpacing() - 8.f))) {
|
||||
|
||||
// -card0 / -card1 override
|
||||
for (size_t i = 0; i < 2; i++) {
|
||||
if (card_cmd_overrides[i].has_value()) {
|
||||
build_card_selectable(card_cmd_overrides[i].value());
|
||||
}
|
||||
}
|
||||
|
||||
// cards from card manager JSON
|
||||
for (auto &card : this->cards) {
|
||||
|
||||
// get card name
|
||||
std::string card_name = "";
|
||||
if (card.id.length() == 16) {
|
||||
card_name += card.id.substr(0, 4);
|
||||
card_name += " ";
|
||||
card_name += card.id.substr(4, 4);
|
||||
card_name += " ";
|
||||
card_name += card.id.substr(8, 4);
|
||||
card_name += " ";
|
||||
card_name += card.id.substr(12, 4);
|
||||
} else {
|
||||
card_name += card.id;
|
||||
}
|
||||
if (!card.name.empty()) {
|
||||
card_name += " - ";
|
||||
card_name += card.name;
|
||||
}
|
||||
|
||||
|
||||
if (!this->search_filter_in_lower_case.empty() && !card.search_string.empty()) {
|
||||
const bool matched =
|
||||
card.search_string.find(this->search_filter_in_lower_case) != std::string::npos;
|
||||
|
||||
card.search_string.find(this->search_filter_in_lower_case) != std::string::npos;
|
||||
|
||||
if (!matched) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// draw entry
|
||||
ImGui::PushID(&card);
|
||||
|
||||
ImVec4 color(card.color[0], card.color[1], card.color[2], 1.f);
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, color);
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, color);
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, color);
|
||||
ImGui::SmallButton(" ");
|
||||
ImGui::PopStyleColor(3);
|
||||
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Selectable(card_name.c_str(), this->current_card == &card)) {
|
||||
this->current_card = &card;
|
||||
}
|
||||
ImGui::PopID();
|
||||
build_card_selectable(card);
|
||||
}
|
||||
}
|
||||
ImGui::EndChild();
|
||||
@@ -504,4 +604,11 @@ namespace overlay::windows {
|
||||
this->color_buffer[1] = g / 255.f;
|
||||
this->color_buffer[2] = b / 255.f;
|
||||
}
|
||||
|
||||
void CardManager::insert_card_over_api(int reader, CardEntry &card) {
|
||||
uint8_t card_bin[8];
|
||||
if (card.id.length() == 16 && hex2bin(card.id.c_str(), card_bin)) {
|
||||
eamuse_card_insert(reader, card_bin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
|
||||
#include "overlay/window.h"
|
||||
|
||||
@@ -10,6 +11,7 @@ namespace overlay::windows {
|
||||
std::string name = "unnamed";
|
||||
std::string id = "E004010000000000";
|
||||
std::string search_string = "";
|
||||
bool read_only = false;
|
||||
float color[3] {};
|
||||
};
|
||||
|
||||
@@ -29,7 +31,10 @@ namespace overlay::windows {
|
||||
char name_buffer[65] {};
|
||||
char card_buffer[17] {};
|
||||
float color_buffer[3] {};
|
||||
|
||||
std::optional<CardEntry> card_cmd_overrides[2];
|
||||
|
||||
std::optional<CardEntry> loaded_card[2];
|
||||
CardEntry *current_card = nullptr;
|
||||
|
||||
std::string search_filter = "";
|
||||
@@ -41,10 +46,13 @@ namespace overlay::windows {
|
||||
void generate_search_string(CardEntry *card);
|
||||
void generate_random_color();
|
||||
|
||||
void build_card();
|
||||
bool build_card(int reader);
|
||||
void open_card_editor();
|
||||
void build_card_editor();
|
||||
void build_card_list();
|
||||
void build_card_selectable(CardEntry &card);
|
||||
void build_footer();
|
||||
|
||||
void insert_card_over_api(int reader, CardEntry &card);
|
||||
};
|
||||
}
|
||||
|
||||
+1871
-1803
File diff suppressed because it is too large
Load Diff
@@ -178,9 +178,11 @@ namespace overlay::windows {
|
||||
static_cast<int>(ImGui::GetIO().DisplaySize.x),
|
||||
static_cast<int>(ImGui::GetIO().DisplaySize.y));
|
||||
|
||||
// removed for size (along with setting IMGUI_DISABLE_DEMO_WINDOWS
|
||||
// and IMGUI_DISABLE_DEBUG_TOOLS) - saves about 300kb in each
|
||||
// binary
|
||||
if (ImGui::Button("ImGui Debug Log")) {
|
||||
overlay::SHOW_DEBUG_LOG_WINDOW = !overlay::SHOW_DEBUG_LOG_WINDOW;
|
||||
}
|
||||
|
||||
// removed for size (IMGUI_DISABLE_DEMO_WINDOWS)
|
||||
|
||||
// metrics button
|
||||
// this->metrics_open |= ImGui::Button("Metrics Window");
|
||||
@@ -749,7 +751,7 @@ namespace overlay::windows {
|
||||
if (ImGui::CollapsingHeader("Touch")) {
|
||||
|
||||
// status
|
||||
ImGui::Text("Status: %s", is_touch_available() ? "available" : "unavailable");
|
||||
ImGui::Text("Status: %s", is_touch_available("Control::touch_view") ? "available" : "unavailable");
|
||||
|
||||
// touch points
|
||||
ImGui::SetNextItemOpen(true, ImGuiCond_Once);
|
||||
|
||||
@@ -206,7 +206,7 @@ namespace overlay::windows {
|
||||
bottom_right.x += overlay_content_top_left.x;
|
||||
bottom_right.y += overlay_content_top_left.y;
|
||||
ImGui::GetBackgroundDrawList()->AddImage(
|
||||
reinterpret_cast<void *>(this->texture),
|
||||
reinterpret_cast<ImTextureID>(this->texture),
|
||||
overlay_content_top_left,
|
||||
bottom_right);
|
||||
|
||||
|
||||
@@ -151,7 +151,7 @@ namespace overlay::windows {
|
||||
url_fetch_errors += fmt::format("WinHttpSendRequest failed: {}\n", gle);
|
||||
if (gle == 12175) {
|
||||
url_fetch_errors += "\nThis is ERROR_WINHTTP_SECURE_FAILURE - most likely TLS 1.1 / TLS 1.2 error on old OS versions.\n\n";
|
||||
url_fetch_errors += "Look up MSDN article on 'Update to enable TLS 1.1 and TLS 1.2 as default secure protocols in WinHTTP in Windows' for a fix.";
|
||||
url_fetch_errors += "Look up MSDN article on 'Update to enable TLS 1.1 and TLS 1.2 as default secure protocols in WinHTTP in Windows' for a fix.\n";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -183,7 +183,7 @@ namespace overlay::windows {
|
||||
statusCode,
|
||||
netutils::http_status_reason_phrase(statusCode));
|
||||
if (statusCode == 404) {
|
||||
url_fetch_errors += "(Patch server did not find any patches for this game version)";
|
||||
url_fetch_errors += "(Patch server did not find any patches for this game version)\n";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -550,7 +550,7 @@ namespace overlay::windows {
|
||||
ImGui::Text("Failed to import patches from URL.");
|
||||
if (!url_fetch_errors.empty()) {
|
||||
ImGui::TextUnformatted("");
|
||||
ImGui::PushTextWrapPos(ImGui::GetIO().DisplaySize.x * 0.5);
|
||||
ImGui::PushTextWrapPos(ImGui::GetIO().DisplaySize.x * 0.7);
|
||||
ImGui::TextUnformatted(url_fetch_errors.c_str());
|
||||
ImGui::PopTextWrapPos();
|
||||
}
|
||||
@@ -558,6 +558,12 @@ namespace overlay::windows {
|
||||
if (ImGui::Button("OK")) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
if (!url_fetch_errors.empty()) {
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Copy Error")) {
|
||||
clipboard::copy_text(url_fetch_errors);
|
||||
}
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
@@ -651,7 +657,7 @@ namespace overlay::windows {
|
||||
ImGui::TableNextColumn();
|
||||
if (!patch.caution.empty()) {
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::WarnMarker(nullptr, patch.caution.c_str());
|
||||
ImGui::WarnMarker(patch.description.c_str(), patch.caution.c_str());
|
||||
} else {
|
||||
ImGui::DummyMarker();
|
||||
}
|
||||
@@ -1517,16 +1523,44 @@ namespace overlay::windows {
|
||||
try {
|
||||
auto patches_json = getFromUrl(dll_name, json_path);
|
||||
if (!patches_json.empty()) {
|
||||
if (!fileutils::dir_exists(LOCAL_PATCHES_PATH))
|
||||
|
||||
// see if this is valid JSON
|
||||
Document doc_temp;
|
||||
doc_temp.Parse(patches_json.c_str());
|
||||
const auto error = doc_temp.GetParseError();
|
||||
if (error) {
|
||||
log_warning(
|
||||
"patchmanager",
|
||||
"remotely fetched JSON file parse error: {}",
|
||||
rapidjson::GetParseError_En(error));
|
||||
url_fetch_errors += fmt::format(
|
||||
"Invalid JSON received from remote URL.\n"
|
||||
"Your DLL version might not be supported.\n"
|
||||
"URL: {}\n"
|
||||
"JSON Parse Error: {}\n",
|
||||
json_path,
|
||||
rapidjson::GetParseError_En(error));
|
||||
return false;
|
||||
} else {
|
||||
log_info("patchmanager", "remotely fetched JSON was successfully parsed");
|
||||
}
|
||||
|
||||
// create patches dir
|
||||
if (!fileutils::dir_exists(LOCAL_PATCHES_PATH)) {
|
||||
fileutils::dir_create(LOCAL_PATCHES_PATH);
|
||||
}
|
||||
// save to file
|
||||
std::filesystem::path save_path = LOCAL_PATCHES_PATH / (identifier + ".json");
|
||||
fileutils::text_write(save_path, patches_json);
|
||||
log_info("patchmanager", "remotely fetched JSON saved to: {}", save_path.string());
|
||||
return true;
|
||||
} else {
|
||||
log_warning("patchmanager", "failed to fetch patches JSON for {}", dll_name);
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
log_warning("patchmanager", "exception occurred while loading remote patches JSON for {}: {}", dll_name, e.what());
|
||||
url_fetch_errors += fmt::format(
|
||||
"Exception while loading remote patches for {}: {}\n", dll_name, e.what());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -138,8 +138,15 @@ static void touch_initialize() {
|
||||
}
|
||||
SPICETOUCH_INITIALIZED = true;
|
||||
|
||||
if (!RI_MGR) {
|
||||
log_fatal(
|
||||
LOG_MODULE_NAME,
|
||||
"touch_initialize() - RI Manager not available, called too early! "
|
||||
"This is a BUG in spice, please file a bug report with log.txt.");
|
||||
}
|
||||
|
||||
// initialize handler
|
||||
if (RI_MGR && rawinput::touch::is_enabled(RI_MGR.get())) {
|
||||
if (rawinput::touch::is_enabled(RI_MGR.get())) {
|
||||
TOUCH_HANDLER = new RawInputTouchHandler();
|
||||
} else if (Win8Handler::is_available()) {
|
||||
TOUCH_HANDLER = new Win8Handler();
|
||||
@@ -166,13 +173,26 @@ static inline void touch_unregister_window(HWND hWnd) {
|
||||
}
|
||||
}
|
||||
|
||||
bool is_touch_available() {
|
||||
bool is_touch_available(LPCSTR caller) {
|
||||
static bool called_once = false;
|
||||
|
||||
if (!RI_MGR) {
|
||||
log_fatal(
|
||||
LOG_MODULE_NAME,
|
||||
"is_touch_available({}) - RI Manager not available, called too early! "
|
||||
"This is a BUG in spice, please file a bug report with log.txt.",
|
||||
caller);
|
||||
}
|
||||
|
||||
// initialize touch handler
|
||||
touch_initialize();
|
||||
|
||||
// Check if a touch handler has been set. No need to call `is_available` here
|
||||
// as `touch_initialize` does that.
|
||||
if (!called_once) {
|
||||
log_misc("touch", "is_touch_available called by: {}, returning {}",
|
||||
caller, (TOUCH_HANDLER != nullptr) ? "TRUE" : "false");
|
||||
called_once = true;
|
||||
}
|
||||
|
||||
return TOUCH_HANDLER != nullptr;
|
||||
}
|
||||
|
||||
@@ -202,7 +222,7 @@ static LRESULT CALLBACK SpiceTouchWndProc(HWND hWnd, UINT msg, WPARAM wParam, LP
|
||||
SPICETOUCH_REGISTERED_TOUCH = true;
|
||||
|
||||
// check if touch is available
|
||||
if (is_touch_available()) {
|
||||
if (is_touch_available("SpiceTouchWndProc")) {
|
||||
|
||||
// notify the handler of our window
|
||||
TOUCH_HANDLER->window_register(hWnd);
|
||||
|
||||
@@ -27,7 +27,7 @@ extern int SPICETOUCH_TOUCH_Y;
|
||||
extern int SPICETOUCH_TOUCH_WIDTH;
|
||||
extern int SPICETOUCH_TOUCH_HEIGHT;
|
||||
|
||||
bool is_touch_available();
|
||||
bool is_touch_available(LPCSTR caller);
|
||||
|
||||
void touch_attach_wnd(HWND hWnd);
|
||||
void touch_attach_dx_hook();
|
||||
|
||||
Reference in New Issue
Block a user