mirror of
https://github.com/SFML/SFML.git
synced 2024-11-24 20:31:05 +08:00
Merge branch 'master' of https://github.com/SFML/SFML into comparisonbenchmark
This commit is contained in:
commit
bb0f88594f
7
.github/workflows/ci.yml
vendored
7
.github/workflows/ci.yml
vendored
@ -32,6 +32,7 @@ jobs:
|
||||
- { name: Windows VS2019 x64, os: windows-2019, flags: -DSFML_USE_MESA3D=ON -GNinja }
|
||||
- { name: Windows VS2022 x86, os: windows-2022, flags: -DSFML_USE_MESA3D=ON -GNinja }
|
||||
- { name: Windows VS2022 x64, os: windows-2022, flags: -DSFML_USE_MESA3D=ON -GNinja }
|
||||
- { name: Windows VS2022 arm64, os: windows-2022, flags: -DSFML_USE_MESA3D=OFF -GNinja -DSFML_BUILD_TEST_SUITE=OFF }
|
||||
- { name: Windows VS2022 ClangCL MSBuild, os: windows-2022, flags: -DSFML_USE_MESA3D=ON -T ClangCL } # ninja doesn't support specifying the toolset, so use the ClangCL toolset to test building with MSBuild as well
|
||||
- { name: Windows VS2022 OpenGL ES, os: windows-2022, flags: -DSFML_USE_MESA3D=ON -DSFML_OPENGL_ES=ON -GNinja }
|
||||
- { name: Windows VS2022 Unity, os: windows-2022, flags: -DSFML_USE_MESA3D=ON -DCMAKE_UNITY_BUILD=ON -GNinja }
|
||||
@ -117,7 +118,7 @@ jobs:
|
||||
if: contains(matrix.platform.name, 'Windows VS') && !contains(matrix.platform.name, 'MSBuild')
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
arch: ${{ contains(matrix.platform.name, 'x86') && 'x86' || 'x64' }}
|
||||
arch: ${{ contains(matrix.platform.name, 'arm64') && 'amd64_arm64' || contains(matrix.platform.name, 'x86') && 'x86' || 'x64' }}
|
||||
|
||||
# Although the CMake configuration will run with 3.24 on Windows and 3.22
|
||||
# elsewhere, we install 3.25 on Windows in order to support specifying
|
||||
@ -237,7 +238,7 @@ jobs:
|
||||
find build/bin -name test-sfml-window -or -name test-sfml-window.exe -exec sh -c "{} *sf::Context* --section=\"Version String\" --success | grep OpenGL" \;
|
||||
|
||||
- name: Test (Windows)
|
||||
if: runner.os == 'Windows' && !contains(matrix.platform.name, 'MinGW')
|
||||
if: runner.os == 'Windows' && !contains(matrix.platform.name, 'MinGW') && !contains(matrix.platform.name, 'arm64')
|
||||
run: cmake --build build --target runtests --config ${{ matrix.type.name == 'Debug' && 'Debug' || 'Release' }}
|
||||
|
||||
- name: Test (Linux/macOS/MinGW)
|
||||
@ -291,7 +292,7 @@ jobs:
|
||||
ctest --test-dir build --output-on-failure -C ${{ matrix.type.name == 'Debug' && 'Debug' || 'Release' }} --repeat until-pass:3
|
||||
|
||||
- name: Upload Coverage Report to Coveralls
|
||||
if: matrix.type.name == 'Debug' && github.repository == 'SFML/SFML' && !contains(matrix.platform.name, 'iOS') && !contains(matrix.platform.name, 'Android') # Disable upload in forks
|
||||
if: matrix.type.name == 'Debug' && github.repository == 'SFML/SFML' && !contains(matrix.platform.name, 'iOS') && !contains(matrix.platform.name, 'Android') && !contains(matrix.platform.name, 'arm64') # Disable upload in forks
|
||||
uses: coverallsapp/github-action@v2
|
||||
with:
|
||||
file: ./build/coverage.out
|
||||
|
@ -6,9 +6,7 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
|
||||
set(OPENGL_ES 0)
|
||||
|
||||
# detect the architecture
|
||||
if(${CMAKE_GENERATOR_PLATFORM} MATCHES "ARM64")
|
||||
set(ARCH_ARM64 1)
|
||||
elseif("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "" AND ${CMAKE_SYSTEM_PROCESSOR} MATCHES "ARM64")
|
||||
if("${CMAKE_GENERATOR_PLATFORM}" MATCHES "ARM64" OR "${MSVC_CXX_ARCHITECTURE_ID}" MATCHES "ARM64" OR "${CMAKE_SYSTEM_PROCESSOR}" MATCHES "ARM64")
|
||||
set(ARCH_ARM64 1)
|
||||
elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
set(ARCH_X86 1)
|
||||
|
@ -4,11 +4,11 @@ set(MESA3D_SHA256 "FEF8A643689414A70347AE8027D24674DEFD85E8D6428C8A9D4145BB3F44A
|
||||
get_filename_component(MESA3D_ARCHIVE "${MESA3D_URL}" NAME)
|
||||
get_filename_component(MESA3D_ARCHIVE_DIRECTORY "${MESA3D_URL}" NAME_WLE)
|
||||
|
||||
if(${ARCH_X64})
|
||||
if(ARCH_X64)
|
||||
set(MESA3D_ARCH "x64")
|
||||
elseif(${ARCH_X86})
|
||||
elseif(ARCH_X86)
|
||||
set(MESA3D_ARCH "x86")
|
||||
else()
|
||||
elseif(SFML_USE_MESA3D)
|
||||
message(FATAL_ERROR "Mesa 3D does currently not support the target architecture.")
|
||||
endif()
|
||||
|
||||
@ -61,7 +61,7 @@ if(SFML_OS_WINDOWS AND SFML_USE_MESA3D)
|
||||
add_custom_target(install-mesa3d DEPENDS ${MESA3D_INSTALLED_FILES})
|
||||
|
||||
set_target_properties(install-mesa3d PROPERTIES EXCLUDE_FROM_ALL ON)
|
||||
elseif(SFML_OS_WINDOWS AND EXISTS "${MESA3D_ARCH_PATH}")
|
||||
elseif(SFML_OS_WINDOWS AND MESA3D_ARCH AND EXISTS "${MESA3D_ARCH_PATH}")
|
||||
# we are removing the files
|
||||
|
||||
# compile a list of file names that we have to remove
|
||||
|
@ -24,12 +24,10 @@
|
||||
namespace
|
||||
{
|
||||
// Width and height of the application window
|
||||
const unsigned int windowWidth = 800;
|
||||
const unsigned int windowHeight = 600;
|
||||
const sf::Vector2u windowSize(800, 600);
|
||||
|
||||
// Resolution of the generated terrain
|
||||
const unsigned int resolutionX = 800;
|
||||
const unsigned int resolutionY = 600;
|
||||
const sf::Vector2u resolution(800, 600);
|
||||
|
||||
// Thread pool parameters
|
||||
const unsigned int threadCount = 4;
|
||||
@ -68,7 +66,7 @@ float edgeDropoffExponent = 1.5f;
|
||||
float snowcapHeight = 0.6f;
|
||||
|
||||
// Terrain lighting parameters
|
||||
float heightFactor = windowHeight / 2.0f;
|
||||
float heightFactor = static_cast<float>(windowSize.y) / 2.0f;
|
||||
float heightFlatten = 3.0f;
|
||||
float lightFactor = 0.7f;
|
||||
} // namespace
|
||||
@ -88,7 +86,7 @@ void generateTerrain(sf::Vertex* vertexBuffer);
|
||||
int main()
|
||||
{
|
||||
// Create the window of the application
|
||||
sf::RenderWindow window(sf::VideoMode({windowWidth, windowHeight}), "SFML Island", sf::Style::Titlebar | sf::Style::Close);
|
||||
sf::RenderWindow window(sf::VideoMode(windowSize), "SFML Island", sf::Style::Titlebar | sf::Style::Close);
|
||||
window.setVerticalSyncEnabled(true);
|
||||
|
||||
const sf::Font font("resources/tuffy.ttf");
|
||||
@ -133,14 +131,14 @@ int main()
|
||||
}
|
||||
|
||||
// Create our VertexBuffer with enough space to hold all the terrain geometry
|
||||
if (!terrain.create(resolutionX * resolutionY * 6))
|
||||
if (!terrain.create(resolution.x * resolution.y * 6))
|
||||
{
|
||||
std::cerr << "Failed to create vertex buffer" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Resize the staging buffer to be able to hold all the terrain geometry
|
||||
terrainStagingBuffer.resize(resolutionX * resolutionY * 6);
|
||||
terrainStagingBuffer.resize(resolution.x * resolution.y * 6);
|
||||
|
||||
// Generate the initial terrain
|
||||
generateTerrain(terrainStagingBuffer.data());
|
||||
@ -152,7 +150,7 @@ int main()
|
||||
}
|
||||
|
||||
// Center the status text
|
||||
statusText.setPosition((sf::Vector2f(windowWidth, windowHeight) - statusText.getLocalBounds().size) / 2.f);
|
||||
statusText.setPosition((sf::Vector2f(windowSize) - statusText.getLocalBounds().size) / 2.f);
|
||||
|
||||
// Set up an array of pointers to our settings for arrow navigation
|
||||
constexpr std::array<Setting, 9> settings = {
|
||||
@ -279,58 +277,45 @@ int main()
|
||||
/// Get the terrain elevation at the given coordinates.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
float getElevation(float x, float y)
|
||||
float getElevation(sf::Vector2u position)
|
||||
{
|
||||
x = x / resolutionX - 0.5f;
|
||||
y = y / resolutionY - 0.5f;
|
||||
const sf::Vector2f normalized = sf::Vector2f(position).componentWiseDiv(sf::Vector2f(resolution)) -
|
||||
sf::Vector2f(0.5f, 0.5f);
|
||||
|
||||
float elevation = 0.0f;
|
||||
|
||||
for (int i = 0; i < perlinOctaves; ++i)
|
||||
{
|
||||
elevation += stb_perlin_noise3(x * perlinFrequency * static_cast<float>(std::pow(perlinFrequencyBase, i)),
|
||||
y * perlinFrequency * static_cast<float>(std::pow(perlinFrequencyBase, i)),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0) *
|
||||
const sf::Vector2f scaled = normalized * perlinFrequency * static_cast<float>(std::pow(perlinFrequencyBase, i));
|
||||
elevation += stb_perlin_noise3(scaled.x, scaled.y, 0, 0, 0, 0) *
|
||||
static_cast<float>(std::pow(perlinFrequencyBase, -i));
|
||||
}
|
||||
|
||||
elevation = (elevation + 1.f) / 2.f;
|
||||
|
||||
const float distance = 2.0f * std::sqrt(x * x + y * y);
|
||||
const float distance = 2.0f * normalized.length();
|
||||
elevation = (elevation + heightBase) * (1.0f - edgeFactor * std::pow(distance, edgeDropoffExponent));
|
||||
elevation = std::clamp(elevation, 0.0f, 1.0f);
|
||||
|
||||
return elevation;
|
||||
}
|
||||
|
||||
float getElevation(unsigned int x, unsigned int y)
|
||||
{
|
||||
return getElevation(static_cast<float>(x), static_cast<float>(y));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the terrain moisture at the given coordinates.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
float getMoisture(float x, float y)
|
||||
float getMoisture(sf::Vector2u position)
|
||||
{
|
||||
x = x / resolutionX - 0.5f;
|
||||
y = y / resolutionY - 0.5f;
|
||||
const sf::Vector2f normalized = sf::Vector2f(position).componentWiseDiv(sf::Vector2f(resolution)) -
|
||||
sf::Vector2f(0.5f, 0.5f);
|
||||
const sf::Vector2f transformed = normalized * 4.f + sf::Vector2f(0.5f, 0.5f);
|
||||
|
||||
const float moisture = stb_perlin_noise3(x * 4.f + 0.5f, y * 4.f + 0.5f, 0, 0, 0, 0);
|
||||
const float moisture = stb_perlin_noise3(transformed.x, transformed.y, 0, 0, 0, 0);
|
||||
|
||||
return (moisture + 1.f) / 2.f;
|
||||
}
|
||||
|
||||
float getMoisture(unsigned int x, unsigned int y)
|
||||
{
|
||||
return getMoisture(static_cast<float>(x), static_cast<float>(y));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the lowlands terrain color for the given moisture.
|
||||
@ -372,18 +357,16 @@ sf::Color getHighlandsTerrainColor(float elevation, float moisture)
|
||||
{
|
||||
const sf::Color lowlandsColor = getLowlandsTerrainColor(moisture);
|
||||
|
||||
sf::Color color = moisture < 0.6f ? sf::Color(112, 128, 144)
|
||||
const sf::Color color = moisture < 0.6f ? sf::Color(112, 128, 144)
|
||||
: colorFromFloats(112 + (110 * (moisture - 0.6f) / 0.4f),
|
||||
128 + (56 * (moisture - 0.6f) / 0.4f),
|
||||
144 - (9 * (moisture - 0.6f) / 0.4f));
|
||||
|
||||
const float factor = std::min((elevation - 0.4f) / 0.1f, 1.f);
|
||||
|
||||
color.r = static_cast<std::uint8_t>(lowlandsColor.r * (1.f - factor) + color.r * factor);
|
||||
color.g = static_cast<std::uint8_t>(lowlandsColor.g * (1.f - factor) + color.g * factor);
|
||||
color.b = static_cast<std::uint8_t>(lowlandsColor.b * (1.f - factor) + color.b * factor);
|
||||
|
||||
return color;
|
||||
return colorFromFloats(lowlandsColor.r * (1.f - factor) + color.r * factor,
|
||||
lowlandsColor.g * (1.f - factor) + color.g * factor,
|
||||
lowlandsColor.b * (1.f - factor) + color.b * factor);
|
||||
}
|
||||
|
||||
|
||||
@ -396,15 +379,13 @@ sf::Color getSnowcapTerrainColor(float elevation, float moisture)
|
||||
{
|
||||
const sf::Color highlandsColor = getHighlandsTerrainColor(elevation, moisture);
|
||||
|
||||
sf::Color color = sf::Color::White;
|
||||
const sf::Color color = sf::Color::White;
|
||||
|
||||
const float factor = std::min((elevation - snowcapHeight) / 0.05f, 1.f);
|
||||
|
||||
color.r = static_cast<std::uint8_t>(highlandsColor.r * (1.f - factor) + color.r * factor);
|
||||
color.g = static_cast<std::uint8_t>(highlandsColor.g * (1.f - factor) + color.g * factor);
|
||||
color.b = static_cast<std::uint8_t>(highlandsColor.b * (1.f - factor) + color.b * factor);
|
||||
|
||||
return color;
|
||||
return colorFromFloats(highlandsColor.r * (1.f - factor) + color.r * factor,
|
||||
highlandsColor.g * (1.f - factor) + color.g * factor,
|
||||
highlandsColor.b * (1.f - factor) + color.b * factor);
|
||||
}
|
||||
|
||||
|
||||
@ -446,9 +427,7 @@ sf::Vector2f computeNormal(float left, float right, float bottom, float top)
|
||||
const sf::Vector3f deltaX(1, 0, (std::pow(right, heightFlatten) - std::pow(left, heightFlatten)) * heightFactor);
|
||||
const sf::Vector3f deltaY(0, 1, (std::pow(top, heightFlatten) - std::pow(bottom, heightFlatten)) * heightFactor);
|
||||
|
||||
sf::Vector3f crossProduct(deltaX.y * deltaY.z - deltaX.z * deltaY.y,
|
||||
deltaX.z * deltaY.x - deltaX.x * deltaY.z,
|
||||
deltaX.x * deltaY.y - deltaX.y * deltaY.x);
|
||||
sf::Vector3f crossProduct = deltaX.cross(deltaY);
|
||||
|
||||
// Scale cross product to make z component 1.0f so we can drop it
|
||||
crossProduct /= crossProduct.z;
|
||||
@ -458,6 +437,26 @@ sf::Vector2f computeNormal(float left, float right, float bottom, float top)
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Compute the vertex representing the terrain at the given
|
||||
/// coordinates.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
const auto scalingFactors = sf::Vector2f(windowSize).componentWiseDiv(sf::Vector2f(resolution));
|
||||
|
||||
sf::Vertex computeVertex(sf::Vector2u position)
|
||||
{
|
||||
sf::Vertex vertex;
|
||||
vertex.position = sf::Vector2f(position).componentWiseMul(scalingFactors);
|
||||
vertex.color = getTerrainColor(getElevation(position), getMoisture(position));
|
||||
vertex.texCoords = computeNormal(getElevation(position - sf::Vector2u(1, 0)),
|
||||
getElevation(position + sf::Vector2u(1, 0)),
|
||||
getElevation(position + sf::Vector2u(0, 1)),
|
||||
getElevation(position - sf::Vector2u(0, 1)));
|
||||
return vertex;
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Process a terrain generation work item. Use the vector
|
||||
/// of vertices as scratch memory and upload the data to
|
||||
@ -466,23 +465,20 @@ sf::Vector2f computeNormal(float left, float right, float bottom, float top)
|
||||
////////////////////////////////////////////////////////////
|
||||
void processWorkItem(std::vector<sf::Vertex>& vertices, const WorkItem& workItem)
|
||||
{
|
||||
const unsigned int rowBlockSize = (resolutionY / blockCount) + 1;
|
||||
const unsigned int rowBlockSize = (resolution.y / blockCount) + 1;
|
||||
const unsigned int rowStart = rowBlockSize * workItem.index;
|
||||
|
||||
if (rowStart >= resolutionY)
|
||||
if (rowStart >= resolution.y)
|
||||
return;
|
||||
|
||||
const unsigned int rowEnd = std::min(rowStart + rowBlockSize, resolutionY);
|
||||
const unsigned int rowEnd = std::min(rowStart + rowBlockSize, resolution.y);
|
||||
const unsigned int rowCount = rowEnd - rowStart;
|
||||
|
||||
const float scalingFactorX = float{windowWidth} / float{resolutionX};
|
||||
const float scalingFactorY = float{windowHeight} / float{resolutionY};
|
||||
|
||||
for (unsigned int y = rowStart; y < rowEnd; ++y)
|
||||
{
|
||||
for (unsigned int x = 0; x < resolutionX; ++x)
|
||||
for (unsigned int x = 0; x < resolution.x; ++x)
|
||||
{
|
||||
const unsigned int arrayIndexBase = ((y - rowStart) * resolutionX + x) * 6;
|
||||
const unsigned int arrayIndexBase = ((y - rowStart) * resolution.x + x) * 6;
|
||||
|
||||
// Top left corner (first triangle)
|
||||
if (x > 0)
|
||||
@ -491,17 +487,11 @@ void processWorkItem(std::vector<sf::Vertex>& vertices, const WorkItem& workItem
|
||||
}
|
||||
else if (y > rowStart)
|
||||
{
|
||||
vertices[arrayIndexBase + 0] = vertices[arrayIndexBase - resolutionX * 6 + 1];
|
||||
vertices[arrayIndexBase + 0] = vertices[arrayIndexBase - resolution.x * 6 + 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
vertices[arrayIndexBase + 0].position = sf::Vector2f(static_cast<float>(x) * scalingFactorX,
|
||||
static_cast<float>(y) * scalingFactorY);
|
||||
vertices[arrayIndexBase + 0].color = getTerrainColor(getElevation(x, y), getMoisture(x, y));
|
||||
vertices[arrayIndexBase + 0].texCoords = computeNormal(getElevation(x - 1, y),
|
||||
getElevation(x + 1, y),
|
||||
getElevation(x, y + 1),
|
||||
getElevation(x, y - 1));
|
||||
vertices[arrayIndexBase + 0] = computeVertex({x, y});
|
||||
}
|
||||
|
||||
// Bottom left corner (first triangle)
|
||||
@ -511,23 +501,11 @@ void processWorkItem(std::vector<sf::Vertex>& vertices, const WorkItem& workItem
|
||||
}
|
||||
else
|
||||
{
|
||||
vertices[arrayIndexBase + 1].position = sf::Vector2f(static_cast<float>(x) * scalingFactorX,
|
||||
static_cast<float>(y + 1) * scalingFactorY);
|
||||
vertices[arrayIndexBase + 1].color = getTerrainColor(getElevation(x, y + 1), getMoisture(x, y + 1));
|
||||
vertices[arrayIndexBase + 1].texCoords = computeNormal(getElevation(x - 1, y + 1),
|
||||
getElevation(x + 1, y + 1),
|
||||
getElevation(x, y + 2),
|
||||
getElevation(x, y));
|
||||
vertices[arrayIndexBase + 1] = computeVertex({x, y + 1});
|
||||
}
|
||||
|
||||
// Bottom right corner (first triangle)
|
||||
vertices[arrayIndexBase + 2].position = sf::Vector2f(static_cast<float>(x + 1) * scalingFactorX,
|
||||
static_cast<float>(y + 1) * scalingFactorY);
|
||||
vertices[arrayIndexBase + 2].color = getTerrainColor(getElevation(x + 1, y + 1), getMoisture(x + 1, y + 1));
|
||||
vertices[arrayIndexBase + 2].texCoords = computeNormal(getElevation(x, y + 1),
|
||||
getElevation(x + 2, y + 1),
|
||||
getElevation(x + 1, y + 2),
|
||||
getElevation(x + 1, y));
|
||||
vertices[arrayIndexBase + 2] = computeVertex({x + 1, y + 1});
|
||||
|
||||
// Top left corner (second triangle)
|
||||
vertices[arrayIndexBase + 3] = vertices[arrayIndexBase + 0];
|
||||
@ -538,25 +516,19 @@ void processWorkItem(std::vector<sf::Vertex>& vertices, const WorkItem& workItem
|
||||
// Top right corner (second triangle)
|
||||
if (y > rowStart)
|
||||
{
|
||||
vertices[arrayIndexBase + 5] = vertices[arrayIndexBase - resolutionX * 6 + 2];
|
||||
vertices[arrayIndexBase + 5] = vertices[arrayIndexBase - resolution.x * 6 + 2];
|
||||
}
|
||||
else
|
||||
{
|
||||
vertices[arrayIndexBase + 5].position = sf::Vector2f(static_cast<float>(x + 1) * scalingFactorX,
|
||||
static_cast<float>(y) * scalingFactorY);
|
||||
vertices[arrayIndexBase + 5].color = getTerrainColor(getElevation(x + 1, y), getMoisture(x + 1, y));
|
||||
vertices[arrayIndexBase + 5].texCoords = computeNormal(getElevation(x, y),
|
||||
getElevation(x + 2, y),
|
||||
getElevation(x + 1, y + 1),
|
||||
getElevation(x + 1, y - 1));
|
||||
vertices[arrayIndexBase + 5] = computeVertex({x + 1, y});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the resulting geometry from our thread-local buffer into the target buffer
|
||||
std::memcpy(workItem.targetBuffer + (resolutionX * rowStart * 6),
|
||||
std::memcpy(workItem.targetBuffer + (resolution.x * rowStart * 6),
|
||||
vertices.data(),
|
||||
sizeof(sf::Vertex) * resolutionX * rowCount * 6);
|
||||
sizeof(sf::Vertex) * resolution.x * rowCount * 6);
|
||||
}
|
||||
|
||||
|
||||
@ -568,9 +540,9 @@ void processWorkItem(std::vector<sf::Vertex>& vertices, const WorkItem& workItem
|
||||
////////////////////////////////////////////////////////////
|
||||
void threadFunction()
|
||||
{
|
||||
const unsigned int rowBlockSize = (resolutionY / blockCount) + 1;
|
||||
const unsigned int rowBlockSize = (resolution.y / blockCount) + 1;
|
||||
|
||||
std::vector<sf::Vertex> vertices(resolutionX * rowBlockSize * 6);
|
||||
std::vector<sf::Vertex> vertices(resolution.x * rowBlockSize * 6);
|
||||
|
||||
WorkItem workItem = {nullptr, 0};
|
||||
|
||||
|
@ -346,11 +346,11 @@ private:
|
||||
/// {
|
||||
/// // Open the source and get audio settings
|
||||
/// ...
|
||||
/// unsigned int channelCount = ...;
|
||||
/// unsigned int sampleRate = ...;
|
||||
/// unsigned int channelCount = 2; // Stereo
|
||||
/// unsigned int sampleRate = 44100; // 44100 Hz
|
||||
///
|
||||
/// // Initialize the stream -- important!
|
||||
/// initialize(channelCount, sampleRate);
|
||||
/// initialize(channelCount, sampleRate, {sf::SoundChannel::FrontLeft, sf::SoundChannel::FrontRight});
|
||||
/// return true;
|
||||
/// }
|
||||
///
|
||||
|
@ -180,9 +180,8 @@ public:
|
||||
/// If \a `state` is `State::Fullscreen`, then \a `mode` must be
|
||||
/// a valid video mode.
|
||||
///
|
||||
/// The last parameter is an optional structure specifying
|
||||
/// advanced OpenGL context settings such as anti-aliasing,
|
||||
/// depth-buffer bits, etc.
|
||||
/// The last parameter is a structure specifying advanced OpenGL
|
||||
/// context settings such as anti-aliasing, depth-buffer bits, etc.
|
||||
///
|
||||
/// \param mode Video mode to use (defines the width, height and depth of the rendering area of the window)
|
||||
/// \param title Title of the window
|
||||
@ -193,6 +192,38 @@ public:
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual void create(VideoMode mode, const String& title, std::uint32_t style, State state, const ContextSettings& settings);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create (or recreate) the window
|
||||
///
|
||||
/// If the window was already created, it closes it first.
|
||||
/// If \a `state` is `State::Fullscreen`, then \a `mode` must be
|
||||
/// a valid video mode.
|
||||
///
|
||||
/// \param mode Video mode to use (defines the width, height and depth of the rendering area of the window)
|
||||
/// \param title Title of the window
|
||||
/// \param state %Window state
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void create(VideoMode mode, const String& title, State state) override;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create (or recreate) the window
|
||||
///
|
||||
/// If the window was already created, it closes it first.
|
||||
/// If \a `state` is `State::Fullscreen`, then \a `mode` must be
|
||||
/// a valid video mode.
|
||||
///
|
||||
/// The last parameter is a structure specifying advanced OpenGL
|
||||
/// context settings such as anti-aliasing, depth-buffer bits, etc.
|
||||
///
|
||||
/// \param mode Video mode to use (defines the width, height and depth of the rendering area of the window)
|
||||
/// \param title Title of the window
|
||||
/// \param state %Window state
|
||||
/// \param settings Additional settings for the underlying OpenGL context
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual void create(VideoMode mode, const String& title, State state, const ContextSettings& settings);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create (or recreate) the window from an existing control
|
||||
///
|
||||
|
@ -157,6 +157,20 @@ public:
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual void create(VideoMode mode, const String& title, std::uint32_t style = Style::Default, State state = State::Windowed);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create (or recreate) the window
|
||||
///
|
||||
/// If the window was already created, it closes it first.
|
||||
/// If \a `state` is `State::Fullscreen`, then \a `mode` must be
|
||||
/// a valid video mode.
|
||||
///
|
||||
/// \param mode Video mode to use (defines the width, height and depth of the rendering area of the window)
|
||||
/// \param title Title of the window
|
||||
/// \param state %Window state
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual void create(VideoMode mode, const String& title, State state);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create (or recreate) the window from an existing control
|
||||
///
|
||||
|
@ -362,13 +362,10 @@ std::uint64_t SoundFileReaderFlac::read(std::int16_t* samples, std::uint64_t max
|
||||
if (left > maxCount)
|
||||
{
|
||||
// There are more leftovers than needed
|
||||
std::copy(m_clientData.leftovers.begin(),
|
||||
m_clientData.leftovers.begin() + static_cast<std::vector<std::int16_t>::difference_type>(maxCount),
|
||||
samples);
|
||||
std::vector<std::int16_t> leftovers(m_clientData.leftovers.begin() +
|
||||
static_cast<std::vector<std::int16_t>::difference_type>(maxCount),
|
||||
const auto signedMaxCount = static_cast<std::vector<std::int16_t>::difference_type>(maxCount);
|
||||
std::copy(m_clientData.leftovers.begin(), m_clientData.leftovers.begin() + signedMaxCount, samples);
|
||||
m_clientData.leftovers = std::vector<std::int16_t>(m_clientData.leftovers.begin() + signedMaxCount,
|
||||
m_clientData.leftovers.end());
|
||||
m_clientData.leftovers.swap(leftovers);
|
||||
return maxCount;
|
||||
}
|
||||
|
||||
|
@ -31,81 +31,52 @@
|
||||
#include <SFML/System/Err.hpp>
|
||||
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace sf::priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
void glCheckError(const std::filesystem::path& file, unsigned int line, std::string_view expression)
|
||||
bool glCheckError(const std::filesystem::path& file, unsigned int line, std::string_view expression)
|
||||
{
|
||||
// Get the last error
|
||||
const GLenum errorCode = glGetError();
|
||||
|
||||
if (errorCode != GL_NO_ERROR)
|
||||
const auto logError = [&](const char* error, const char* description)
|
||||
{
|
||||
std::string error = "Unknown error";
|
||||
std::string description = "No description";
|
||||
|
||||
// Decode the error code
|
||||
switch (errorCode)
|
||||
{
|
||||
case GL_INVALID_ENUM:
|
||||
{
|
||||
error = "GL_INVALID_ENUM";
|
||||
description = "An unacceptable value has been specified for an enumerated argument.";
|
||||
break;
|
||||
}
|
||||
|
||||
case GL_INVALID_VALUE:
|
||||
{
|
||||
error = "GL_INVALID_VALUE";
|
||||
description = "A numeric argument is out of range.";
|
||||
break;
|
||||
}
|
||||
|
||||
case GL_INVALID_OPERATION:
|
||||
{
|
||||
error = "GL_INVALID_OPERATION";
|
||||
description = "The specified operation is not allowed in the current state.";
|
||||
break;
|
||||
}
|
||||
|
||||
case GL_STACK_OVERFLOW:
|
||||
{
|
||||
error = "GL_STACK_OVERFLOW";
|
||||
description = "This command would cause a stack overflow.";
|
||||
break;
|
||||
}
|
||||
|
||||
case GL_STACK_UNDERFLOW:
|
||||
{
|
||||
error = "GL_STACK_UNDERFLOW";
|
||||
description = "This command would cause a stack underflow.";
|
||||
break;
|
||||
}
|
||||
|
||||
case GL_OUT_OF_MEMORY:
|
||||
{
|
||||
error = "GL_OUT_OF_MEMORY";
|
||||
description = "There is not enough memory left to execute the command.";
|
||||
break;
|
||||
}
|
||||
|
||||
case GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION:
|
||||
{
|
||||
error = "GL_INVALID_FRAMEBUFFER_OPERATION";
|
||||
description = "The object bound to FRAMEBUFFER_BINDING is not \"framebuffer complete\".";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Log the error
|
||||
err() << "An internal OpenGL call failed in " << file.filename() << "(" << line << ")."
|
||||
<< "\nExpression:\n " << expression << "\nError description:\n " << error << "\n " << description << '\n'
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
switch (glGetError())
|
||||
{
|
||||
case GL_NO_ERROR:
|
||||
return true;
|
||||
|
||||
case GL_INVALID_ENUM:
|
||||
return logError("GL_INVALID_ENUM", "An unacceptable value has been specified for an enumerated argument.");
|
||||
|
||||
case GL_INVALID_VALUE:
|
||||
return logError("GL_INVALID_VALUE", "A numeric argument is out of range.");
|
||||
|
||||
case GL_INVALID_OPERATION:
|
||||
return logError("GL_INVALID_OPERATION", "The specified operation is not allowed in the current state.");
|
||||
|
||||
case GL_STACK_OVERFLOW:
|
||||
return logError("GL_STACK_OVERFLOW", "This command would cause a stack overflow.");
|
||||
|
||||
case GL_STACK_UNDERFLOW:
|
||||
return logError("GL_STACK_UNDERFLOW", "This command would cause a stack underflow.");
|
||||
|
||||
case GL_OUT_OF_MEMORY:
|
||||
return logError("GL_OUT_OF_MEMORY", "There is not enough memory left to execute the command.");
|
||||
|
||||
case GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION:
|
||||
return logError("GL_INVALID_FRAMEBUFFER_OPERATION",
|
||||
"The object bound to FRAMEBUFFER_BINDING is not \"framebuffer complete\".");
|
||||
|
||||
default:
|
||||
return logError("Unknown error", "Unknown description");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sf::priv
|
||||
|
@ -63,7 +63,9 @@ namespace sf::priv
|
||||
/// \param line Line number of the source file where the call is located
|
||||
/// \param expression The evaluated expression as a string
|
||||
///
|
||||
/// \return `false` if an error occurred, `true` otherwise
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void glCheckError(const std::filesystem::path& file, unsigned int line, std::string_view expression);
|
||||
bool glCheckError(const std::filesystem::path& file, unsigned int line, std::string_view expression);
|
||||
|
||||
} // namespace sf::priv
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
@ -154,7 +155,7 @@ void Image::resize(Vector2u size, Color color)
|
||||
}
|
||||
|
||||
// Commit the new pixel buffer
|
||||
m_pixels.swap(newPixels);
|
||||
m_pixels = std::move(newPixels);
|
||||
|
||||
// Assign the new size
|
||||
m_size = size;
|
||||
@ -179,7 +180,7 @@ void Image::resize(Vector2u size, const std::uint8_t* pixels)
|
||||
std::vector<std::uint8_t> newPixels(pixels, pixels + size.x * size.y * 4);
|
||||
|
||||
// Commit the new pixel buffer
|
||||
m_pixels.swap(newPixels);
|
||||
m_pixels = std::move(newPixels);
|
||||
|
||||
// Assign the new size
|
||||
m_size = size;
|
||||
|
@ -312,9 +312,7 @@ Vector2f Text::findCharacterPos(std::size_t index) const
|
||||
}
|
||||
|
||||
// Transform the position to global coordinates
|
||||
position = getTransform().transformPoint(position);
|
||||
|
||||
return position;
|
||||
return getTransform().transformPoint(position);
|
||||
}
|
||||
|
||||
|
||||
|
@ -33,139 +33,88 @@
|
||||
#include <glad/egl.h>
|
||||
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace sf::priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
void eglCheckError(const std::filesystem::path& file, unsigned int line, std::string_view expression)
|
||||
bool eglCheckError(const std::filesystem::path& file, unsigned int line, std::string_view expression)
|
||||
{
|
||||
// Obtain information about the success or failure of the most recent EGL
|
||||
// function called in the current thread
|
||||
const EGLint errorCode = eglGetError();
|
||||
|
||||
if (errorCode != EGL_SUCCESS)
|
||||
const auto logError = [&](const char* error, const char* description)
|
||||
{
|
||||
std::string error = "unknown error";
|
||||
std::string description = "no description";
|
||||
|
||||
// Decode the error code returned
|
||||
switch (errorCode)
|
||||
{
|
||||
case EGL_NOT_INITIALIZED:
|
||||
{
|
||||
error = "EGL_NOT_INITIALIZED";
|
||||
description = "EGL is not initialized, or could not be initialized, for the specified display";
|
||||
break;
|
||||
}
|
||||
|
||||
case EGL_BAD_ACCESS:
|
||||
{
|
||||
error = "EGL_BAD_ACCESS";
|
||||
description =
|
||||
"EGL cannot access a requested resource (for example, a context is bound in another thread)";
|
||||
break;
|
||||
}
|
||||
|
||||
case EGL_BAD_ALLOC:
|
||||
{
|
||||
error = "EGL_BAD_ALLOC";
|
||||
description = "EGL failed to allocate resources for the requested operation";
|
||||
break;
|
||||
}
|
||||
case EGL_BAD_ATTRIBUTE:
|
||||
{
|
||||
error = "EGL_BAD_ATTRIBUTE";
|
||||
description = "an unrecognized attribute or attribute value was passed in an attribute list";
|
||||
break;
|
||||
}
|
||||
|
||||
case EGL_BAD_CONTEXT:
|
||||
{
|
||||
error = "EGL_BAD_CONTEXT";
|
||||
description = "an EGLContext argument does not name a valid EGLContext";
|
||||
break;
|
||||
}
|
||||
|
||||
case EGL_BAD_CONFIG:
|
||||
{
|
||||
error = "EGL_BAD_CONFIG";
|
||||
description = "an EGLConfig argument does not name a valid EGLConfig";
|
||||
break;
|
||||
}
|
||||
|
||||
case EGL_BAD_CURRENT_SURFACE:
|
||||
{
|
||||
error = "EGL_BAD_CURRENT_SURFACE";
|
||||
description =
|
||||
"the current surface of the calling thread is a window, pbuffer, or pixmap that is no longer valid";
|
||||
break;
|
||||
}
|
||||
|
||||
case EGL_BAD_DISPLAY:
|
||||
{
|
||||
error = "EGL_BAD_DISPLAY";
|
||||
description =
|
||||
"an EGLDisplay argument does not name a valid EGLDisplay; or, EGL is not initialized on the "
|
||||
"specified EGLDisplay";
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case EGL_BAD_SURFACE:
|
||||
{
|
||||
error = "EGL_BAD_SURFACE";
|
||||
description =
|
||||
"an EGLSurface argument does not name a valid surface (window, pbuffer, or pixmap) configured for "
|
||||
"rendering";
|
||||
break;
|
||||
}
|
||||
|
||||
case EGL_BAD_MATCH:
|
||||
{
|
||||
error = "EGL_BAD_MATCH";
|
||||
description =
|
||||
"arguments are inconsistent; for example, an otherwise valid context requires buffers (e.g. depth "
|
||||
"or stencil) not allocated by an otherwise valid surface";
|
||||
break;
|
||||
}
|
||||
|
||||
case EGL_BAD_PARAMETER:
|
||||
{
|
||||
error = "EGL_BAD_PARAMETER";
|
||||
description = "one or more argument values are invalid";
|
||||
break;
|
||||
}
|
||||
|
||||
case EGL_BAD_NATIVE_PIXMAP:
|
||||
{
|
||||
error = "EGL_BAD_NATIVE_PIXMAP";
|
||||
description = "an EGLNativePixmapType argument does not refer to a valid native pixmap";
|
||||
break;
|
||||
}
|
||||
|
||||
case EGL_BAD_NATIVE_WINDOW:
|
||||
{
|
||||
error = "EGL_BAD_NATIVE_WINDOW";
|
||||
description = "an EGLNativeWindowType argument does not refer to a valid native window";
|
||||
break;
|
||||
}
|
||||
|
||||
case EGL_CONTEXT_LOST:
|
||||
{
|
||||
error = "EGL_CONTEXT_LOST";
|
||||
description =
|
||||
"a power management event has occurred. The application must destroy all contexts and reinitialize "
|
||||
"client API state and objects to continue rendering";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Log the error
|
||||
err() << "An internal EGL call failed in " << file.filename() << " (" << line << ") : "
|
||||
<< "\nExpression:\n " << expression << "\nError description:\n " << error << "\n " << description << '\n'
|
||||
<< std::endl;
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
switch (eglGetError())
|
||||
{
|
||||
case EGL_SUCCESS:
|
||||
return true;
|
||||
|
||||
case EGL_NOT_INITIALIZED:
|
||||
return logError("EGL_NOT_INITIALIZED",
|
||||
"EGL is not initialized, or could not be initialized, for the specified display");
|
||||
|
||||
case EGL_BAD_ACCESS:
|
||||
return logError("EGL_BAD_ACCESS",
|
||||
"EGL cannot access a requested resource (for example, a context is bound in another "
|
||||
"thread)");
|
||||
|
||||
case EGL_BAD_ALLOC:
|
||||
return logError("EGL_BAD_ALLOC", "EGL failed to allocate resources for the requested operation");
|
||||
|
||||
case EGL_BAD_ATTRIBUTE:
|
||||
return logError("EGL_BAD_ATTRIBUTE",
|
||||
"an unrecognized attribute or attribute value was passed in an attribute list");
|
||||
|
||||
case EGL_BAD_CONTEXT:
|
||||
return logError("EGL_BAD_CONTEXT", "an EGLContext argument does not name a valid EGLContext");
|
||||
|
||||
case EGL_BAD_CONFIG:
|
||||
return logError("EGL_BAD_CONFIG", "an EGLConfig argument does not name a valid EGLConfig");
|
||||
|
||||
case EGL_BAD_CURRENT_SURFACE:
|
||||
return logError("EGL_BAD_CURRENT_SURFACE",
|
||||
"the current surface of the calling thread is a window, pbuffer, or pixmap that is no "
|
||||
"longer valid");
|
||||
|
||||
case EGL_BAD_DISPLAY:
|
||||
return logError("EGL_BAD_DISPLAY",
|
||||
"an EGLDisplay argument does not name a valid EGLDisplay; or, EGL is not initialized on "
|
||||
"the specified EGLDisplay");
|
||||
|
||||
|
||||
case EGL_BAD_SURFACE:
|
||||
return logError("EGL_BAD_SURFACE",
|
||||
"an EGLSurface argument does not name a valid surface (window, pbuffer, or pixmap) "
|
||||
"configured for rendering");
|
||||
|
||||
case EGL_BAD_MATCH:
|
||||
return logError("EGL_BAD_MATCH",
|
||||
"arguments are inconsistent; for example, an otherwise valid context requires buffers "
|
||||
"(e.g. depth or stencil) not allocated by an otherwise valid surface");
|
||||
|
||||
case EGL_BAD_PARAMETER:
|
||||
return logError("EGL_BAD_PARAMETER", "one or more argument values are invalid");
|
||||
|
||||
case EGL_BAD_NATIVE_PIXMAP:
|
||||
return logError("EGL_BAD_NATIVE_PIXMAP",
|
||||
"an EGLNativePixmapType argument does not refer to a valid native pixmap");
|
||||
|
||||
case EGL_BAD_NATIVE_WINDOW:
|
||||
return logError("EGL_BAD_NATIVE_WINDOW",
|
||||
"an EGLNativeWindowType argument does not refer to a valid native window");
|
||||
|
||||
case EGL_CONTEXT_LOST:
|
||||
return logError("EGL_CONTEXT_LOST",
|
||||
"a power management event has occurred. The application must destroy all contexts and "
|
||||
"reinitialize client API state and objects to continue rendering");
|
||||
|
||||
default:
|
||||
return logError("Unknown error", "Unknown description");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,9 @@ namespace sf::priv
|
||||
/// \param line Line number of the source file where the call is located
|
||||
/// \param expression The evaluated expression as a string
|
||||
///
|
||||
/// \return `false` if an error occurred, `true` otherwise
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void eglCheckError(const std::filesystem::path& file, unsigned int line, std::string_view expression);
|
||||
bool eglCheckError(const std::filesystem::path& file, unsigned int line, std::string_view expression);
|
||||
|
||||
} // namespace sf::priv
|
||||
|
@ -95,6 +95,20 @@ void Window::create(VideoMode mode, const String& title, std::uint32_t style, St
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Window::create(VideoMode mode, const String& title, State state)
|
||||
{
|
||||
Window::create(mode, title, sf::Style::Default, state, ContextSettings{});
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Window::create(VideoMode mode, const String& title, State state, const ContextSettings& settings)
|
||||
{
|
||||
Window::create(mode, title, sf::Style::Default, state, settings);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Window::create(WindowHandle handle)
|
||||
{
|
||||
|
@ -102,6 +102,13 @@ void WindowBase::create(VideoMode mode, const String& title, std::uint32_t style
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void WindowBase::create(VideoMode mode, const String& title, State state)
|
||||
{
|
||||
create(mode, title, Style::Default, state);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void WindowBase::create(WindowHandle handle)
|
||||
{
|
||||
|
@ -287,6 +287,7 @@ private:
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
IOHIDManagerRef m_manager{}; ///< Underlying HID Manager
|
||||
bool m_keysInitialized{}; ///< Has initializeKeyboard been called at least once?
|
||||
EnumArray<Keyboard::Scancode, IOHIDElements, Keyboard::ScancodeCount> m_keys; ///< All the keys on any connected keyboard
|
||||
EnumArray<Keyboard::Key, Keyboard::Scancode, Keyboard::KeyCount> m_keyToScancodeMapping{}; ///< Mapping from Key to Scancode
|
||||
EnumArray<Keyboard::Scancode, Keyboard::Key, Keyboard::ScancodeCount> m_scancodeToKeyMapping{}; ///< Mapping from Scancode to Key
|
||||
|
@ -562,6 +562,13 @@ bool HIDInputManager::isKeyPressed(Keyboard::Key key)
|
||||
////////////////////////////////////////////////////////////
|
||||
bool HIDInputManager::isKeyPressed(Keyboard::Scancode code)
|
||||
{
|
||||
// Lazy load m_keys to prevent unnecessary macOS input monitoring permission requests
|
||||
if (!m_keysInitialized)
|
||||
{
|
||||
initializeKeyboard();
|
||||
m_keysInitialized = true;
|
||||
}
|
||||
|
||||
return (code != Keyboard::Scan::Unknown) && isPressed(m_keys[code]);
|
||||
}
|
||||
|
||||
@ -716,7 +723,6 @@ HIDInputManager::HIDInputManager()
|
||||
}
|
||||
|
||||
// Build up our knowledge of the hardware
|
||||
initializeKeyboard();
|
||||
buildMappings();
|
||||
|
||||
// Register for notification on keyboard layout changes
|
||||
@ -924,6 +930,8 @@ void HIDInputManager::freeUp()
|
||||
|
||||
m_manager = nil;
|
||||
|
||||
if (m_keysInitialized)
|
||||
{
|
||||
for (auto& key : m_keys)
|
||||
{
|
||||
for (IOHIDElementRef iohidElementRef : key)
|
||||
@ -932,6 +940,8 @@ void HIDInputManager::freeUp()
|
||||
key.clear();
|
||||
}
|
||||
}
|
||||
m_keysInitialized = false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
@ -128,7 +128,16 @@ TEST_CASE("[Window] sf::Window", runDisplayTests())
|
||||
CHECK(window.getSettings().attributeFlags == sf::ContextSettings::Default);
|
||||
}
|
||||
|
||||
SECTION("Mode, title, style, and context settings")
|
||||
SECTION("Mode, title, style, and state")
|
||||
{
|
||||
window.create(sf::VideoMode({240, 360}), "Window Tests", sf::Style::Resize, sf::State::Windowed);
|
||||
CHECK(window.isOpen());
|
||||
CHECK(window.getSize() == sf::Vector2u(240, 360));
|
||||
CHECK(window.getNativeHandle() != sf::WindowHandle());
|
||||
CHECK(window.getSettings().attributeFlags == sf::ContextSettings::Default);
|
||||
}
|
||||
|
||||
SECTION("Mode, title, style, state, and context settings")
|
||||
{
|
||||
window.create(sf::VideoMode({240, 360}),
|
||||
"Window Tests",
|
||||
@ -142,5 +151,28 @@ TEST_CASE("[Window] sf::Window", runDisplayTests())
|
||||
CHECK(window.getSettings().stencilBits >= 1);
|
||||
CHECK(window.getSettings().antiAliasingLevel >= 1);
|
||||
}
|
||||
|
||||
SECTION("Mode, title, and state")
|
||||
{
|
||||
window.create(sf::VideoMode({240, 360}), "Window Tests", sf::State::Windowed);
|
||||
CHECK(window.isOpen());
|
||||
CHECK(window.getSize() == sf::Vector2u(240, 360));
|
||||
CHECK(window.getNativeHandle() != sf::WindowHandle());
|
||||
CHECK(window.getSettings().attributeFlags == sf::ContextSettings::Default);
|
||||
}
|
||||
|
||||
SECTION("Mode, title, state, and context settings")
|
||||
{
|
||||
window.create(sf::VideoMode({240, 360}),
|
||||
"Window Tests",
|
||||
sf::State::Windowed,
|
||||
sf::ContextSettings{/* depthBits*/ 1, /* stencilBits */ 1, /* antiAliasingLevel */ 1});
|
||||
CHECK(window.isOpen());
|
||||
CHECK(window.getSize() == sf::Vector2u(240, 360));
|
||||
CHECK(window.getNativeHandle() != sf::WindowHandle());
|
||||
CHECK(window.getSettings().depthBits >= 1);
|
||||
CHECK(window.getSettings().stencilBits >= 1);
|
||||
CHECK(window.getSettings().antiAliasingLevel >= 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -88,6 +88,14 @@ TEST_CASE("[Window] sf::WindowBase", runDisplayTests())
|
||||
CHECK(windowBase.getNativeHandle() != sf::WindowHandle());
|
||||
}
|
||||
|
||||
SECTION("Mode, title, and state")
|
||||
{
|
||||
windowBase.create(sf::VideoMode({240, 360}), "WindowBase Tests", sf::State::Windowed);
|
||||
CHECK(windowBase.isOpen());
|
||||
CHECK(windowBase.getSize() == sf::Vector2u(240, 360));
|
||||
CHECK(windowBase.getNativeHandle() != sf::WindowHandle());
|
||||
}
|
||||
|
||||
SECTION("Mode, title, style, and state")
|
||||
{
|
||||
windowBase.create(sf::VideoMode({240, 360}), "WindowBase Tests", sf::Style::Resize, sf::State::Windowed);
|
||||
|
Loading…
Reference in New Issue
Block a user