First Commit

This commit is contained in:
Sylar 2023-10-17 23:31:17 +02:00
parent 745ae1520f
commit 533aed49f6
576 changed files with 111963 additions and 0 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
bin
Debug
Build

21
.vscode/c_cpp_properties.json vendored Executable file
View file

@ -0,0 +1,21 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${default}",
"${workspaceRoot}/src/vendor/GLAD",
"${workspaceRoot}/src/vendor",
"${workspaceRoot}/src/ostd",
"${workspaceRoot}/src"
],
"defines": [],
"compilerPath": "/usr/bin/clang++",
"cStandard": "c17",
"cppStandard": "c++20",
"intelliSenseMode": "linux-clang-x64",
"compileCommands": "${workspaceFolder}/Debug/compile_commands.json"
}
],
"version": 4
}

141
.vscode/settings.json vendored Executable file
View file

@ -0,0 +1,141 @@
{
"C_Cpp.errorSquiggles": "Enabled",
"files.associations": {
"functional": "cpp",
"thread": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"csetjmp": "cpp",
"csignal": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"any": "cpp",
"array": "cpp",
"atomic": "cpp",
"hash_map": "cpp",
"barrier": "cpp",
"bit": "cpp",
"*.tcc": "cpp",
"bitset": "cpp",
"cfenv": "cpp",
"charconv": "cpp",
"chrono": "cpp",
"cinttypes": "cpp",
"codecvt": "cpp",
"compare": "cpp",
"complex": "cpp",
"concepts": "cpp",
"condition_variable": "cpp",
"coroutine": "cpp",
"cstdint": "cpp",
"cuchar": "cpp",
"deque": "cpp",
"forward_list": "cpp",
"list": "cpp",
"map": "cpp",
"set": "cpp",
"string": "cpp",
"unordered_map": "cpp",
"unordered_set": "cpp",
"vector": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"iterator": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"optional": "cpp",
"random": "cpp",
"ratio": "cpp",
"regex": "cpp",
"source_location": "cpp",
"string_view": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"fstream": "cpp",
"future": "cpp",
"initializer_list": "cpp",
"iomanip": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"latch": "cpp",
"limits": "cpp",
"mutex": "cpp",
"new": "cpp",
"numbers": "cpp",
"ostream": "cpp",
"ranges": "cpp",
"scoped_allocator": "cpp",
"semaphore": "cpp",
"shared_mutex": "cpp",
"span": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"stop_token": "cpp",
"streambuf": "cpp",
"syncstream": "cpp",
"typeindex": "cpp",
"typeinfo": "cpp",
"valarray": "cpp",
"variant": "cpp",
"*.rh": "cpp",
"hash_set": "cpp",
"strstream": "cpp",
"expected": "cpp",
"spanstream": "cpp",
"stacktrace": "cpp",
"*.ipp": "cpp"
},
"workbench.colorCustomizations": {
"editor.background": "#131313",
"tab.hoverBackground": "#111",
"tab.inactiveBackground": "#000",
"tab.activeBackground": "#1b1b1b",
"tab.activeBorder": "#bb5400",
"editorIndentGuide.background": "#252525",
"editorWhitespace.foreground": "#683700",
"editor.lineHighlightBorder": "#1a1a1a",
"editor.lineHighlightBackground": "#490050",
"editorBracketMatch.background": "#444",
"editorBracketMatch.border": "#b80318",
"editor.selectionBackground": "#3b3b3b",
"editor.selectionHighlightBackground": "#702900",
"statusBar.background": "#2e2850",
"minimap.background" : "#1b1b1b",
"sideBar.background": "#1b1b1b"
},
"workbench.editor.wrapTabs": true,
"todohighlight.isEnable": true,
"todohighlight.keywords": [
{
"text": "TODO:",
"color": "red",
"backgroundColor": "rgba(0, 0, 0, 0)"
},
{
"text": "INFO:",
"color": "blue",
"backgroundColor": "rgba(0, 0, 0, 0)"
},
{
"text": "HACK:",
"color": "purple",
"backgroundColor": "rgba(0, 0, 0, 0)"
}
],
"editor.insertSpaces": false,
"workbench.list.openMode": "doubleClick"
}

191
CMakeLists.txt Executable file
View file

@ -0,0 +1,191 @@
#Setup
#-----------------------------------------------------------------------------------------
set(CMAKE_CXX_COMPILER "clang++")
cmake_minimum_required(VERSION 3.18)
project(${PROJ_NAME} LANGUAGES C CXX)
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_CXX_STANDARD 20)
file(STRINGS "./tools/build.nr" BUILD_NUMBER)
#-----------------------------------------------------------------------------------------
#Variables
#-----------------------------------------------------------------------------------------
set(PROJ_NAME omnia-framework)
set(MAJOR_VER 0)
set(MINOR_VER 1)
set(OMNIA_STD_LIB ostd)
set(OMNIA_GFX_LIB ogfx)
set(TEST_TARGET framework-test)
set(RUN_CONFIG O_F_DEBUG)
message("** Building ${PROJ_NAME} ${MAJOR_VER}.${MINOR_VER}.${BUILD_NUMBER}")
#-----------------------------------------------------------------------------------------
#Sources
#-----------------------------------------------------------------------------------------
list(APPEND OSTD_VENDOR_SOURCES
${CMAKE_CURRENT_LIST_DIR}/src/vendor/clip/clip.cpp
${CMAKE_CURRENT_LIST_DIR}/src/vendor/clip/image.cpp
)
list(APPEND OGFX_VENDOR_SOURCES
${CMAKE_CURRENT_LIST_DIR}/src/vendor/GLAD/glad.c
)
list(APPEND INCLUDE_DIRS
${CMAKE_CURRENT_LIST_DIR}/src
${CMAKE_CURRENT_LIST_DIR}/src/ostd
${CMAKE_CURRENT_LIST_DIR}/src/vendor
${CMAKE_CURRENT_LIST_DIR}/src/vendor/GLAD
)
list(APPEND TEST_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/src/test/main.cpp
${CMAKE_CURRENT_LIST_DIR}/src/test/TestApp2D.cpp
${CMAKE_CURRENT_LIST_DIR}/src/test/TestApp3D.cpp
${CMAKE_CURRENT_LIST_DIR}/src/test/TetrisApp.cpp
)
list(APPEND OSH_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/src/osh/commandShell.cpp
)
list(APPEND OXGE_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/src/oxge/iso/Engine.cpp
)
list(APPEND OGFX_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/BitmapFont.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/BlendRenderer.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/Errors.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/Camera.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/GraphicsApplication.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/GLBuffers.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/Mesh.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/OX3DLoader.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/Renderer2D.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/RenderCommands.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/RenderCore.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/RenderTarget.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/ResourceManager.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/RTData.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/Shader.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/Texture.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/Window.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/Widgets.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/DebugTools.cpp
)
list(APPEND OSTD_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/src/ostd/BaseObject.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ostd/Color.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ostd/DataFile.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ostd/Errors.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ostd/File.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ostd/Geometry.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ostd/Logger.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ostd/Logic.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ostd/OutputHandlers.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ostd/PathFinder.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ostd/QuadTree.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ostd/ShuntingYard.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ostd/Signals.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ostd/Random.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ostd/RichString.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ostd/Serial.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ostd/SineWave.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ostd/StringEditor.cpp
${CMAKE_CURRENT_LIST_DIR}/src/ostd/Utils.cpp
)
if (WIN32)
list(APPEND OSTD_VENDOR_SOURCES
${CMAKE_CURRENT_LIST_DIR}/src/vendor/clip/clip_win.cpp
)
endif (WIN32)
if (UNIX)
list(APPEND OSTD_VENDOR_SOURCES
${CMAKE_CURRENT_LIST_DIR}/src/vendor/clip/clip_x11.cpp
)
endif (UNIX)
list(APPEND OSTD_SOURCE_FILES ${OSTD_VENDOR_SOURCES})
list(APPEND OGFX_SOURCE_FILES ${OGFX_VENDOR_SOURCES})
#-----------------------------------------------------------------------------------------
#Targets
#-----------------------------------------------------------------------------------------
add_library(${OMNIA_STD_LIB} SHARED ${OSTD_SOURCE_FILES})
add_library(${OMNIA_GFX_LIB} SHARED ${OGFX_SOURCE_FILES})
add_executable(${TEST_TARGET} ${TEST_SOURCE_FILES})
target_compile_definitions(${OMNIA_STD_LIB} PUBLIC ${RUN_CONFIG} BUILD_NR=${BUILD_NUMBER} MAJ_V=${MAJOR_VER} MIN_V=${MINOR_VER} VERSION_STR="${MAJOR_VER}.${MINOR_VER}.${BUILD_NUMBER}")
target_compile_definitions(${OMNIA_GFX_LIB} PUBLIC ${RUN_CONFIG} BUILD_NR=${BUILD_NUMBER} MAJ_V=${MAJOR_VER} MIN_V=${MINOR_VER} VERSION_STR="${MAJOR_VER}.${MINOR_VER}.${BUILD_NUMBER}")
target_include_directories(${OMNIA_STD_LIB} PUBLIC ${INCLUDE_DIRS})
target_include_directories(${OMNIA_GFX_LIB} PUBLIC ${INCLUDE_DIRS})
target_include_directories(${TEST_TARGET} PUBLIC ${INCLUDE_DIRS})
#TODO: Different flags for Release/Debug
add_compile_options(-O3 -m32 -MMD -MP -Wall -ggdb -fsanitize=address)
if (UNIX)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath='$ORIGIN'")
target_link_libraries(${OMNIA_GFX_LIB} PUBLIC X11 GL)
endif (UNIX)
target_link_libraries(${OMNIA_GFX_LIB} PUBLIC sfml-system sfml-window sfml-graphics)
#-----------------------------------------------------------------------------------------
#Linking Targets
#-----------------------------------------------------------------------------------------
target_link_libraries(${OMNIA_GFX_LIB} PUBLIC ${OMNIA_STD_LIB})
target_link_libraries(${TEST_TARGET} PUBLIC ${OMNIA_STD_LIB})
target_link_libraries(${TEST_TARGET} PUBLIC ${OMNIA_GFX_LIB})
#-----------------------------------------------------------------------------------------
#BuildNumber Target
#-----------------------------------------------------------------------------------------
if (WIN32)
add_custom_command ( OUTPUT ./tools/build.nr
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/tools/inc_bnr.exe
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tools/
)
endif (WIN32)
if (UNIX)
add_custom_command ( OUTPUT ./tools/build.nr
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/tools/inc_bnr
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tools/
)
endif (UNIX)
add_custom_target(
IncBnr ALL
DEPENDS ./tools/build.nr
)
#-----------------------------------------------------------------------------------------
#Install
#-----------------------------------------------------------------------------------------
#TODO: Change TEST_TARGET to last lib built, for release config
add_custom_command(TARGET ${TEST_TARGET} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_SOURCE_DIR}/extra/ $<TARGET_FILE_DIR:${TEST_TARGET}>
VERBATIM
)
set(CMAKE_INSTALL_MESSAGE NEVER)
install(TARGETS ${OMNIA_STD_LIB} DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/Build/bin)
install(TARGETS ${OMNIA_GFX_LIB} DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/Build/bin)
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/licences DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/Build)
add_custom_target(FinalMessage ALL ${CMAKE_COMMAND} -E cmake_echo_color --cyan "[100%] Built ${PROJ_NAME} ${MAJOR_VER}.${MINOR_VER}.${BUILD_NUMBER}")
add_dependencies(FinalMessage ${TEST_TARGET})
#-----------------------------------------------------------------------------------------

14
compile Executable file
View file

@ -0,0 +1,14 @@
#/bin/bash
rm -r Build
rm -r bin
#export CXX=/usr/bin/clang++
cmake -B bin -S ./
cd bin
make install
cd ..
if [ $? -eq 0 ]; then
printf "Installing includes...\n"
python ./tools/create_includes.py
printf "Done!\n"
fi

10
extra/make_and_run Executable file
View file

@ -0,0 +1,10 @@
#!/bin/bash
printf "\n============================================[ Building Application ]============================================\n\n"
rm -r ./res
\cp -r ../extra/* ./
make
if [ $? -eq 0 ]; then
printf "\n============================================[ Running Application ]============================================\n\n"
./framework-test
fi

BIN
extra/models/cube3.ox3d Normal file

Binary file not shown.

BIN
extra/models/monkey2.ox3d Normal file

Binary file not shown.

BIN
extra/other/tileset.xcf Executable file

Binary file not shown.

104
extra/shaders/basicShader.fs Executable file
View file

@ -0,0 +1,104 @@
#version 410 core
out vec4 FragColor;
in vec2 outTexCoords;
in vec3 outNormal;
in vec3 outFragPos;
struct Material {
sampler2D diffuse;
sampler2D specular;
float shininess;
};
struct LightSource {
vec3 position;
vec3 direction;
float cutOff;
float outerCutOff;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float constant;
float linear;
float quadratic;
int type;
};
const int SpotLight = 0;
const int Directional = 1;
const int PointLight = 2;
//@[skip_auto_register]
uniform Material material;
//@[skip_auto_register]
uniform LightSource light;
uniform vec3 uViewPosition;
//float near = 0.1;
//float far = 100.0;
//float LinearizeDepth(float depth)
//{
// float z = depth * 2.0 - 1.0; // back to NDC
// return (2.0 * near * far) / (far + near - z * (far - near));
//}
void main()
{
//Ambient light
vec3 ambient = light.ambient * vec3(texture(material.diffuse, outTexCoords));
vec3 norm = normalize(outNormal);
vec3 lightDir;
float intensity = 1.0;
if (light.type == PointLight)
{
lightDir = normalize(light.position - outFragPos);
}
else if (light.type == Directional)
{
lightDir = normalize(-light.position);
}
else if (light.type == SpotLight)
{
lightDir = normalize(light.position - outFragPos);
float theta = dot(lightDir, normalize(-light.direction));
float epsilon = light.cutOff - light.outerCutOff;
intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 0.5);
}
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, outTexCoords));
//Specular light
vec3 viewDir = normalize(uViewPosition - outFragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 specular = light.specular * spec * vec3(texture(material.specular, outTexCoords));
//Attenuation
if (light.type != Directional)
{
float dist = length(light.position - outFragPos);
float attenuation = 1.0 / (light.constant * light.linear * dist * light.quadratic * (dist * dist));
if (light.type == SpotLight)
{
diffuse *= intensity;
specular *= intensity;
}
//else
// ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
}
//Final color
vec3 result = (ambient + diffuse + specular);
FragColor = vec4(result, 1.0);
//FragColor = vec4(vec3(LinearizeDepth(gl_FragCoord.z) / far), 1.0);
}

23
extra/shaders/basicShader.vs Executable file
View file

@ -0,0 +1,23 @@
#version 410 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec4 aCol;
layout (location = 2) in vec2 aTexCoords;
layout (location = 3) in vec3 aNormal;
out vec2 outTexCoords;
out vec3 outNormal;
out vec3 outFragPos;
uniform mat4 uModel;
uniform mat4 uView;
uniform mat4 uProj;
uniform mat4 uNorm;
void main()
{
gl_Position = uProj * uView * uModel * vec4(aPos, 1.0);
outTexCoords = aTexCoords;
outNormal = vec3(uNorm * vec4(aNormal, 1.0));
outFragPos = vec3(uModel * vec4(aPos, 1.0));
}

8
extra/shaders/lightShader.fs Executable file
View file

@ -0,0 +1,8 @@
#version 410 core
out vec4 FragColor;
void main()
{
FragColor = vec4(1.0);
}

15
extra/shaders/lightShader.vs Executable file
View file

@ -0,0 +1,15 @@
#version 410 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec4 aCol;
layout (location = 2) in vec2 aTexCoords;
layout (location = 3) in vec3 aNormal;
uniform mat4 uModel;
uniform mat4 uView;
uniform mat4 uProj;
void main()
{
gl_Position = uProj * uView * uModel * vec4(aPos, 1.0);
}

12
extra/shaders/screenPlane.fs Executable file
View file

@ -0,0 +1,12 @@
#version 420
out vec4 FragColor;
in vec2 TexCoords;
uniform sampler2D screenTexture;
void main()
{
FragColor = texture(screenTexture, TexCoords);
}

14
extra/shaders/screenPlane.vs Executable file
View file

@ -0,0 +1,14 @@
#version 420
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec4 aCol;
layout (location = 2) in vec2 aTexCoords;
layout (location = 3) in vec3 aNormal;
out vec2 TexCoords;
void main()
{
gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0);
TexCoords = aTexCoords;
}

12
extra/shaders/skybox.fs Executable file
View file

@ -0,0 +1,12 @@
#version 420
out vec4 FragColor;
in vec3 TexCoords;
uniform samplerCube skybox;
void main()
{
FragColor = texture(skybox, TexCoords);
}

17
extra/shaders/skybox.vs Executable file
View file

@ -0,0 +1,17 @@
#version 420
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec4 aCol;
layout (location = 2) in vec2 aTexCoords;
layout (location = 3) in vec3 aNormal;
out vec3 TexCoords;
uniform mat4 proj;
uniform mat4 view;
void main()
{
gl_Position = proj * view * vec4(aPos, 1.0);
TexCoords = aPos;
}

BIN
extra/textures/awesomeface.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

BIN
extra/textures/container.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB

BIN
extra/textures/container2.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 457 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

BIN
extra/textures/skybox/back.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 723 KiB

BIN
extra/textures/skybox/bottom.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 KiB

BIN
extra/textures/skybox/front.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 462 KiB

BIN
extra/textures/skybox/left.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 588 KiB

BIN
extra/textures/skybox/right.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 525 KiB

BIN
extra/textures/skybox/top.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
extra/textures/tetris.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 906 B

BIN
extra/textures/tileset.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

BIN
extra/textures/wall.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 KiB

BIN
extra/textures/wood.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
extra/textures/wood.jpg.001.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

View file

@ -0,0 +1,22 @@
MIT License
Copyright(c) 2020 Jordan Peck (jordan.me2@gmail.com)
Copyright(c) 2020 Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

9
licences/SFML-LICENSE.md Executable file
View file

@ -0,0 +1,9 @@
Copyright (C) 2007-2022 Laurent Gomila - laurent@sfml-dev.org
This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

20
licences/clip-LICENSE.txt Executable file
View file

@ -0,0 +1,20 @@
Copyright (c) 2015-2022 David Capello
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

37
licences/stb-LICENSE Executable file
View file

@ -0,0 +1,37 @@
This software is available under 2 licenses -- choose whichever you prefer.
------------------------------------------------------------------------------
ALTERNATIVE A - MIT License
Copyright (c) 2017 Sean Barrett
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
------------------------------------------------------------------------------
ALTERNATIVE B - Public Domain (www.unlicense.org)
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this
software dedicate any and all copyright interest in the software to the public
domain. We make this dedication for the benefit of the public at large and to
the detriment of our heirs and successors. We intend this dedication to be an
overt act of relinquishment in perpetuity of all present and future rights to
this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

31
licences/termcolor-LICENSE Executable file
View file

@ -0,0 +1,31 @@
Copyright (c) 2013, Ihor Kalnytskyi.
All rights reserved.
Redistribution and use in source and binary forms of the software as well
as documentation, with or without modification, are permitted provided
that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* The names of the contributors may not be used to endorse or
promote products derived from this software without specific
prior written permission.
THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.

270
src/ogfx/BitmapFont.cpp Executable file
View file

@ -0,0 +1,270 @@
#include "BitmapFont.hpp"
#include <ogfx/ResourceManager.hpp>
#include <ogfx/Texture.hpp>
#include <ogfx/Errors.hpp>
#include <Logger.hpp>
//TODO: Add errors
namespace ogfx
{
using namespace ostd;
BitmapFont& BitmapFont::create(String filePath, bool monospace)
{
m_texture = ResourceManager::loadTexture(filePath, true, GL_NEAREST, GL_NEAREST);
m_monoSpace = monospace;
__load();
return *this;
}
BitmapFont& BitmapFont::create(ResourceID texture, bool monospace)
{
m_texture = texture;
m_monoSpace = monospace;
__load();
return *this;
}
TextureAtlasIndex BitmapFont::getChar(unsigned char c, Rectangle& outRect)
{
outRect = m_charBounds[(uint32_t)c];
if (m_monoSpace) outRect.w = m_maxCharWidth + 4;
return m_characters[(uint32_t)c];
}
float BitmapFont::getSpaceWidth(void)
{
if (m_monoSpace) return m_maxCharWidth;
return m_spaceWidth;
}
void BitmapFont::setSpaceWidth(float w)
{
m_spaceWidth = w;
if (!m_monoSpace)
m_charBounds[(uint32_t)' '] = { (m_charSize.x - m_spaceWidth) / 2.0f, 5.0f, m_spaceWidth, m_charSize.y - 10 };
}
void BitmapFont::enableMonoSpace(bool mono)
{
if (isInvalid()) return; //TODO: Error
create(m_texture, mono);
}
void BitmapFont::calc_char_bounds(void)
{
uint32_t xtiles = m_textureSize.x / m_charSize.x;
uint32_t ytiles = m_textureSize.y / m_charSize.y;
const auto& pixels = ResourceManager::getTexture(m_texture).getPixelData();
uint8_t** sub_pixels = new uint8_t*[m_charSize.y];
for (int32_t row = 0; row < m_charSize.y; row++)
sub_pixels[row] = new uint8_t[m_charSize.x];
for (int32_t y = ytiles - 1; y >= 0; y--)
{
for (int32_t x = 0; x < xtiles; x++)
{
int32_t xx = (x * m_charSize.x * 4);
int32_t yy = (y * m_charSize.y * 4);
for (int32_t row = 0; row < m_charSize.y; row++)
{
for (int32_t col = 0; col < m_charSize.x; col++)
{
int32_t real_x = xx + (col * 4);
int32_t real_y = yy + (row * 4);
int32_t _1d_coord = CONVERT_2D_1D(real_x, real_y, (uint32_t)m_textureSize.x);
sub_pixels[row][col] = pixels[_1d_coord];
}
}
auto rect = test_grid(sub_pixels, m_charSize.x, m_charSize.y);
// std::cout << (char)m_charBounds.size() << "\n";
// std::cout << rect.getPosition() << "\n";
// std::cout << rect.getSize() << "\n\n";
if (rect.w > m_maxCharWidth)
m_maxCharWidth = rect.w;
m_charBounds.push_back(rect);
}
}
if (m_monoSpace)
{
for (auto& cb : m_charBounds)
{
float oldw = cb.w;
float newx_offset = (m_maxCharWidth - oldw) / 2;
cb.w = m_maxCharWidth;
cb.x -= newx_offset;
if (cb.x < 0) cb.x = 0;
}
}
}
Rectangle BitmapFont::test_grid(uint8_t** grid, int32_t width, int32_t height, uint8_t invalid_alpha)
{
int32_t top = 0, bottom = height, left = 0, right = width;
bool found = false;
// for (int32_t row = 0; row < height; row++)
// {
// for (int32_t col = 0; col < width; col++)
// {
// if (grid[row][col] != invalid_alpha)
// {
// top = row;
// found = true;
// break;
// }
// }
// if (found) break;
// }
// if (!found) return { 0, 0, 0, 0 }; //TODO: ERROR
found = false;
for (int32_t col = 0; col < width; col++)
{
for (int32_t row = 0; row < height; row++)
{
if (grid[row][col] != invalid_alpha)
{
left = col;
found = true;
break;
}
}
if (found) break;
}
if (!found) return { 0, 0, 0, 0 }; //TODO: ERROR
found = false;
for (int32_t col = width - 1; col >= 0; col--)
{
for (int32_t row = 0; row < width; row++)
{
if (grid[row][col] != invalid_alpha)
{
right = col;
found = true;
break;
}
}
if (found) break;
}
if (!found) return { 0, 0, 0, 0 }; //TODO: ERROR
// found = false;
// for (int32_t row = height - 1; row >= 0; row--)
// {
// for (int32_t col = 0; col < width; col++)
// {
// if (grid[row][col] != invalid_alpha)
// {
// bottom = row;
// found = true;
// break;
// }
// }
// if (found) break;
// }
Rectangle rect = Rectangle((float)left, (float)top, (float)(right - left), (float)(bottom - top));
if (rect.x < 0) rect.x = 0;
if (rect.y < 0) rect.y = 0;
if (rect.w > width) rect.w = width;
if (rect.h > height) rect.h = height;
return { rect.x, 0, rect.w, (float)height };
return rect;
}
// void BitmapFont::calc_char_bounds(void)
// {
// uint32_t xtiles = m_textureSize.x / m_charSize.x;
// uint32_t ytiles = m_textureSize.y / m_charSize.y;
// const auto& pixels = ResourceManager::getTexture(m_texture).getPixelData();
// for (int32_t y = ytiles - 1; y >= 0; y--)
// {
// for (int32_t x = 0; x < xtiles; x++)
// {
// int32_t xx = (x * m_charSize.x * 4);
// int32_t yy = (y * m_charSize.y * 4);
// float bl = m_charSize.x, bt = m_charSize.y, br = 0.0f, bb = 0.0f;
// int32_t revy = 0;
// for (int32_t ty = m_charSize.y - 1; ty >= 0; ty--, revy++)
// {
// for (int32_t tx = 0; tx < m_charSize.x; tx++)
// {
// uint32_t px = xx + (tx * 4);
// uint32_t py = yy + (ty * 4);
// uint8_t alpha = pixels[CONVERT_2D_1D(px, py, (uint32_t)m_textureSize.x)];
// if (alpha != 0)
// {
// if (revy < m_charSize.y / 2)
// { if (revy < bt) bt = revy; }
// else if (revy > bb) bb = revy;
// if (tx < m_charSize.x / 2)
// { if (tx < bl) bl = tx; }
// else if (tx > br) br = tx;
// }
// }
// }
// Rectangle rect(bl - 2, bt - 2, br - bl + 4, bb - bt + 4);
// std::cout << (char)m_charBounds.size() << "\n";
// std::cout << rect.getPosition() << "\n";
// std::cout << rect.getSize() << "\n\n";
// if (rect.x < 0) rect.x = 0;
// if (rect.y < 0) rect.y = 0;
// if (rect.w < 10) rect.w = 10;
// if (rect.h < 10) rect.h = 10;
// if (rect.w > m_maxCharWidth)
// m_maxCharWidth = rect.w;
// m_charBounds.push_back(rect);
// }
// }
// if (m_monoSpace)
// {
// for (auto& cb : m_charBounds)
// {
// float oldw = cb.w;
// float newx = m_maxCharWidth - oldw;
// newx = cb.x - (newx / 2.0f);
// cb.w = m_maxCharWidth;
// if (newx >= 0) cb.x = newx;
// }
// }
// }
void BitmapFont::__load(void)
{
invalidate();
m_characters.clear();
m_charBounds.clear();
m_maxCharWidth = 0.0f;
if (m_texture == ResourceManager::InvalidResource)
{
ErrorHandler::pushError(BitmapFont::ERR_INVALID_TEXTURE);
String err_str = ErrorHandler::getLastErrorString();
OX_ERROR("%s", err_str.c_str());
return;
}
auto& tex = ResourceManager::getTexture(m_texture);
if (tex.getWidth() % 16 != 0 || tex.getHeight() % 16 != 0)
{
ErrorHandler::pushError(BitmapFont::ERR_INVALID_TEXTURE_SIZE);
String err_str = ErrorHandler::getLastErrorString();
OX_ERROR("%s", err_str.c_str());
return;
}
m_charSize = { (float)(tex.getWidth() / 16.0f), (float)(tex.getHeight() / 16.0f) };
m_textureSize = { (float)tex.getWidth(), (float)tex.getHeight() };
calc_char_bounds();
if (!m_monoSpace)
m_charBounds[(uint32_t)' '] = { (m_charSize.x - m_spaceWidth) / 2.0f, 5.0f, m_spaceWidth, m_charSize.y - 10 };
for (uint32_t y = 0; y < 16; y++)
{
for (uint32_t x = 0; x < 16; x++)
{
auto& bounds = m_charBounds[CONVERT_2D_1D(x, y, 16)];
m_characters.push_back(tex.addTileInfo((x * m_charSize.x) + bounds.x,
(y * m_charSize.y) + bounds.y,
bounds.w,
bounds.h));
}
}
setTypeName("ox::BitmapFont");
validate();
}
}

50
src/ogfx/BitmapFont.hpp Executable file
View file

@ -0,0 +1,50 @@
#ifndef __BITMAP_FONT_HPP__
#define __BITMAP_FONT_HPP__
#include <ostd/BaseObject.hpp>
#include <ostd/Types.hpp>
#include <ostd/Geometry.hpp>
#include <ostd/Defines.hpp>
namespace ogfx
{
using namespace ostd; //TODO: Remove from header
class BitmapFont : public BaseObject
{
public:
inline BitmapFont(void) { invalidate(); }
inline BitmapFont(String filePath, bool monospace = false) { create(filePath, monospace); }
BitmapFont& create(String filePath, bool monospace = false);
BitmapFont& create(ResourceID texture, bool monospace = false);
TextureAtlasIndex getChar(unsigned char c, Rectangle& outRect);
float getSpaceWidth(void);
inline ResourceID getTexture(void) { return m_texture; }
inline float getBaseCharHeight(void) { return m_charSize.y; }
void setSpaceWidth(float w);
inline bool isMonoSpace(void) { return m_monoSpace; }
void enableMonoSpace(bool mono = true);
private:
void calc_char_bounds(void);
void __load(void);
Rectangle test_grid(uint8_t** grid, int32_t width, int32_t height, uint8_t invalid_alpha = 0);
private:
ResourceID m_texture;
std::vector<TextureAtlasIndex> m_characters;
std::vector<Rectangle> m_charBounds;
Vec2 m_charSize;
Vec2 m_textureSize;
float m_spaceWidth { 20.0f };
float m_maxCharWidth { 0.0f };
bool m_monoSpace { false };
public:
inline static constexpr int32_t ERR_INVALID_TEXTURE = OX_BITMAPFONT_ERR_MASK + 0x0001;
inline static constexpr int32_t ERR_INVALID_TEXTURE_SIZE = OX_BITMAPFONT_ERR_MASK + 0x0002;
};
}
#endif

101
src/ogfx/BlendRenderer.cpp Executable file
View file

@ -0,0 +1,101 @@
#include "BlendRenderer.hpp"
#include <ostd/Signals.hpp>
#include <ogfx/RenderCore.hpp>
namespace ogfx
{
BlendRenderer& BlendRenderer::create(IPoint screenSize, OrthoCamera& camera)
{
m_screenSize = screenSize;
m_destination.create(screenSize.x, screenSize.y);
m_shader = ResourceManager::getDefaultBlendShader();
m_blendModes.resize(BlendRenderer::MaxLayers, tBlendModes::Transparent);;
connectSignal(tBuiltinSignals::WindowResized);
m_camera = &camera;
setTypeName("ox::BlendRenderer");
validate();
return *this;
}
LayerID BlendRenderer::addLayer(RenderTarget& target, uint8_t blendMode)
{//TODO: Errors
if (isInvalid()) return BlendRenderer::InvalidLayer;
if (m_layers.size() >= BlendRenderer::MaxLayers) return BlendRenderer::InvalidLayer;
LayerID id = BlendRenderer::s_nextID++;
m_layers.push_back({ target, blendMode });
return id;
}
void BlendRenderer::process(RenderCore& gfx)
{
if (isInvalid()) return;
uint32_t rt = gfx.getCurrentRenderTarget();
ResourceID shad = gfx.getCurrentShaderID();
gfx.setRenderTarget(m_destination);
gfx.bindShader(m_shader);
gfx.clear({ 0, 0, 0, 0 });
gfx.updateUniform_mat4f("u_viewProjMatrix", m_camera->getProjectionMatrix());
uint32_t index = 0;
for (auto& layer : m_layers)
{
m_blendModes[index] = layer.blendMode;
gfx.drawRenderTarget(*layer.target, { 0.0f, 0.0f }, { (float)m_screenSize.x, (float)m_screenSize.y });
// gfx.drawRenderTarget(*layer.target);//, { 0.0f, 0.0f }, { (float)m_screenSize.x, (float)m_screenSize.y });
index++;
}
if (index < BlendRenderer::MaxLayers)
{
for ( ; index < BlendRenderer::MaxLayers; index++)
m_blendModes[index] = tBlendModes::Transparent;
}
gfx.updateUniform_arri("u_blendModes", m_blendModes);
gfx.updateUniform_i("u_layerCount", m_layers.size());
gfx.bindShader(shad);
gfx.setRenderTarget(rt);
}
void BlendRenderer::renderTo(RenderCore& gfx, const RenderTarget& target, ResourceID shader)
{
if (isInvalid()) return;
uint32_t rt = gfx.getCurrentRenderTarget();
ResourceID shad = gfx.getCurrentShaderID();
gfx.setRenderTarget(target);
gfx.bindShader(shader);
gfx.updateUniform_mat4f("u_viewProjMatrix", m_camera->getProjectionMatrix());
gfx.drawRenderTarget(m_destination);
gfx.bindShader(shad);
gfx.setRenderTarget(rt);
}
bool BlendRenderer::overrideDefaultBlendShader(ResourceID shader)
{
if (ResourceManager::getShader(shader).isInvalid()) return false;
m_shader = shader;
return true;
}
void BlendRenderer::renderToScreen(RenderCore& gfx, ResourceID shader)
{
renderTo(gfx, Renderer2D::getDefaultRenderTarget(), shader);
}
void BlendRenderer::setDefaultBlendShader(void)
{
m_shader = ResourceManager::getDefaultBlendShader();
}
BlendRenderer::tLayer& BlendRenderer::getLayer(LayerID layer)
{
if (layer >= m_layers.size()) return BlendRenderer::s_invalidLayer;
return m_layers[layer];
}
void BlendRenderer::handleSignal(tSignal& signal)
{
if (signal.ID == tBuiltinSignals::WindowResized)
{
WindowSizeObj& newSize = static_cast<WindowSizeObj&>(signal.userData);
m_screenSize = { newSize.width, newSize.height };
}
}
}

72
src/ogfx/BlendRenderer.hpp Executable file
View file

@ -0,0 +1,72 @@
#ifndef __BLEND_RENDERER_HPP__
#define __BLEND_RENDERER_HPP__
#include <ogfx/Camera.hpp>
#include <ogfx/RenderTarget.hpp>
namespace ogfx
{
using namespace ostd; //TODO: Remove from header
struct tBlendModes
{
inline static constexpr uint8_t Override = 0;
inline static constexpr uint8_t Transparent = 1;
inline static constexpr uint8_t Multiply = 2;
inline static constexpr uint8_t Add = 3;
inline static constexpr uint8_t Subtract = 4;
inline static constexpr uint8_t Normal = 5;
inline static constexpr uint8_t Invalid = 0xFF;
};
class RenderCore;
class BlendRenderer : public BaseObject
{
public: struct tLayer
{
RenderTarget* target { nullptr };
uint8_t blendMode { tBlendModes::Override };
inline tLayer(void) { }
inline tLayer(RenderTarget& _target, uint8_t _blendMode) { target = &_target; blendMode = _blendMode; }
inline bool isValid(void) { return m_valid && target != nullptr && blendMode != tBlendModes::Invalid && target->isValid(); }
private:
inline tLayer(bool v = false) { m_valid = v; }
bool m_valid { true };
friend class BlendRenderer;
};
public:
inline BlendRenderer(void) { invalidate(); }
inline BlendRenderer(IPoint screenSize, OrthoCamera& camera) { create(screenSize, camera); }
BlendRenderer& create(IPoint screenSize, OrthoCamera& camera);
LayerID addLayer(RenderTarget& target, uint8_t blendMode = tBlendModes::Override);
void process(RenderCore& gfx);
void renderTo(RenderCore& gfx, const RenderTarget& target, ResourceID shader);
void renderToScreen(RenderCore& gfx, ResourceID shader);
bool overrideDefaultBlendShader(ResourceID shader);
void setDefaultBlendShader(void);
tLayer& getLayer(LayerID layer);
void handleSignal(tSignal& signal) override;
inline RenderTarget& getDestination(void) { return m_destination; }
private:
RenderTarget m_destination;
ResourceID m_shader;
std::vector<tLayer> m_layers;
IPoint m_screenSize;
std::vector<int32_t> m_blendModes;
OrthoCamera* m_camera { nullptr };
inline static LayerID s_nextID = 0;
inline static tLayer s_invalidLayer { false };
public:
inline static constexpr int32_t MaxLayers = 14;
inline static constexpr LayerID InvalidLayer = 1024;
};
}
#endif

187
src/ogfx/Camera.cpp Executable file
View file

@ -0,0 +1,187 @@
#include "Camera.hpp"
#include "DataStructures.hpp"
#include "Window.hpp"
#include "Signals.hpp"
#include <ostd/Utils.hpp>
namespace ogfx
{
using namespace ostd;
FirstPersonCamera& FirstPersonCamera::create(Window &window, bool invert_y)
{
m_window = &window;
m_invert_y = invert_y;
updateProjectionMatrix();
setTypeName("ogfx::FirstPersonCamera");
validate();
updateViewMatrix();
return *this;
}
void FirstPersonCamera::mouseMoved(float x, float y)
{
if (isInvalid()) return;
m_reset_mouse = true;
float xpos = x - (m_window->getSize().x / 2.0f);
float ypos = y - (m_window->getSize().y / 2.0f);
xpos *= m_moveSensitivity;
ypos *= m_moveSensitivity * (m_invert_y ? 1.0f : -1.0f);
m_yaw += xpos;
m_pitch += ypos;
if (m_pitch > 89.0f)
m_pitch = 89.0f;
if (m_pitch < -89.0f)
m_pitch = -89.0f;
glm::vec3 front;
front.x = cos(glm::radians(m_yaw)) * cos(glm::radians(m_pitch));
front.y = sin(glm::radians(m_pitch));
front.z = sin(glm::radians(m_yaw)) * cos(glm::radians(m_pitch));
m_front = glm::normalize(front);
}
void FirstPersonCamera::updateViewMatrix(void)
{
if (isInvalid()) return;
m_viewMat = glm::lookAt(m_position, m_position + m_front, m_up);
}
void FirstPersonCamera::updateProjectionMatrix(float fov, float near, float far)
{
tPerspective persp(m_window->getSize().x, m_window->getSize().y);
if (fov != 0.0f) persp.FOV = fov;
if (near != 0.0f) persp.nearPlane = near;
if (far != 0.0f) persp.farPlane = far;
persp.update();
m_perspMat = persp.getMatrix();
}
void FirstPersonCamera::update(void)
{
if (isInvalid()) return;
if (m_reset_mouse)
{
m_window->centerMouse();
m_reset_mouse = false;
}
glm::vec3 absolute_front = m_front;
absolute_front.y = 0.0f;
if (m_move_keys[KeyForward])
m_position += m_moveSpeed * absolute_front;
if (m_move_keys[KeyLeft])
m_position -= glm::normalize(glm::cross(m_front, m_up)) * m_moveSpeed;
if (m_move_keys[KeyBackwards])
m_position -= m_moveSpeed * absolute_front;
if (m_move_keys[KeyRight])
m_position += glm::normalize(glm::cross(m_front, m_up)) * m_moveSpeed;
if (m_move_keys[KeyUp])
m_position += m_moveSpeed * m_up;
if (m_move_keys[KeyDown])
m_position -= m_moveSpeed * m_up;
updateViewMatrix();
}
void FirstPersonCamera::KeyPressed(uint32_t key)
{
if (isInvalid()) return;
switch (key)
{
case KeyForward:
case KeyLeft:
case KeyBackwards:
case KeyRight:
case KeyUp:
case KeyDown:
break;
default: return;
}
m_move_keys[key] = true;
}
void FirstPersonCamera::keyReleased(uint32_t key)
{
if (isInvalid()) return;
switch (key)
{
case KeyForward:
case KeyLeft:
case KeyBackwards:
case KeyRight:
case KeyUp:
case KeyDown:
break;
default: return;
}
m_move_keys[key] = false;
}
OrthoCamera::OrthoCamera(float left, float right, float bottom, float top, float near, float far)
{
create(left, right, bottom, top, near, far);
}
OrthoCamera& OrthoCamera::createDefault(float windowWidth, float WindowHeight, bool soft)
{
return create(0.0f, windowWidth * 1.0f, WindowHeight * 1.0f, 0.0f, -1.0f, 1.0f, soft);
}
OrthoCamera& OrthoCamera::create(float left, float right, float bottom, float top, float near, float far, bool soft)
{
m_projection = glm::ortho(left, right, bottom, top, near, far);
__update_view_proj_mat();
enableSignals();
if (!soft)
connectSignal(tBuiltinSignals::WindowResized);
setTypeName("ox::OrthoCamera");
validate();
return *this;
}
void OrthoCamera::handleSignal(ostd::tSignal& signal)
{
if (signal.ID == tBuiltinSignals::WindowResized)
{
WindowSizeObj wsobj = static_cast<WindowSizeObj&>(signal.userData);
createDefault(wsobj.width, wsobj.height, true);
}
}
String OrthoCamera::toString(void) const
{
StringEditor se = getTypeName();
se.add(" position = { ");
se.addf(m_position.x).add(", ");
se.addf(m_position.y).add(", ");
se.addf(m_position.z).add(" } rotation = { ").addf(m_rotation).add(" } ");
return se.str();
}
void OrthoCamera::__update_view_proj_mat(void)
{
glm::mat4 transform = glm::translate(glm::mat4(1.0f), m_position);
transform = glm::rotate(transform, glm::radians(m_rotation), glm::vec3(0, 0, 1));
m_view = glm::inverse(transform);
m_viewProj = m_projection * m_view;
}
}

98
src/ogfx/Camera.hpp Executable file
View file

@ -0,0 +1,98 @@
#ifndef __CAMERA_HPP__
#define __CAMERA_HPP__
#include <ostd/Geometry.hpp>
#include <ostd/BaseObject.hpp>
#include <vendor/glm/glm.hpp>
namespace ogfx
{
using namespace ostd; //TODO: Remove from header
class Window;
class FirstPersonCamera : BaseObject
{
public:
inline FirstPersonCamera(void) { invalidate(); }
inline FirstPersonCamera(Window& window, bool invert_y = false) { create(window, invert_y); }
FirstPersonCamera& create(Window& window, bool invert_y = false);
void mouseMoved(float x, float y);
void updateViewMatrix(void);
void updateProjectionMatrix(float fov = 0.0f, float near = 0.0f, float far = 0.0f);
inline glm::mat4& getViewMat(void) { return m_viewMat; }
inline glm::mat4& getProjMat(void) { return m_perspMat; }
void update(void);
void KeyPressed(uint32_t key);
void keyReleased(uint32_t key);
inline ostd::Vec3 getPosition(void) { return { m_position.x, m_position.y, m_position.z }; }
inline ostd::Vec3 getFront(void) { return { m_front.x, m_front.y, m_front.z }; }
private:
glm::vec3 m_position { 0.0f, 0.0f, 10.0f };
glm::vec3 m_front { 0.0f, 0.0f, -1.0f };
glm::vec3 m_up { 0.0f, 1.0f, 0.0f };
float m_yaw { -90.0f };
float m_pitch { 0.0f };
float m_moveSpeed { 0.4f };
float m_moveSensitivity { 0.02f };
bool m_invert_y { false };
bool m_reset_mouse { true };
bool m_move_keys[6] { false, false, false, false, false, false };
glm::mat4 m_viewMat { 1.0f };
glm::mat4 m_perspMat { 1.0f };
Window* m_window { nullptr };
public:
inline static constexpr uint32_t KeyForward = 0;
inline static constexpr uint32_t KeyBackwards = 2;
inline static constexpr uint32_t KeyLeft = 1;
inline static constexpr uint32_t KeyRight = 3;
inline static constexpr uint32_t KeyUp = 4;
inline static constexpr uint32_t KeyDown = 5;
};
class OrthoCamera : public BaseObject
{
public:
inline OrthoCamera(void) { invalidate(); }
//inline OrthoCamera(float left, float right, float bottom, float top, float near = -1.0f, float far = 1.0f) { create(left, right, bottom, top, near, far); }
OrthoCamera(float left, float right, float bottom, float top, float near = -1.0f, float far = 1.0f);
OrthoCamera& createDefault(float windowWidth, float windowHeight, bool soft = false);
void handleSignal(ostd::tSignal& signal) override;
inline const glm::vec3& getPosition(void) const { return m_position; }
inline void setPosition(const glm::vec3& pos) { m_position = pos; __update_view_proj_mat(); }
inline float getRotation(void) const { return m_rotation; }
inline void setRotation(float rot) { m_rotation = rot; __update_view_proj_mat(); }
inline const glm::mat4& getProjectionMatrix(void) const { return m_projection; }
inline const glm::mat4& getViewMatrix(void) const { return m_view; }
inline const glm::mat4& getViewProjectionMatrix(void) const { return m_viewProj; }
String toString(void) const override;
private:
void __update_view_proj_mat(void);
OrthoCamera& create(float left, float ight, float bottom, float top, float near = -1.0f, float far = 1.0f, bool soft = false);
private:
glm::mat4 m_projection { 1.0f };
glm::mat4 m_view { 1.0f };
glm::mat4 m_viewProj { 1.0f };
glm::vec3 m_position { 0.0f, 0.0f, 0.0f };
float m_rotation { 0.0f };
};
typedef OrthoCamera Camera2D;
}
#endif

225
src/ogfx/DataStructures.hpp Executable file
View file

@ -0,0 +1,225 @@
#ifndef __DATA_STRUCTURES_HPP__
#define __DATA_STRUCTURES_HPP__
#include <vendor/glm/matrix.hpp>
#include <ostd/Geometry.hpp>
#include <ostd/Color.hpp>
#include <ogfx/GLBuffers.hpp>
#include <vendor/glm/gtc/matrix_transform.hpp>
namespace ogfx
{
using namespace ostd; //TODO: Remove from header
struct tVertex
{
Vec3 position;
Color::FloatCol color;
Vec2 texCoords;
Vec3 normal;
inline static VertexBufferLayout getVertexBufferLayout(void)
{
VertexBufferLayout layout;
layout.push<float>(3);
layout.push<float>(4);
layout.push<float>(2);
layout.push<float>(3);
return layout;
}
};
struct tVertex2D
{
Vec3 position;
Color::FloatCol color;
Vec2 texCoords;
float texIndex { 0.0f };
inline static VertexBufferLayout getVertexBufferLayout(void)
{
VertexBufferLayout layout;
layout.push<float>(3);
layout.push<float>(4);
layout.push<float>(2);
layout.push<float>(1);
return layout;
}
};
struct tPerspective
{
float FOV { 45.0f };
float windowWidth { 0 };
float windowHeight { 0 };
float nearPlane { 0.1f };
float farPlane { 300.0f };
inline tPerspective(int32_t win_w, float win_h) { windowWidth = win_w; windowHeight = win_h; update(); }
inline tPerspective(float fov, float win_w, float win_h, float near, float far)
{
FOV = fov;
windowWidth = win_w;
windowHeight = win_h;
nearPlane = near;
farPlane = far;
update();
}
inline void update(void) { m_matrix = glm::perspective(FOV, getAspectRatio(), nearPlane, farPlane); }
inline float getAspectRatio(void) { return windowWidth / windowHeight; }
inline const glm::mat4& getMatrix(void) { return m_matrix; }
private:
glm::mat4 m_matrix;
};
class Transform2D
{
private:
float m_rotation { 0.0f };
Vec2 m_translation { 0.0f, 0.0f };
Vec2 m_scale { 1.0f, 1.0f };
bool m_centeredOrigin { false };
Vec2 m_baseSize { 0.0f, 0.0f };
bool m_applied { false };
glm::mat4 m_matrix;
std::vector<Vec2> m_vertices;
public:
inline Transform2D(void) { apply(); }
inline Transform2D& resetRotation(float newValue = 0.0f) { m_applied = (m_rotation == newValue && m_applied); m_rotation = newValue; return *this; }
inline Transform2D& resetTranslation(Vec2 newValue = { 0.0f, 0.0f }) { m_applied = (m_translation == newValue && m_applied); m_translation = newValue; return *this; }
inline Transform2D& resetScale(Vec2 newValue = { 1.0f, 1.0f }) { m_applied = (m_scale == newValue && m_applied); m_scale = newValue; return *this; }
inline Transform2D& reset(float _rotation = 0.0f, Vec2 _translation = { 0.0f, 0.0f }, Vec2 _scale = { 1.0f,1.0f }) { resetRotation(_rotation); resetTranslation(_translation); return resetScale(_scale); }
inline Transform2D& rotate(float value) { m_applied = (value == 0.0f && m_applied); m_rotation += value; return *this; }
inline Transform2D& translate(Vec2 value) { m_applied = (value == Vec2(0.0f, 0.0f) && m_applied); m_translation += value; return *this; }
inline Transform2D& scale(Vec2 value) { m_applied = (value == Vec2(0.0f, 0.0f) && m_applied); m_scale += value; return *this; }
inline float getRotation(void) const { return m_rotation; }
inline Vec2 getTranslation(void) const { return m_translation; }
inline Vec2 getScale(void) const { return m_scale; }
inline bool isOriginCentered(void) const { return m_centeredOrigin; }
inline bool isApplied(void) const { return m_applied; }
inline glm::mat4 getMatrix(void) const { return m_matrix; }
inline std::vector<Vec2> getVertices(void) const { return m_vertices; }
inline Vec2 getBaseSize(void) const { return m_baseSize; }
inline Transform2D& setOriginCentered(bool b = true) { m_applied = (m_centeredOrigin == b && m_applied); m_centeredOrigin = b; return *this; }
inline Transform2D& setBaseSize(Vec2 baseSize) { m_applied = (m_baseSize == baseSize && m_applied); m_baseSize = baseSize; return *this; }
inline Transform2D& apply(void)
{
if (m_applied) return *this;
glm::vec4 npos(0.0f, 0.0f, 0.0f, 1.0f);
glm::mat4 model = glm::translate(glm::mat4(1.0f), { m_translation.x, m_translation.y, 0.0f });
model = glm::rotate(model, DEG_TO_RAD(m_rotation), { 0.0f, 0.0f, 1.0f });
model = glm::scale(model, { m_scale.x, m_scale.y, 1.0f });
m_vertices.clear();
if (m_centeredOrigin)
{
npos = { -(m_baseSize.x / 2.0f), -(m_baseSize.y / 2.0f), 0.0f, 1.0f };
npos = model * npos;
m_vertices.push_back({ npos.x, npos.y });
npos = { m_baseSize.x / 2.0f, -(m_baseSize.y / 2.0f), 0.0f, 1.0f };
npos = model * npos;
m_vertices.push_back({ npos.x, npos.y });
npos = { m_baseSize.x / 2.0f, m_baseSize.y / 2.0f, 0.0f, 1.0f };
npos = model * npos;
m_vertices.push_back({ npos.x, npos.y });
npos = { -(m_baseSize.x / 2.0f), m_baseSize.y / 2.0f, 0.0f, 1.0f };
npos = model * npos;
m_vertices.push_back({ npos.x, npos.y });
}
else
{
npos = { 0.0f, 0.0f, 0.0f, 1.0f };
npos = model * npos;
m_vertices.push_back({ npos.x, npos.y });
npos = { m_baseSize.x, 0.0f, 0.0f, 1.0f };
npos = model * npos;
m_vertices.push_back({ npos.x, npos.y });
npos = { m_baseSize.x, m_baseSize.y, 0.0f, 1.0f };
npos = model * npos;
m_vertices.push_back({ npos.x, npos.y });
npos = { 0.0f, m_baseSize.y, 0.0f, 1.0f };
npos = model * npos;
m_vertices.push_back({ npos.x, npos.y });
}
m_applied = true;
return *this;
}
};
class Transform3D
{
private:
Vec3 m_rotation { 0.0f, 0.0f, 0.0f };
Vec3 m_translation { 0.0f, 0.0f, 0.0f };
Vec3 m_scale { 1.0f, 1.0f, 1.0f };
bool m_updateNormalMatrix { true };
bool m_applied { true };
glm::mat4 m_matrix;
glm::mat4 m_normalMatrix;
public:
inline Transform3D(void) { m_matrix = glm::mat4(1.0f); m_normalMatrix = m_matrix; }
inline Transform3D& loadIdentity(void) { m_matrix = glm::mat4(1.0f); m_applied = true; m_rotation = { 0.0f, 0.0f, 0.0f }; m_translation = { 0.0f, 0.0f, 0.0f }; m_scale = { 1.0f, 1.0f, 1.0f }; m_normalMatrix = m_matrix; m_updateNormalMatrix = false; m_applied = true; return *this; }
inline Transform3D& rotate(Vec3 value) { m_applied = (value == Vec3(0.0f, 0.0f, 0.0f) && m_applied); m_updateNormalMatrix = !m_applied; m_rotation += value; return *this; }
inline Transform3D& translate(Vec3 value) { m_applied = (value == Vec3(0.0f, 0.0f, 0.0f) && m_applied); m_translation += value; return *this; }
inline Transform3D& scale(Vec3 value) { m_applied = (value == Vec3(0.0f, 0.0f, 0.0f) && m_applied); m_updateNormalMatrix = !m_applied; m_scale += value; return *this; }
inline Vec3 getRotation(void) const { return m_rotation; }
inline Vec3 getTranslation(void) const { return m_translation; }
inline Vec3 getScale(void) const { return m_scale; }
inline bool isApplied(void) const { return m_applied; }
inline glm::mat4 getMatrix(void) const { return m_matrix; }
inline glm::mat4 getNormalMatrix(void) const { return m_normalMatrix; }
inline Transform3D& apply(void)
{
if (m_applied) return *this;
m_matrix = glm::translate(glm::mat4(1.0f), { m_translation.x, m_translation.y, m_translation.z });
m_matrix = glm::scale(m_matrix, { m_scale.x, m_scale.y, m_scale.z });
m_matrix = glm::rotate(m_matrix, DEG_TO_RAD(m_rotation.z), { 0.0f, 0.0f, 1.0f });
m_matrix = glm::rotate(m_matrix, DEG_TO_RAD(m_rotation.y), { 0.0f, 1.0f, 0.0f });
m_matrix = glm::rotate(m_matrix, DEG_TO_RAD(m_rotation.x), { 1.0f, 0.0f, 0.0f });
if (m_updateNormalMatrix)
{
m_normalMatrix = glm::transpose(glm::inverse(m_matrix));
m_updateNormalMatrix = false;
}
m_applied = true;
return *this;
}
};
struct tContextSettings
{
struct tGLProfile
{
inline static constexpr uint8_t Core = 0;
inline static constexpr uint8_t Compatibility = 1;
};
uint8_t depthBits { 24 };
uint8_t stencilBits { 8 };
uint8_t antiAliasLevel { 0 }; //TODO: Add "enums"
uint8_t GLMajorVersion = { 4 };
uint8_t GLMinorVersion { 2 };
uint8_t GLProfile { tGLProfile::Core };
};
}
#endif

240
src/ogfx/DebugTools.cpp Normal file
View file

@ -0,0 +1,240 @@
#include "DebugTools.hpp"
#include <ostd/Signals.hpp>
#include <ogfx/RenderCore.hpp>
#include <ogfx/GraphicsApplication.hpp>
namespace ogfx
{
void DebugInfoWidget::init(ogfx::oxgui::Widget& parent)
{
if (parent.isInvalid())
{
invalidate();
}
setPosition({ 0, 0 });
setSize(parent.getContentSize());
connectSignals();
connectSignal(DebugTools::OnProfileDataRecieved);
setTypeName("ogfx::DebugInfoWidget");
validate();
enable();
parent.addWidget(*this);
}
void DebugInfoWidget::renderContent(ogfx::RenderCore& gfx)
{
if (m_dataList == nullptr) return;
Renderer2D::tTextInfo textInfo;
textInfo.characterHeight = 24;
textInfo.characterSpacing = 6;
textInfo.font = ogfx::ResourceManager::getDefaultBitmapFont();
ogfx::Renderer2D::Text::characterHeight = textInfo.characterHeight;
ogfx::Renderer2D::Text::characterSpacing = textInfo.characterSpacing;
ogfx::Renderer2D::Text::font = textInfo.font;
auto stateGradientPixels = ogfx::ResourceManager::getTexture(ogfx::ResourceManager::getStateGradientTexture()).getPixelData();
ostd::Vec2 pos = getPosition() + ostd::Vec2 { 10, 20 };
bool line = true;
float max_avg = 0;
for (auto& data : m_dataList->data)
{
if (ostd::StringEditor(data.second.name).startsWith("Total Frame Time"))
continue;
float avg = data.second.getAvgTime();
if (avg > max_avg)
max_avg = avg;
}
for (auto& data : m_dataList->data)
{
if (!line)
gfx.drawQuad({ getx() + 1, pos.y }, { getw() - 2, 20 }, { 30, 30, 30, 255 }, false);
line = !line;
float avg_val = data.second.getAvgTime();
uint32_t mapped = std::round(ostd::Utils::map_value(avg_val, 0.0f, max_avg, 1.0f, 198.0f)) * 4;
textInfo.characterSpacing = 6;
textInfo.font = ogfx::ResourceManager::getDefaultBitmapFont();
ogfx::Renderer2D::Text::characterSpacing = textInfo.characterSpacing;
ogfx::Renderer2D::Text::font = textInfo.font;
textInfo.color = { stateGradientPixels[mapped], stateGradientPixels[mapped + 1], stateGradientPixels[mapped + 2] };
if (ostd::StringEditor(data.second.name).startsWith("Total Frame Time"))
textInfo.color = { 200, 200, 200 };
ostd::StringEditor str(data.second.name);
str.add(": ");
gfx.drawText(str.str(), pos, textInfo);
str.clr().addf(avg_val).add(" ms");
textInfo.characterSpacing = -10;
textInfo.font = ogfx::ResourceManager::getDefaultBitmapFontMono();
ogfx::Renderer2D::Text::characterSpacing = textInfo.characterSpacing;
ogfx::Renderer2D::Text::font = textInfo.font;
float w = ogfx::Renderer2D::Text::getStringBounds(str.str()).x;
gfx.drawText(str.str(), { getx() + getw() - w + 35, pos.y }, textInfo);
pos += ostd::Vec2 { 0, 20 };
}
textInfo.characterHeight = 24;
textInfo.characterSpacing = 6;
textInfo.font = ogfx::ResourceManager::getDefaultBitmapFont();
textInfo.color = { 30, 150, 200 };
ogfx::Renderer2D::Text::characterHeight = textInfo.characterHeight;
ogfx::Renderer2D::Text::characterSpacing = textInfo.characterSpacing;
ogfx::Renderer2D::Text::font = textInfo.font;
ostd::StringEditor str;
gfx.drawQuad({ getx() + 1, pos.y }, { getw() - 2, 20 }, { 30, 30, 70, 200 }, false);
gfx.drawText("FPS: ", pos, textInfo);
str.addi(DebugTools::m_fps);
textInfo.characterSpacing = -5;
textInfo.font = ogfx::ResourceManager::getDefaultBitmapFontMono();
textInfo.color = { 190, 0, 190 };
ogfx::Renderer2D::Text::characterSpacing = textInfo.characterSpacing;
ogfx::Renderer2D::Text::font = textInfo.font;
float w = ogfx::Renderer2D::Text::getStringBounds(str.str()).x;
// std::cout << str << "\n";
gfx.drawText(str.str(), { getx() + getw() - 10 - w, pos.y }, textInfo);
textInfo.color = { 30, 150, 200 };
textInfo.font = ogfx::ResourceManager::getDefaultBitmapFont();
textInfo.characterSpacing = 6;
str.clr();
pos += ostd::Vec2 { 0, 20 };
gfx.drawText("UPS: ", pos, textInfo);
str.addi(DebugTools::m_ups);
textInfo.characterSpacing = -5;
textInfo.font = ogfx::ResourceManager::getDefaultBitmapFontMono();
textInfo.color = { 190, 0, 190 };
ogfx::Renderer2D::Text::characterSpacing = textInfo.characterSpacing;
ogfx::Renderer2D::Text::font = textInfo.font;
w = ogfx::Renderer2D::Text::getStringBounds(str.str()).x;
gfx.drawText(str.str(), { getx() + getw() - 10 - w, pos.y }, textInfo);
textInfo.color = { 30, 150, 200 };
textInfo.font = ogfx::ResourceManager::getDefaultBitmapFont();
textInfo.characterSpacing = 6;
str.clr();
pos += ostd::Vec2 { 0, 20 };
gfx.drawQuad({ getx() + 1, pos.y }, { getw() - 2, 20 }, { 30, 30, 70, 200 }, false);
gfx.drawText("Uniform Updates: ", pos, textInfo);
str.addi(DebugTools::m_uniformUpdates);
textInfo.characterSpacing = -5;
textInfo.font = ogfx::ResourceManager::getDefaultBitmapFontMono();
textInfo.color = { 190, 0, 190 };
ogfx::Renderer2D::Text::characterSpacing = textInfo.characterSpacing;
ogfx::Renderer2D::Text::font = textInfo.font;
w = ogfx::Renderer2D::Text::getStringBounds(str.str()).x;
gfx.drawText(str.str(), { getx() + getw() - 10 - w, pos.y }, textInfo);
textInfo.color = { 30, 150, 200 };
textInfo.font = ogfx::ResourceManager::getDefaultBitmapFont();
textInfo.characterSpacing = 6;
str.clr();
pos += ostd::Vec2 { 0, 20 };
gfx.drawText("Render Queue: ", pos, textInfo);
str.addi(DebugTools::m_renderCmdCount);
textInfo.characterSpacing = -5;
textInfo.font = ogfx::ResourceManager::getDefaultBitmapFontMono();
textInfo.color = { 190, 0, 190 };
ogfx::Renderer2D::Text::characterSpacing = textInfo.characterSpacing;
ogfx::Renderer2D::Text::font = textInfo.font;
w = ogfx::Renderer2D::Text::getStringBounds(str.str()).x;
gfx.drawText(str.str(), { getx() + getw() - 10 - w, pos.y }, textInfo);
textInfo.color = { 30, 150, 200 };
textInfo.font = ogfx::ResourceManager::getDefaultBitmapFont();
textInfo.characterSpacing = 6;
str.clr();
pos += ostd::Vec2 { 0, 20 };
gfx.drawQuad({ getx() + 1, pos.y }, { getw() - 2, 20 }, { 30, 30, 70, 200 }, false);
gfx.drawText("Draw Calls: ", pos, textInfo);
str.addi(ogfx::Renderer2D::getRenderStats().drawCalls);
textInfo.characterSpacing = -5;
textInfo.font = ogfx::ResourceManager::getDefaultBitmapFontMono();
textInfo.color = { 190, 0, 190 };
ogfx::Renderer2D::Text::characterSpacing = textInfo.characterSpacing;
ogfx::Renderer2D::Text::font = textInfo.font;
w = ogfx::Renderer2D::Text::getStringBounds(str.str()).x;
gfx.drawText(str.str(), { getx() + getw() - 10 - w, pos.y }, textInfo);
textInfo.color = { 30, 150, 200 };
textInfo.font = ogfx::ResourceManager::getDefaultBitmapFont();
textInfo.characterSpacing = 6;
str.clr();
pos += ostd::Vec2 { 0, 20 };
gfx.drawText("Quad Count: ", pos, textInfo);
str.addi(ogfx::Renderer2D::getRenderStats().quadCount);
textInfo.characterSpacing = -5;
textInfo.font = ogfx::ResourceManager::getDefaultBitmapFontMono();
textInfo.color = { 190, 0, 190 };
ogfx::Renderer2D::Text::characterSpacing = textInfo.characterSpacing;
ogfx::Renderer2D::Text::font = textInfo.font;
w = ogfx::Renderer2D::Text::getStringBounds(str.str()).x;
gfx.drawText(str.str(), { getx() + getw() - 10 - w, pos.y }, textInfo);
textInfo.color = { 30, 150, 200 };
textInfo.font = ogfx::ResourceManager::getDefaultBitmapFont();
textInfo.characterSpacing = 6;
str.clr();
pos += ostd::Vec2 { 0, 20 };
gfx.drawQuad({ getx() + 1, pos.y }, { getw() - 2, 20 }, { 30, 30, 70, 200 }, false);
gfx.drawText("RenderBuffer Binds: ", pos, textInfo);
str.addi(ogfx::Renderer2D::getRenderStats().renderBufferBinds);
textInfo.characterSpacing = -5;
textInfo.font = ogfx::ResourceManager::getDefaultBitmapFontMono();
textInfo.color = { 190, 0, 190 };
ogfx::Renderer2D::Text::characterSpacing = textInfo.characterSpacing;
ogfx::Renderer2D::Text::font = textInfo.font;
w = ogfx::Renderer2D::Text::getStringBounds(str.str()).x;
gfx.drawText(str.str(), { getx() + getw() - 10 - w, pos.y }, textInfo);
textInfo.color = { 30, 150, 200 };
textInfo.font = ogfx::ResourceManager::getDefaultBitmapFont();
textInfo.characterSpacing = 6;
str.clr();
pos += ostd::Vec2 { 0, 20 };
gfx.drawText("Shader Binds: ", pos, textInfo);
str.addi(ogfx::Renderer2D::getRenderStats().shaderBinds);
textInfo.characterSpacing = -5;
textInfo.font = ogfx::ResourceManager::getDefaultBitmapFontMono();
textInfo.color = { 190, 0, 190 };
ogfx::Renderer2D::Text::characterSpacing = textInfo.characterSpacing;
ogfx::Renderer2D::Text::font = textInfo.font;
w = ogfx::Renderer2D::Text::getStringBounds(str.str()).x;
gfx.drawText(str.str(), { getx() + getw() - 10 - w, pos.y }, textInfo);
textInfo.color = { 30, 150, 200 };
textInfo.font = ogfx::ResourceManager::getDefaultBitmapFont();
textInfo.characterSpacing = 6;
str.clr();
pos += ostd::Vec2 { 0, 20 };
}
void DebugInfoWidget::onSignal(ostd::tSignal& signal)
{
if (signal.ID == DebugTools::OnProfileDataRecieved && m_dataList == nullptr)
{
m_dataList = (DebugTimesList*)(&signal.userData);
}
}
void DebugTools::showDebugWindow(GraphicsApplication2D* parent_app, bool show)
{
if (parent_app == nullptr) return;
if (!m_debugWindowEnabled) return;
parent_app->m_debugToolsWindow.enable(show);
m_debugWindowTabPanel.selectTab((show ? 0 : 1));
}
}

94
src/ogfx/DebugTools.hpp Normal file
View file

@ -0,0 +1,94 @@
#pragma once
#include <ostd/Utils.hpp>
#include <unordered_map>
#include <ostd/BaseObject.hpp>
#include <ogfx/RTData.hpp>
#include <ogfx/Widgets.hpp>
namespace ogfx
{
class DebugTimeEntry
{
public:
ostd::String name { "UNNAMED" };
double totalTime { 0 };
uint32_t sampleCount { 0 };
double avgTime { 0 };
inline double getAvgTime(void)
{
return avgTime;
}
inline void computeAvgTime(void)
{
if (sampleCount <= 0) return;
avgTime = totalTime / sampleCount;
}
};
class DebugTimesList : public ostd::BaseObject
{
public:
std::unordered_map<uint32_t, DebugTimeEntry> data;
inline void updateEntry(uint32_t id, DebugTimeEntry entry = DebugTimeEntry()) { data[id] = entry; }
inline DebugTimeEntry& get(uint32_t id) { return data[id]; }
};
class DebugInfoWidget : public ogfx::oxgui::Widget
{
public:
inline DebugInfoWidget(void) { }
void init(ogfx::oxgui::Widget& parent);
void renderContent(ogfx::RenderCore& gfx) override;
void onSignal(ostd::tSignal& signal) override;
private:
DebugTimesList* m_dataList { nullptr };
};
class GraphicsApplication2D;
class DebugTools
{
public:
static void showDebugWindow(GraphicsApplication2D* parent_app, bool show = true);
inline static ostd::Timer m_profileTimer;
inline static ostd::Timer m_totalFrameTimer;
inline static DebugTimesList m_timesList;
inline static uint32_t m_fps { 0 };
inline static uint32_t m_ups { 0 };
inline static uint32_t m_uniformUpdates { 0 };
inline static uint32_t m_renderCmdCount { 0 };
inline static bool m_debugWindowEnabled { false };
inline static bool m_drawBasicFrameInfo { false };
inline static DebugInfoWidget m_debugInfoWidget;
inline static ogfx::oxgui::TabPanel m_debugWindowTabPanel;
inline static ogfx::oxgui::TabWidget m_debugWindowInfoTab;
inline static ogfx::oxgui::TabWidget m_debugWindowWatcherTab;
inline static ogfx::oxgui::TabWidget m_debugWindowTab3;
inline static constexpr uint32_t FramerateCalculations = 0;
inline static constexpr uint32_t OnSecondsUpdate = 1;
inline static constexpr uint32_t EventHandling = 2;
inline static constexpr uint32_t OnSignalsRefresh = 23;
inline static constexpr uint32_t OnUpdate = 4;
inline static constexpr uint32_t OnRender = 5;
inline static constexpr uint32_t OnDisplay = 6;
inline static constexpr uint32_t OnFrameFinalize = 7;
inline static constexpr uint32_t OnWindowDisplay = 8;
inline static constexpr uint32_t TotalFrameTime = 128;
inline static const uint32_t OnProfileDataRecieved = ogfx::RTData::newCustomSignal(2200);
inline static void enableDebugWindow(bool enable = true) { m_debugWindowEnabled = enable; }
};
}

81
src/ogfx/Errors.cpp Executable file
View file

@ -0,0 +1,81 @@
#include "Errors.hpp"
#include <Utils.hpp>
#include <ogfx/Shader.hpp>
#include <Defines.hpp>
#include <Logger.hpp>
#include <ogfx/GLBuffers.hpp>
#include <ogfx/Texture.hpp>
#include <ogfx/BitmapFont.hpp>
namespace ogfx
{
using namespace ostd;
String ErrorHandler::mapError(int32_t err_code)
{
StringEditor se;
se.add(Utils::getHexStr(err_code, true, 4)).add(": ");
switch (err_code)
{
case OX_NO_ERROR: return "";
/** ox::Shader Errors **/
case Shader::ERR_SHADER_COMPILE_FAILED: return se.add("A Shader failed to compile").str();
case Shader::ERR_SHADER_SOURCE_READ_FILED: return se.add("Failed to read shader source code").str();
case Shader::ERR_FAILED_TO_REGISTER_UNIFORM: return se.add("Failed to register uniform").str();
case Shader::ERR_FAILED_TO_UPDATE_UNIFORM: return se.add("Failed to update uniform").str();
/** ox::VertexArray Errors **/
case VertexArray::ERR_NO_EBO_SET: return se.add("No ElementBuffer set in VertexArray.").str();
/** ox::Texture Errors **/
case Texture::ERR_IMAGE_LOAD_FAILED: return se.add("Failed to load Texture.").str();
case Texture::ERR_NO_DATA_STORED: return se.add("Attempting to retrieve local Texture data of a non-stored instance.").str();
/** ox::BitmapFont Errors **/
case BitmapFont::ERR_INVALID_TEXTURE: return se.add("Invalid BitmapFont Texture.").str();
case BitmapFont::ERR_INVALID_TEXTURE_SIZE: return se.add("Invalid Size for ox::BitmapFont Texture: width and height must both be multiples of 16.").str();
/** Custom or undefined Errors **/
default:
{
if (ErrorHandler::s_customMapErrorCallback != nullptr)
return (*ErrorHandler::s_customMapErrorCallback)(err_code);
}
}
return "Unknown Error.";
}
void ErrorHandler::pushError(int32_t err_code)
{
if (err_code != OX_NO_ERROR)
s_errorStack.push_back(err_code);
}
String ErrorHandler::getLastErrorString(void)
{
if (ErrorHandler::s_errorStack.size() == 0) return "";
return ErrorHandler::mapError(ErrorHandler::s_errorStack[s_errorStack.size() - 1]);
}
void ErrorHandler::__gl_clearErrors(void)
{
while(glGetError() != GL_NO_ERROR);
}
bool ErrorHandler::__gl_printError(const char* func_call, const char* file_path, int32_t line_number)
{
bool res = false;
StringEditor se;
while (GLenum err_code = glGetError())
{
se = "[OpenGL]: (err_code = ";
se.add(Utils::getHexStr(err_code, true, 4)).add(")");
OX_ERROR("%s:\nFile: %s on Line %d\n\t%s;\n", se.c_str(), file_path, line_number, func_call);
res = true;
}
return res;
}
}

45
src/ogfx/Errors.hpp Executable file
View file

@ -0,0 +1,45 @@
#ifndef __ERRORS_HPP__
#define __ERRORS_HPP__
#include <ostd/Types.hpp>
#include <vector>
#ifdef __DEBUG__
#define GLCall( x ) \
ogfx::ErrorHandler::__gl_clearErrors(); \
x; \
if ( ogfx::ErrorHandler::__gl_printError( #x, __FILE__, __LINE__) ) __builtin_trap();
#define GLCallRV( x ) [&]() { \
ogfx::ErrorHandler::__gl_clearErrors(); \
auto retVal = x; \
if ( ogfx::ErrorHandler::__gl_printError( #x, __FILE__, __LINE__) ) __builtin_trap(); \
return retVal; \
}()
#else
#define GLCall( x ) x
#define GLCallRV( x ) x
#endif
namespace ogfx
{
using namespace ostd; //TODO: Remove
typedef String(*fpCustomMapErrorCallback)(int32_t);
class ErrorHandler
{
public:
static String mapError(int32_t err_code);
static void pushError(int32_t err_code);
static String getLastErrorString(void);
inline static void setCustomMapErrorCallback(fpCustomMapErrorCallback callback) { s_customMapErrorCallback = callback; }
static void __gl_clearErrors(void);
static bool __gl_printError(const char* func_call, const char* file_path, int32_t line_number);
private:
inline static fpCustomMapErrorCallback s_customMapErrorCallback { nullptr };
inline static std::vector<int32_t> s_errorStack;
};
}
#endif

167
src/ogfx/GLBuffers.cpp Executable file
View file

@ -0,0 +1,167 @@
#include "GLBuffers.hpp"
#include "Errors.hpp"
//TODO: Implement Errors
namespace ogfx
{
using namespace ostd;
VertexBuffer::~VertexBuffer(void)
{
if (isInvalid()) return;
uint32_t gl_id = getOpenGLID();
GLCall(glDeleteBuffers(1, &gl_id));
}
VertexBuffer& VertexBuffer::create(const void* data, uint32_t byte_size, bool dynamic)
{
uint32_t gl_id;
GLCall(glGenBuffers(1, &gl_id));
setID(gl_id);
bind();
GLCall(glBufferData(GL_ARRAY_BUFFER, byte_size, data, (dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW)));
unbind();
setTypeName("ox::VertexBuffer");
validate();
return *this;
}
void VertexBuffer::bind(void) const
{
GLCall(glBindBuffer(GL_ARRAY_BUFFER, getOpenGLID()));
}
void VertexBuffer::unbind(void) const
{
GLCall(glBindBuffer(GL_ARRAY_BUFFER, 0));
}
ElementBuffer::~ElementBuffer(void)
{
if (isInvalid()) return;
uint32_t gl_id = getOpenGLID();
GLCall(glDeleteBuffers(1, &gl_id));
}
ElementBuffer& ElementBuffer::create(const void* data, uint32_t elem_count)
{
m_elem_count = elem_count;
uint32_t gl_id;
GLCall(glGenBuffers(1, &gl_id));
setID(gl_id);
bind();
GLCall(glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_elem_count * sizeof(uint32_t), data, GL_STATIC_DRAW));
unbind();
setTypeName("ox::ElementBuffer");
validate();
return *this;
}
void ElementBuffer::bind(void) const
{
GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, getOpenGLID()));
}
void ElementBuffer::unbind(void) const
{
GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
}
uint32_t tVertexBufferElem::gl_typeToSize(uint32_t type)
{
switch (type)
{
case GL_FLOAT: return sizeof(GLfloat);
case GL_UNSIGNED_INT: return sizeof(GLuint);
case GL_INT: return sizeof(GLint);
case GL_BYTE: return sizeof(GLbyte);
case GL_UNSIGNED_BYTE: return sizeof(GLubyte);
default: break;
}
OX_WARN("Unkwnown type in tVertexBufferElem");
return 0;
}
VertexArray::VertexArray(bool init)
{
if (!init) return;
create();
}
VertexArray::~VertexArray(void)
{
if (isInvalid()) return;
uint32_t gl_id = getOpenGLID();
GLCall(glDeleteVertexArrays(1, &gl_id));
}
VertexArray& VertexArray::create(void)
{
uint32_t gl_id;
GLCall(glGenVertexArrays(1, &gl_id));
setID(gl_id);
setTypeName("ox::VertexArray");
return *this;
}
uint32_t VertexArray::addBuffer(VertexBuffer& vbo, const VertexBufferLayout& layout)
{
bind();
vbo.bind();
const auto& elements = layout.getElements();
uint64_t offset = 0;
for (uint32_t i = 0; i < elements.size(); i++)
{
const auto& elem = elements[i];
GLCall(glEnableVertexAttribArray(i));
GLCall(glVertexAttribPointer(i, elem.count, elem.type, elem.normalized, layout.getStride(), (const void*)offset));
offset += elem.count * tVertexBufferElem::gl_typeToSize(elem.type);
}
unbind();
vbo.unbind();
m_vertexBuffers.push_back(&vbo);
return m_vertexBuffers.size() - 1;
}
void VertexArray::setElementBuffer(const ElementBuffer& ebo)
{
if (!ebo.isValid())
{
OX_WARN("Invalid ElementBuffer object passed in VertexArray.");
return;
}
bind();
ebo.bind();
unbind();
ebo.unbind();
validate();
}
void VertexArray::bind(void) const
{
GLCall(glBindVertexArray(getOpenGLID()));
}
void VertexArray::unbind(void) const
{
GLCall(glBindVertexArray(0));
}
VertexBuffer& VertexArray::getVerteBuffer(uint32_t internal_index)
{
if (internal_index >= m_vertexBuffers.size()) return (VertexBuffer&)BaseObject::InvalidRef();
return *(m_vertexBuffers[internal_index]);
}
uint32_t VertexArray::getElementCount(void) const
{
return m_elem_count;
}
}

120
src/ogfx/GLBuffers.hpp Executable file
View file

@ -0,0 +1,120 @@
#ifndef __GL_BUFFERS_HPP__
#define __GL_BUFFERS_HPP__
#include <vector>
#include <ostd/BaseObject.hpp>
#include <vendor/GLAD/glad/glad.h>
#include <ostd/Defines.hpp>
#include <ostd/Logger.hpp>
namespace ogfx
{
using namespace ostd; //TODO: Remove this from header
class VertexBuffer : public BaseObject
{
public:
inline VertexBuffer(void) { invalidate(); }
inline VertexBuffer(const void* data, uint32_t byte_size, bool dynamic = false) { create(data, byte_size, dynamic); }
~VertexBuffer(void);
VertexBuffer& create(const void* data, uint32_t byte_size, bool dynamic = false);
void bind(void) const;
void unbind(void) const;
inline uint32_t getOpenGLID(void) const { return static_cast<uint32_t>(getID()); }
};
class ElementBuffer : public BaseObject
{
public:
inline ElementBuffer(void) { invalidate(); }
inline ElementBuffer(const uint32_t* data, uint32_t elem_count) { create(data, elem_count); }
~ElementBuffer(void);
ElementBuffer& create(const void* data, uint32_t elem_count);
void bind(void) const;
void unbind(void) const;
inline uint32_t getElementCount(void) const { return m_elem_count; }
inline uint32_t getOpenGLID(void) const { return static_cast<uint32_t>(getID()); }
private:
uint32_t m_elem_count { 0 };
};
struct tVertexBufferElem
{
uint32_t type;
uint32_t count;
int32_t normalized;
static uint32_t gl_typeToSize(uint32_t type);
};
class VertexBufferLayout
{
public:
inline VertexBufferLayout(void) : m_stride(0) { }
template<typename T>
inline void push(uint32_t count)
{
if constexpr(std::is_same_v<T, float>)
{
m_elements.push_back({ GL_FLOAT, count, GL_FALSE });
m_stride += count * tVertexBufferElem::gl_typeToSize(GL_FLOAT);
}
else if constexpr(std::is_same_v<T, uint32_t>)
{
m_elements.push_back({ GL_UNSIGNED_INT, count, GL_FALSE });
m_stride += count * tVertexBufferElem::gl_typeToSize(GL_UNSIGNED_INT);
}
else if constexpr(std::is_same_v<T, int32_t>)
{
m_elements.push_back({ GL_INT, count, GL_FALSE });
m_stride += count * tVertexBufferElem::gl_typeToSize(GL_INT);
}
else if constexpr(std::is_same_v<T, uint8_t>)
{
m_elements.push_back({ GL_UNSIGNED_BYTE, count, GL_TRUE });
m_stride += count * tVertexBufferElem::gl_typeToSize(GL_UNSIGNED_BYTE);
}
else if constexpr(std::is_same_v<T, int8_t>)
{
m_elements.push_back({ GL_BYTE, count, GL_TRUE });
m_stride += count * tVertexBufferElem::gl_typeToSize(GL_BYTE);
}
else
{
OX_WARN("Invalid template parameter in ox::VertexBufferLayout");
return;
}
}
inline uint32_t getStride(void) const { return m_stride; }
inline const std::vector<tVertexBufferElem>& getElements(void) const { return m_elements; }
private:
std::vector<tVertexBufferElem> m_elements;
uint32_t m_stride;
};
class VertexArray : public BaseObject
{
public:
VertexArray(bool init = true);
~VertexArray(void);
VertexArray& create(void);
uint32_t addBuffer(VertexBuffer& vbo, const VertexBufferLayout& layout);
void setElementBuffer(const ElementBuffer& ebo);
void bind(void) const;
void unbind(void) const;
uint32_t getElementCount(void) const;
VertexBuffer& getVerteBuffer(uint32_t internal_index = 0);
inline uint32_t getOpenGLID(void) const { return static_cast<uint32_t>(getID()); }
private:
uint32_t m_elem_count;
std::vector<VertexBuffer*> m_vertexBuffers;
public:
inline static constexpr int32_t ERR_NO_EBO_SET = OX_GLBUFFERS_ERR_MASK + 0x0001;
};
}
#endif

View file

@ -0,0 +1,695 @@
#include "GraphicsApplication.hpp"
#include "Errors.hpp"
#include "Renderer2D.hpp"
#include "Signals.hpp"
#include "RenderCommands.hpp"
#include "RenderCore.hpp"
#include "Utils.hpp"
#include "RTData.hpp"
#include "Widgets.hpp"
namespace ogfx
{
using namespace ostd;
GraphicsApplication2D& GraphicsApplication2D::create(int32_t windowWidth, int32_t windowHeight, const ostd::String& windowTitle, tContextSettings contextSettings)
{
/** Window Code **/
m_window.create({ static_cast<float>(windowWidth), static_cast<float>(windowHeight) }, windowTitle, contextSettings);
if (!m_window.isValid())
{
ErrorHandler::pushError(GraphicsApplication2D::ERR_WINDOW_CREATE_FAIL);
String err_str = ErrorHandler::getLastErrorString();
OX_FATAL("%s", err_str.c_str());
return *this;
}
m_window.printOpenGLInfo();
// m_window.setWindowIcon(windowIconPath);
/** Subsystem initialization **/
Renderer2D::init();
SignalHandler::init();
ResourceManager::init();
Renderer2D::Text::init();
// Input::init(m_window.getGLFWWindowPtr());
RenderCommandPool::init();
RenderCore::initRenderQUeue();
oxgui::WidgetManager::init();
/******************************/
m_lastFrameTime = Timer::getEpoch() / 1000.0;
enableVSync(false);
connectSignal(tBuiltinSignals::OnGuiEvent);
if (ogfx::DebugTools::m_debugWindowEnabled)
{
DebugTools::m_timesList.updateEntry(DebugTools::FramerateCalculations);
DebugTools::m_timesList.get(DebugTools::FramerateCalculations).name = "Framerate Calculations";
DebugTools::m_timesList.updateEntry(DebugTools::OnSecondsUpdate);
DebugTools::m_timesList.get(DebugTools::OnSecondsUpdate).name = "Seconds Update";
DebugTools::m_timesList.updateEntry(DebugTools::EventHandling);
DebugTools::m_timesList.get(DebugTools::EventHandling).name = "Event Handling";
DebugTools::m_timesList.updateEntry(DebugTools::OnUpdate);
DebugTools::m_timesList.get(DebugTools::OnUpdate).name = "Update";
DebugTools::m_timesList.updateEntry(DebugTools::OnRender);
DebugTools::m_timesList.get(DebugTools::OnRender).name = "Render";
DebugTools::m_timesList.updateEntry(DebugTools::OnDisplay);
DebugTools::m_timesList.get(DebugTools::OnDisplay).name = "Render Queue Execution";
DebugTools::m_timesList.updateEntry(DebugTools::OnFrameFinalize);
DebugTools::m_timesList.get(DebugTools::OnFrameFinalize).name = "Frame Finalize";
DebugTools::m_timesList.updateEntry(DebugTools::OnSignalsRefresh);
DebugTools::m_timesList.get(DebugTools::OnSignalsRefresh).name = "Signals Refresh";
DebugTools::m_timesList.updateEntry(DebugTools::OnWindowDisplay);
DebugTools::m_timesList.get(DebugTools::OnWindowDisplay).name = "Flip Buffers";
DebugTools::m_timesList.updateEntry(DebugTools::TotalFrameTime);
DebugTools::m_timesList.get(DebugTools::TotalFrameTime).name = "Total Frame Time";
m_debugToolsWindow.create({ 5, 5 }, { 600, 410 });
m_debugToolsWindow.enable();
m_debugToolsWindow.setTitle("Debug Tools");
// m_debugToolsWindow.setBounds(5, 5, 500, 385);
oxgui::WidgetTheme theme = oxgui::WidgetManager::getGlobalTheme();
oxgui::WidgetManager::addWidget(m_debugToolsWindow);
theme.subWindow.titleBarColor_focused = { 85, 0, 85 };
theme.subWindow.backgroundColor = { 0, 0, 0, 235 };
theme.subWindow.borderColor_focused = { 85, 0, 85 };
m_debugToolsWindow.setTheme(theme);
m_debugToolsWindow.enableGlobalThemeOverride(true);
theme.tabPanel.backgroundColor = { 10, 10, 10 };
theme.tabPanel.tabBackground_focused = { 10, 10, 10 };
// theme.tabPanel.tabBarBackground = { 85, 0, 85 };
DebugTools::m_debugWindowTabPanel.setTheme(theme);
DebugTools::m_debugWindowTabPanel.enableGlobalThemeOverride(true);
DebugTools::m_debugWindowTabPanel.create(m_debugToolsWindow);
DebugTools::m_debugWindowTabPanel.addTab(DebugTools::m_debugWindowInfoTab);
DebugTools::m_debugWindowTabPanel.addTab(DebugTools::m_debugWindowWatcherTab);
DebugTools::m_debugWindowTabPanel.addTab(DebugTools::m_debugWindowTab3);
DebugTools::m_debugWindowInfoTab.setText("Debug Info");
DebugTools::m_debugWindowWatcherTab.setText("Watcher");
DebugTools::m_debugWindowTab3.setText("Tab3");
DebugTools::m_debugWindowTabPanel.selectTab(0);
DebugTools::m_debugInfoWidget.init(DebugTools::m_debugWindowInfoTab);
}
setTypeName("ogfx::GraphicsApplication2D");
validate();
onSetup();
m_window.initialize();
return *this;
}
void GraphicsApplication2D::destroy(void)
{
RenderCommandPool::destroy();
Renderer2D::shutdown();
}
void GraphicsApplication2D::nextFrame(void)
{
if (!isRunning()) return;
const bool DEBUG = ogfx::DebugTools::m_debugWindowEnabled;
if (DEBUG)
{
DebugTools::m_totalFrameTimer.start(false, "", ostd::eTimeUnits::Milliseconds);
DebugTools::m_profileTimer.start(false, "", ostd::eTimeUnits::Milliseconds);
}
double currTime = Timer::getEpoch() / 1000.0;
m_rtfps++;
RTData::DeltaTime = (float)(currTime - m_lastFrameTime);
m_lastFrameTime = currTime;
double timeDiff = currTime - m_prevTime;
if (DEBUG)
{
DebugTools::m_timesList.get(DebugTools::FramerateCalculations).totalTime += DebugTools::m_profileTimer.end(false);
DebugTools::m_timesList.get(DebugTools::FramerateCalculations).sampleCount++;
DebugTools::m_profileTimer.start(false, "", ostd::eTimeUnits::Milliseconds);
}
if (timeDiff >= 1.0f)
{
onSecondsUpdate();
// SoundHandler::update();
m_prevTime = currTime;
if (DEBUG)
{
DebugTools::m_fps = m_rtfps;
DebugTools::m_ups = m_rtups;
for (auto& data : DebugTools::m_timesList.data)
{
data.second.computeAvgTime();
data.second.sampleCount = 1;
data.second.totalTime = data.second.getAvgTime();
}
}
m_rtfps = 0;
m_rtups = 0;
}
// LightingManager::update();
onFrameStart();
if (DEBUG)
{
DebugTools::m_timesList.get(DebugTools::OnSecondsUpdate).totalTime += DebugTools::m_profileTimer.end(false);
DebugTools::m_timesList.get(DebugTools::OnSecondsUpdate).sampleCount++;
DebugTools::m_profileTimer.start(false, "", ostd::eTimeUnits::Milliseconds);
}
m_window.handleEvents();
if (DEBUG)
{
DebugTools::m_timesList.get(DebugTools::EventHandling).totalTime += DebugTools::m_profileTimer.end(false);
DebugTools::m_timesList.get(DebugTools::EventHandling).sampleCount++;
DebugTools::m_profileTimer.start(false, "", ostd::eTimeUnits::Milliseconds);
}
while (m_upsAccumulator > m_upsStep)
{
onUpdate();
m_upsAccumulator -= m_upsStep;
m_rtups++;
if (DEBUG)
{
SignalHandler::emitSignal(DebugTools::OnProfileDataRecieved, tSignalPriority::RealTime, DebugTools::m_timesList);
ogfx::DebugTools::m_drawBasicFrameInfo = ogfx::DebugTools::m_debugWindowTabPanel.getSelectedTab() != 0;
}
}
m_upsAccumulator += m_upsClock.restart();
if (DEBUG)
{
DebugTools::m_timesList.get(DebugTools::OnUpdate).totalTime += DebugTools::m_profileTimer.end(false);
DebugTools::m_timesList.get(DebugTools::OnUpdate).sampleCount++;
DebugTools::m_profileTimer.start(false, "", ostd::eTimeUnits::Milliseconds);
}
onRender();
onGuiRender();
Renderer2D::resetStats();
if (DEBUG)
{
DebugTools::m_timesList.get(DebugTools::OnRender).totalTime += DebugTools::m_profileTimer.end(false);
DebugTools::m_timesList.get(DebugTools::OnRender).sampleCount++;
DebugTools::m_profileTimer.start(false, "", ostd::eTimeUnits::Milliseconds);
}
RenderCore::display();
if (DEBUG)
{
DebugTools::m_renderCmdCount = RenderCore::getRenderCmdCount();
}
RenderCore::resetRenderCmdCount();
Renderer2D::setDefaultRenderTarget();
if (DEBUG)
{
DebugTools::m_timesList.get(DebugTools::OnDisplay).totalTime += DebugTools::m_profileTimer.end(false);
DebugTools::m_timesList.get(DebugTools::OnDisplay).sampleCount++;
DebugTools::m_profileTimer.start(false, "", ostd::eTimeUnits::Milliseconds);
}
SignalHandler::refresh();
if (DEBUG)
{
DebugTools::m_timesList.get(DebugTools::OnSignalsRefresh).totalTime += DebugTools::m_profileTimer.end(false);
DebugTools::m_timesList.get(DebugTools::OnSignalsRefresh).sampleCount++;
DebugTools::m_profileTimer.start(false, "", ostd::eTimeUnits::Milliseconds);
}
m_window.renderFrame();
if (DEBUG)
{
DebugTools::m_timesList.get(DebugTools::OnWindowDisplay).totalTime += DebugTools::m_profileTimer.end(false);
DebugTools::m_timesList.get(DebugTools::OnWindowDisplay).sampleCount++;
DebugTools::m_profileTimer.start(false, "", ostd::eTimeUnits::Milliseconds);
}
onFrameEnd();
RenderCommandPool::newFrame();
if (DEBUG)
{
DebugTools::m_uniformUpdates = Shader::getUniformUpdateCount();
}
Shader::resetUniformUpdateCount();
if (DEBUG)
{
DebugTools::m_timesList.get(DebugTools::OnFrameFinalize).totalTime += DebugTools::m_profileTimer.end(false);
DebugTools::m_timesList.get(DebugTools::OnFrameFinalize).sampleCount++;
}
if (!isRunning())
{
destroy();
OX_DEBUG("Destroying SFML Window");
}
if (DEBUG)
{
DebugTools::m_timesList.get(DebugTools::TotalFrameTime).totalTime += DebugTools::m_totalFrameTimer.end(false);
DebugTools::m_timesList.get(DebugTools::TotalFrameTime).sampleCount++;
for (auto& data : DebugTools::m_timesList.data)
{
data.second.computeAvgTime();
}
}
}
void GraphicsApplication2D::handleSignal(tSignal& signal)
{
if (signal.ID == tBuiltinSignals::OnGuiEvent)
{
Event& evt = (Event&)signal.userData;
sf::Event& event = evt.sf();
if (event.type == sf::Event::Closed)
{
m_window.close();
onClose();
}
else if (event.type == sf::Event::KeyPressed)
{
if (event.key.code == sf::Keyboard::Escape)
{
m_window.close();
onClose();
}
onKeyPressed(evt);
}
else if (event.type == sf::Event::KeyReleased)
{
// if (event.key.code == sf::Keyboard::F9)
// m_showDebugInfo = !m_showDebugInfo;
onKeyReleased(evt);
}
else if (event.type == sf::Event::Resized)
{
glViewport(0, 0, event.size.width, event.size.height);
m_window.initialize();
}
else if (event.type == sf::Event::MouseMoved)
{
onMousePressed(evt);
}
else if (event.type == sf::Event::MouseButtonPressed)
{
onMouseReleased(evt);
}
else if (event.type == sf::Event::MouseButtonReleased)
{
onMouseMoved(evt);
}
}
onSignal(signal);
}
void GraphicsApplication2D::drawDebugInfo(RenderCore& gfx, Color col)
{
if (!ogfx::DebugTools::m_debugWindowEnabled || !ogfx::DebugTools::m_drawBasicFrameInfo) return;
gfx.drawText(StringEditor("FPS: ").addi(ogfx::DebugTools::m_fps).str(), { 5, 5 }, 30.0f, col);
gfx.drawText(StringEditor("FrameTime: ").addf(DebugTools::m_timesList.get(DebugTools::TotalFrameTime).getAvgTime()).str(), { 5, 35 }, 30.0f, col);
}
// void GraphicsApplication2D::drawDebugInfo(RenderCore& gfx, Color col)
// {
// if (!m_showDebugInfo) return;
// float sp = gfx.getTextSpacing();
// ResourceID font = gfx.getFont();
// Renderer2D::Text::font = ResourceManager::getDefaultBitmapFontMono();
// gfx.setTextSpacing(-15.0f);
// gfx.setFont(ResourceManager::getDefaultBitmapFontMono());
// float fontSize = 24;
// float fontSpacing = -15;
// float strw = 0;
// float maxw = 0;
// std::vector<String> debugStrings;
// debugStrings.reserve(100);
// StringEditor str;
// str = "DrawCalls: ";
// str.addi(Renderer2D::getRenderStats().drawCalls);
// strw = Renderer2D::Text::getStringBounds(str.str(), { 0, 0 }, fontSize, fontSpacing).x;
// debugStrings.push_back(str.str());
// if (strw > maxw) maxw = strw;
// str = "Quads: ";
// str.addi(Renderer2D::getRenderStats().quadCount);
// strw = Renderer2D::Text::getStringBounds(str.str(), { 0, 0 }, fontSize, fontSpacing).x;
// debugStrings.push_back(str.str());
// if (strw > maxw) maxw = strw;
// str = "FPS: ";
// str.addi(getFps());
// strw = Renderer2D::Text::getStringBounds(str.str(), { 0, 0 }, fontSize, fontSpacing).x;
// debugStrings.push_back(str.str());
// if (strw > maxw) maxw = strw;
// str = "UPS: ";
// str.addi(m_ups);
// strw = Renderer2D::Text::getStringBounds(str.str(), { 0, 0 }, fontSize, fontSpacing).x;
// debugStrings.push_back(str.str());
// if (strw > maxw) maxw = strw;
// str = "RenderTarget Binds: ";
// str.addi(Renderer2D::getRenderStats().renderBufferBinds);
// strw = Renderer2D::Text::getStringBounds(str.str(), { 0, 0 }, fontSize, fontSpacing).x;
// debugStrings.push_back(str.str());
// if (strw > maxw) maxw = strw;
// str = "Shader Binds: ";
// str.addi(Renderer2D::getRenderStats().shaderBinds);
// strw = Renderer2D::Text::getStringBounds(str.str(), { 0, 0 }, fontSize, fontSpacing).x;
// debugStrings.push_back(str.str());
// if (strw > maxw) maxw = strw;
// str = "Uniform Updates: ";
// str.addi(m_uniformUpdates);
// strw = Renderer2D::Text::getStringBounds(str.str(), { 0, 0 }, fontSize, fontSpacing).x;
// debugStrings.push_back(str.str());
// if (strw > maxw) maxw = strw;
// str = "Render Queue: ";
// str.addi(m_renderCmdCount);
// strw = Renderer2D::Text::getStringBounds(str.str(), { 0, 0 }, fontSize, fontSpacing).x;
// debugStrings.push_back(str.str());
// if (strw > maxw) maxw = strw;
// Renderer2D::Text::font = font;
// gfx.drawQuad({ 0, 0 }, { (maxw * 2) + 40, (debugStrings.size() * fontSize * 2) + 15 }, { 0, 0, 0, 223 });
// float offsety = 20;
// int32_t i = 0;
// for (auto& str : debugStrings)
// gfx.drawText(str, { 5.0f, 10.0f + (i++ * offsety) }, fontSize, col);
// gfx.setTextSpacing(sp);
// gfx.setFont(font);
// }
GraphicsApplication& GraphicsApplication::create(int32_t windowWidth, int32_t windowHeight, const ostd::String& windowTitle, tContextSettings contextSettings)
{
/** Window Code **/
m_window.create({ static_cast<float>(windowWidth), static_cast<float>(windowHeight) }, windowTitle, contextSettings);
if (!m_window.isValid())
{
ErrorHandler::pushError(GraphicsApplication::ERR_WINDOW_CREATE_FAIL);
String err_str = ErrorHandler::getLastErrorString();
OX_FATAL("%s", err_str.c_str());
return *this;
}
m_window.printOpenGLInfo();
// m_window.setWindowIcon(windowIconPath);
/** Subsystem initialization **/
Renderer2D::init();
SignalHandler::init();
ResourceManager::init();
Renderer2D::Text::init();
RenderCommandPool::init();
RenderCore::initRenderQUeue();
oxgui::WidgetManager::init();
/******************************/
m_lastFrameTime = Timer::getEpoch() / 1000.0;
enableVSync(false);
connectSignal(tBuiltinSignals::OnGuiEvent);
if (ogfx::DebugTools::m_debugWindowEnabled)
{
DebugTools::m_timesList.updateEntry(DebugTools::FramerateCalculations);
DebugTools::m_timesList.get(DebugTools::FramerateCalculations).name = "Framerate Calculations";
DebugTools::m_timesList.updateEntry(DebugTools::OnSecondsUpdate);
DebugTools::m_timesList.get(DebugTools::OnSecondsUpdate).name = "Seconds Update";
DebugTools::m_timesList.updateEntry(DebugTools::EventHandling);
DebugTools::m_timesList.get(DebugTools::EventHandling).name = "Event Handling";
DebugTools::m_timesList.updateEntry(DebugTools::OnUpdate);
DebugTools::m_timesList.get(DebugTools::OnUpdate).name = "Update";
DebugTools::m_timesList.updateEntry(DebugTools::OnRender);
DebugTools::m_timesList.get(DebugTools::OnRender).name = "Render";
DebugTools::m_timesList.updateEntry(DebugTools::OnDisplay);
DebugTools::m_timesList.get(DebugTools::OnDisplay).name = "Render Queue Execution";
DebugTools::m_timesList.updateEntry(DebugTools::OnFrameFinalize);
DebugTools::m_timesList.get(DebugTools::OnFrameFinalize).name = "Frame Finalize";
DebugTools::m_timesList.updateEntry(DebugTools::OnSignalsRefresh);
DebugTools::m_timesList.get(DebugTools::OnSignalsRefresh).name = "Signals Refresh";
DebugTools::m_timesList.updateEntry(DebugTools::OnWindowDisplay);
DebugTools::m_timesList.get(DebugTools::OnWindowDisplay).name = "Flip Buffers";
DebugTools::m_timesList.updateEntry(DebugTools::TotalFrameTime);
DebugTools::m_timesList.get(DebugTools::TotalFrameTime).name = "Total Frame Time";
m_debugToolsWindow.create({ 5, 5 }, { 600, 410 });
m_debugToolsWindow.enable();
m_debugToolsWindow.setTitle("Debug Tools");
// m_debugToolsWindow.setBounds(5, 5, 500, 385);
oxgui::WidgetTheme theme = oxgui::WidgetManager::getGlobalTheme();
oxgui::WidgetManager::addWidget(m_debugToolsWindow);
theme.subWindow.titleBarColor_focused = { 85, 0, 85 };
theme.subWindow.backgroundColor = { 0, 0, 0, 235 };
theme.subWindow.borderColor_focused = { 85, 0, 85 };
m_debugToolsWindow.setTheme(theme);
m_debugToolsWindow.enableGlobalThemeOverride(true);
theme.tabPanel.backgroundColor = { 10, 10, 10 };
theme.tabPanel.tabBackground_focused = { 10, 10, 10 };
// theme.tabPanel.tabBarBackground = { 85, 0, 85 };
DebugTools::m_debugWindowTabPanel.setTheme(theme);
DebugTools::m_debugWindowTabPanel.enableGlobalThemeOverride(true);
DebugTools::m_debugWindowTabPanel.create(m_debugToolsWindow);
DebugTools::m_debugWindowTabPanel.addTab(DebugTools::m_debugWindowInfoTab);
DebugTools::m_debugWindowTabPanel.addTab(DebugTools::m_debugWindowWatcherTab);
DebugTools::m_debugWindowTabPanel.addTab(DebugTools::m_debugWindowTab3);
DebugTools::m_debugWindowInfoTab.setText("Debug Info");
DebugTools::m_debugWindowWatcherTab.setText("Watcher");
DebugTools::m_debugWindowTab3.setText("Tab3");
DebugTools::m_debugWindowTabPanel.selectTab(0);
DebugTools::m_debugInfoWidget.init(DebugTools::m_debugWindowInfoTab);
}
setTypeName("ogfx::GraphicsApplication");
validate();
m_window.initialize();
onSetup();
return *this;
}
void GraphicsApplication::destroy(void)
{
RenderCommandPool::destroy();
Renderer2D::shutdown();
}
void GraphicsApplication::nextFrame(void)
{
if (!isRunning()) return;
const bool DEBUG = ogfx::DebugTools::m_debugWindowEnabled;
if (DEBUG)
{
DebugTools::m_totalFrameTimer.start(false, "", ostd::eTimeUnits::Milliseconds);
DebugTools::m_profileTimer.start(false, "", ostd::eTimeUnits::Milliseconds);
}
double currTime = Timer::getEpoch() / 1000.0;
m_rtfps++;
RTData::DeltaTime = (float)(currTime - m_lastFrameTime);
m_lastFrameTime = currTime;
double timeDiff = currTime - m_prevTime;
if (DEBUG)
{
DebugTools::m_timesList.get(DebugTools::FramerateCalculations).totalTime += DebugTools::m_profileTimer.end(false);
DebugTools::m_timesList.get(DebugTools::FramerateCalculations).sampleCount++;
DebugTools::m_profileTimer.start(false, "", ostd::eTimeUnits::Milliseconds);
}
if (timeDiff >= 1.0f)
{
onSecondsUpdate();
// SoundHandler::update();
m_prevTime = currTime;
if (DEBUG)
{
DebugTools::m_fps = m_rtfps;
DebugTools::m_ups = m_rtups;
for (auto& data : DebugTools::m_timesList.data)
{
data.second.computeAvgTime();
data.second.sampleCount = 1;
data.second.totalTime = data.second.getAvgTime();
}
}
m_rtfps = 0;
m_rtups = 0;
}
onFrameStart();
if (DEBUG)
{
DebugTools::m_timesList.get(DebugTools::OnSecondsUpdate).totalTime += DebugTools::m_profileTimer.end(false);
DebugTools::m_timesList.get(DebugTools::OnSecondsUpdate).sampleCount++;
DebugTools::m_profileTimer.start(false, "", ostd::eTimeUnits::Milliseconds);
}
m_window.handleEvents();
if (DEBUG)
{
DebugTools::m_timesList.get(DebugTools::EventHandling).totalTime += DebugTools::m_profileTimer.end(false);
DebugTools::m_timesList.get(DebugTools::EventHandling).sampleCount++;
DebugTools::m_profileTimer.start(false, "", ostd::eTimeUnits::Milliseconds);
}
while (m_upsAccumulator > m_upsStep)
{
onUpdate();
m_upsAccumulator -= m_upsStep;
m_rtups++;
if (DEBUG)
{
SignalHandler::emitSignal(DebugTools::OnProfileDataRecieved, tSignalPriority::RealTime, DebugTools::m_timesList);
ogfx::DebugTools::m_drawBasicFrameInfo = ogfx::DebugTools::m_debugWindowTabPanel.getSelectedTab() != 0;
}
}
m_upsAccumulator += m_upsClock.restart();
if (DEBUG)
{
DebugTools::m_timesList.get(DebugTools::OnUpdate).totalTime += DebugTools::m_profileTimer.end(false);
DebugTools::m_timesList.get(DebugTools::OnUpdate).sampleCount++;
DebugTools::m_profileTimer.start(false, "", ostd::eTimeUnits::Milliseconds);
}
onRender();
onGuiRender();
Renderer2D::resetStats();
if (DEBUG)
{
DebugTools::m_timesList.get(DebugTools::OnRender).totalTime += DebugTools::m_profileTimer.end(false);
DebugTools::m_timesList.get(DebugTools::OnRender).sampleCount++;
DebugTools::m_profileTimer.start(false, "", ostd::eTimeUnits::Milliseconds);
}
RenderCore::display();
if (DEBUG)
{
DebugTools::m_renderCmdCount = RenderCore::getRenderCmdCount();
}
RenderCore::resetRenderCmdCount();
Renderer2D::setDefaultRenderTarget();
if (DEBUG)
{
DebugTools::m_timesList.get(DebugTools::OnDisplay).totalTime += DebugTools::m_profileTimer.end(false);
DebugTools::m_timesList.get(DebugTools::OnDisplay).sampleCount++;
DebugTools::m_profileTimer.start(false, "", ostd::eTimeUnits::Milliseconds);
}
SignalHandler::refresh();
if (DEBUG)
{
DebugTools::m_timesList.get(DebugTools::OnSignalsRefresh).totalTime += DebugTools::m_profileTimer.end(false);
DebugTools::m_timesList.get(DebugTools::OnSignalsRefresh).sampleCount++;
DebugTools::m_profileTimer.start(false, "", ostd::eTimeUnits::Milliseconds);
}
m_window.renderFrame();
if (DEBUG)
{
DebugTools::m_timesList.get(DebugTools::OnWindowDisplay).totalTime += DebugTools::m_profileTimer.end(false);
DebugTools::m_timesList.get(DebugTools::OnWindowDisplay).sampleCount++;
DebugTools::m_profileTimer.start(false, "", ostd::eTimeUnits::Milliseconds);
}
onFrameEnd();
RenderCommandPool::newFrame();
if (DEBUG)
{
DebugTools::m_uniformUpdates = Shader::getUniformUpdateCount();
}
Shader::resetUniformUpdateCount();
if (DEBUG)
{
DebugTools::m_timesList.get(DebugTools::OnFrameFinalize).totalTime += DebugTools::m_profileTimer.end(false);
DebugTools::m_timesList.get(DebugTools::OnFrameFinalize).sampleCount++;
}
if (!isRunning())
{
destroy();
OX_DEBUG("Destroying SFML Window");
}
if (DEBUG)
{
DebugTools::m_timesList.get(DebugTools::TotalFrameTime).totalTime += DebugTools::m_totalFrameTimer.end(false);
DebugTools::m_timesList.get(DebugTools::TotalFrameTime).sampleCount++;
for (auto& data : DebugTools::m_timesList.data)
{
data.second.computeAvgTime();
}
}
}
void GraphicsApplication::handleSignal(tSignal& signal)
{
if (signal.ID == tBuiltinSignals::OnGuiEvent)
{
Event& evt = (Event&)signal.userData;
sf::Event& event = evt.sf();
if (event.type == sf::Event::Closed)
{
m_window.close();
onClose();
}
else if (event.type == sf::Event::KeyPressed)
{
if (event.key.code == sf::Keyboard::Escape)
{
m_window.close();
onClose();
}
onKeyPressed(evt);
}
else if (event.type == sf::Event::KeyReleased)
{
onKeyReleased(evt);
}
else if (event.type == sf::Event::Resized)
{
glViewport(0, 0, event.size.width, event.size.height);
m_window.initialize();
}
else if (event.type == sf::Event::MouseMoved)
{
onMousePressed(evt);
}
else if (event.type == sf::Event::MouseButtonPressed)
{
onMouseReleased(evt);
}
else if (event.type == sf::Event::MouseButtonReleased)
{
onMouseMoved(evt);
}
}
onSignal(signal);
}
void GraphicsApplication::drawDebugInfo(RenderCore& gfx, Color col)
{
if (!ogfx::DebugTools::m_debugWindowEnabled || !ogfx::DebugTools::m_drawBasicFrameInfo) return;
gfx.drawText(StringEditor("FPS: ").addi(ogfx::DebugTools::m_fps).str(), { 5, 5 }, 30.0f, col);
gfx.drawText(StringEditor("FrameTime: ").addf(DebugTools::m_timesList.get(DebugTools::TotalFrameTime).getAvgTime()).str(), { 5, 35 }, 30.0f, col);
}
}

View file

@ -0,0 +1,137 @@
#pragma once
#include <ostd/BaseObject.hpp>
#include <ogfx/DataStructures.hpp>
#include <ogfx/Window.hpp>
#include <ogfx/DebugTools.hpp>
namespace ogfx
{
class RenderCore;
class GraphicsApplication2D : public ostd::BaseObject
{
public:
inline GraphicsApplication2D(void) { invalidate(); }
inline GraphicsApplication2D(int32_t windowWidth, int32_t windowHeight, const ostd::String& windowTitle, tContextSettings contextSettings = tContextSettings()) { create(windowWidth, windowHeight, windowTitle, contextSettings); }
GraphicsApplication2D& create(int32_t windowWidth, int32_t windowHeight, const ostd::String& windowTitle, tContextSettings contextSettings = tContextSettings());
void destroy(void);
void nextFrame(void);
inline bool isRunning(void) { return isValid() && m_window.isRunning(); }
// inline uint32_t& getFps(void) { return m_fps; }
inline void enableVSync(bool enabled = true) { m_window.sf().setVerticalSyncEnabled(enabled); }
inline IPoint getWindowSize(void) { return { m_window.getSize().x, m_window.getSize().y }; }
inline int32_t getWindowWidth(void) { return m_window.getSize().x; }
inline int32_t getWindowHeight(void) { return m_window.getSize().y; }
// inline void enableDebugInfo(bool v = true) { m_showDebugInfo = v; }
// inline bool isDebugInfoEnabled(void) { return m_showDebugInfo; }
// void drawDebugInfo(RenderCore& gfx, Color col = { 150, 180, 130 });
void drawDebugInfo(RenderCore& gfx, Color col = { 150, 180, 130 });
void handleSignal(tSignal& signal) override;
virtual void onFrameStart(void) { }
virtual void onFrameEnd(void) { }
virtual void onSetup(void) { }
virtual void onRender(void) { }
virtual void onUpdate(void) { }
virtual void onSecondsUpdate(void) { }
virtual void onGuiRender(void) { }
virtual void onKeyPressed(Event& evt) { }
virtual void onKeyReleased(Event& evt) { }
virtual void onMousePressed(Event& evt) { }
virtual void onMouseReleased(Event& evt) { }
virtual void onMouseMoved(Event& evt) { }
virtual void onSignal(tSignal& signal) { }
virtual void onClose(void) { }
protected:
Window m_window;
Color m_clearColor;
private:
uint32_t m_rtfps { 0 };
uint32_t m_rtups { 0 };
// uint32_t m_fps { 0 };
// uint32_t m_ups { 0 };
double m_prevTime { 0.0 };
double m_lastFrameTime { 0.0 };
sf::Clock m_upsClock;
sf::Time m_upsAccumulator = sf::Time::Zero;
sf::Time m_upsStep = sf::seconds(1.f / 60.f);
// uint32_t m_uniformUpdates { 0 };
// uint32_t m_renderCmdCount { 0 };
// bool m_showDebugInfo { false };
ogfx::oxgui::SubWindow m_debugToolsWindow;
public:
inline static constexpr int32_t ERR_WINDOW_CREATE_FAIL = OX_GFX_APPLICATION_2D_ERR_MASK + 0x0001;
inline static constexpr int32_t ERR_INVALID_APP_INSTANCE = OX_GFX_APPLICATION_2D_ERR_MASK + 0x0002;
friend class DebugTools;
};
class GraphicsApplication : public ostd::BaseObject
{
public:
inline GraphicsApplication(void) { invalidate(); }
inline GraphicsApplication(int32_t windowWidth, int32_t windowHeight, const ostd::String& windowTitle, tContextSettings contextSettings = tContextSettings()) { create(windowWidth, windowHeight, windowTitle, contextSettings); }
GraphicsApplication& create(int32_t windowWidth, int32_t windowHeight, const ostd::String& windowTitle, tContextSettings contextSettings = tContextSettings());
void destroy(void);
void nextFrame(void);
inline bool isRunning(void) { return isValid() && m_window.isRunning(); }
inline void enableVSync(bool enabled = true) { m_window.sf().setVerticalSyncEnabled(enabled); }
inline IPoint getWindowSize(void) { return { m_window.getSize().x, m_window.getSize().y }; }
inline int32_t getWindowWidth(void) { return m_window.getSize().x; }
inline int32_t getWindowHeight(void) { return m_window.getSize().y; }
void drawDebugInfo(RenderCore& gfx, Color col = { 150, 180, 130 });
void handleSignal(tSignal& signal) override;
virtual void onFrameStart(void) { }
virtual void onFrameEnd(void) { }
virtual void onSetup(void) { }
virtual void onRender(void) { }
virtual void onUpdate(void) { }
virtual void onSecondsUpdate(void) { }
virtual void onGuiRender(void) { }
virtual void onKeyPressed(Event& evt) { }
virtual void onKeyReleased(Event& evt) { }
virtual void onMousePressed(Event& evt) { }
virtual void onMouseReleased(Event& evt) { }
virtual void onMouseMoved(Event& evt) { }
virtual void onSignal(tSignal& signal) { }
virtual void onClose(void) { }
protected:
Window m_window;
Color m_clearColor;
private:
uint32_t m_rtfps { 0 };
uint32_t m_rtups { 0 };
double m_prevTime { 0.0 };
double m_lastFrameTime { 0.0 };
sf::Clock m_upsClock;
sf::Time m_upsAccumulator = sf::Time::Zero;
sf::Time m_upsStep = sf::seconds(1.f / 60.f);
ogfx::oxgui::SubWindow m_debugToolsWindow;
public:
inline static constexpr int32_t ERR_WINDOW_CREATE_FAIL = OX_GFX_APPLICATION_2D_ERR_MASK + 0x0001;
inline static constexpr int32_t ERR_INVALID_APP_INSTANCE = OX_GFX_APPLICATION_2D_ERR_MASK + 0x0002;
friend class DebugTools;
};
}

79
src/ogfx/Mesh.cpp Normal file
View file

@ -0,0 +1,79 @@
#include "Mesh.hpp"
namespace ogfx
{
using namespace ostd;
void Mesh::initialize(void)
{
vao.create();
auto layout = tVertex::getVertexBufferLayout();
vbo.create(&vertices[0], vertices.size() * layout.getStride());
vao.addBuffer(vbo, layout);
ebo.create(&indices[0], indices.size());
vao.setElementBuffer(ebo);
}
void Mesh::bind(void)
{
vao.bind();
}
void Mesh::unbind(void)
{
vao.unbind();
}
void Mesh::draw(void)
{
glDrawElements(GL_TRIANGLES, ebo.getElementCount(), GL_UNSIGNED_INT, 0);
}
Mesh Mesh::newPlaneMesh(bool auto_initialize)
{
Mesh plane;
plane.indices = { 0, 1, 3, 1, 2, 3 };
plane.vertices = {
tVertex { { 1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {1.0f, 1.0f}, {0.0f, 0.0f, 1.0f}},
tVertex { { 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 0.0f, 1.0f}},
tVertex { {-1.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0.0f, 0.0f}, {0.0f, 0.0f, 1.0f}},
tVertex { {-1.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}}
};
if (auto_initialize) plane.initialize();
return plane;
}
Mesh Mesh::newCubeMesh(bool auto_initialize)
{
Mesh cube;
cube.indices = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 0, 18, 1, 3, 19, 4, 6, 20, 7, 9, 21, 10, 12, 22, 13, 15, 23, 16 };
cube.vertices = {
tVertex { { -1.000000, 1.000000, 1.000000 }, {1.0, 1.0, 1.0, 1.0}, { 0.875000, 0.500000 }, { 0.000000, 0.000000, 1.000000 } },
tVertex { { 1.000000, -1.000000, 1.000000 }, {1.0, 1.0, 1.0, 1.0}, { 0.625000, 0.750000 }, { 0.000000, 0.000000, 1.000000 } },
tVertex { { 1.000000, 1.000000, 1.000000 }, {1.0, 1.0, 1.0, 1.0}, { 0.625000, 0.500000 }, { 0.000000, 0.000000, 1.000000 } },
tVertex { { 1.000000, -1.000000, 1.000000 }, {1.0, 1.0, 1.0, 1.0}, { 0.625000, 0.750000 }, { 0.000000, -1.000000, 0.000000 } },
tVertex { { -1.000000, -1.000000, -1.000000 }, {1.0, 1.0, 1.0, 1.0}, { 0.375000, 1.000000 }, { 0.000000, -1.000000, 0.000000 } },
tVertex { { 1.000000, -1.000000, -1.000000 }, {1.0, 1.0, 1.0, 1.0}, { 0.375000, 0.750000 }, { 0.000000, -1.000000, 0.000000 } },
tVertex { { -1.000000, -1.000000, 1.000000 }, {1.0, 1.0, 1.0, 1.0}, { 0.625000, 0.000000 }, { -1.000000, 0.000000, 0.000000 } },
tVertex { { -1.000000, 1.000000, -1.000000 }, {1.0, 1.0, 1.0, 1.0}, { 0.375000, 0.250000 }, { -1.000000, 0.000000, 0.000000 } },
tVertex { { -1.000000, -1.000000, -1.000000 }, {1.0, 1.0, 1.0, 1.0}, { 0.375000, 0.000000 }, { -1.000000, 0.000000, 0.000000 } },
tVertex { { 1.000000, 1.000000, -1.000000 }, {1.0, 1.0, 1.0, 1.0}, { 0.375000, 0.500000 }, { 0.000000, 0.000000, -1.000000 } },
tVertex { { -1.000000, -1.000000, -1.000000 }, {1.0, 1.0, 1.0, 1.0}, { 0.125000, 0.750000 }, { 0.000000, 0.000000, -1.000000 } },
tVertex { { -1.000000, 1.000000, -1.000000 }, {1.0, 1.0, 1.0, 1.0}, { 0.125000, 0.500000 }, { 0.000000, 0.000000, -1.000000 } },
tVertex { { 1.000000, 1.000000, 1.000000 }, {1.0, 1.0, 1.0, 1.0}, { 0.625000, 0.500000 }, { 1.000000, 0.000000, 0.000000 } },
tVertex { { 1.000000, -1.000000, -1.000000 }, {1.0, 1.0, 1.0, 1.0}, { 0.375000, 0.750000 }, { 1.000000, 0.000000, 0.000000 } },
tVertex { { 1.000000, 1.000000, -1.000000 }, {1.0, 1.0, 1.0, 1.0}, { 0.375000, 0.500000 }, { 1.000000, 0.000000, 0.000000 } },
tVertex { { -1.000000, 1.000000, 1.000000 }, {1.0, 1.0, 1.0, 1.0}, { 0.625000, 0.250000 }, { 0.000000, 1.000000, 0.000000 } },
tVertex { { 1.000000, 1.000000, -1.000000 }, {1.0, 1.0, 1.0, 1.0}, { 0.375000, 0.500000 }, { 0.000000, 1.000000, 0.000000 } },
tVertex { { -1.000000, 1.000000, -1.000000 }, {1.0, 1.0, 1.0, 1.0}, { 0.375000, 0.250000 }, { 0.000000, 1.000000, 0.000000 } },
tVertex { { -1.000000, -1.000000, 1.000000 }, {1.0, 1.0, 1.0, 1.0}, { 0.875000, 0.750000 }, { 0.000000, 0.000000, 1.000000 } },
tVertex { { -1.000000, -1.000000, 1.000000 }, {1.0, 1.0, 1.0, 1.0}, { 0.625000, 1.000000 }, { 0.000000, -1.000000, 0.000000 } },
tVertex { { -1.000000, 1.000000, 1.000000 }, {1.0, 1.0, 1.0, 1.0}, { 0.625000, 0.250000 }, { -1.000000, 0.000000, 0.000000 } },
tVertex { { 1.000000, -1.000000, -1.000000 }, {1.0, 1.0, 1.0, 1.0}, { 0.375000, 0.750000 }, { 0.000000, 0.000000, -1.000000 } },
tVertex { { 1.000000, -1.000000, 1.000000 }, {1.0, 1.0, 1.0, 1.0}, { 0.625000, 0.750000 }, { 1.000000, 0.000000, 0.000000 } },
tVertex { { 1.000000, 1.000000, 1.000000 }, {1.0, 1.0, 1.0, 1.0}, { 0.625000, 0.500000 }, { 0.000000, 1.000000, 0.000000 } }
};
if (auto_initialize) cube.initialize();
return cube;
}
}

36
src/ogfx/Mesh.hpp Executable file
View file

@ -0,0 +1,36 @@
#ifndef __TEMP_HPP__
#define __TEMP_HPP__
#include <ogfx/DataStructures.hpp>
#include <vector>
namespace ogfx
{
class Mesh
{
public:
inline Mesh(void) { }
void initialize(void);
inline Transform3D& getTransform(void) { return transform; }
void bind(void);
void unbind(void);
void draw(void);
static Mesh newPlaneMesh(bool auto_initialize = false);
static Mesh newCubeMesh(bool auto_initialize = false);
private:
VertexArray vao { false };
VertexBuffer vbo;
ElementBuffer ebo;
Transform3D transform;
public:
std::vector<uint32_t> indices;
std::vector<tVertex> vertices;
std::vector<ResourceID> textures;
};
}
#endif

126
src/ogfx/OX3DLoader.cpp Executable file
View file

@ -0,0 +1,126 @@
#include "OX3DLoader.hpp"
#include "Serial.hpp"
#include "Types.hpp"
#include "Utils.hpp"
#include "ogfx/DataStructures.hpp"
#include "ogfx/ResourceManager.hpp"
#include <cstdint>
#include <fstream>
#include <vector>
namespace ogfx
{
using namespace ostd;
Mesh OX3DLoader::loadFromFile(const String& filePath, const ostd::String& texturesSubPath)
{
s_error = true;
Mesh mesh;
loadRawData(filePath);
if (s_rawData.size() == 0) return mesh; //TODO: Error
serial::SerialIO reader(s_rawData, serial::SerialIO::tEndianness::BigEndian);
int32_t meshCount = 0;
StreamIndex addr = 0;
//Start Reading
reader.r_DWord(addr, meshCount);
addr += tTypeSize::DWORD;
if (meshCount < 1) return mesh; //TODO: Error
meshCount = 1; //TODO: Remove this. This is a manual override to force reading only the first mesh
for (int32_t currentMeshIndex = meshCount - 1; currentMeshIndex >= 0; currentMeshIndex--)
{
int32_t vertCount = 0;
reader.r_DWord(addr, vertCount);
addr += tTypeSize::DWORD;
if (vertCount < 3) return mesh; //TODO: Error
for (uint32_t v = 0; v < vertCount; v++)
{
tVertex vertex;
reader.r_Float(addr, vertex.position.x);
addr += tTypeSize::FLOAT;
reader.r_Float(addr, vertex.position.y);
addr += tTypeSize::FLOAT;
reader.r_Float(addr, vertex.position.z);
addr += tTypeSize::FLOAT;
reader.r_Float(addr, vertex.normal.x);
addr += tTypeSize::FLOAT;
reader.r_Float(addr, vertex.normal.y);
addr += tTypeSize::FLOAT;
reader.r_Float(addr, vertex.normal.z);
addr += tTypeSize::FLOAT;
reader.r_Float(addr, vertex.texCoords.x);
addr += tTypeSize::FLOAT;
reader.r_Float(addr, vertex.texCoords.y);
addr += tTypeSize::FLOAT;
mesh.vertices.push_back(vertex);
}
int32_t indicesCount = 0;
reader.r_DWord(addr, indicesCount);
addr += tTypeSize::DWORD;
if (indicesCount < 3) return mesh; //TODO: Error
for (uint32_t i = 0; i < indicesCount; i++)
{
int32_t index = 0;
reader.r_DWord(addr, index);
addr += tTypeSize::DWORD;
mesh.indices.push_back(index);
}
int32_t textureCount = 0;
reader.r_DWord(addr, textureCount);
addr += tTypeSize::DWORD;
if (textureCount < 1) break;
for (uint32_t t = 0; t < textureCount; t++)
{
int8_t tex_type = 0; //TODO: Use
reader.r_Byte(addr, tex_type);
addr += tTypeSize::BYTE;
int32_t tex_path_len = 0;
reader.r_DWord(addr, tex_path_len);
addr += tTypeSize::DWORD;
if (tex_path_len < 1) return mesh; //TODO: Error
StringEditor texPath_se;
if (texturesSubPath != "")
texPath_se.add(texturesSubPath).add("/");
for (uint32_t i = 0; i < tex_path_len; i++)
{
int8_t c = 0;
reader.r_Byte(addr, c);
addr += tTypeSize::BYTE;
texPath_se.add(c);
}
/*std::vector<uint8_t> tex_data;
int32_t tex_size = 0;
reader.r_DWord(addr, tex_size);
addr += tTypeSize::DWORD;
if (tex_size < 4) return mesh; //TODO: Error
for (uint32_t i = 0; i < tex_size; i++)
{
int8_t b = 0;
reader.r_Byte(addr, b);
addr += tTypeSize::BYTE;
tex_data.push_back(b);
}*/
//mesh.textures.push_back(ResourceManager::loadTexture(&tex_data[0], tex_size, 0, 0));
mesh.textures.push_back(ResourceManager::loadTexture(texPath_se.str()));
}
}
s_error = false;
//mesh.initialize();
return mesh;
}
void OX3DLoader::loadRawData(const String& filePath)
{
s_rawData.clear();
std::ifstream fin(filePath, std::ios::binary);
if (!fin.is_open()) return; //TODO: Error
fin.seekg(0, std::ios::end);
size_t fileSize = fin.tellg();
fin.seekg(0, std::ios::beg);
s_rawData = ByteStream(fileSize, 0);
fin.read(reinterpret_cast<char*>(&s_rawData[0]), fileSize);
}
}

25
src/ogfx/OX3DLoader.hpp Executable file
View file

@ -0,0 +1,25 @@
#ifndef __OX3D_LOADER_HPP__
#define __OX3D_LOADER_HPP__
#include <ostd/Types.hpp>
#include <ogfx/Mesh.hpp>
namespace ogfx
{
class OX3DLoader
{
public:
static Mesh loadFromFile(const ostd::String& filePath, const ostd::String& texturesSubPath = ""); //TODO: Handle more than only the first mesh
static inline bool errorOccurred(void) { return s_error; }
private:
static void loadRawData(const ostd::String& filePath);
private:
inline static ostd::ByteStream s_rawData;
inline static bool s_error = false;
};
}
#endif

12
src/ogfx/RTData.cpp Executable file
View file

@ -0,0 +1,12 @@
#include "RTData.hpp"
#include <ostd/Signals.hpp>
namespace ogfx
{
using namespace ostd;
uint32_t RTData::newCustomSignal(uint32_t sub_id)
{
return tBuiltinSignals::CustomSignalBase + sub_id;
}
}

18
src/ogfx/RTData.hpp Executable file
View file

@ -0,0 +1,18 @@
#ifndef __RTDATA_HPP__
#define __RTDATA_HPP__
#include <ostd/Types.hpp>
#include <ostd/Geometry.hpp>
namespace ogfx
{
class RTData
{
public:
inline static float DeltaTime { 0.0f };
inline static ostd::IPoint windowSize { 0, 0 };
static uint32_t newCustomSignal(uint32_t sub_id);
};
}
#endif

446
src/ogfx/RenderCommands.cpp Executable file
View file

@ -0,0 +1,446 @@
#include "RenderCommands.hpp"
#include <ogfx/RenderCore.hpp>
namespace ogfx
{
using namespace ostd;
static constexpr uint32_t DEFAULT_POOL_BLOCK_SIZE = 512;
static constexpr uint32_t SMALL_POOL_BLOCK_SIZE = 64;
void RenderCommandPool::init(void)
{
s_clearCmdPool.reserve(DEFAULT_POOL_BLOCK_SIZE);
for (uint32_t i = 0; i < DEFAULT_POOL_BLOCK_SIZE; i++)
s_clearCmdPool.push_back(new rcom::Clear({ 0, 0, 0, 0 }));
s_drawQuadPool.reserve(DEFAULT_POOL_BLOCK_SIZE);
for (uint32_t i = 0; i < DEFAULT_POOL_BLOCK_SIZE; i++)
s_drawQuadPool.push_back(new rcom::DrawQuad({}, { 0, 0, 0, 0 }, { 0, 0 }));
s_drawLinePool.reserve(DEFAULT_POOL_BLOCK_SIZE);
for (uint32_t i = 0; i < DEFAULT_POOL_BLOCK_SIZE; i++)
s_drawLinePool.push_back(new rcom::DrawLine({ 0, 0 }, { 0, 0 }, 0.0f, { 0, 0, 0, 0 }));
s_drawTextPool.reserve(DEFAULT_POOL_BLOCK_SIZE);
for (uint32_t i = 0; i < DEFAULT_POOL_BLOCK_SIZE; i++)
s_drawTextPool.push_back(new rcom::DrawText("", 0, Vec2(0.0f, 0.0f), Color(0, 0, 0, 0), 0.0f, 0.0f));
s_bindShaderPool.reserve(SMALL_POOL_BLOCK_SIZE);
for (uint32_t i = 0; i < SMALL_POOL_BLOCK_SIZE; i++)
s_bindShaderPool.push_back(new rcom::BindShader(0));
s_updUfQueue.reserve(SMALL_POOL_BLOCK_SIZE);
for (uint32_t i = 0; i < SMALL_POOL_BLOCK_SIZE; i++)
s_updUfQueue.push_back(new rcom::UpdateUniform<float>("", 0, 0.0f));
s_updUiQueue.reserve(SMALL_POOL_BLOCK_SIZE);
for (uint32_t i = 0; i < SMALL_POOL_BLOCK_SIZE; i++)
s_updUiQueue.push_back(new rcom::UpdateUniform<int32_t>("", 0, 0));
s_updUbQueue.reserve(SMALL_POOL_BLOCK_SIZE);
for (uint32_t i = 0; i < SMALL_POOL_BLOCK_SIZE; i++)
s_updUbQueue.push_back(new rcom::UpdateUniform<bool>("", 0, false));
s_updUvec2Queue.reserve(SMALL_POOL_BLOCK_SIZE);
for (uint32_t i = 0; i < SMALL_POOL_BLOCK_SIZE; i++)
s_updUvec2Queue.push_back(new rcom::UpdateUniform<Vec2>("", 0, { 0.0f, 0.0f }));
s_updUvec3Queue.reserve(SMALL_POOL_BLOCK_SIZE);
for (uint32_t i = 0; i < SMALL_POOL_BLOCK_SIZE; i++)
s_updUvec3Queue.push_back(new rcom::UpdateUniform<Vec3>("", 0, { 0.0f, 0.0f, 0.0f }));
s_updUvec4Queue.reserve(SMALL_POOL_BLOCK_SIZE);
for (uint32_t i = 0; i < SMALL_POOL_BLOCK_SIZE; i++)
s_updUvec4Queue.push_back(new rcom::UpdateUniform<Vec4>("", 0, { 0.0f, 0.0f, 0.0f, 0.0f }));
s_updUmat4Queue.reserve(SMALL_POOL_BLOCK_SIZE);
for (uint32_t i = 0; i < SMALL_POOL_BLOCK_SIZE; i++)
s_updUmat4Queue.push_back(new rcom::UpdateUniform<glm::mat4>("", 0, glm::mat4(0.0f)));
s_updUcolQueue.reserve(SMALL_POOL_BLOCK_SIZE);
for (uint32_t i = 0; i < SMALL_POOL_BLOCK_SIZE; i++)
s_updUcolQueue.push_back(new rcom::UpdateUniform<Color>("", 0, { 0, 0, 0, 0 }));
s_updUarriQueue.reserve(SMALL_POOL_BLOCK_SIZE);
for (uint32_t i = 0; i < SMALL_POOL_BLOCK_SIZE; i++)
s_updUarriQueue.push_back(new rcom::UpdateUniform<std::vector<int32_t>>("", 0, { }));
s_updUarrfQueue.reserve(SMALL_POOL_BLOCK_SIZE);
for (uint32_t i = 0; i < SMALL_POOL_BLOCK_SIZE; i++)
s_updUarrfQueue.push_back(new rcom::UpdateUniform<std::vector<float>>("", 0, { }));
s_initialized = true;
}
void RenderCommandPool::destroy(void)
{
return; //TODO: Fix memory leak (got a crash when caling this function, that's why it's currently disabled)
if (!s_initialized) return;
for (auto& clr : s_clearCmdPool)
delete clr;
for (auto& drwQuad : s_drawQuadPool)
delete drwQuad;
for (auto& drwLine : s_drawLinePool)
delete drwLine;
for (auto& drwText : s_drawTextPool)
delete drwText;
for (auto& bindUnif : s_bindShaderPool)
delete bindUnif;
for (auto& upd : s_updUfQueue)
delete upd;
for (auto& upd : s_updUiQueue)
delete upd;
for (auto& upd : s_updUbQueue)
delete upd;
for (auto& upd : s_updUvec2Queue)
delete upd;
for (auto& upd : s_updUvec3Queue)
delete upd;
for (auto& upd : s_updUvec4Queue)
delete upd;
for (auto& upd : s_updUmat4Queue)
delete upd;
for (auto& upd : s_updUcolQueue)
delete upd;
for (auto& upd : s_updUarriQueue)
delete upd;
for (auto& upd : s_updUarrfQueue)
delete upd;
}
void RenderCommandPool::newFrame(void)
{
s_nextClrCmd = 0;
s_nextDrwQuadCmd = 0;
s_nextDrwLineCmd = 0;
s_nextDrwTextCmd = 0;
s_nextBindShaderCmd = 0;
s_nextUpdaUfCmd = 0;
s_nextUpdaUiCmd = 0;
s_nextUpdaUbCmd = 0;
s_nextUpdaUvec2Cmd = 0;
s_nextUpdaUvec3Cmd = 0;
s_nextUpdaUvec4Cmd = 0;
s_nextUpdaUmat4Cmd = 0;
s_nextUpdaUcolCmd = 0;
s_nextUpdaUarriCmd = 0;
s_nextUpdaUarrfCmd = 0;
}
RenderCommand* RenderCommandPool::newClearCommand(const Color& clearColor)
{
if (s_nextClrCmd == s_clearCmdPool.size())
{
s_clearCmdPool.reserve(s_clearCmdPool.size() + DEFAULT_POOL_BLOCK_SIZE);
for (uint32_t i = 0; i < DEFAULT_POOL_BLOCK_SIZE; i++)
s_clearCmdPool.push_back(new rcom::Clear({ 0, 0, 0, 0 }));
OX_DEBUG("Reallocated ClearCommand pool to size=%d.", s_clearCmdPool.size());
}
rcom::Clear* cmd = s_clearCmdPool[s_nextClrCmd++];
cmd->create(clearColor);
return (RenderCommand*)cmd;
}
RenderCommand* RenderCommandPool::newDrawQuadCommand(const std::vector<Vec2>& vertices, const Color& color, TextureID texture)
{
if (s_nextDrwQuadCmd == s_drawQuadPool.size())
{
s_drawQuadPool.reserve(s_drawQuadPool.size() + DEFAULT_POOL_BLOCK_SIZE);
for (uint32_t i = 0; i < DEFAULT_POOL_BLOCK_SIZE; i++)
s_drawQuadPool.push_back(new rcom::DrawQuad({}, { 0, 0, 0, 0 }, { 0, 0 }));
OX_DEBUG("Reallocated DrawQuadCommand pool to size=%d.", s_drawQuadPool.size());
}
rcom::DrawQuad* cmd = s_drawQuadPool[s_nextDrwQuadCmd++];
cmd->create(vertices, color, texture);
return (RenderCommand*)cmd;
}
RenderCommand* RenderCommandPool::newDrawLineCommand(const Vec2& start, const Vec2& end, float thikness, const Color& color)
{
if (s_nextDrwLineCmd == s_drawLinePool.size())
{
s_drawLinePool.reserve(s_drawLinePool.size() + DEFAULT_POOL_BLOCK_SIZE);
for (uint32_t i = 0; i < DEFAULT_POOL_BLOCK_SIZE; i++)
s_drawLinePool.push_back(new rcom::DrawLine({ 0, 0 }, { 0, 0 }, 0.0f, { 0, 0, 0, 0 }));
OX_DEBUG("Reallocated DrawLineCommand pool to size=%d.", s_drawLinePool.size());
}
rcom::DrawLine* cmd = s_drawLinePool[s_nextDrwLineCmd++];
cmd->create(start, end, thikness, color);
return (RenderCommand*)cmd;
}
RenderCommand* RenderCommandPool::newDrawTextCommand(const String& text, ResourceID font, const Vec2& position, const Color& color, float charHeight, float spacing)
{
if (s_nextDrwTextCmd == s_drawTextPool.size())
{
s_drawTextPool.reserve(s_drawTextPool.size() + DEFAULT_POOL_BLOCK_SIZE);
for (uint32_t i = 0; i < DEFAULT_POOL_BLOCK_SIZE; i++)
s_drawTextPool.push_back(new rcom::DrawText("", 0, Vec2(0.0f, 0.0f), Color(0, 0, 0, 0), 0.0f, 0.0f));
OX_DEBUG("Reallocated DrawTextCommand pool to size=%d.", s_drawTextPool.size());
}
rcom::DrawText* cmd = s_drawTextPool[s_nextDrwTextCmd++];
cmd->create(text, font, position, color, charHeight, spacing);
return (RenderCommand*)cmd;
}
RenderCommand* RenderCommandPool::newBindSHaderCommand(ResourceID shader)
{
if (s_nextBindShaderCmd == s_bindShaderPool.size())
{
s_bindShaderPool.reserve(s_bindShaderPool.size() + SMALL_POOL_BLOCK_SIZE);
for (uint32_t i = 0; i < DEFAULT_POOL_BLOCK_SIZE; i++)
s_bindShaderPool.push_back(new rcom::BindShader(0));
OX_DEBUG("Reallocated BindShaderCommand pool to size=%d.", s_bindShaderPool.size());
}
rcom::BindShader* cmd = s_bindShaderPool[s_nextBindShaderCmd++];
cmd->create(shader);
return (RenderCommand*)cmd;
}
RenderCommand* RenderCommandPool::newUpdateUniform_f_Command(const String& name, ResourceID shader, float value)
{
if (s_nextUpdaUfCmd == s_updUfQueue.size())
{
s_updUfQueue.reserve(s_updUfQueue.size() + SMALL_POOL_BLOCK_SIZE);
for (uint32_t i = 0; i < SMALL_POOL_BLOCK_SIZE; i++)
s_updUfQueue.push_back(new rcom::UpdateUniform<float>("", 0, 0.0f));
OX_DEBUG("Reallocated UpdateUniform_f_Command pool to size=%d.", s_updUfQueue.size());
}
auto cmd = s_updUfQueue[s_nextUpdaUfCmd++];
cmd->create(name, shader, value);
return (RenderCommand*)cmd;
}
RenderCommand* RenderCommandPool::newUpdateUniform_i_Command(const String& name, ResourceID shader, int32_t value)
{
if (s_nextUpdaUiCmd == s_updUiQueue.size())
{
s_updUiQueue.reserve(s_updUiQueue.size() + SMALL_POOL_BLOCK_SIZE);
for (uint32_t i = 0; i < SMALL_POOL_BLOCK_SIZE; i++)
s_updUiQueue.push_back(new rcom::UpdateUniform<int32_t>("", 0, 0));
OX_DEBUG("Reallocated UpdateUniform_i_Command pool to size=%d.", s_updUiQueue.size());
}
auto cmd = s_updUiQueue[s_nextUpdaUiCmd++];
cmd->create(name, shader, value);
return (RenderCommand*)cmd;
}
RenderCommand* RenderCommandPool::newUpdateUniform_b_Command(const String& name, ResourceID shader, bool value)
{
if (s_nextUpdaUbCmd == s_updUbQueue.size())
{
s_updUbQueue.reserve(s_updUbQueue.size() + SMALL_POOL_BLOCK_SIZE);
for (uint32_t i = 0; i < SMALL_POOL_BLOCK_SIZE; i++)
s_updUbQueue.push_back(new rcom::UpdateUniform<bool>("", 0, false));
OX_DEBUG("Reallocated UpdateUniform_b_Command pool to size=%d.", s_updUbQueue.size());
}
auto cmd = s_updUbQueue[s_nextUpdaUbCmd++];
cmd->create(name, shader, value);
return (RenderCommand*)cmd;
}
RenderCommand* RenderCommandPool::newUpdateUniform_vec2_Command(const String& name, ResourceID shader, Vec2 value)
{
if (s_nextUpdaUvec2Cmd == s_updUvec2Queue.size())
{
s_updUvec2Queue.reserve(s_updUvec2Queue.size() + SMALL_POOL_BLOCK_SIZE);
for (uint32_t i = 0; i < SMALL_POOL_BLOCK_SIZE; i++)
s_updUvec2Queue.push_back(new rcom::UpdateUniform<Vec2>("", 0, { 0.0f, 0.0f }));
OX_DEBUG("Reallocated UpdateUniform_vec2_Command pool to size=%d.", s_updUvec2Queue.size());
}
auto cmd = s_updUvec2Queue[s_nextUpdaUvec2Cmd++];
cmd->create(name, shader, value);
return (RenderCommand*)cmd;
}
RenderCommand* RenderCommandPool::newUpdateUniform_vec3_Command(const String& name, ResourceID shader, Vec3 value)
{
if (s_nextUpdaUvec3Cmd == s_updUvec3Queue.size())
{
s_updUvec3Queue.reserve(s_updUvec3Queue.size() + SMALL_POOL_BLOCK_SIZE);
for (uint32_t i = 0; i < SMALL_POOL_BLOCK_SIZE; i++)
s_updUvec3Queue.push_back(new rcom::UpdateUniform<Vec3>("", 0, { 0.0f, 0.0f }));
OX_DEBUG("Reallocated UpdateUniform_vec3_Command pool to size=%d.", s_updUvec3Queue.size());
}
auto cmd = s_updUvec3Queue[s_nextUpdaUvec3Cmd++];
cmd->create(name, shader, value);
return (RenderCommand*)cmd;
}
RenderCommand* RenderCommandPool::newUpdateUniform_vec4_Command(const String& name, ResourceID shader, Vec4 value)
{
if (s_nextUpdaUvec4Cmd == s_updUvec4Queue.size())
{
s_updUvec4Queue.reserve(s_updUvec4Queue.size() + SMALL_POOL_BLOCK_SIZE);
for (uint32_t i = 0; i < SMALL_POOL_BLOCK_SIZE; i++)
s_updUvec4Queue.push_back(new rcom::UpdateUniform<Vec4>("", 0, { 0.0f, 0.0f }));
OX_DEBUG("Reallocated UpdateUniform_vec4_Command pool to size=%d.", s_updUvec4Queue.size());
}
auto cmd = s_updUvec4Queue[s_nextUpdaUvec4Cmd++];
cmd->create(name, shader, value);
return (RenderCommand*)cmd;
}
RenderCommand* RenderCommandPool::newUpdateUniform_mat4_Command(const String& name, ResourceID shader, const glm::mat4& value)
{
if (s_nextUpdaUmat4Cmd == s_updUmat4Queue.size())
{
s_updUmat4Queue.reserve(s_updUmat4Queue.size() + SMALL_POOL_BLOCK_SIZE);
for (uint32_t i = 0; i < SMALL_POOL_BLOCK_SIZE; i++)
s_updUmat4Queue.push_back(new rcom::UpdateUniform<glm::mat4>("", 0, glm::mat4(0.0f)));
OX_DEBUG("Reallocated UpdateUniform_mat4_Command pool to size=%d.", s_updUmat4Queue.size());
}
auto cmd = s_updUmat4Queue[s_nextUpdaUmat4Cmd++];
cmd->create(name, shader, value);
return (RenderCommand*)cmd;
}
RenderCommand* RenderCommandPool::newUpdateUniform_col_Command(const String& name, ResourceID shader, const Color& value)
{
if (s_nextUpdaUcolCmd == s_updUcolQueue.size())
{
s_updUcolQueue.reserve(s_updUcolQueue.size() + SMALL_POOL_BLOCK_SIZE);
for (uint32_t i = 0; i < SMALL_POOL_BLOCK_SIZE; i++)
s_updUcolQueue.push_back(new rcom::UpdateUniform<Color>("", 0, { 0, 0, 0, 0 }));
OX_DEBUG("Reallocated UpdateUniform_col_Command pool to size=%d.", s_updUcolQueue.size());
}
auto cmd = s_updUcolQueue[s_nextUpdaUcolCmd++];
cmd->create(name, shader, value);
return (RenderCommand*)cmd;
}
RenderCommand* RenderCommandPool::newUpdateUniform_arri_Command(const String& name, ResourceID shader, const std::vector<int32_t>& value)
{
if (s_nextUpdaUarriCmd == s_updUarriQueue.size())
{
s_updUarriQueue.reserve(s_updUarriQueue.size() + SMALL_POOL_BLOCK_SIZE);
for (uint32_t i = 0; i < SMALL_POOL_BLOCK_SIZE; i++)
s_updUarriQueue.push_back(new rcom::UpdateUniform<std::vector<int32_t>>("", 0, { }));
OX_DEBUG("Reallocated UpdateUniform_arri_Command pool to size=%d.", s_updUarriQueue.size());
}
auto cmd = s_updUarriQueue[s_nextUpdaUarriCmd++];
cmd->create(name, shader, value);
return (RenderCommand*)cmd;
}
RenderCommand* RenderCommandPool::newUpdateUniform_arrf_Command(const String& name, ResourceID shader, const std::vector<float>& value)
{
if (s_nextUpdaUarrfCmd == s_updUarrfQueue.size())
{
s_updUarrfQueue.reserve(s_updUarrfQueue.size() + SMALL_POOL_BLOCK_SIZE);
for (uint32_t i = 0; i < SMALL_POOL_BLOCK_SIZE; i++)
s_updUarrfQueue.push_back(new rcom::UpdateUniform<std::vector<float>>("", 0, { }));
OX_DEBUG("Reallocated UpdateUniform_arrf_Command pool to size=%d.", s_updUarrfQueue.size());
}
auto cmd = s_updUarrfQueue[s_nextUpdaUarrfCmd++];
cmd->create(name, shader, value);
return (RenderCommand*)cmd;
}
namespace rcom
{
BindShader::BindShader(ResourceID shaderID)
{
setTypeName("ox::rcom::BindShader");
m_commandID = tRenderCommands::BindShader;
validate();
create(shaderID);
}
BindShader& BindShader::create(ResourceID shaderID)
{
m_shaderID = shaderID;
return *this;
}
uint8_t BindShader::execute(void)
{
if (isInvalid()) return tRenderCommandErrors::InvalidatedRenderCommand;
if (Renderer2D::bindShader(m_shaderID).isInvalid())
return tRenderCommandErrors::InvalidShader;
return tRenderCommandErrors::NoError;
}
Clear::Clear(const Color& clearColor)
{
setTypeName("ox::rcom::Clear");
validate();
m_commandID = tRenderCommands::Clear;
create(clearColor);
}
Clear& Clear::create(const Color& clearColor)
{
m_clearColor = clearColor;
return *this;
}
uint8_t Clear::execute(void)
{
if (isInvalid()) return tRenderCommandErrors::InvalidatedRenderCommand;
Renderer2D::clear(m_clearColor);
return tRenderCommandErrors::NoError;
}
DrawQuad::DrawQuad(const std::vector<Vec2>& vertices, const Color& color, TextureID texture)
{
setTypeName("ox::rcom::DrawQuad");
m_commandID = tRenderCommands::DrawQuad;
validate();
create(vertices, color, texture);
}
DrawQuad& DrawQuad::create(const std::vector<Vec2>& vertices, const Color& color, TextureID texture)
{
m_color = color;
m_texture = texture;
m_vertices = vertices;
return *this;
}
uint8_t DrawQuad::execute(void)
{
if (isInvalid()) return tRenderCommandErrors::InvalidatedRenderCommand;
Renderer2D::drawQuad(m_vertices, m_color, m_texture.texture, m_texture.tile);
return tRenderCommandErrors::NoError;
}
DrawLine::DrawLine(const Vec2& start, const Vec2& end, float thikness, const Color& color)
{
setTypeName("ox::rcom::DrawLine");
m_commandID = tRenderCommands::DrawLine;
validate();
create(start, end, thikness, color);
}
DrawLine& DrawLine::create(const Vec2& start, const Vec2& end, float thikness, const Color& color)
{
m_start = start;
m_end = end;
m_thickness = thikness;
m_color = color;
return *this;
}
uint8_t DrawLine::execute(void)
{
if (isInvalid()) return tRenderCommandErrors::InvalidatedRenderCommand;
Renderer2D::drawLine(m_start, m_end, m_thickness, m_color);
return tRenderCommandErrors::NoError;
}
DrawText::DrawText(const String& text, ResourceID font, const Vec2& position, const Color& color, float charHeight, float spacing)
{
setTypeName("ox::rcom::DrawText");
m_commandID = tRenderCommands::DrawText;
validate();
create(text, font, position, color, charHeight, spacing);
}
DrawText& DrawText::create(const String& text, ResourceID font, const Vec2& position, const Color& color, float charHeight, float spacing)
{
m_text = text;
m_textInfo.font = font;
m_textInfo.characterHeight = charHeight;
m_textInfo.color = color;
m_textInfo.characterSpacing = spacing;
m_position = position;
return *this;
}
uint8_t DrawText::execute(void)
{
if (isInvalid()) return tRenderCommandErrors::InvalidatedRenderCommand;
Renderer2D::Text::draw(m_text, m_position, m_textInfo);
return tRenderCommandErrors::NoError;
}
}
} // namespace ox

229
src/ogfx/RenderCommands.hpp Executable file
View file

@ -0,0 +1,229 @@
#ifndef __RENDER_COMMANDS_HPP__
#define __RENDER_COMMANDS_HPP__
#include <ostd/BaseObject.hpp>
#include <ostd/Types.hpp>
#include <ostd/Color.hpp>
#include <ogfx/Renderer2D.hpp>
namespace ogfx
{
using namespace ostd; //TODO: Remove from header
struct tRenderCommands
{
inline static constexpr uint8_t Invalid = 0x00;
inline static constexpr uint8_t BindShader = 0x10;
inline static constexpr uint8_t UpdateUniform = 0x11;
inline static constexpr uint8_t DrawQuad = 0x12;
inline static constexpr uint8_t DrawText = 0x13;
inline static constexpr uint8_t Clear = 0x14;
inline static constexpr uint8_t DrawLine = 0x15;
};
struct tRenderCommandErrors
{
inline static constexpr uint8_t NoError = 0x00;
inline static constexpr uint8_t InvalidShader = 0x01;
inline static constexpr uint8_t UnknownUniformType = 0x02;
inline static constexpr uint8_t InvalidatedRenderCommand = 0x03;
};
class RenderCommand : public BaseObject
{
public:
inline RenderCommand(void) { m_commandID = tRenderCommands::Invalid; invalidate(); }
inline virtual ~RenderCommand(void) { }
virtual uint8_t execute(void) = 0;
inline uint8_t getCommandID(void) { return m_commandID; }
protected:
uint8_t m_commandID;
};
namespace rcom
{
class Clear;
class DrawQuad;
class DrawLine;
class DrawText;
class BindShader;
template <typename T>
class UpdateUniform;
}
class RenderCommandPool
{
public:
static void init(void);
static void destroy(void);
static void newFrame(void);
static RenderCommand* newClearCommand(const Color& clearColor);
static RenderCommand* newDrawQuadCommand(const std::vector<Vec2>& vertices, const Color& color, TextureID texture);
static RenderCommand* newDrawLineCommand(const Vec2& start, const Vec2& end, float thikness, const Color& color);
static RenderCommand* newDrawTextCommand(const String& text, ResourceID font, const Vec2& position, const Color& color, float charHeight, float spacing);
static RenderCommand* newBindSHaderCommand(ResourceID shader);
static RenderCommand* newUpdateUniform_f_Command(const String& name, ResourceID shader, float value);
static RenderCommand* newUpdateUniform_i_Command(const String& name, ResourceID shader, int32_t value);
static RenderCommand* newUpdateUniform_b_Command(const String& name, ResourceID shader, bool value);
static RenderCommand* newUpdateUniform_vec2_Command(const String& name, ResourceID shader, Vec2 value);
static RenderCommand* newUpdateUniform_vec3_Command(const String& name, ResourceID shader, Vec3 value);
static RenderCommand* newUpdateUniform_vec4_Command(const String& name, ResourceID shader, Vec4 value);
static RenderCommand* newUpdateUniform_mat4_Command(const String& name, ResourceID shader, const glm::mat4& value);
static RenderCommand* newUpdateUniform_col_Command(const String& name, ResourceID shader, const Color& value);
static RenderCommand* newUpdateUniform_arri_Command(const String& name, ResourceID shader, const std::vector<int32_t>& value);
static RenderCommand* newUpdateUniform_arrf_Command(const String& name, ResourceID shader, const std::vector<float>& value);
private:
inline static std::vector<rcom::Clear*> s_clearCmdPool;
inline static uint32_t s_nextClrCmd { 0 };
inline static std::vector<rcom::DrawQuad*> s_drawQuadPool;
inline static uint32_t s_nextDrwQuadCmd { 0 };
inline static std::vector<rcom::DrawText*> s_drawTextPool;
inline static uint32_t s_nextDrwTextCmd { 0 };
inline static std::vector<rcom::DrawLine*> s_drawLinePool;
inline static uint32_t s_nextDrwLineCmd { 0 };
inline static std::vector<rcom::BindShader*> s_bindShaderPool;
inline static uint32_t s_nextBindShaderCmd { 0 };
inline static std::vector<rcom::UpdateUniform<float>*> s_updUfQueue;
inline static uint32_t s_nextUpdaUfCmd { 0 };
inline static std::vector<rcom::UpdateUniform<int32_t>*> s_updUiQueue;
inline static uint32_t s_nextUpdaUiCmd { 0 };
inline static std::vector<rcom::UpdateUniform<bool>*> s_updUbQueue;
inline static uint32_t s_nextUpdaUbCmd { 0 };
inline static std::vector<rcom::UpdateUniform<Vec2>*> s_updUvec2Queue;
inline static uint32_t s_nextUpdaUvec2Cmd { 0 };
inline static std::vector<rcom::UpdateUniform<Vec3>*> s_updUvec3Queue;
inline static uint32_t s_nextUpdaUvec3Cmd { 0 };
inline static std::vector<rcom::UpdateUniform<Vec4>*> s_updUvec4Queue;
inline static uint32_t s_nextUpdaUvec4Cmd { 0 };
inline static std::vector<rcom::UpdateUniform<glm::mat4>*> s_updUmat4Queue;
inline static uint32_t s_nextUpdaUmat4Cmd { 0 };
inline static std::vector<rcom::UpdateUniform<Color>*> s_updUcolQueue;
inline static uint32_t s_nextUpdaUcolCmd { 0 };
inline static std::vector<rcom::UpdateUniform<std::vector<int32_t>>*> s_updUarriQueue;
inline static uint32_t s_nextUpdaUarriCmd { 0 };
inline static std::vector<rcom::UpdateUniform<std::vector<float>>*> s_updUarrfQueue;
inline static uint32_t s_nextUpdaUarrfCmd { 0 };
inline static bool s_initialized { false };
};
namespace rcom
{
class BindShader : public RenderCommand
{
public:
BindShader(ResourceID shaderID);
BindShader& create(ResourceID shaderID);
uint8_t execute(void) override;
private:
ResourceID m_shaderID;
};
class Clear : public RenderCommand
{
public:
Clear(const Color& clearColor);
Clear& create(const Color& clearColor);
uint8_t execute(void) override;
private:
Color m_clearColor;
};
class DrawQuad : public RenderCommand
{
public:
DrawQuad(const std::vector<Vec2>& vertices, const Color& color, TextureID texture);
DrawQuad& create(const std::vector<Vec2>& vertices, const Color& color, TextureID texture);
uint8_t execute(void) override;
private:
Color m_color;
std::vector<Vec2> m_vertices;
TextureID m_texture;
};
class DrawLine : public RenderCommand
{
public:
DrawLine(const Vec2& start, const Vec2& end, float thikness, const Color& color);
DrawLine& create(const Vec2& start, const Vec2& end, float thikness, const Color& color);
uint8_t execute(void) override;
private:
Vec2 m_start;
Vec2 m_end;
float m_thickness;
Color m_color;
};
class DrawText : public RenderCommand
{
public:
DrawText(const String& text, ResourceID font, const Vec2& position, const Color& color, float charHeight, float spacing);
DrawText& create(const String& text, ResourceID font, const Vec2& position, const Color& color, float charHeight, float spacing);
uint8_t execute(void) override;
private:
Renderer2D::tTextInfo m_textInfo;
String m_text;
Vec2 m_position;
};
template <typename T>
class UpdateUniform : public RenderCommand
{
public:
inline UpdateUniform(String name, ResourceID shaderID, T value)
{
m_commandID = tRenderCommands::UpdateUniform;
setTypeName("ox::rcom::UpdateUniform");
validate();
create(name, shaderID, value);
}
inline UpdateUniform<T>& create(String name, ResourceID shaderID, T value)
{
m_shaderID = shaderID;
m_value = value;
m_name = name;
return *this;
}
inline uint8_t execute(void) override
{
if (isInvalid()) return tRenderCommandErrors::InvalidatedRenderCommand;
auto& shader = ResourceManager::getShader(m_shaderID);
if (shader.isInvalid()) return tRenderCommandErrors::InvalidShader;
if constexpr(std::is_same_v<T, float>)
shader.updateUniform_f(m_name, m_value);
else if constexpr(std::is_same_v<T, int32_t>)
shader.updateUniform_i(m_name, m_value);
else if constexpr(std::is_same_v<T, bool>)
shader.updateUniform_b(m_name, m_value);
else if constexpr(std::is_same_v<T, Vec2>)
shader.updateUniform_vec2f(m_name, m_value);
else if constexpr(std::is_same_v<T, Vec3>)
shader.updateUniform_vec3f(m_name, m_value);
else if constexpr(std::is_same_v<T, Vec4>)
shader.updateUniform_vec4f(m_name, m_value);
else if constexpr(std::is_same_v<T, glm::mat4>)
shader.updateUniform_mat4f(m_name, m_value);
else if constexpr(std::is_same_v<T, std::vector<int32_t>>)
shader.updateUniform_arri(m_name, m_value.size(), &m_value[0]);
else if constexpr(std::is_same_v<T, std::vector<float>>)
shader.updateUniform_arrf(m_name, m_value.size(), &m_value[0]);
else if constexpr(std::is_same_v<T, Color>)
shader.updateUniform_vec4f(m_name, m_value);
else
return tRenderCommandErrors::UnknownUniformType;
return tRenderCommandErrors::NoError;
}
private:
T m_value;
String m_name;
ResourceID m_shaderID { ResourceManager::InvalidResource };
};
}
}
#endif

336
src/ogfx/RenderCore.cpp Executable file
View file

@ -0,0 +1,336 @@
#include "RenderCore.hpp"
#include <ogfx/ResourceManager.hpp>
//#include <omniax/core/GameObject.hpp>
#include <ogfx/Camera.hpp>
namespace ogfx
{
using namespace ostd;
void RenderCore::display(void)
{
for (auto& targ : s_renderQueue)
{
targ.exec();
m_renderCmdCount += targ.cmdList.size();
targ.cmdList.clear();
}
}
// void RenderCore::newFrame(void)
// {
// s_renderQueue.clear();
// tRComPair default_rtarg;
// default_rtarg.rTarg = &Renderer2D::getDefaultRenderTarget();
// s_renderQueue.push_back(default_rtarg);
// }
void RenderCore::initRenderQUeue(void)
{
s_renderQueue.reserve(100);
tRComPair default_rtarg;
default_rtarg.rTarg = &Renderer2D::getDefaultRenderTarget();
s_renderQueue.push_back(default_rtarg);
}
RenderCore::RenderCore(void)
{
}
void RenderCore::init(void)
{
m_textFont = ResourceManager::getDefaultBitmapFont();
__store_text_parameters();
}
void RenderCore::setRenderTarget(const RenderTarget& target, bool follow_camera)
{
bool valid_cam = hasValidCamera();
for (uint32_t i = 0; i < RenderCore::s_renderQueue.size(); i++)
{
auto& rtarg = RenderCore::s_renderQueue[i];
if (rtarg.rTarg->getResourceID() == target.getResourceID())
{
m_currentRenderTarget = i;
if (follow_camera && valid_cam)
updateUniform_mat4f("u_viewProjMatrix", m_camera->getViewProjectionMatrix());
else if (valid_cam)
updateUniform_mat4f("u_viewProjMatrix", m_camera->getProjectionMatrix());
return;
}
}
tRComPair rtarg;
rtarg.rTarg = &target;
RenderCore::s_renderQueue.push_back(rtarg);
m_currentRenderTarget = RenderCore::s_renderQueue.size() - 1;
if (follow_camera && valid_cam)
updateUniform_mat4f("u_viewProjMatrix", m_camera->getViewProjectionMatrix());
else if (valid_cam)
updateUniform_mat4f("u_viewProjMatrix", m_camera->getProjectionMatrix());
}
void RenderCore::setDefaultRenderTarget(void)
{
m_currentRenderTarget = 0;
if (hasValidCamera())
updateUniform_mat4f("u_viewProjMatrix", m_camera->getProjectionMatrix());
}
void RenderCore::bindShader(ResourceID shader)
{
RenderCore::s_renderQueue[m_currentRenderTarget].cmdList.push_back(RenderCommandPool::newBindSHaderCommand(shader));
m_currentShader = shader;
}
void RenderCore::clear(Color clearColor)
{
RenderCore::s_renderQueue[m_currentRenderTarget].cmdList.push_back(RenderCommandPool::newClearCommand(clearColor));
}
void RenderCore::updateUniform_f(String uniform_name, float value)
{
RenderCore::s_renderQueue[m_currentRenderTarget].cmdList.push_back(RenderCommandPool::newUpdateUniform_f_Command(uniform_name, m_currentShader, value));
}
void RenderCore::updateUniform_i(String uniform_name, int32_t value)
{
RenderCore::s_renderQueue[m_currentRenderTarget].cmdList.push_back(RenderCommandPool::newUpdateUniform_i_Command(uniform_name, m_currentShader, value));
}
void RenderCore::updateUniform_b(String uniform_name, bool value)
{
RenderCore::s_renderQueue[m_currentRenderTarget].cmdList.push_back(RenderCommandPool::newUpdateUniform_b_Command(uniform_name, m_currentShader, value));
}
void RenderCore::updateUniform_vec2f(String uniform_name, const Vec2& value)
{
RenderCore::s_renderQueue[m_currentRenderTarget].cmdList.push_back(RenderCommandPool::newUpdateUniform_vec2_Command(uniform_name, m_currentShader, value));
}
void RenderCore::updateUniform_vec3f(String uniform_name, const Vec3& value)
{
RenderCore::s_renderQueue[m_currentRenderTarget].cmdList.push_back(RenderCommandPool::newUpdateUniform_vec3_Command(uniform_name, m_currentShader, value));
}
void RenderCore::updateUniform_vec4f(String uniform_name, const Vec4& value)
{
RenderCore::s_renderQueue[m_currentRenderTarget].cmdList.push_back(RenderCommandPool::newUpdateUniform_vec4_Command(uniform_name, m_currentShader, value));
}
void RenderCore::updateUniform_col(String uniform_name, const Color& value)
{
RenderCore::s_renderQueue[m_currentRenderTarget].cmdList.push_back(RenderCommandPool::newUpdateUniform_col_Command(uniform_name, m_currentShader, value));
}
void RenderCore::updateUniform_mat4f(String uniform_name, const glm::mat4& value)
{
RenderCore::s_renderQueue[m_currentRenderTarget].cmdList.push_back(RenderCommandPool::newUpdateUniform_mat4_Command(uniform_name, m_currentShader, value));
}
void RenderCore::updateUniform_arri(String uniform_name, const std::vector<int32_t>& value)
{
RenderCore::s_renderQueue[m_currentRenderTarget].cmdList.push_back(RenderCommandPool::newUpdateUniform_arri_Command(uniform_name, m_currentShader, value));
}
void RenderCore::updateUniform_arrf(String uniform_name, const std::vector<float>& value)
{
RenderCore::s_renderQueue[m_currentRenderTarget].cmdList.push_back(RenderCommandPool::newUpdateUniform_arrf_Command(uniform_name, m_currentShader, value));
}
// void RenderCore::drawGameObject(GameObject& obj)
// {
// obj.draw(*this);
// }
void RenderCore::drawImage(TextureID texture, Vec2 position, Vec2 size, bool centereOrigin)
{
RenderCore::s_renderQueue[m_currentRenderTarget].cmdList.push_back(RenderCommandPool::newDrawQuadCommand(Renderer2D::getStaticQuad(position, size, centereOrigin), { 255, 255, 255 }, texture));
}
void RenderCore::drawImage(ResourceID texture, Vec2 position, Vec2 size, bool centereOrigin)
{
RenderCore::s_renderQueue[m_currentRenderTarget].cmdList.push_back(RenderCommandPool::newDrawQuadCommand(Renderer2D::getStaticQuad(position, size, centereOrigin), { 255, 255, 255 }, { texture, Texture::FullTextureCoords }));
}
void RenderCore::drawImage(TextureID texture, Vec2 position, Vec2 size, Color tint, bool centereOrigin)
{
RenderCore::s_renderQueue[m_currentRenderTarget].cmdList.push_back(RenderCommandPool::newDrawQuadCommand(Renderer2D::getStaticQuad(position, size, centereOrigin), tint, texture));
}
void RenderCore::drawImage(ResourceID texture, Vec2 position, Vec2 size, Color tint, bool centereOrigin)
{
RenderCore::s_renderQueue[m_currentRenderTarget].cmdList.push_back(RenderCommandPool::newDrawQuadCommand(Renderer2D::getStaticQuad(position, size, centereOrigin), tint, { texture, Texture::FullTextureCoords }));
}
void RenderCore::drawImage(TextureID texture, Color tint, Transform2D& transform)
{
RenderCore::s_renderQueue[m_currentRenderTarget].cmdList.push_back(RenderCommandPool::newDrawQuadCommand(transform.getVertices(), tint, texture));
}
void RenderCore::drawImage(ResourceID texture, Color tint, Transform2D& transform)
{
RenderCore::s_renderQueue[m_currentRenderTarget].cmdList.push_back(RenderCommandPool::newDrawQuadCommand(transform.getVertices(), tint, { texture, Texture::FullTextureCoords }));
}
void RenderCore::drawImage(TextureID texture, Transform2D& transform)
{
RenderCore::s_renderQueue[m_currentRenderTarget].cmdList.push_back(RenderCommandPool::newDrawQuadCommand(transform.getVertices(), { 255, 255, 255 }, texture));
}
void RenderCore::drawImage(ResourceID texture, Transform2D& transform)
{
RenderCore::s_renderQueue[m_currentRenderTarget].cmdList.push_back(RenderCommandPool::newDrawQuadCommand(transform.getVertices(), { 255, 255, 255 }, { texture, Texture::FullTextureCoords }));
}
void RenderCore::drawRenderTarget(const RenderTarget& target)
{
drawImage(target.getResourceID(), { 0.0f, 0.0f }, target.getSize());
}
void RenderCore::drawRenderTarget(const RenderTarget& target, Vec2 position, Vec2 size)
{
drawImage(target.getResourceID(), position, size);
}
void RenderCore::drawRenderTarget(const RenderTarget& target, Vec2 position, Vec2 size, Color tint)
{
drawImage(target.getResourceID(), position, size, tint);
}
void RenderCore::drawRenderTarget(const RenderTarget& target, Transform2D& transform)
{
drawImage(target.getResourceID(), transform);
}
void RenderCore::drawRenderTarget(const RenderTarget& target, Color tint, Transform2D& transform)
{
drawImage(target.getResourceID(), tint, transform);
}
void RenderCore::drawQuad(Vec2 position, Vec2 size, Color color)
{
RenderCore::s_renderQueue[m_currentRenderTarget].cmdList.push_back(RenderCommandPool::newDrawQuadCommand(Renderer2D::getStaticQuad(position, size), color, { 0, 0 }));
}
void RenderCore::drawQuad(Vec2 position, Vec2 size, Color color, bool centeredOrigin)
{
RenderCore::s_renderQueue[m_currentRenderTarget].cmdList.push_back(RenderCommandPool::newDrawQuadCommand(Renderer2D::getStaticQuad(position, size, centeredOrigin), color, { 0, 0 }));
}
void RenderCore::drawQuad(Color color, Transform2D& transform)
{
RenderCore::s_renderQueue[m_currentRenderTarget].cmdList.push_back(RenderCommandPool::newDrawQuadCommand(transform.getVertices(), color, { 0, 0 }));
}
void RenderCore::drawQuad(const std::vector<Vec2>& vertices, const Color& tintColor, TextureID texture)
{
RenderCore::s_renderQueue[m_currentRenderTarget].cmdList.push_back(RenderCommandPool::newDrawQuadCommand(vertices, tintColor, texture));
}
void RenderCore::drawLine(const Vec2& start, const Vec2& end, float thikness, const Color& color)
{
RenderCore::s_renderQueue[m_currentRenderTarget].cmdList.push_back(RenderCommandPool::newDrawLineCommand(start, end, thikness, color));
}
void RenderCore::drawText(const String& text, Vec2 position)
{
RenderCore::s_renderQueue[m_currentRenderTarget].cmdList.push_back(RenderCommandPool::newDrawTextCommand(text, m_textFont, position, m_textColor, m_textHeight, m_textSpacing));
}
void RenderCore::drawText(const String& text, Vec2 position, float fontSize)
{
__store_text_parameters();
m_textHeight = fontSize;
drawText(text, position);
__restore_text_parameters();
}
void RenderCore::drawText(const String& text, Vec2 position, Color color)
{
__store_text_parameters();
m_textColor = color;
drawText(text, position);
__restore_text_parameters();
}
void RenderCore::drawText(const String& text, Vec2 position, float fontSize, Color color)
{
__store_text_parameters();
m_textHeight = fontSize;
m_textColor = color;
drawText(text, position);
__restore_text_parameters();
}
void RenderCore::drawText(const String& text, Vec2 position, ResourceID font, float fontSize)
{
__store_text_parameters();
m_textHeight = fontSize;
m_textFont = font;
drawText(text, position);
__restore_text_parameters();
}
void RenderCore::drawText(const String& text, Vec2 position, ResourceID font, Color color)
{
__store_text_parameters();
m_textFont = font;
m_textColor = color;
drawText(text, position);
__restore_text_parameters();
}
void RenderCore::drawText(const String& text, Vec2 position, ResourceID font, float fontSize, Color color)
{
__store_text_parameters();
m_textFont = font;
m_textColor = color;
m_textHeight = fontSize;
drawText(text, position);
__restore_text_parameters();
}
void RenderCore::drawText(const String& text, Vec2 position, const Renderer2D::tTextInfo& params)
{
__store_text_parameters();
setTextParameters(params);
drawText(text, position);
__restore_text_parameters();
}
void RenderCore::setTextParameters(const Renderer2D::tTextInfo& params)
{
m_textFont = params.font;
m_textColor = params.color;
m_textHeight = params.characterHeight;
m_textSpacing = params.characterSpacing;
}
void RenderCore::__store_text_parameters(void)
{
m_textHeight_stored = m_textHeight;
m_textSpacing_stored = m_textSpacing;
m_textFont_stored = m_textFont;
m_textColor_stored = m_textColor;
}
void RenderCore::__restore_text_parameters(void)
{
m_textHeight = m_textHeight_stored;
m_textSpacing = m_textSpacing_stored;
m_textFont = m_textFont_stored;
m_textColor = m_textColor_stored;
}
bool RenderCore::hasValidCamera(void)
{
return m_camera != nullptr && m_camera->isValid();
}
OrthoCamera& RenderCore::getCamera(void)
{
if (hasValidCamera()) return *m_camera;
return ((OrthoCamera&)BaseObject::InvalidRef());
}
}

152
src/ogfx/RenderCore.hpp Executable file
View file

@ -0,0 +1,152 @@
#ifndef __RENDER_CORE_HPP__
#define __RENDER_CORE_HPP__
#include <ostd/BaseObject.hpp>
#include <ostd/Types.hpp>
#include <ostd/Geometry.hpp>
#include <ogfx/DataStructures.hpp>
#include <ostd/Color.hpp>
#include <ogfx/Renderer2D.hpp>
#include <ogfx/RenderCommands.hpp>
#include <ogfx/RenderTarget.hpp>
// #include <omniax/runtime/RTData.hpp>
namespace ogfx
{
using namespace ostd; //TODO: Remove from header
class RenderTarget;
// class GameObject;
class OrthoCamera;
class RenderCore : public BaseObject
{
private: struct tRComPair
{
std::vector<RenderCommand*> cmdList;
const RenderTarget* rTarg { nullptr };
inline tRComPair(void)
{
cmdList.reserve(100);
rTarg = nullptr;
}
inline void exec(void)
{
if (rTarg == nullptr || cmdList.size() == 0) return;
Renderer2D::setRenderTarget(*rTarg);
uint8_t err = tRenderCommandErrors::NoError;
for (auto& cmd : cmdList)
{
if ((err = cmd->execute()) != tRenderCommandErrors::NoError)
OX_WARN("RenderCommand Error: RenderTarget=%d Command=%d; Result=%d", rTarg->getResourceID(), cmd->getCommandID(), err);
}
// cmdList.clear();
}
};
public:
static void display(void);
// static void newFrame(void);
static void initRenderQUeue(void);
RenderCore(void);
void init(void);
void setRenderTarget(const RenderTarget& target, bool follow_camera = true);
void setDefaultRenderTarget(void);
void bindShader(ResourceID shader);
void clear(Color clearColor);
void updateUniform_f(String uniform_name, float value);
void updateUniform_i(String uniform_name, int32_t value);
void updateUniform_b(String uniform_name, bool value);
void updateUniform_vec2f(String uniform_name, const Vec2& value);
void updateUniform_vec3f(String uniform_name, const Vec3& value);
void updateUniform_vec4f(String uniform_name, const Vec4& value);
void updateUniform_col(String uniform_name, const Color& value);
void updateUniform_mat4f(String uniform_name, const glm::mat4& value);
void updateUniform_arri(String uniform_name, const std::vector<int32_t>& value);
void updateUniform_arrf(String uniform_name, const std::vector<float>& value);
// void drawGameObject(GameObject& obj);
void drawImage(TextureID texture, Vec2 position, Vec2 size, bool centereOrigin = false);
void drawImage(ResourceID texture, Vec2 position, Vec2 size, bool centereOrigin = false);
void drawImage(TextureID texture, Vec2 position, Vec2 size, Color tint, bool centereOrigin = false);
void drawImage(ResourceID texture, Vec2 position, Vec2 size, Color tint, bool centereOrigin = false);
void drawImage(TextureID texture, Color tint, Transform2D& transform);
void drawImage(ResourceID texture, Color tint, Transform2D& transform);
void drawImage(TextureID texture, Transform2D& transform);
void drawImage(ResourceID texture, Transform2D& transform);
void drawRenderTarget(const RenderTarget& target);
void drawRenderTarget(const RenderTarget& target, Vec2 position, Vec2 size);
void drawRenderTarget(const RenderTarget& target, Vec2 position, Vec2 size, Color tint);
void drawRenderTarget(const RenderTarget& target, Transform2D& transform);
void drawRenderTarget(const RenderTarget& target, Color tint, Transform2D& transform);
void drawQuad(Vec2 position, Vec2 size, Color color);
void drawQuad(Vec2 position, Vec2 size, Color color, bool centeredOrigin);
void drawQuad(Color color, Transform2D& transform);
void drawQuad(const std::vector<Vec2>& vertices, const Color& tintColor, TextureID texture);
void drawLine(const Vec2& start, const Vec2& end, float thikness, const Color& color);
void drawText(const String& text, Vec2 position);
void drawText(const String& text, Vec2 position, float fontSize);
void drawText(const String& text, Vec2 position, Color color);
void drawText(const String& text, Vec2 position, float fontSize, Color color);
void drawText(const String& text, Vec2 position, ResourceID font, float fontSize);
void drawText(const String& text, Vec2 position, ResourceID font, Color color);
void drawText(const String& text, Vec2 position, ResourceID font, float fontSize, Color color);
void drawText(const String& text, Vec2 position, const Renderer2D::tTextInfo& params);
void setTextParameters(const Renderer2D::tTextInfo& params);
inline void setFontSize(float size) { m_textHeight = size; }
inline void setTextSpacing(float spacing) { m_textSpacing = spacing; }
inline void setFont(ResourceID font) { m_textFont = font; }
inline void setFont(ResourceID font, float size) { m_textFont = font; m_textHeight = size; }
inline void setFont(ResourceID font, float size, float spacing) { m_textFont = font; m_textHeight = size; m_textSpacing = spacing; }
inline void setFontColor(Color color) { m_textColor = color; }
inline float getFontSize(void) { return m_textHeight; }
inline float getTextSpacing(void) { return m_textSpacing; }
inline ResourceID getFont(void) { return m_textFont; }
inline Color getTextColor(void) { return m_textColor; }
inline ResourceID getCurrentShaderID(void) { return m_currentShader; }
inline uint32_t getCurrentRenderTarget(void) { return m_currentRenderTarget; }
inline void setRenderTarget(uint32_t rt) { if (rt < RenderCore::s_renderQueue.size()) m_currentRenderTarget = rt; }
inline void setCamera(OrthoCamera& camera) { m_camera = &camera; }
inline static void resetRenderCmdCount(void) { m_renderCmdCount = 0; }
inline static uint32_t getRenderCmdCount(void) { return m_renderCmdCount; }
bool hasValidCamera(void);
OrthoCamera& getCamera(void);
private:
void __store_text_parameters(void);
void __restore_text_parameters(void);
private:
float m_textHeight { 32.0f };
float m_textSpacing { 5.0f };
ResourceID m_textFont { 0 };
Color m_textColor { 255, 255, 255 };
float m_textHeight_stored { 32.0f };
float m_textSpacing_stored { 5.0f };
ResourceID m_textFont_stored { 0 };
Color m_textColor_stored { 255, 255, 255 };
inline static std::vector<tRComPair> s_renderQueue;
uint32_t m_currentRenderTarget { 0 };
ResourceID m_currentShader { 0 };
inline static uint32_t m_renderCmdCount { 0 };
OrthoCamera* m_camera { nullptr };
};
}
#endif

87
src/ogfx/RenderTarget.cpp Executable file
View file

@ -0,0 +1,87 @@
#include "RenderTarget.hpp"
#include "GLBuffers.hpp"
#include "Errors.hpp"
#include "ResourceManager.hpp"
#include "Signals.hpp"
namespace ogfx
{
using namespace ostd;
RenderTarget::~RenderTarget(void)
{
destroy();
}
void RenderTarget::destroy(void)
{
uint32_t id = getOpenGLFrameBufferID();
GLCall(glDeleteRenderbuffers(1, &m_rbo_gl_id));
GLCall(glDeleteFramebuffers(1, &id));
ResourceManager::destroyResource(m_texture, tResourceType::Texture);
setID(id);
invalidate();
}
RenderTarget& RenderTarget::create(int32_t width, int32_t height, bool soft)
{
m_texture = ResourceManager::newTexture(width, height);
m_width = width;
m_height = height;
uint32_t gl_id;
GLCall(glGenFramebuffers(1, &gl_id));
setID(gl_id);
bind();
GLCall(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ResourceManager::getTexture(m_texture).getOpenGLID(), 0));
GLCall(glGenRenderbuffers(1, &m_rbo_gl_id));
GLCall(glBindRenderbuffer(GL_RENDERBUFFER, m_rbo_gl_id));
GLCall(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, m_width, m_height));
GLCall(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_rbo_gl_id));
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
ErrorHandler::pushError(RenderTarget::ERR_FAILED_TO_CREATE_FRAMEBUFFER);
String err_str = ErrorHandler::getLastErrorString();
OX_ERROR("%s", err_str.c_str());
unbind();
destroy();
return *this;
}
unbind();
enableSignals();
if (!soft)
connectSignal(tBuiltinSignals::WindowResized);
setTypeName("ogfx::RenderTarget");
validate();
return *this;
}
void RenderTarget::bind(void) const
{
glBindFramebuffer(GL_FRAMEBUFFER, getOpenGLFrameBufferID());
}
void RenderTarget::unbind(void) const
{
GLCall(glBindFramebuffer(GL_FRAMEBUFFER, 0));
}
void RenderTarget::bindScreenTexture(void) const
{
ResourceManager::getTexture(m_texture).bind();
}
void RenderTarget::handleSignal(tSignal& signal)
{
if (signal.ID == tBuiltinSignals::WindowResized)
{
WindowSizeObj wsobj = static_cast<WindowSizeObj&>(signal.userData);
unbind();
destroy();
create(wsobj.width, wsobj.height, true);
}
}
}

46
src/ogfx/RenderTarget.hpp Executable file
View file

@ -0,0 +1,46 @@
#ifndef __RENDER_TARGET_HPP__
#define __RENDER_TARGET_HPP__
#include <ostd/BaseObject.hpp>
#include <ostd/Geometry.hpp>
#include <ostd/Types.hpp>
#include <ostd/Defines.hpp>
namespace ogfx
{
class RenderTarget : public ostd::BaseObject
{
public:
inline RenderTarget(void) { invalidate(); }
inline RenderTarget(int32_t width, int32_t height) { create(width, height); }
virtual ~RenderTarget(void);
void destroy(void);
RenderTarget& create(int32_t width, int32_t height, bool soft = false);
inline uint32_t getOpenGLFrameBufferID(void) const { return static_cast<uint32_t>(getID()); }
inline uint32_t getOpenGLRenderBufferID(void) const { return m_rbo_gl_id; }
inline ostd::ResourceID getResourceID(void) const { return m_texture; }
void bind(void) const;
void unbind(void) const;
void bindScreenTexture(void) const;
void handleSignal(ostd::tSignal& signal) override;
inline ostd::Vec2 getSize(void) const { return { (float)m_width, (float)m_height }; }
private:
ostd::ResourceID m_texture;
uint32_t m_rbo_gl_id;
int32_t m_width;
int32_t m_height;
bool m_signalConnected { false };
public:
inline static constexpr int32_t ERR_FAILED_TO_CREATE_FRAMEBUFFER = OX_RENDERTARGET_ERR_MASK + 0x0001;
};
typedef RenderTarget RenderTexture;
}
#endif

570
src/ogfx/Renderer2D.cpp Executable file
View file

@ -0,0 +1,570 @@
#include "Renderer2D.hpp"
#include "GLBuffers.hpp"
#include "Shader.hpp"
#include "Errors.hpp"
#include "DataStructures.hpp"
#include "RenderTarget.hpp"
#include <ostd/Logger.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <ostd/Signals.hpp>
//#include <omniax/runtime/RTData.hpp>
#include <cstring>
namespace ogfx
{
using namespace ostd;
void Renderer2D::Text::init(void)
{
Text::font = ResourceManager::getDefaultBitmapFont();
}
void Renderer2D::Text::draw(const String& text, const Vec2& position, const Color& color)
{
if (ResourceManager::getBitmapFont(Renderer2D::Text::font).isInvalid())
{
ErrorHandler::pushError(Renderer2D::Text::ERR_INVALID_BITMAPFONT);
String err_str = ErrorHandler::getLastErrorString();
OX_ERROR("Renderer2D::Text::draw(const String&, const Vec2&, const Color&): %s", err_str.c_str());
return;
}
Renderer2D::drawText(text, Renderer2D::Text::font, position, color, Renderer2D::Text::characterHeight, Renderer2D::Text::characterSpacing);
}
void Renderer2D::Text::draw(const String& text, const Vec2& position, const tTextInfo& info)
{
tTextInfo oldInfo { Renderer2D::Text::characterHeight,
Renderer2D::Text::characterSpacing,
Renderer2D::Text::font,
{ 0, 0, 0, 0 } };
Renderer2D::Text::characterHeight = info.characterHeight;
Renderer2D::Text::characterSpacing = info.characterSpacing;
Renderer2D::Text::font = info.font;
draw(text, position, info.color);
Renderer2D::Text::characterHeight = oldInfo.characterHeight;
Renderer2D::Text::characterSpacing = oldInfo.characterSpacing;
Renderer2D::Text::font = oldInfo.font;
}
void Renderer2D::Text::drawCentered(const String& text, const Vec2& position, const Color& color)
{
auto size = Renderer2D::Text::getStringBounds(text);
Vec2 pos = position - (size / 2.0f);
Renderer2D::Text::draw(text, pos, color);
}
void Renderer2D::Text::drawCentered(const String& text, const Vec2& position, const tTextInfo& info)
{
tTextInfo oldInfo { Renderer2D::Text::characterHeight,
Renderer2D::Text::characterSpacing,
Renderer2D::Text::font,
{ 0, 0, 0, 0 } };
Renderer2D::Text::characterHeight = info.characterHeight;
Renderer2D::Text::characterSpacing = info.characterSpacing;
Renderer2D::Text::font = info.font;
drawCentered(text, position, info.color);
Renderer2D::Text::characterHeight = oldInfo.characterHeight;
Renderer2D::Text::characterSpacing = oldInfo.characterSpacing;
Renderer2D::Text::font = oldInfo.font;
}
Vec2 Renderer2D::Text::getStringBounds(const String& text, Vec2 padding, float characterHeight, float spacing)
{
auto& _font = ResourceManager::getBitmapFont(Renderer2D::Text::font);
if (_font.isInvalid())
{
ErrorHandler::pushError(Renderer2D::Text::ERR_INVALID_BITMAPFONT);
String err_str = ErrorHandler::getLastErrorString();
OX_ERROR("ogfx::Renderer2D::Text::getStringBounds(const String&, const Vec2&, float, float): %s", err_str.c_str());
return { 0.0f, 0.0f };
}
if (characterHeight == 0.0f) characterHeight = Renderer2D::Text::characterHeight;
if (spacing == 0.0f) spacing = characterSpacing;
const float baseCharHeight = _font.getBaseCharHeight();
float scale = characterHeight / baseCharHeight;
Vec2 bounds;
Rectangle cbounds;
if (spacing < 0) spacing = 0;
for (auto& c : text)
{
_font.getChar(c, cbounds);
bounds.x += (cbounds.w * scale) + (spacing * scale);
float ny = cbounds.h * scale;
if (ny > bounds.y) bounds.y = ny;
}
bounds += (padding * 2);
return bounds;
}
// Vec2 Renderer2D::Text::getStringBounds(const String& text, Vec2 padding, float characterHeight, float spacing)
// {
// auto& _font = ResourceManager::getBitmapFont(Renderer2D::Text::font);
// if (_font.isInvalid())
// {
// ErrorHandler::pushError(Renderer2D::Text::ERR_INVALID_BITMAPFONT);
// String err_str = ErrorHandler::getLastErrorString();
// OX_ERROR("ogfx::Renderer2D::Text::getStringBounds(const String&, const Vec2&, float, float): %s", err_str.c_str());
// return { 0.0f, 0.0f };
// }
// if (characterHeight == 0.0f) characterHeight = Renderer2D::Text::characterHeight;
// if (spacing == 0.0f) spacing = characterSpacing;
// const float baseCharHeight = _font.getBaseCharHeight();
// float scale = characterHeight / baseCharHeight;
// Vec2 bounds;
// Rectangle cbounds;
// for (auto& c : text)
// {
// _font.getChar(c, cbounds);
// bounds.x += cbounds.w + spacing;
// }
// bounds.x *= scale;
// bounds.y *= scale;
// bounds += (padding * 2);
// std::cout << bounds << "\n";
// return bounds;
// }
static constexpr size_t MaxQuadCount = 16384;
static constexpr size_t MaxVertexCount = MaxQuadCount * 4;
static constexpr size_t MaxIndexCount = MaxQuadCount * 6;
static constexpr size_t MaxTextures = 16;
struct tRendererData
{
VertexArray vao { false };
VertexBuffer vbo;
ElementBuffer ebo;
uint32_t whiteTexture { 0 };
int32_t whiteTextureSlot { 0 };
uint32_t indexCount { 0 };
tVertex2D* buffer { nullptr };
tVertex2D* bufferPtr { nullptr };
uint32_t texSlots[MaxTextures];
uint32_t texSlotIndex { 1 };
Texture* currentTex { nullptr };
ResourceID currentTexResID { ResourceManager::InvalidResource };
float currentTexIndex { 0.0f };
Shader* currentShader { nullptr };
ResourceID currentShaderResID { ResourceManager::InvalidResource };
Renderer2D::tRenderStats renderStats;
const RenderTarget* currentRenderTarget { nullptr };
};
static tRendererData s_rendererData;
void Renderer2D::init(void)
{
s_rendererData.buffer = new tVertex2D[MaxVertexCount];
s_rendererData.vao.create();
s_rendererData.vao.bind();
s_rendererData.vbo.create(nullptr, MaxVertexCount * sizeof(tVertex2D), true);
s_rendererData.vao.addBuffer(s_rendererData.vbo, tVertex2D::getVertexBufferLayout());
int32_t indices[MaxIndexCount];
uint32_t offset = 0;
for (size_t i = 0; i < MaxIndexCount; i += 6)
{
indices[i + 0] = 0 + offset;
indices[i + 1] = 1 + offset;
indices[i + 2] = 2 + offset;
indices[i + 3] = 2 + offset;
indices[i + 4] = 3 + offset;
indices[i + 5] = 0 + offset;
offset += 4;
}
s_rendererData.ebo.create(indices, MaxIndexCount);
s_rendererData.vao.setElementBuffer(s_rendererData.ebo);
GLCall(glGenTextures(1, &s_rendererData.whiteTexture));
GLCall(glBindTexture(GL_TEXTURE_2D, s_rendererData.whiteTexture));
GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
uint32_t color = 0xffffffff;
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &color);
s_rendererData.texSlots[0] = s_rendererData.whiteTexture;
for (size_t i = 1; i < MaxTextures; i++)
s_rendererData.texSlots[i] = 0;
s_rendererData.currentTex = nullptr;
s_rendererData.currentTexResID = ResourceManager::InvalidResource;
s_rendererData.currentTexIndex = 0.0f;
s_rendererData.currentShaderResID = ResourceManager::InvalidResource;
s_rendererData.currentShader = nullptr;
s_rendererData.currentRenderTarget = nullptr;
}
void Renderer2D::shutdown(void)
{
GLCall(glDeleteTextures(1, &s_rendererData.whiteTexture));
//delete[] s_rendererData.buffer; //TODO: Fix memory leak (had a crash here, that's why it's currently disabled)
}
void Renderer2D::beginBatch(void)
{
s_rendererData.bufferPtr = s_rendererData.buffer;
}
void Renderer2D::endBatch(void)
{
GLsizeiptr size = (uint8_t*)s_rendererData.bufferPtr - (uint8_t*)s_rendererData.buffer;
s_rendererData.vbo.bind();
GLCall(glBufferSubData(GL_ARRAY_BUFFER, 0, size, s_rendererData.buffer));
}
void Renderer2D::flush(void)
{
for (uint32_t i = 0; i < s_rendererData.texSlotIndex; i++)
{
GLCall(glActiveTexture(GL_TEXTURE0 + i));
GLCall(glBindTexture(GL_TEXTURE_2D, s_rendererData.texSlots[i]));
}
s_rendererData.vao.bind();
GLCall(glDrawElements(GL_TRIANGLES, s_rendererData.indexCount, GL_UNSIGNED_INT, nullptr));
s_rendererData.renderStats.drawCalls++;
s_rendererData.indexCount = 0;
s_rendererData.texSlotIndex = 1;
}
const Renderer2D::tRenderStats& Renderer2D::getRenderStats(void)
{
return s_rendererData.renderStats;
}
void Renderer2D::resetStats(void)
{
memset(&s_rendererData.renderStats, 0, sizeof(Renderer2D::tRenderStats));
}
void Renderer2D::drawQuad(const Transform2D& transform, const Color& color)
{
Renderer2D::drawQuad(transform.getVertices(), color);
}
void Renderer2D::drawQuad(const Transform2D& transform, ResourceID texture, TextureAtlasIndex tile_index, const Color& tint)
{
Renderer2D::drawQuad(transform.getVertices(), tint, texture, tile_index);
}
void Renderer2D::drawQuad(const std::vector<Vec2>& vertices, const Color& tintColor, ResourceID texture, TextureAtlasIndex tile_index)
{
if (vertices.size() != 4) return;
if (s_rendererData.indexCount >= MaxIndexCount)
{
Renderer2D::endBatch();
Renderer2D::flush();
Renderer2D::beginBatch();
}
float z_val = 0.0f;
float texIndex = 0.0f;
auto texCoords = Texture::tTexCoords { { 0.0f, 0.0f }, { 0.0f, 0.0f }, { 0.0f, 0.0f }, { 0.0f, 0.0f } };
if (texture != ResourceManager::InvalidResource)
{
if (s_rendererData.texSlotIndex >= MaxTextures)
{
Renderer2D::endBatch();
Renderer2D::flush();
Renderer2D::beginBatch();
}
if (s_rendererData.currentTexResID != texture || s_rendererData.currentTex == nullptr || s_rendererData.currentTexResID == ResourceManager::InvalidResource)
{
s_rendererData.currentTex = &(ResourceManager::getTexture(texture));
if (s_rendererData.currentTex->isInvalid())
{
ErrorHandler::pushError(Renderer2D::ERR_INVALID_TEXTURE);
String err_str = ErrorHandler::getLastErrorString();
OX_ERROR("ogfx::Renderer2D::drawQuad(const std::vector<Vec2>&, const Color&, ResourceID, TextureAtlasIndex): %s", err_str.c_str());
return;
}
s_rendererData.currentTexResID = texture;
s_rendererData.currentTexIndex = 0.0f;
for (uint32_t i = 1; i < s_rendererData.texSlotIndex; i++)
{
if (s_rendererData.texSlots[i] == s_rendererData.currentTex->getOpenGLID())
{
s_rendererData.currentTexIndex = (float)i;
break;
}
}
if (s_rendererData.currentTexIndex == 0.0f)
{
s_rendererData.currentTexIndex = (float)s_rendererData.texSlotIndex;
s_rendererData.texSlots[s_rendererData.texSlotIndex] = s_rendererData.currentTex->getOpenGLID();
s_rendererData.texSlotIndex++;
}
}
texCoords = s_rendererData.currentTex->getTile(tile_index);
texIndex = s_rendererData.currentTexIndex;
}
s_rendererData.bufferPtr->color = tintColor.getNormalizedColor();
s_rendererData.bufferPtr->texCoords = texCoords.topLeft;
s_rendererData.bufferPtr->texIndex = texIndex;
s_rendererData.bufferPtr->position = { vertices[0], z_val };
s_rendererData.bufferPtr++;
s_rendererData.bufferPtr->color = tintColor.getNormalizedColor();
s_rendererData.bufferPtr->texCoords = texCoords.topRight;
s_rendererData.bufferPtr->texIndex = texIndex;
s_rendererData.bufferPtr->position = { vertices[1], z_val };
s_rendererData.bufferPtr++;
s_rendererData.bufferPtr->color = tintColor.getNormalizedColor();
s_rendererData.bufferPtr->texCoords = texCoords.bottomRight;
s_rendererData.bufferPtr->texIndex = texIndex;
s_rendererData.bufferPtr->position = { vertices[2], z_val };
s_rendererData.bufferPtr++;
s_rendererData.bufferPtr->color = tintColor.getNormalizedColor();
s_rendererData.bufferPtr->texCoords = texCoords.bottomLeft;
s_rendererData.bufferPtr->texIndex = texIndex;
s_rendererData.bufferPtr->position = { vertices[3], z_val };
s_rendererData.bufferPtr++;
s_rendererData.indexCount += 6;
s_rendererData.renderStats.quadCount++;
}
void Renderer2D::drawLine(const Vec2& start, const Vec2& end, float thickness, const Color& color)
{
if (s_rendererData.indexCount >= MaxIndexCount)
{
Renderer2D::endBatch();
Renderer2D::flush();
Renderer2D::beginBatch();
}
float texIndex = 0.0f;
float z_val = 0.0f;
Vec2 unitDirection = (start - end).normalize();
Vec2 unitPerpendicular(-unitDirection.y, unitDirection.x);
Vec2 offset = unitPerpendicular * (thickness / 2.f);
s_rendererData.bufferPtr->color = color.getNormalizedColor();
s_rendererData.bufferPtr->texCoords = { 0.0f, 1.0f };
s_rendererData.bufferPtr->texIndex = texIndex;
s_rendererData.bufferPtr->position = { start + offset, z_val };
s_rendererData.bufferPtr++;
s_rendererData.bufferPtr->color = color.getNormalizedColor();
s_rendererData.bufferPtr->texCoords = { 1.0f, 1.0f };
s_rendererData.bufferPtr->texIndex = texIndex;
s_rendererData.bufferPtr->position = { end + offset, z_val };
s_rendererData.bufferPtr++;
s_rendererData.bufferPtr->color = color.getNormalizedColor();
s_rendererData.bufferPtr->texCoords = { 1.0f, 0.0f };
s_rendererData.bufferPtr->texIndex = texIndex;
s_rendererData.bufferPtr->position = { end - offset, z_val };
s_rendererData.bufferPtr++;
s_rendererData.bufferPtr->color = color.getNormalizedColor();
s_rendererData.bufferPtr->texCoords = { 0.0f, 0.0f };
s_rendererData.bufferPtr->texIndex = texIndex;
s_rendererData.bufferPtr->position = { start - offset, z_val };
s_rendererData.bufferPtr++;
s_rendererData.indexCount += 6;
s_rendererData.renderStats.quadCount++;
}
void Renderer2D::drawTriangle(const Triangle& triangle, const Color& color)
{
if (s_rendererData.indexCount >= MaxIndexCount)
{
Renderer2D::endBatch();
Renderer2D::flush();
Renderer2D::beginBatch();
}
float texIndex = 0.0f;
float z_val = 0.0f;
s_rendererData.bufferPtr->color = color.getNormalizedColor();
s_rendererData.bufferPtr->texCoords = { 0.0f, 1.0f };
s_rendererData.bufferPtr->texIndex = texIndex;
s_rendererData.bufferPtr->position = { triangle.vA, z_val };
s_rendererData.bufferPtr++;
s_rendererData.bufferPtr->color = color.getNormalizedColor();
s_rendererData.bufferPtr->texCoords = { 1.0f, 1.0f };
s_rendererData.bufferPtr->texIndex = texIndex;
s_rendererData.bufferPtr->position = { triangle.vB, z_val };
s_rendererData.bufferPtr++;
s_rendererData.bufferPtr->color = color.getNormalizedColor();
s_rendererData.bufferPtr->texCoords = { 1.0f, 0.0f };
s_rendererData.bufferPtr->texIndex = texIndex;
s_rendererData.bufferPtr->position = { triangle.vC, z_val };
s_rendererData.bufferPtr++;
s_rendererData.bufferPtr->color = color.getNormalizedColor();
s_rendererData.bufferPtr->texCoords = { 0.0f, 0.0f };
s_rendererData.bufferPtr->texIndex = texIndex;
s_rendererData.bufferPtr->position = { triangle.vC, z_val };
s_rendererData.bufferPtr++;
s_rendererData.indexCount += 6;
s_rendererData.renderStats.quadCount++;
}
Shader& Renderer2D::bindShader(ResourceID shader)
{
if (shader != s_rendererData.currentShaderResID || s_rendererData.currentShader == nullptr || s_rendererData.currentShaderResID == ResourceManager::InvalidResource)
{
s_rendererData.currentShader = &(ResourceManager::getShader(shader));
if (s_rendererData.currentShader->isInvalid())
{
ErrorHandler::pushError(Renderer2D::ERR_INVALID_SHADER);
String err_str = ErrorHandler::getLastErrorString();
OX_ERROR("ogfx::Renderer2D::bindShader(...): %s", err_str.c_str());
return (Shader&)BaseObject::InvalidRef();
}
s_rendererData.currentShaderResID = shader;
if (s_rendererData.indexCount > 0)
{
Renderer2D::endBatch();
Renderer2D::flush();
}
s_rendererData.currentShader->bind();
s_rendererData.renderStats.shaderBinds++;
Renderer2D::beginBatch();
return *s_rendererData.currentShader;
}
return *s_rendererData.currentShader;
}
void Renderer2D::drawSingle(const VertexArray& vao, const Shader& shader)
{
shader.bind();
vao.bind();
GLCall(glDrawElements(GL_TRIANGLES, vao.getElementCount(), GL_UNSIGNED_INT, 0));
}
void Renderer2D::drawText(const String& text, ResourceID font, Vec2 position, Color color, float charHeight, float spacing)
{
auto& _font = ResourceManager::getBitmapFont(font);
const float baseCharHeight = _font.getBaseCharHeight();
float scale = charHeight / baseCharHeight;
float nextCharX = position.x;
spacing *= scale;
for (uint8_t i = 0; i < text.length(); i++)
{
Rectangle bounds;
TextureAtlasIndex tile = _font.getChar(text[i], bounds);
bounds.mulSize(scale, scale);
bounds.mulPos(scale, scale);
Renderer2D::drawQuad(Renderer2D::getStaticQuad({ nextCharX, position.y + bounds.y }, bounds.getSize(), false), color, _font.getTexture(), tile);
nextCharX += bounds.w + spacing;
}
}
void Renderer2D::clear(const Color& color, uint32_t gl_mask)
{
const auto fcol = color.getNormalizedColor();
glClearColor(fcol.r, fcol.g, fcol.b, fcol.a);
glClear(gl_mask);
}
void Renderer2D::setRenderTarget(const RenderTarget& target)
{
if (target.isInvalid())
{
if (s_rendererData.currentRenderTarget != nullptr)
setDefaultRenderTarget();
return;
}
s_rendererData.currentRenderTarget = &target;
if (s_rendererData.indexCount > 0)
{
Renderer2D::endBatch();
Renderer2D::flush();
}
Renderer2D::beginBatch();
s_rendererData.currentRenderTarget->bind();
glViewport(0, 0, s_rendererData.currentRenderTarget->getSize().x, s_rendererData.currentRenderTarget->getSize().y);
s_rendererData.renderStats.renderBufferBinds++;
//Renderer2D::beginBatch();
}
void Renderer2D::setDefaultRenderTarget(void)
{
if (s_rendererData.indexCount > 0)
{
Renderer2D::endBatch();
Renderer2D::flush();
}
Renderer2D::beginBatch();
s_rendererData.currentRenderTarget = nullptr;
GLCall(glBindFramebuffer(GL_FRAMEBUFFER, 0));
//TODO: Fix
//glViewport(0, 0, (float)RTData::windowSize.x, (float)RTData::windowSize.y);
s_rendererData.renderStats.renderBufferBinds++;
//Renderer2D::beginBatch();
}
void Renderer2D::enableDepthTest(bool enable)
{
if (enable) glEnable(GL_DEPTH_TEST);
else glDisable(GL_DEPTH_TEST);
}
const RenderTarget& Renderer2D::getCurrentRenderTarget(void)
{
if (s_rendererData.currentRenderTarget == nullptr)
return (const RenderTarget&)BaseObject::InvalidRef();
return *s_rendererData.currentRenderTarget;
}
const Shader& Renderer2D::getCurrentShader(void)
{
if (s_rendererData.currentShader == nullptr)
return (const Shader&)BaseObject::InvalidRef();
return *s_rendererData.currentShader;
}
ResourceID Renderer2D::getCurrentShaderID(void)
{
return s_rendererData.currentShaderResID;
}
std::vector<Vec2> Renderer2D::getStaticQuad(Vec2 position, Vec2 size, bool centered)
{
std::vector<Vec2> vertices;
if (centered)
{
Vec2 s = (size / 2.0f);
vertices.push_back({ position.x - s.x, position.y - s.y });
vertices.push_back({ position.x + s.x, position.y - s.y });
vertices.push_back({ position.x + s.x, position.y + s.y });
vertices.push_back({ position.x - s.x, position.y + s.y });
}
else
{
vertices.push_back({ position.x, position.y });
vertices.push_back({ position.x + size.x, position.y });
vertices.push_back({ position.x + size.x, position.y + size.y });
vertices.push_back({ position.x, position.y + size.y });
}
return vertices;
}
}

96
src/ogfx/Renderer2D.hpp Executable file
View file

@ -0,0 +1,96 @@
#ifndef __RENDERER_2D_HPP__
#define __RENDERER_2D_HPP__
#include <ostd/Geometry.hpp>
#include <ostd/Color.hpp>
#include <ogfx/Texture.hpp>
#include <ogfx/DataStructures.hpp>
#include <ogfx/ResourceManager.hpp>
namespace ogfx
{
using namespace ostd; //TODO: Remove from header
class VertexArray;
class Shader;
class RenderTarget;
class Renderer2D
{
public: struct tRenderStats
{
uint32_t drawCalls { 0 };
uint32_t quadCount { 0 };
uint32_t renderBufferBinds { 0 };
uint32_t shaderBinds { 0 };
};
public: struct tTextInfo
{
float characterHeight { 32.0f };
float characterSpacing { 5.0f };
ResourceID font { ResourceManager::InvalidResource };
Color color { 255, 255, 255 };
};
public: class Text
{
public:
static void init(void);
static void draw(const String& text, const Vec2& position, const Color& color);
static void draw(const String& text, const Vec2& position, const tTextInfo& info);
static void drawCentered(const String& text, const Vec2& position, const Color& color);
static void drawCentered(const String& text, const Vec2& position, const tTextInfo& info);
static Vec2 getStringBounds(const String& text, Vec2 padding = { 0.0f, 0.0f }, float characterHeight = 0.0f, float spacing = 0.0f);
inline static void setFont(ResourceID _font) { font = _font; }
public:
inline static ResourceID font { ResourceManager::InvalidResource };
inline static float characterHeight { 32.0f };
inline static float characterSpacing { 5.0f };
public:
inline static constexpr int32_t ERR_INVALID_BITMAPFONT = OX_RENDERER2D_TEXT_ERR_MASK + 0x0001;
};
public:
static void init(void);
static void shutdown(void);
static void beginBatch(void);
static void endBatch(void);
static void flush(void);
static const tRenderStats& getRenderStats(void);
static void resetStats(void);
static void drawQuad(const Transform2D& transform, const Color& color);
static void drawQuad(const Transform2D& transform, ResourceID texture, TextureAtlasIndex tile_index = Texture::FullTextureCoords, const Color& tint = { 255, 255, 255 });
static void drawQuad(const std::vector<Vec2>& vertices, const Color& tintColor, ResourceID texture = ResourceManager::InvalidResource, TextureAtlasIndex tile_index = Texture::FullTextureCoords);
static void drawLine(const Vec2& start, const Vec2& end, float thickness, const Color& color);
static void drawTriangle(const Triangle& triangle, const Color& color);
static void drawSingle(const VertexArray& vao, const Shader& shader);
static void drawText(const String& text, ResourceID font, Vec2 position, Color color, float charHeight, float spacing = 5.0f);
static Shader& bindShader(ResourceID shader);
static void clear(const Color& color, uint32_t gl_mask = GL_COLOR_BUFFER_BIT);
static void setRenderTarget(const RenderTarget& target);
static void setDefaultRenderTarget(void);
static void enableDepthTest(bool enable = true);
static const RenderTarget& getCurrentRenderTarget(void);
static const Shader& getCurrentShader(void);
static ResourceID getCurrentShaderID(void);
inline static const RenderTarget& getDefaultRenderTarget(void) { return (const RenderTarget&)BaseObject::InvalidRef(); }
static std::vector<Vec2> getStaticQuad(Vec2 position, Vec2 size, bool centered = true);
public:
inline static constexpr int32_t ERR_INVALID_TEXTURE = OX_RENDERER2D_ERR_MASK + 0x0001;
inline static constexpr int32_t ERR_INVALID_SHADER = OX_RENDERER2D_ERR_MASK + 0x0002;
};
typedef RenderTarget RenderTexture;
}
#endif

268
src/ogfx/ResourceManager.cpp Executable file
View file

@ -0,0 +1,268 @@
#include "ResourceManager.hpp"
#include <ogfx/static_resources/default_shaders.hpp>
#include <ogfx/static_resources/default_bitmap_font.hpp>
#include <ogfx/static_resources/default_light_texture.hpp>
#include <ogfx/static_resources/StateGradient.hpp>
#include <ogfx/static_resources/BasicShadowTexture.hpp>
#include <Logger.hpp>
namespace ogfx
{
using namespace ostd;
void ResourceManager::init(void)
{
ResourceManager::s_defaultShader = ResourceManager::newShader(oxres::defaultShader_vert, oxres::defaultShader_frag);
ResourceManager::s_defaultBlendShader = ResourceManager::newShader(oxres::defaultBlendShader_vert, oxres::defaultBlendShader_frag);
ResourceManager::s_defaultBitmapFont = ResourceManager::loadBitmapFont(oxres::default_bitmap_font.data, oxres::default_bitmap_font.size);
ResourceManager::s_defaultBitmapFontMono = ResourceManager::loadBitmapFont(oxres::default_bitmap_font.data, oxres::default_bitmap_font.size, true);
int32_t samplers[16];
for (uint8_t i = 0; i < 16; i++)
samplers[i] = i;
auto& defShad = ResourceManager::getShader(ResourceManager::s_defaultShader);
defShad.bind();
defShad.updateUniform_arri("u_textures", 16, samplers);
auto& blendShad = ResourceManager::getShader(ResourceManager::s_defaultBlendShader);
blendShad.bind();
blendShad.updateUniform_arri("u_textures", 16, samplers);
blendShad.unbind();
ResourceManager::s_defaultLightTexture = ResourceManager::loadTexture(oxres::default_light_texture.data, oxres::default_light_texture.size);
ResourceManager::s_stateGradientTexture = ResourceManager::loadTexture(oxres::StateGradient.data, oxres::StateGradient.size, true);
ResourceManager::s_basicShadowTexture = ResourceManager::loadTexture(oxres::BasicShadowTexture.data, oxres::BasicShadowTexture.size, true);
}
ResourceID ResourceManager::loadShader(const String& vertex_file_path, const String& fragment_file_path)
{
auto id = (ResourceManager::s_ghostShader != 0 ? ResourceManager::s_ghostShader : ResourceManager::s_next_id++);
ResourceManager::s_shaders[id].createFromSeparateFiles(vertex_file_path, fragment_file_path);
if (ResourceManager::s_shaders[id].isInvalid())
{
ResourceManager::s_ghostShader = id;
OX_WARN("ox::ResourceManager::loadShader(const ox::String&, const ox::String&): Failed to load shader:\nVertex Shader path: %s\nFragment Shader path: %s", vertex_file_path.c_str(), fragment_file_path.c_str());
return ResourceManager::InvalidResource;
}
ResourceManager::s_ghostShader = 0;
return id;
}
ResourceID ResourceManager::loadShader(const String& shader_name, bool single_file, const String& shader_folder)
{
auto id = (ResourceManager::s_ghostShader != 0 ? ResourceManager::s_ghostShader : ResourceManager::s_next_id++);
ResourceManager::s_shaders[id].createFromName(shader_name, single_file, shader_folder);
if (ResourceManager::s_shaders[id].isInvalid())
{
ResourceManager::s_ghostShader = id;
OX_WARN("ox::ResourceManager::loadShader(const ox::String&, bool, const String&): Failed to load shader:\nShader name: %s\nShader folder: %s", shader_name.c_str(), shader_folder.c_str());
return ResourceManager::InvalidResource;
}
ResourceManager::s_ghostShader = 0;
return id;
}
ResourceID ResourceManager::newShader(const String& vertex_shader_source, const String& fragment_shader_source)
{
auto id = (ResourceManager::s_ghostShader != 0 ? ResourceManager::s_ghostShader : ResourceManager::s_next_id++);
ResourceManager::s_shaders[id].createFromSources(vertex_shader_source, fragment_shader_source);
if (ResourceManager::s_shaders[id].isInvalid())
{
ResourceManager::s_ghostShader = id;
OX_WARN("ox::ResourceManager::newShader(const ox::String&, const String&): Failed to create shader.");
return ResourceManager::InvalidResource;
}
ResourceManager::s_ghostShader = 0;
return id;
}
ResourceID ResourceManager::loadTexture(const String& filePath, bool store_data, int32_t min_filter_mode, int32_t mag_filter_mode, int32_t wrap_s_mode, int32_t wrap_t_mode)
{
auto id = (ResourceManager::s_ghostTexture != 0 ? ResourceManager::s_ghostTexture : ResourceManager::s_next_id++);
ResourceManager::s_textures[id].create(filePath, store_data, min_filter_mode, mag_filter_mode, wrap_s_mode, wrap_t_mode);
if (ResourceManager::s_textures[id].isInvalid())
{
ResourceManager::s_ghostTexture = id;
OX_WARN("ox::ResourceManager::loadTexture(const ox::String&, bool, int32_t, int32_t, int32_t, int32_t): Failed to load texture:\nTexture path: %s", filePath.c_str());
return ResourceManager::InvalidResource;
}
ResourceManager::s_ghostTexture = 0;
return id;
}
ResourceID ResourceManager::loadTexture(const unsigned char* data, uint32_t data_size, bool store_data, int32_t min_filter_mode, int32_t mag_filter_mode, int32_t wrap_s_mode, int32_t wrap_t_mode)
{
auto id = (ResourceManager::s_ghostTexture != 0 ? ResourceManager::s_ghostTexture : ResourceManager::s_next_id++);
ResourceManager::s_textures[id].create(data, data_size, store_data, min_filter_mode, mag_filter_mode, wrap_s_mode, wrap_t_mode);
if (ResourceManager::s_textures[id].isInvalid())
{
ResourceManager::s_ghostTexture = id;
OX_WARN("ox::ResourceManager::loadTexture(const unsigned char*, uint32_t, bool, int32_t, int32_t, int32_t, int32_t): Failed to load texture from memory.");
return ResourceManager::InvalidResource;
}
ResourceManager::s_ghostTexture = 0;
return id;
}
ResourceID ResourceManager::loadTexture(const unsigned char* rawData, uint32_t data_size, int32_t width, int32_t height, int32_t bpp, int32_t min_filter_mode, int32_t mag_filter_mode, int32_t wrap_s_mode, int32_t wrap_t_mode)
{
auto id = (ResourceManager::s_ghostTexture != 0 ? ResourceManager::s_ghostTexture : ResourceManager::s_next_id++);
ResourceManager::s_textures[id].createFromRawData(rawData, data_size, width, height, bpp, min_filter_mode, mag_filter_mode, wrap_s_mode, wrap_t_mode);
if (ResourceManager::s_textures[id].isInvalid())
{
ResourceManager::s_ghostTexture = id;
OX_WARN("ox::ResourceManager::loadTexture(const unsigned char*, uint32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t): Failed to load texture from memory.");
return ResourceManager::InvalidResource;
}
ResourceManager::s_ghostTexture = 0;
return id;
}
ResourceID ResourceManager::newTexture(int32_t width, int32_t height)
{
auto id = (ResourceManager::s_ghostTexture != 0 ? ResourceManager::s_ghostTexture : ResourceManager::s_next_id++);
ResourceManager::s_textures[id].create(width, height);
if (ResourceManager::s_textures[id].isInvalid())
{
ResourceManager::s_ghostTexture = id;
OX_WARN("ox::ResourceManager::newTexture(int32_t, int32_t): Failed to create texture.");
return ResourceManager::InvalidResource;
}
ResourceManager::s_ghostTexture = 0;
return id;
}
ResourceID ResourceManager::loadBitmapFont(const String& filePath, bool monospace)
{
auto id = (ResourceManager::s_ghostBitmapFont != 0 ? ResourceManager::s_ghostBitmapFont : ResourceManager::s_next_id++);
ResourceManager::s_bitmapFonts[id].create(filePath, monospace);
if (ResourceManager::s_bitmapFonts[id].isInvalid())
{
ResourceManager::s_ghostBitmapFont = id;
OX_WARN("ox::ResourceManager::loadBitmapFont(const String&): Failed to load bitmap font:\nFile path: %s", filePath.c_str());
return ResourceManager::InvalidResource;
}
ResourceManager::s_ghostBitmapFont = 0;
return id;
}
ResourceID ResourceManager::loadBitmapFont(const unsigned char* data, uint32_t data_size, bool monospace)
{
auto id = (ResourceManager::s_ghostBitmapFont != 0 ? ResourceManager::s_ghostBitmapFont : ResourceManager::s_next_id++);
auto ftex = loadTexture(data, data_size, true, GL_NEAREST, GL_NEAREST);
ResourceManager::s_bitmapFonts[id].create(ftex, monospace);
if (ResourceManager::s_bitmapFonts[id].isInvalid())
{
ResourceManager::s_ghostBitmapFont = id;
OX_WARN("ox::ResourceManager::loadBitmapFont(const unsigned char*, uint32_t): Failed to load bitmap font from memory.");
return ResourceManager::InvalidResource;
}
ResourceManager::s_ghostBitmapFont = 0;
return id;
}
// ResourceID ResourceManager::loadSound(const String& filePath)
// {
// auto id = (ResourceManager::s_ghostSoundBuffer != 0 ? ResourceManager::s_ghostSoundBuffer : ResourceManager::s_next_id++);
// ResourceManager::s_soundBuffers[id].create(filePath);
// if (ResourceManager::s_soundBuffers[id].isInvalid())
// {
// ResourceManager::s_ghostSoundBuffer = id;
// OX_WARN("ox::ResourceManager::loadSoundBuffer(const String&): Failed to load sound buffer:\nFile path: %s", filePath.c_str());
// return ResourceManager::InvalidResource;
// }
// ResourceManager::s_ghostSoundBuffer = 0;
// return id;
// }
// SoundInstance ResourceManager::newSoundInstance(ResourceID soundBuffer, float volume, bool loop)
// {
// auto& sbuff = ResourceManager::getSoundBuffer(soundBuffer);
// if (sbuff.isInvalid())
// {
// //TODO: Error
// return *((SoundInstance*)&BaseObject::InvalidRef());
// }
// SoundInstance sound(sbuff);
// if (sound.isInvalid())
// {
// //TODO: Error
// return *((SoundInstance*)&BaseObject::InvalidRef());
// }
// return sound.setVolume(volume).enableLoop(loop);
// }
bool ResourceManager::destroyResource(ResourceID resource, uint8_t res_type)
{
if (res_type == tResourceType::Texture)
{
auto it = ResourceManager::s_textures.find(resource);
if (it == ResourceManager::s_textures.end())
{
OX_WARN("ox::ResourceManager::destroyResource(...): Attempting to destroy an invalid texture.");
return false;
}
ResourceManager::s_textures.erase(it);
return true;
}
else if (res_type == tResourceType::Shader)
{
return false;
}
else if (res_type == tResourceType::BitmapFont)
{
return false;
}
else if (res_type == tResourceType::SoundBuffer)
{
return false;
}
else
{
OX_WARN("ox::ResourceManager::destroyResource(...): Invalid resource type.");
return false;
}
return false;
}
Shader& ResourceManager::getShader(ResourceID id)
{
if (ResourceManager::s_shaders.find(id) == ResourceManager::s_shaders.end())
{
OX_WARN("ox::ResourceManager::getShader(...): Attempting to retrieve an invalid shader.");
OX_DEBUG("SHADER_RES_ID: %d", id);
return (Shader&)BaseObject::InvalidRef();
}
return ResourceManager::s_shaders[id];
}
Texture& ResourceManager::getTexture(ResourceID id)
{
if (ResourceManager::s_textures.find(id) == ResourceManager::s_textures.end())
{
OX_WARN("ox::ResourceManager::getTexture(...): Attempting to retrieve an invalid texture.");
return (Texture&)BaseObject::InvalidRef();
}
return ResourceManager::s_textures[id];
}
BitmapFont& ResourceManager::getBitmapFont(ResourceID id)
{
if (ResourceManager::s_bitmapFonts.find(id) == ResourceManager::s_bitmapFonts.end())
{
OX_WARN("ox::ResourceManager::getBitmapFont(...): Attempting to retrieve an invalid bitmap font.");
OX_DEBUG("DEFAULT_BITMAP_FONT: %d", s_defaultBitmapFont);
OX_DEBUG("CURRENT_BITMAP_FONT: %d", id);
OX_DEBUG("TOTAL_BITMAP_FONTS: %d", s_bitmapFonts.size());
return (BitmapFont&)BaseObject::InvalidRef();
}
return ResourceManager::s_bitmapFonts[id];
}
// SoundBuffer& ResourceManager::getSoundBuffer(ResourceID id)
// {
// if (ResourceManager::s_soundBuffers.find(id) == ResourceManager::s_soundBuffers.end())
// {
// OX_WARN("ox::ResourceManager::getSoundBuffer(...): Attempting to retrieve an invalid sound buffer.");
// return (SoundBuffer&)BaseObject::InvalidRef();
// }
// return ResourceManager::s_soundBuffers[id];
// }
} // namespace ox

97
src/ogfx/ResourceManager.hpp Executable file
View file

@ -0,0 +1,97 @@
#ifndef __RESOURCE_MANAGER_HPP__
#define __RESOURCE_MANAGER_HPP__
#include <ostd/Types.hpp>
#include <unordered_map>
#include <ogfx/Shader.hpp>
//#include <Audio.hpp>
#include <ogfx/Texture.hpp>
#include <ogfx/BitmapFont.hpp>
namespace ogfx
{
using namespace ostd; //TODO: Remove from header
struct tResourceType
{
inline static constexpr uint8_t Invalid = 0;
inline static constexpr uint8_t Shader = 1;
inline static constexpr uint8_t Texture = 2;
inline static constexpr uint8_t BitmapFont = 3;
inline static constexpr uint8_t SoundBuffer = 4;
};
class ResourceManager
{
public:
static void init(void);
static ResourceID loadShader(const String& vertex_file_path, const String& fragment_file_path);
static ResourceID loadShader(const String& shader_name, bool single_file = true, const String& shader_folder = "");
static ResourceID newShader(const String& vertex_shader_source, const String& fragment_shader_source);
static ResourceID loadTexture(const String& filePath,
bool store_data = false,
int32_t min_filter_mode = GL_LINEAR,
int32_t mag_filter_mode = GL_LINEAR,
int32_t wrap_s_mode = GL_CLAMP_TO_EDGE,
int32_t wrap_t_mode = GL_CLAMP_TO_EDGE);
static ResourceID loadTexture(const unsigned char* data,
unsigned int data_size,
bool store_data = false,
int32_t min_filter_mode = GL_LINEAR,
int32_t mag_filter_mode = GL_LINEAR,
int32_t wrap_s_mode = GL_CLAMP_TO_EDGE,
int32_t wrap_t_mode = GL_CLAMP_TO_EDGE);
static ResourceID loadTexture(const unsigned char* rawData,
unsigned int data_size,
int32_t width,
int32_t height,
int32_t bpp = 4,
int32_t min_filter_mode = GL_LINEAR,
int32_t mag_filter_mode = GL_LINEAR,
int32_t wrap_s_mode = GL_CLAMP_TO_EDGE,
int32_t wrap_t_mode = GL_CLAMP_TO_EDGE);
static ResourceID newTexture(int32_t width, int32_t height);
static ResourceID loadBitmapFont(const String& filePath, bool monospace = false);
static ResourceID loadBitmapFont(const unsigned char* data, unsigned int data_size, bool monospace = false);
//static ResourceID loadSound(const String& filePath);
//static SoundInstance newSoundInstance(ResourceID soundBuffer, float volume = 100.0f, bool loop = false);
static bool destroyResource(ResourceID resource, uint8_t res_type);
static Shader& getShader(ResourceID id);
static Texture& getTexture(ResourceID id);
static BitmapFont& getBitmapFont(ResourceID id);
//static SoundBuffer& getSoundBuffer(ResourceID id);
inline static ResourceID getDefaultShader(void) { return ResourceManager::s_defaultShader; }
inline static ResourceID getDefaultBlendShader(void) { return ResourceManager::s_defaultBlendShader; }
inline static ResourceID getDefaultBitmapFont(void) { return ResourceManager::s_defaultBitmapFont; }
inline static ResourceID getDefaultBitmapFontMono(void) { return ResourceManager::s_defaultBitmapFontMono; }
inline static ResourceID getDefaultLightTexture(void) { return ResourceManager::s_defaultLightTexture; }
inline static ResourceID getStateGradientTexture(void) { return ResourceManager::s_stateGradientTexture; }
inline static ResourceID getBasicShadowTexture(void) { return ResourceManager::s_basicShadowTexture; }
private:
inline static std::unordered_map<ResourceID, Shader> s_shaders;
inline static std::unordered_map<ResourceID, Texture> s_textures;
inline static std::unordered_map<ResourceID, BitmapFont> s_bitmapFonts;
//inline static std::unordered_map<ResourceID, SoundBuffer> s_soundBuffers;
inline static ResourceID s_next_id = 1024;
inline static ResourceID s_defaultShader { 0 };
inline static ResourceID s_defaultBlendShader { 0 };
inline static ResourceID s_defaultBitmapFont { 0 };
inline static ResourceID s_defaultBitmapFontMono { 0 };
inline static ResourceID s_defaultLightTexture { 0 };
inline static ResourceID s_ghostTexture { 0 };
inline static ResourceID s_ghostShader { 0 };
inline static ResourceID s_ghostBitmapFont { 0 };
inline static ResourceID s_stateGradientTexture { 0 };
inline static ResourceID s_basicShadowTexture { 0 };
inline static ResourceID s_ghostSoundBuffer { 0 };
public:
inline static const uint8_t InvalidResource = 0;
};
} // namespace ox
#endif

365
src/ogfx/Shader.cpp Executable file
View file

@ -0,0 +1,365 @@
#include "Shader.hpp"
#include <Utils.hpp>
#include <glad/glad.h>
#include <Logger.hpp>
#include <Defines.hpp>
#include "Errors.hpp"
//TODO: Implement Errors
namespace ogfx
{
using namespace ostd;
Shader::~Shader(void)
{
glDeleteProgram(getOpenGLID());
}
Shader& Shader::createFromName(String shaderName, bool singleFile, String shaderFolder, bool auto_register_uniforms)
{
StringEditor se = shaderFolder;
se.trim();
bool use_custom_shader_folder = se.str() != "";
String tmp_shader_folder = "";
if (use_custom_shader_folder)
{
tmp_shader_folder = Shader::getShaderFolder();
Shader::setShaderFolder(se.str());
}
uint64_t shader_id;
if (!singleFile) shader_id = Shader::gl_loadShader(shaderName);
else shader_id = Shader::gl_loadShaderFromSingleFile(shaderName);
if (use_custom_shader_folder)
Shader::setShaderFolder(tmp_shader_folder);
setID(shader_id);
if (shader_id == 0) return *this;
setTypeName("ox::Shader");
validate();
bind();
Shader::s_auto_register_uniforms = auto_register_uniforms;
__auto_register_uniforms();
unbind();
return *this;
}
Shader& Shader::createFromSources(String vertSource, String fragSource, bool auto_register_uniforms)
{
uint64_t shader_id = Shader::gl_createShaderProgram(vertSource, fragSource);
setID(shader_id);
if (shader_id == 0) return *this;
setTypeName("ox::Shader");
validate();
bind();
Shader::s_auto_register_uniforms = auto_register_uniforms;
__auto_register_uniforms();
unbind();
return *this;
}
Shader& Shader::createFromSeparateFiles(String vertFilePath, String fragFilePath, bool auto_register_uniforms)
{
std::vector<String> vertLines;
std::vector<String> fragLines;
if (!Utils::readFile(vertFilePath, vertLines))
{
ErrorHandler::pushError(Shader::ERR_SHADER_SOURCE_READ_FILED);
String error_str = ErrorHandler::getLastErrorString();
OX_ERROR("%s.\nShader path: %s (vertex)", error_str.c_str(), vertFilePath.c_str());
return *this;
}
if (!Utils::readFile(fragFilePath, fragLines))
{
ErrorHandler::pushError(Shader::ERR_SHADER_SOURCE_READ_FILED);
String error_str = ErrorHandler::getLastErrorString();
OX_ERROR("%s.\nShader path: %s (fragment)", error_str.c_str(), fragFilePath.c_str());
return *this;
};
String vertSource = Shader::linesToString(vertLines);
String fragSource = Shader::linesToString(fragLines);
createFromSources(vertSource, fragSource);
bind();
Shader::s_auto_register_uniforms = auto_register_uniforms;
__auto_register_uniforms();
unbind();
return *this;
}
void Shader::bind(void) const { glUseProgram(getOpenGLID()); }
void Shader::unbind(void) const { glUseProgram(0); }
int32_t Shader::registerUniform(String uniform_name)
{
int32_t uni_loc = glGetUniformLocation(getOpenGLID(), uniform_name.c_str());
if (uni_loc == -1)
{
ErrorHandler::pushError(Shader::ERR_FAILED_TO_REGISTER_UNIFORM);
String error_str = ErrorHandler::getLastErrorString();
OX_ERROR("%s:\nUniform name: <%s>", error_str.c_str(), uniform_name.c_str());
}
m_uniforms[uniform_name] = uni_loc;
return OX_NO_ERROR;
}
int32_t Shader::gl_getUniformLocation(String uniform_name)
{
return glGetUniformLocation(getOpenGLID(), uniform_name.c_str());
}
int32_t Shader::getRegisteredUniform(String uniform_name)
{
if (m_uniforms.find(uniform_name) == m_uniforms.end()) return -1;
return m_uniforms.at(uniform_name);
}
void Shader::updateUniform_f(String uniform_name, float value)
{
if (!__can_update_uniform(uniform_name)) return;
glUniform1f(m_uniforms.at(uniform_name), value);
Shader::s_uniform_updates++;
}
void Shader::updateUniform_i(String uniform_name, int32_t value)
{
if (!__can_update_uniform(uniform_name)) return;
glUniform1i(m_uniforms.at(uniform_name), value);
Shader::s_uniform_updates++;
}
void Shader::updateUniform_b(String uniform_name, bool value)
{
if (!__can_update_uniform(uniform_name)) return;
glUniform1i(m_uniforms.at(uniform_name), (int)value);
Shader::s_uniform_updates++;
}
void Shader::updateUniform_vec2f(String uniform_name, const Vec2& value)
{
if (!__can_update_uniform(uniform_name)) return;
glUniform2f(m_uniforms.at(uniform_name), value.x, value.y);
Shader::s_uniform_updates++;
}
void Shader::updateUniform_vec3f(String uniform_name, const Vec3& value)
{
if (!__can_update_uniform(uniform_name)) return;
glUniform3f(m_uniforms.at(uniform_name), value.x, value.y, value.z);
Shader::s_uniform_updates++;
}
void Shader::updateUniform_vec4f(String uniform_name, float x, float y, float z, float w)
{
if (!__can_update_uniform(uniform_name)) return;
glUniform4f(m_uniforms.at(uniform_name), x, y, z, w);
Shader::s_uniform_updates++;
}
void Shader::updateUniform_vec4f(String uniform_name, const Color& value)
{
if (!__can_update_uniform(uniform_name)) return;
const auto fcol = value.getNormalizedColor();
glUniform4f(m_uniforms.at(uniform_name), fcol.r, fcol.g, fcol.b, fcol.a);
Shader::s_uniform_updates++;
}
void Shader::updateUniform_mat4f(String uniform_name, const glm::mat4& value)
{
if (!__can_update_uniform(uniform_name)) return;
glUniformMatrix4fv(m_uniforms.at(uniform_name), 1, GL_FALSE, &value[0][0]);
Shader::s_uniform_updates++;
}
void Shader::updateUniform_arri(String uniform_name, int32_t array_size, const int32_t* value)
{
if (!__can_update_uniform(uniform_name)) return;
glUniform1iv(m_uniforms.at(uniform_name), array_size, value);
Shader::s_uniform_updates++;
}
void Shader::updateUniform_arrf(String uniform_name, int32_t array_size, const float* value)
{
if (!__can_update_uniform(uniform_name)) return;
glUniform1fv(m_uniforms.at(uniform_name), array_size, value);
Shader::s_uniform_updates++;
}
bool Shader::readShaderSource(String shaderName, String& vertSource, String& fragSource)
{
std::vector<String> vertLines;
std::vector<String> fragLines;
if (!Utils::readFile(Shader::s_shader_folder + "/" + shaderName + "." + Shader::s_vertex_shader_extension, vertLines)) return false;
if (!Utils::readFile(Shader::s_shader_folder + "/" + shaderName + "." + Shader::s_fragment_shader_extension, fragLines)) return false;
vertSource = Shader::linesToString(vertLines);
fragSource = Shader::linesToString(fragLines);
return true;
}
uint32_t Shader::gl_compileShader(uint32_t gl_shader_type, const String& source)
{
if (Shader::s_auto_register_uniforms)
{
auto tokens = StringEditor(source).tokenize(";", true);
for (auto line : tokens)
{
bool skip_next_uniform = false;
StringEditor se = line;
if (se.startsWith("//@[skip_auto_register]"))
{
skip_next_uniform = true;
}
else if(se.startsWith(("uniform ")))
{
if (skip_next_uniform) continue;
se = se.substr(8);
se.trim();
if (se.len() == 0) continue;
int32_t index = se.indexOf(" ");
if (index <= 0) continue;
se = se.substr(index + 1);
se.trim();
index = se.indexOf("[");
if (index > 0)
{
se = se.substr(0, index);
se.trim();
}
Shader::m_temp_uniform_names.push_back(se.str());
}
}
}
uint32_t id = glCreateShader(gl_shader_type);
const char* src = source.c_str();
glShaderSource(id, 1, &src, nullptr);
glCompileShader(id);
int32_t result;
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE)
{
int32_t length;
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
char* message = (char*)alloca(length * sizeof(char));
glGetShaderInfoLog(id, length, &length, message);
String shader_type_str = (gl_shader_type == GL_FRAGMENT_SHADER ? "Fragment" : "Vertex");
ErrorHandler::pushError(Shader::ERR_SHADER_COMPILE_FAILED);
String error_str = ErrorHandler::getLastErrorString();
OX_ERROR("%s: <%s shader>.\nGLSL Error:\n%s", error_str.c_str(), shader_type_str.c_str(), message);
glDeleteShader(id);
return 0;
}
return id;
}
uint32_t Shader::gl_createShaderProgram(const String& vertexShader, const String& fragmentShader)
{
uint32_t program = glCreateProgram();
uint32_t vs = Shader::gl_compileShader(GL_VERTEX_SHADER, vertexShader);
if (vs == 0) return 0;
uint32_t fs = Shader::gl_compileShader(GL_FRAGMENT_SHADER, fragmentShader);
if (fs == 0) return 0;
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
glValidateProgram(program);
glDeleteShader(vs);
glDeleteShader(fs);
return program;
}
uint32_t Shader::gl_loadShader(String shaderName)
{
String vertSource;
String fragSource;
if (!Shader::readShaderSource(shaderName, vertSource, fragSource))
{
ErrorHandler::pushError(Shader::ERR_SHADER_SOURCE_READ_FILED);
String error_str = ErrorHandler::getLastErrorString();
OX_ERROR("%s.\nShader name: %s", error_str.c_str(), shaderName.c_str());
return 0;
}
return Shader::gl_createShaderProgram(vertSource, fragSource);
}
uint32_t Shader::gl_loadShaderFromSingleFile(String shaderName)
{
constexpr uint8_t VERTEX = 0;
constexpr uint8_t FRAGMENT = 1;
constexpr uint8_t NONE = 255;
uint8_t mode = NONE;
StringEditor sources[2];
std::vector<String> lines;
if (!Utils::readFile(Shader::s_shader_folder + "/" + shaderName + "." + Shader::s_single_shader_extension, lines))
{
ErrorHandler::pushError(Shader::ERR_SHADER_SOURCE_READ_FILED);
String error_str = ErrorHandler::getLastErrorString();
OX_ERROR("%s.\nShader name: %s (single file)", error_str.c_str(), shaderName.c_str());;
return 0;
}
StringEditor sel;
for (auto& line : lines)
{
sel = line;
sel.trim().toLower();
if (sel.startsWith("#version "))
{
sources[VERTEX].add(line);
sources[FRAGMENT].add(line);
continue;
}
else if (sel.startsWith("@shader_type"))
{
sel = sel.substr(12);
sel.trim();
if (sel.str() == "[vertex]")
mode = VERTEX;
else if (sel.str() == "[fragment]")
mode = FRAGMENT;
else
mode = NONE;
continue;
}
else if (mode != NONE)
{
sources[mode].add(line).add("\n");
continue;
}
}
return Shader::gl_createShaderProgram(sources[VERTEX].str(), sources[FRAGMENT].str());
}
void Shader::__auto_register_uniforms(void)
{
if (Shader::s_auto_register_uniforms)
{
for (auto& unif : Shader::m_temp_uniform_names)
registerUniform(unif);
}
Shader::s_auto_register_uniforms = true;
std::vector<String>().swap(Shader::m_temp_uniform_names);
}
bool Shader::__can_update_uniform(const String& uniform_name)
{
if (m_uniforms.find(uniform_name) == m_uniforms.end())
{
ErrorHandler::pushError(Shader::ERR_FAILED_TO_UPDATE_UNIFORM);
String error_str = ErrorHandler::getLastErrorString();
OX_ERROR("%s:\nUniform name: <%s>", error_str.c_str(), uniform_name.c_str());
return false;
}
return true;
}
String Shader::linesToString(const std::vector<String>& lines)
{
String full;
for (auto& line : lines)
full += line + "\n";
return full;
}
}

88
src/ogfx/Shader.hpp Executable file
View file

@ -0,0 +1,88 @@
#ifndef __SHADER_HPP__
#define __SHADER_HPP__
#include <ostd/Types.hpp>
#include <ostd/BaseObject.hpp>
#include <unordered_map>
#include <vector>
#include <ostd/Geometry.hpp>
#include <ostd/Color.hpp>
#include <vendor/glm/glm.hpp>
#include <ostd/Defines.hpp>
namespace ogfx
{
using namespace ostd; //TODO: Remove this from header
class Shader : public ostd::BaseObject
{
public:
inline Shader(void) { invalidate(); }
inline Shader(String shaderName, bool singleFile = false, String shaderFolder = "", bool auto_register_uniforms = true) { createFromName(shaderName, singleFile, shaderFolder, auto_register_uniforms); }
~Shader(void);
Shader& createFromName(String shaderName, bool singleFile = false, String shaderFolder = "", bool auto_register_uniforms = true);
Shader& createFromSources(String vertSource, String fragSource, bool auto_register_uniforms = true);
Shader& createFromSeparateFiles(String vertFilePath, String fragFilePath, bool auto_register_uniforms = true);
void bind(void) const;
void unbind(void) const;
inline uint32_t getOpenGLID(void) const { return static_cast<uint32_t>(getID()); }
//TODO: Register struct uniforms automatically
int32_t registerUniform(String uniform_name);
int32_t gl_getUniformLocation(String uniform_name);
int32_t getRegisteredUniform(String uniform_name);
void updateUniform_f(String uniform_name, float value);
void updateUniform_i(String uniform_name, int32_t value);
void updateUniform_b(String uniform_name, bool value);
void updateUniform_vec2f(String uniform_name, const Vec2& value);
void updateUniform_vec3f(String uniform_name, const Vec3& value);
void updateUniform_vec4f(String uniform_name, float x, float y, float z, float w);
inline void updateUniform_vec4f(String uniform_name, const Vec4& value) { updateUniform_vec4f(uniform_name, value.x, value.y, value.z, value.w); }
void updateUniform_vec4f(String uniform_name, const Color& value);
void updateUniform_mat4f(String uniform_name, const glm::mat4& value);
void updateUniform_arri(String uniform_name, int32_t array_size, const int32_t* value);
void updateUniform_arrf(String uniform_name, int32_t array_size, const float* value);
inline static void setShaderFolder(String folder_path) { Shader::s_shader_folder = folder_path; }
inline static String getShaderFolder(void) { return Shader::s_shader_folder; }
inline static void setFragmentShaderExtension(String frag_ext) { Shader::s_fragment_shader_extension = frag_ext; }
inline static String getFragmentShaderExtension(void) { return Shader::s_fragment_shader_extension; }
inline static void setVertexShaderExtension(String vert_ext) { Shader::s_vertex_shader_extension = vert_ext; }
inline static String getVertexShaderExtension(void) { return Shader::s_vertex_shader_extension; }
inline static void setSingleShaderExtension(String single_ext) { Shader::s_single_shader_extension = single_ext; }
inline static String getSingleShaderExtension(void) { return Shader::s_single_shader_extension; }
static bool readShaderSource(String shaderName, String& vertSource, String& fragSource);
static uint32_t gl_compileShader(uint32_t gl_shader_type, const String& source);
static uint32_t gl_createShaderProgram(const String& vertexShader, const String& fragmentShader);
static uint32_t gl_loadShader(String shaderName);
static uint32_t gl_loadShaderFromSingleFile(String shaderName);
inline static uint32_t getUniformUpdateCount(void) { return s_uniform_updates; }
inline static void resetUniformUpdateCount(void) { s_uniform_updates = 0; }
private:
void __auto_register_uniforms(void);
bool __can_update_uniform(const String& uniform_name);
static String linesToString(const std::vector<String>& lines);
private:
std::unordered_map<String, int32_t> m_uniforms;
inline static std::vector<String> m_temp_uniform_names;
inline static bool s_auto_register_uniforms { true };
inline static uint32_t s_uniform_updates { 0 };
private:
inline static String s_shader_folder { "shaders" };
inline static String s_vertex_shader_extension { "vs" };
inline static String s_fragment_shader_extension { "fs" };
inline static String s_single_shader_extension { "shad" };
public:
inline static constexpr int32_t ERR_SHADER_COMPILE_FAILED = OX_SHADER_ERR_MASK + 0x0001;
inline static constexpr int32_t ERR_SHADER_SOURCE_READ_FILED = OX_SHADER_ERR_MASK + 0x0002;
inline static constexpr int32_t ERR_FAILED_TO_REGISTER_UNIFORM = OX_SHADER_ERR_MASK + 0x0003;
inline static constexpr int32_t ERR_FAILED_TO_UPDATE_UNIFORM = OX_SHADER_ERR_MASK + 0x0004;
};
}
#endif

387
src/ogfx/Texture.cpp Executable file
View file

@ -0,0 +1,387 @@
#include "Texture.hpp"
#ifndef STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION
#endif
#include <stb_image/stb_image.h>
#include <Logger.hpp>
#include "Errors.hpp"
//TODO: Implement Errors
namespace ogfx
{
using namespace ostd;
Texture::Texture(const String& path, bool store_data, int32_t min_filter_mode, int32_t mag_filter_mode, int32_t wrap_s_mode, int32_t wrap_t_mode)
{
create(path, store_data, min_filter_mode, mag_filter_mode, wrap_s_mode, wrap_t_mode);;
}
Texture::Texture(int32_t width, int32_t height)
{
create(width, height);
}
Texture::~Texture(void)
{
uint32_t id = getOpenGLID();
GLCall(glDeleteTextures(1, &id));
setID(id);
invalidate();
}
Texture& Texture::create(const String& path, bool store_data, int32_t min_filter_mode, int32_t mag_filter_mode, int32_t wrap_s_mode, int32_t wrap_t_mode)
{
invalidate();
stbi_set_flip_vertically_on_load(1);
if (m_localData != nullptr)
stbi_image_free(m_localData);
m_localData = nullptr;
m_filePath = "";
m_bpp = 0;
m_dataStored = false;
setID(0);
m_localData = stbi_load(path.c_str(), &m_width, &m_height, &m_bpp, 4);
if (m_localData == nullptr)
{
ErrorHandler::pushError(Texture::ERR_IMAGE_LOAD_FAILED);
String err_str = ErrorHandler::getLastErrorString();
OX_ERROR("%s\nFile Path: %s", err_str.c_str(), path.c_str());
return *this;
}
uint32_t gl_id;
GLCall(glGenTextures(1, &gl_id));
setID(gl_id);
bind();
GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter_mode));
GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter_mode));
GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s_mode));
GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t_mode));
GLCall(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_localData));
GLCall(glGenerateMipmap(GL_TEXTURE_2D));
//unbind();
m_dataStored = store_data;
if (!m_dataStored)
{
stbi_image_free(m_localData);
m_localData = nullptr;
}
m_filePath = path;
setTypeName("ox::Texture");
validate();
return *this;
}
Texture& Texture::create(int32_t width, int32_t height)
{
invalidate();
if (m_localData != nullptr)
stbi_image_free(m_localData);
m_localData = nullptr;
m_filePath = "";
m_bpp = 0;
m_dataStored = false;
setID(0);
m_width = width;
m_height = height;
uint32_t gl_id;
GLCall(glGenTextures(1, &gl_id));
setID(gl_id);
bind();
GLCall(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_width, m_height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr));
GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
GLCall(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_localData));
GLCall(glGenerateMipmap(GL_TEXTURE_2D));
setTypeName("ox::Texture");
validate();
return *this;
}
Texture& Texture::create(const unsigned char* data, unsigned int data_size, bool store_data, int32_t min_filter_mode, int32_t mag_filter_mode, int32_t wrap_s_mode, int32_t wrap_t_mode)
{
invalidate();
stbi_set_flip_vertically_on_load(1);
if (m_localData != nullptr)
stbi_image_free(m_localData);
m_localData = nullptr;
m_filePath = "";
m_bpp = 0;
m_dataStored = false;
setID(0);
m_localData = stbi_load_from_memory(data, data_size, &m_width, &m_height, &m_bpp, 4);
if (m_localData == nullptr)
{
ErrorHandler::pushError(Texture::ERR_IMAGE_LOAD_FAILED);
String err_str = ErrorHandler::getLastErrorString();
OX_ERROR("%s\nMemory://data", err_str.c_str());
return *this;
}
uint32_t gl_id;
GLCall(glGenTextures(1, &gl_id));
setID(gl_id);
bind();
GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter_mode));
GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter_mode));
GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s_mode));
GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t_mode));
GLCall(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_localData));
GLCall(glGenerateMipmap(GL_TEXTURE_2D));
//unbind();
m_dataStored = store_data;
if (!m_dataStored)
{
stbi_image_free(m_localData);
m_localData = nullptr;
}
setTypeName("ox::Texture");
validate();
return *this;
}
Texture& Texture::createFromRawData(const unsigned char* rawData, unsigned int data_size, int32_t width, int32_t height, int32_t bpp, int32_t min_filter_mode, int32_t mag_filter_mode, int32_t wrap_s_mode, int32_t wrap_t_mode)
{
invalidate();
stbi_set_flip_vertically_on_load(1);
if (m_localData != nullptr && m_dataStored)
stbi_image_free(m_localData);
else if (m_localData != nullptr && m_dataCopied)
delete[] m_localData;
m_localData = new uint8_t[data_size];
for (uint32_t i = 0; i < data_size; i++)
m_localData[i] = rawData[i];
m_filePath = "";
m_bpp = bpp;
m_width = width;
m_height = height;
m_dataStored = false;
m_dataCopied = true;
uint32_t gl_id;
GLCall(glGenTextures(1, &gl_id));
setID(gl_id);
bind();
GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter_mode));
GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter_mode));
GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s_mode));
GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t_mode));
GLCall(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_localData));
GLCall(glGenerateMipmap(GL_TEXTURE_2D));
setTypeName("ox::Texture");
validate();
return *this;
}
const uint8_t* Texture::getPixelData(void)
{
if (!hasDataStored())
{
ErrorHandler::pushError(Texture::ERR_NO_DATA_STORED);
String err_str = ErrorHandler::getLastErrorString();
OX_ERROR("%s", err_str.c_str());
return nullptr;
}
return m_localData;
}
void Texture::bind(uint32_t slot) const
{
GLCall(glActiveTexture(GL_TEXTURE0 + slot));
GLCall(glBindTexture(GL_TEXTURE_2D, getOpenGLID()));
}
void Texture::unbind(void) const
{
GLCall(glBindTexture(GL_TEXTURE_2D, 0));
}
TextureAtlasIndex Texture::addTileInfo(uint32_t x, uint32_t y, uint32_t w, uint32_t h)
{
if (isInvalid() || x + w > m_width || y + h > m_height)
{
OX_WARN("ox::Texture::addTileInfo(...): Invalid texture coordinates.");
return Texture::FullTextureCoords;
}
if (!hasTileData())
m_tiles.push_back(tTexCoords());
Vec2 bottomLeft = { (float)x / (float)m_width, 1.0f - ((float)(y + h) / (float)m_height) };
Vec2 bottomRight = { (float)(x + w) / (float)m_width, 1.0f - ((float)(y + h) / (float)m_height) };
Vec2 topLeft = { (float)x / (float)m_width, 1.0f - ((float)y / (float)m_height) };
Vec2 topRight = { (float)(x + w) / (float)m_width, 1.0f - ((float)y / (float)m_height) };
tTexCoords texc;
texc.bottomLeft = bottomLeft;
texc.bottomRight = bottomRight;
texc.topLeft = topLeft;
texc.topRight = topRight;
m_tiles.push_back(texc);
return m_tiles.size() - 1;
}
Texture::tTexCoords Texture::getTile(TextureAtlasIndex index)
{
if (!hasTileData() || index >= m_tiles.size())
{
//OX_WARN("ox::Texture::getTile(...): Unable to retrieve tile.");
return Texture::tTexCoords();
}
return m_tiles[index];
}
CubeTexture::CubeTexture(const std::vector<String>& paths, bool store_data, int32_t min_filter_mode, int32_t mag_filter_mode, int32_t wrap_s_mode, int32_t wrap_t_mode, int32_t wrap_r_mode)
{
create(paths, store_data, min_filter_mode, mag_filter_mode, wrap_s_mode, wrap_t_mode, wrap_r_mode);
}
CubeTexture::~CubeTexture(void)
{
uint32_t id = getOpenGLID();
GLCall(glDeleteTextures(1, &id));
setID(id);
invalidate();
}
CubeTexture& CubeTexture::create(const std::vector<String>& paths, bool store_data, int32_t min_filter_mode, int32_t mag_filter_mode, int32_t wrap_s_mode, int32_t wrap_t_mode, int32_t wrap_r_mode)
{
invalidate();
if (paths.size() != 6) return *this; //TODO: Error
stbi_set_flip_vertically_on_load(0);
for (auto& tex_data : m_localData)
{
if (tex_data != nullptr)
stbi_image_free(tex_data);
}
m_localData.clear();
m_bpp = 0;
m_dataStored = false;
setID(0);
for (uint32_t i = 0; i < 6; i++)
{
m_localData.push_back(stbi_load(paths[i].c_str(), &m_width, &m_height, &m_bpp, 4));
//TODO: Check for different sizes and error if not equal
if (m_localData[i] == nullptr)
{
ErrorHandler::pushError(Texture::ERR_IMAGE_LOAD_FAILED);
String err_str = ErrorHandler::getLastErrorString();
OX_ERROR("%s\nFile Path: %s", err_str.c_str(), paths[i].c_str());
return *this;
}
}
uint32_t gl_id;
GLCall(glGenTextures(1, &gl_id));
setID(gl_id);
bind();
GLCall(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, min_filter_mode));
GLCall(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, mag_filter_mode));
GLCall(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, wrap_s_mode));
GLCall(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, wrap_t_mode));
GLCall(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, wrap_r_mode));
for (uint32_t i = 0; i < 6; i++)
{
GLCall(glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA8, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_localData[i]));
}
m_dataStored = store_data;
if (!m_dataStored)
{
for (auto& tex_data : m_localData)
{
stbi_image_free(tex_data);
}
m_localData.clear();
}
setTypeName("ox::CubeTexture");
validate();
return *this;
}
CubeTexture& CubeTexture::create(const std::vector<const unsigned char*>& data, unsigned int data_size, bool store_data, int32_t min_filter_mode, int32_t mag_filter_mode, int32_t wrap_s_mode, int32_t wrap_t_mode, int32_t wrap_r_mode)
{
invalidate();
if (data.size() != 6) return *this; //TODO: Error
stbi_set_flip_vertically_on_load(1);
for (auto& tex_data : m_localData)
{
if (tex_data != nullptr)
stbi_image_free(tex_data);
}
m_localData.clear();
m_bpp = 0;
m_dataStored = false;
setID(0);
for (uint32_t i = 0; i < 6; i++)
{
m_localData.push_back(stbi_load_from_memory(data[i], data_size, &m_width, &m_height, &m_bpp, 4));
//TODO: Check for different sizes and error if not equal
if (m_localData[i] == nullptr)
{
ErrorHandler::pushError(Texture::ERR_IMAGE_LOAD_FAILED);
String err_str = ErrorHandler::getLastErrorString();
OX_ERROR("%s\nMemory://data", err_str.c_str());
return *this;
}
}
uint32_t gl_id;
GLCall(glGenTextures(1, &gl_id));
setID(gl_id);
bind();
GLCall(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, min_filter_mode));
GLCall(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, mag_filter_mode));
GLCall(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, wrap_s_mode));
GLCall(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, wrap_t_mode));
GLCall(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, wrap_r_mode));
for (uint32_t i = 0; i < 6; i++)
{
GLCall(glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA8, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_localData[i]));
}
m_dataStored = store_data;
if (!m_dataStored)
{
for (auto& tex_data : m_localData)
{
stbi_image_free(tex_data);
}
m_localData.clear();
}
setTypeName("ox::CubeTexture");
validate();
return *this;
}
void CubeTexture::bind(uint32_t slot) const
{
GLCall(glActiveTexture(GL_TEXTURE0 + slot));
GLCall(glBindTexture(GL_TEXTURE_CUBE_MAP, getOpenGLID()));
}
void CubeTexture::unbind(void) const
{
GLCall(glBindTexture(GL_TEXTURE_CUBE_MAP, 0));
}
}

135
src/ogfx/Texture.hpp Executable file
View file

@ -0,0 +1,135 @@
#ifndef __TEXTURE_HPP__
#define __TEXTURE_HPP__
#include <ostd/BaseObject.hpp>
#include <ostd/Types.hpp>
#include <vendor/GLAD/glad/glad.h>
#include <ostd/Defines.hpp>
#include <ostd/Geometry.hpp>
namespace ogfx
{
using namespace ostd; //TODO: Remove from header
typedef uint32_t TextureAtlasIndex;
class Texture : public BaseObject
{
public: struct tTexCoords
{
Vec2 topLeft { 0.0f, 1.0f };
Vec2 topRight { 1.0f, 1.0f };
Vec2 bottomRight { 1.0f, 0.0f };
Vec2 bottomLeft { 0.0f, 0.0f };
};
public:
inline Texture(void) { invalidate(); }
Texture(const String& path,
bool store_data = false,
int32_t min_filter_mode = GL_LINEAR,
int32_t mag_filter_mode = GL_LINEAR,
int32_t wrap_s_mode = GL_CLAMP_TO_EDGE,
int32_t wrap_t_mode = GL_CLAMP_TO_EDGE);
Texture(int32_t width, int32_t height);
~Texture(void);
Texture& create(const String& path,
bool store_data = false,
int32_t min_filter_mode = GL_LINEAR,
int32_t mag_filter_mode = GL_LINEAR,
int32_t wrap_s_mode = GL_CLAMP_TO_EDGE,
int32_t wrap_t_mode = GL_CLAMP_TO_EDGE);
Texture& create(int32_t width, int32_t height);
Texture& create(const unsigned char* data,
unsigned int data_size,
bool store_data = false,
int32_t min_filter_mode = GL_LINEAR,
int32_t mag_filter_mode = GL_LINEAR,
int32_t wrap_s_mode = GL_CLAMP_TO_EDGE,
int32_t wrap_t_mode = GL_CLAMP_TO_EDGE);
Texture& createFromRawData(const unsigned char* rawData,
unsigned int data_size,
int32_t width,
int32_t height,
int32_t bpp = 4,
int32_t min_filter_mode = GL_LINEAR,
int32_t mag_filter_mode = GL_LINEAR,
int32_t wrap_s_mode = GL_CLAMP_TO_EDGE,
int32_t wrap_t_mode = GL_CLAMP_TO_EDGE);
const uint8_t* getPixelData(void);
void bind(uint32_t slot = 0) const;
void unbind(void) const;
inline uint32_t getOpenGLID(void) const { return static_cast<uint32_t>(getID()); }
inline String getFilePath(void) const { return m_filePath; }
inline int32_t getWidth(void) const { return m_width; }
inline int32_t getHeight(void) const { return m_height; }
inline int32_t getBitsPerPixel(void) const { return m_bpp; }
inline bool hasDataStored(void) const { return isValid() && m_dataStored; }
inline bool hasTileData(void) { return m_tiles.size() > 0; }
TextureAtlasIndex addTileInfo(uint32_t x, uint32_t y, uint32_t w, uint32_t h);
tTexCoords getTile(TextureAtlasIndex index);
private:
String m_filePath;
uint8_t* m_localData { nullptr };
int32_t m_width { 0 };
int32_t m_height { 0 };
int32_t m_bpp { 0 };
bool m_dataStored { false };
bool m_dataCopied { false };
std::vector<tTexCoords> m_tiles;
public:
inline static constexpr int32_t ERR_IMAGE_LOAD_FAILED = OX_TEXTURE_ERR_MASK + 0x0001;
inline static constexpr int32_t ERR_NO_DATA_STORED = OX_TEXTURE_ERR_MASK + 0x0002;
inline static constexpr TextureAtlasIndex FullTextureCoords = 0;
};
class CubeTexture : public BaseObject
{
public:
inline CubeTexture(void) { invalidate(); }
CubeTexture(const std::vector<String>& paths,
bool store_data = false,
int32_t min_filter_mode = GL_LINEAR,
int32_t mag_filter_mode = GL_LINEAR,
int32_t wrap_s_mode = GL_CLAMP_TO_EDGE,
int32_t wrap_t_mode = GL_CLAMP_TO_EDGE,
int32_t wrap_r_mode = GL_CLAMP_TO_EDGE);
~CubeTexture(void);
CubeTexture& create(const std::vector<String>& paths,
bool store_data = false,
int32_t min_filter_mode = GL_LINEAR,
int32_t mag_filter_mode = GL_LINEAR,
int32_t wrap_s_mode = GL_CLAMP_TO_EDGE,
int32_t wrap_t_mode = GL_CLAMP_TO_EDGE,
int32_t wrap_r_mode = GL_CLAMP_TO_EDGE);
CubeTexture& create(const std::vector<const unsigned char*>& data,
unsigned int data_size,
bool store_data = false,
int32_t min_filter_mode = GL_LINEAR,
int32_t mag_filter_mode = GL_LINEAR,
int32_t wrap_s_mode = GL_CLAMP_TO_EDGE,
int32_t wrap_t_mode = GL_CLAMP_TO_EDGE,
int32_t wrap_r_mode = GL_CLAMP_TO_EDGE);
void bind(uint32_t slot = 0) const;
void unbind(void) const;
inline uint32_t getOpenGLID(void) const { return static_cast<uint32_t>(getID()); }
inline int32_t getWidth(void) const { return m_width; }
inline int32_t getHeight(void) const { return m_height; }
inline int32_t getBitsPerPixel(void) const { return m_bpp; }
inline bool hasDataStored(void) const { return isValid() && m_dataStored; }
private:
std::vector<uint8_t*> m_localData;
int32_t m_width { 0 };
int32_t m_height { 0 };
int32_t m_bpp { 0 };
bool m_dataStored { false };
};
}
#endif

639
src/ogfx/Widgets.cpp Normal file
View file

@ -0,0 +1,639 @@
#include "Widgets.hpp"
#include <ostd/Signals.hpp>
#include "Window.hpp"
#include "RenderCore.hpp"
#include "Utils.hpp"
namespace ogfx
{
namespace oxgui
{
using namespace ostd;
Widget::Widget(void)
{
enableSignals(true);
setTypeName("ogfx::oxgui::Widget");
validate();
}
void Widget::connectSignals(void)
{
connectSignal(tBuiltinSignals::OnGuiEvent);
connectSignal(tBuiltinSignals::WindowResized);
connectSignal(OnWidgetFocusGainedSignal);
}
void Widget::handleSignal(ostd::tSignal& signal)
{
if (!isEnabled()) return;
if (m_parent != nullptr)
{
onSignal(signal);
return;
}
if (signal.ID == tBuiltinSignals::OnGuiEvent)
{
Event& evt = static_cast<Event&>(signal.userData);
sf::Event& event = evt.sf();
if (event.type == sf::Event::KeyPressed)
{
if (!isFocused()) return;
onKeyPressed(evt);
signal.handled = true;
}
else if (event.type == sf::Event::KeyReleased)
{
if (!isFocused()) return;
onKeyReleased(evt);
signal.handled = true;
}
else if (event.type == sf::Event::MouseButtonPressed)
{
Vec2 mousePos { (float)event.mouseButton.x, (float)event.mouseButton.y };
if (!contains(mousePos, true))
{
if (isFocused())
{
focus(false);
onFocusLost();
}
return;
}
if (!isFocused())
{
if (WidgetManager::testForFocus(*this, mousePos))
{
focus();
SignalHandler::emitSignal(OnWidgetFocusGainedSignal, tSignalPriority::RealTime, *this);
onFocusGained();
__on_mouse_pressed(evt);
signal.handled = true;
}
}
else
{
__on_mouse_pressed(evt);
signal.handled = true;
}
}
else if (event.type == sf::Event::MouseButtonReleased)
{
Vec2 mousePos { (float)event.mouseButton.x, (float)event.mouseButton.y };
if (!contains(mousePos, true) || !isFocused()) return;
onMouseReleased(evt);
signal.handled = true;
}
else if (event.type == sf::Event::MouseMoved)
{
Vec2 mousePos { (float)event.mouseMove.x, (float)event.mouseMove.y };
if (isFocused())
{
__on_mouse_moved(evt);
signal.handled = true;
}
}
}
else if (signal.ID == OnWidgetFocusGainedSignal)
{
auto& sender = (Widget&)signal.userData;
if (!sender.compareByOID(*this)) focus(false);
}
onSignal(signal);
}
void Widget::setx(float x)
{
for (auto& w : m_widgets)
{
float xdiff = w.second->getx() - getx();
w.second->setx(x + xdiff);
}
this->x = x;
}
void Widget::sety(float y)
{
for (auto& w : m_widgets)
{
float ydiff = w.second->gety() - gety();
w.second->sety(y + ydiff);
}
this->y = y;
}
WidgetID Widget::addWidget(Widget& widget)
{
if (widget.m_parent != nullptr)
return tWidgetState::WidgetHasParent;
for (auto& w : m_widgets)
{
if (w.second->compareByOID(widget))
return tWidgetState::DuplicatedWidget;
}
m_widgets[s_nextWidgetID++] = &widget;
widget.m_parent = this;
widget.addPos(getPosition());
__recursize_handle_set(*this);
return s_nextWidgetID - 1;
}
void Widget::focus(bool value)
{
m_focused = value;
// if (!value)
// {
for (auto& w : m_widgets)
w.second->focus(false);
// }
}
void Widget::drawOutlinedQuad(ogfx::RenderCore& gfx, const ostd::Vec2& position, const ostd::Vec2& size, const ostd::Color& fill, const ostd::Color& border, float borderWidth)
{
Vec2 pos = position + getPosition();
gfx.drawQuad(pos, size, fill, false);
gfx.drawQuad(pos, { size.x, borderWidth }, border, false);
gfx.drawQuad({ pos.x, pos.y + size.y - borderWidth }, { size.x, borderWidth }, border, false);
gfx.drawQuad({ pos.x, pos.y + borderWidth }, { borderWidth, size.y - (borderWidth * 2) }, border, false);
gfx.drawQuad({ pos.x + size.x - borderWidth, pos.y + borderWidth }, { borderWidth, size.y - (borderWidth * 2) }, border, false);
}
void Widget::render(ogfx::RenderCore& gfx)
{
if (!isEnabled()) return;
// if (!ostd::StringEditor(getTypeName()).startsWith("ogfx::oxgui"))
// return;
renderFrame(gfx);
renderContent(gfx);
if (m_disableAutoChildrenRender)
return;
for (auto& w : m_widgets)
w.second->render(gfx);
}
void Widget::__on_mouse_pressed(ogfx::Event& evt)
{
for (auto& w : m_widgets)
w.second->__on_mouse_pressed(evt);
onMousePressed(evt);
}
void Widget::__on_mouse_released(ogfx::Event& evt)
{
onMouseReleased(evt);
}
void Widget::__on_mouse_moved(ogfx::Event& evt)
{
for (auto& w : m_widgets)
w.second->__on_mouse_moved(evt);
onMouseMoved(evt);
}
void Widget::__on_key_pressed(ogfx::Event& evt)
{
onKeyPressed(evt);
}
void Widget::__on_key_released(ogfx::Event& evt)
{
onKeyReleased(evt);
}
void Widget::__recursize_handle_set(Widget& widget)
{
widget.setSubWindowHandle(getSubWindowHandle());
if (widget.getChildren().size() == 0) return;
for (auto& w : widget.getChildren())
__recursize_handle_set(*w.second);
}
void WidgetManager::init(void)
{
//SubWindow Theme
s_globalTheme.subWindow.titleBarColor_focused = { 20, 80, 200 };
s_globalTheme.subWindow.titleBarColor_unfocused = { 50, 50, 50, 255 };
s_globalTheme.subWindow.backgroundColor = { 0, 0, 0, 225 };
s_globalTheme.subWindow.borderColor_focused = { 20, 80, 255 };
s_globalTheme.subWindow.borderColor_unfocused = { 50, 50, 50, 255 };
s_globalTheme.subWindow.closeButtonColor = { 120, 30, 50 };
s_globalTheme.subWindow.closeButtonColor_hover = { 170, 30, 50 };
s_globalTheme.subWindow.closeButtonTextColor = { 200, 200, 200 };
s_globalTheme.subWindow.titleColor = { 200, 200, 200 };
s_globalTheme.subWindow.closeButtonFont = ResourceManager::getDefaultBitmapFont();
s_globalTheme.subWindow.titleFont = ResourceManager::getDefaultBitmapFont();
s_globalTheme.subWindow.font = ResourceManager::getDefaultBitmapFont();
//TabPanel Theme
s_globalTheme.tabPanel.backgroundColor = { 30, 30, 30, 255 };
s_globalTheme.tabPanel.tabBackground_focused = { 30, 30, 30, 255 };
s_globalTheme.tabPanel.tabBackground_unfocused = { 20, 20, 20, 255 };
s_globalTheme.tabPanel.focusedTabHighlight = { 255, 140, 35, 255 };
s_globalTheme.tabPanel.unfocusedTabHighlight = { 255, 140, 35, 60 };
s_globalTheme.tabPanel.tabBarBackground = { 5, 5, 5, 255 };
s_globalTheme.tabPanel.tabBackground_hover = { 50, 50, 50, 255 };
s_globalTheme.tabPanel.focusedTabNameColor = { 220, 220, 220, 225 };
s_globalTheme.tabPanel.unfocusedTabNameColor = { 100, 100, 100, 255 };
s_globalTheme.tabPanel.tabNameFont = ResourceManager::getDefaultBitmapFont();
s_globalTheme.tabPanel.font = ResourceManager::getDefaultBitmapFont();
}
void WidgetManager::addWidget(Widget& widget)
{
int32_t handle = s_widgets.size();
recursive_handle_set(widget, handle);
s_widgets.push_back(&widget);
s_widgetOrder.push_back(handle);
}
void WidgetManager::render(RenderCore& gfx)
{
// Renderer2D::tTextInfo textInfo;
// textInfo.font = ResourceManager::getDefaultBitmapFont();
// textInfo.characterHeight = 30;
// textInfo.color = { 30, 220, 40 };
// textInfo.characterSpacing = 0
reorder_widgets();
for (auto& index : s_widgetOrder)
{
s_widgets[index]->render(gfx);
// StringEditor str;
// str.addi(find_index(index));
// gfx.drawText(str.str(), s_widgets[index]->getPosition() + Vec2 { 5, 5 }, textInfo);
}
}
bool WidgetManager::testForFocus(Widget& widget, const ostd::Vec2& mouseClick)
{
if (widget.isFocused()) return true;
for (int32_t i = s_widgetOrder.size() - 1; i >= 0; i--)
{
uint32_t index = s_widgetOrder[i];
if (s_widgets[index]->contains(mouseClick))
{
if (s_widgets[index]->compareByOID(widget))
return true;
return false;
}
}
return false;
}
Widget& WidgetManager::getSubWindow(int32_t handle)
{
if (handle < 0 || handle >= s_widgets.size())
return (Widget&)BaseObject::InvalidRef();
return *s_widgets[handle];
}
int32_t WidgetManager::find_index(uint32_t index)
{
for (int32_t i = 0; i < s_widgetOrder.size(); i++)
{
if (s_widgetOrder[i] == index) return i;
}
return -1;
}
void WidgetManager::recursive_handle_set(Widget& widget, int32_t handle)
{
widget.setSubWindowHandle(handle);
if (widget.getChildren().size() == 0) return;
for (auto& w : widget.getChildren())
recursive_handle_set(*w.second, handle);
}
void WidgetManager::reorder_widgets(void)
{
Widget* focused_widget = nullptr;
int32_t i = 0;
for (i = s_widgetOrder.size() - 1; i >= 0; i--)
{
Widget& w = *s_widgets[s_widgetOrder[i]];
if (w.isFocused())
{
focused_widget = &w;
break;
}
}
if (focused_widget == nullptr) return;
if (i == s_widgetOrder.size() - 1) return;
uint32_t index = s_widgetOrder[i];
s_widgetOrder.erase(s_widgetOrder.begin() + i);
s_widgetOrder.push_back(index);
}
SubWindow& SubWindow::create(const ostd::Vec2& position, const ostd::Vec2& size)
{
setPosition(position);
setSize(size);
connectSignals();
m_title = "Window Title";
setTypeName("ogfx::oxgui::SubWindow");
validate();
return *this;
}
void SubWindow::renderFrame(ogfx::RenderCore& gfx)
{
WidgetTheme* theme = &WidgetManager::getGlobalTheme();
if (m_overrideGlobalTheme)
theme = &m_theme;
float closeBtnX = getx() + getw() - m_closeBtnWidth - 1;
m_closeBtnRect = Rectangle({ closeBtnX, gety() }, { m_closeBtnWidth, m_titleBarHeight - 3 });
float border_width = 1;
Color col;
if (isFocused()) col = theme->subWindow.borderColor_focused;
else col = theme->subWindow.borderColor_unfocused;
if (theme->subWindow.enableShadow)
gfx.drawImage(ResourceManager::getBasicShadowTexture(), getPosition() - Vec2 { 50, 50 }, getSize() + Vec2 { 100, 100 }, { 255, 255, 255, (uint8_t)(isFocused() ? 255 : 100) }, false);
drawOutlinedQuad(gfx, { 0, 0 }, getSize(), theme->subWindow.backgroundColor, col, border_width);
if (isFocused()) col = theme->subWindow.titleBarColor_focused;
else col = theme->subWindow.titleBarColor_unfocused;
gfx.drawQuad(getPosition(), { getw(), m_titleBarHeight }, col, false);
Color closeBtnCol = theme->subWindow.closeButtonColor;
if (m_hoverCloseBtn)
closeBtnCol = theme->subWindow.closeButtonColor_hover;
gfx.drawQuad(m_closeBtnRect.getPosition(), m_closeBtnRect.getSize(), closeBtnCol, false);
Renderer2D::Text::font = theme->subWindow.closeButtonFont;
Renderer2D::Text::characterHeight = 20;
Renderer2D::Text::characterSpacing = 0;
float closeBtnTxtw = Renderer2D::Text::getStringBounds("X").x;
gfx.drawText("X", Vec2 { closeBtnX + ((m_closeBtnWidth / 2.0f) - (closeBtnTxtw / 2.0f)), gety() - 2 }, theme->subWindow.closeButtonFont, (float)20, theme->subWindow.closeButtonTextColor);
Vec2 titleBounds = Renderer2D::Text::getStringBounds(m_title);
Renderer2D::Text::font = theme->subWindow.titleFont;
gfx.drawText(m_title, Vec2 { getx() + ((getw() / 2.0f) - (titleBounds.x / 2.0f)) - (m_closeBtnWidth / 2.0f), gety() }, theme->subWindow.titleFont, (float)20, theme->subWindow.titleColor);
}
void SubWindow::onMousePressed(ogfx::Event& evt)
{
auto& sfevt = evt.sf();
Vec2 mpos = { (float)sfevt.mouseButton.x, (float)sfevt.mouseButton.y };
if (Rectangle(getPosition(), { getw(), m_titleBarHeight }).contains(mpos, false))
{
m_mousePressed = true;
m_clickPos = mpos;
}
}
void SubWindow::onMouseReleased(ogfx::Event& evt)
{
m_mousePressed = false;
}
void SubWindow::onMouseMoved(ogfx::Event& evt)
{
auto& sfevt = evt.sf();
Vec2 mpos = { (float)sfevt.mouseMove.x, (float)sfevt.mouseMove.y };
if (m_closeBtnRect.contains(mpos, true))
m_hoverCloseBtn = true;
else
m_hoverCloseBtn = false;
if (!isFocused() && !m_mousePressed) return;
if (m_mousePressed && contains(mpos, true))
{
Vec2 diff = mpos - m_clickPos;
addPos(diff);
m_clickPos = mpos;
}
else if (m_mousePressed)
m_mousePressed = false;
}
void SubWindow::onSignal(tSignal& signal)
{
if (signal.ID == tBuiltinSignals::WindowResized)
{
WindowSizeObj& wsobj = static_cast<WindowSizeObj&>(signal.userData);
if (getx() + getw() > wsobj.width)
{
float xdiff = wsobj.width - getx();
xdiff = getw() - xdiff;
subx(xdiff);
}
if (gety() + geth() > wsobj.height)
{
float ydiff = wsobj.height - gety();
ydiff = geth() - ydiff;
suby(ydiff);
}
}
}
TabWidget& TabWidget::create(TabPanel& parent, const ostd::String& text)
{
if (parent.isInvalid())
{
invalidate();
return *this;
}
m_text = text;
setPosition({ 0, 5 });
setSize(parent.getContentSize());
m_disableAutoChildrenRender = true;
setTypeName("ogfx::oxgui::TabWidget");
validate();
enable();
parent.addWidget(*this);
return *this;
}
void TabWidget::onMousePressed(ogfx::Event& evt)
{
}
void TabWidget::onMouseReleased(ogfx::Event& evt)
{
}
TabPanel& TabPanel::create(Widget& parent, const ostd::Vec2& subPosition, const ostd::Vec2& size)
{
if (parent.isInvalid())
{
invalidate();
return *this;
}
setPosition(parent.getContentOffset() + subPosition);
if (size == Vec2 { 0, 0 })
setSize(parent.getContentSize());
else
setSize(size);
m_enableTabBarColorBlend = true;
setTypeName("ogfx::oxgui::TabPanel");
connectSignals();
validate();
enable();
parent.addWidget(*this);
return *this;
}
void TabPanel::renderFrame(ogfx::RenderCore& gfx)
{
WidgetTheme* theme = &WidgetManager::getGlobalTheme();
if (m_overrideGlobalTheme)
theme = &m_theme;
drawOutlinedQuad(gfx, { 0, 0 }, getSize(), theme->tabPanel.backgroundColor, theme->tabPanel.backgroundColor);
Color tabBarColor = theme->tabPanel.tabBarBackground;
if (m_enableTabBarColorBlend)
{
Widget& baseWin = WidgetManager::getSubWindow(getSubWindowHandle());
if (baseWin.isValid())
{
if (baseWin.isFocused())
tabBarColor = theme->subWindow.titleBarColor_focused;
else
tabBarColor = theme->subWindow.titleBarColor_unfocused;
}
}
gfx.drawQuad(getPosition() - Vec2 { 0, 1 }, { getw(), theme->tabPanel.tabBarHeight }, tabBarColor, false);
if (m_selectedTab < 0) return;
Renderer2D::tTextInfo textInfo;
textInfo.characterHeight = theme->tabPanel.tabNameFontSize;
textInfo.characterSpacing = 3;
textInfo.font = theme->tabPanel.tabNameFont;
Renderer2D::Text::characterHeight = textInfo.characterHeight;
Renderer2D::Text::characterSpacing = textInfo.characterSpacing;
Renderer2D::Text::font = textInfo.font;
float tabx = 0;
m_hoverTab = -1;
for (uint32_t i = 0; i < m_tabs.size(); i++)
{
auto& tab = m_tabs[i];
float tabw = theme->tabPanel.fixedTabWidth;
Vec2 tabPos = getPosition() + Vec2 { tabx, 0 };
Vec2 tabSize = { tabw, theme->tabPanel.tabBarHeight };
Color col = theme->tabPanel.tabBackground_unfocused;
if (i == m_selectedTab)
col = theme->tabPanel.tabBackground_focused;
else if (Rectangle(tabPos, tabSize).contains(m_mousePos, true))
{
m_hoverTab = i;
col = theme->tabPanel.tabBackground_hover;
}
gfx.drawQuad(tabPos, tabSize, col, false);
if (i == m_selectedTab)
{
gfx.drawQuad(getPosition() + Vec2 { tabx, 0 }, { tabw, theme->tabPanel.tabHighlightHeight }, theme->tabPanel.focusedTabHighlight, false);
gfx.drawQuad(tabPos, { theme->tabPanel.tabHighlightHeight, tabSize.y }, theme->tabPanel.focusedTabHighlight, false);
gfx.drawQuad(tabPos + Vec2 { tabw - theme->tabPanel.tabHighlightHeight, 0 }, { theme->tabPanel.tabHighlightHeight, tabSize.y }, theme->tabPanel.focusedTabHighlight, false);
}
else
{
gfx.drawQuad(getPosition() + Vec2 { tabx, theme->tabPanel.tabBarHeight - theme->tabPanel.tabHighlightHeight }, { tabw, theme->tabPanel.tabHighlightHeight }, theme->tabPanel.focusedTabHighlight, false);
gfx.drawQuad(tabPos, { theme->tabPanel.tabHighlightHeight, tabSize.y - theme->tabPanel.tabHighlightHeight }, { 50, 50, 50 }, false);
}
Vec2 nameBounds = Renderer2D::Text::getStringBounds(tab->getText());
if (i == m_selectedTab)
textInfo.color = theme->tabPanel.focusedTabNameColor;
else
textInfo.color = theme->tabPanel.unfocusedTabNameColor;
gfx.drawText(tab->getText(), getPosition() + Vec2 { tabx, 0 } + ((Vec2 { tabw, 0 } / 2.0f) - Vec2 { nameBounds.x / 2.0f, -2 }), textInfo);
tabx += tabw;
}
}
void TabPanel::renderContent(ogfx::RenderCore& gfx)
{
if (m_selectedTab == -1) return;
auto& tab = m_tabs[m_selectedTab];
for (auto& w : tab->getChildren())
w.second->render(gfx);
}
ostd::Vec2 TabPanel::getContentSize(void)
{
float tabBarHeight = WidgetManager::getGlobalTheme().tabPanel.tabBarHeight;
if (isGlobalThemeOverrideEnabled())
tabBarHeight = m_theme.tabPanel.tabBarHeight;
return getSize() - ostd::Vec2 { 0, tabBarHeight };
}
ostd::Vec2 TabPanel::getContentOffset(void)
{
float tabBarHeight = WidgetManager::getGlobalTheme().tabPanel.tabBarHeight;
if (isGlobalThemeOverrideEnabled())
tabBarHeight = m_theme.tabPanel.tabBarHeight;
return ostd::Vec2 { 0, tabBarHeight };
}
void TabPanel::onMousePressed(ogfx::Event& evt)
{
if (m_hoverTab != -1)
{
m_selectedTab = m_hoverTab;
m_hoverTab = -1;
}
}
void TabPanel::onMouseReleased(ogfx::Event& evt)
{
}
void TabPanel::onMouseMoved(ogfx::Event& evt)
{
auto& sfmpos = evt.sf().mouseMove;
m_mousePos = { (float)sfmpos.x, (float)sfmpos.y };
}
// TabWidget& TabPanel::newTab(const ostd::String& text)
// {
// TabWidget tab;
// m_tabs.push_back(tab);
// m_tabs[m_tabs.size() - 1].create(*this, text);
// m_selectedTab = m_tabs.size() - 1;
// return m_tabs[m_tabs.size() - 1];
// }
void TabPanel::addTab(TabWidget& tab)
{
tab.create(*this, "");
m_tabs.push_back(&tab);
m_selectedTab = m_tabs.size() - 1;
}
}
}

257
src/ogfx/Widgets.hpp Normal file
View file

@ -0,0 +1,257 @@
#pragma once
#include <ostd/BaseObject.hpp>
#include <ostd/Geometry.hpp>
#include <ostd/Color.hpp>
#include <ogfx/RTData.hpp>
#include <unordered_map>
namespace ogfx
{
class RenderCore;
class Event;
namespace oxgui
{
struct tWidgetState
{
inline static constexpr ostd::WidgetID DuplicatedWidget = 0x00000001;
inline static constexpr ostd::WidgetID WidgetHasParent = 0x00000002;
inline static constexpr ostd::WidgetID ValidWidgetBase = 0x00000400;
inline static bool check(ostd::WidgetID result) { return result >= ValidWidgetBase; }
};
class WidgetTheme
{
using Col = ostd::Color;
using Font = ostd::ResourceID;
public: struct tSubWindowTheme {
Col titleBarColor_focused;
Col titleBarColor_unfocused;
Col titleColor;
Col closeButtonColor;
Col closeButtonColor_hover;
Col closeButtonTextColor;
Col borderColor_focused;
Col borderColor_unfocused;
Col backgroundColor;
Font titleFont { 0 };
Font closeButtonFont { 0 };
Font font { 0 };
bool enableShadow { true };
};
public: struct tTabPanel {
Col backgroundColor;
Col tabBackground_focused;
Col tabBackground_unfocused;
Col focusedTabHighlight;
Col unfocusedTabHighlight;
Col tabBarBackground;
Col tabBackground_hover;
Col focusedTabNameColor;
Col unfocusedTabNameColor;
Font tabNameFont { 0 };
Font font { 0 };
float fixedTabWidth { 130 };
float tabBarHeight { 25 };
float tabHighlightHeight { 1 };
float tabNameFontSize { 20 };
};
public:
tSubWindowTheme subWindow;
tTabPanel tabPanel;
};
class Widget : public ostd::BaseObject, public ostd::Rectangle
{
public:
~Widget(void) = default;
void connectSignals(void);
void handleSignal(ostd::tSignal& signal) override;
inline void enableGlobalThemeOverride(bool enable = true) { m_overrideGlobalTheme = enable; }
inline bool isGlobalThemeOverrideEnabled(void) { return m_overrideGlobalTheme; }
inline void setTheme(WidgetTheme theme) { m_theme = theme; }
inline WidgetTheme& getTheme(void) { return m_theme; }
inline std::unordered_map<ostd::WidgetID, Widget*>& getChildren(void) { return m_widgets; }
inline void setSubWindowHandle(int32_t handle) { m_subWindowHandle = handle; }
inline int32_t getSubWindowHandle(void) { return m_subWindowHandle; }
void setx(float x) override;
void sety(float y) override;
ostd::WidgetID addWidget(Widget& widget);
inline void enable(bool enabled = true) { m_enabled = enabled; }
inline bool isEnabled(void) { return m_enabled; }
void focus(bool value = true);
inline bool isFocused(void) { return m_focused; }
inline virtual ostd::Vec2 getContentSize(void) { return getSize(); }
inline virtual ostd::Vec2 getContentOffset(void) { return { 0, 0 }; }
inline virtual void onSignal(ostd::tSignal& signal) { }
inline virtual void onKeyPressed(ogfx::Event& evt) { }
inline virtual void onKeyReleased(ogfx::Event& evt) { }
inline virtual void onMousePressed(ogfx::Event& evt) { }
inline virtual void onMouseReleased(ogfx::Event& evt) { }
inline virtual void onMouseMoved(ogfx::Event& evt) { }
inline virtual void onFocusGained(void) { }
inline virtual void onFocusLost(void) { }
inline virtual void renderFrame(ogfx::RenderCore& gfx) { }
inline virtual void renderContent(ogfx::RenderCore& gfx) { }
void render(ogfx::RenderCore& gfx);
private:
void __on_mouse_pressed(ogfx::Event& evt);
void __on_mouse_released(ogfx::Event& evt);
void __on_mouse_moved(ogfx::Event& evt);
void __on_key_pressed(ogfx::Event& evt);
void __on_key_released(ogfx::Event& evt);
void __recursize_handle_set(Widget& widget);
protected:
Widget(void);
void drawOutlinedQuad(ogfx::RenderCore& gfx, const ostd::Vec2& position, const ostd::Vec2& size, const ostd::Color& fill, const ostd::Color& border, float borderWidth = 2);
private:
bool m_enabled { false };
bool m_focused { false };
int32_t m_subWindowHandle { -1 };
std::unordered_map<ostd::WidgetID, Widget*> m_widgets;
inline static ostd::WidgetID s_nextWidgetID = tWidgetState::ValidWidgetBase;
protected:
inline static const uint32_t OnWidgetFocusGainedSignal = RTData::newCustomSignal(1200);
WidgetTheme m_theme;
bool m_overrideGlobalTheme { false };
Widget* m_parent { nullptr };
bool m_disableAutoChildrenRender { false };
};
class WidgetManager : public ostd::BaseObject
{
public:
static void init(void);
static void addWidget(Widget& widget);
static void render(RenderCore& gfx);
static bool testForFocus(Widget& widget, const ostd::Vec2& mouseClick);
static Widget& getSubWindow(int32_t handle);
inline static void setGlobalTheme(WidgetTheme theme) { s_globalTheme = theme; }
inline static WidgetTheme& getGlobalTheme(void) { return s_globalTheme; }
private:
static void reorder_widgets(void);
static int32_t find_index(uint32_t index);
static void recursive_handle_set(Widget& widget, int32_t handle);
private:
inline static std::vector<Widget*> s_widgets;
inline static std::vector<uint32_t> s_widgetOrder;
inline static WidgetTheme s_globalTheme;
};
class SubWindow : public Widget
{
public:
inline SubWindow(void) : Widget() { invalidate(); }
inline SubWindow(const ostd::Vec2& position, const ostd::Vec2& size) : Widget() { create(position, size); }
virtual ~SubWindow(void) = default;
SubWindow& create(const ostd::Vec2& position, const ostd::Vec2& size);
inline ostd::String getTitle(void) { return m_title; }
inline void setTitle(const ostd::String& title) { m_title = title; }
inline ostd::Vec2 getContentSize(void) override { return getSize() - ostd::Vec2 { m_borderWidth * 2, m_titleBarHeight + (m_borderWidth * 2) }; }
inline ostd::Vec2 getContentOffset(void) override { return ostd::Vec2 { m_borderWidth, m_titleBarHeight + m_borderWidth }; }
virtual void renderFrame(ogfx::RenderCore& gfx) override;
void onMousePressed(ogfx::Event& evt) override;
void onMouseReleased(ogfx::Event& evt) override;
void onMouseMoved(ogfx::Event& evt) override;
void onSignal(ostd::tSignal& signal) override;
// inline virtual void onSignal(ostd::tSignal& signal) { }
// inline virtual void onFocusGained(void) { }
// inline virtual void onFocusLost(void) { }
// void onKeyPressed(ogfx::Event& evt) override;
// void onKeyReleased(ogfx::Event& evt) override;
private:
bool m_mousePressed { false };
ostd::Vec2 m_clickPos { 0, 0 };
float m_titleBarHeight { 20 };
float m_closeBtnWidth { 24 };
float m_borderWidth { 1 };
Rectangle m_closeBtnRect;
bool m_hoverCloseBtn { false };
ostd::String m_title { "" };
};
class TabPanel;
class TabWidget : public Widget
{
public:
inline TabWidget(void) : Widget() { invalidate(); }
inline TabWidget(TabPanel& parent, const ostd::String& text) { create(parent, text); }
TabWidget& create(TabPanel& parent, const ostd::String& text);
void onMousePressed(ogfx::Event& evt) override;
void onMouseReleased(ogfx::Event& evt) override;
inline ostd::Vec2 getContentOffset(void) override { return m_parent->getContentOffset(); }
inline ostd::Vec2 getContentSize(void) override { return getSize(); }
inline void setText(const ostd::String& text) { m_text = text; }
inline ostd::String getText(void) { return m_text; }
private:
ostd::String m_text { "" };
};
class TabPanel : public Widget
{
public:
inline TabPanel(void) : Widget() { invalidate(); }
inline TabPanel(Widget& parent, const ostd::Vec2& subPosition = { 0, 0 }, const ostd::Vec2& size = { 0, 0 }) { create(parent, subPosition, size); }
TabPanel& create(Widget& parent, const ostd::Vec2& subPosition = { 0, 0 }, const ostd::Vec2& size = { 0, 0 });
virtual void renderFrame(ogfx::RenderCore& gfx) override;
virtual void renderContent(ogfx::RenderCore& gfx) override;
ostd::Vec2 getContentSize(void) override;
ostd::Vec2 getContentOffset(void) override;
void onMousePressed(ogfx::Event& evt) override;
void onMouseReleased(ogfx::Event& evt) override;
void onMouseMoved(ogfx::Event& evt) override;
// TabWidget& newTab(const ostd::String& text);
void addTab(TabWidget& tab);
inline bool selectTab(uint32_t tabIndex) { if (tabIndex >= m_tabs.size()) return false; m_selectedTab = tabIndex; return true; }
inline int32_t getSelectedTab(void) { return m_selectedTab; }
private:
std::vector<TabWidget*> m_tabs;
int32_t m_selectedTab { -1 };
ostd::Vec2 m_mousePos { -10000, -10000 };
int32_t m_hoverTab { -1 };
bool m_enableTabBarColorBlend { false };
};
}
}

93
src/ogfx/Window.cpp Executable file
View file

@ -0,0 +1,93 @@
#include "Window.hpp"
#include "Logger.hpp"
#include "Signals.hpp"
namespace ogfx
{
Window& Window::create(ostd::UI16Point size, ostd::String title, tContextSettings contextSettings)
{
sf::ContextSettings settings;
settings.depthBits = contextSettings.depthBits;
settings.stencilBits = contextSettings.stencilBits;
settings.antialiasingLevel = contextSettings.antiAliasLevel;
settings.majorVersion = contextSettings.GLMajorVersion;
settings.minorVersion = contextSettings.GLMinorVersion;
settings.attributeFlags = (contextSettings.GLProfile == tContextSettings::tGLProfile::Core ? settings.Core : settings.Default);
m_sfml_window.create(sf::VideoMode(size.x, size.y), title, sf::Style::Default, settings);
m_sfml_window.setActive(true);
m_sfml_window.setKeyRepeatEnabled(false);
enableVSync();
if (!gladLoadGLLoader(reinterpret_cast<GLADloadproc>(sf::Context::getFunction)))
{
OX_FATAL("Failed to initialize GLAD.");
return *this;
}
glViewport(0, 0, size.x, size.y);
glEnable(GL_BLEND);
glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
setTypeName("ogfx::Window");
validate();
__calc_win_deco_sizes();
return *this;
}
void Window::handleEvents(void)
{
sf::Event event;
while (m_sfml_window.pollEvent(event))
{
Event evt(event);
if (event.type == sf::Event::Resized)
{
WindowSizeObj wsobj(event.size.width, event.size.height);
SignalHandler::emitSignal(tBuiltinSignals::WindowResized, tSignalPriority::RealTime, wsobj);
}
else
SignalHandler::emitSignal(tBuiltinSignals::OnGuiEvent, tSignalPriority::RealTime, evt);
}
}
Window& Window::centerMouse(void)
{
m_disable_mouse_moved_event = true;
sf::Vector2i mpos = m_sfml_window.getPosition();
sf::Vector2i deco(getBorderSize(), getTitleBarSize());
mpos += sf::Vector2i(m_sfml_window.getSize().x / 2, m_sfml_window.getSize().y / 2);
sf::Mouse::setPosition(mpos + deco);
return *this;
}
void Window::printOpenGLInfo(void)
{
OX_INFO("OpenGL Version: %s", glGetString(GL_VERSION));
int nrAttributes;
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &nrAttributes);
OX_INFO("Maximum number of vertex attributes supported: %d", nrAttributes);
int nTexUnits;
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &nTexUnits);
OX_INFO("Maximum number of Texture Units (per Stage): %d", nTexUnits);
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &nTexUnits);
OX_INFO("Maximum number of Texture Units (Total): %d", nTexUnits);
}
void Window::__calc_win_deco_sizes(void)
{
if (isInvalid()) return;
auto mousePos = sf::Mouse::getPosition();
sf::Vector2i deco { 0, 0 };
sf::Vector2i offset { 100, 100 };
sf::Vector2i npos = m_sfml_window.getPosition() + offset;
sf::Mouse::setPosition(npos);
auto mposr = sf::Mouse::getPosition(m_sfml_window);
deco = offset - mposr;
sf::Mouse::setPosition(mousePos);
m_win_deco_sizes = deco;
}
}

64
src/ogfx/Window.hpp Executable file
View file

@ -0,0 +1,64 @@
#ifndef __WINDOW_HPP__
#define __WINDOW_HPP__
#include <ostd/BaseObject.hpp>
#include <SFML/Window.hpp>
#include <ogfx/DataStructures.hpp>
namespace ogfx
{
class Event : public ostd::BaseObject
{
public:
inline Event(sf::Event& evt) { m_handled = false; setTypeName("ogfx::Event"); validate(); m_event = evt; }
inline sf::Event& sf(void) { return m_event; }
inline bool isHandled(void) { return m_handled; }
inline void markAsHandled(void) { m_handled = true; }
private:
sf::Event m_event;
bool m_handled; //TODO: Add more stuff (type, key and such) to this class in order to avoid using the SFML event directly if possible
};
class Window : public ostd::BaseObject
{
public:
inline Window(void) { invalidate(); }
inline Window(ostd::UI16Point size) { create(size, "OmniaX Window", tContextSettings()); }
inline Window(ostd::UI16Point size, ostd::String title) { create(size, title, tContextSettings()); }
inline Window(ostd::UI16Point size, ostd::String title, tContextSettings contextSettings) { create(size, title, contextSettings); }
Window& create(ostd::UI16Point size, ostd::String title, tContextSettings contextSettings);
inline Window& enableVSync(bool v = true) { m_sfml_window.setVerticalSyncEnabled(v); return *this; }
inline Window& hideMouseCursor(bool v = true) { m_sfml_window.setMouseCursorVisible(!v); return *this; }
inline Window& disableMouseMove(bool v = true) { m_disable_mouse_moved_event = v; return *this; }
inline Window& close(void) { m_running = false; return *this; }
inline Window& renderFrame(void) { m_sfml_window.display(); return *this; }
inline bool isRunning(void) { return m_running; }
inline uint32_t getTitleBarSize(void) { return m_win_deco_sizes.y; }
inline uint32_t getBorderSize(void) { return m_win_deco_sizes.x; }
inline sf::Window& sf(void) { return m_sfml_window; }
inline sf::Vector2i getSize(void) { return (sf::Vector2i)m_sfml_window.getSize(); }
inline sf::Vector2i getPosition(void) { return (sf::Vector2i)m_sfml_window.getPosition(); }
inline bool isMouseMoveEnabled(void) { return !m_disable_mouse_moved_event; }
void handleEvents(void);
Window& centerMouse(void);
void printOpenGLInfo(void);
inline Window& initialize(void) { __calc_win_deco_sizes(); return *this; }
private:
void __calc_win_deco_sizes(void);
private:
sf::Window m_sfml_window;
bool m_running { true };
sf::Vector2i m_win_deco_sizes { 0, 0 };
bool m_disable_mouse_moved_event { false };
};
}
#endif

View file

@ -0,0 +1,785 @@
#ifndef __BasicShadowTexture_HPP__
#define __BasicShadowTexture_HPP__
namespace oxres
{
struct BasicShadowTexture_t {
const unsigned int size = 15442;
const unsigned char data[15442] = {
137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 2,
0, 0, 0, 2, 0, 8, 6, 0, 0, 0, 244, 120, 212, 250, 0, 0, 1, 132, 105, 67,
67, 80, 73, 67, 67, 32, 112, 114, 111, 102, 105, 108, 101, 0, 0, 40, 145, 125, 145, 61,
72, 195, 64, 28, 197, 95, 211, 74, 69, 42, 14, 22, 145, 226, 144, 161, 117, 178, 139, 138,
56, 214, 42, 20, 161, 66, 168, 21, 90, 117, 48, 185, 244, 11, 154, 180, 36, 41, 46, 142,
130, 107, 193, 193, 143, 197, 170, 131, 139, 179, 174, 14, 174, 130, 32, 248, 1, 226, 232, 228,
164, 232, 34, 37, 254, 47, 41, 180, 136, 241, 224, 184, 31, 239, 238, 61, 238, 222, 1, 66,
171, 202, 52, 51, 144, 0, 52, 221, 50, 50, 169, 164, 152, 203, 175, 138, 193, 87, 132, 16,
193, 8, 2, 136, 201, 204, 172, 207, 73, 82, 26, 158, 227, 235, 30, 62, 190, 222, 197, 121,
150, 247, 185, 63, 199, 160, 90, 48, 25, 224, 19, 137, 19, 172, 110, 88, 196, 27, 196, 51,
155, 86, 157, 243, 62, 113, 152, 149, 101, 149, 248, 156, 120, 194, 160, 11, 18, 63, 114, 93,
113, 249, 141, 115, 201, 97, 129, 103, 134, 141, 108, 102, 158, 56, 76, 44, 150, 122, 88, 233,
97, 86, 54, 52, 226, 105, 226, 168, 170, 233, 148, 47, 228, 92, 86, 57, 111, 113, 214, 170,
13, 214, 185, 39, 127, 97, 168, 160, 175, 44, 115, 157, 230, 24, 82, 88, 196, 18, 36, 136,
80, 208, 64, 5, 85, 88, 136, 211, 170, 147, 98, 34, 67, 251, 73, 15, 127, 196, 241, 75,
228, 82, 200, 85, 1, 35, 199, 2, 106, 208, 32, 59, 126, 240, 63, 248, 221, 173, 89, 156,
154, 116, 147, 66, 73, 160, 239, 197, 182, 63, 98, 64, 112, 23, 104, 55, 109, 251, 251, 216,
182, 219, 39, 128, 255, 25, 184, 210, 187, 254, 90, 11, 152, 253, 36, 189, 217, 213, 162, 71,
192, 208, 54, 112, 113, 221, 213, 148, 61, 224, 114, 7, 24, 125, 170, 203, 134, 236, 72, 126,
154, 66, 177, 8, 188, 159, 209, 55, 229, 129, 225, 91, 96, 96, 205, 237, 173, 179, 143, 211,
7, 32, 75, 93, 165, 111, 128, 131, 67, 96, 188, 68, 217, 235, 30, 239, 238, 239, 237, 237,
223, 51, 157, 254, 126, 0, 149, 74, 114, 180, 110, 138, 64, 17, 0, 0, 0, 6, 98, 75,
71, 68, 0, 0, 0, 0, 0, 0, 249, 67, 187, 127, 0, 0, 0, 9, 112, 72, 89, 115,
0, 0, 46, 35, 0, 0, 46, 35, 1, 120, 165, 63, 118, 0, 0, 0, 7, 116, 73, 77,
69, 7, 230, 12, 26, 22, 33, 46, 190, 127, 207, 43, 0, 0, 0, 25, 116, 69, 88, 116,
67, 111, 109, 109, 101, 110, 116, 0, 67, 114, 101, 97, 116, 101, 100, 32, 119, 105, 116, 104,
32, 71, 73, 77, 80, 87, 129, 14, 23, 0, 0, 32, 0, 73, 68, 65, 84, 120, 218, 237,
157, 231, 146, 35, 45, 211, 109, 19, 77, 221, 255, 29, 143, 248, 254, 156, 57, 161, 183, 30,
32, 13, 73, 217, 181, 34, 58, 90, 173, 150, 41, 3, 236, 157, 137, 43, 178, 150, 114, 226,
231, 148, 147, 143, 25, 0, 0, 174, 69, 61, 240, 125, 245, 2, 199, 125, 138, 216, 157, 37,
252, 229, 2, 231, 143, 129, 0, 0, 184, 150, 128, 103, 126, 102, 61, 233, 152, 211, 207, 253,
170, 2, 88, 46, 240, 90, 68, 29, 0, 128, 104, 255, 140, 215, 30, 98, 2, 178, 133, 173,
28, 248, 254, 114, 226, 103, 98, 28, 0, 0, 238, 25, 245, 175, 16, 237, 91, 26, 129, 76,
129, 58, 74, 252, 203, 129, 175, 65, 208, 1, 0, 158, 111, 24, 234, 129, 175, 185, 140, 9,
56, 115, 144, 94, 182, 240, 151, 131, 190, 7, 147, 0, 0, 112, 207, 108, 64, 150, 64, 215,
131, 190, 103, 233, 251, 207, 22, 187, 140, 72, 189, 220, 192, 20, 96, 26, 0, 0, 242, 163,
224, 179, 197, 62, 195, 8, 156, 102, 2, 142, 136, 220, 87, 8, 255, 138, 255, 121, 207, 9,
209, 6, 0, 184, 159, 153, 88, 37, 248, 117, 242, 248, 234, 65, 231, 63, 45, 98, 43, 197,
63, 34, 224, 217, 239, 137, 158, 35, 166, 0, 0, 224, 122, 153, 131, 168, 232, 215, 131, 222,
115, 138, 9, 56, 90, 228, 162, 162, 155, 241, 252, 81, 153, 1, 12, 1, 0, 192, 185, 130,
191, 34, 210, 247, 10, 126, 157, 56, 159, 67, 140, 192, 81, 11, 231, 100, 71, 253, 51, 207,
29, 157, 21, 192, 12, 0, 0, 28, 35, 250, 43, 162, 253, 58, 241, 220, 140, 17, 88, 110,
2, 174, 176, 136, 206, 108, 20, 95, 146, 205, 1, 25, 1, 0, 0, 34, 126, 203, 115, 171,
204, 193, 33, 38, 96, 245, 40, 248, 172, 190, 249, 136, 240, 175, 200, 28, 204, 92, 15, 196,
31, 0, 96, 157, 9, 136, 136, 105, 150, 240, 95, 213, 8, 212, 89, 81, 58, 83, 252, 51,
132, 63, 98, 20, 102, 51, 4, 8, 63, 0, 192, 177, 70, 32, 99, 192, 94, 246, 223, 214,
215, 156, 98, 2, 206, 72, 117, 175, 136, 240, 87, 152, 128, 50, 121, 77, 16, 126, 0, 128,
99, 141, 192, 76, 63, 254, 204, 223, 171, 51, 4, 75, 76, 64, 86, 148, 59, 99, 40, 102,
196, 186, 4, 94, 55, 99, 0, 86, 14, 18, 196, 64, 0, 0, 145, 252, 252, 103, 173, 136,
246, 173, 255, 203, 200, 24, 68, 179, 25, 167, 26, 128, 236, 168, 63, 34, 252, 71, 27, 130,
236, 235, 4, 0, 128, 81, 152, 127, 253, 108, 196, 31, 17, 252, 26, 252, 236, 72, 54, 32,
197, 4, 28, 33, 106, 153, 233, 253, 213, 143, 173, 102, 224, 232, 108, 0, 38, 2, 0, 222,
20, 229, 159, 17, 245, 31, 249, 216, 154, 13, 88, 106, 2, 34, 105, 238, 179, 197, 127, 246,
255, 51, 102, 32, 195, 52, 33, 222, 0, 0, 115, 162, 150, 21, 249, 71, 31, 71, 95, 235,
53, 5, 75, 77, 128, 53, 218, 61, 66, 252, 61, 143, 71, 207, 101, 155, 130, 136, 81, 98,
154, 32, 0, 192, 194, 232, 245, 64, 225, 31, 61, 55, 107, 14, 78, 53, 1, 101, 145, 104,
101, 136, 127, 84, 248, 103, 62, 235, 10, 70, 0, 99, 0, 0, 111, 22, 250, 51, 133, 63,
106, 0, 102, 62, 43, 250, 247, 180, 9, 40, 39, 136, 127, 79, 84, 103, 5, 127, 133, 73,
184, 146, 17, 192, 20, 0, 192, 211, 197, 126, 149, 240, 103, 71, 247, 214, 223, 51, 153, 129,
229, 38, 32, 106, 0, 50, 196, 223, 154, 1, 88, 245, 219, 243, 92, 212, 20, 172, 16, 108,
196, 31, 0, 222, 96, 2, 60, 98, 103, 253, 123, 54, 194, 207, 250, 125, 9, 19, 80, 46,
36, 254, 94, 19, 80, 18, 94, 107, 53, 8, 103, 25, 0, 196, 30, 0, 222, 106, 10, 178,
12, 192, 76, 148, 239, 17, 246, 85, 89, 129, 101, 38, 192, 107, 0, 86, 139, 127, 228, 183,
215, 28, 100, 152, 1, 143, 1, 96, 118, 0, 0, 64, 76, 164, 50, 167, 247, 121, 35, 126,
175, 200, 175, 204, 10, 44, 49, 1, 30, 3, 112, 5, 241, 247, 8, 255, 108, 214, 192, 146,
161, 176, 94, 3, 4, 127, 29, 92, 71, 184, 99, 116, 11, 190, 235, 24, 29, 236, 23, 77,
239, 107, 207, 101, 24, 6, 111, 86, 192, 99, 2, 78, 51, 0, 89, 226, 239, 17, 120, 239,
99, 175, 33, 176, 62, 206, 200, 4, 32, 108, 0, 240, 118, 163, 20, 137, 252, 189, 105, 127,
143, 200, 207, 60, 182, 154, 129, 195, 77, 128, 213, 0, 28, 37, 254, 51, 162, 175, 253, 109,
53, 5, 89, 70, 64, 19, 241, 59, 9, 60, 102, 4, 128, 236, 196, 89, 199, 170, 69, 255,
71, 10, 127, 244, 127, 86, 51, 112, 168, 9, 216, 110, 32, 254, 154, 232, 123, 141, 128, 119,
172, 192, 106, 35, 128, 200, 2, 0, 230, 100, 157, 240, 91, 34, 240, 150, 152, 151, 221, 255,
122, 127, 75, 231, 239, 222, 57, 149, 193, 115, 191, 223, 91, 6, 223, 213, 210, 143, 234, 120,
222, 100, 0, 34, 226, 175, 153, 130, 217, 40, 191, 247, 92, 134, 57, 200, 202, 6, 96, 4,
0, 0, 214, 8, 255, 17, 81, 127, 203, 4, 244, 140, 128, 245, 188, 123, 34, 47, 3, 241,
239, 153, 128, 150, 176, 187, 77, 192, 22, 184, 129, 214, 209, 240, 154, 248, 91, 140, 192, 72,
236, 181, 255, 89, 141, 130, 246, 24, 19, 0, 0, 240, 108, 241, 239, 25, 128, 150, 9, 232,
9, 111, 196, 16, 244, 196, 94, 130, 38, 192, 197, 150, 44, 66, 35, 193, 211, 140, 65, 36,
226, 207, 52, 6, 86, 99, 98, 49, 58, 24, 0, 0, 128, 227, 12, 64, 239, 57, 171, 248,
143, 12, 64, 43, 242, 31, 25, 2, 75, 22, 160, 103, 6, 122, 34, 111, 53, 1, 174, 44,
192, 230, 20, 160, 232, 122, 254, 71, 68, 251, 145, 31, 113, 102, 6, 60, 217, 0, 171, 33,
64, 248, 185, 38, 240, 110, 209, 227, 154, 216, 5, 63, 18, 245, 71, 35, 255, 168, 208, 143,
50, 2, 173, 174, 128, 222, 227, 104, 138, 223, 108, 2, 60, 93, 0, 103, 138, 255, 234, 31,
111, 70, 192, 98, 0, 86, 77, 15, 68, 28, 1, 224, 41, 38, 39, 107, 186, 95, 86, 186,
63, 235, 199, 115, 254, 154, 9, 240, 152, 1, 23, 219, 34, 65, 58, 82, 252, 63, 139, 13,
193, 138, 76, 0, 217, 0, 0, 192, 36, 140, 255, 191, 58, 242, 207, 248, 249, 6, 175, 69,
105, 156, 203, 40, 245, 191, 164, 43, 96, 11, 70, 169, 158, 109, 132, 179, 197, 255, 147, 244,
124, 102, 183, 192, 140, 17, 152, 17, 123, 76, 2, 0, 220, 53, 3, 48, 19, 253, 91, 250,
252, 51, 34, 255, 175, 34, 252, 159, 160, 33, 136, 76, 7, 76, 55, 1, 145, 117, 0, 188,
169, 255, 214, 227, 214, 223, 17, 225, 255, 56, 255, 214, 158, 23, 71, 70, 192, 123, 206, 86,
225, 126, 178, 168, 99, 88, 0, 214, 9, 234, 221, 207, 109, 117, 218, 95, 123, 190, 37, 246,
165, 243, 188, 24, 12, 193, 215, 120, 45, 202, 164, 9, 8, 179, 37, 53, 206, 222, 57, 254,
51, 194, 63, 250, 251, 19, 48, 3, 51, 89, 129, 25, 19, 224, 201, 158, 0, 0, 60, 213,
208, 68, 22, 252, 209, 196, 63, 18, 237, 151, 142, 25, 216, 155, 128, 111, 67, 232, 63, 13,
209, 255, 56, 140, 192, 168, 75, 192, 179, 8, 144, 43, 11, 224, 93, 8, 72, 75, 121, 143,
132, 48, 35, 221, 223, 18, 120, 235, 115, 217, 70, 224, 40, 19, 128, 17, 0, 128, 167, 102,
50, 86, 136, 255, 72, 248, 69, 250, 105, 253, 95, 225, 47, 141, 191, 191, 141, 207, 223, 139,
127, 207, 8, 204, 100, 3, 180, 113, 1, 81, 19, 240, 255, 51, 0, 25, 27, 213, 140, 230,
247, 123, 163, 126, 75, 100, 63, 122, 238, 35, 190, 236, 128, 167, 91, 64, 36, 62, 38, 128,
76, 0, 0, 96, 0, 108, 226, 223, 18, 121, 77, 240, 45, 89, 128, 79, 199, 4, 124, 141,
194, 223, 250, 190, 239, 78, 232, 63, 1, 19, 208, 50, 2, 158, 65, 129, 94, 138, 103, 33,
160, 232, 34, 63, 210, 17, 85, 73, 16, 255, 214, 111, 139, 9, 136, 102, 5, 44, 226, 79,
87, 0, 0, 192, 113, 169, 255, 200, 104, 255, 150, 9, 40, 29, 35, 80, 58, 191, 127, 51,
10, 159, 78, 54, 32, 98, 2, 122, 70, 32, 189, 43, 96, 19, 127, 10, 186, 56, 95, 219,
19, 60, 75, 151, 192, 94, 188, 189, 194, 63, 147, 17, 200, 234, 14, 208, 174, 223, 91, 7,
4, 114, 206, 128, 40, 114, 206, 25, 3, 255, 162, 83, 252, 74, 39, 250, 111, 137, 127, 235,
187, 255, 137, 188, 12, 178, 1, 123, 209, 47, 70, 193, 151, 78, 6, 64, 50, 179, 0, 222,
149, 0, 61, 209, 191, 53, 245, 47, 98, 27, 237, 175, 9, 188, 229, 177, 214, 77, 96, 53,
3, 158, 76, 128, 55, 27, 112, 164, 8, 34, 182, 0, 80, 79, 254, 158, 232, 214, 190, 17,
19, 240, 237, 100, 1, 180, 136, 191, 52, 12, 65, 203, 28, 180, 196, 255, 179, 123, 79, 235,
252, 75, 231, 26, 105, 93, 1, 50, 120, 94, 205, 2, 120, 167, 1, 106, 130, 53, 211, 231,
223, 139, 254, 61, 66, 175, 253, 237, 49, 2, 45, 67, 32, 11, 51, 1, 94, 81, 70, 188,
1, 224, 110, 38, 34, 106, 2, 102, 214, 244, 223, 139, 126, 107, 176, 95, 235, 247, 72, 240,
247, 199, 249, 155, 13, 104, 137, 255, 191, 246, 250, 211, 248, 140, 98, 184, 94, 189, 174, 128,
169, 85, 2, 163, 43, 1, 122, 231, 250, 183, 222, 175, 137, 190, 214, 5, 240, 81, 158, 27,
153, 129, 158, 41, 152, 93, 56, 72, 36, 182, 82, 160, 8, 93, 1, 156, 59, 16, 93, 191,
231, 220, 173, 253, 255, 25, 169, 255, 79, 195, 12, 124, 6, 66, 93, 27, 81, 255, 94, 252,
91, 231, 208, 51, 1, 101, 144, 5, 40, 206, 107, 233, 237, 10, 24, 102, 1, 60, 211, 0,
75, 224, 53, 25, 27, 251, 124, 58, 70, 192, 106, 2, 172, 102, 32, 106, 4, 68, 242, 103,
5, 204, 10, 31, 162, 9, 0, 87, 51, 51, 71, 140, 250, 215, 82, 255, 31, 37, 250, 223,
139, 126, 75, 248, 123, 207, 183, 76, 64, 105, 100, 1, 70, 154, 89, 149, 54, 221, 186, 21,
176, 41, 11, 96, 93, 10, 56, 18, 253, 207, 174, 243, 111, 21, 126, 203, 143, 150, 53, 152,
49, 1, 34, 177, 69, 130, 60, 102, 0, 97, 199, 0, 1, 209, 252, 83, 174, 147, 117, 183,
191, 172, 197, 126, 122, 163, 243, 123, 81, 127, 235, 239, 162, 8, 255, 222, 4, 148, 129, 17,
232, 101, 3, 70, 221, 1, 189, 40, 126, 42, 11, 96, 221, 13, 48, 18, 253, 107, 89, 1,
17, 251, 226, 63, 171, 126, 86, 152, 0, 17, 223, 160, 192, 222, 181, 35, 3, 0, 0, 79,
49, 64, 25, 155, 253, 68, 7, 253, 105, 226, 255, 49, 68, 253, 17, 190, 59, 29, 249, 14,
116, 161, 42, 217, 0, 109, 243, 160, 16, 91, 80, 148, 172, 209, 255, 204, 194, 63, 31, 37,
51, 208, 250, 249, 115, 49, 19, 160, 101, 1, 200, 0, 112, 174, 128, 120, 146, 1, 240, 71,
255, 43, 197, 223, 218, 245, 27, 53, 3, 154, 46, 212, 193, 115, 158, 44, 128, 58, 35, 32,
178, 25, 144, 39, 250, 247, 68, 254, 86, 177, 47, 70, 241, 247, 154, 129, 140, 129, 129, 34,
199, 45, 14, 132, 96, 2, 192, 93, 12, 205, 170, 69, 127, 172, 83, 254, 190, 63, 191, 127,
77, 128, 71, 252, 173, 231, 169, 105, 154, 55, 19, 48, 186, 158, 83, 89, 0, 207, 58, 0,
179, 209, 191, 229, 53, 214, 168, 191, 12, 196, 254, 79, 82, 70, 224, 104, 19, 160, 137, 248,
29, 5, 30, 83, 2, 240, 206, 236, 193, 236, 226, 63, 25, 226, 63, 138, 254, 163, 194, 175,
77, 217, 251, 4, 50, 1, 251, 168, 221, 122, 207, 181, 233, 128, 234, 107, 162, 123, 1, 120,
27, 249, 158, 32, 122, 162, 126, 75, 228, 255, 199, 96, 2, 254, 56, 50, 0, 209, 233, 129,
154, 9, 200, 204, 0, 32, 178, 0, 112, 117, 115, 50, 155, 1, 240, 174, 246, 183, 143, 254,
123, 169, 255, 253, 207, 95, 233, 47, 91, 47, 206, 115, 136, 234, 68, 47, 11, 160, 237, 26,
216, 50, 20, 67, 237, 136, 238, 6, 104, 157, 238, 55, 59, 19, 64, 91, 228, 231, 51, 16,
255, 104, 86, 192, 50, 38, 192, 99, 2, 60, 89, 128, 179, 87, 6, 36, 178, 7, 32, 83,
176, 250, 120, 50, 182, 250, 181, 26, 128, 125, 212, 175, 101, 0, 100, 208, 142, 203, 224, 88,
247, 207, 125, 12, 102, 64, 11, 20, 45, 11, 252, 120, 179, 0, 210, 202, 0, 104, 141, 251,
108, 132, 218, 139, 254, 45, 153, 0, 207, 108, 128, 63, 78, 51, 224, 49, 2, 163, 101, 131,
69, 230, 186, 2, 44, 127, 35, 196, 0, 112, 87, 227, 49, 51, 245, 79, 91, 241, 239, 43,
227, 244, 191, 39, 245, 47, 226, 239, 243, 255, 21, 253, 95, 241, 175, 242, 191, 211, 1, 235,
224, 187, 122, 131, 248, 100, 96, 6, 68, 17, 124, 117, 74, 224, 38, 115, 131, 205, 138, 18,
181, 70, 163, 127, 235, 10, 128, 150, 110, 128, 136, 25, 176, 102, 1, 62, 226, 223, 58, 88,
139, 250, 239, 144, 5, 192, 120, 0, 144, 1, 152, 141, 254, 45, 25, 0, 203, 220, 255, 111,
32, 250, 239, 165, 253, 37, 33, 250, 223, 27, 130, 178, 51, 2, 255, 248, 138, 158, 53, 214,
54, 9, 82, 163, 252, 17, 179, 219, 1, 203, 64, 224, 101, 16, 249, 90, 215, 1, 176, 172,
245, 175, 153, 0, 139, 17, 136, 204, 12, 232, 117, 11, 136, 204, 119, 5, 68, 178, 44, 0,
0, 87, 52, 28, 89, 203, 254, 246, 50, 1, 35, 3, 96, 141, 254, 255, 42, 162, 175, 29,
247, 254, 113, 47, 27, 48, 250, 25, 101, 1, 162, 219, 0, 15, 13, 130, 101, 37, 192, 168,
48, 69, 82, 255, 61, 241, 47, 98, 91, 238, 119, 111, 2, 44, 70, 160, 151, 13, 152, 89,
31, 64, 100, 205, 242, 192, 119, 23, 123, 140, 10, 192, 189, 34, 249, 204, 99, 95, 181, 236,
239, 126, 192, 223, 199, 16, 253, 255, 117, 4, 106, 189, 99, 111, 29, 211, 167, 241, 216, 147,
253, 30, 205, 227, 247, 92, 115, 83, 55, 192, 230, 188, 185, 90, 250, 223, 35, 130, 51, 59,
3, 106, 153, 128, 150, 17, 136, 142, 11, 88, 157, 5, 176, 100, 2, 86, 138, 39, 162, 12,
128, 217, 56, 234, 115, 163, 115, 255, 71, 209, 255, 39, 24, 253, 127, 59, 145, 191, 69, 248,
71, 199, 244, 233, 100, 2, 170, 216, 6, 200, 139, 204, 79, 11, 52, 97, 93, 7, 192, 154,
254, 183, 152, 5, 175, 224, 123, 103, 3, 180, 132, 223, 147, 9, 240, 174, 15, 224, 25, 11,
224, 49, 2, 17, 129, 70, 204, 1, 224, 74, 166, 97, 101, 250, 191, 37, 254, 222, 249, 254,
189, 182, 88, 20, 225, 239, 9, 126, 149, 255, 29, 252, 183, 31, 3, 80, 59, 66, 47, 210,
222, 135, 64, 12, 70, 192, 186, 81, 80, 119, 29, 0, 143, 248, 120, 55, 12, 202, 222, 20,
40, 186, 63, 128, 102, 4, 60, 131, 2, 163, 51, 2, 188, 6, 128, 153, 0, 100, 52, 224,
29, 17, 243, 147, 175, 71, 198, 210, 191, 173, 145, 255, 31, 177, 143, 252, 215, 6, 253, 181,
218, 142, 106, 200, 0, 212, 142, 200, 143, 140, 128, 150, 254, 247, 118, 5, 84, 37, 35, 208,
237, 6, 216, 130, 55, 221, 58, 242, 127, 198, 12, 68, 68, 255, 143, 242, 99, 237, 18, 136,
154, 128, 204, 53, 1, 44, 98, 246, 6, 177, 67, 208, 1, 195, 112, 239, 115, 204, 52, 0,
173, 168, 123, 47, 254, 150, 53, 254, 173, 131, 254, 246, 194, 255, 199, 144, 17, 40, 131, 168,
223, 98, 2, 68, 108, 187, 252, 137, 37, 202, 31, 225, 49, 0, 150, 197, 127, 196, 32, 114,
45, 209, 243, 110, 10, 20, 221, 253, 239, 207, 132, 1, 136, 238, 19, 96, 49, 70, 100, 0,
56, 71, 64, 252, 201, 0, 248, 87, 255, 235, 45, 249, 59, 147, 250, 183, 44, 52, 244, 17,
251, 162, 68, 163, 244, 127, 230, 140, 128, 148, 49, 0, 154, 88, 71, 140, 130, 37, 226, 247,
108, 10, 100, 53, 2, 214, 108, 128, 214, 21, 80, 20, 19, 48, 179, 38, 64, 134, 9, 64,
36, 185, 22, 128, 160, 95, 241, 90, 88, 196, 223, 34, 252, 34, 237, 145, 255, 45, 241, 239,
45, 245, 251, 87, 244, 57, 254, 163, 232, 127, 100, 0, 34, 59, 10, 142, 198, 207, 69, 102,
4, 84, 131, 25, 248, 207, 66, 64, 189, 15, 140, 52, 162, 145, 141, 130, 188, 230, 192, 187,
52, 176, 119, 76, 128, 101, 44, 128, 119, 137, 96, 79, 22, 96, 213, 253, 0, 0, 56, 202,
248, 84, 195, 115, 51, 209, 255, 103, 103, 4, 202, 46, 218, 254, 138, 127, 149, 191, 222, 119,
253, 17, 123, 23, 68, 203, 16, 104, 221, 0, 34, 227, 110, 0, 111, 132, 111, 221, 27, 160,
68, 198, 0, 140, 28, 75, 47, 234, 215, 62, 43, 50, 24, 208, 51, 35, 224, 227, 204, 2,
120, 87, 8, 204, 152, 13, 96, 205, 182, 176, 34, 32, 0, 92, 53, 51, 113, 196, 244, 191,
239, 78, 136, 247, 209, 191, 182, 246, 190, 231, 92, 44, 99, 14, 62, 3, 209, 175, 78, 241,
215, 140, 64, 201, 188, 223, 86, 3, 80, 20, 241, 150, 142, 248, 91, 133, 94, 22, 10, 255,
72, 208, 123, 227, 1, 178, 179, 0, 158, 12, 192, 236, 204, 139, 55, 128, 241, 0, 132, 248,
250, 231, 58, 51, 5, 112, 148, 1, 136, 70, 255, 34, 190, 126, 255, 63, 157, 199, 31, 25,
143, 63, 136, 238, 26, 219, 211, 216, 234, 48, 1, 203, 6, 1, 122, 26, 102, 205, 109, 89,
211, 255, 163, 8, 219, 186, 82, 224, 31, 209, 7, 2, 122, 150, 10, 142, 206, 6, 208, 76,
192, 157, 50, 0, 8, 48, 0, 6, 100, 85, 6, 192, 186, 251, 95, 217, 101, 1, 188, 209,
127, 85, 162, 254, 158, 216, 183, 178, 14, 31, 135, 9, 16, 99, 0, 60, 74, 227, 239, 23,
43, 106, 13, 16, 84, 205, 128, 182, 20, 176, 103, 0, 160, 38, 246, 154, 27, 139, 76, 17,
204, 200, 4, 120, 199, 2, 156, 49, 29, 48, 42, 186, 8, 53, 0, 156, 97, 44, 50, 23,
0, 210, 12, 64, 107, 254, 252, 72, 111, 70, 162, 255, 167, 99, 0, 246, 70, 224, 211, 48,
31, 30, 19, 96, 201, 2, 104, 131, 1, 67, 81, 191, 236, 150, 2, 206, 16, 27, 111, 255,
127, 180, 43, 96, 36, 254, 17, 67, 48, 50, 2, 51, 43, 3, 122, 179, 0, 154, 1, 160,
11, 0, 51, 3, 68, 227, 119, 59, 191, 172, 25, 0, 154, 1, 248, 21, 219, 175, 163, 253,
176, 12, 250, 251, 52, 126, 247, 162, 255, 189, 94, 125, 39, 179, 0, 51, 105, 126, 211, 64,
192, 200, 94, 0, 150, 44, 129, 214, 255, 47, 146, 187, 71, 192, 200, 16, 88, 6, 5, 106,
187, 10, 30, 105, 0, 34, 134, 236, 9, 226, 136, 192, 3, 6, 225, 89, 231, 48, 202, 2,
100, 26, 128, 81, 234, 191, 56, 142, 171, 26, 133, 191, 247, 56, 26, 253, 123, 179, 0, 145,
168, 191, 137, 197, 0, 120, 6, 0, 90, 26, 244, 34, 177, 129, 130, 150, 197, 130, 180, 199,
150, 232, 95, 51, 2, 150, 93, 2, 35, 55, 156, 21, 1, 49, 2, 128, 240, 63, 217, 0,
140, 50, 0, 222, 46, 128, 239, 79, 196, 255, 27, 249, 123, 196, 95, 75, 253, 127, 59, 98,
95, 12, 25, 0, 173, 235, 219, 170, 131, 35, 193, 119, 109, 253, 27, 53, 0, 222, 134, 91,
219, 4, 72, 58, 66, 56, 19, 253, 207, 136, 127, 75, 244, 45, 93, 1, 222, 177, 0, 34,
235, 103, 2, 188, 81, 64, 49, 12, 128, 160, 95, 239, 124, 87, 205, 0, 248, 21, 255, 186,
51, 1, 163, 46, 0, 45, 226, 247, 244, 243, 71, 197, 191, 56, 244, 177, 39, 232, 218, 218,
0, 174, 181, 3, 178, 12, 128, 55, 66, 45, 131, 76, 194, 168, 95, 196, 178, 21, 111, 134,
17, 24, 153, 131, 214, 98, 68, 71, 13, 4, 204, 20, 60, 132, 19, 0, 178, 141, 140, 103,
22, 64, 116, 0, 224, 63, 161, 175, 13, 225, 215, 22, 250, 17, 209, 151, 20, 238, 165, 253,
247, 98, 175, 253, 173, 117, 111, 139, 162, 127, 150, 217, 0, 251, 182, 60, 188, 20, 240, 236,
18, 192, 61, 33, 19, 71, 70, 32, 210, 37, 160, 237, 23, 16, 53, 5, 214, 217, 0, 214,
110, 0, 79, 70, 196, 42, 212, 87, 23, 113, 76, 6, 192, 243, 179, 12, 213, 241, 191, 222,
24, 128, 72, 6, 224, 43, 255, 221, 74, 247, 171, 68, 252, 214, 232, 255, 59, 16, 253, 143,
248, 231, 252, 91, 187, 5, 142, 108, 155, 235, 150, 244, 65, 35, 177, 215, 166, 99, 148, 164,
159, 143, 140, 183, 14, 142, 206, 18, 136, 174, 10, 120, 149, 169, 128, 8, 49, 0, 28, 105,
60, 86, 79, 1, 220, 247, 253, 91, 82, 255, 35, 3, 160, 205, 241, 47, 1, 209, 23, 241,
205, 136, 179, 232, 169, 119, 89, 96, 117, 208, 160, 101, 51, 32, 175, 32, 89, 187, 3, 180,
81, 143, 34, 241, 153, 2, 214, 141, 131, 102, 119, 23, 28, 69, 255, 159, 193, 49, 123, 197,
255, 169, 131, 0, 49, 38, 0, 247, 29, 71, 176, 106, 27, 224, 214, 50, 192, 223, 206, 243,
214, 12, 196, 104, 89, 225, 86, 223, 255, 55, 57, 218, 159, 13, 138, 179, 150, 5, 110, 110,
6, 148, 209, 120, 123, 230, 170, 143, 78, 54, 34, 248, 222, 61, 4, 178, 50, 6, 61, 3,
224, 221, 25, 176, 119, 109, 188, 134, 12, 33, 7, 192, 56, 92, 233, 88, 162, 93, 0, 251,
191, 203, 206, 4, 88, 12, 192, 191, 136, 94, 164, 191, 46, 191, 182, 155, 224, 140, 200, 71,
3, 94, 147, 120, 103, 16, 93, 7, 32, 50, 232, 207, 186, 227, 157, 22, 53, 103, 204, 26,
200, 136, 254, 61, 6, 64, 27, 3, 112, 245, 229, 128, 17, 120, 0, 12, 66, 134, 9, 176,
206, 255, 31, 101, 3, 60, 6, 224, 215, 8, 140, 198, 20, 140, 250, 253, 51, 34, 253, 145,
174, 137, 248, 54, 43, 178, 100, 1, 76, 102, 97, 51, 124, 145, 71, 32, 138, 193, 44, 104,
209, 191, 53, 83, 144, 97, 2, 180, 191, 71, 102, 97, 52, 6, 192, 155, 1, 184, 170, 1,
64, 248, 1, 48, 2, 103, 24, 128, 253, 82, 191, 35, 3, 240, 253, 137, 244, 165, 33, 250,
191, 219, 241, 238, 119, 245, 27, 45, 225, 59, 234, 54, 142, 238, 251, 98, 233, 54, 47, 78,
65, 15, 103, 6, 182, 131, 11, 162, 119, 150, 64, 84, 248, 71, 55, 109, 148, 242, 215, 102,
9, 88, 186, 10, 50, 7, 2, 94, 41, 11, 128, 41, 0, 184, 167, 216, 151, 131, 190, 183,
24, 158, 175, 187, 231, 247, 211, 218, 90, 81, 255, 63, 122, 35, 245, 69, 218, 75, 241, 202,
192, 88, 104, 105, 254, 222, 255, 178, 86, 125, 245, 142, 3, 208, 22, 1, 242, 172, 21, 144,
106, 0, 162, 130, 21, 217, 36, 72, 12, 159, 225, 217, 85, 240, 35, 190, 177, 3, 25, 51,
1, 68, 124, 187, 2, 106, 21, 248, 202, 130, 140, 89, 0, 56, 54, 130, 47, 39, 29, 155,
85, 252, 75, 67, 152, 101, 16, 245, 87, 233, 119, 5, 244, 162, 127, 105, 68, 252, 218, 220,
125, 107, 255, 191, 71, 119, 196, 152, 1, 176, 4, 199, 214, 76, 128, 171, 188, 28, 149, 1,
136, 236, 42, 104, 89, 23, 192, 243, 188, 69, 236, 173, 89, 131, 34, 190, 46, 128, 140, 213,
0, 223, 184, 18, 32, 6, 2, 222, 38, 224, 87, 175, 7, 213, 120, 108, 154, 248, 247, 118,
185, 27, 153, 128, 239, 79, 38, 96, 20, 253, 239, 51, 0, 251, 212, 255, 111, 38, 33, 186,
172, 175, 182, 228, 176, 103, 185, 223, 114, 214, 253, 94, 177, 20, 176, 37, 197, 225, 25, 13,
57, 51, 232, 194, 58, 16, 48, 186, 229, 176, 39, 163, 144, 217, 5, 176, 186, 128, 32, 188,
0, 207, 171, 79, 117, 241, 185, 212, 65, 52, 106, 17, 255, 34, 237, 212, 191, 252, 8, 127,
111, 196, 126, 207, 128, 180, 178, 0, 214, 29, 251, 188, 131, 248, 180, 5, 126, 60, 131, 231,
45, 227, 0, 166, 103, 5, 108, 147, 55, 188, 76, 22, 164, 104, 186, 68, 140, 55, 38, 210,
61, 224, 233, 42, 184, 82, 6, 128, 181, 0, 0, 222, 151, 29, 56, 171, 174, 105, 99, 13,
234, 192, 8, 140, 196, 95, 18, 51, 0, 117, 32, 254, 25, 163, 251, 173, 1, 170, 22, 252,
90, 2, 189, 244, 157, 0, 127, 13, 192, 17, 41, 8, 139, 11, 242, 100, 0, 122, 14, 203,
187, 231, 114, 246, 207, 71, 230, 198, 0, 92, 121, 16, 32, 98, 13, 112, 143, 58, 85, 15,
62, 238, 94, 215, 128, 39, 3, 160, 137, 219, 71, 254, 119, 205, 255, 35, 218, 115, 143, 182,
88, 117, 205, 186, 32, 208, 239, 107, 179, 178, 55, 255, 147, 65, 216, 46, 84, 152, 189, 3,
223, 172, 11, 7, 137, 193, 76, 204, 46, 57, 28, 237, 2, 240, 78, 3, 44, 23, 106, 96,
200, 42, 0, 209, 250, 243, 235, 64, 13, 124, 159, 37, 77, 29, 221, 227, 190, 55, 104, 79,
118, 6, 35, 67, 236, 101, 32, 244, 158, 189, 107, 86, 223, 231, 26, 253, 127, 214, 74, 128,
209, 221, 0, 181, 207, 138, 68, 255, 86, 177, 143, 24, 130, 79, 240, 245, 35, 7, 41, 146,
55, 8, 240, 206, 194, 135, 104, 195, 155, 202, 104, 189, 241, 57, 123, 214, 160, 23, 137, 47,
92, 243, 239, 185, 239, 32, 162, 222, 63, 206, 72, 249, 139, 33, 234, 239, 25, 129, 81, 192,
106, 9, 108, 15, 109, 11, 55, 99, 1, 47, 73, 149, 196, 226, 170, 196, 121, 65, 69, 230,
210, 253, 171, 210, 72, 214, 197, 128, 44, 6, 224, 9, 253, 255, 8, 60, 128, 189, 62, 212,
27, 28, 123, 56, 242, 116, 70, 182, 159, 157, 9, 200, 90, 50, 94, 196, 215, 151, 239, 205,
18, 136, 248, 6, 193, 103, 68, 252, 174, 207, 216, 22, 21, 222, 140, 134, 127, 148, 194, 215,
156, 149, 199, 201, 101, 45, 243, 88, 146, 10, 145, 55, 250, 103, 29, 0, 128, 103, 27, 132,
122, 225, 99, 172, 19, 175, 245, 102, 3, 44, 6, 32, 187, 109, 23, 227, 119, 137, 193, 12,
136, 162, 73, 158, 182, 51, 101, 92, 192, 182, 176, 96, 120, 79, 108, 36, 126, 30, 103, 85,
140, 199, 16, 93, 113, 208, 250, 30, 145, 120, 6, 0, 3, 0, 0, 79, 199, 179, 122, 160,
167, 189, 63, 106, 187, 94, 79, 87, 64, 100, 42, 160, 85, 244, 15, 89, 10, 120, 182, 127,
194, 35, 98, 22, 231, 164, 101, 0, 68, 41, 24, 154, 64, 143, 196, 94, 100, 222, 44, 104,
194, 255, 20, 19, 128, 33, 0, 240, 11, 227, 29, 234, 77, 149, 216, 66, 64, 158, 207, 174,
131, 182, 176, 53, 66, 222, 211, 246, 102, 100, 110, 139, 65, 159, 86, 104, 102, 10, 219, 73,
7, 84, 156, 143, 173, 175, 213, 82, 51, 22, 35, 33, 6, 243, 16, 17, 250, 149, 203, 1,
63, 69, 96, 49, 8, 240, 70, 129, 191, 91, 61, 168, 11, 142, 179, 37, 244, 163, 231, 60,
3, 253, 180, 182, 95, 20, 193, 246, 232, 142, 69, 191, 34, 107, 1, 68, 162, 124, 245, 61,
153, 123, 1, 148, 192, 251, 172, 131, 253, 138, 241, 38, 120, 50, 0, 214, 116, 190, 246, 154,
72, 118, 64, 130, 89, 128, 232, 117, 126, 11, 24, 8, 184, 130, 128, 63, 169, 156, 122, 55,
23, 106, 153, 3, 203, 50, 192, 94, 147, 48, 50, 1, 209, 118, 93, 6, 102, 96, 102, 247,
86, 111, 64, 87, 188, 66, 126, 84, 6, 224, 10, 141, 184, 85, 32, 35, 11, 52, 136, 196,
86, 112, 178, 246, 73, 105, 105, 42, 79, 161, 98, 75, 96, 0, 140, 230, 85, 204, 74, 47,
43, 208, 18, 255, 72, 102, 161, 245, 57, 69, 49, 40, 158, 238, 87, 111, 6, 32, 218, 46,
71, 103, 122, 77, 71, 251, 103, 26, 0, 207, 28, 200, 72, 97, 180, 12, 162, 243, 186, 192,
76, 55, 57, 114, 149, 214, 232, 255, 238, 99, 0, 48, 18, 0, 199, 138, 247, 234, 122, 87,
7, 223, 211, 91, 1, 208, 146, 5, 24, 137, 186, 165, 11, 96, 36, 230, 226, 204, 0, 88,
131, 77, 77, 111, 196, 16, 64, 30, 206, 118, 209, 130, 111, 73, 125, 107, 162, 47, 18, 27,
153, 233, 29, 201, 111, 113, 156, 214, 247, 120, 50, 28, 136, 47, 6, 3, 238, 45, 206, 119,
40, 211, 213, 121, 124, 209, 46, 0, 203, 184, 130, 209, 123, 60, 139, 194, 89, 131, 82, 79,
244, 127, 228, 189, 106, 93, 131, 91, 27, 0, 207, 128, 63, 107, 52, 172, 185, 50, 49, 186,
64, 237, 111, 239, 20, 190, 204, 105, 128, 229, 194, 247, 15, 0, 195, 249, 14, 19, 210, 203,
4, 120, 119, 2, 108, 125, 86, 29, 8, 95, 111, 22, 128, 85, 91, 44, 153, 93, 205, 4,
68, 183, 186, 95, 105, 12, 196, 106, 14, 182, 139, 21, 112, 45, 13, 99, 185, 145, 214, 44,
192, 204, 242, 140, 158, 12, 128, 39, 107, 48, 99, 124, 222, 34, 204, 152, 13, 120, 123, 102,
224, 232, 186, 224, 157, 181, 48, 187, 19, 96, 43, 115, 96, 201, 0, 104, 109, 182, 87, 140,
35, 3, 252, 74, 210, 61, 61, 228, 222, 30, 177, 25, 80, 246, 78, 131, 101, 225, 69, 204,
26, 39, 96, 249, 142, 140, 12, 192, 213, 4, 17, 113, 6, 50, 3, 207, 50, 25, 150, 115,
202, 216, 9, 208, 179, 188, 112, 47, 3, 160, 181, 217, 150, 126, 125, 143, 166, 149, 139, 149,
139, 211, 13, 192, 145, 21, 198, 42, 158, 61, 113, 23, 199, 251, 102, 178, 4, 87, 24, 3,
240, 86, 113, 198, 144, 192, 29, 5, 247, 110, 38, 99, 180, 19, 224, 76, 6, 160, 151, 85,
208, 250, 191, 189, 35, 245, 181, 65, 123, 153, 217, 130, 163, 202, 134, 233, 254, 109, 23, 44,
192, 89, 209, 110, 116, 81, 33, 237, 239, 200, 88, 2, 237, 123, 51, 210, 255, 172, 6, 8,
112, 255, 50, 91, 111, 114, 206, 154, 248, 106, 187, 1, 122, 183, 3, 110, 101, 17, 44, 237,
177, 40, 209, 255, 236, 248, 42, 111, 192, 121, 169, 118, 112, 59, 185, 128, 29, 181, 169, 144,
245, 127, 150, 77, 30, 188, 199, 21, 153, 87, 122, 165, 117, 0, 16, 111, 128, 123, 213, 177,
51, 6, 7, 90, 186, 1, 70, 81, 124, 81, 178, 7, 189, 99, 208, 150, 77, 142, 164, 253,
189, 193, 218, 109, 219, 208, 237, 192, 194, 90, 22, 124, 86, 73, 184, 57, 171, 187, 0, 188,
5, 145, 105, 128, 152, 19, 184, 62, 245, 5, 117, 33, 210, 13, 48, 218, 241, 207, 178, 153,
205, 104, 252, 64, 207, 60, 172, 104, 211, 87, 104, 220, 153, 109, 88, 243, 122, 109, 23, 45,
136, 101, 225, 231, 148, 164, 27, 149, 209, 141, 241, 246, 189, 0, 16, 109, 192, 112, 94, 123,
187, 95, 239, 241, 174, 236, 2, 168, 193, 246, 216, 211, 166, 71, 62, 107, 85, 54, 160, 56,
175, 195, 225, 25, 128, 59, 53, 234, 51, 166, 194, 179, 121, 81, 89, 112, 227, 153, 5, 0,
128, 153, 184, 138, 97, 40, 134, 99, 41, 50, 158, 211, 31, 17, 54, 205, 52, 204, 140, 235,
242, 156, 247, 161, 83, 245, 86, 178, 93, 188, 82, 88, 251, 225, 103, 69, 200, 178, 30, 180,
136, 63, 37, 111, 93, 10, 114, 244, 57, 103, 141, 1, 64, 204, 1, 158, 147, 125, 168, 139,
143, 197, 179, 79, 189, 39, 141, 239, 49, 25, 90, 27, 237, 105, 191, 51, 198, 13, 96, 0,
46, 18, 225, 151, 192, 123, 102, 156, 97, 239, 179, 206, 26, 3, 240, 70, 65, 199, 192, 64,
38, 245, 101, 245, 161, 6, 63, 63, 123, 12, 64, 239, 51, 172, 169, 240, 114, 161, 118, 225,
114, 109, 210, 246, 128, 2, 125, 197, 93, 241, 86, 245, 33, 149, 187, 22, 52, 4, 28, 94,
94, 30, 235, 3, 206, 215, 42, 184, 153, 175, 139, 188, 62, 75, 27, 202, 129, 215, 249, 148,
246, 110, 187, 112, 133, 57, 234, 56, 178, 230, 131, 70, 142, 167, 4, 255, 247, 4, 193, 68,
224, 1, 3, 113, 47, 131, 80, 140, 199, 91, 12, 17, 188, 39, 67, 112, 7, 209, 157, 89,
8, 232, 246, 187, 1, 94, 41, 205, 114, 84, 69, 32, 181, 132, 200, 3, 28, 81, 87, 234,
69, 143, 183, 94, 228, 187, 143, 216, 82, 247, 113, 3, 0, 87, 103, 0, 158, 42, 40, 25,
125, 244, 89, 179, 0, 216, 13, 16, 224, 189, 230, 224, 42, 179, 1, 44, 3, 0, 51, 103,
1, 200, 32, 131, 144, 25, 212, 173, 106, 251, 46, 147, 205, 189, 218, 118, 192, 101, 113, 133,
17, 185, 222, 66, 58, 119, 26, 212, 135, 208, 3, 96, 12, 178, 178, 1, 43, 179, 8, 103,
175, 65, 67, 6, 224, 130, 2, 181, 186, 239, 103, 198, 89, 178, 228, 47, 0, 188, 193, 24,
88, 163, 125, 237, 152, 35, 3, 3, 105, 239, 30, 108, 0, 50, 93, 96, 198, 20, 188, 217,
149, 253, 142, 40, 176, 136, 61, 192, 123, 141, 65, 77, 252, 236, 154, 244, 222, 153, 129, 129,
214, 117, 0, 86, 27, 130, 85, 171, 217, 98, 0, 146, 46, 146, 119, 243, 157, 163, 110, 214,
234, 254, 161, 183, 10, 62, 70, 7, 60, 212, 23, 215, 139, 44, 33, 207, 52, 9, 153, 159,
1, 47, 201, 0, 156, 41, 0, 217, 25, 4, 196, 15, 113, 135, 107, 149, 169, 250, 240, 115,
175, 73, 159, 53, 59, 223, 127, 54, 187, 0, 24, 128, 165, 133, 135, 105, 120, 156, 19, 208,
62, 60, 205, 20, 148, 11, 159, 19, 153, 128, 23, 27, 128, 71, 205, 197, 92, 36, 126, 229,
165, 231, 13, 112, 149, 178, 90, 31, 116, 78, 117, 193, 107, 175, 208, 150, 188, 186, 109, 33,
3, 128, 81, 224, 28, 0, 48, 3, 68, 220, 47, 228, 67, 5, 189, 132, 232, 48, 170, 255,
127, 143, 31, 241, 135, 39, 182, 53, 79, 168, 155, 111, 105, 167, 202, 27, 142, 233, 67, 189,
60, 252, 70, 33, 110, 8, 63, 80, 206, 97, 93, 187, 89, 78, 56, 62, 50, 0, 47, 46,
156, 87, 49, 10, 229, 166, 215, 149, 6, 17, 48, 2, 207, 109, 7, 223, 18, 16, 221, 238,
92, 48, 0, 100, 14, 168, 48, 0, 212, 1, 218, 177, 23, 222, 91, 12, 0, 80, 57, 0,
168, 11, 212, 221, 117, 231, 123, 217, 235, 133, 1, 160, 144, 114, 172, 0, 212, 9, 174, 233,
11, 193, 0, 0, 149, 18, 128, 186, 1, 47, 188, 79, 24, 0, 42, 37, 215, 18, 128, 58,
2, 100, 0, 168, 24, 0, 0, 180, 117, 180, 199, 24, 0, 42, 20, 231, 199, 61, 0, 0,
192, 0, 0, 32, 254, 0, 212, 25, 192, 0, 0, 208, 144, 1, 80, 119, 0, 3, 0, 0,
0, 0, 119, 49, 113, 24, 0, 32, 130, 1, 160, 14, 1, 25, 0, 184, 97, 69, 45, 92,
15, 0, 218, 22, 218, 60, 202, 6, 6, 128, 155, 12, 0, 240, 166, 54, 139, 246, 17, 3,
128, 40, 115, 109, 0, 168, 83, 0, 24, 0, 42, 51, 231, 6, 64, 221, 122, 203, 185, 21,
238, 199, 245, 13, 64, 161, 176, 210, 64, 1, 0, 117, 140, 107, 72, 6, 0, 168, 84, 0,
64, 93, 59, 227, 188, 95, 223, 102, 97, 0, 174, 89, 72, 11, 5, 24, 0, 30, 212, 222,
209, 125, 129, 1, 224, 198, 115, 29, 0, 128, 58, 199, 117, 192, 0, 172, 45, 16, 133, 130,
68, 5, 4, 160, 238, 1, 144, 1, 0, 26, 32, 0, 234, 32, 0, 6, 128, 10, 196, 117,
3, 160, 46, 2, 6, 0, 128, 6, 7, 128, 58, 201, 53, 120, 209, 53, 197, 0, 220, 183,
144, 177, 14, 55, 0, 220, 185, 77, 160, 45, 57, 153, 141, 75, 0, 84, 86, 128, 199, 213,
211, 202, 165, 0, 50, 0, 247, 23, 216, 114, 225, 99, 3, 0, 12, 251, 29, 219, 52, 192,
0, 0, 226, 15, 64, 221, 5, 12, 0, 0, 13, 8, 192, 243, 234, 48, 245, 24, 48, 0,
64, 163, 1, 128, 153, 127, 197, 57, 209, 126, 189, 204, 0, 148, 139, 22, 180, 21, 98, 90,
110, 122, 29, 1, 224, 125, 109, 36, 65, 200, 69, 97, 22, 0, 32, 252, 0, 239, 171, 231,
204, 18, 0, 186, 0, 0, 241, 7, 160, 206, 115, 44, 24, 0, 56, 178, 96, 23, 42, 31,
0, 156, 92, 247, 203, 13, 142, 17, 22, 177, 189, 224, 134, 35, 180, 84, 44, 174, 15, 144,
242, 30, 151, 245, 202, 241, 188, 175, 45, 98, 12, 192, 59, 133, 7, 113, 227, 58, 112, 175,
49, 7, 71, 139, 46, 194, 78, 6, 0, 16, 61, 206, 29, 46, 93, 46, 234, 139, 175, 67,
61, 241, 253, 128, 1, 128, 133, 34, 86, 184, 86, 0, 24, 130, 7, 139, 56, 117, 222, 1,
131, 0, 175, 93, 184, 10, 21, 35, 124, 174, 52, 4, 64, 121, 162, 221, 1, 50, 0, 175,
119, 159, 133, 107, 15, 144, 90, 198, 234, 11, 206, 181, 62, 232, 184, 74, 210, 107, 48, 0,
0, 8, 63, 80, 238, 94, 97, 4, 222, 210, 70, 188, 178, 29, 161, 11, 96, 93, 97, 96,
250, 33, 231, 6, 180, 21, 156, 27, 215, 24, 3, 0, 20, 228, 228, 235, 200, 181, 4, 202,
35, 109, 36, 188, 192, 0, 20, 10, 34, 149, 137, 6, 2, 40, 155, 156, 19, 101, 139, 12,
0, 80, 9, 0, 40, 163, 0, 47, 55, 0, 76, 207, 121, 254, 117, 33, 197, 10, 148, 87,
218, 29, 244, 4, 3, 64, 161, 225, 218, 2, 80, 118, 185, 182, 83, 239, 41, 220, 203, 107,
24, 128, 163, 111, 4, 149, 146, 6, 20, 128, 50, 76, 93, 124, 61, 31, 42, 37, 231, 199,
57, 0, 80, 150, 1, 3, 0, 84, 86, 0, 0, 218, 124, 12, 0, 0, 21, 18, 128, 50,
13, 79, 188, 207, 24, 128, 231, 21, 26, 70, 225, 2, 80, 182, 105, 167, 0, 3, 64, 97,
228, 62, 0, 80, 198, 185, 222, 128, 1, 0, 0, 0, 192, 80, 96, 0, 128, 138, 5, 64,
89, 7, 50, 0, 20, 120, 42, 42, 215, 25, 128, 50, 15, 24, 0, 160, 81, 1, 0, 160,
141, 193, 0, 192, 209, 149, 169, 112, 13, 0, 40, 251, 180, 115, 128, 1, 160, 210, 3, 0,
208, 54, 2, 6, 128, 2, 6, 0, 64, 219, 141, 102, 188, 211, 0, 92, 121, 83, 32, 140,
6, 215, 9, 128, 58, 0, 24, 0, 160, 161, 0, 0, 218, 42, 192, 0, 0, 21, 135, 70,
2, 128, 122, 15, 24, 0, 0, 0, 0, 192, 0, 0, 0, 0, 81, 60, 96, 0, 128, 74,
9, 0, 0, 24, 0, 192, 172, 0, 80, 39, 128, 251, 141, 1, 0, 0, 0, 0, 12, 0,
0, 0, 0, 96, 0, 0, 0, 0, 0, 3, 0, 215, 128, 190, 78, 0, 234, 6, 96, 0,
0, 0, 0, 0, 3, 0, 0, 0, 240, 92, 46, 149, 229, 193, 0, 0, 0, 0, 144, 1,
0, 0, 0, 0, 12, 0, 0, 0, 0, 96, 0, 0, 0, 0, 30, 206, 107, 102, 99, 96,
0, 128, 138, 5, 64, 29, 1, 50, 0, 0, 0, 0, 128, 1, 0, 0, 0, 0, 12, 0,
0, 0, 0, 96, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 24, 0, 0, 0, 0, 192,
0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 48, 0, 0, 0, 0, 128, 1, 0, 0, 0,
0, 12, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 24, 0, 0,
0, 0, 192, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 48, 0, 0, 0, 0, 24, 0,
0, 0, 0, 192, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 48, 0, 0, 0, 0, 128,
1, 0, 0, 0, 0, 12, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 3, 0, 0, 0,
0, 24, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 48, 0, 0,
0, 0, 128, 1, 0, 0, 0, 0, 12, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 3,
0, 0, 0, 0, 24, 0, 0, 0, 0, 12, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0,
3, 0, 0, 0, 0, 24, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 6, 0, 0, 0,
0, 48, 0, 0, 0, 0, 128, 1, 0, 0, 0, 0, 12, 0, 0, 0, 0, 96, 0, 0,
0, 0, 0, 3, 0, 0, 0, 0, 24, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 6,
0, 0, 0, 0, 48, 0, 0, 0, 0, 128, 1, 0, 0, 0, 0, 12, 0, 0, 0, 0,
6, 0, 0, 0, 0, 48, 0, 0, 0, 0, 128, 1, 0, 0, 0, 0, 12, 0, 0, 0,
0, 96, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 24, 0, 0, 0, 0, 192, 0, 0,
0, 0, 0, 6, 0, 0, 0, 0, 48, 0, 0, 0, 0, 128, 1, 0, 0, 0, 0, 12,
0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 24, 0, 0, 0, 0,
192, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 3, 0, 0, 0, 0, 24, 0, 0, 0,
0, 192, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 48, 0, 0, 0, 0, 128, 1, 0,
0, 0, 0, 12, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 24,
0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 48, 0, 0, 0, 0,
128, 1, 0, 0, 0, 0, 12, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 3, 0, 0,
0, 0, 24, 0, 0, 0, 0, 12, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 3, 0,
0, 0, 0, 24, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 48,
0, 0, 0, 0, 128, 1, 0, 0, 0, 0, 12, 0, 0, 0, 0, 96, 0, 0, 0, 0,
0, 3, 0, 0, 0, 0, 24, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 6, 0, 0,
0, 0, 48, 0, 0, 0, 0, 128, 1, 0, 0, 0, 0, 12, 0, 0, 0, 0, 6, 0,
0, 0, 0, 48, 0, 0, 0, 0, 128, 1, 0, 0, 0, 0, 12, 0, 0, 0, 0, 96,
0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 24, 0, 0, 0, 0, 192, 0, 0, 0, 0,
0, 6, 0, 0, 0, 0, 48, 0, 0, 0, 0, 128, 1, 0, 0, 0, 0, 12, 0, 0,
0, 0, 96, 0, 224, 94, 84, 46, 1, 0, 117, 4, 48, 0, 0, 0, 0, 152, 48, 12,
0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 24, 0, 0, 0, 128,
187, 113, 169, 241, 5, 24, 0, 0, 0, 0, 50, 0, 0, 239, 114, 192, 0, 212, 13, 192,
0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 48, 0, 0, 0, 0, 128, 1, 0, 152, 130,
190, 78, 0, 234, 4, 247, 27, 3, 0, 52, 32, 0, 0, 128, 1, 0, 0, 0, 130, 13,
192, 0, 0, 0, 0, 0, 6, 0, 103, 205, 185, 2, 80, 23, 56, 87, 192, 0, 208, 72,
0, 0, 208, 86, 193, 219, 12, 64, 189, 112, 33, 165, 2, 112, 157, 0, 168, 3, 128, 1,
160, 178, 1, 0, 192, 13, 219, 238, 71, 107, 6, 93, 0, 20, 40, 0, 0, 218, 70, 50,
0, 112, 161, 2, 95, 185, 6, 0, 148, 125, 218, 57, 192, 0, 0, 13, 10, 0, 208, 198,
192, 237, 12, 64, 165, 176, 3, 215, 25, 128, 50, 15, 100, 0, 0, 104, 16, 129, 178, 14,
128, 1, 0, 0, 0, 192, 188, 97, 0, 184, 169, 220, 7, 0, 202, 56, 112, 189, 49, 0,
20, 210, 87, 21, 120, 42, 44, 80, 207, 105, 167, 0, 3, 0, 52, 148, 0, 148, 105, 224,
62, 99, 0, 184, 129, 0, 0, 64, 155, 143, 1, 224, 134, 63, 250, 252, 48, 98, 64, 125,
4, 120, 184, 1, 168, 7, 87, 38, 42, 35, 13, 39, 0, 101, 152, 186, 136, 1, 224, 18,
80, 57, 184, 182, 0, 148, 221, 23, 92, 219, 122, 98, 224, 137, 1, 160, 146, 29, 122, 174,
245, 97, 231, 77, 99, 10, 148, 87, 218, 29, 244, 4, 3, 0, 184, 126, 0, 202, 40, 192,
27, 12, 64, 165, 34, 211, 24, 209, 192, 2, 101, 147, 115, 162, 108, 145, 1, 224, 38, 114,
29, 185, 150, 64, 121, 164, 141, 4, 12, 192, 37, 11, 97, 165, 66, 113, 110, 64, 91, 193,
185, 113, 141, 175, 202, 198, 37, 128, 135, 52, 82, 133, 75, 1, 136, 18, 4, 239, 213, 43,
239, 39, 6, 32, 191, 160, 21, 142, 235, 244, 74, 142, 25, 0, 68, 255, 153, 231, 90, 23,
190, 239, 117, 38, 128, 46, 128, 107, 87, 10, 54, 223, 136, 159, 43, 17, 26, 80, 158, 104,
119, 128, 12, 192, 227, 42, 103, 57, 225, 189, 79, 104, 200, 200, 12, 0, 162, 245, 236, 115,
199, 112, 96, 0, 0, 19, 128, 33, 0, 68, 227, 224, 235, 192, 117, 196, 0, 192, 13, 4,
250, 205, 38, 192, 218, 96, 113, 125, 16, 29, 193, 190, 48, 0, 0, 26, 30, 73, 68, 65,
84, 55, 174, 15, 247, 0, 3, 112, 243, 130, 120, 165, 169, 44, 229, 98, 215, 25, 145, 163,
177, 2, 168, 28, 207, 59, 239, 15, 131, 0, 223, 93, 144, 25, 44, 7, 240, 238, 246, 233,
14, 109, 20, 96, 0, 48, 7, 84, 50, 0, 160, 253, 129, 44, 24, 3, 0, 251, 74, 72,
183, 0, 0, 194, 15, 100, 0, 40, 216, 134, 207, 174, 134, 247, 214, 135, 156, 43, 0, 208,
70, 30, 241, 217, 116, 79, 98, 0, 224, 196, 134, 130, 202, 7, 128, 248, 223, 245, 156, 104,
191, 48, 0, 64, 163, 1, 128, 153, 231, 50, 0, 6, 0, 48, 1, 0, 212, 93, 0, 12,
192, 77, 42, 107, 189, 240, 177, 1, 0, 226, 79, 123, 130, 1, 128, 23, 52, 40, 84, 92,
0, 196, 31, 161, 199, 0, 80, 185, 78, 254, 188, 74, 165, 6, 128, 11, 152, 244, 187, 181,
97, 128, 1, 0, 76, 0, 0, 117, 146, 107, 240, 222, 107, 138, 1, 160, 226, 112, 221, 0,
168, 139, 64, 6, 0, 128, 134, 7, 128, 58, 8, 24, 128, 123, 87, 136, 74, 69, 162, 1,
2, 160, 238, 1, 144, 1, 160, 2, 114, 29, 0, 128, 182, 7, 48, 0, 143, 40, 212, 20,
126, 0, 218, 8, 218, 42, 238, 5, 6, 128, 194, 192, 121, 3, 80, 215, 56, 111, 174, 227,
53, 13, 64, 165, 32, 82, 65, 1, 128, 58, 198, 53, 36, 3, 64, 1, 228, 220, 0, 128,
186, 85, 111, 120, 109, 110, 127, 63, 48, 0, 84, 70, 0, 0, 32, 3, 0, 152, 13, 204,
17, 0, 117, 234, 86, 199, 75, 123, 131, 1, 120, 109, 5, 173, 92, 15, 0, 218, 22, 218,
60, 202, 6, 6, 0, 104, 32, 0, 168, 67, 0, 24, 0, 0, 0, 0, 192, 0, 0, 17,
12, 0, 117, 7, 184, 135, 24, 0, 160, 18, 0, 80, 103, 128, 12, 0, 149, 137, 243, 3,
0, 0, 12, 0, 34, 7, 220, 63, 0, 234, 10, 245, 25, 3, 64, 101, 4, 174, 37, 0,
117, 4, 48, 0, 0, 52, 112, 0, 212, 13, 238, 19, 6, 0, 128, 134, 14, 128, 58, 193,
53, 197, 0, 0, 133, 157, 202, 9, 64, 221, 229, 254, 92, 249, 122, 97, 0, 238, 83, 208,
42, 21, 11, 128, 58, 64, 59, 198, 189, 197, 0, 60, 255, 102, 214, 39, 22, 184, 206, 49,
99, 4, 224, 141, 237, 201, 93, 235, 43, 38, 231, 33, 231, 137, 1, 56, 215, 1, 35, 124,
24, 1, 160, 156, 211, 86, 230, 102, 14, 234, 1, 199, 250, 8, 62, 20, 190, 75, 220, 224,
74, 33, 165, 129, 4, 132, 159, 8, 151, 115, 61, 242, 152, 200, 0, 80, 120, 105, 48, 1,
40, 199, 71, 183, 41, 212, 237, 11, 176, 221, 188, 48, 190, 113, 52, 106, 89, 240, 218, 59,
53, 60, 133, 106, 11, 152, 239, 203, 158, 83, 189, 217, 185, 188, 218, 136, 108, 212, 215, 148,
194, 124, 85, 177, 173, 15, 20, 205, 214, 61, 193, 20, 0, 98, 255, 174, 243, 35, 131, 128,
1, 184, 116, 129, 105, 153, 2, 175, 81, 200, 50, 22, 79, 52, 2, 158, 123, 139, 65, 0,
68, 230, 156, 243, 174, 9, 175, 175, 220, 67, 12, 64, 246, 77, 174, 134, 199, 25, 162, 159,
253, 25, 51, 223, 241, 214, 116, 58, 141, 0, 192, 250, 250, 81, 15, 248, 30, 234, 50, 6,
96, 121, 97, 169, 73, 78, 244, 87, 172, 247, 194, 61, 43, 228, 101, 225, 245, 33, 98, 6,
160, 61, 60, 235, 184, 102, 2, 178, 81, 187, 189, 98, 202, 97, 228, 156, 46, 115, 207, 182,
151, 21, 240, 21, 131, 7, 45, 17, 251, 140, 168, 158, 49, 190, 0, 99, 0, 128, 208, 103,
9, 111, 102, 16, 182, 226, 154, 188, 54, 171, 176, 93, 172, 192, 214, 139, 222, 236, 186, 248,
220, 139, 156, 55, 62, 0, 99, 0, 128, 208, 31, 121, 28, 89, 237, 253, 10, 81, 127, 213,
44, 129, 141, 2, 63, 117, 12, 209, 129, 126, 222, 126, 254, 222, 235, 175, 50, 184, 15, 99,
0, 240, 124, 161, 247, 28, 155, 87, 72, 107, 240, 187, 50, 199, 111, 29, 21, 28, 214, 171,
220, 239, 45, 177, 16, 148, 183, 184, 166, 159, 194, 146, 213, 167, 159, 125, 253, 175, 222, 56,
96, 12, 0, 238, 37, 244, 87, 58, 214, 154, 36, 222, 145, 239, 124, 212, 26, 52, 219, 11,
10, 243, 236, 184, 128, 21, 43, 96, 89, 6, 6, 122, 13, 70, 189, 145, 192, 90, 174, 41,
38, 1, 16, 247, 123, 158, 131, 103, 80, 223, 25, 123, 163, 172, 26, 11, 22, 61, 143, 211,
202, 198, 246, 128, 194, 88, 47, 88, 129, 87, 245, 231, 123, 94, 119, 119, 65, 157, 189, 175,
24, 8, 64, 192, 143, 63, 223, 186, 232, 243, 35, 171, 17, 214, 27, 220, 243, 83, 51, 10,
219, 131, 11, 172, 197, 145, 85, 231, 223, 154, 48, 107, 17, 188, 12, 254, 111, 201, 2, 180,
62, 103, 85, 97, 46, 15, 43, 15, 0, 24, 152, 227, 63, 191, 6, 94, 99, 105, 203, 51,
178, 17, 175, 111, 147, 182, 139, 23, 216, 42, 107, 6, 147, 88, 10, 160, 117, 90, 203, 40,
42, 183, 164, 229, 181, 89, 0, 103, 13, 0, 140, 92, 71, 162, 110, 128, 119, 137, 73, 100,
36, 126, 53, 190, 183, 6, 62, 191, 58, 191, 111, 198, 184, 220, 62, 240, 216, 22, 21, 136,
59, 12, 72, 139, 222, 212, 170, 68, 235, 71, 206, 2, 176, 154, 140, 171, 54, 74, 24, 6,
128, 251, 101, 171, 34, 35, 246, 143, 158, 5, 224, 201, 238, 122, 179, 9, 143, 25, 8, 184,
93, 180, 96, 215, 133, 159, 147, 49, 98, 180, 26, 68, 217, 242, 191, 189, 105, 240, 116, 33,
120, 174, 119, 185, 113, 67, 130, 153, 0, 68, 251, 62, 231, 104, 21, 233, 153, 213, 249, 86,
204, 2, 168, 19, 250, 176, 106, 188, 68, 93, 93, 238, 182, 132, 139, 86, 22, 158, 108, 212,
145, 101, 14, 24, 177, 166, 171, 90, 2, 46, 202, 223, 71, 141, 1, 200, 42, 52, 87, 22,
89, 250, 252, 1, 206, 171, 11, 171, 198, 0, 84, 241, 143, 1, 200, 104, 211, 35, 215, 242,
202, 131, 14, 235, 25, 25, 0, 139, 227, 138, 156, 64, 214, 77, 25, 57, 73, 235, 248, 131,
200, 82, 192, 90, 215, 193, 200, 72, 244, 142, 165, 220, 164, 97, 33, 82, 7, 184, 191, 145,
245, 6, 116, 154, 136, 71, 162, 250, 106, 252, 222, 12, 237, 200, 74, 255, 95, 234, 254, 110,
23, 44, 60, 89, 203, 59, 86, 71, 65, 241, 246, 23, 253, 254, 180, 132, 124, 36, 116, 171,
186, 0, 238, 178, 37, 238, 145, 21, 0, 179, 1, 111, 18, 229, 43, 156, 243, 202, 46, 128,
106, 104, 143, 189, 70, 96, 118, 253, 151, 170, 28, 111, 214, 198, 114, 143, 50, 0, 153, 5,
173, 58, 110, 104, 157, 40, 8, 209, 46, 128, 158, 40, 245, 196, 95, 139, 254, 163, 145, 255,
17, 5, 238, 106, 130, 75, 183, 0, 32, 206, 231, 29, 79, 13, 180, 217, 181, 243, 227, 109,
143, 189, 199, 53, 18, 108, 207, 119, 158, 125, 127, 92, 153, 245, 109, 193, 151, 23, 99, 33,
88, 89, 248, 163, 105, 154, 94, 65, 168, 3, 23, 57, 18, 240, 209, 177, 21, 197, 4, 136,
232, 221, 0, 218, 57, 150, 7, 54, 76, 68, 245, 128, 56, 95, 251, 188, 60, 233, 255, 234,
16, 46, 107, 123, 220, 123, 77, 164, 59, 192, 59, 173, 240, 86, 229, 98, 115, 138, 249, 209,
133, 204, 58, 15, 84, 155, 231, 169, 61, 239, 117, 147, 163, 244, 127, 145, 255, 78, 205, 171,
73, 25, 0, 111, 244, 127, 84, 161, 43, 23, 109, 136, 0, 48, 27, 247, 205, 0, 136, 18,
140, 137, 34, 236, 213, 113, 44, 51, 81, 125, 102, 244, 127, 232, 20, 195, 237, 194, 5, 200,
211, 71, 111, 185, 128, 150, 148, 146, 119, 101, 64, 75, 6, 96, 212, 151, 239, 205, 0, 136,
196, 54, 93, 42, 47, 104, 136, 200, 12, 0, 145, 254, 249, 231, 25, 29, 3, 224, 105, 127,
103, 218, 236, 209, 231, 88, 198, 19, 68, 199, 48, 28, 33, 238, 110, 35, 178, 221, 168, 208,
89, 221, 228, 76, 6, 193, 234, 64, 61, 25, 128, 158, 80, 89, 196, 191, 151, 57, 240, 138,
223, 217, 141, 213, 93, 102, 40, 0, 96, 50, 114, 142, 47, 210, 13, 48, 18, 227, 72, 214,
96, 20, 252, 89, 197, 216, 58, 254, 160, 158, 112, 221, 167, 191, 115, 187, 208, 1, 207, 204,
201, 212, 110, 170, 181, 64, 89, 251, 147, 90, 51, 1, 44, 179, 0, 90, 93, 3, 154, 248,
91, 210, 255, 43, 11, 95, 121, 65, 67, 6, 128, 137, 88, 243, 61, 158, 72, 186, 138, 62,
136, 219, 26, 185, 91, 70, 224, 107, 153, 4, 235, 76, 50, 239, 160, 66, 79, 144, 186, 148,
237, 134, 5, 214, 115, 83, 34, 41, 153, 200, 44, 1, 45, 122, 183, 68, 241, 210, 17, 255,
26, 248, 140, 76, 1, 191, 147, 120, 211, 13, 0, 68, 230, 231, 158, 235, 76, 23, 128, 38,
160, 218, 58, 45, 22, 115, 225, 201, 36, 120, 179, 0, 51, 250, 117, 202, 34, 66, 91, 82,
1, 177, 174, 129, 239, 117, 62, 145, 62, 25, 75, 97, 138, 184, 73, 81, 162, 127, 77, 252,
71, 98, 63, 219, 5, 32, 198, 172, 195, 211, 5, 156, 76, 3, 96, 32, 174, 113, 252, 222,
46, 0, 173, 29, 182, 116, 201, 206, 182, 235, 50, 48, 3, 213, 168, 53, 145, 235, 49, 243,
218, 67, 51, 0, 89, 51, 3, 170, 243, 177, 39, 157, 100, 205, 0, 88, 94, 91, 141, 63,
163, 254, 127, 235, 115, 25, 194, 121, 245, 134, 229, 234, 99, 21, 0, 48, 8, 57, 199, 57,
51, 21, 176, 58, 162, 119, 203, 143, 214, 246, 71, 50, 0, 22, 3, 161, 101, 38, 36, 225,
61, 83, 229, 104, 115, 126, 88, 36, 210, 95, 225, 142, 188, 174, 44, 234, 38, 37, 248, 218,
94, 132, 239, 17, 202, 106, 52, 12, 229, 194, 13, 70, 185, 105, 195, 6, 128, 33, 88, 215,
174, 91, 12, 128, 71, 232, 53, 113, 183, 24, 11, 107, 230, 65, 148, 54, 223, 58, 14, 225,
18, 247, 125, 91, 88, 40, 188, 75, 32, 90, 6, 84, 88, 28, 165, 117, 16, 200, 140, 155,
220, 167, 254, 91, 199, 110, 21, 241, 34, 8, 35, 0, 188, 207, 0, 104, 194, 26, 21, 108,
79, 59, 46, 98, 31, 124, 104, 9, 52, 181, 107, 81, 19, 175, 231, 116, 249, 216, 38, 110,
250, 234, 37, 104, 173, 35, 51, 173, 3, 249, 50, 10, 148, 72, 172, 111, 104, 116, 205, 122,
171, 39, 150, 5, 247, 226, 204, 198, 129, 1, 122, 0, 207, 16, 125, 235, 49, 122, 231, 210,
175, 104, 163, 103, 223, 103, 53, 42, 214, 0, 120, 164, 73, 209, 107, 155, 150, 1, 240, 136,
84, 68, 144, 180, 254, 22, 143, 75, 26, 101, 0, 60, 5, 97, 198, 93, 142, 12, 192, 87,
68, 62, 73, 34, 29, 217, 113, 240, 110, 141, 5, 6, 1, 16, 248, 231, 28, 123, 230, 24,
128, 239, 130, 12, 64, 164, 155, 193, 186, 214, 128, 245, 188, 35, 229, 161, 102, 222, 191, 109,
242, 67, 180, 189, 237, 45, 133, 193, 146, 86, 241, 186, 50, 239, 13, 181, 254, 124, 229, 191,
163, 254, 71, 253, 65, 255, 94, 111, 141, 240, 181, 221, 0, 35, 131, 232, 202, 203, 26, 68,
140, 4, 32, 220, 231, 158, 239, 204, 32, 186, 89, 81, 207, 48, 11, 162, 24, 18, 79, 234,
95, 211, 8, 9, 4, 192, 105, 28, 177, 25, 80, 70, 161, 17, 37, 197, 162, 13, 206, 147,
164, 194, 245, 175, 128, 253, 227, 243, 243, 220, 103, 23, 245, 123, 140, 147, 53, 243, 18, 73,
169, 191, 77, 88, 25, 79, 1, 112, 124, 61, 200, 216, 15, 192, 98, 2, 190, 13, 161, 255,
254, 252, 100, 101, 5, 44, 217, 106, 207, 116, 243, 179, 238, 115, 181, 24, 128, 72, 180, 25,
61, 208, 153, 165, 121, 173, 89, 128, 35, 7, 147, 236, 143, 121, 100, 2, 180, 229, 131, 61,
59, 1, 70, 183, 5, 190, 90, 131, 66, 196, 14, 8, 245, 243, 142, 123, 118, 71, 192, 85,
209, 125, 214, 248, 0, 113, 136, 188, 165, 187, 97, 116, 221, 234, 162, 123, 86, 55, 227, 155,
202, 162, 136, 223, 187, 57, 143, 37, 11, 224, 21, 251, 239, 79, 36, 223, 75, 249, 239, 83,
255, 251, 108, 192, 62, 250, 255, 77, 253, 239, 127, 52, 241, 183, 236, 4, 184, 122, 193, 31,
118, 247, 3, 192, 108, 172, 200, 2, 120, 166, 2, 90, 178, 0, 95, 71, 166, 96, 181, 9,
176, 8, 123, 100, 13, 0, 145, 220, 85, 3, 255, 147, 1, 200, 186, 249, 197, 33, 238, 50,
112, 58, 171, 250, 242, 127, 197, 126, 36, 252, 45, 241, 255, 54, 142, 185, 213, 5, 80, 12,
25, 128, 200, 78, 128, 214, 181, 255, 159, 180, 118, 63, 217, 1, 64, 120, 239, 121, 46, 171,
51, 0, 189, 46, 128, 150, 41, 248, 74, 78, 70, 65, 211, 54, 75, 134, 218, 122, 205, 170,
243, 154, 158, 110, 0, 102, 78, 76, 12, 25, 0, 239, 212, 141, 72, 164, 191, 255, 233, 13,
254, 155, 201, 0, 104, 38, 64, 196, 191, 16, 208, 83, 197, 155, 236, 0, 192, 245, 235, 130,
183, 255, 63, 34, 254, 145, 12, 192, 183, 243, 247, 87, 49, 19, 51, 3, 7, 91, 122, 101,
9, 106, 79, 185, 215, 153, 123, 1, 244, 254, 30, 21, 6, 107, 55, 128, 182, 72, 131, 55,
205, 191, 31, 180, 167, 153, 130, 58, 200, 0, 124, 119, 130, 87, 12, 63, 117, 247, 250, 253,
111, 235, 2, 66, 103, 52, 12, 229, 1, 13, 22, 0, 70, 225, 92, 19, 144, 213, 5, 160,
101, 0, 180, 108, 192, 215, 105, 2, 60, 186, 163, 5, 181, 163, 235, 18, 185, 191, 238, 241,
2, 219, 73, 133, 36, 99, 203, 71, 173, 128, 252, 254, 124, 20, 51, 80, 228, 127, 211, 249,
255, 132, 250, 219, 16, 230, 81, 244, 63, 234, 2, 248, 141, 252, 165, 147, 5, 216, 11, 236,
153, 171, 7, 150, 139, 53, 48, 0, 112, 109, 99, 48, 179, 37, 176, 37, 19, 240, 117, 100,
1, 190, 18, 239, 26, 200, 232, 54, 16, 71, 6, 192, 18, 36, 71, 178, 43, 234, 189, 223,
12, 55, 180, 24, 111, 124, 107, 16, 155, 101, 97, 4, 235, 88, 129, 172, 41, 124, 31, 131,
240, 91, 198, 0, 140, 162, 255, 86, 38, 64, 148, 199, 162, 60, 142, 68, 225, 71, 70, 252,
0, 240, 238, 140, 192, 89, 6, 160, 118, 132, 222, 58, 101, 240, 59, 200, 14, 140, 12, 132,
87, 252, 61, 98, 62, 179, 123, 224, 178, 12, 128, 117, 30, 122, 171, 91, 192, 186, 91, 82,
214, 6, 14, 214, 1, 128, 189, 254, 122, 233, 8, 116, 75, 28, 103, 13, 192, 232, 187, 174,
96, 2, 48, 8, 0, 8, 252, 172, 248, 107, 193, 93, 166, 1, 104, 153, 1, 237, 255, 218,
184, 130, 217, 149, 101, 189, 65, 175, 229, 90, 79, 237, 15, 144, 181, 18, 160, 53, 91, 96,
77, 135, 100, 175, 12, 213, 18, 255, 95, 225, 111, 117, 9, 104, 51, 0, 70, 6, 160, 254,
191, 207, 212, 204, 128, 24, 178, 0, 22, 145, 189, 163, 8, 99, 28, 0, 174, 39, 228, 153,
199, 188, 114, 57, 96, 235, 56, 0, 45, 130, 255, 138, 127, 28, 128, 119, 175, 24, 45, 250,
207, 232, 255, 79, 203, 0, 204, 110, 90, 99, 93, 22, 56, 178, 83, 159, 213, 16, 124, 59,
194, 191, 79, 235, 183, 178, 0, 34, 253, 244, 188, 213, 0, 236, 71, 251, 91, 197, 95, 75,
255, 71, 68, 19, 161, 5, 128, 35, 141, 137, 117, 78, 251, 234, 129, 128, 150, 159, 106, 124,
188, 98, 29, 1, 207, 18, 248, 158, 232, 223, 124, 111, 86, 204, 2, 144, 132, 147, 157, 29,
248, 247, 233, 100, 0, 90, 191, 181, 84, 253, 232, 188, 63, 141, 223, 69, 17, 254, 172, 46,
128, 171, 139, 59, 198, 3, 224, 29, 25, 130, 35, 182, 4, 214, 196, 191, 101, 2, 254, 138,
173, 43, 160, 74, 191, 75, 32, 186, 212, 176, 37, 216, 21, 209, 7, 2, 90, 178, 41, 150,
107, 95, 181, 12, 192, 40, 165, 63, 51, 24, 80, 12, 55, 122, 244, 183, 55, 197, 223, 19,
254, 189, 232, 107, 125, 255, 69, 185, 97, 159, 134, 112, 87, 209, 167, 0, 90, 197, 63, 43,
3, 128, 48, 3, 192, 145, 70, 195, 155, 1, 176, 10, 191, 182, 30, 192, 239, 223, 127, 13,
134, 32, 50, 30, 32, 115, 223, 1, 239, 166, 66, 233, 247, 121, 75, 252, 176, 200, 110, 128,
218, 138, 74, 34, 254, 101, 124, 71, 194, 223, 234, 223, 31, 165, 232, 123, 81, 255, 222, 8,
252, 59, 127, 111, 6, 32, 91, 252, 223, 34, 238, 152, 24, 32, 74, 191, 246, 121, 206, 116,
3, 88, 51, 0, 85, 108, 3, 253, 60, 194, 111, 201, 14, 88, 215, 24, 240, 44, 88, 39,
202, 235, 122, 198, 169, 167, 163, 38, 86, 44, 5, 220, 154, 10, 88, 196, 182, 216, 207, 204,
82, 190, 22, 225, 215, 12, 128, 231, 92, 63, 187, 243, 254, 24, 50, 0, 34, 177, 233, 127,
79, 28, 4, 136, 160, 3, 134, 225, 217, 199, 191, 114, 91, 96, 171, 9, 248, 155, 156, 5,
208, 22, 26, 138, 236, 50, 168, 101, 0, 60, 115, 252, 93, 93, 5, 209, 205, 128, 170, 161,
225, 182, 118, 3, 72, 130, 17, 24, 9, 255, 199, 96, 0, 52, 49, 218, 127, 255, 103, 103,
110, 44, 226, 111, 201, 2, 32, 254, 0, 152, 128, 183, 153, 128, 153, 193, 222, 214, 129, 128,
127, 21, 19, 240, 87, 236, 3, 5, 163, 51, 6, 122, 17, 123, 100, 145, 32, 145, 201, 41,
128, 145, 12, 128, 182, 81, 141, 182, 32, 80, 198, 8, 127, 45, 35, 96, 77, 251, 255, 109,
8, 145, 117, 48, 99, 111, 35, 159, 168, 1, 232, 153, 129, 183, 152, 0, 204, 1, 32, 242,
207, 23, 127, 25, 136, 94, 182, 1, 168, 74, 244, 255, 119, 247, 19, 157, 49, 48, 179, 251,
160, 72, 124, 154, 96, 74, 153, 218, 36, 54, 149, 111, 20, 237, 239, 83, 254, 69, 41, 4,
214, 53, 0, 70, 35, 249, 123, 207, 89, 210, 254, 69, 124, 219, 235, 238, 179, 0, 214, 232,
127, 118, 5, 64, 207, 253, 64, 56, 1, 224, 76, 35, 19, 217, 222, 54, 99, 32, 160, 214,
13, 96, 17, 124, 237, 255, 22, 193, 215, 140, 128, 24, 179, 3, 209, 251, 96, 202, 24, 108,
138, 240, 123, 102, 2, 120, 167, 3, 106, 139, 39, 104, 27, 245, 104, 130, 255, 237, 68, 253,
150, 126, 255, 81, 74, 102, 111, 110, 254, 29, 67, 118, 250, 255, 74, 43, 0, 98, 40, 0,
200, 60, 204, 124, 167, 69, 252, 189, 38, 192, 51, 24, 240, 111, 227, 183, 53, 242, 215, 196,
63, 18, 253, 107, 70, 64, 6, 153, 130, 217, 76, 76, 237, 25, 128, 140, 155, 223, 74, 141,
139, 241, 196, 172, 187, 248, 105, 25, 129, 95, 225, 223, 139, 254, 95, 135, 192, 85, 131, 1,
176, 116, 1, 104, 226, 63, 51, 6, 224, 201, 2, 141, 241, 0, 132, 248, 222, 231, 53, 179,
26, 160, 102, 2, 162, 179, 1, 70, 93, 1, 127, 197, 191, 156, 176, 119, 41, 97, 145, 216,
34, 65, 150, 217, 114, 174, 251, 179, 57, 110, 244, 104, 223, 249, 50, 48, 1, 34, 254, 53,
147, 91, 219, 242, 182, 54, 241, 25, 69, 251, 214, 41, 127, 154, 19, 237, 25, 128, 223, 200,
191, 151, 5, 16, 137, 173, 2, 120, 181, 12, 0, 98, 12, 128, 233, 200, 202, 0, 104, 226,
111, 17, 200, 200, 190, 0, 127, 7, 70, 96, 166, 43, 32, 154, 1, 232, 9, 183, 53, 107,
50, 125, 223, 183, 137, 27, 92, 6, 207, 89, 199, 1, 120, 7, 252, 89, 141, 128, 54, 224,
207, 114, 126, 90, 70, 162, 52, 76, 192, 153, 107, 0, 32, 214, 0, 112, 37, 83, 177, 114,
45, 128, 153, 110, 128, 86, 87, 128, 150, 9, 248, 43, 190, 37, 131, 173, 11, 6, 137, 248,
167, 14, 166, 177, 41, 17, 126, 9, 220, 240, 210, 121, 28, 185, 0, 35, 35, 176, 23, 127,
75, 127, 191, 165, 239, 127, 228, 56, 63, 142, 232, 223, 155, 1, 136, 138, 63, 139, 255, 0,
16, 129, 95, 245, 60, 103, 77, 128, 22, 144, 205, 12, 6, 156, 25, 11, 224, 217, 116, 104,
102, 64, 96, 164, 76, 89, 119, 25, 172, 150, 205, 128, 188, 75, 2, 107, 239, 143, 174, 243,
175, 237, 220, 215, 138, 194, 255, 58, 47, 216, 239, 119, 254, 217, 137, 125, 111, 55, 193, 207,
194, 232, 255, 174, 251, 0, 32, 238, 0, 239, 50, 9, 145, 253, 0, 50, 178, 0, 35, 19,
48, 90, 26, 248, 175, 35, 19, 96, 93, 60, 40, 99, 73, 224, 214, 185, 183, 174, 153, 246,
25, 166, 123, 177, 57, 111, 112, 81, 110, 120, 111, 61, 0, 79, 87, 192, 87, 254, 183, 159,
189, 236, 62, 99, 36, 182, 95, 177, 141, 198, 23, 131, 235, 172, 59, 225, 111, 13, 60, 244,
124, 103, 246, 10, 128, 79, 17, 77, 196, 31, 48, 1, 24, 128, 136, 248, 207, 236, 14, 152,
53, 43, 192, 106, 10, 190, 226, 203, 124, 107, 166, 200, 26, 249, 15, 217, 38, 110, 246, 104,
238, 124, 25, 152, 0, 111, 212, 111, 17, 254, 72, 95, 127, 235, 194, 254, 145, 113, 223, 127,
111, 39, 193, 143, 216, 82, 255, 44, 1, 140, 49, 0, 132, 254, 109, 231, 150, 101, 0, 68,
108, 107, 241, 71, 102, 4, 244, 50, 1, 81, 193, 143, 110, 39, 172, 101, 70, 82, 203, 217,
166, 136, 122, 116, 108, 64, 77, 50, 1, 145, 44, 192, 108, 228, 255, 71, 17, 254, 189, 224,
91, 183, 21, 94, 97, 0, 16, 75, 204, 7, 32, 194, 87, 191, 158, 25, 6, 64, 196, 215,
5, 208, 51, 2, 214, 174, 128, 209, 52, 193, 191, 162, 15, 252, 155, 93, 19, 160, 39, 254,
158, 212, 191, 186, 118, 192, 102, 140, 240, 71, 162, 111, 153, 14, 40, 78, 19, 176, 31, 213,
223, 18, 125, 139, 17, 176, 94, 152, 94, 234, 127, 180, 230, 128, 214, 255, 223, 19, 253, 200,
244, 191, 168, 32, 33, 100, 0, 112, 150, 113, 178, 44, 90, 99, 157, 14, 40, 226, 31, 7,
16, 237, 10, 248, 78, 100, 1, 180, 99, 25, 9, 183, 37, 243, 33, 202, 251, 68, 28, 123,
4, 68, 246, 2, 232, 237, 3, 208, 50, 3, 251, 46, 129, 217, 238, 128, 175, 140, 83, 237,
218, 230, 62, 189, 194, 245, 71, 198, 105, 255, 25, 241, 207, 28, 252, 119, 69, 65, 199, 100,
0, 144, 213, 176, 28, 211, 204, 96, 192, 168, 9, 136, 76, 11, 140, 44, 31, 156, 181, 54,
128, 117, 35, 160, 20, 180, 165, 128, 61, 207, 245, 110, 118, 111, 48, 160, 214, 239, 111, 89,
218, 87, 38, 132, 95, 6, 81, 127, 43, 250, 111, 165, 254, 61, 131, 254, 86, 164, 255, 17,
95, 174, 9, 32, 184, 119, 184, 38, 43, 187, 1, 102, 179, 0, 35, 193, 215, 118, 17, 244,
110, 22, 20, 221, 32, 200, 58, 123, 160, 167, 121, 205, 215, 109, 198, 104, 95, 19, 253, 170,
136, 239, 42, 19, 32, 13, 241, 47, 198, 194, 56, 26, 244, 215, 234, 255, 183, 26, 128, 153,
232, 127, 117, 228, 143, 56, 2, 192, 81, 38, 39, 99, 95, 0, 107, 22, 96, 102, 64, 160,
37, 27, 96, 93, 61, 48, 83, 252, 69, 108, 253, 252, 161, 244, 255, 63, 3, 48, 187, 243,
159, 136, 190, 76, 176, 215, 217, 236, 77, 128, 40, 98, 58, 218, 74, 215, 210, 223, 255, 71,
254, 155, 242, 111, 13, 252, 251, 42, 6, 192, 35, 254, 140, 254, 199, 176, 0, 130, 250, 166,
243, 140, 118, 1, 88, 76, 192, 200, 0, 212, 129, 72, 255, 21, 223, 184, 0, 205, 4, 104,
251, 2, 120, 7, 8, 182, 196, 190, 102, 149, 49, 203, 66, 64, 158, 231, 70, 55, 221, 147,
5, 216, 11, 255, 62, 27, 32, 138, 232, 139, 98, 4, 106, 199, 8, 236, 163, 255, 34, 237,
244, 255, 204, 212, 63, 175, 240, 207, 138, 32, 34, 10, 0, 103, 153, 23, 207, 64, 64, 45,
2, 142, 78, 9, 156, 237, 14, 176, 252, 30, 205, 2, 24, 13, 16, 244, 140, 250, 31, 69,
254, 163, 160, 183, 123, 237, 55, 195, 205, 211, 54, 250, 177, 20, 146, 72, 22, 160, 101, 4,
190, 13, 97, 179, 70, 255, 145, 180, 127, 111, 222, 255, 175, 9, 16, 57, 126, 237, 127, 68,
157, 107, 0, 68, 249, 119, 207, 0, 120, 178, 0, 61, 173, 144, 65, 68, 109, 153, 22, 104,
217, 4, 200, 147, 254, 255, 202, 220, 58, 0, 222, 213, 253, 194, 233, 255, 95, 3, 16, 89,
247, 223, 147, 9, 24, 101, 1, 100, 32, 250, 251, 12, 128, 52, 204, 64, 49, 94, 152, 145,
115, 28, 165, 253, 181, 1, 127, 163, 113, 0, 30, 241, 63, 114, 228, 63, 226, 9, 0, 71,
152, 152, 204, 113, 0, 90, 176, 104, 49, 0, 189, 165, 130, 181, 93, 0, 61, 131, 1, 103,
133, 95, 140, 231, 106, 185, 126, 195, 123, 99, 93, 7, 160, 23, 253, 183, 198, 3, 120, 179,
0, 210, 16, 254, 79, 199, 12, 88, 4, 108, 212, 111, 210, 27, 241, 175, 173, 246, 231, 49,
0, 34, 115, 163, 255, 201, 0, 0, 192, 155, 51, 0, 163, 232, 223, 99, 2, 102, 103, 6,
88, 51, 3, 163, 148, 191, 197, 16, 244, 206, 45, 59, 250, 15, 173, 3, 48, 90, 246, 215,
187, 73, 208, 200, 8, 88, 7, 5, 246, 76, 129, 24, 132, 95, 75, 253, 71, 54, 251, 89,
189, 241, 207, 217, 98, 143, 217, 0, 32, 170, 95, 153, 1, 240, 100, 1, 178, 76, 192, 140,
17, 176, 12, 4, 180, 204, 84, 152, 217, 29, 55, 229, 254, 142, 150, 2, 94, 157, 5, 216,
223, 216, 239, 32, 242, 255, 4, 68, 223, 106, 8, 90, 27, 252, 124, 22, 138, 191, 38, 252,
44, 255, 11, 0, 79, 53, 26, 213, 248, 247, 153, 38, 192, 178, 112, 80, 214, 166, 64, 214,
46, 0, 75, 100, 111, 30, 252, 39, 202, 82, 192, 171, 179, 0, 90, 38, 96, 31, 145, 207,
20, 202, 214, 40, 255, 214, 247, 20, 177, 13, 252, 139, 26, 0, 235, 227, 43, 139, 60, 166,
3, 128, 168, 127, 69, 22, 192, 51, 38, 96, 102, 60, 128, 197, 4, 204, 100, 6, 162, 131,
1, 69, 252, 83, 0, 235, 108, 57, 176, 172, 4, 40, 201, 89, 0, 237, 38, 183, 210, 241,
158, 212, 255, 168, 96, 20, 25, 167, 253, 203, 34, 241, 207, 140, 254, 17, 97, 0, 184, 179,
249, 56, 35, 11, 224, 49, 1, 85, 244, 149, 254, 172, 209, 190, 119, 206, 255, 236, 138, 127,
174, 105, 151, 158, 105, 128, 145, 44, 64, 29, 8, 152, 118, 18, 191, 66, 252, 143, 81, 87,
192, 62, 218, 111, 61, 223, 90, 131, 160, 213, 5, 224, 217, 234, 247, 14, 125, 255, 152, 6,
0, 56, 51, 147, 112, 212, 88, 0, 17, 61, 229, 254, 149, 185, 89, 2, 214, 174, 3, 235,
166, 64, 214, 157, 253, 82, 163, 255, 158, 1, 200, 204, 2, 20, 227, 129, 253, 206, 231, 108,
205, 193, 223, 207, 16, 248, 54, 222, 255, 25, 152, 129, 214, 227, 223, 227, 31, 141, 250, 215,
182, 250, 157, 77, 255, 91, 4, 26, 1, 231, 58, 192, 59, 133, 243, 201, 215, 33, 178, 63,
192, 200, 0, 104, 25, 129, 175, 196, 183, 17, 214, 140, 65, 239, 239, 154, 244, 19, 141, 254,
135, 215, 220, 59, 11, 64, 203, 2, 212, 65, 148, 63, 106, 212, 189, 217, 128, 189, 9, 40,
29, 51, 160, 9, 127, 221, 9, 253, 103, 32, 250, 179, 27, 254, 100, 173, 250, 135, 8, 2,
192, 157, 205, 79, 100, 155, 96, 205, 0, 104, 226, 239, 157, 34, 104, 49, 2, 218, 99, 75,
212, 47, 226, 91, 6, 88, 12, 153, 0, 115, 166, 192, 179, 14, 128, 37, 11, 32, 131, 12,
128, 55, 5, 212, 203, 6, 124, 7, 34, 187, 23, 127, 77, 248, 191, 141, 104, 223, 186, 201,
207, 149, 6, 254, 97, 10, 0, 224, 14, 153, 142, 163, 6, 4, 138, 248, 54, 13, 178, 118,
13, 68, 68, 95, 219, 24, 104, 116, 173, 170, 216, 22, 250, 177, 152, 131, 230, 58, 0, 30,
177, 183, 102, 1, 90, 25, 0, 235, 78, 130, 223, 31, 17, 31, 153, 128, 150, 25, 40, 13,
241, 223, 255, 222, 71, 254, 117, 39, 234, 90, 244, 47, 18, 219, 237, 239, 236, 121, 255, 152,
4, 0, 88, 41, 238, 89, 6, 192, 146, 1, 16, 137, 117, 3, 68, 54, 17, 154, 249, 125,
149, 212, 191, 43, 3, 16, 205, 2, 204, 206, 12, 104, 157, 108, 111, 106, 158, 40, 191, 123,
226, 255, 81, 12, 64, 84, 248, 53, 209, 191, 195, 194, 63, 152, 4, 0, 4, 254, 140, 239,
245, 238, 109, 111, 89, 69, 111, 198, 0, 68, 179, 3, 209, 173, 128, 181, 181, 0, 44, 247,
204, 21, 253, 255, 26, 128, 140, 44, 64, 235, 255, 145, 49, 1, 251, 44, 128, 200, 120, 117,
190, 158, 240, 239, 159, 107, 137, 255, 199, 96, 0, 68, 142, 157, 242, 183, 82, 132, 17, 120,
0, 56, 211, 28, 68, 12, 128, 22, 253, 139, 196, 7, 6, 106, 51, 5, 60, 34, 255, 117,
124, 166, 71, 248, 45, 231, 31, 186, 23, 209, 221, 0, 69, 198, 59, 3, 246, 186, 2, 60,
70, 160, 101, 2, 138, 193, 8, 244, 132, 127, 244, 119, 182, 248, 91, 31, 103, 137, 51, 194,
14, 0, 119, 50, 10, 217, 99, 1, 102, 77, 128, 199, 8, 104, 98, 31, 17, 127, 77, 248,
53, 209, 119, 71, 255, 191, 25, 0, 107, 22, 64, 51, 10, 173, 223, 34, 255, 29, 233, 111,
53, 2, 123, 19, 208, 51, 2, 123, 113, 254, 205, 2, 244, 254, 142, 166, 252, 163, 187, 253,
245, 132, 154, 165, 127, 1, 224, 173, 230, 192, 181, 112, 205, 226, 76, 128, 87, 196, 173, 203,
252, 90, 230, 253, 247, 142, 213, 98, 150, 106, 224, 62, 152, 151, 2, 182, 100, 1, 196, 144,
1, 232, 13, 12, 180, 152, 128, 223, 148, 125, 239, 249, 175, 34, 224, 214, 190, 126, 111, 159,
127, 36, 234, 103, 222, 255, 181, 224, 122, 35, 82, 112, 254, 245, 246, 174, 11, 32, 98, 223,
53, 208, 107, 0, 172, 34, 30, 17, 125, 109, 189, 255, 106, 52, 58, 211, 101, 218, 186, 20,
112, 164, 43, 160, 101, 8, 102, 178, 1, 86, 51, 48, 154, 182, 231, 17, 252, 140, 168, 63,
51, 3, 128, 104, 1, 192, 211, 204, 84, 52, 3, 48, 147, 13, 200, 202, 8, 68, 94, 99,
57, 30, 235, 249, 141, 30, 155, 76, 66, 116, 37, 64, 45, 91, 224, 237, 18, 176, 102, 3,
68, 17, 125, 171, 1, 176, 254, 111, 214, 0, 16, 253, 19, 233, 3, 153, 1, 200, 201, 2,
100, 24, 0, 145, 248, 86, 188, 25, 83, 251, 44, 226, 95, 197, 191, 198, 127, 168, 203, 101,
115, 222, 56, 75, 87, 128, 102, 2, 90, 175, 143, 154, 0, 143, 65, 240, 24, 2, 175, 240,
211, 239, 15, 0, 48, 103, 168, 86, 140, 7, 24, 137, 255, 140, 25, 200, 50, 0, 61, 193,
183, 94, 143, 169, 107, 238, 93, 9, 112, 118, 60, 64, 43, 3, 80, 156, 39, 85, 2, 63,
51, 17, 191, 119, 145, 159, 149, 211, 253, 48, 4, 0, 240, 196, 12, 74, 230, 250, 0, 158,
44, 128, 44, 48, 0, 214, 207, 180, 70, 251, 233, 169, 127, 75, 6, 32, 210, 21, 48, 138,
246, 173, 38, 160, 12, 156, 79, 153, 48, 7, 85, 114, 211, 253, 179, 3, 254, 232, 251, 7,
0, 196, 127, 222, 0, 204, 102, 3, 36, 96, 0, 34, 255, 215, 190, 223, 242, 59, 77, 252,
53, 3, 96, 53, 6, 214, 108, 129, 200, 120, 177, 160, 189, 200, 85, 199, 119, 148, 206, 49,
121, 211, 252, 136, 63, 0, 0, 38, 192, 99, 10, 44, 175, 61, 66, 252, 67, 130, 18, 29,
148, 54, 18, 187, 81, 154, 220, 242, 123, 244, 216, 34, 232, 179, 162, 159, 177, 192, 207, 236,
136, 127, 196, 30, 0, 222, 104, 10, 50, 102, 6, 204, 24, 128, 136, 25, 176, 254, 157, 37,
254, 211, 209, 191, 213, 0, 172, 52, 1, 86, 17, 214, 12, 129, 85, 232, 61, 98, 127, 228,
84, 63, 196, 30, 0, 48, 5, 249, 70, 192, 155, 13, 176, 70, 238, 145, 40, 127, 70, 244,
211, 197, 95, 36, 214, 5, 160, 221, 48, 235, 204, 0, 145, 156, 233, 128, 173, 239, 41, 202,
241, 236, 199, 5, 204, 10, 191, 71, 244, 179, 196, 30, 211, 0, 0, 119, 140, 240, 35, 159,
227, 153, 6, 151, 109, 4, 102, 132, 190, 6, 142, 35, 75, 252, 77, 34, 50, 59, 37, 205,
51, 239, 221, 50, 146, 222, 147, 158, 143, 102, 14, 34, 191, 61, 25, 15, 175, 80, 35, 230,
0, 128, 105, 136, 27, 130, 12, 3, 160, 137, 191, 245, 255, 30, 147, 161, 137, 255, 232, 241,
84, 244, 239, 53, 0, 103, 153, 0, 175, 41, 240, 62, 103, 61, 38, 239, 121, 102, 136, 60,
198, 0, 0, 222, 152, 29, 240, 172, 111, 159, 49, 85, 208, 146, 13, 152, 21, 251, 200, 224,
190, 101, 226, 31, 49, 0, 87, 49, 1, 17, 97, 47, 129, 239, 246, 26, 128, 21, 38, 0,
163, 0, 0, 79, 17, 246, 108, 241, 159, 201, 6, 100, 155, 129, 200, 239, 222, 115, 203, 197,
63, 219, 0, 68, 77, 128, 55, 18, 207, 24, 200, 231, 53, 35, 89, 6, 224, 237, 98, 141,
81, 1, 56, 79, 88, 159, 112, 238, 94, 3, 224, 17, 221, 217, 110, 130, 136, 208, 71, 70,
251, 167, 136, 255, 72, 232, 174, 96, 2, 102, 178, 2, 153, 38, 0, 241, 199, 36, 0, 32,
238, 207, 48, 1, 81, 241, 159, 137, 242, 163, 253, 253, 75, 197, 95, 19, 188, 51, 77, 64,
84, 212, 179, 4, 63, 123, 113, 159, 179, 68, 13, 49, 5, 128, 187, 154, 150, 240, 62, 247,
6, 113, 141, 26, 130, 149, 130, 63, 35, 254, 145, 251, 84, 189, 59, 213, 173, 50, 1, 30,
81, 142, 118, 29, 120, 133, 63, 35, 234, 159, 21, 96, 4, 28, 0, 222, 110, 32, 50, 199,
4, 204, 26, 129, 85, 130, 127, 184, 248, 123, 162, 219, 163, 77, 64, 84, 184, 51, 162, 252,
25, 209, 207, 52, 80, 0, 0, 24, 132, 120, 244, 63, 155, 17, 152, 21, 249, 168, 216, 175,
22, 255, 174, 1, 56, 194, 4, 68, 132, 223, 251, 120, 86, 232, 75, 240, 60, 16, 121, 0,
128, 99, 205, 65, 13, 60, 151, 221, 85, 144, 21, 233, 31, 38, 254, 153, 145, 108, 182, 9,
88, 97, 10, 188, 145, 254, 17, 233, 126, 204, 1, 0, 32, 242, 185, 239, 89, 209, 45, 144,
45, 246, 25, 75, 249, 78, 95, 183, 35, 5, 109, 214, 4, 100, 71, 246, 43, 83, 253, 119,
23, 118, 140, 9, 0, 66, 123, 183, 227, 95, 209, 53, 112, 68, 148, 127, 138, 248, 175, 18,
178, 89, 19, 224, 17, 241, 172, 255, 173, 48, 1, 8, 42, 0, 192, 49, 134, 101, 70, 252,
179, 12, 65, 36, 202, 175, 129, 243, 78, 203, 152, 172, 234, 195, 142, 100, 22, 202, 197, 254,
158, 57, 23, 12, 1, 0, 192, 49, 25, 138, 236, 233, 130, 103, 252, 125, 184, 248, 123, 132,
232, 44, 19, 144, 37, 228, 87, 78, 247, 99, 6, 0, 0, 209, 95, 243, 254, 149, 153, 129,
168, 208, 31, 149, 242, 87, 223, 183, 210, 0, 204, 136, 103, 150, 136, 31, 145, 230, 207, 20,
112, 204, 0, 0, 32, 250, 185, 159, 181, 218, 4, 204, 70, 248, 117, 209, 245, 82, 223, 247,
231, 0, 113, 90, 105, 2, 86, 60, 119, 150, 248, 3, 0, 96, 0, 142, 53, 1, 51, 70,
96, 246, 185, 83, 197, 63, 34, 96, 51, 130, 183, 218, 8, 100, 69, 247, 68, 253, 0, 0,
239, 202, 6, 172, 18, 243, 153, 180, 126, 93, 125, 77, 143, 158, 187, 62, 211, 159, 190, 82,
244, 103, 143, 13, 177, 7, 0, 184, 142, 41, 152, 17, 215, 154, 240, 252, 108, 127, 126, 61,
226, 218, 157, 49, 138, 125, 54, 194, 206, 140, 232, 203, 5, 175, 15, 0, 0, 28, 39, 138,
153, 102, 32, 250, 158, 12, 243, 51, 181, 27, 224, 157, 76, 192, 42, 193, 247, 158, 23, 66,
15, 0, 112, 47, 99, 112, 180, 33, 184, 164, 248, 103, 9, 216, 85, 141, 64, 118, 132, 127,
180, 216, 99, 46, 0, 224, 237, 209, 251, 17, 223, 183, 194, 16, 28, 37, 252, 83, 239, 207,
18, 153, 35, 50, 9, 101, 241, 255, 179, 174, 9, 194, 13, 0, 112, 77, 35, 81, 147, 94,
87, 15, 250, 158, 165, 239, 191, 210, 104, 246, 76, 129, 62, 99, 133, 67, 0, 0, 184, 167,
73, 168, 7, 190, 38, 67, 248, 83, 62, 35, 91, 208, 142, 140, 158, 203, 137, 159, 137, 97,
0, 0, 184, 71, 212, 63, 243, 121, 245, 196, 207, 92, 126, 77, 86, 8, 212, 209, 227, 10,
142, 16, 120, 132, 28, 0, 224, 29, 198, 161, 94, 224, 181, 135, 152, 161, 85, 194, 118, 214,
216, 130, 114, 129, 243, 199, 44, 0, 0, 220, 35, 27, 16, 249, 204, 122, 210, 49, 167, 159,
251, 255, 1, 67, 190, 69, 189, 21, 93, 150, 173, 0, 0, 0, 0, 73, 69, 78, 68, 174,
66, 96, 130
};
};
BasicShadowTexture_t BasicShadowTexture;
}
#endif

View file

@ -0,0 +1,44 @@
#ifndef __StateGradient_HPP__
#define __StateGradient_HPP__
namespace oxres
{
struct StateGradient_t {
const unsigned int size = 632;
const unsigned char data[632] = {
137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0,
200, 0, 0, 0, 1, 8, 2, 0, 0, 0, 20, 221, 118, 181, 0, 0, 1, 131, 105, 67,
67, 80, 73, 67, 67, 32, 112, 114, 111, 102, 105, 108, 101, 0, 0, 40, 145, 125, 145, 61,
72, 195, 64, 28, 197, 95, 83, 69, 145, 138, 67, 59, 20, 113, 8, 82, 157, 236, 162, 34,
142, 181, 10, 69, 168, 16, 106, 133, 86, 29, 76, 46, 253, 130, 38, 13, 73, 138, 139, 163,
224, 90, 112, 240, 99, 177, 234, 224, 226, 172, 171, 131, 171, 32, 8, 126, 128, 56, 58, 57,
41, 186, 72, 137, 255, 75, 10, 45, 98, 60, 56, 238, 199, 187, 123, 143, 187, 119, 128, 208,
172, 50, 205, 234, 73, 0, 154, 110, 155, 153, 84, 82, 204, 229, 87, 197, 190, 87, 132, 16,
69, 24, 163, 136, 201, 204, 50, 230, 36, 41, 13, 223, 241, 117, 143, 0, 95, 239, 226, 60,
203, 255, 220, 159, 99, 80, 45, 88, 12, 8, 136, 196, 9, 102, 152, 54, 241, 6, 241, 204,
166, 109, 112, 222, 39, 142, 176, 178, 172, 18, 159, 19, 79, 152, 116, 65, 226, 71, 174, 43,
30, 191, 113, 46, 185, 44, 240, 204, 136, 153, 205, 204, 19, 71, 136, 197, 82, 23, 43, 93,
204, 202, 166, 70, 60, 77, 28, 83, 53, 157, 242, 133, 156, 199, 42, 231, 45, 206, 90, 181,
206, 218, 247, 228, 47, 12, 21, 244, 149, 101, 174, 211, 28, 65, 10, 139, 88, 130, 4, 17,
10, 234, 168, 160, 10, 27, 113, 90, 117, 82, 44, 100, 104, 63, 233, 227, 31, 118, 253, 18,
185, 20, 114, 85, 192, 200, 177, 128, 26, 52, 200, 174, 31, 252, 15, 126, 119, 107, 21, 167,
38, 189, 164, 80, 18, 232, 125, 113, 156, 143, 49, 160, 111, 23, 104, 53, 28, 231, 251, 216,
113, 90, 39, 64, 240, 25, 184, 210, 59, 254, 90, 19, 152, 253, 36, 189, 209, 209, 98, 71,
192, 208, 54, 112, 113, 221, 209, 148, 61, 224, 114, 7, 136, 62, 25, 178, 41, 187, 82, 144,
166, 80, 44, 2, 239, 103, 244, 77, 121, 32, 124, 11, 12, 172, 121, 189, 181, 247, 113, 250,
0, 100, 169, 171, 244, 13, 112, 112, 8, 140, 151, 40, 123, 221, 231, 221, 253, 221, 189, 253,
123, 166, 221, 223, 15, 209, 38, 114, 204, 181, 133, 24, 137, 0, 0, 0, 9, 112, 72, 89,
115, 0, 0, 46, 35, 0, 0, 46, 35, 1, 120, 165, 63, 118, 0, 0, 0, 7, 116, 73,
77, 69, 7, 230, 12, 24, 21, 25, 24, 206, 21, 144, 155, 0, 0, 0, 25, 116, 69, 88,
116, 67, 111, 109, 109, 101, 110, 116, 0, 67, 114, 101, 97, 116, 101, 100, 32, 119, 105, 116,
104, 32, 71, 73, 77, 80, 87, 129, 14, 23, 0, 0, 0, 99, 73, 68, 65, 84, 40, 207,
141, 144, 65, 18, 192, 32, 8, 3, 23, 253, 122, 191, 141, 244, 64, 157, 98, 69, 235, 76,
14, 17, 67, 32, 200, 101, 20, 30, 84, 16, 222, 231, 10, 2, 53, 16, 9, 237, 179, 166,
116, 193, 71, 121, 50, 104, 51, 215, 77, 104, 96, 208, 38, 236, 139, 78, 52, 19, 27, 216,
248, 165, 153, 161, 215, 109, 228, 154, 185, 157, 47, 118, 210, 222, 254, 204, 117, 17, 54, 10,
180, 199, 220, 24, 198, 56, 154, 93, 38, 189, 73, 32, 55, 250, 88, 138, 3, 247, 50, 102,
231, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130
};
};
StateGradient_t StateGradient;
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,899 @@
#ifndef __default_icon_64_HPP__
#define __default_icon_64_HPP__
namespace oxres
{
struct default_icon_64_t {
const unsigned int size = 17682;
const unsigned char data[17682] = {
137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0,
64, 0, 0, 0, 64, 8, 6, 0, 0, 0, 170, 105, 113, 222, 0, 0, 29, 95, 122, 84,
88, 116, 82, 97, 119, 32, 112, 114, 111, 102, 105, 108, 101, 32, 116, 121, 112, 101, 32, 101,
120, 105, 102, 0, 0, 120, 218, 237, 155, 89, 146, 29, 185, 210, 156, 223, 115, 21, 90, 66,
98, 6, 150, 131, 209, 76, 59, 208, 242, 245, 121, 32, 139, 151, 236, 110, 201, 212, 191, 222,
100, 98, 53, 89, 85, 231, 228, 201, 4, 98, 240, 112, 15, 68, 63, 251, 127, 252, 247, 243,
252, 55, 254, 148, 236, 226, 19, 83, 169, 185, 229, 252, 242, 39, 182, 216, 124, 231, 135, 250,
222, 63, 221, 254, 117, 111, 180, 127, 237, 79, 252, 222, 226, 247, 63, 94, 127, 126, 189, 225,
121, 41, 240, 61, 220, 95, 107, 254, 174, 255, 121, 221, 253, 186, 193, 253, 214, 249, 41, 253,
118, 163, 58, 191, 55, 198, 159, 111, 180, 239, 9, 190, 254, 229, 70, 223, 131, 130, 86, 228,
249, 97, 125, 55, 106, 223, 141, 130, 191, 111, 184, 239, 6, 253, 110, 235, 205, 173, 150, 223,
183, 48, 246, 253, 190, 126, 118, 82, 239, 223, 71, 255, 248, 123, 169, 86, 117, 87, 241, 151,
223, 99, 193, 122, 43, 241, 156, 224, 253, 14, 46, 188, 252, 27, 194, 183, 128, 160, 191, 254,
9, 157, 31, 34, 255, 186, 144, 184, 80, 95, 122, 37, 216, 191, 245, 91, 9, 6, 249, 39,
59, 253, 250, 211, 88, 209, 217, 159, 43, 254, 126, 209, 31, 94, 249, 245, 147, 251, 231, 215,
159, 191, 122, 43, 250, 239, 146, 240, 23, 35, 231, 95, 223, 255, 241, 245, 199, 165, 127, 246,
138, 153, 254, 247, 248, 169, 223, 79, 254, 207, 215, 203, 235, 230, 93, 209, 95, 172, 175, 191,
231, 172, 122, 108, 207, 236, 162, 199, 140, 169, 243, 183, 169, 159, 173, 216, 79, 92, 135, 59,
162, 30, 93, 31, 150, 150, 185, 109, 38, 134, 42, 223, 245, 213, 248, 170, 68, 245, 36, 20,
214, 59, 223, 193, 215, 116, 205, 121, 220, 117, 92, 116, 203, 117, 119, 220, 182, 239, 211, 77,
150, 24, 253, 126, 124, 225, 7, 239, 167, 15, 246, 98, 13, 197, 55, 63, 241, 152, 195, 151,
124, 185, 227, 75, 104, 97, 133, 138, 147, 167, 185, 61, 6, 255, 107, 45, 206, 30, 219, 222,
249, 216, 211, 42, 79, 94, 142, 75, 189, 227, 102, 78, 113, 241, 111, 191, 158, 127, 251, 129,
115, 100, 91, 231, 222, 250, 203, 86, 172, 203, 123, 25, 155, 101, 200, 115, 250, 151, 203, 240,
136, 59, 159, 81, 147, 25, 248, 231, 235, 175, 127, 228, 215, 128, 7, 147, 172, 172, 20, 105,
24, 118, 220, 91, 140, 228, 254, 131, 4, 193, 28, 29, 184, 48, 241, 253, 230, 160, 43, 235,
187, 1, 38, 226, 209, 137, 197, 184, 128, 7, 240, 26, 185, 225, 178, 123, 139, 247, 197, 57,
12, 89, 113, 80, 103, 233, 62, 68, 63, 240, 128, 75, 201, 47, 22, 233, 99, 8, 25, 223,
84, 175, 71, 243, 145, 226, 236, 82, 159, 60, 47, 63, 188, 14, 152, 225, 137, 20, 114, 40,
248, 166, 133, 142, 179, 98, 76, 196, 79, 137, 149, 24, 234, 41, 164, 152, 82, 202, 169, 164,
154, 90, 234, 57, 228, 152, 83, 206, 185, 100, 129, 98, 47, 161, 196, 167, 164, 146, 75, 41,
181, 180, 210, 107, 168, 177, 166, 154, 107, 169, 181, 182, 218, 155, 111, 1, 208, 76, 45, 183,
210, 106, 107, 173, 119, 158, 217, 185, 115, 231, 211, 157, 11, 122, 31, 126, 132, 17, 71, 122,
70, 30, 101, 212, 209, 70, 159, 132, 207, 140, 51, 205, 60, 203, 172, 179, 205, 190, 252, 10,
11, 252, 88, 121, 149, 85, 87, 91, 125, 187, 77, 40, 237, 184, 211, 206, 187, 236, 186, 219,
238, 135, 80, 59, 225, 57, 241, 164, 147, 79, 57, 245, 180, 211, 127, 121, 237, 115, 235, 223,
190, 254, 133, 215, 220, 231, 53, 111, 158, 210, 133, 229, 151, 215, 120, 181, 148, 159, 91, 56,
193, 73, 146, 207, 112, 152, 127, 162, 195, 227, 69, 46, 32, 160, 189, 124, 246, 86, 23, 163,
151, 231, 228, 179, 183, 121, 178, 34, 121, 22, 153, 228, 179, 229, 228, 49, 60, 24, 183, 243,
233, 184, 31, 223, 61, 254, 122, 84, 158, 251, 191, 242, 219, 83, 226, 31, 126, 243, 255, 85,
207, 61, 114, 221, 191, 244, 220, 223, 253, 246, 79, 94, 91, 42, 67, 211, 60, 118, 179, 80,
70, 125, 3, 217, 199, 251, 187, 118, 95, 187, 138, 221, 223, 190, 63, 255, 171, 55, 254, 237,
247, 255, 127, 163, 255, 194, 141, 112, 217, 42, 242, 227, 126, 203, 9, 167, 20, 82, 103, 150,
188, 215, 228, 39, 240, 253, 224, 191, 61, 87, 34, 70, 245, 95, 3, 167, 66, 236, 192, 72,
46, 41, 236, 55, 81, 41, 222, 62, 90, 6, 175, 78, 94, 39, 112, 139, 54, 66, 206, 225,
84, 222, 154, 155, 187, 248, 177, 242, 137, 251, 188, 167, 172, 118, 166, 221, 50, 246, 181, 198,
0, 161, 253, 51, 169, 80, 99, 159, 52, 150, 203, 109, 12, 238, 48, 150, 62, 199, 181, 122,
246, 88, 165, 204, 224, 119, 25, 147, 23, 18, 183, 223, 45, 133, 217, 55, 225, 215, 194, 209,
71, 249, 173, 251, 67, 237, 47, 196, 189, 62, 68, 252, 231, 224, 236, 57, 51, 156, 51, 124,
31, 236, 144, 5, 132, 188, 247, 57, 181, 145, 17, 218, 30, 64, 193, 53, 57, 165, 221, 227,
120, 217, 243, 153, 235, 244, 39, 197, 249, 38, 54, 195, 126, 243, 232, 110, 45, 55, 71, 174,
125, 55, 2, 249, 180, 54, 203, 26, 167, 102, 158, 186, 214, 217, 60, 114, 110, 214, 145, 90,
209, 205, 210, 6, 118, 66, 36, 161, 202, 121, 150, 231, 233, 142, 13, 111, 153, 224, 237, 201,
145, 143, 111, 237, 171, 238, 94, 23, 37, 96, 213, 153, 211, 114, 131, 219, 112, 15, 62, 238,
230, 183, 233, 48, 206, 248, 245, 250, 243, 219, 27, 121, 234, 62, 105, 30, 31, 107, 63, 153,
135, 57, 93, 90, 254, 126, 139, 24, 87, 119, 187, 56, 222, 193, 22, 21, 147, 234, 70, 44,
176, 236, 150, 71, 235, 217, 219, 199, 65, 142, 51, 3, 217, 205, 142, 101, 177, 49, 113, 222,
150, 33, 239, 118, 90, 31, 11, 103, 54, 62, 127, 183, 200, 246, 214, 51, 70, 177, 167, 249,
141, 81, 162, 153, 145, 235, 226, 110, 197, 214, 86, 114, 240, 13, 44, 108, 241, 128, 92, 21,
75, 207, 48, 86, 171, 102, 252, 172, 143, 18, 16, 250, 212, 179, 90, 202, 49, 237, 83, 211,
217, 179, 140, 112, 86, 8, 101, 111, 219, 196, 28, 126, 202, 145, 117, 149, 177, 249, 112, 88,
187, 59, 174, 97, 61, 103, 109, 222, 217, 43, 213, 129, 41, 113, 208, 19, 184, 186, 41, 236,
0, 163, 25, 241, 19, 152, 115, 48, 192, 6, 108, 9, 54, 2, 10, 194, 83, 117, 95, 118,
193, 190, 112, 3, 62, 124, 147, 194, 214, 99, 62, 159, 147, 2, 119, 63, 122, 50, 1, 173,
224, 197, 118, 60, 58, 17, 225, 51, 159, 222, 166, 75, 96, 125, 111, 132, 125, 221, 227, 172,
210, 219, 78, 3, 201, 1, 7, 238, 133, 29, 240, 201, 17, 202, 4, 13, 227, 60, 79, 8,
83, 209, 254, 237, 162, 2, 149, 165, 239, 210, 71, 2, 104, 65, 225, 88, 222, 185, 65, 92,
2, 207, 191, 74, 72, 223, 107, 189, 63, 192, 17, 127, 251, 254, 252, 122, 65, 217, 138, 3,
210, 138, 169, 158, 26, 198, 94, 99, 19, 104, 189, 144, 162, 50, 46, 97, 175, 101, 135, 187,
236, 18, 199, 38, 26, 84, 15, 113, 15, 6, 120, 136, 250, 165, 85, 173, 131, 61, 8, 217,
108, 22, 33, 126, 72, 50, 42, 99, 47, 45, 141, 177, 139, 118, 190, 112, 103, 133, 253, 165,
53, 217, 79, 10, 215, 170, 137, 187, 181, 82, 96, 108, 56, 155, 176, 62, 212, 71, 74, 71,
44, 148, 4, 246, 74, 62, 80, 226, 192, 18, 174, 38, 84, 1, 145, 124, 148, 209, 1, 151,
227, 43, 42, 38, 235, 242, 24, 50, 251, 17, 195, 234, 245, 89, 176, 163, 85, 129, 23, 43,
85, 179, 231, 57, 128, 129, 220, 222, 226, 48, 209, 196, 35, 175, 167, 36, 121, 125, 146, 184,
131, 240, 133, 218, 49, 91, 72, 153, 71, 186, 51, 170, 97, 197, 120, 110, 208, 167, 76, 124,
205, 60, 106, 37, 45, 202, 206, 56, 122, 165, 217, 240, 107, 9, 153, 220, 225, 213, 25, 195,
144, 99, 43, 102, 105, 206, 130, 184, 175, 104, 241, 70, 73, 61, 104, 145, 182, 120, 21, 186,
102, 9, 208, 135, 235, 37, 207, 188, 118, 88, 121, 80, 8, 227, 9, 197, 145, 242, 196, 249,
98, 239, 155, 162, 155, 91, 223, 189, 36, 216, 114, 108, 138, 108, 3, 161, 199, 110, 222, 217,
181, 167, 70, 135, 96, 47, 70, 139, 145, 89, 249, 101, 229, 126, 194, 219, 10, 212, 125, 84,
123, 175, 221, 247, 120, 46, 145, 85, 29, 81, 5, 158, 134, 243, 144, 191, 21, 56, 22, 92,
242, 70, 132, 181, 181, 61, 193, 219, 52, 132, 162, 199, 135, 5, 153, 92, 144, 3, 124, 12,
241, 32, 199, 220, 77, 222, 78, 237, 38, 190, 73, 38, 96, 207, 177, 181, 215, 119, 57, 80,
182, 111, 150, 17, 69, 203, 202, 90, 231, 137, 107, 192, 29, 54, 121, 58, 112, 58, 65, 225,
214, 177, 231, 158, 190, 229, 51, 152, 138, 127, 9, 59, 192, 243, 217, 7, 143, 27, 192, 34,
69, 88, 1, 80, 74, 230, 122, 2, 2, 178, 10, 49, 218, 30, 245, 25, 88, 50, 142, 39,
179, 18, 88, 95, 20, 122, 132, 10, 89, 62, 210, 122, 217, 19, 172, 226, 57, 35, 151, 102,
184, 227, 252, 212, 154, 242, 205, 123, 133, 224, 181, 88, 198, 153, 30, 212, 108, 61, 64, 134,
194, 134, 228, 44, 177, 141, 66, 112, 117, 62, 147, 197, 75, 214, 115, 241, 128, 155, 175, 226,
79, 31, 74, 70, 60, 191, 13, 153, 58, 208, 198, 10, 134, 69, 124, 129, 222, 176, 76, 18,
36, 13, 60, 169, 237, 133, 173, 236, 188, 232, 249, 40, 134, 102, 132, 41, 171, 150, 52, 153,
147, 164, 133, 196, 181, 232, 26, 203, 134, 225, 245, 30, 38, 198, 127, 207, 155, 209, 113, 101,
18, 71, 241, 200, 96, 23, 16, 39, 159, 33, 223, 89, 81, 215, 71, 9, 32, 2, 170, 237,
21, 166, 156, 165, 103, 41, 36, 1, 181, 122, 166, 187, 117, 73, 160, 65, 18, 243, 184, 161,
21, 145, 2, 211, 242, 72, 219, 31, 15, 153, 216, 123, 37, 252, 66, 201, 86, 2, 171, 219,
176, 78, 106, 34, 60, 238, 110, 80, 169, 233, 118, 247, 34, 119, 105, 249, 161, 164, 163, 92,
46, 21, 99, 128, 125, 147, 145, 164, 136, 150, 69, 141, 3, 247, 224, 118, 20, 17, 144, 223,
15, 54, 211, 26, 245, 42, 1, 32, 212, 39, 254, 155, 209, 190, 37, 1, 205, 198, 56, 212,
150, 23, 191, 229, 124, 204, 240, 33, 60, 100, 122, 144, 103, 63, 100, 27, 20, 8, 108, 26,
40, 245, 40, 127, 21, 238, 205, 95, 240, 17, 163, 115, 213, 155, 85, 210, 169, 240, 20, 21,
4, 36, 107, 167, 102, 12, 188, 155, 31, 10, 152, 128, 195, 17, 57, 62, 18, 144, 34, 13,
171, 79, 200, 188, 165, 51, 254, 27, 150, 133, 181, 192, 174, 235, 152, 67, 21, 186, 129, 88,
41, 2, 187, 44, 111, 245, 196, 158, 250, 243, 26, 128, 84, 130, 64, 201, 212, 20, 59, 5,
152, 200, 88, 120, 32, 192, 66, 229, 50, 118, 62, 5, 112, 74, 18, 99, 38, 102, 96, 101,
104, 5, 253, 182, 167, 12, 132, 71, 104, 250, 82, 126, 182, 240, 177, 223, 152, 200, 252, 64,
2, 164, 30, 28, 96, 8, 241, 217, 14, 82, 64, 24, 102, 64, 138, 236, 42, 100, 178, 79,
88, 218, 99, 148, 27, 192, 241, 233, 134, 186, 94, 185, 5, 130, 116, 75, 200, 183, 173, 114,
25, 74, 128, 84, 89, 153, 181, 171, 200, 192, 4, 199, 129, 134, 59, 238, 230, 7, 136, 91,
149, 97, 162, 27, 15, 47, 69, 31, 79, 38, 4, 210, 104, 6, 122, 94, 112, 138, 61, 99,
109, 155, 234, 45, 144, 216, 8, 129, 169, 20, 75, 31, 16, 18, 234, 88, 107, 100, 213, 31,
101, 123, 120, 96, 103, 152, 206, 226, 5, 41, 176, 11, 165, 172, 189, 162, 38, 4, 2, 85,
122, 1, 216, 131, 48, 144, 163, 225, 45, 235, 45, 162, 129, 150, 155, 96, 175, 3, 212, 148,
92, 208, 133, 71, 207, 17, 135, 81, 161, 35, 214, 96, 129, 220, 23, 103, 97, 161, 209, 165,
80, 112, 148, 152, 32, 129, 200, 19, 21, 38, 193, 234, 1, 245, 200, 205, 164, 208, 220, 86,
14, 158, 78, 82, 96, 246, 68, 170, 17, 249, 77, 162, 163, 112, 201, 164, 90, 87, 139, 43,
69, 219, 250, 147, 92, 101, 196, 150, 224, 92, 229, 252, 67, 136, 240, 220, 36, 192, 77, 142,
235, 181, 210, 84, 196, 157, 136, 105, 39, 178, 52, 124, 40, 226, 91, 177, 64, 53, 222, 168,
68, 194, 191, 92, 2, 43, 250, 104, 78, 223, 19, 24, 39, 69, 142, 85, 130, 158, 60, 245,
212, 93, 70, 212, 163, 213, 43, 240, 111, 35, 184, 186, 7, 179, 131, 178, 47, 222, 212, 5,
94, 215, 222, 152, 138, 231, 58, 182, 11, 236, 186, 167, 144, 96, 228, 76, 211, 155, 100, 97,
193, 60, 4, 92, 144, 7, 182, 246, 78, 201, 111, 1, 60, 160, 230, 173, 133, 30, 36, 101,
163, 248, 149, 74, 186, 168, 213, 12, 162, 85, 165, 63, 220, 50, 98, 97, 16, 102, 19, 227,
34, 188, 64, 173, 235, 164, 108, 72, 221, 7, 81, 43, 69, 22, 120, 216, 12, 138, 196, 224,
148, 120, 42, 97, 243, 24, 20, 145, 155, 117, 162, 32, 201, 112, 161, 42, 73, 87, 150, 63,
137, 226, 153, 192, 135, 67, 21, 25, 170, 136, 51, 53, 41, 58, 2, 183, 140, 254, 226, 226,
97, 208, 214, 214, 47, 174, 71, 218, 239, 6, 248, 39, 160, 46, 33, 239, 66, 47, 16, 4,
162, 41, 105, 89, 248, 54, 33, 177, 225, 226, 99, 186, 182, 223, 77, 140, 96, 214, 140, 147,
11, 201, 78, 100, 93, 156, 95, 31, 245, 127, 20, 88, 183, 138, 12, 191, 98, 41, 75, 26,
4, 42, 251, 67, 51, 221, 111, 160, 26, 108, 39, 31, 166, 198, 76, 242, 17, 46, 112, 19,
86, 116, 158, 84, 222, 13, 163, 161, 34, 128, 167, 16, 63, 239, 177, 166, 182, 70, 145, 167,
164, 24, 61, 39, 89, 177, 17, 1, 26, 201, 35, 128, 63, 8, 185, 180, 21, 68, 60, 148,
226, 68, 226, 10, 14, 201, 199, 245, 72, 213, 77, 158, 123, 195, 191, 73, 11, 80, 38, 73,
143, 37, 103, 16, 83, 4, 185, 128, 24, 45, 178, 221, 129, 10, 144, 64, 10, 201, 194, 14,
122, 204, 253, 41, 61, 240, 176, 96, 76, 176, 126, 30, 117, 215, 163, 199, 69, 210, 136, 13,
81, 60, 214, 38, 203, 187, 74, 224, 54, 101, 210, 224, 160, 42, 31, 133, 68, 79, 108, 53,
63, 178, 204, 80, 12, 201, 74, 191, 57, 138, 58, 200, 134, 37, 186, 42, 59, 192, 99, 195,
98, 26, 252, 100, 73, 7, 226, 68, 97, 74, 113, 215, 216, 39, 232, 66, 201, 118, 174, 166,
154, 10, 95, 220, 59, 8, 60, 151, 54, 64, 160, 1, 222, 152, 42, 167, 27, 235, 231, 242,
67, 161, 210, 23, 63, 235, 18, 215, 4, 229, 131, 229, 60, 124, 18, 154, 20, 124, 216, 133,
136, 12, 136, 177, 6, 100, 93, 190, 10, 177, 8, 1, 223, 146, 99, 235, 64, 198, 133, 244,
202, 82, 252, 1, 12, 46, 105, 15, 1, 126, 67, 231, 237, 39, 201, 3, 196, 38, 49, 73,
72, 146, 159, 33, 37, 101, 1, 118, 59, 37, 104, 63, 208, 73, 161, 182, 226, 116, 32, 233,
168, 121, 81, 232, 36, 237, 230, 72, 30, 104, 130, 131, 156, 61, 20, 77, 129, 196, 43, 0,
137, 197, 79, 72, 249, 14, 240, 194, 172, 32, 204, 205, 41, 223, 131, 113, 78, 65, 54, 53,
11, 159, 241, 40, 39, 141, 89, 164, 42, 163, 83, 72, 150, 71, 80, 5, 213, 195, 92, 20,
80, 149, 68, 132, 6, 44, 114, 165, 97, 120, 40, 85, 44, 56, 69, 224, 156, 216, 137, 45,
192, 108, 19, 67, 65, 202, 69, 112, 163, 53, 27, 137, 192, 145, 132, 60, 30, 5, 244, 218,
76, 101, 194, 30, 179, 200, 233, 60, 92, 181, 96, 145, 16, 156, 13, 137, 254, 253, 165, 208,
196, 127, 88, 120, 130, 233, 128, 102, 232, 78, 200, 168, 219, 183, 4, 29, 209, 36, 164, 23,
161, 43, 128, 36, 187, 21, 242, 38, 104, 136, 117, 160, 187, 149, 23, 85, 74, 133, 65, 61,
29, 110, 54, 236, 215, 237, 29, 116, 110, 63, 109, 52, 68, 30, 69, 34, 131, 48, 206, 68,
3, 213, 211, 152, 167, 173, 53, 201, 197, 198, 82, 60, 55, 23, 43, 202, 166, 89, 20, 146,
150, 9, 4, 174, 96, 234, 161, 78, 72, 7, 35, 180, 8, 175, 34, 9, 138, 8, 122, 179,
147, 67, 122, 170, 128, 44, 92, 198, 132, 1, 194, 17, 162, 87, 102, 181, 104, 130, 178, 3,
74, 210, 6, 6, 145, 3, 240, 119, 0, 158, 138, 82, 95, 47, 38, 112, 117, 83, 47, 96,
62, 32, 113, 137, 83, 45, 241, 62, 213, 110, 138, 228, 67, 228, 217, 104, 159, 212, 34, 122,
143, 135, 131, 207, 19, 0, 131, 251, 129, 144, 157, 253, 151, 214, 193, 250, 168, 150, 106, 193,
86, 3, 7, 53, 165, 159, 234, 68, 95, 144, 50, 146, 2, 182, 46, 86, 208, 169, 141, 94,
98, 10, 1, 124, 178, 174, 68, 51, 120, 128, 13, 211, 170, 134, 229, 36, 157, 233, 51, 60,
126, 174, 80, 129, 25, 29, 130, 184, 45, 174, 211, 116, 59, 159, 96, 25, 64, 73, 220, 74,
132, 202, 26, 234, 132, 31, 207, 18, 164, 160, 186, 127, 36, 26, 218, 192, 46, 183, 62, 13,
85, 73, 50, 52, 124, 25, 170, 134, 129, 56, 104, 137, 138, 87, 146, 13, 192, 41, 201, 50,
109, 123, 11, 247, 88, 92, 40, 169, 63, 8, 157, 164, 88, 188, 40, 233, 151, 76, 123, 57,
57, 37, 106, 143, 89, 249, 240, 91, 59, 27, 36, 129, 6, 27, 223, 89, 29, 5, 66, 107,
163, 201, 50, 162, 105, 0, 131, 136, 154, 70, 38, 227, 41, 107, 154, 136, 205, 9, 220, 171,
84, 170, 49, 243, 203, 228, 200, 171, 33, 86, 156, 215, 205, 208, 122, 243, 179, 43, 113, 182,
114, 39, 118, 34, 59, 6, 98, 12, 171, 196, 212, 155, 12, 54, 74, 119, 146, 16, 165, 89,
163, 1, 90, 209, 68, 181, 43, 155, 53, 205, 27, 216, 104, 115, 9, 43, 131, 113, 112, 164,
98, 21, 49, 63, 75, 113, 180, 111, 179, 2, 168, 19, 214, 188, 146, 180, 78, 25, 46, 36,
2, 132, 143, 113, 97, 229, 59, 124, 102, 163, 201, 177, 3, 40, 58, 212, 1, 192, 78, 210,
91, 243, 137, 192, 185, 39, 172, 97, 184, 71, 232, 69, 76, 189, 229, 178, 32, 88, 241, 16,
192, 6, 1, 108, 81, 127, 3, 101, 121, 147, 134, 219, 10, 96, 221, 82, 14, 226, 128, 41,
9, 49, 179, 101, 196, 47, 208, 145, 249, 173, 135, 192, 82, 5, 214, 38, 22, 142, 129, 181,
160, 105, 201, 68, 101, 85, 81, 72, 28, 39, 71, 244, 157, 211, 35, 172, 162, 122, 85, 16,
66, 138, 3, 52, 87, 237, 134, 187, 11, 171, 177, 128, 213, 131, 5, 113, 104, 9, 165, 140,
86, 130, 209, 104, 65, 183, 233, 241, 31, 35, 62, 127, 90, 113, 164, 203, 33, 13, 155, 225,
12, 170, 240, 225, 118, 176, 66, 138, 2, 79, 103, 150, 227, 65, 106, 140, 213, 132, 97, 90,
49, 14, 153, 69, 26, 160, 98, 163, 176, 91, 202, 64, 119, 137, 152, 197, 168, 93, 233, 57,
28, 214, 173, 43, 179, 96, 112, 160, 17, 245, 38, 4, 196, 215, 55, 23, 231, 97, 162, 218,
128, 45, 199, 114, 219, 114, 88, 41, 147, 102, 67, 44, 90, 107, 100, 115, 230, 105, 42, 75,
138, 62, 111, 231, 9, 197, 189, 237, 231, 23, 205, 24, 48, 97, 100, 111, 167, 72, 149, 55,
2, 210, 11, 95, 246, 117, 63, 73, 133, 126, 57, 138, 105, 128, 240, 234, 12, 234, 106, 83,
191, 176, 40, 14, 112, 70, 159, 92, 55, 101, 152, 179, 227, 79, 233, 232, 79, 120, 87, 109,
41, 101, 135, 141, 122, 120, 81, 254, 246, 139, 163, 198, 230, 99, 78, 111, 67, 14, 55, 142,
14, 42, 101, 196, 49, 232, 55, 200, 253, 30, 197, 218, 198, 149, 26, 79, 147, 194, 226, 158,
106, 206, 225, 226, 36, 148, 27, 214, 206, 84, 101, 29, 84, 127, 32, 7, 171, 160, 36, 242,
11, 89, 116, 11, 240, 94, 162, 11, 44, 110, 177, 9, 8, 14, 121, 85, 30, 114, 114, 173,
139, 173, 91, 89, 5, 54, 81, 248, 12, 201, 113, 242, 109, 107, 18, 118, 32, 210, 199, 174,
127, 104, 154, 40, 222, 196, 178, 216, 26, 194, 168, 114, 132, 250, 82, 37, 196, 198, 236, 117,
73, 233, 58, 159, 173, 143, 201, 211, 34, 193, 244, 18, 149, 174, 227, 0, 79, 105, 30, 136,
36, 88, 235, 146, 90, 4, 126, 244, 147, 26, 154, 235, 89, 121, 126, 171, 49, 85, 13, 197,
83, 31, 138, 162, 234, 136, 38, 238, 69, 117, 253, 17, 131, 1, 159, 89, 183, 64, 18, 162,
83, 4, 73, 218, 83, 94, 91, 133, 123, 186, 119, 14, 8, 237, 96, 227, 241, 64, 98, 71,
248, 35, 222, 4, 195, 34, 93, 250, 254, 2, 79, 224, 95, 173, 1, 157, 73, 12, 33, 18,
42, 25, 212, 213, 226, 245, 175, 202, 76, 122, 253, 211, 166, 18, 1, 10, 89, 71, 110, 181,
114, 33, 111, 84, 104, 126, 7, 68, 37, 171, 102, 86, 106, 198, 233, 17, 56, 179, 85, 29,
102, 218, 123, 81, 221, 90, 34, 52, 183, 201, 19, 18, 108, 164, 197, 2, 107, 233, 158, 146,
176, 179, 248, 71, 4, 52, 34, 193, 223, 241, 6, 174, 158, 199, 128, 23, 37, 74, 165, 73,
141, 100, 113, 40, 80, 208, 71, 213, 157, 172, 116, 120, 207, 33, 179, 40, 140, 214, 75, 98,
107, 206, 161, 22, 231, 215, 175, 137, 151, 2, 94, 110, 140, 224, 92, 249, 0, 12, 151, 144,
13, 107, 79, 18, 22, 104, 192, 49, 186, 199, 226, 143, 0, 78, 72, 168, 176, 145, 240, 254,
112, 213, 187, 172, 238, 223, 201, 222, 146, 244, 68, 80, 103, 76, 17, 7, 7, 173, 128, 218,
190, 202, 159, 227, 29, 36, 157, 157, 4, 255, 12, 145, 26, 4, 92, 208, 97, 236, 160, 74,
1, 161, 1, 180, 201, 171, 87, 79, 42, 131, 190, 25, 255, 138, 45, 234, 172, 8, 74, 220,
117, 210, 146, 169, 255, 95, 3, 223, 25, 231, 69, 138, 18, 244, 104, 55, 228, 115, 67, 48,
44, 194, 62, 249, 228, 73, 229, 122, 42, 133, 0, 158, 13, 111, 25, 254, 167, 145, 72, 70,
144, 247, 10, 21, 146, 227, 118, 18, 91, 68, 187, 61, 4, 114, 253, 164, 59, 22, 175, 212,
129, 178, 47, 177, 34, 169, 92, 196, 156, 224, 24, 10, 127, 138, 159, 138, 118, 204, 203, 249,
253, 20, 250, 108, 17, 73, 62, 24, 97, 254, 173, 34, 41, 79, 97, 27, 78, 100, 45, 188,
184, 111, 195, 69, 69, 29, 176, 188, 43, 248, 51, 15, 74, 26, 16, 167, 77, 138, 222, 226,
66, 223, 29, 46, 133, 73, 108, 162, 27, 238, 247, 176, 179, 121, 79, 51, 178, 255, 79, 203,
20, 66, 71, 145, 59, 21, 134, 182, 132, 227, 68, 7, 16, 53, 76, 6, 92, 21, 128, 83,
106, 199, 142, 196, 17, 74, 47, 173, 199, 169, 203, 11, 12, 5, 5, 145, 2, 34, 75, 243,
22, 35, 176, 170, 184, 106, 219, 34, 184, 151, 178, 216, 5, 49, 59, 226, 66, 149, 175, 88,
163, 224, 216, 93, 87, 160, 174, 241, 17, 11, 143, 15, 223, 40, 198, 144, 170, 136, 40, 152,
89, 185, 141, 208, 223, 188, 5, 138, 20, 36, 199, 18, 99, 32, 64, 85, 20, 4, 82, 83,
68, 70, 32, 72, 174, 145, 222, 179, 126, 45, 249, 125, 139, 116, 184, 177, 196, 90, 144, 127,
209, 89, 29, 18, 188, 97, 86, 18, 10, 69, 8, 42, 150, 137, 138, 129, 18, 0, 15, 81,
149, 240, 81, 55, 200, 72, 53, 144, 170, 192, 24, 96, 106, 181, 104, 198, 21, 148, 149, 169,
115, 31, 229, 188, 5, 77, 81, 7, 13, 141, 88, 16, 11, 248, 94, 88, 169, 37, 160, 110,
159, 95, 76, 193, 154, 83, 69, 201, 175, 222, 242, 158, 219, 206, 125, 200, 254, 210, 154, 193,
76, 182, 130, 160, 75, 0, 43, 117, 164, 144, 8, 112, 57, 229, 104, 91, 239, 83, 212, 146,
160, 58, 168, 237, 78, 250, 16, 186, 224, 16, 242, 224, 181, 118, 149, 85, 57, 181, 201, 88,
94, 5, 199, 216, 175, 91, 6, 213, 226, 120, 77, 196, 41, 189, 18, 206, 231, 161, 118, 81,
56, 18, 50, 192, 190, 215, 12, 40, 193, 170, 168, 185, 41, 240, 193, 168, 99, 166, 220, 35,
20, 108, 11, 251, 107, 206, 139, 250, 208, 89, 30, 43, 41, 46, 17, 19, 37, 194, 109, 208,
34, 30, 192, 233, 249, 141, 222, 240, 115, 66, 119, 200, 182, 161, 119, 209, 218, 220, 70, 26,
177, 231, 78, 24, 145, 162, 17, 160, 17, 175, 76, 144, 108, 157, 142, 32, 124, 69, 235, 82,
126, 106, 2, 91, 67, 145, 12, 75, 164, 66, 193, 213, 98, 230, 126, 111, 169, 50, 98, 154,
205, 96, 37, 211, 125, 113, 91, 143, 163, 94, 201, 166, 126, 176, 3, 161, 50, 32, 10, 171,
149, 51, 23, 1, 164, 195, 97, 162, 37, 151, 74, 69, 145, 254, 200, 175, 5, 37, 63, 133,
99, 153, 171, 18, 214, 84, 102, 122, 181, 226, 97, 194, 115, 127, 108, 102, 60, 170, 30, 193,
202, 7, 236, 183, 246, 16, 21, 1, 144, 250, 101, 181, 215, 122, 110, 42, 68, 69, 221, 104,
136, 72, 26, 166, 102, 130, 85, 96, 121, 246, 118, 180, 220, 126, 132, 82, 228, 182, 180, 198,
78, 84, 215, 201, 198, 2, 203, 54, 56, 123, 151, 188, 31, 193, 249, 233, 17, 6, 170, 45,
39, 182, 23, 200, 5, 158, 151, 78, 159, 92, 37, 70, 151, 39, 32, 163, 33, 31, 11, 212,
254, 89, 222, 176, 213, 13, 105, 241, 226, 43, 89, 63, 66, 128, 141, 76, 157, 103, 163, 85,
176, 165, 95, 58, 197, 96, 55, 87, 104, 217, 9, 163, 53, 16, 36, 79, 212, 203, 203, 58,
196, 208, 169, 12, 96, 30, 85, 168, 119, 54, 201, 23, 148, 235, 144, 8, 56, 49, 200, 1,
92, 77, 170, 91, 83, 171, 236, 246, 225, 252, 165, 53, 119, 255, 169, 188, 234, 167, 80, 13,
213, 201, 70, 163, 195, 152, 182, 122, 147, 0, 19, 246, 149, 232, 189, 42, 119, 97, 254, 100,
112, 147, 174, 20, 168, 82, 104, 51, 193, 252, 203, 128, 127, 41, 79, 178, 76, 7, 96, 176,
86, 103, 157, 183, 123, 20, 74, 132, 43, 157, 73, 23, 171, 32, 151, 0, 233, 56, 106, 5,
170, 95, 65, 18, 178, 214, 83, 159, 43, 113, 213, 171, 224, 106, 5, 6, 43, 177, 196, 136,
231, 117, 40, 181, 18, 155, 2, 95, 100, 25, 97, 40, 178, 167, 228, 27, 95, 215, 210, 24,
46, 72, 145, 230, 99, 180, 186, 168, 73, 101, 196, 250, 30, 188, 94, 48, 153, 197, 208, 4,
34, 51, 35, 9, 86, 201, 80, 200, 64, 207, 152, 188, 75, 118, 82, 13, 208, 48, 69, 166,
26, 237, 249, 74, 157, 1, 199, 146, 234, 167, 218, 160, 50, 72, 130, 98, 237, 102, 57, 244,
88, 187, 249, 47, 220, 184, 32, 37, 137, 113, 223, 212, 141, 164, 64, 74, 75, 179, 150, 121,
153, 151, 206, 117, 100, 28, 83, 84, 67, 130, 53, 69, 116, 30, 82, 52, 59, 98, 200, 117,
184, 227, 199, 246, 41, 176, 240, 88, 86, 140, 206, 218, 210, 107, 138, 7, 245, 21, 88, 26,
59, 130, 20, 139, 191, 97, 40, 117, 56, 240, 193, 148, 38, 147, 180, 46, 20, 2, 30, 167,
120, 227, 190, 81, 15, 112, 150, 209, 77, 115, 15, 108, 77, 22, 66, 78, 18, 222, 212, 220,
1, 82, 135, 27, 244, 95, 203, 168, 191, 58, 213, 4, 194, 121, 198, 201, 81, 244, 58, 24,
84, 169, 237, 119, 27, 54, 75, 105, 129, 166, 5, 79, 43, 181, 193, 62, 222, 202, 47, 68,
85, 248, 117, 245, 156, 200, 65, 98, 236, 165, 58, 12, 181, 171, 96, 88, 91, 19, 33, 23,
196, 142, 129, 24, 73, 172, 62, 164, 94, 241, 4, 6, 49, 136, 142, 46, 36, 110, 129, 59,
228, 174, 238, 126, 138, 20, 92, 86, 70, 154, 68, 174, 224, 87, 117, 136, 143, 186, 0, 189,
212, 146, 128, 168, 242, 234, 186, 39, 70, 228, 22, 59, 173, 239, 100, 235, 71, 152, 72, 14,
130, 60, 106, 83, 214, 244, 38, 247, 58, 185, 142, 75, 128, 68, 196, 48, 126, 202, 81, 60,
204, 73, 214, 192, 255, 118, 7, 100, 22, 37, 91, 231, 124, 60, 96, 10, 81, 169, 205, 83,
252, 23, 9, 134, 17, 224, 69, 234, 161, 173, 14, 14, 123, 24, 91, 159, 145, 228, 240, 240,
76, 225, 3, 251, 156, 77, 57, 56, 90, 134, 67, 190, 118, 118, 74, 229, 216, 243, 167, 33,
40, 253, 245, 171, 213, 124, 174, 228, 145, 144, 137, 90, 111, 66, 201, 191, 221, 14, 172, 15,
106, 2, 128, 132, 102, 36, 244, 26, 200, 20, 179, 47, 200, 2, 51, 118, 21, 100, 13, 51,
252, 130, 202, 178, 76, 165, 42, 105, 225, 92, 26, 75, 154, 26, 57, 156, 173, 131, 94, 89,
43, 76, 14, 207, 182, 140, 141, 38, 80, 248, 138, 249, 35, 242, 140, 218, 168, 224, 93, 122,
102, 2, 228, 15, 197, 8, 233, 1, 72, 190, 146, 87, 196, 219, 135, 236, 78, 202, 172, 7,
194, 218, 143, 66, 136, 215, 10, 18, 162, 52, 209, 180, 202, 66, 237, 64, 194, 109, 19, 2,
221, 81, 240, 224, 129, 210, 166, 91, 122, 232, 168, 36, 135, 106, 240, 122, 196, 24, 32, 163,
217, 189, 124, 14, 215, 31, 201, 245, 142, 170, 141, 48, 113, 138, 75, 81, 107, 120, 65, 57,
217, 219, 80, 35, 118, 10, 253, 173, 53, 69, 112, 1, 72, 203, 105, 6, 86, 103, 78, 139,
236, 207, 141, 93, 146, 1, 144, 193, 8, 215, 69, 126, 36, 69, 176, 164, 176, 82, 213, 180,
207, 107, 201, 186, 174, 202, 156, 192, 32, 41, 134, 33, 98, 21, 164, 174, 86, 96, 7, 207,
79, 107, 11, 62, 107, 146, 4, 115, 77, 163, 204, 71, 98, 123, 245, 25, 212, 175, 194, 40,
85, 67, 7, 19, 232, 136, 31, 49, 219, 218, 26, 153, 233, 3, 64, 177, 159, 217, 205, 58,
78, 42, 176, 253, 85, 62, 2, 239, 248, 247, 130, 14, 49, 210, 126, 199, 156, 243, 182, 254,
235, 54, 179, 63, 255, 155, 219, 232, 40, 11, 6, 64, 129, 85, 243, 19, 150, 34, 192, 143,
188, 172, 9, 131, 153, 20, 49, 212, 72, 120, 37, 32, 153, 159, 43, 238, 0, 135, 171, 175,
197, 112, 127, 88, 207, 190, 200, 2, 231, 249, 154, 16, 176, 187, 150, 164, 232, 142, 76, 138,
97, 151, 117, 109, 172, 97, 240, 168, 163, 243, 170, 107, 176, 79, 157, 8, 86, 145, 60, 72,
165, 117, 198, 224, 16, 234, 75, 7, 107, 154, 12, 191, 9, 57, 170, 219, 6, 22, 154, 10,
176, 122, 114, 226, 169, 73, 53, 251, 105, 95, 83, 206, 218, 197, 1, 43, 159, 183, 130, 165,
227, 235, 239, 239, 175, 47, 254, 115, 212, 120, 187, 226, 71, 185, 161, 169, 226, 227, 8, 141,
151, 95, 194, 179, 172, 51, 191, 162, 128, 152, 16, 222, 170, 139, 58, 224, 2, 42, 142, 245,
246, 150, 69, 157, 58, 15, 195, 112, 218, 206, 86, 117, 78, 101, 215, 133, 252, 101, 226, 243,
163, 127, 228, 4, 0, 35, 161, 207, 250, 108, 160, 7, 200, 23, 169, 34, 119, 26, 130, 162,
33, 78, 141, 117, 41, 46, 22, 150, 121, 42, 44, 127, 14, 51, 95, 29, 103, 168, 201, 191,
213, 91, 157, 214, 246, 214, 44, 167, 78, 89, 167, 178, 72, 179, 4, 148, 13, 216, 81, 211,
204, 152, 19, 237, 23, 107, 31, 20, 114, 117, 107, 251, 70, 103, 178, 157, 51, 68, 34, 64,
106, 157, 30, 14, 117, 241, 236, 96, 69, 39, 171, 34, 194, 129, 114, 3, 139, 231, 50, 176,
2, 5, 184, 208, 19, 109, 36, 23, 9, 44, 138, 129, 180, 48, 47, 198, 250, 138, 250, 193,
6, 188, 80, 63, 224, 233, 121, 46, 135, 189, 168, 126, 75, 51, 4, 135, 192, 129, 234, 83,
246, 254, 222, 133, 87, 229, 134, 89, 188, 29, 45, 18, 97, 52, 160, 60, 165, 145, 204, 134,
28, 125, 173, 211, 172, 126, 103, 131, 66, 203, 204, 27, 77, 27, 244, 82, 85, 227, 49, 91,
167, 102, 169, 237, 184, 200, 121, 205, 152, 120, 247, 16, 127, 224, 14, 48, 235, 161, 18, 247,
144, 72, 212, 72, 110, 134, 73, 19, 69, 146, 118, 124, 6, 162, 91, 197, 110, 69, 8, 193,
90, 136, 170, 72, 139, 218, 145, 98, 189, 233, 60, 57, 233, 28, 182, 223, 227, 160, 153, 44,
86, 222, 94, 188, 84, 144, 141, 101, 32, 208, 160, 94, 148, 95, 112, 17, 89, 140, 235, 82,
229, 95, 12, 14, 228, 71, 138, 162, 142, 89, 251, 120, 212, 250, 207, 119, 140, 36, 235, 152,
171, 94, 65, 102, 199, 42, 106, 198, 82, 61, 117, 130, 42, 42, 106, 157, 242, 117, 69, 209,
119, 180, 185, 1, 124, 104, 32, 69, 6, 90, 3, 158, 134, 239, 184, 142, 82, 209, 110, 139,
249, 92, 46, 116, 7, 115, 166, 198, 109, 34, 252, 124, 252, 103, 200, 0, 0, 197, 176, 154,
208, 177, 99, 158, 250, 192, 88, 186, 128, 243, 178, 83, 34, 117, 218, 177, 179, 245, 55, 38,
172, 79, 103, 54, 243, 37, 75, 239, 192, 87, 253, 213, 235, 118, 26, 189, 208, 76, 211, 64,
41, 236, 169, 3, 223, 63, 15, 2, 75, 2, 64, 164, 145, 180, 175, 22, 116, 86, 212, 91,
74, 198, 65, 102, 69, 189, 117, 245, 168, 79, 114, 246, 74, 82, 1, 12, 167, 230, 103, 124,
103, 85, 46, 228, 123, 180, 43, 126, 131, 83, 200, 86, 92, 175, 158, 107, 27, 247, 96, 37,
206, 159, 225, 183, 57, 238, 236, 27, 11, 194, 144, 80, 149, 62, 234, 3, 253, 135, 104, 82,
248, 196, 145, 118, 203, 47, 143, 15, 43, 249, 16, 242, 171, 233, 157, 65, 165, 28, 219, 166,
147, 52, 221, 38, 57, 184, 235, 117, 61, 14, 67, 235, 142, 150, 102, 27, 235, 33, 26, 137,
249, 145, 141, 169, 86, 29, 162, 78, 216, 132, 211, 249, 249, 130, 33, 36, 29, 195, 59, 9,
35, 101, 175, 14, 237, 168, 165, 154, 205, 202, 214, 242, 168, 238, 246, 80, 41, 144, 75, 140,
25, 224, 12, 210, 13, 154, 53, 211, 88, 213, 50, 140, 208, 105, 8, 22, 52, 77, 77, 65,
93, 147, 116, 132, 221, 0, 251, 26, 248, 200, 100, 155, 130, 20, 21, 68, 161, 174, 72, 81,
104, 244, 45, 11, 26, 160, 240, 245, 103, 18, 113, 240, 96, 29, 18, 98, 169, 163, 113, 2,
204, 99, 211, 39, 160, 104, 180, 3, 101, 157, 191, 93, 209, 173, 255, 141, 227, 177, 54, 197,
37, 187, 197, 78, 181, 135, 14, 85, 109, 24, 43, 15, 40, 81, 212, 156, 46, 149, 48, 184,
16, 186, 199, 1, 16, 209, 208, 223, 49, 126, 17, 67, 153, 59, 182, 231, 167, 67, 254, 53,
200, 143, 211, 105, 145, 82, 123, 93, 112, 226, 105, 166, 215, 178, 225, 208, 111, 212, 154, 66,
181, 127, 59, 106, 124, 254, 233, 172, 145, 130, 129, 225, 116, 232, 80, 179, 218, 230, 168, 5,
77, 26, 22, 235, 34, 132, 123, 188, 218, 13, 128, 213, 255, 190, 7, 119, 207, 109, 137, 163,
43, 113, 244, 176, 35, 31, 155, 232, 186, 179, 118, 214, 250, 109, 73, 103, 160, 36, 29, 171,
42, 214, 11, 93, 187, 103, 175, 150, 241, 202, 250, 63, 49, 26, 241, 90, 32, 90, 177, 3,
152, 170, 202, 91, 103, 199, 254, 170, 133, 100, 109, 250, 108, 243, 45, 84, 243, 95, 147, 105,
149, 212, 208, 73, 227, 58, 150, 199, 4, 135, 78, 79, 154, 159, 200, 245, 169, 243, 147, 31,
86, 6, 190, 68, 168, 120, 254, 99, 178, 208, 14, 231, 17, 39, 8, 116, 116, 16, 81, 161,
65, 0, 117, 176, 236, 64, 177, 107, 188, 0, 27, 65, 124, 1, 55, 111, 229, 71, 69, 210,
106, 143, 206, 177, 27, 143, 183, 49, 165, 113, 197, 230, 55, 196, 64, 46, 138, 58, 131, 84,
170, 200, 93, 44, 71, 168, 243, 104, 142, 71, 115, 44, 200, 71, 82, 192, 210, 205, 223, 146,
141, 116, 251, 108, 20, 172, 15, 60, 70, 100, 177, 142, 74, 220, 125, 98, 117, 5, 135, 39,
79, 217, 208, 49, 217, 120, 108, 62, 193, 9, 119, 250, 136, 205, 94, 45, 70, 235, 240, 112,
134, 10, 88, 177, 53, 118, 169, 34, 29, 191, 148, 232, 34, 15, 175, 141, 126, 216, 184, 172,
70, 171, 242, 61, 149, 209, 172, 169, 216, 23, 149, 60, 129, 85, 83, 227, 17, 80, 255, 198,
175, 24, 131, 250, 143, 144, 31, 183, 107, 6, 74, 17, 252, 226, 37, 71, 147, 14, 222, 236,
251, 168, 155, 255, 225, 99, 68, 91, 66, 246, 118, 188, 212, 235, 158, 235, 187, 123, 174, 175,
106, 169, 89, 8, 63, 156, 205, 249, 96, 198, 97, 88, 0, 163, 80, 7, 27, 50, 74, 74,
105, 182, 198, 137, 216, 147, 250, 9, 96, 234, 234, 35, 218, 40, 84, 89, 54, 182, 170, 97,
51, 13, 78, 156, 63, 6, 51, 200, 4, 151, 53, 60, 37, 229, 247, 204, 31, 168, 81, 255,
221, 161, 87, 82, 106, 96, 220, 86, 55, 131, 196, 66, 47, 84, 155, 213, 43, 136, 242, 122,
71, 135, 178, 127, 127, 205, 16, 105, 80, 161, 13, 18, 227, 169, 125, 86, 145, 101, 137, 81,
235, 50, 107, 14, 99, 94, 135, 171, 247, 222, 177, 43, 14, 130, 214, 199, 217, 81, 16, 80,
71, 234, 29, 57, 55, 187, 198, 220, 246, 29, 122, 201, 237, 161, 108, 43, 93, 145, 225, 214,
106, 132, 39, 156, 114, 107, 200, 199, 104, 190, 161, 170, 84, 49, 134, 166, 71, 109, 20, 76,
190, 26, 214, 47, 81, 119, 78, 231, 47, 207, 157, 105, 145, 254, 158, 196, 202, 235, 212, 178,
234, 223, 201, 62, 58, 6, 51, 19, 13, 223, 208, 213, 219, 197, 192, 175, 254, 207, 97, 214,
127, 158, 208, 252, 237, 59, 92, 15, 222, 136, 18, 91, 213, 14, 84, 197, 186, 86, 253, 109,
149, 132, 6, 172, 121, 27, 140, 116, 155, 255, 48, 24, 73, 191, 96, 100, 127, 205, 74, 236,
218, 71, 210, 112, 17, 169, 85, 146, 17, 46, 74, 184, 27, 34, 12, 247, 188, 173, 152, 126,
16, 171, 144, 108, 43, 235, 201, 106, 217, 109, 117, 217, 65, 180, 161, 97, 143, 215, 132, 188,
242, 177, 200, 243, 58, 21, 201, 146, 221, 20, 231, 92, 139, 26, 43, 154, 204, 98, 235, 249,
14, 232, 222, 222, 237, 51, 92, 87, 63, 71, 253, 174, 212, 122, 116, 66, 5, 141, 126, 74,
196, 15, 96, 229, 64, 249, 129, 204, 98, 244, 48, 216, 184, 223, 47, 32, 212, 97, 215, 229,
109, 45, 63, 136, 249, 87, 101, 67, 72, 121, 103, 149, 116, 198, 71, 146, 19, 118, 187, 104,
54, 51, 68, 73, 201, 214, 32, 195, 30, 138, 145, 26, 64, 37, 215, 135, 51, 46, 207, 29,
63, 35, 122, 73, 125, 75, 77, 220, 232, 118, 54, 39, 58, 48, 54, 208, 131, 160, 203, 136,
217, 23, 129, 84, 28, 181, 78, 13, 198, 149, 47, 93, 87, 251, 84, 83, 164, 72, 114, 84,
112, 28, 79, 122, 107, 43, 151, 107, 33, 182, 52, 3, 104, 121, 133, 0, 134, 27, 196, 163,
97, 58, 117, 141, 190, 153, 196, 32, 74, 6, 74, 128, 216, 194, 195, 109, 227, 71, 249, 158,
247, 119, 117, 215, 124, 29, 232, 209, 16, 43, 148, 152, 34, 172, 225, 10, 96, 239, 126, 92,
120, 121, 199, 149, 68, 165, 117, 39, 2, 146, 130, 90, 165, 56, 139, 141, 81, 249, 148, 158,
31, 90, 165, 246, 167, 5, 103, 130, 45, 106, 168, 146, 64, 119, 21, 218, 157, 82, 168, 94,
99, 117, 189, 6, 157, 108, 184, 159, 188, 0, 218, 48, 115, 105, 106, 115, 47, 103, 122, 141,
212, 34, 177, 140, 198, 188, 44, 175, 46, 201, 140, 241, 13, 100, 218, 184, 136, 152, 53, 161,
169, 1, 183, 228, 99, 211, 188, 114, 177, 170, 91, 132, 225, 164, 85, 213, 57, 173, 209, 156,
74, 58, 34, 147, 54, 244, 90, 44, 173, 82, 152, 37, 216, 120, 52, 32, 83, 239, 212, 189,
2, 199, 198, 44, 53, 184, 101, 110, 71, 28, 58, 248, 58, 32, 250, 88, 198, 171, 168, 169,
238, 124, 61, 228, 76, 204, 244, 64, 41, 163, 64, 80, 27, 94, 72, 43, 92, 110, 14, 157,
31, 53, 155, 79, 185, 51, 137, 9, 107, 190, 119, 58, 241, 125, 126, 126, 248, 215, 223, 187,
248, 62, 248, 119, 0, 56, 101, 191, 245, 72, 183, 114, 18, 136, 41, 42, 197, 147, 74, 20,
34, 229, 211, 181, 80, 65, 247, 72, 241, 36, 165, 52, 119, 104, 188, 99, 223, 196, 184, 72,
175, 33, 172, 162, 115, 140, 231, 78, 244, 89, 225, 249, 166, 29, 86, 85, 23, 61, 166, 24,
208, 100, 101, 189, 64, 16, 112, 132, 40, 88, 226, 76, 94, 92, 26, 254, 115, 231, 125, 151,
254, 119, 192, 69, 188, 237, 199, 95, 93, 22, 221, 55, 28, 40, 223, 132, 52, 167, 104, 28,
144, 17, 200, 225, 69, 253, 61, 214, 1, 35, 5, 0, 13, 121, 57, 150, 111, 196, 168, 152,
36, 105, 241, 249, 160, 138, 180, 73, 209, 102, 241, 209, 38, 163, 252, 76, 153, 183, 127, 154,
50, 255, 199, 239, 207, 255, 233, 133, 255, 239, 221, 72, 212, 186, 61, 255, 19, 187, 127, 241,
97, 132, 149, 181, 233, 0, 0, 1, 132, 105, 67, 67, 80, 73, 67, 67, 32, 112, 114, 111,
102, 105, 108, 101, 0, 0, 120, 156, 125, 145, 61, 72, 195, 64, 28, 197, 95, 211, 74, 69,
170, 14, 22, 17, 113, 200, 80, 157, 44, 20, 21, 113, 212, 42, 20, 161, 66, 168, 21, 90,
117, 48, 185, 244, 11, 154, 52, 36, 45, 46, 142, 130, 107, 193, 193, 143, 197, 170, 131, 139,
179, 174, 14, 174, 130, 32, 248, 1, 226, 232, 228, 164, 232, 34, 37, 254, 47, 41, 180, 136,
241, 224, 184, 31, 239, 238, 61, 238, 222, 1, 66, 163, 204, 52, 43, 16, 3, 52, 189, 106,
166, 18, 113, 49, 147, 93, 21, 131, 175, 8, 160, 15, 131, 0, 98, 50, 179, 140, 57, 73,
74, 194, 115, 124, 221, 195, 199, 215, 187, 40, 207, 242, 62, 247, 231, 232, 85, 115, 22, 3,
124, 34, 241, 44, 51, 204, 42, 241, 6, 241, 244, 102, 213, 224, 188, 79, 28, 102, 69, 89,
37, 62, 39, 30, 55, 233, 130, 196, 143, 92, 87, 92, 126, 227, 92, 112, 88, 224, 153, 97,
51, 157, 154, 39, 14, 19, 139, 133, 14, 86, 58, 152, 21, 77, 141, 120, 138, 56, 162, 106,
58, 229, 11, 25, 151, 85, 206, 91, 156, 181, 114, 141, 181, 238, 201, 95, 24, 202, 233, 43,
203, 92, 167, 57, 130, 4, 22, 177, 4, 9, 34, 20, 212, 80, 66, 25, 85, 68, 105, 213,
73, 177, 144, 162, 253, 184, 135, 127, 216, 241, 75, 228, 82, 200, 85, 2, 35, 199, 2, 42,
208, 32, 59, 126, 240, 63, 248, 221, 173, 149, 159, 156, 112, 147, 66, 113, 160, 235, 197, 182,
63, 70, 129, 224, 46, 208, 172, 219, 246, 247, 177, 109, 55, 79, 0, 255, 51, 112, 165, 183,
253, 149, 6, 48, 243, 73, 122, 189, 173, 69, 142, 128, 254, 109, 224, 226, 186, 173, 41, 123,
192, 229, 14, 48, 244, 100, 200, 166, 236, 72, 126, 154, 66, 62, 15, 188, 159, 209, 55, 101,
129, 129, 91, 160, 103, 205, 237, 173, 181, 143, 211, 7, 32, 77, 93, 37, 111, 128, 131, 67,
96, 172, 64, 217, 235, 30, 239, 238, 238, 236, 237, 223, 51, 173, 254, 126, 0, 74, 241, 114,
151, 40, 2, 220, 52, 0, 0, 13, 26, 105, 84, 88, 116, 88, 77, 76, 58, 99, 111, 109,
46, 97, 100, 111, 98, 101, 46, 120, 109, 112, 0, 0, 0, 0, 0, 60, 63, 120, 112, 97,
99, 107, 101, 116, 32, 98, 101, 103, 105, 110, 61, 34, 239, 187, 191, 34, 32, 105, 100, 61,
34, 87, 53, 77, 48, 77, 112, 67, 101, 104, 105, 72, 122, 114, 101, 83, 122, 78, 84, 99,
122, 107, 99, 57, 100, 34, 63, 62, 10, 60, 120, 58, 120, 109, 112, 109, 101, 116, 97, 32,
120, 109, 108, 110, 115, 58, 120, 61, 34, 97, 100, 111, 98, 101, 58, 110, 115, 58, 109, 101,
116, 97, 47, 34, 32, 120, 58, 120, 109, 112, 116, 107, 61, 34, 88, 77, 80, 32, 67, 111,
114, 101, 32, 52, 46, 52, 46, 48, 45, 69, 120, 105, 118, 50, 34, 62, 10, 32, 60, 114,
100, 102, 58, 82, 68, 70, 32, 120, 109, 108, 110, 115, 58, 114, 100, 102, 61, 34, 104, 116,
116, 112, 58, 47, 47, 119, 119, 119, 46, 119, 51, 46, 111, 114, 103, 47, 49, 57, 57, 57,
47, 48, 50, 47, 50, 50, 45, 114, 100, 102, 45, 115, 121, 110, 116, 97, 120, 45, 110, 115,
35, 34, 62, 10, 32, 32, 60, 114, 100, 102, 58, 68, 101, 115, 99, 114, 105, 112, 116, 105,
111, 110, 32, 114, 100, 102, 58, 97, 98, 111, 117, 116, 61, 34, 34, 10, 32, 32, 32, 32,
120, 109, 108, 110, 115, 58, 120, 109, 112, 77, 77, 61, 34, 104, 116, 116, 112, 58, 47, 47,
110, 115, 46, 97, 100, 111, 98, 101, 46, 99, 111, 109, 47, 120, 97, 112, 47, 49, 46, 48,
47, 109, 109, 47, 34, 10, 32, 32, 32, 32, 120, 109, 108, 110, 115, 58, 115, 116, 69, 118,
116, 61, 34, 104, 116, 116, 112, 58, 47, 47, 110, 115, 46, 97, 100, 111, 98, 101, 46, 99,
111, 109, 47, 120, 97, 112, 47, 49, 46, 48, 47, 115, 84, 121, 112, 101, 47, 82, 101, 115,
111, 117, 114, 99, 101, 69, 118, 101, 110, 116, 35, 34, 10, 32, 32, 32, 32, 120, 109, 108,
110, 115, 58, 100, 99, 61, 34, 104, 116, 116, 112, 58, 47, 47, 112, 117, 114, 108, 46, 111,
114, 103, 47, 100, 99, 47, 101, 108, 101, 109, 101, 110, 116, 115, 47, 49, 46, 49, 47, 34,
10, 32, 32, 32, 32, 120, 109, 108, 110, 115, 58, 71, 73, 77, 80, 61, 34, 104, 116, 116,
112, 58, 47, 47, 119, 119, 119, 46, 103, 105, 109, 112, 46, 111, 114, 103, 47, 120, 109, 112,
47, 34, 10, 32, 32, 32, 32, 120, 109, 108, 110, 115, 58, 116, 105, 102, 102, 61, 34, 104,
116, 116, 112, 58, 47, 47, 110, 115, 46, 97, 100, 111, 98, 101, 46, 99, 111, 109, 47, 116,
105, 102, 102, 47, 49, 46, 48, 47, 34, 10, 32, 32, 32, 32, 120, 109, 108, 110, 115, 58,
120, 109, 112, 61, 34, 104, 116, 116, 112, 58, 47, 47, 110, 115, 46, 97, 100, 111, 98, 101,
46, 99, 111, 109, 47, 120, 97, 112, 47, 49, 46, 48, 47, 34, 10, 32, 32, 32, 120, 109,
112, 77, 77, 58, 68, 111, 99, 117, 109, 101, 110, 116, 73, 68, 61, 34, 103, 105, 109, 112,
58, 100, 111, 99, 105, 100, 58, 103, 105, 109, 112, 58, 53, 97, 97, 52, 98, 49, 57, 56,
45, 53, 56, 100, 101, 45, 52, 100, 102, 56, 45, 57, 54, 54, 51, 45, 53, 54, 98, 97,
98, 50, 50, 100, 57, 54, 51, 56, 34, 10, 32, 32, 32, 120, 109, 112, 77, 77, 58, 73,
110, 115, 116, 97, 110, 99, 101, 73, 68, 61, 34, 120, 109, 112, 46, 105, 105, 100, 58, 102,
100, 48, 54, 102, 54, 56, 99, 45, 48, 98, 54, 55, 45, 52, 55, 49, 102, 45, 56, 97,
50, 97, 45, 100, 51, 48, 54, 100, 99, 52, 98, 56, 54, 97, 56, 34, 10, 32, 32, 32,
120, 109, 112, 77, 77, 58, 79, 114, 105, 103, 105, 110, 97, 108, 68, 111, 99, 117, 109, 101,
110, 116, 73, 68, 61, 34, 120, 109, 112, 46, 100, 105, 100, 58, 50, 98, 53, 57, 100, 99,
49, 56, 45, 97, 48, 51, 97, 45, 52, 100, 53, 57, 45, 56, 56, 48, 97, 45, 56, 56,
99, 54, 51, 53, 57, 48, 54, 98, 49, 52, 34, 10, 32, 32, 32, 100, 99, 58, 70, 111,
114, 109, 97, 116, 61, 34, 105, 109, 97, 103, 101, 47, 112, 110, 103, 34, 10, 32, 32, 32,
71, 73, 77, 80, 58, 65, 80, 73, 61, 34, 50, 46, 48, 34, 10, 32, 32, 32, 71, 73,
77, 80, 58, 80, 108, 97, 116, 102, 111, 114, 109, 61, 34, 76, 105, 110, 117, 120, 34, 10,
32, 32, 32, 71, 73, 77, 80, 58, 84, 105, 109, 101, 83, 116, 97, 109, 112, 61, 34, 49,
54, 52, 57, 57, 55, 51, 55, 57, 48, 55, 54, 55, 49, 55, 51, 34, 10, 32, 32, 32,
71, 73, 77, 80, 58, 86, 101, 114, 115, 105, 111, 110, 61, 34, 50, 46, 49, 48, 46, 51,
48, 34, 10, 32, 32, 32, 116, 105, 102, 102, 58, 79, 114, 105, 101, 110, 116, 97, 116, 105,
111, 110, 61, 34, 49, 34, 10, 32, 32, 32, 120, 109, 112, 58, 67, 114, 101, 97, 116, 111,
114, 84, 111, 111, 108, 61, 34, 71, 73, 77, 80, 32, 50, 46, 49, 48, 34, 62, 10, 32,
32, 32, 60, 120, 109, 112, 77, 77, 58, 72, 105, 115, 116, 111, 114, 121, 62, 10, 32, 32,
32, 32, 60, 114, 100, 102, 58, 83, 101, 113, 62, 10, 32, 32, 32, 32, 32, 60, 114, 100,
102, 58, 108, 105, 10, 32, 32, 32, 32, 32, 32, 115, 116, 69, 118, 116, 58, 97, 99, 116,
105, 111, 110, 61, 34, 115, 97, 118, 101, 100, 34, 10, 32, 32, 32, 32, 32, 32, 115, 116,
69, 118, 116, 58, 99, 104, 97, 110, 103, 101, 100, 61, 34, 47, 34, 10, 32, 32, 32, 32,
32, 32, 115, 116, 69, 118, 116, 58, 105, 110, 115, 116, 97, 110, 99, 101, 73, 68, 61, 34,
120, 109, 112, 46, 105, 105, 100, 58, 51, 102, 102, 101, 98, 52, 98, 50, 45, 50, 99, 53,
49, 45, 52, 102, 54, 56, 45, 56, 56, 50, 48, 45, 99, 55, 101, 55, 53, 52, 48, 55,
53, 99, 97, 51, 34, 10, 32, 32, 32, 32, 32, 32, 115, 116, 69, 118, 116, 58, 115, 111,
102, 116, 119, 97, 114, 101, 65, 103, 101, 110, 116, 61, 34, 71, 105, 109, 112, 32, 50, 46,
49, 48, 32, 40, 76, 105, 110, 117, 120, 41, 34, 10, 32, 32, 32, 32, 32, 32, 115, 116,
69, 118, 116, 58, 119, 104, 101, 110, 61, 34, 50, 48, 50, 50, 45, 48, 52, 45, 49, 53,
84, 48, 48, 58, 48, 51, 58, 49, 48, 43, 48, 50, 58, 48, 48, 34, 47, 62, 10, 32,
32, 32, 32, 60, 47, 114, 100, 102, 58, 83, 101, 113, 62, 10, 32, 32, 32, 60, 47, 120,
109, 112, 77, 77, 58, 72, 105, 115, 116, 111, 114, 121, 62, 10, 32, 32, 60, 47, 114, 100,
102, 58, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 62, 10, 32, 60, 47, 114, 100,
102, 58, 82, 68, 70, 62, 10, 60, 47, 120, 58, 120, 109, 112, 109, 101, 116, 97, 62, 10,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10,
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
32, 32, 32, 32, 32, 32, 32, 10, 60, 63, 120, 112, 97, 99, 107, 101, 116, 32, 101, 110,
100, 61, 34, 119, 34, 63, 62, 72, 241, 114, 133, 0, 0, 0, 6, 98, 75, 71, 68, 0,
255, 0, 157, 0, 209, 55, 56, 181, 18, 0, 0, 0, 9, 112, 72, 89, 115, 0, 0, 15,
97, 0, 0, 15, 97, 1, 168, 63, 167, 105, 0, 0, 0, 7, 116, 73, 77, 69, 7, 230,
4, 14, 22, 3, 10, 202, 197, 230, 211, 0, 0, 24, 126, 73, 68, 65, 84, 120, 218, 237,
122, 121, 144, 156, 199, 117, 223, 175, 175, 239, 156, 115, 119, 102, 239, 3, 88, 92, 139, 155,
160, 120, 8, 16, 111, 136, 37, 90, 180, 73, 198, 169, 136, 82, 172, 40, 150, 19, 91, 150,
29, 187, 162, 200, 149, 84, 172, 148, 195, 18, 21, 151, 93, 177, 108, 185, 74, 145, 109, 217,
114, 164, 136, 166, 25, 210, 148, 68, 136, 18, 33, 30, 34, 9, 18, 16, 65, 226, 220, 37,
1, 44, 128, 221, 197, 46, 246, 158, 157, 217, 217, 185, 190, 249, 142, 238, 206, 31, 59, 75,
46, 22, 0, 41, 197, 82, 98, 39, 120, 85, 93, 61, 61, 245, 205, 87, 243, 126, 253, 222,
235, 247, 250, 247, 128, 107, 114, 77, 174, 201, 53, 185, 38, 215, 228, 154, 92, 147, 107, 242,
255, 167, 144, 127, 96, 239, 213, 255, 88, 1, 32, 43, 230, 149, 131, 174, 24, 100, 197, 115,
186, 49, 84, 99, 232, 21, 179, 94, 5, 132, 254, 135, 8, 192, 74, 133, 41, 0, 6, 192,
236, 54, 59, 98, 123, 123, 110, 237, 238, 75, 118, 175, 105, 113, 211, 107, 108, 33, 178, 156,
33, 205, 41, 226, 132, 42, 83, 35, 82, 32, 145, 214, 8, 195, 72, 7, 85, 79, 122, 115,
229, 160, 50, 55, 81, 158, 155, 60, 50, 121, 110, 236, 208, 204, 112, 46, 82, 170, 10, 192,
3, 16, 0, 144, 141, 113, 37, 96, 254, 175, 0, 176, 188, 139, 12, 128, 249, 64, 231, 3,
237, 183, 118, 220, 178, 167, 213, 205, 220, 18, 55, 237, 235, 146, 166, 179, 33, 97, 218, 9,
83, 48, 98, 112, 2, 193, 0, 198, 20, 24, 83, 32, 36, 2, 161, 17, 64, 66, 104, 18,
65, 33, 64, 164, 235, 136, 224, 35, 80, 117, 120, 81, 77, 150, 131, 114, 113, 49, 40, 95,
88, 172, 87, 78, 143, 47, 230, 142, 191, 50, 122, 238, 216, 254, 209, 243, 99, 0, 22, 27,
160, 132, 171, 44, 229, 255, 24, 0, 203, 59, 45, 62, 218, 243, 137, 222, 59, 59, 238, 122,
160, 197, 201, 220, 151, 177, 211, 215, 167, 237, 152, 229, 26, 38, 76, 78, 27, 138, 202, 134,
162, 17, 8, 13, 1, 18, 1, 52, 2, 33, 17, 64, 195, 198, 28, 129, 144, 112, 197, 247,
75, 192, 128, 132, 144, 8, 224, 203, 58, 60, 89, 67, 201, 175, 200, 153, 202, 194, 240, 116,
121, 225, 240, 43, 163, 163, 207, 124, 253, 248, 224, 113, 13, 228, 0, 84, 87, 129, 241, 51,
3, 128, 0, 160, 156, 8, 235, 63, 109, 253, 131, 221, 253, 233, 205, 159, 238, 112, 219, 126,
46, 99, 167, 237, 184, 105, 131, 51, 128, 82, 217, 80, 114, 165, 114, 151, 174, 151, 193, 88,
189, 198, 10, 171, 88, 9, 198, 50, 56, 104, 88, 74, 45, 172, 33, 239, 149, 212, 116, 185,
56, 126, 54, 151, 219, 255, 141, 215, 7, 190, 253, 198, 116, 225, 12, 128, 2, 128, 250, 10,
55, 249, 169, 2, 64, 1, 24, 15, 109, 251, 147, 61, 219, 210, 59, 63, 215, 29, 235, 189,
35, 99, 55, 81, 91, 112, 16, 42, 175, 170, 236, 242, 250, 29, 229, 150, 148, 213, 141, 29,
86, 8, 160, 72, 8, 141, 16, 154, 4, 111, 63, 71, 169, 4, 99, 18, 148, 74, 208, 198,
188, 12, 206, 242, 123, 34, 29, 160, 228, 87, 48, 85, 42, 214, 206, 230, 230, 95, 126, 106,
112, 248, 145, 39, 223, 156, 56, 12, 96, 174, 225, 34, 63, 49, 16, 228, 106, 187, 254, 47,
122, 126, 189, 227, 67, 93, 247, 127, 190, 47, 190, 225, 227, 109, 78, 7, 183, 184, 0, 33,
242, 178, 29, 90, 253, 39, 201, 42, 229, 65, 67, 68, 186, 142, 51, 133, 97, 228, 189, 124,
84, 10, 74, 94, 53, 170, 150, 165, 14, 171, 10, 145, 175, 16, 249, 156, 2, 166, 32, 194,
18, 212, 114, 77, 238, 38, 109, 17, 75, 59, 70, 44, 97, 113, 102, 155, 4, 142, 73, 96,
114, 13, 202, 150, 222, 169, 73, 136, 106, 224, 97, 178, 180, 24, 188, 57, 157, 59, 240, 244,
224, 133, 111, 60, 62, 48, 125, 8, 192, 108, 195, 34, 126, 108, 215, 224, 87, 80, 158, 255,
225, 117, 127, 177, 119, 71, 250, 250, 63, 95, 19, 95, 223, 155, 16, 73, 16, 130, 37, 112,
73, 227, 180, 34, 141, 24, 212, 88, 147, 75, 214, 43, 103, 5, 2, 13, 66, 0, 131, 49,
88, 156, 163, 26, 17, 165, 180, 242, 170, 97, 125, 108, 174, 186, 112, 250, 249, 243, 231, 142,
134, 33, 157, 1, 224, 135, 50, 34, 190, 242, 205, 186, 242, 98, 49, 147, 100, 62, 208, 215,
182, 102, 91, 123, 102, 93, 119, 58, 182, 169, 43, 237, 174, 237, 72, 218, 177, 164, 195, 224,
90, 64, 220, 230, 216, 100, 39, 141, 206, 38, 241, 193, 45, 29, 238, 45, 183, 109, 204, 124,
247, 11, 223, 63, 245, 151, 51, 53, 57, 8, 96, 97, 69, 140, 120, 87, 97, 43, 149, 231,
68, 24, 255, 237, 198, 71, 63, 117, 67, 102, 207, 95, 175, 79, 110, 106, 118, 184, 11, 178,
164, 61, 8, 85, 0, 145, 0, 85, 32, 68, 53, 230, 75, 215, 32, 178, 241, 156, 2, 161,
114, 105, 38, 10, 10, 17, 24, 5, 66, 21, 160, 80, 47, 85, 75, 126, 117, 222, 143, 194,
185, 132, 233, 86, 214, 55, 183, 210, 142, 100, 115, 169, 213, 236, 59, 191, 43, 243, 254, 145,
245, 201, 141, 19, 25, 179, 245, 2, 85, 246, 208, 88, 46, 56, 242, 210, 240, 196, 203, 223,
28, 60, 242, 131, 39, 78, 156, 126, 190, 228, 213, 206, 86, 130, 122, 88, 143, 194, 52, 163,
218, 54, 5, 224, 154, 4, 153, 184, 193, 123, 155, 173, 173, 31, 88, 159, 186, 51, 105, 17,
249, 198, 120, 57, 7, 160, 214, 112, 137, 31, 251, 60, 55, 254, 234, 230, 111, 253, 251, 157,
77, 239, 123, 168, 221, 233, 164, 148, 172, 192, 134, 168, 183, 205, 124, 101, 212, 38, 87, 113,
131, 229, 152, 160, 73, 136, 162, 95, 192, 80, 97, 56, 56, 56, 113, 114, 228, 185, 243, 111,
30, 177, 73, 211, 64, 135, 219, 117, 161, 205, 105, 207, 101, 172, 108, 37, 97, 36, 106, 174,
136, 123, 113, 35, 225, 37, 141, 180, 55, 80, 253, 65, 58, 178, 78, 95, 31, 51, 35, 241,
244, 224, 204, 137, 185, 133, 176, 232, 73, 207, 31, 170, 191, 169, 1, 152, 0, 210, 54, 35,
189, 159, 189, 115, 235, 7, 111, 232, 109, 254, 133, 254, 118, 119, 83, 91, 82, 16, 203, 208,
240, 101, 128, 177, 124, 53, 122, 225, 244, 220, 190, 207, 126, 123, 232, 203, 74, 99, 160, 113,
132, 94, 53, 54, 44, 3, 32, 190, 122, 211, 223, 253, 214, 245, 205, 55, 253, 215, 54, 167,
147, 82, 66, 87, 61, 37, 175, 30, 181, 201, 82, 128, 211, 36, 128, 130, 15, 133, 0, 154,
46, 5, 185, 217, 218, 140, 126, 118, 244, 224, 228, 99, 131, 175, 190, 220, 227, 174, 127, 245,
186, 204, 251, 206, 246, 167, 183, 148, 50, 86, 51, 76, 102, 48, 70, 24, 165, 132, 42, 70,
184, 207, 169, 225, 89, 204, 169, 74, 133, 250, 201, 252, 49, 86, 73, 238, 187, 189, 189, 169,
254, 59, 181, 176, 62, 242, 226, 249, 177, 111, 61, 61, 48, 115, 34, 39, 103, 230, 27, 62,
78, 0, 196, 0, 116, 126, 230, 246, 117, 119, 239, 237, 207, 254, 242, 230, 78, 183, 191, 53,
33, 192, 40, 193, 76, 169, 142, 67, 231, 243, 199, 63, 247, 173, 83, 127, 112, 161, 20, 189,
138, 165, 163, 51, 186, 18, 8, 4, 0, 253, 147, 235, 255, 251, 207, 223, 148, 189, 229, 137,
222, 88, 159, 113, 153, 242, 208, 151, 28, 95, 154, 4, 136, 224, 193, 147, 101, 212, 100, 9,
229, 112, 65, 21, 252, 121, 175, 18, 45, 86, 43, 81, 169, 90, 139, 42, 85, 169, 67, 95,
35, 138, 134, 10, 99, 179, 167, 166, 11, 111, 220, 220, 178, 231, 216, 205, 173, 239, 47, 52,
219, 77, 54, 5, 154, 65, 84, 138, 128, 184, 141, 24, 164, 150, 148, 34, 37, 70, 68, 206,
100, 246, 28, 135, 181, 112, 177, 58, 17, 62, 159, 123, 172, 251, 246, 157, 243, 95, 108, 73,
24, 187, 11, 94, 229, 248, 143, 70, 47, 254, 237, 23, 95, 57, 249, 156, 6, 38, 26, 38,
14, 0, 174, 160, 164, 231, 161, 15, 175, 251, 200, 237, 155, 50, 191, 186, 169, 45, 222, 28,
55, 57, 138, 94, 136, 215, 70, 10, 163, 15, 127, 247, 244, 239, 31, 157, 242, 126, 208, 8,
144, 225, 106, 16, 200, 131, 189, 159, 204, 254, 114, 223, 111, 12, 110, 73, 239, 108, 21, 84,
92, 193, 72, 20, 52, 9, 225, 235, 50, 74, 97, 30, 51, 222, 68, 116, 161, 124, 126, 126,
188, 114, 97, 226, 100, 254, 196, 200, 129, 217, 87, 71, 203, 178, 50, 197, 33, 242, 9, 154,
42, 185, 44, 86, 205, 152, 45, 65, 135, 211, 165, 123, 227, 125, 122, 123, 211, 142, 112, 77,
188, 199, 230, 140, 118, 82, 66, 58, 57, 229, 25, 70, 121, 140, 17, 102, 18, 80, 6, 104,
165, 180, 10, 35, 29, 121, 82, 69, 69, 165, 213, 52, 131, 113, 193, 98, 177, 139, 165, 160,
82, 250, 206, 248, 163, 217, 187, 119, 143, 125, 121, 71, 103, 234, 22, 95, 250, 250, 204, 92,
110, 240, 249, 161, 177, 175, 127, 229, 71, 103, 159, 5, 48, 217, 56, 254, 8, 128, 196, 61,
253, 169, 235, 62, 117, 219, 218, 135, 118, 245, 164, 118, 183, 38, 44, 84, 252, 8, 175, 13,
231, 39, 62, 251, 248, 224, 231, 207, 22, 194, 103, 26, 32, 92, 98, 9, 36, 193, 211, 206,
215, 118, 63, 249, 189, 247, 101, 222, 127, 135, 197, 236, 75, 85, 215, 10, 165, 176, 128, 41,
239, 130, 58, 85, 60, 49, 247, 250, 220, 193, 211, 79, 79, 60, 117, 162, 40, 23, 78, 1,
184, 208, 120, 97, 177, 133, 181, 123, 27, 227, 155, 195, 38, 43, 19, 109, 78, 237, 192, 214,
244, 14, 210, 238, 118, 154, 38, 227, 201, 72, 121, 189, 10, 225, 38, 78, 69, 175, 201, 173,
140, 193, 140, 56, 103, 194, 97, 132, 26, 132, 128, 234, 37, 4, 34, 169, 100, 61, 148, 65,
197, 151, 245, 98, 32, 131, 41, 2, 114, 214, 98, 241, 179, 245, 40, 44, 60, 57, 249, 213,
206, 95, 188, 117, 238, 177, 93, 221, 233, 117, 154, 68, 152, 42, 45, 202, 193, 169, 185, 195,
143, 31, 27, 254, 139, 239, 188, 53, 251, 106, 227, 127, 4, 0, 12, 70, 72, 215, 151, 31,
220, 252, 111, 239, 220, 148, 253, 213, 158, 38, 155, 149, 253, 8, 47, 15, 229, 134, 127, 237,
127, 12, 62, 84, 12, 213, 115, 0, 230, 87, 6, 71, 230, 171, 186, 222, 28, 223, 145, 111,
183, 187, 62, 146, 52, 82, 116, 57, 234, 3, 64, 174, 62, 139, 199, 70, 254, 122, 241, 143,
7, 190, 240, 194, 55, 199, 254, 234, 155, 3, 139, 39, 30, 175, 235, 250, 243, 0, 142, 3,
24, 1, 48, 119, 127, 219, 71, 74, 15, 174, 255, 68, 253, 166, 182, 61, 254, 135, 123, 30,
144, 187, 91, 111, 87, 107, 226, 125, 204, 100, 194, 245, 101, 185, 39, 210, 193, 118, 131, 89,
27, 28, 35, 214, 97, 11, 39, 107, 25, 102, 147, 41, 120, 202, 16, 52, 193, 5, 137, 9,
206, 98, 130, 49, 135, 83, 102, 115, 42, 76, 74, 184, 73, 64, 172, 72, 69, 102, 164, 3,
229, 240, 88, 169, 199, 238, 159, 59, 82, 60, 52, 210, 158, 142, 30, 200, 198, 77, 218, 20,
19, 180, 187, 201, 238, 222, 214, 153, 184, 103, 99, 214, 202, 252, 240, 236, 252, 140, 6, 202,
0, 234, 26, 40, 126, 239, 205, 220, 235, 27, 178, 86, 53, 237, 26, 123, 82, 142, 193, 146,
182, 209, 212, 149, 50, 218, 247, 159, 206, 159, 94, 225, 10, 111, 31, 131, 250, 229, 220, 179,
211, 119, 182, 222, 179, 53, 107, 183, 246, 155, 204, 124, 27, 0, 137, 8, 23, 171, 35, 229,
71, 47, 126, 237, 91, 0, 190, 11, 224, 52, 128, 124, 195, 236, 162, 223, 221, 242, 5, 245,
43, 91, 62, 173, 183, 55, 239, 208, 59, 179, 187, 72, 139, 221, 70, 12, 106, 242, 72, 135,
118, 41, 200, 183, 251, 178, 178, 77, 48, 99, 131, 43, 98, 29, 182, 176, 51, 166, 201, 155,
12, 131, 36, 133, 33, 99, 220, 140, 28, 110, 72, 139, 113, 101, 49, 174, 77, 70, 169, 73,
41, 53, 40, 225, 156, 130, 81, 13, 205, 67, 21, 82, 165, 101, 45, 109, 102, 138, 133, 133,
196, 133, 192, 61, 186, 169, 61, 105, 108, 50, 5, 96, 8, 32, 155, 16, 98, 77, 198, 190,
238, 214, 245, 201, 221, 126, 16, 148, 206, 204, 121, 243, 141, 58, 161, 186, 255, 84, 126, 160,
55, 109, 78, 143, 229, 107, 116, 108, 190, 86, 138, 89, 220, 201, 151, 188, 225, 177, 98, 48,
210, 136, 31, 122, 101, 30, 32, 133, 50, 78, 173, 75, 108, 122, 176, 201, 204, 216, 203, 129,
208, 96, 2, 77, 118, 202, 181, 96, 249, 175, 23, 14, 157, 0, 48, 211, 48, 53, 13, 64,
63, 190, 247, 25, 146, 182, 147, 112, 77, 11, 148, 18, 162, 149, 102, 82, 73, 163, 18, 21,
147, 229, 168, 176, 129, 16, 108, 182, 133, 219, 229, 24, 118, 214, 52, 120, 147, 97, 232, 132,
176, 2, 151, 91, 158, 201, 141, 154, 65, 13, 79, 48, 225, 115, 202, 35, 65, 169, 230, 148,
80, 70, 64, 25, 1, 3, 64, 160, 180, 212, 145, 14, 2, 70, 217, 66, 187, 211, 181, 248,
198, 194, 193, 233, 158, 140, 255, 177, 148, 195, 9, 161, 18, 148, 42, 196, 45, 138, 206, 180,
145, 233, 111, 143, 223, 153, 113, 152, 121, 112, 100, 113, 10, 64, 9, 64, 245, 249, 161, 194,
91, 251, 6, 115, 7, 246, 13, 230, 158, 255, 246, 201, 185, 167, 199, 138, 193, 217, 134, 11,
4, 171, 1, 208, 111, 149, 79, 44, 110, 75, 236, 170, 180, 216, 109, 31, 138, 27, 9, 66,
64, 64, 136, 70, 76, 216, 200, 218, 205, 107, 74, 222, 162, 119, 166, 124, 106, 164, 113, 174,
70, 199, 238, 27, 37, 113, 211, 5, 97, 18, 96, 18, 0, 161, 82, 129, 133, 50, 180, 74,
97, 161, 213, 151, 181, 205, 6, 51, 215, 58, 134, 219, 98, 26, 70, 218, 48, 117, 146, 91,
190, 203, 172, 170, 201, 173, 146, 96, 214, 34, 163, 102, 137, 81, 81, 163, 148, 135, 140, 80,
77, 9, 161, 140, 104, 70, 160, 41, 129, 166, 82, 41, 29, 69, 42, 12, 21, 212, 66, 140,
39, 22, 230, 10, 198, 164, 103, 31, 233, 181, 132, 222, 226, 152, 132, 48, 166, 65, 136, 130,
193, 9, 50, 49, 211, 232, 203, 184, 55, 246, 183, 216, 189, 207, 159, 201, 95, 84, 26, 11,
13, 107, 40, 54, 204, 126, 166, 97, 189, 254, 202, 12, 113, 101, 38, 168, 94, 156, 219, 127,
110, 79, 230, 142, 77, 205, 86, 75, 191, 197, 44, 128, 72, 80, 170, 145, 176, 226, 172, 51,
214, 190, 121, 114, 241, 98, 126, 204, 27, 27, 7, 80, 217, 145, 186, 94, 245, 36, 187, 97,
26, 4, 132, 42, 2, 77, 169, 148, 154, 215, 35, 207, 41, 5, 249, 110, 13, 181, 201, 226,
78, 135, 45, 172, 102, 195, 160, 73, 97, 70, 49, 110, 213, 76, 102, 23, 57, 179, 10, 148,
154, 121, 74, 141, 34, 161, 188, 74, 8, 11, 9, 161, 154, 64, 51, 2, 205, 9, 20, 215,
90, 17, 169, 148, 14, 66, 21, 214, 165, 10, 23, 13, 102, 206, 117, 196, 186, 75, 143, 30,
25, 58, 48, 21, 156, 201, 217, 134, 222, 153, 176, 169, 99, 8, 13, 66, 52, 24, 37, 72,
58, 6, 233, 106, 114, 214, 239, 234, 138, 111, 63, 54, 154, 159, 44, 250, 106, 126, 217, 93,
87, 93, 174, 92, 49, 21, 134, 134, 10, 38, 203, 23, 143, 110, 73, 109, 223, 219, 108, 53,
103, 13, 198, 0, 162, 192, 25, 65, 218, 74, 154, 61, 137, 206, 237, 227, 197, 177, 92, 222,
47, 78, 154, 48, 106, 140, 17, 213, 158, 200, 194, 20, 6, 209, 138, 18, 41, 193, 107, 97,
37, 94, 141, 22, 123, 41, 161, 235, 108, 238, 100, 77, 195, 72, 11, 3, 9, 110, 250, 22,
179, 202, 130, 91, 11, 140, 154, 243, 132, 138, 121, 80, 94, 4, 161, 181, 165, 180, 25, 140,
64, 11, 162, 149, 1, 45, 133, 210, 146, 69, 82, 194, 143, 100, 88, 11, 85, 176, 200, 169,
152, 78, 155, 153, 197, 182, 120, 91, 121, 255, 233, 225, 55, 95, 186, 112, 250, 96, 54, 129,
141, 9, 155, 117, 57, 6, 3, 33, 0, 33, 4, 174, 201, 208, 145, 178, 219, 182, 116, 196,
119, 189, 49, 146, 159, 90, 168, 171, 217, 6, 8, 234, 189, 106, 1, 0, 208, 83, 254, 120,
197, 212, 214, 241, 78, 183, 235, 195, 105, 43, 21, 227, 140, 128, 16, 9, 193, 41, 50, 78,
218, 233, 75, 246, 94, 119, 177, 116, 177, 48, 180, 112, 110, 186, 20, 46, 212, 52, 145, 170,
59, 209, 13, 174, 45, 170, 36, 17, 181, 176, 26, 247, 100, 165, 135, 17, 214, 107, 113, 187,
217, 20, 60, 41, 12, 229, 50, 211, 55, 153, 89, 225, 204, 90, 32, 212, 200, 19, 194, 22,
64, 88, 101, 169, 178, 36, 4, 208, 38, 180, 180, 181, 150, 182, 86, 145, 161, 148, 228, 161,
148, 218, 11, 101, 88, 9, 85, 176, 192, 168, 152, 140, 25, 241, 98, 214, 205, 250, 25, 55,
229, 157, 154, 157, 157, 122, 228, 240, 232, 75, 237, 77, 129, 147, 180, 249, 142, 132, 37, 40,
37, 75, 9, 129, 45, 24, 90, 18, 102, 211, 246, 206, 196, 174, 129, 177, 252, 116, 174, 38,
103, 86, 6, 190, 119, 3, 0, 0, 212, 201, 197, 35, 185, 20, 75, 191, 213, 98, 183, 252,
92, 218, 74, 90, 140, 45, 213, 3, 6, 103, 200, 56, 105, 119, 99, 122, 205, 77, 211, 181,
137, 234, 241, 220, 192, 116, 161, 62, 95, 205, 216, 25, 149, 49, 91, 9, 131, 201, 235, 81,
45, 230, 201, 74, 23, 165, 188, 203, 228, 86, 218, 224, 60, 206, 133, 118, 152, 17, 24, 204,
168, 50, 42, 74, 148, 240, 69, 80, 86, 1, 136, 191, 244, 143, 181, 1, 173, 28, 232, 40,
14, 21, 186, 90, 71, 150, 148, 33, 243, 101, 132, 106, 32, 131, 114, 164, 130, 121, 78, 197,
69, 71, 36, 22, 44, 97, 4, 109, 137, 140, 76, 88, 110, 84, 245, 253, 197, 239, 28, 155,
61, 156, 136, 87, 42, 41, 135, 239, 78, 58, 130, 179, 198, 49, 110, 9, 134, 108, 220, 74,
246, 181, 196, 182, 29, 58, 155, 187, 88, 10, 244, 76, 195, 18, 244, 123, 1, 0, 0, 242,
245, 194, 193, 137, 22, 179, 245, 124, 218, 74, 237, 77, 89, 9, 139, 93, 98, 9, 41, 171,
47, 213, 253, 126, 66, 164, 241, 210, 196, 193, 169, 197, 250, 98, 37, 109, 55, 171, 102, 209,
194, 164, 146, 118, 93, 86, 219, 9, 104, 167, 193, 204, 148, 224, 60, 198, 56, 108, 198, 35,
131, 138, 58, 35, 194, 35, 148, 213, 9, 72, 184, 84, 102, 107, 19, 90, 199, 128, 40, 1,
29, 38, 181, 10, 99, 74, 134, 86, 40, 67, 94, 15, 165, 170, 248, 145, 95, 12, 165, 63,
99, 80, 115, 204, 21, 137, 5, 206, 89, 104, 10, 166, 58, 18, 109, 42, 193, 211, 10, 138,
122, 79, 30, 29, 27, 48, 236, 194, 100, 54, 110, 222, 153, 180, 13, 193, 232, 18, 8, 166,
160, 200, 198, 204, 244, 154, 102, 103, 227, 190, 193, 185, 17, 253, 206, 125, 129, 126, 47, 0,
52, 128, 232, 208, 252, 43, 23, 146, 60, 121, 186, 217, 74, 223, 149, 52, 99, 142, 96, 20,
32, 10, 130, 18, 52, 59, 73, 177, 54, 213, 121, 67, 103, 60, 179, 246, 153, 209, 31, 78,
45, 134, 139, 213, 54, 187, 43, 76, 138, 148, 8, 164, 151, 6, 84, 155, 96, 70, 82, 48,
225, 114, 70, 44, 202, 148, 32, 76, 50, 74, 35, 10, 170, 200, 82, 194, 101, 64, 43, 23,
90, 38, 161, 194, 180, 86, 65, 82, 203, 32, 38, 101, 96, 5, 81, 72, 171, 65, 20, 149,
252, 168, 94, 136, 84, 120, 209, 98, 177, 11, 174, 17, 47, 114, 198, 66, 202, 180, 230, 148,
235, 110, 167, 15, 113, 222, 164, 115, 94, 206, 255, 211, 35, 47, 156, 237, 73, 25, 83, 217,
184, 185, 55, 237, 8, 78, 9, 5, 1, 96, 25, 12, 217, 152, 145, 237, 72, 136, 214, 231,
206, 20, 206, 53, 10, 163, 112, 245, 49, 120, 53, 9, 95, 207, 191, 54, 174, 165, 62, 150,
181, 155, 63, 144, 48, 221, 148, 201, 25, 8, 85, 160, 84, 35, 105, 185, 164, 59, 209, 210,
183, 189, 165, 239, 150, 177, 210, 136, 63, 152, 59, 87, 232, 113, 215, 212, 109, 110, 155, 82,
71, 45, 140, 136, 164, 160, 194, 97, 148, 153, 148, 17, 65, 8, 24, 8, 8, 33, 148, 52,
204, 158, 104, 153, 128, 14, 83, 90, 5, 41, 173, 252, 132, 148, 190, 19, 200, 64, 120, 97,
136, 178, 31, 6, 197, 122, 228, 205, 105, 141, 225, 152, 72, 141, 57, 34, 86, 97, 140, 68,
148, 106, 5, 77, 1, 197, 209, 102, 245, 224, 66, 105, 68, 191, 52, 247, 92, 240, 194, 217,
194, 185, 45, 109, 78, 37, 19, 51, 239, 76, 218, 130, 18, 66, 64, 0, 56, 38, 71, 115,
204, 232, 134, 146, 228, 141, 241, 242, 249, 198, 93, 162, 124, 55, 0, 86, 146, 24, 209, 64,
113, 96, 106, 162, 52, 241, 74, 187, 219, 186, 37, 102, 216, 221, 142, 97, 46, 129, 64, 20,
28, 67, 160, 45, 222, 148, 92, 151, 110, 191, 109, 166, 62, 102, 159, 206, 77, 140, 174, 79,
246, 87, 64, 116, 156, 0, 105, 70, 133, 197, 8, 55, 8, 97, 156, 128, 82, 16, 74, 161,
4, 209, 202, 132, 150, 46, 116, 152, 208, 202, 79, 42, 229, 39, 164, 12, 220, 80, 250, 166,
23, 6, 180, 18, 68, 178, 88, 15, 189, 124, 32, 235, 23, 5, 181, 134, 18, 70, 211, 172,
201, 44, 143, 49, 42, 65, 160, 161, 40, 180, 226, 128, 162, 248, 249, 31, 222, 182, 108, 210,
193, 51, 167, 230, 79, 221, 212, 155, 72, 180, 196, 205, 27, 93, 147, 97, 41, 159, 1, 226,
150, 32, 105, 71, 172, 59, 62, 58, 63, 59, 91, 149, 163, 0, 42, 0, 244, 101, 0, 216,
212, 49, 35, 29, 185, 0, 28, 0, 70, 227, 114, 52, 28, 175, 141, 207, 237, 31, 127, 246,
197, 117, 241, 94, 43, 38, 172, 157, 174, 97, 81, 206, 8, 64, 36, 4, 35, 72, 152, 54,
171, 69, 213, 174, 167, 134, 94, 25, 93, 27, 95, 63, 218, 108, 53, 41, 169, 101, 130, 18,
234, 80, 48, 65, 193, 40, 192, 40, 52, 7, 148, 128, 142, 44, 173, 35, 91, 169, 192, 149,
42, 116, 163, 200, 119, 130, 40, 48, 234, 81, 64, 43, 65, 40, 139, 245, 208, 47, 120, 81,
109, 86, 105, 117, 206, 229, 201, 225, 152, 145, 94, 224, 140, 7, 148, 80, 69, 64, 180, 214,
12, 144, 12, 237, 143, 153, 171, 35, 123, 240, 234, 80, 254, 196, 158, 245, 233, 27, 91, 19,
102, 175, 193, 151, 178, 90, 70, 9, 18, 182, 97, 164, 93, 209, 185, 111, 48, 119, 182, 81,
73, 250, 151, 0, 96, 51, 135, 253, 217, 205, 127, 243, 165, 143, 175, 251, 228, 195, 255, 188,
239, 19, 191, 116, 95, 207, 253, 247, 45, 212, 242, 11, 163, 181, 209, 18, 128, 106, 168, 163,
226, 254, 137, 23, 14, 199, 153, 59, 106, 113, 99, 187, 107, 152, 73, 75, 112, 16, 162, 192,
152, 134, 201, 168, 115, 174, 116, 46, 152, 45, 213, 222, 220, 148, 218, 50, 71, 136, 230, 74,
75, 135, 128, 112, 2, 70, 160, 41, 180, 102, 90, 43, 174, 116, 36, 164, 138, 140, 80, 133,
102, 24, 5, 134, 47, 67, 238, 133, 1, 41, 7, 161, 92, 108, 40, 63, 23, 170, 96, 212,
160, 206, 233, 164, 145, 153, 182, 152, 235, 9, 202, 35, 16, 162, 161, 9, 160, 232, 149, 148,
39, 0, 80, 139, 180, 111, 18, 125, 186, 47, 27, 251, 39, 45, 9, 203, 94, 46, 240, 76,
65, 17, 51, 121, 115, 169, 234, 133, 3, 83, 213, 51, 0, 242, 151, 0, 16, 233, 144, 36,
88, 106, 248, 186, 204, 245, 191, 182, 189, 121, 235, 198, 142, 88, 251, 218, 53, 137, 158, 59,
138, 181, 66, 105, 184, 58, 60, 211, 48, 155, 202, 107, 115, 71, 135, 142, 79, 15, 190, 212,
234, 54, 37, 77, 206, 55, 218, 66, 48, 193, 8, 108, 33, 96, 27, 172, 229, 59, 103, 14,
140, 180, 88, 29, 195, 29, 110, 103, 73, 234, 136, 74, 29, 25, 26, 32, 208, 68, 105, 77,
34, 173, 72, 168, 36, 13, 100, 72, 125, 25, 81, 47, 138, 80, 13, 67, 93, 14, 162, 176,
88, 15, 253, 188, 23, 86, 231, 2, 233, 95, 96, 196, 56, 149, 20, 153, 11, 174, 72, 149,
56, 17, 97, 164, 165, 42, 5, 69, 61, 239, 229, 112, 44, 119, 4, 79, 142, 63, 186, 154,
135, 100, 0, 172, 127, 115, 107, 215, 166, 187, 183, 182, 124, 50, 19, 51, 118, 101, 227, 166,
177, 164, 127, 35, 30, 24, 156, 88, 130, 181, 63, 126, 116, 230, 28, 128, 209, 203, 92, 224,
228, 226, 209, 114, 143, 221, 51, 156, 181, 51, 247, 102, 157, 140, 209, 226, 54, 187, 235, 82,
189, 55, 27, 16, 234, 196, 194, 201, 169, 6, 8, 181, 249, 96, 33, 247, 189, 177, 23, 95,
213, 145, 60, 37, 24, 235, 53, 25, 109, 117, 77, 131, 52, 217, 174, 101, 152, 65, 203, 179,
195, 199, 134, 122, 98, 125, 227, 77, 102, 243, 162, 210, 81, 20, 169, 0, 82, 71, 74, 41,
21, 72, 169, 124, 41, 165, 23, 73, 89, 11, 35, 89, 9, 162, 112, 209, 143, 252, 133, 122,
88, 207, 215, 163, 218, 116, 164, 194, 17, 78, 205, 83, 9, 209, 60, 98, 243, 120, 209, 147,
94, 48, 89, 189, 168, 78, 228, 143, 232, 163, 185, 215, 201, 223, 141, 60, 74, 30, 126, 235,
63, 44, 83, 116, 2, 128, 251, 241, 27, 90, 251, 254, 221, 222, 181, 15, 126, 250, 182, 222,
207, 223, 181, 57, 251, 240, 214, 142, 196, 205, 29, 105, 199, 96, 132, 92, 114, 251, 199, 24,
129, 45, 152, 67, 116, 164, 14, 143, 149, 78, 146, 171, 16, 34, 206, 239, 109, 255, 252, 199,
62, 216, 179, 247, 79, 251, 146, 61, 182, 38, 33, 198, 42, 35, 209, 129, 201, 3, 79, 255,
151, 99, 127, 244, 149, 170, 170, 45, 95, 54, 42, 0, 54, 5, 233, 250, 204, 174, 143, 221,
183, 167, 107, 219, 175, 172, 111, 110, 91, 239, 75, 79, 63, 59, 242, 198, 15, 143, 142, 248,
95, 250, 167, 107, 63, 58, 212, 27, 239, 53, 35, 93, 239, 84, 136, 186, 8, 72, 11, 163,
44, 65, 9, 181, 8, 40, 215, 208, 74, 107, 21, 74, 45, 171, 74, 171, 60, 1, 157, 50,
168, 51, 238, 242, 228, 12, 64, 203, 3, 249, 19, 234, 240, 220, 171, 116, 120, 241, 44, 157,
171, 207, 208, 153, 112, 84, 100, 82, 101, 247, 222, 29, 173, 107, 54, 182, 198, 250, 83, 142,
216, 217, 228, 24, 55, 52, 199, 140, 205, 77, 174, 97, 196, 45, 14, 131, 211, 198, 126, 175,
38, 151, 9, 148, 214, 56, 63, 87, 209, 95, 121, 113, 248, 149, 63, 59, 56, 245, 48, 121,
23, 86, 40, 254, 187, 219, 63, 247, 145, 187, 123, 238, 250, 226, 186, 84, 79, 92, 48, 130,
130, 63, 135, 183, 10, 111, 93, 120, 110, 252, 197, 175, 254, 229, 208, 163, 79, 3, 184, 216,
200, 174, 0, 32, 198, 8, 237, 253, 237, 235, 126, 241, 222, 27, 59, 55, 60, 152, 176, 204,
254, 243, 133, 201, 3, 47, 158, 46, 126, 241, 158, 174, 7, 206, 108, 111, 222, 161, 24, 69,
60, 84, 245, 166, 72, 133, 41, 64, 185, 26, 90, 0, 68, 17, 144, 58, 37, 172, 36, 168,
85, 48, 153, 83, 224, 48, 203, 51, 222, 108, 56, 226, 126, 233, 198, 190, 246, 252, 103, 24,
139, 146, 148, 74, 195, 224, 42, 110, 25, 186, 201, 52, 16, 115, 13, 102, 218, 6, 131, 37,
216, 18, 47, 73, 201, 21, 88, 30, 114, 73, 106, 163, 1, 204, 44, 214, 241, 141, 67, 99,
23, 255, 243, 247, 71, 190, 14, 224, 111, 200, 123, 112, 6, 177, 223, 234, 255, 205, 123, 238,
233, 221, 251, 71, 155, 154, 251, 186, 226, 166, 133, 64, 85, 49, 93, 155, 82, 111, 21, 78,
29, 249, 193, 232, 75, 95, 123, 108, 228, 153, 3, 141, 114, 211, 3, 64, 40, 152, 155, 97,
173, 157, 119, 173, 219, 112, 211, 29, 107, 55, 223, 43, 24, 105, 30, 206, 151, 191, 110, 84,
119, 190, 180, 167, 237, 182, 106, 214, 206, 16, 66, 180, 33, 181, 52, 180, 86, 20, 128, 38,
132, 70, 148, 240, 64, 107, 4, 243, 94, 94, 254, 168, 248, 116, 122, 243, 230, 227, 191, 177,
169, 141, 127, 186, 167, 217, 182, 4, 95, 162, 201, 150, 40, 180, 168, 65, 184, 144, 171, 180,
15, 144, 85, 249, 28, 121, 91, 253, 249, 114, 128, 125, 39, 167, 230, 127, 243, 127, 158, 126,
66, 3, 143, 0, 56, 249, 94, 228, 40, 5, 224, 222, 213, 114, 219, 206, 127, 181, 237, 227,
127, 184, 45, 179, 113, 79, 75, 44, 5, 70, 21, 106, 178, 140, 217, 218, 140, 60, 95, 28,
62, 126, 100, 118, 240, 137, 175, 14, 60, 249, 66, 85, 5, 147, 0, 170, 130, 24, 170, 223,
222, 102, 134, 42, 76, 114, 129, 236, 3, 219, 54, 110, 171, 132, 178, 78, 117, 243, 249, 181,
226, 166, 241, 181, 177, 254, 64, 80, 65, 148, 86, 196, 151, 30, 93, 12, 22, 233, 120, 249,
130, 73, 211, 39, 55, 108, 232, 172, 220, 223, 213, 68, 255, 89, 79, 147, 221, 154, 118, 25,
40, 147, 151, 115, 16, 80, 13, 197, 174, 164, 252, 229, 215, 255, 74, 3, 115, 101, 31, 223,
31, 152, 206, 253, 246, 19, 103, 158, 10, 149, 254, 91, 0, 199, 0, 148, 126, 28, 122, 156,
2, 48, 13, 34, 186, 126, 239, 134, 207, 254, 235, 221, 29, 215, 253, 250, 218, 84, 71, 34,
110, 26, 0, 141, 224, 203, 42, 22, 252, 2, 38, 171, 211, 185, 137, 242, 244, 43, 195, 197,
139, 47, 63, 50, 240, 236, 143, 38, 235, 139, 51, 91, 157, 157, 53, 87, 196, 148, 193, 12,
106, 115, 155, 197, 44, 155, 180, 103, 73, 218, 53, 101, 75, 139, 75, 214, 39, 28, 178, 185,
201, 229, 125, 148, 70, 109, 166, 208, 125, 173, 9, 171, 53, 27, 23, 36, 229, 50, 112, 166,
174, 78, 179, 175, 242, 235, 119, 118, 250, 242, 239, 67, 165, 49, 81, 240, 240, 212, 137, 169,
139, 255, 113, 223, 185, 125, 74, 227, 73, 0, 39, 26, 183, 70, 242, 39, 233, 15, 224, 0,
82, 119, 183, 223, 114, 227, 47, 109, 185, 239, 119, 182, 100, 214, 222, 214, 22, 79, 179, 165,
90, 60, 130, 34, 1, 234, 178, 138, 114, 88, 66, 222, 43, 84, 103, 107, 243, 167, 138, 126,
105, 112, 170, 60, 63, 120, 42, 55, 53, 52, 56, 157, 155, 214, 145, 89, 113, 184, 19, 26,
92, 104, 169, 34, 179, 18, 86, 83, 125, 237, 216, 178, 165, 45, 254, 190, 76, 204, 216, 154,
180, 121, 175, 107, 177, 236, 77, 107, 50, 137, 206, 180, 117, 89, 15, 193, 82, 233, 124, 53,
222, 243, 82, 32, 52, 128, 146, 23, 225, 204, 76, 57, 124, 244, 240, 248, 155, 127, 126, 112,
106, 31, 128, 253, 141, 123, 205, 202, 114, 42, 252, 147, 116, 136, 44, 159, 181, 22, 128, 182,
127, 185, 241, 254, 15, 126, 168, 111, 247, 167, 54, 54, 119, 237, 108, 137, 37, 168, 99, 176,
70, 175, 192, 18, 13, 30, 193, 135, 47, 61, 212, 101, 13, 190, 242, 116, 45, 170, 5, 94,
228, 149, 66, 229, 87, 34, 29, 148, 36, 66, 127, 233, 198, 73, 58, 148, 42, 215, 228, 72,
198, 44, 26, 183, 13, 240, 76, 92, 144, 184, 77, 47, 99, 163, 222, 49, 127, 92, 213, 5,
52, 52, 188, 64, 98, 170, 88, 215, 7, 207, 207, 207, 125, 233, 249, 243, 7, 78, 229, 130,
253, 0, 14, 173, 8, 218, 234, 239, 211, 35, 180, 108, 13, 14, 1, 233, 252, 100, 255, 189,
119, 221, 218, 179, 243, 99, 27, 51, 29, 55, 180, 197, 147, 70, 220, 18, 16, 76, 95, 78,
163, 55, 62, 47, 247, 9, 128, 188, 163, 212, 210, 144, 141, 0, 183, 188, 94, 101, 246, 111,
3, 160, 175, 232, 243, 74, 3, 213, 32, 194, 92, 201, 215, 199, 198, 138, 133, 167, 78, 76,
29, 127, 226, 228, 252, 139, 0, 94, 5, 48, 180, 130, 49, 214, 63, 173, 38, 169, 229, 68,
196, 5, 208, 118, 119, 215, 245, 215, 223, 179, 254, 134, 95, 88, 223, 212, 118, 107, 79, 186,
169, 163, 201, 177, 136, 107, 48, 112, 174, 222, 49, 225, 85, 100, 234, 101, 13, 22, 203, 254,
254, 182, 210, 239, 152, 254, 210, 111, 222, 185, 210, 211, 0, 180, 6, 252, 72, 161, 228, 133,
152, 92, 240, 162, 19, 19, 197, 233, 253, 131, 179, 39, 159, 122, 171, 112, 8, 192, 17, 0,
103, 27, 229, 175, 127, 181, 158, 129, 191, 111, 155, 220, 74, 32, 44, 0, 105, 0, 221, 31,
221, 180, 231, 230, 221, 221, 27, 239, 232, 74, 166, 118, 118, 36, 227, 237, 105, 199, 20, 174,
201, 96, 9, 2, 193, 213, 219, 221, 31, 132, 94, 129, 105, 126, 215, 118, 25, 137, 80, 42,
120, 129, 68, 165, 30, 97, 182, 84, 15, 207, 205, 85, 114, 131, 19, 139, 35, 143, 188, 54,
117, 98, 214, 147, 39, 27, 62, 62, 214, 216, 113, 255, 189, 186, 70, 126, 218, 125, 130, 180,
145, 154, 218, 13, 48, 218, 187, 221, 100, 223, 135, 214, 111, 221, 218, 223, 210, 186, 57, 27,
115, 214, 54, 57, 102, 75, 202, 17, 201, 132, 205, 77, 219, 32, 68, 112, 5, 206, 52, 24,
147, 151, 208, 239, 10, 33, 164, 14, 17, 233, 0, 245, 200, 71, 217, 175, 135, 249, 170, 239,
205, 44, 214, 23, 166, 23, 235, 179, 135, 71, 10, 163, 207, 158, 89, 56, 231, 73, 61, 2,
96, 180, 81, 221, 21, 126, 210, 6, 170, 159, 69, 167, 232, 234, 226, 196, 108, 0, 18, 7,
144, 2, 208, 108, 80, 154, 217, 144, 74, 181, 246, 183, 54, 183, 182, 37, 220, 166, 76, 204,
76, 113, 170, 45, 198, 180, 208, 144, 132, 82, 77, 106, 161, 31, 46, 214, 235, 181, 66, 181,
94, 25, 152, 92, 88, 24, 154, 175, 207, 251, 82, 231, 27, 196, 198, 124, 227, 142, 191, 216,
80, 184, 254, 191, 219, 66, 247, 179, 106, 149, 189, 90, 67, 229, 50, 40, 188, 97, 41, 70,
99, 136, 198, 96, 171, 186, 73, 163, 134, 98, 97, 131, 205, 9, 26, 159, 151, 239, 249, 213,
207, 178, 137, 242, 154, 92, 147, 107, 114, 77, 174, 201, 53, 185, 38, 215, 228, 154, 252, 191,
44, 255, 11, 186, 123, 33, 219, 12, 195, 59, 78, 0, 0, 0, 0, 73, 69, 78, 68, 174,
66, 96, 130
};
};
default_icon_64_t default_icon_64;
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,112 @@
#ifndef __DEFAULT_SHADERS_HPP__
#define __DEFAULT_SHADERS_HPP__
#include <ostd/Types.hpp>
namespace oxres
{
const ostd::String defaultShader_vert =
"#version 420 core\n"
"layout(location = 0) in vec3 a_position;\n"
"layout(location = 1) in vec4 a_color;\n"
"layout(location = 2) in vec2 a_texCoords;\n"
"layout(location = 3) in float a_texIndex;\n"
"out vec4 v_vertexColor;\n"
"out vec2 v_texCoords;\n"
"out float v_texIndex;\n"
"uniform mat4 u_viewProjMatrix;\n"
"void main()\n"
"{\n"
"gl_Position = u_viewProjMatrix * vec4(a_position, 1.0);\n"
"v_vertexColor = a_color;\n"
"v_texCoords = a_texCoords;\n"
"v_texIndex = a_texIndex;\n"
"}\n"
;
const ostd::String defaultShader_frag =
"#version 420 core\n"
"out vec4 out_FragColor;\n"
"uniform sampler2D u_textures[16];\n"
"in vec4 v_vertexColor;\n"
"in vec2 v_texCoords;\n"
"in float v_texIndex;\n"
"void main()\n"
"{\n"
"int iTexID = int(v_texIndex);\n"
"vec4 color = texture(u_textures[iTexID], v_texCoords) * v_vertexColor;\n"
"out_FragColor = color;"
"}\n"
;
const ostd::String defaultBlendShader_vert =
"#version 420 core\n"
"layout(location = 0) in vec3 a_position;\n"
"layout(location = 1) in vec4 a_color;\n"
"layout(location = 2) in vec2 a_texCoords;\n"
"layout(location = 3) in float a_texIndex;\n"
"out vec2 v_texCoords;\n"
"uniform mat4 u_viewProjMatrix;\n"
"void main()\n"
"{\n"
"gl_Position = u_viewProjMatrix * vec4(a_position, 1.0);\n"
"v_texCoords = a_texCoords;\n"
"}\n"
;
const ostd::String defaultBlendShader_frag =
"#version 420 core\n"
"out vec4 out_FragColor;\n"
"uniform sampler2D u_textures[16];\n"
"uniform int u_blendModes[14];\n"
"uniform int u_layerCount;\n"
"in vec2 v_texCoords;\n"
"const int BMOverride = 0;\n"
"const int BMTransparent = 1;\n"
"const int BMMultiply = 2;\n"
"const int BMAdd = 3;\n"
"const int BMSubtract = 4;\n"
"const int BMNormal = 5;\n"
"void main()\n"
"{\n"
"vec4 color = vec4(1.0, 1.0, 1.0, 1.0);\n"
"for (int i = 0; i < u_layerCount; i++)\n"
"{\n"
"int ti = i + 1;\n"
"int bm = u_blendModes[i];\n"
"if (bm == BMOverride)\n"
"color = texture(u_textures[ti], v_texCoords);\n"
"else if (bm == BMTransparent)\n"
"continue;\n"
"else if (bm == BMMultiply)\n"
"color *= texture(u_textures[ti], v_texCoords);\n"
"else if (bm == BMAdd)\n"
"color += texture(u_textures[ti], v_texCoords);\n"
"else if (bm == BMSubtract)\n"
"color -= texture(u_textures[ti], v_texCoords);\n"
"else if (bm == BMNormal)\n"
"{\n"
"vec4 col = texture(u_textures[ti], v_texCoords);\n"
"color = vec4(col.rgb * col.a + color.rgb * (1.0 - col.a), 1.0);\n"
"}\n"
"}\n"
"out_FragColor = color;\n"
"}\n"
;
}
#endif

61
src/ostd/BaseObject.cpp Executable file
View file

@ -0,0 +1,61 @@
#include "BaseObject.hpp"
#include "Utils.hpp"
#include "Defines.hpp"
#include "Signals.hpp"
namespace ostd
{
BaseObject BaseObject::s_invalid_obj { false };
BaseObject::BaseObject(const BaseObject& copy)
{
m_uid = copy.m_uid;
m_oid = copy.m_oid;
m_valid = copy.m_valid;
m_typeName = copy.m_typeName;
m_signalsEnabled = copy.m_signalsEnabled;
}
BaseObject& BaseObject::operator=(const BaseObject& copy)
{
m_uid = copy.m_uid;
m_oid = copy.m_oid;
m_valid = copy.m_valid;
m_typeName = copy.m_typeName;
m_signalsEnabled = copy.m_signalsEnabled;
return *this;
}
std::ostream& operator<<(std::ostream& out, const BaseObject& val)
{
out << val.toString();
return out;
}
void BaseObject::print(bool newLine, IOutputHandler* __destination) const
{
if (__destination == nullptr)
std::cout << toString() << (newLine ? "\n" : "");
else
{
__destination->p(toString());
if (newLine) __destination->nl();
}
}
std::string BaseObject::getObjectHeaderString(void) const
{
return StringEditor(getTypeName()).add("->uid=").addi(getID()).add("/oid=").addi(getCompareOID()).add("/valid=").add(STR_BOOL(isValid())).str();
}
void BaseObject::connectSignal(uint32_t signal_id)
{
SignalHandler::connect(*this, signal_id);
}
void BaseObject::__handle_signal(tSignal& signal)
{
if (m_signalsEnabled)
handleSignal(signal);
}
} //namesoace ox

70
src/ostd/BaseObject.hpp Executable file
View file

@ -0,0 +1,70 @@
#ifndef __BASE_OBJECT_HPP__
#define __BASE_OBJECT_HPP__
#include <cstdint>
#include <string>
#include <iostream>
namespace ostd
{
class IOutputHandler;
struct tSignal;
class BaseObject
{
public:
BaseObject(const BaseObject& copy);
inline virtual ~BaseObject(void) = default;
virtual BaseObject& operator=(const BaseObject& copy);
virtual inline uint64_t getID(void) const { return m_uid; }
virtual inline void setID(uint64_t id) { m_uid = id; }
virtual inline bool isValid(void) const { return !isInvalid(); }
virtual inline bool isInvalid(void) const { return !m_valid || m_oid == 0; }
virtual inline void invalidate(void) { m_valid = false; }
virtual inline void validate(void) { m_valid = true; }
virtual inline void setValid(bool valid) { m_valid = valid; }
inline uint64_t getCompareOID(void) const { return m_oid; }
inline bool compareByOID(const BaseObject& other) const { return m_oid == other.m_oid; }
inline static BaseObject& InvalidRef(void) { return BaseObject::s_invalid_obj; }
// inline static BaseObject InvalidInst(void) { return BaseObject::s_invalid_obj; }
inline void setTypeName(std::string tn) { m_typeName = tn; }
inline std::string getTypeName(void) const { return m_typeName; }
std::string getObjectHeaderString(void) const;
inline bool signalsEnabled(void) { return m_signalsEnabled; }
inline void enableSignals(bool e = true) { m_signalsEnabled = e; }
virtual inline std::string toString(void) const { return getObjectHeaderString(); };
virtual void print(bool newLine = true, IOutputHandler* __destination = nullptr) const;
virtual inline void handleSignal(tSignal& signal) { }
void connectSignal(uint32_t signal_id);
void __handle_signal(tSignal& signal);
friend std::ostream& operator<<(std::ostream& os, const BaseObject& obj);
protected:
inline BaseObject(void) { m_uid = -1; m_valid = false; m_oid = BaseObject::s_next_oid++; }
private:
inline BaseObject(bool __valid) { m_uid = -1; m_valid = __valid; m_oid = 0; }
private:
uint64_t m_uid;
uint64_t m_oid;
bool m_valid;
std::string m_typeName;
bool m_signalsEnabled { true };
inline static uint64_t s_next_oid { 1024 };
static BaseObject s_invalid_obj;
};
} //namesoace ox
#endif

914
src/ostd/Bitfields.hpp Executable file
View file

@ -0,0 +1,914 @@
#ifndef __BITFIELDS_HPP__
#define __BITFIELDS_HPP__
#include <cstdint>
#define get_bit(__bit_field, __bit_n ) __bit_field.bits.b##__bit_n
#define set_bit(__bit_field, __bit_n ) __bit_field.bits.b##__bit_n = true
#define clr_bit(__bit_field, __bit_n ) __bit_field.bits.b##__bit_n = false
#define tgl_bit(__bit_field, __bit_n ) __bit_field.bits.b##__bit_n = !__bit_field.bits.b##__bit_n
#define val_bit(__bit_field, __bit_n, __val ) __bit_field.bits.b##__bit_n = __val
namespace ostd
{
union BitField_8
{
uint8_t value = 0;
struct {
bool b0 : 1;
bool b1 : 1;
bool b2 : 1;
bool b3 : 1;
bool b4 : 1;
bool b5 : 1;
bool b6 : 1;
bool b7 : 1;
} bits;
};
union BitField_16
{
uint16_t value = 0;
struct {
bool b0 : 1;
bool b1 : 1;
bool b2 : 1;
bool b3 : 1;
bool b4 : 1;
bool b5 : 1;
bool b6 : 1;
bool b7 : 1;
bool b8 : 1;
bool b9 : 1;
bool b10 : 1;
bool b11 : 1;
bool b12 : 1;
bool b13 : 1;
bool b14 : 1;
bool b15 : 1;
} bits;
};
union BitField_32
{
uint32_t value = 0;
struct {
bool b0 : 1;
bool b1 : 1;
bool b2 : 1;
bool b3 : 1;
bool b4 : 1;
bool b5 : 1;
bool b6 : 1;
bool b7 : 1;
bool b8 : 1;
bool b9 : 1;
bool b10 : 1;
bool b11 : 1;
bool b12 : 1;
bool b13 : 1;
bool b14 : 1;
bool b15 : 1;
bool b16 : 1;
bool b17 : 1;
bool b18 : 1;
bool b19 : 1;
bool b20 : 1;
bool b21 : 1;
bool b22 : 1;
bool b23 : 1;
bool b24 : 1;
bool b25 : 1;
bool b26 : 1;
bool b27 : 1;
bool b28 : 1;
bool b29 : 1;
bool b30 : 1;
bool b31 : 1;
} bits;
};
union BitField_64
{
uint64_t value = 0;
struct {
bool b0 : 1;
bool b1 : 1;
bool b2 : 1;
bool b3 : 1;
bool b4 : 1;
bool b5 : 1;
bool b6 : 1;
bool b7 : 1;
bool b8 : 1;
bool b9 : 1;
bool b10 : 1;
bool b11 : 1;
bool b12 : 1;
bool b13 : 1;
bool b14 : 1;
bool b15 : 1;
bool b16 : 1;
bool b17 : 1;
bool b18 : 1;
bool b19 : 1;
bool b20 : 1;
bool b21 : 1;
bool b22 : 1;
bool b23 : 1;
bool b24 : 1;
bool b25 : 1;
bool b26 : 1;
bool b27 : 1;
bool b28 : 1;
bool b29 : 1;
bool b30 : 1;
bool b31 : 1;
bool b32 : 1;
bool b33 : 1;
bool b34 : 1;
bool b35 : 1;
bool b36 : 1;
bool b37 : 1;
bool b38 : 1;
bool b39 : 1;
bool b40 : 1;
bool b41 : 1;
bool b42 : 1;
bool b43 : 1;
bool b44 : 1;
bool b45 : 1;
bool b46 : 1;
bool b47 : 1;
bool b48 : 1;
bool b49 : 1;
bool b50 : 1;
bool b51 : 1;
bool b52 : 1;
bool b53 : 1;
bool b54 : 1;
bool b55 : 1;
bool b56 : 1;
bool b57 : 1;
bool b58 : 1;
bool b59 : 1;
bool b60 : 1;
bool b61 : 1;
bool b62 : 1;
bool b63 : 1;
} bits;
} ;
class Bits
{
public:
//8-Bit field
static inline bool get(const BitField_8& bf, const uint8_t& bit)
{
switch (bit)
{
case 0: return get_bit(bf, 0);
case 1: return get_bit(bf, 1);
case 2: return get_bit(bf, 2);
case 3: return get_bit(bf, 3);
case 4: return get_bit(bf, 4);
case 5: return get_bit(bf, 5);
case 6: return get_bit(bf, 6);
case 7: return get_bit(bf, 7);
default: return false;
}
}
static inline void set(BitField_8& bf, const uint8_t& bit)
{
switch (bit)
{
case 0: set_bit(bf, 0); break;
case 1: set_bit(bf, 1); break;
case 2: set_bit(bf, 2); break;
case 3: set_bit(bf, 3); break;
case 4: set_bit(bf, 4); break;
case 5: set_bit(bf, 5); break;
case 6: set_bit(bf, 6); break;
case 7: set_bit(bf, 7); break;
default: break;
}
}
static inline void clr(BitField_8& bf, const uint8_t& bit)
{
switch (bit)
{
case 0: clr_bit(bf, 0); break;
case 1: clr_bit(bf, 1); break;
case 2: clr_bit(bf, 2); break;
case 3: clr_bit(bf, 3); break;
case 4: clr_bit(bf, 4); break;
case 5: clr_bit(bf, 5); break;
case 6: clr_bit(bf, 6); break;
case 7: clr_bit(bf, 7); break;
default: break;
}
}
static inline void tgl(BitField_8& bf, const uint8_t& bit)
{
switch (bit)
{
case 0: tgl_bit(bf, 0); break;
case 1: tgl_bit(bf, 1); break;
case 2: tgl_bit(bf, 2); break;
case 3: tgl_bit(bf, 3); break;
case 4: tgl_bit(bf, 4); break;
case 5: tgl_bit(bf, 5); break;
case 6: tgl_bit(bf, 6); break;
case 7: tgl_bit(bf, 7); break;
default: break;
}
}
static inline void val(BitField_8& bf, const uint8_t& bit, bool value)
{
switch (bit)
{
case 0: val_bit(bf, 0, value); break;
case 1: val_bit(bf, 1, value); break;
case 2: val_bit(bf, 2, value); break;
case 3: val_bit(bf, 3, value); break;
case 4: val_bit(bf, 4, value); break;
case 5: val_bit(bf, 5, value); break;
case 6: val_bit(bf, 6, value); break;
case 7: val_bit(bf, 7, value); break;
default: break;
}
}
//16-Bit field
static inline bool get(const BitField_16& bf, const uint8_t& bit)
{
switch (bit)
{
case 0: return get_bit(bf, 0);
case 1: return get_bit(bf, 1);
case 2: return get_bit(bf, 2);
case 3: return get_bit(bf, 3);
case 4: return get_bit(bf, 4);
case 5: return get_bit(bf, 5);
case 6: return get_bit(bf, 6);
case 7: return get_bit(bf, 7);
case 8: return get_bit(bf, 8);
case 9: return get_bit(bf, 9);
case 10: return get_bit(bf, 10);
case 11: return get_bit(bf, 11);
case 12: return get_bit(bf, 12);
case 13: return get_bit(bf, 13);
case 14: return get_bit(bf, 14);
case 15: return get_bit(bf, 15);
default: return false;
}
}
static inline void set(BitField_16& bf, const uint8_t& bit)
{
switch (bit)
{
case 0: set_bit(bf, 0); break;
case 1: set_bit(bf, 1); break;
case 2: set_bit(bf, 2); break;
case 3: set_bit(bf, 3); break;
case 4: set_bit(bf, 4); break;
case 5: set_bit(bf, 5); break;
case 6: set_bit(bf, 6); break;
case 7: set_bit(bf, 7); break;
case 8: set_bit(bf, 8); break;
case 9: set_bit(bf, 9); break;
case 10: set_bit(bf, 10); break;
case 11: set_bit(bf, 11); break;
case 12: set_bit(bf, 12); break;
case 13: set_bit(bf, 13); break;
case 14: set_bit(bf, 14); break;
case 15: set_bit(bf, 15); break;
default: break;
}
}
static inline void clr(BitField_16& bf, const uint8_t& bit)
{
switch (bit)
{
case 0: clr_bit(bf, 0); break;
case 1: clr_bit(bf, 1); break;
case 2: clr_bit(bf, 2); break;
case 3: clr_bit(bf, 3); break;
case 4: clr_bit(bf, 4); break;
case 5: clr_bit(bf, 5); break;
case 6: clr_bit(bf, 6); break;
case 7: clr_bit(bf, 7); break;
case 8: clr_bit(bf, 8); break;
case 9: clr_bit(bf, 9); break;
case 10: clr_bit(bf, 10); break;
case 11: clr_bit(bf, 11); break;
case 12: clr_bit(bf, 12); break;
case 13: clr_bit(bf, 13); break;
case 14: clr_bit(bf, 14); break;
case 15: clr_bit(bf, 15); break;
default: break;
}
}
static inline void tgl(BitField_16& bf, const uint8_t& bit)
{
switch (bit)
{
case 0: tgl_bit(bf, 0); break;
case 1: tgl_bit(bf, 1); break;
case 2: tgl_bit(bf, 2); break;
case 3: tgl_bit(bf, 3); break;
case 4: tgl_bit(bf, 4); break;
case 5: tgl_bit(bf, 5); break;
case 6: tgl_bit(bf, 6); break;
case 7: tgl_bit(bf, 7); break;
case 8: tgl_bit(bf, 8); break;
case 9: tgl_bit(bf, 9); break;
case 10: tgl_bit(bf, 10); break;
case 11: tgl_bit(bf, 11); break;
case 12: tgl_bit(bf, 12); break;
case 13: tgl_bit(bf, 13); break;
case 14: tgl_bit(bf, 14); break;
case 15: tgl_bit(bf, 15); break;
default: break;
}
}
static inline void val(BitField_16& bf, const uint8_t& bit, bool value)
{
switch (bit)
{
case 0: val_bit(bf, 0, value); break;
case 1: val_bit(bf, 1, value); break;
case 2: val_bit(bf, 2, value); break;
case 3: val_bit(bf, 3, value); break;
case 4: val_bit(bf, 4, value); break;
case 5: val_bit(bf, 5, value); break;
case 6: val_bit(bf, 6, value); break;
case 7: val_bit(bf, 7, value); break;
case 8: val_bit(bf, 8, value); break;
case 9: val_bit(bf, 9, value); break;
case 10: val_bit(bf, 10, value); break;
case 11: val_bit(bf, 11, value); break;
case 12: val_bit(bf, 12, value); break;
case 13: val_bit(bf, 13, value); break;
case 14: val_bit(bf, 14, value); break;
case 15: val_bit(bf, 15, value); break;
default: break;
}
}
//32-Bit field
static inline bool get(const BitField_32& bf, const uint8_t& bit)
{
switch (bit)
{
case 0: return get_bit(bf, 0);
case 1: return get_bit(bf, 1);
case 2: return get_bit(bf, 2);
case 3: return get_bit(bf, 3);
case 4: return get_bit(bf, 4);
case 5: return get_bit(bf, 5);
case 6: return get_bit(bf, 6);
case 7: return get_bit(bf, 7);
case 8: return get_bit(bf, 8);
case 9: return get_bit(bf, 9);
case 10: return get_bit(bf, 10);
case 11: return get_bit(bf, 11);
case 12: return get_bit(bf, 12);
case 13: return get_bit(bf, 13);
case 14: return get_bit(bf, 14);
case 15: return get_bit(bf, 15);
case 16: return get_bit(bf, 16);
case 17: return get_bit(bf, 17);
case 18: return get_bit(bf, 18);
case 19: return get_bit(bf, 19);
case 20: return get_bit(bf, 20);
case 21: return get_bit(bf, 21);
case 22: return get_bit(bf, 22);
case 23: return get_bit(bf, 23);
case 24: return get_bit(bf, 24);
case 25: return get_bit(bf, 25);
case 26: return get_bit(bf, 26);
case 27: return get_bit(bf, 27);
case 28: return get_bit(bf, 28);
case 29: return get_bit(bf, 29);
case 30: return get_bit(bf, 30);
case 31: return get_bit(bf, 31);
default: return false;
}
}
static inline void set(BitField_32& bf, const uint8_t& bit)
{
switch (bit)
{
case 0: set_bit(bf, 0); break;
case 1: set_bit(bf, 1); break;
case 2: set_bit(bf, 2); break;
case 3: set_bit(bf, 3); break;
case 4: set_bit(bf, 4); break;
case 5: set_bit(bf, 5); break;
case 6: set_bit(bf, 6); break;
case 7: set_bit(bf, 7); break;
case 8: set_bit(bf, 8); break;
case 9: set_bit(bf, 9); break;
case 10: set_bit(bf, 10); break;
case 11: set_bit(bf, 11); break;
case 12: set_bit(bf, 12); break;
case 13: set_bit(bf, 13); break;
case 14: set_bit(bf, 14); break;
case 15: set_bit(bf, 15); break;
case 16: set_bit(bf, 16); break;
case 17: set_bit(bf, 17); break;
case 18: set_bit(bf, 18); break;
case 19: set_bit(bf, 19); break;
case 20: set_bit(bf, 20); break;
case 21: set_bit(bf, 21); break;
case 22: set_bit(bf, 22); break;
case 23: set_bit(bf, 23); break;
case 24: set_bit(bf, 24); break;
case 25: set_bit(bf, 25); break;
case 26: set_bit(bf, 26); break;
case 27: set_bit(bf, 27); break;
case 28: set_bit(bf, 28); break;
case 29: set_bit(bf, 29); break;
case 30: set_bit(bf, 30); break;
case 31: set_bit(bf, 31); break;
default: break;
}
}
static inline void clr(BitField_32& bf, const uint8_t& bit)
{
switch (bit)
{
case 0: clr_bit(bf, 0); break;
case 1: clr_bit(bf, 1); break;
case 2: clr_bit(bf, 2); break;
case 3: clr_bit(bf, 3); break;
case 4: clr_bit(bf, 4); break;
case 5: clr_bit(bf, 5); break;
case 6: clr_bit(bf, 6); break;
case 7: clr_bit(bf, 7); break;
case 8: clr_bit(bf, 8); break;
case 9: clr_bit(bf, 9); break;
case 10: clr_bit(bf, 10); break;
case 11: clr_bit(bf, 11); break;
case 12: clr_bit(bf, 12); break;
case 13: clr_bit(bf, 13); break;
case 14: clr_bit(bf, 14); break;
case 15: clr_bit(bf, 15); break;
case 16: clr_bit(bf, 16); break;
case 17: clr_bit(bf, 17); break;
case 18: clr_bit(bf, 18); break;
case 19: clr_bit(bf, 19); break;
case 20: clr_bit(bf, 20); break;
case 21: clr_bit(bf, 21); break;
case 22: clr_bit(bf, 22); break;
case 23: clr_bit(bf, 23); break;
case 24: clr_bit(bf, 24); break;
case 25: clr_bit(bf, 25); break;
case 26: clr_bit(bf, 26); break;
case 27: clr_bit(bf, 27); break;
case 28: clr_bit(bf, 28); break;
case 29: clr_bit(bf, 29); break;
case 30: clr_bit(bf, 30); break;
case 31: clr_bit(bf, 31); break;
default: break;
}
}
static inline void tgl(BitField_32& bf, const uint8_t& bit)
{
switch (bit)
{
case 0: tgl_bit(bf, 0); break;
case 1: tgl_bit(bf, 1); break;
case 2: tgl_bit(bf, 2); break;
case 3: tgl_bit(bf, 3); break;
case 4: tgl_bit(bf, 4); break;
case 5: tgl_bit(bf, 5); break;
case 6: tgl_bit(bf, 6); break;
case 7: tgl_bit(bf, 7); break;
case 8: tgl_bit(bf, 8); break;
case 9: tgl_bit(bf, 9); break;
case 10: tgl_bit(bf, 10); break;
case 11: tgl_bit(bf, 11); break;
case 12: tgl_bit(bf, 12); break;
case 13: tgl_bit(bf, 13); break;
case 14: tgl_bit(bf, 14); break;
case 15: tgl_bit(bf, 15); break;
case 16: tgl_bit(bf, 16); break;
case 17: tgl_bit(bf, 17); break;
case 18: tgl_bit(bf, 18); break;
case 19: tgl_bit(bf, 19); break;
case 20: tgl_bit(bf, 20); break;
case 21: tgl_bit(bf, 21); break;
case 22: tgl_bit(bf, 22); break;
case 23: tgl_bit(bf, 23); break;
case 24: tgl_bit(bf, 24); break;
case 25: tgl_bit(bf, 25); break;
case 26: tgl_bit(bf, 26); break;
case 27: tgl_bit(bf, 27); break;
case 28: tgl_bit(bf, 28); break;
case 29: tgl_bit(bf, 29); break;
case 30: tgl_bit(bf, 30); break;
case 31: tgl_bit(bf, 31); break;
default: break;
}
}
static inline void val(BitField_32& bf, const uint8_t& bit, bool value)
{
switch (bit)
{
case 0: val_bit(bf, 0, value); break;
case 1: val_bit(bf, 1, value); break;
case 2: val_bit(bf, 2, value); break;
case 3: val_bit(bf, 3, value); break;
case 4: val_bit(bf, 4, value); break;
case 5: val_bit(bf, 5, value); break;
case 6: val_bit(bf, 6, value); break;
case 7: val_bit(bf, 7, value); break;
case 8: val_bit(bf, 8, value); break;
case 9: val_bit(bf, 9, value); break;
case 10: val_bit(bf, 10, value); break;
case 11: val_bit(bf, 11, value); break;
case 12: val_bit(bf, 12, value); break;
case 13: val_bit(bf, 13, value); break;
case 14: val_bit(bf, 14, value); break;
case 15: val_bit(bf, 15, value); break;
case 16: val_bit(bf, 16, value); break;
case 17: val_bit(bf, 17, value); break;
case 18: val_bit(bf, 18, value); break;
case 19: val_bit(bf, 19, value); break;
case 20: val_bit(bf, 20, value); break;
case 21: val_bit(bf, 21, value); break;
case 22: val_bit(bf, 22, value); break;
case 23: val_bit(bf, 23, value); break;
case 24: val_bit(bf, 24, value); break;
case 25: val_bit(bf, 25, value); break;
case 26: val_bit(bf, 26, value); break;
case 27: val_bit(bf, 27, value); break;
case 28: val_bit(bf, 28, value); break;
case 29: val_bit(bf, 29, value); break;
case 30: val_bit(bf, 30, value); break;
case 31: val_bit(bf, 31, value); break;
default: break;
}
}
//64-Bit field
static inline bool get(const BitField_64& bf, const uint8_t& bit)
{
switch (bit)
{
case 0: return get_bit(bf, 0);
case 1: return get_bit(bf, 1);
case 2: return get_bit(bf, 2);
case 3: return get_bit(bf, 3);
case 4: return get_bit(bf, 4);
case 5: return get_bit(bf, 5);
case 6: return get_bit(bf, 6);
case 7: return get_bit(bf, 7);
case 8: return get_bit(bf, 8);
case 9: return get_bit(bf, 9);
case 10: return get_bit(bf, 10);
case 11: return get_bit(bf, 11);
case 12: return get_bit(bf, 12);
case 13: return get_bit(bf, 13);
case 14: return get_bit(bf, 14);
case 15: return get_bit(bf, 15);
case 16: return get_bit(bf, 16);
case 17: return get_bit(bf, 17);
case 18: return get_bit(bf, 18);
case 19: return get_bit(bf, 19);
case 20: return get_bit(bf, 20);
case 21: return get_bit(bf, 21);
case 22: return get_bit(bf, 22);
case 23: return get_bit(bf, 23);
case 24: return get_bit(bf, 24);
case 25: return get_bit(bf, 25);
case 26: return get_bit(bf, 26);
case 27: return get_bit(bf, 27);
case 28: return get_bit(bf, 28);
case 29: return get_bit(bf, 29);
case 30: return get_bit(bf, 30);
case 31: return get_bit(bf, 31);
case 32: return get_bit(bf, 32);
case 33: return get_bit(bf, 33);
case 34: return get_bit(bf, 34);
case 35: return get_bit(bf, 35);
case 36: return get_bit(bf, 36);
case 37: return get_bit(bf, 37);
case 38: return get_bit(bf, 38);
case 39: return get_bit(bf, 39);
case 40: return get_bit(bf, 40);
case 41: return get_bit(bf, 41);
case 42: return get_bit(bf, 42);
case 43: return get_bit(bf, 43);
case 44: return get_bit(bf, 44);
case 45: return get_bit(bf, 45);
case 46: return get_bit(bf, 46);
case 47: return get_bit(bf, 47);
case 48: return get_bit(bf, 48);
case 49: return get_bit(bf, 49);
case 50: return get_bit(bf, 50);
case 51: return get_bit(bf, 51);
case 52: return get_bit(bf, 52);
case 53: return get_bit(bf, 53);
case 54: return get_bit(bf, 54);
case 55: return get_bit(bf, 55);
case 56: return get_bit(bf, 56);
case 57: return get_bit(bf, 57);
case 58: return get_bit(bf, 58);
case 59: return get_bit(bf, 59);
case 60: return get_bit(bf, 60);
case 61: return get_bit(bf, 61);
case 62: return get_bit(bf, 62);
case 63: return get_bit(bf, 63);
default: return false;
}
}
static inline void set(BitField_64& bf, const uint8_t& bit)
{
switch (bit)
{
case 0: set_bit(bf, 0); break;
case 1: set_bit(bf, 1); break;
case 2: set_bit(bf, 2); break;
case 3: set_bit(bf, 3); break;
case 4: set_bit(bf, 4); break;
case 5: set_bit(bf, 5); break;
case 6: set_bit(bf, 6); break;
case 7: set_bit(bf, 7); break;
case 8: set_bit(bf, 8); break;
case 9: set_bit(bf, 9); break;
case 10: set_bit(bf, 10); break;
case 11: set_bit(bf, 11); break;
case 12: set_bit(bf, 12); break;
case 13: set_bit(bf, 13); break;
case 14: set_bit(bf, 14); break;
case 15: set_bit(bf, 15); break;
case 16: set_bit(bf, 16); break;
case 17: set_bit(bf, 17); break;
case 18: set_bit(bf, 18); break;
case 19: set_bit(bf, 19); break;
case 20: set_bit(bf, 20); break;
case 21: set_bit(bf, 21); break;
case 22: set_bit(bf, 22); break;
case 23: set_bit(bf, 23); break;
case 24: set_bit(bf, 24); break;
case 25: set_bit(bf, 25); break;
case 26: set_bit(bf, 26); break;
case 27: set_bit(bf, 27); break;
case 28: set_bit(bf, 28); break;
case 29: set_bit(bf, 29); break;
case 30: set_bit(bf, 30); break;
case 31: set_bit(bf, 31); break;
case 32: set_bit(bf, 32); break;
case 33: set_bit(bf, 33); break;
case 34: set_bit(bf, 34); break;
case 35: set_bit(bf, 35); break;
case 36: set_bit(bf, 36); break;
case 37: set_bit(bf, 37); break;
case 38: set_bit(bf, 38); break;
case 39: set_bit(bf, 39); break;
case 40: set_bit(bf, 40); break;
case 41: set_bit(bf, 41); break;
case 42: set_bit(bf, 42); break;
case 43: set_bit(bf, 43); break;
case 44: set_bit(bf, 44); break;
case 45: set_bit(bf, 45); break;
case 46: set_bit(bf, 46); break;
case 47: set_bit(bf, 47); break;
case 48: set_bit(bf, 48); break;
case 49: set_bit(bf, 49); break;
case 50: set_bit(bf, 50); break;
case 51: set_bit(bf, 51); break;
case 52: set_bit(bf, 52); break;
case 53: set_bit(bf, 53); break;
case 54: set_bit(bf, 54); break;
case 55: set_bit(bf, 55); break;
case 56: set_bit(bf, 56); break;
case 57: set_bit(bf, 57); break;
case 58: set_bit(bf, 58); break;
case 59: set_bit(bf, 59); break;
case 60: set_bit(bf, 60); break;
case 61: set_bit(bf, 61); break;
case 62: set_bit(bf, 62); break;
case 63: set_bit(bf, 63); break;
default: break;
}
}
static inline void clr(BitField_64& bf, const uint8_t& bit)
{
switch (bit)
{
case 0: clr_bit(bf, 0); break;
case 1: clr_bit(bf, 1); break;
case 2: clr_bit(bf, 2); break;
case 3: clr_bit(bf, 3); break;
case 4: clr_bit(bf, 4); break;
case 5: clr_bit(bf, 5); break;
case 6: clr_bit(bf, 6); break;
case 7: clr_bit(bf, 7); break;
case 8: clr_bit(bf, 8); break;
case 9: clr_bit(bf, 9); break;
case 10: clr_bit(bf, 10); break;
case 11: clr_bit(bf, 11); break;
case 12: clr_bit(bf, 12); break;
case 13: clr_bit(bf, 13); break;
case 14: clr_bit(bf, 14); break;
case 15: clr_bit(bf, 15); break;
case 16: clr_bit(bf, 16); break;
case 17: clr_bit(bf, 17); break;
case 18: clr_bit(bf, 18); break;
case 19: clr_bit(bf, 19); break;
case 20: clr_bit(bf, 20); break;
case 21: clr_bit(bf, 21); break;
case 22: clr_bit(bf, 22); break;
case 23: clr_bit(bf, 23); break;
case 24: clr_bit(bf, 24); break;
case 25: clr_bit(bf, 25); break;
case 26: clr_bit(bf, 26); break;
case 27: clr_bit(bf, 27); break;
case 28: clr_bit(bf, 28); break;
case 29: clr_bit(bf, 29); break;
case 30: clr_bit(bf, 30); break;
case 31: clr_bit(bf, 31); break;
case 32: clr_bit(bf, 32); break;
case 33: clr_bit(bf, 33); break;
case 34: clr_bit(bf, 34); break;
case 35: clr_bit(bf, 35); break;
case 36: clr_bit(bf, 36); break;
case 37: clr_bit(bf, 37); break;
case 38: clr_bit(bf, 38); break;
case 39: clr_bit(bf, 39); break;
case 40: clr_bit(bf, 40); break;
case 41: clr_bit(bf, 41); break;
case 42: clr_bit(bf, 42); break;
case 43: clr_bit(bf, 43); break;
case 44: clr_bit(bf, 44); break;
case 45: clr_bit(bf, 45); break;
case 46: clr_bit(bf, 46); break;
case 47: clr_bit(bf, 47); break;
case 48: clr_bit(bf, 48); break;
case 49: clr_bit(bf, 49); break;
case 50: clr_bit(bf, 50); break;
case 51: clr_bit(bf, 51); break;
case 52: clr_bit(bf, 52); break;
case 53: clr_bit(bf, 53); break;
case 54: clr_bit(bf, 54); break;
case 55: clr_bit(bf, 55); break;
case 56: clr_bit(bf, 56); break;
case 57: clr_bit(bf, 57); break;
case 58: clr_bit(bf, 58); break;
case 59: clr_bit(bf, 59); break;
case 60: clr_bit(bf, 60); break;
case 61: clr_bit(bf, 61); break;
case 62: clr_bit(bf, 62); break;
case 63: clr_bit(bf, 63); break;
default: break;
}
}
static inline void tgl(BitField_64& bf, const uint8_t& bit)
{
switch (bit)
{
case 0: tgl_bit(bf, 0); break;
case 1: tgl_bit(bf, 1); break;
case 2: tgl_bit(bf, 2); break;
case 3: tgl_bit(bf, 3); break;
case 4: tgl_bit(bf, 4); break;
case 5: tgl_bit(bf, 5); break;
case 6: tgl_bit(bf, 6); break;
case 7: tgl_bit(bf, 7); break;
case 8: tgl_bit(bf, 8); break;
case 9: tgl_bit(bf, 9); break;
case 10: tgl_bit(bf, 10); break;
case 11: tgl_bit(bf, 11); break;
case 12: tgl_bit(bf, 12); break;
case 13: tgl_bit(bf, 13); break;
case 14: tgl_bit(bf, 14); break;
case 15: tgl_bit(bf, 15); break;
case 16: tgl_bit(bf, 16); break;
case 17: tgl_bit(bf, 17); break;
case 18: tgl_bit(bf, 18); break;
case 19: tgl_bit(bf, 19); break;
case 20: tgl_bit(bf, 20); break;
case 21: tgl_bit(bf, 21); break;
case 22: tgl_bit(bf, 22); break;
case 23: tgl_bit(bf, 23); break;
case 24: tgl_bit(bf, 24); break;
case 25: tgl_bit(bf, 25); break;
case 26: tgl_bit(bf, 26); break;
case 27: tgl_bit(bf, 27); break;
case 28: tgl_bit(bf, 28); break;
case 29: tgl_bit(bf, 29); break;
case 30: tgl_bit(bf, 30); break;
case 31: tgl_bit(bf, 31); break;
case 32: tgl_bit(bf, 32); break;
case 33: tgl_bit(bf, 33); break;
case 34: tgl_bit(bf, 34); break;
case 35: tgl_bit(bf, 35); break;
case 36: tgl_bit(bf, 36); break;
case 37: tgl_bit(bf, 37); break;
case 38: tgl_bit(bf, 38); break;
case 39: tgl_bit(bf, 39); break;
case 40: tgl_bit(bf, 40); break;
case 41: tgl_bit(bf, 41); break;
case 42: tgl_bit(bf, 42); break;
case 43: tgl_bit(bf, 43); break;
case 44: tgl_bit(bf, 44); break;
case 45: tgl_bit(bf, 45); break;
case 46: tgl_bit(bf, 46); break;
case 47: tgl_bit(bf, 47); break;
case 48: tgl_bit(bf, 48); break;
case 49: tgl_bit(bf, 49); break;
case 50: tgl_bit(bf, 50); break;
case 51: tgl_bit(bf, 51); break;
case 52: tgl_bit(bf, 52); break;
case 53: tgl_bit(bf, 53); break;
case 54: tgl_bit(bf, 54); break;
case 55: tgl_bit(bf, 55); break;
case 56: tgl_bit(bf, 56); break;
case 57: tgl_bit(bf, 57); break;
case 58: tgl_bit(bf, 58); break;
case 59: tgl_bit(bf, 59); break;
case 60: tgl_bit(bf, 60); break;
case 61: tgl_bit(bf, 61); break;
case 62: tgl_bit(bf, 62); break;
case 63: tgl_bit(bf, 63); break;
default: break;
}
}
static inline void val(BitField_64& bf, const uint8_t& bit, bool value)
{
switch (bit)
{
case 0: val_bit(bf, 0, value); break;
case 1: val_bit(bf, 1, value); break;
case 2: val_bit(bf, 2, value); break;
case 3: val_bit(bf, 3, value); break;
case 4: val_bit(bf, 4, value); break;
case 5: val_bit(bf, 5, value); break;
case 6: val_bit(bf, 6, value); break;
case 7: val_bit(bf, 7, value); break;
case 8: val_bit(bf, 8, value); break;
case 9: val_bit(bf, 9, value); break;
case 10: val_bit(bf, 10, value); break;
case 11: val_bit(bf, 11, value); break;
case 12: val_bit(bf, 12, value); break;
case 13: val_bit(bf, 13, value); break;
case 14: val_bit(bf, 14, value); break;
case 15: val_bit(bf, 15, value); break;
case 16: val_bit(bf, 16, value); break;
case 17: val_bit(bf, 17, value); break;
case 18: val_bit(bf, 18, value); break;
case 19: val_bit(bf, 19, value); break;
case 20: val_bit(bf, 20, value); break;
case 21: val_bit(bf, 21, value); break;
case 22: val_bit(bf, 22, value); break;
case 23: val_bit(bf, 23, value); break;
case 24: val_bit(bf, 24, value); break;
case 25: val_bit(bf, 25, value); break;
case 26: val_bit(bf, 26, value); break;
case 27: val_bit(bf, 27, value); break;
case 28: val_bit(bf, 28, value); break;
case 29: val_bit(bf, 29, value); break;
case 30: val_bit(bf, 30, value); break;
case 31: val_bit(bf, 31, value); break;
case 32: val_bit(bf, 32, value); break;
case 33: val_bit(bf, 33, value); break;
case 34: val_bit(bf, 34, value); break;
case 35: val_bit(bf, 35, value); break;
case 36: val_bit(bf, 36, value); break;
case 37: val_bit(bf, 37, value); break;
case 38: val_bit(bf, 38, value); break;
case 39: val_bit(bf, 39, value); break;
case 40: val_bit(bf, 40, value); break;
case 41: val_bit(bf, 41, value); break;
case 42: val_bit(bf, 42, value); break;
case 43: val_bit(bf, 43, value); break;
case 44: val_bit(bf, 44, value); break;
case 45: val_bit(bf, 45, value); break;
case 46: val_bit(bf, 46, value); break;
case 47: val_bit(bf, 47, value); break;
case 48: val_bit(bf, 48, value); break;
case 49: val_bit(bf, 49, value); break;
case 50: val_bit(bf, 50, value); break;
case 51: val_bit(bf, 51, value); break;
case 52: val_bit(bf, 52, value); break;
case 53: val_bit(bf, 53, value); break;
case 54: val_bit(bf, 54, value); break;
case 55: val_bit(bf, 55, value); break;
case 56: val_bit(bf, 56, value); break;
case 57: val_bit(bf, 57, value); break;
case 58: val_bit(bf, 58, value); break;
case 59: val_bit(bf, 59, value); break;
case 60: val_bit(bf, 60, value); break;
case 61: val_bit(bf, 61, value); break;
case 62: val_bit(bf, 62, value); break;
case 63: val_bit(bf, 63, value); break;
default: break;
}
}
};
} // namesoace ox
#endif

238
src/ostd/Color.cpp Executable file
View file

@ -0,0 +1,238 @@
#include "Color.hpp"
#include <cmath>
#include "Utils.hpp"
#include "Logger.hpp"
namespace ostd
{
Color::Color(void)
{
set();
setTypeName("ox::Color");
BaseObject::setValid(true);
}
Color::Color(uint8_t rgb_single_value, uint8_t alpha)
{
set(rgb_single_value, alpha);
setTypeName("ox::Color");
BaseObject::setValid(true);
}
Color::Color(uint8_t _r, uint8_t _g, uint8_t _b, uint8_t alpha)
{
set(_r, _g, _b, alpha);
setTypeName("ox::Color");
BaseObject::setValid(true);
}
// Color::Color(const sf::Color& sfml_color)
// {
// set(sfml_color);
// setTypeName("ox::Color");
// BaseObject::setValid(true);
// }
Color::Color(const String& color_string)
{
set(color_string);
setTypeName("ox::Color");
BaseObject::setValid(true);
}
Color::Color(const FloatCol& normalized_color)
{
set(normalized_color);
setTypeName("ox::Color");
BaseObject::setValid(true);
}
Color::Color(const Color& copy) : BaseObject(copy)
{
r = copy.r;
g = copy.g;
b = copy.b;
a = copy.a;
}
bool Color::operator==(const Color& col2)
{
return (r == col2.r && g == col2.g && b == col2.b && a == col2.a);
}
bool Color::operator!=(const Color& col2)
{
return !(*this == col2);
}
Color& Color::operator=(const Color& copy)
{
BaseObject::operator=(copy);
r = copy.r;
g = copy.g;
b = copy.b;
a = copy.a;
return *this;
}
Color& Color::set(void)
{
r = 0;
g = 0;
b = 0;
a = 255;
return *this;
}
Color& Color::set(uint8_t rgb_single_value, uint8_t alpha)
{
r = rgb_single_value;
g = rgb_single_value;
b = rgb_single_value;
a = alpha;
return *this;
}
Color& Color::set(uint8_t _r, uint8_t _g, uint8_t _b, uint8_t alpha)
{
r = _r;
g = _g;
b = _b;
a = alpha;
return *this;
}
// Color& Color::set(const sf::Color& sfml_color)
// {
// r = sfml_color.r;
// g = sfml_color.g;
// b = sfml_color.b;
// a = sfml_color.a;
// return *this;
// }
Color& Color::set(const String& color_string)
{
StringEditor se(color_string);
se.trim();
r = g = b = 0;
a = 255;
if (se.startsWith("#"))
{
StringEditor tmp = se.substr(1);
tmp.trim();
se = "0x" + tmp.str();
}
if (se.startsWith("0x"))
{
int64_t ic = Utils::strToInt(se.str());
union uC32 {
uint8_t data[4];
uint32_t value;
} c32_u;
c32_u.value = static_cast<uint32_t>(ic);
a = c32_u.data[0];
b = c32_u.data[1];
g = c32_u.data[2];
r = c32_u.data[3];
}
else if ((se.startsWith("(") || se.startsWith("rgba(") || se.startsWith("rgb(")) && se.endsWith(")") && se.contains(","))
{
se = se.substr(se.indexOf("(") + 1, se.len() - 1);
se.trim();
auto tokens = se.tokenize(",", true, false);
if (tokens.count() < 3 || tokens.count() > 4)
{
OX_WARN("ox::Color::set(const String&) -> Invalid rgb string format: %s.", color_string.c_str());
return *this;
}
r = Utils::strToInt(tokens.next());
g = Utils::strToInt(tokens.next());
b = Utils::strToInt(tokens.next());
if (tokens.hasNext())
a = Utils::strToInt(tokens.next());
}
else
{
OX_WARN("ox::Color::set(const String&) -> Unkown color string format: %s", color_string.c_str());
}
return *this;
}
Color& Color::set(const FloatCol& normalized_color)
{
r = static_cast<uint8_t>(std::round(normalized_color.r * 255));
g = static_cast<uint8_t>(std::round(normalized_color.g * 255));
b = static_cast<uint8_t>(std::round(normalized_color.b * 255));
a = static_cast<uint8_t>(std::round(normalized_color.a * 255));
return *this;
}
// sf::Color Color::sf(void) const
// {
// return { r, g, b, a };
// }
String Color::hexString(bool include_alpha, String prefix) const
{
String hex = "";
hex += Utils::getHexStr(r, false, 1);
hex += Utils::getHexStr(g, false, 1);
hex += Utils::getHexStr(b, false, 1);
if (include_alpha)
hex += Utils::getHexStr(a, false, 1);
hex = prefix + StringEditor(hex).toUpper().str();
return hex;
}
String Color::rgbString(bool include_parenthesis, bool include_alpha) const
{
StringEditor rgb = "";
if (include_parenthesis)
rgb.add("(");
rgb.addi(r).add(", ");
rgb.addi(g).add(", ");
rgb.addi(b);
if (include_alpha)
rgb.add(", ").addi(a);
if (include_parenthesis)
rgb.add(")");
return rgb.str();
}
uint32_t Color::asInteger(void) const
{
union uC32 {
uint8_t data[4];
uint32_t value;
} c32_u;
c32_u.data[0] = a;
c32_u.data[1] = b;
c32_u.data[2] = g;
c32_u.data[3] = r;
return c32_u.value;
}
Color::FloatCol Color::getNormalizedColor(void) const
{
return { r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f };
}
String Color::toString(void) const
{
return hexString(true, "#") + " -> rgba" + rgbString(true, true);
}
void Color::print(bool newLine, IOutputHandler* __destination) const
{
if (__destination == nullptr)
std::cout << *this << (newLine ? "\n" : "");
else
{
__destination->p(this->toString());
if (newLine) __destination->nl();
}
}
} //namesoace ox

64
src/ostd/Color.hpp Executable file
View file

@ -0,0 +1,64 @@
#ifndef __COLOR_HPP__
#define __COLOR_HPP__
#include <cstdint>
#include <ostd/Types.hpp>
#include <ostd/BaseObject.hpp>
namespace ostd
{
class Color : public BaseObject
{
public: struct FloatCol
{
float r;
float g;
float b;
float a;
FloatCol(void) : r(0.0f), g(0.0f), b(0.0f), a(1.0f) { }
FloatCol(float _r, float _g, float _b, float _a) : r(_r), g(_g), b(_b), a(_a) { }
};
public:
Color(void);
Color(uint8_t rgb_single_value, uint8_t alpha = 255);
Color(uint8_t _r, uint8_t _g, uint8_t _b, uint8_t alpha = 255);
//Color(const sf::Color& sfml_color);
Color(const String& color_string);
Color(const FloatCol& normalized_color);
Color(const Color& copy);
bool operator==(const Color& col2);
bool operator!=(const Color& col2);
Color& operator=(const Color& copy);
Color& set(void);
Color& set(uint8_t rgb_single_value, uint8_t alpha = 255);
Color& set(uint8_t _r, uint8_t _g, uint8_t _b, uint8_t alpha = 255);
//Color& set(const sf::Color& sfml_color);
Color& set(const String& color_string);
Color& set(const FloatCol& normalized_color);
//sf::Color sf(void) const;
String hexString(bool include_alpha = false, String prefix = "0x") const;
String rgbString(bool include_parenthesis = true, bool include_alpha = false) const;
uint32_t asInteger(void) const;
FloatCol getNormalizedColor(void) const;
String toString(void) const override;
void print(bool newLine = true, IOutputHandler* __destination = nullptr) const override;
inline void invalidate(void) override { }
inline void setValid(bool valid) override { }
public:
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t a;
};
} //namesoace ox
#endif

439
src/ostd/DataFile.cpp Executable file
View file

@ -0,0 +1,439 @@
#include "DataFile.hpp"
#include "Utils.hpp"
#include <utility>
//TODO: Add all errors
namespace ostd
{
DataBlock::DataBlock(void)
{
type = eDataBlockType::Invalid;
name = "";
value = "null";
invalidate();
setTypeName("ox::DataBlock");
}
int32_t DataBlock::asInt(void) const
{
if (type != eDataBlockType::Int)
return 0;
return StringEditor(value).toInt();
}
float DataBlock::asFloat(void) const
{
if (type != eDataBlockType::Float)
return 0;
return StringEditor(value).toFloat();
}
String DataBlock::asString(void) const
{
return StringEditor(value).trim().str();
}
std::vector<int32_t> DataBlock::asIntArray(void) const
{
std::vector<int32_t> arr;
StringEditor _value = value;
if (type != eDataBlockType::IntArray || _value.contains("\""))
{
// ErrorHandler::instance().pushError(Errors::InvalidDataBlockType, "omnia::common::DataBlock::asIntArray(...) -> 1");
// return arr;
}
if (!_value.trim().startsWith("(") || !_value.trim().endsWith(")"))
{
// ErrorHandler::instance().pushError(Errors::InvalidDataBlockType, "omnia::common::DataBlock::asIntArray(...) -> 2");
// return arr;
}
_value = _value.substr(1, _value.len() - 1);
auto st = _value.tokenize(",");
while (st.hasNext())
arr.push_back(StringEditor(st.next()).toInt());
return arr;
}
std::vector<String> DataBlock::asStringArray(void) const
{
std::vector<String> arr;
StringEditor _value = value;
if (type != eDataBlockType::StringArray || !_value.contains("\""))
{
// ErrorHandler::instance().pushError(Errors::InvalidDataBlockType, "omnia::common::DataBlock::asStringArray(...) -> 1");
// return arr;
}
if (!_value.trim().startsWith("(") || !_value.trim().endsWith(")"))
{
// ErrorHandler::instance().pushError(Errors::InvalidDataBlockType, "omnia::common::DataBlock::asStringArray(...) -> 2");
// return arr;
}
_value = _value.substr(1, _value.len() - 1);
auto st = _value.tokenize(",");
StringEditor token = "";
while (st.hasNext())
{
token = st.next();
if (!token.startsWith("\"") || !token.endsWith("\""))
{
// ErrorHandler::instance().pushError(Errors::InvalidDataBlockType, "omnia::common::DataBlock::asStringArray(...) -> 3");
// continue;
}
token = token.substr(1, token.len() - 1);
arr.push_back(token.str());
}
return arr;
}
String DataBlock::asLiteral(void) const
{
if (type != eDataBlockType::Literal)
{
// ErrorHandler::instance().pushError(Errors::InvalidDataBlockType, "omnia::common::DataBlock::asLiteral(...)");
// return "";
}
return StringEditor(value).trim().str();
}
Color DataBlock::asColor(void) const
{
if (type != eDataBlockType::IntArray)
{
// ErrorHandler::instance().pushError(Errors::InvalidDataBlockType, "omnia::common::DataBlock::asColor(...)");
// return Color::Transparent;
}
std::vector<int32_t> v = asIntArray();
if (v.size() != 4)
{
// ErrorHandler::instance().pushError(Errors::InvalidDataBlockValue, "omnia::common::DataBlock::asColor(...): Color-array must contain exactly 4 items.");
// return Color::Transparent;
}
return Color(v[0], v[1], v[2], v[3]);
}
void DataFile::load(String filePath)
{
if (StringEditor(filePath).trim().str() == "")
{
// ErrorHandler::instance().pushError(Errors::InvalidDataFilePath, StringBuilder("in omnia::common::DataFile::load(...); path is empty").get());
// invalidate();
return;
}
setValid(true);
setTypeName("ox::DataFile");
m_dataFilePath = filePath;
std::vector<String> lines;
if (!Utils::readFile(filePath, lines))
{
// ErrorHandler::instance().pushError(Errors::InvalidDataFilePath, StringBuilder("in omnia::common::DataFile::load(...); path = ").add(filePath).get());
// invalidate();
return;
}
m_rawContent = "";
for (auto& line : lines)
m_rawContent += line + "\n";
loadDefines(m_rawContent);
String newData = replaceDefines(m_rawContent);
auto st = StringEditor(newData).tokenize("]");
StringEditor token = "";
while (st.hasNext()) //Priority round
{
token = st.next();
if (!token.startsWith("["))
{
// ErrorHandler::instance().pushError(Errors::InvalidDataFileBlock, "omnia::common::DataFile::load(...); Priority-round; All DataFile blocks must start with a '[' character");
continue;
}
token = token.substr(1);
token.trim();
if (token.startsWith("*"))
{
token = token.substr(1);
token.trim();
if (!token.contains(":"))
continue;
StringEditor inst = token.substr(0, token.indexOf(":"));
inst.trim();
StringEditor data = token.substr(token.indexOf(":") + 1);
data.trim();
DFD_LIST paramList;
auto st2 = data.tokenize(";");
String param = "";
while (st2.hasNext())
{
param = st2.next();
DataBlock p = parseParameter(param);
if (p.isValid())
paramList.push_back(p);
// else
// ErrorHandler::instance().pushError(Errors::UnableToParseDataBlock, StringBuilder("omnia::common::DataFile::load(...); Priority-round; param=").add(param).add("; inst=").add(inst).get());
}
onDataBlockRead(inst.toLower().str(), paramList, paramList.size());
}
}
st.cycle();
while (st.hasNext()) //Main Round
{
token = st.next();
if (!token.startsWith("["))
{
// ErrorHandler::instance().pushError(Errors::InvalidDataFileBlock, "omnia::common::DataFile::load(...); Main-round; All DataFile blocks must start with a '[' character");
continue;
}
token = token.substr(1);
token.trim();
if (token.startsWith("$") || token.startsWith("*") || token.startsWith("#") || token.startsWith("@") || token.startsWith("!"))
continue;
else if (token.startsWith(">"))
{
token = token.substr(1);
token.trim();
std::cout << token << "\n";
continue;
}
else
{
if (!token.contains(":"))
continue;
StringEditor inst = token.substr(0, token.indexOf(":"));
inst.trim();
StringEditor data = token.substr(token.indexOf(":") + 1);
data.trim();
DFD_LIST paramList;
auto st2 = data.tokenize(";");
String param = "";
while (st2.hasNext())
{
param = st2.next();
DataBlock p = parseParameter(param);
if (p.isValid())
paramList.push_back(p);
// else
// ErrorHandler::instance().pushError(Errors::UnableToParseDataBlock, StringBuilder("omnia::common::DataFile::load(...); Main-round; param=").add(param).add("; inst=").add(inst).get());
}
onDataBlockRead(inst.toLower().str(), paramList, paramList.size());
}
}
}
void DataFile::addLocal(String name, int32_t value)
{
DataBlock fv;
fv.type = eDataBlockType::Int;
fv.name = name;
fv.value = StringEditor().addi(value).str();
m_localDefs.push_back(fv);
}
void DataFile::addLocal(String name, String value, bool literal)
{
DataBlock fv;
fv.type = (literal ? eDataBlockType::Literal : eDataBlockType::String);
fv.name = name;
fv.value = value;
m_localDefs.push_back(fv);
}
const DataBlock DataFile::getLocal(String name)
{
for (auto& fv : m_localDefs)
{
if (StringEditor(fv.name).trim().str() == StringEditor(name).trim().str())
return std::as_const(fv);
}
DataBlock fv;
// ErrorHandler::instance().pushError(Errors::LocalDataBlockNotFound, StringBuilder("in omnia::common::DataFile::getLocal(...); name=").add(name).get());
return std::as_const(fv);
}
void DataFile::addGlobal(String name, int32_t value)
{
DataBlock fv;
fv.type = eDataBlockType::Int;
fv.name = name;
fv.value = StringEditor().addi(value).str();
s_globalDefs.push_back(fv);
}
void DataFile::addGlobal(String name, String value, bool literal)
{
DataBlock fv;
fv.type = (literal ? eDataBlockType::Literal : eDataBlockType::String);
fv.name = name;
fv.value = value;
s_globalDefs.push_back(fv);
}
const DataBlock DataFile::getGlobal(String name)
{
for (auto& fv : s_globalDefs)
{
if (StringEditor(fv.name).trim().str() == StringEditor(name).trim().str())
return std::as_const(fv);
}
DataBlock fv;
// ErrorHandler::instance().pushError(Errors::GlobalDataBlockNotFound, StringBuilder("in omnia::common::DataFile::getLocal(...); name=").add(name).get());
return fv;//std::as_const(fv);
}
void DataFile::loadDefines(String data)
{
auto st = StringEditor(data).tokenize("]");
StringEditor token = "";
while (st.hasNext())
{
token = st.next();
if (!token.startsWith("["))
{
// ErrorHandler::instance().pushError(Errors::InvalidDataFileBlock, "omnia::common::DataFile::loadDefines(...); All DataFile Defines must start with a '[' character");
continue;
}
token = token.substr(1);
token.trim();
if (token.startsWith("#")) //Local var
{
if (!token.contains("="))
{
// ErrorHandler::instance().pushError(Errors::InvalidDataBlockDefineValue, "omnia::common::DataFile::loadDefines(...); Local DataFile Defines must contain an assignment operator and a valid Value");
continue;
}
String name = "";
StringEditor value = "";
name = token.substr(1, token.indexOf("="));
name = StringEditor(name).trim().str();
value = token.substr(token.indexOf("=") + 1);
value.trim();
if (StringEditor(value).startsWith("%"))
{
value = StringEditor(value).substr(1);
value.trim();
addLocal(name, value.str(), true);
}
else if (!value.startsWith("\"") && !value.endsWith("\""))
addLocal(name, value.toInt());
else if (value.startsWith("\"") && value.endsWith("\""))
{
value = value.substr(1, value.len() - 1);
addLocal(name, value.str());
}
else
{
// ErrorHandler::instance().pushError(Errors::InvalidDataBlockDefineValue, "omnia::common::DataFile::loadDefines(...); Unknown value type in Local Define assignment");
continue;
}
}
else if (token.startsWith("@")) //Global var
{
if (!token.contains("="))
{
// ErrorHandler::instance().pushError(Errors::InvalidDataBlockDefineValue, "omnia::common::DataFile::loadDefines(...); Global DataFile Defines must contain an assignment operator and a valid Value");
continue;
}
String name = "";
StringEditor value = "";
name = token.substr(1, token.indexOf("="));
name = StringEditor(name).trim().str();
value = token.substr(token.indexOf("=") + 1);
value.trim();
if (value.startsWith("%"))
{
value = value.substr(1);
value.trim();
DataFile::addGlobal(name, value.str(), true);
}
else if (!value.startsWith("\"") && !value.endsWith("\""))
DataFile::addGlobal(name, value.toInt());
else if (value.startsWith("\"") && value.endsWith("\""))
{
value = value.substr(1, value.len() - 1);
DataFile::addGlobal(name, value.str());
}
else
{
// ErrorHandler::instance().pushError(Errors::InvalidDataBlockDefineValue, "omnia::common::DataFile::loadDefines(...); Unknown value type in Global Define assignment");
continue;
}
}
}
}
String DataFile::replaceDefines(String data)
{
StringEditor newData = data;
for (auto& def : m_localDefs)
{
if (def.type == eDataBlockType::String)
newData = newData.replaceAll(def.name, StringEditor("\"").add(def.value).add("\"").str());
else if (def.type == eDataBlockType::Int)
newData = newData.replaceAll(def.name, def.value);
else if (def.type == eDataBlockType::Literal)
newData = newData.replaceAll(def.name, def.value);
}
for (auto& def : s_globalDefs)
{
if (def.type == eDataBlockType::String)
newData = newData.replaceAll(def.name, StringEditor("\"").add(def.value).add("\"").str());
else if (def.type == eDataBlockType::Int)
newData = newData.replaceAll(def.name, def.value);
else if (def.type == eDataBlockType::Literal)
newData = newData.replaceAll(def.name, def.value);
}
return newData.str();
}
DataBlock DataFile::parseParameter(String _param)
{
DataBlock db;
StringEditor param = _param;
if (!param.contains("="))
{
// ErrorHandler::instance().pushError(Errors::DataBlockParamAssignMissing, "omnia::common::DataFile::parseParameter(...);");
return db;
}
param = param.trim();
String name = "";
StringEditor value = "";
name = param.substr(0, param.indexOf("="));
name = StringEditor(name).trim().str();
value = param.substr(param.indexOf("=") + 1);
value.trim();
db.name = StringEditor(name).toLower().str();
db.value = value.str();
if (value.startsWith("\""))
{
if (!value.endsWith("\""))
{
db.invalidate();
// ErrorHandler::instance().pushError(Errors::DataBlockUnmatchedDoubleQuote, "omnia::common::DataFile::parseParameter(...);");
return db;
}
value = value.substr(1, value.len() - 1);
db.type = eDataBlockType::String;
db.value = value.str();
}
else if (value.startsWith("("))
{
if (!value.endsWith(")"))
{
db.invalidate();
// ErrorHandler::instance().pushError(Errors::DataBlockUnmatchedParenth, "omnia::common::DataFile::parseParameter(...);");
return db;
}
db.type = (value.contains("\"") ? eDataBlockType::StringArray : eDataBlockType::IntArray);
}
else if (value.toLower().startsWith("f"))
{
value = value.substr(1);
value.trim();
db.value = value.str();
db.type = eDataBlockType::Float;
}
else
db.type = eDataBlockType::Int;
db.validate();
return db;
}
}

80
src/ostd/DataFile.hpp Executable file
View file

@ -0,0 +1,80 @@
#ifndef __DATAFILE_HPP__
#define __DATAFILE_HPP__
#include <ostd/Color.hpp>
#include <ostd/BaseObject.hpp>
#include <vector>
#define DATABLOCK_TRUE 1
#define DATABLOCK_FALSE 0
#define DFD_LIST std::vector<ostd::DataBlock>
namespace ostd
{
enum class eDataBlockType
{
Invalid = 0,
Int,
Float,
String,
IntArray,
StringArray,
Literal
};
struct DataBlock : public BaseObject
{
public:
DataBlock(void);
int32_t asInt(void) const;
float asFloat(void) const;
inline bool asBool(void) const { return asInt() == DATABLOCK_TRUE; }
String asString(void) const;
std::vector<int32_t> asIntArray(void) const;
std::vector<String> asStringArray(void) const;
String asLiteral(void) const;
Color asColor(void) const;
private:
inline DataBlock(bool __invalid) { if (__invalid) invalidate(); }
public:
eDataBlockType type;
String name;
String value;
};
class DataFile : public BaseObject
{
public:
inline DataFile(void) { invalidate(); }
inline DataFile(String filePath) { load(filePath); }
inline virtual ~DataFile(void) = default;
virtual void onDataBlockRead(String instr, DFD_LIST data, int32_t paramCount) = 0;
void load(String filePath);
void addLocal(String name, int32_t value);
void addLocal(String name, String value, bool literal = false);
const DataBlock getLocal(String name);
static void addGlobal(String name, int32_t value);
static void addGlobal(String name, String value, bool literal = false);
static const DataBlock getGlobal(String name);
protected:
void loadDefines(String data);
String replaceDefines(String data);
DataBlock parseParameter(String param);
protected:
String m_dataFilePath;
String m_rawContent;
bool m_hasAutoLoadInfo;
private:
DFD_LIST m_localDefs;
inline static DFD_LIST s_globalDefs;
};
}
#endif

84
src/ostd/Defines.hpp Executable file
View file

@ -0,0 +1,84 @@
#ifndef __DEFINES_HPP__
#define __DEFINES_HPP__
#if defined(_WIN32) || defined(_WIN64)
#define WINDOWS_OS
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT 0x0501
#else
#define LINUX_OS
#endif
//Basic constants
#if !defined(BUILD_NR)
#define BUILD_NR 0
#endif
#if !defined(MAJ_V)
#define MAJ_V 0
#endif
#if !defined(MIN_V)
#define MIN_V 0
#endif
#if !defined(VERSION_STR)
#define VERSION_STR "0.0.0"
#endif
#if !defined(NULL)
#define NULL 0
#endif
#define PI 3.1415926535898f
#define TWO_PI PI * 2.0f
#define HALF_PI PI / 2.0f
#define QUARTER_PI PI / 4.0f
#define DEG_TO_RAD(deg) (float)(deg * (PI / 180.0f))
#define RAD_TO_DEG(rad) (float)(rad * (180.0f / PI))
//Game Time constants
#define TM_R_SECONDS_FOR_G_MINUTE 1
#define TM_G_MINUTES_FOR_G_HOUR 60
#define TM_G_HOURS_FOR_G_DAY 24
#define TM_G_DAYS_FOR_G_LONG_MONTH 31
#define TM_G_DAYS_FOR_G_MEDIUM_MONTH 30
#define TM_G_DAYS_FOR_G_SHORT_MONTH 28
//Macro functions
#define ERROR_DATA() String(CPP_STR(__LINE__)), String(__FILE__)
#define STR_BOOL(b) (b ? "true" : "false")
#define INT_BOOL(i) (i == 0 ? false : true)
#define ZERO(n) (n > 0 ? n : 0)
#define FRAND() ((float)(rand() % 10000)) / 10000.0f
#define RANDOM(min, max) rand() % (max - min + 1) + min
#define LERP(n1, n2, f) (n2 - n1) * f + n1
#define CAP(n, max) (n > max ? max : n)
#define CAPD(n, min) (n < min ? min : n)
#define CAPB(n, min, max) (n < min ? min : (n > max ? max : n))
#define MAX(n1, n2) std::max(n1, n2)
#define MIN(n1, n2) std::min(n1, n2)
#define PROPORTION(w, x, y) ((x * w) / y)
#define CONVERT_1D_2D(i, width) IPoint(i % width, i / width)
#define CONVERT_2D_1D(x, y, width) (x + width * y)
#define PRINT(data) std::cout << data
#define PRINTLN(data) std::cout << data << "\n"
#define NEWLN() std::cout << "\n"
#define STDVEC_CONTAINS(vec, elem) (std::find(vec.begin(), vec.end(), elem) != vec.end())
//Memory management macros
#define new_sh(type) std::make_shared<type>
#define sh_ptr(type) std::shared_ptr<type>
#define new_un(type) std::make_unique<type>
#define un_ptr(type) std::unique_ptr<type>
#define OX_NO_ERROR 0x00000000
#define OX_WINDOW_ERR_MASK 0x00000000
#define OX_SHADER_ERR_MASK 0x00001000
#define OX_GLBUFFERS_ERR_MASK 0x00002000
#define OX_TEXTURE_ERR_MASK 0x00003000
#define OX_GFX_APPLICATION_2D_ERR_MASK 0x00004000
#define OX_BITMAPFONT_ERR_MASK 0x00005000
#define OX_RENDERER2D_ERR_MASK 0x00006000
#define OX_RENDERTARGET_ERR_MASK 0x00007000
#define OX_RENDERER2D_TEXT_ERR_MASK 0x00008000
#endif

58
src/ostd/Errors.cpp Executable file
View file

@ -0,0 +1,58 @@
#include "Errors.hpp"
#include "Logger.hpp"
namespace ostd
{
RuntimeError& RuntimeError::create(uint8_t group, uint64_t code, uint8_t level, const String &msg)
{
m_errGroup = group;
m_errCode = code;
m_message = msg;
m_errLevel = level;
setTypeName("ostd::RuntimeError");
validate();
return *this;
}
void RuntimeError::fire(const String& extraMessage, IOutputHandler* outputHandler, BaseObject& userData, int32_t _line_num, const String& _file_name)
{
if (isInvalid() || m_errGroup == 0x0 || m_errLevel == tErrorLevel::NoError || m_errCode == 0x0) return;
String errorMessage = m_message + "\n";
if (extraMessage != "")
errorMessage += extraMessage + "\n";
if (userData.isValid())
errorMessage += "USER_DATA:\n" + userData.toString() + "\n";
StringEditor msgEdit = "";
msgEdit.add(Utils::getHexStr(m_errGroup)).add("//");
msgEdit.add(Utils::getHexStr(m_errCode, true, 8)).add(" :: ");
if (_file_name != "")
{
msgEdit.add(_file_name).add(" ");
if (_line_num > 0)
msgEdit.add("[LINE: ").addi(_line_num).add("]\n");
else
msgEdit.add("\n");
}
msgEdit.add(errorMessage);
IOutputHandler* tmpOutHndl = nullptr;
if (outputHandler != nullptr)
{
tmpOutHndl = &Logger::getOutputHandler();
Logger::setOutputHandler(*outputHandler);
}
if (m_errLevel == tErrorLevel::Warning)
{
OX_WARN(msgEdit.str());
}
else if (m_errLevel == tErrorLevel::Error)
{
OX_ERROR(msgEdit.str());
}
else if (m_errLevel == tErrorLevel::Fatal)
{
OX_FATAL(msgEdit.str());
}
if (tmpOutHndl != nullptr)
Logger::setOutputHandler(*tmpOutHndl);
}
}

36
src/ostd/Errors.hpp Executable file
View file

@ -0,0 +1,36 @@
#ifndef __ERRORS_HPP__
#define __ERRORS_HPP__
#include <ostd/BaseObject.hpp>
#include <ostd/Utils.hpp>
#include <Types.hpp>
namespace ostd
{
struct tErrorLevel
{
inline static constexpr uint8_t NoError = 0x00;
inline static constexpr uint8_t Warning = 0x01;
inline static constexpr uint8_t Error = 0x02;
inline static constexpr uint8_t Fatal = 0x03;
};
class RuntimeError : public BaseObject
{
public:
inline RuntimeError(void) { invalidate(); }
inline RuntimeError(uint8_t group, uint64_t code, uint8_t level, const String& msg) { create(group, code, level, msg); }
RuntimeError& create(uint8_t group, uint64_t code, uint8_t level, const String& msg);
void fire(const String& extraMessage = "", IOutputHandler* outputHandler = nullptr, BaseObject& userData = BaseObject::InvalidRef(), int32_t _line_num = 0, const String& _file_name = "");
private:
uint8_t m_errGroup { 0x00 };
uint8_t m_errLevel { tErrorLevel::NoError };
uint64_t m_errCode { 0x0000000000000000 };
String m_message { "" };
};
}
#endif

47
src/ostd/File.cpp Executable file
View file

@ -0,0 +1,47 @@
#include "File.hpp"
#include "Utils.hpp"
#include <fstream>
#include <ios>
#include <iterator>
namespace ostd
{
TextFileBuffer& TextFileBuffer::open(const std::filesystem::path &filePath)
{
if (exists())
{
m_extension = "";
m_fullPath = "";
m_name = "";
m_fullName = "";
m_directoryPath = "";
m_directoryName = "";
m_buffer = "";
invalidate();
}
if (!std::filesystem::is_regular_file(filePath)) return *this;
std::ifstream file(filePath, std::ios::in | std::ios::binary);
if (!file.is_open()) return *this;
m_buffer = { std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>() };
m_extension = filePath.extension();
m_fullPath = filePath;
m_fullName = filePath.filename();
m_name = filePath.stem();
StringEditor pathEditor(m_fullPath);
if (pathEditor.contains('/'))
m_directoryPath = pathEditor.substr(0, pathEditor.lastIndexOf('/'));
pathEditor = m_directoryPath;
if (pathEditor.contains('/'))
m_directoryName = pathEditor.substr(pathEditor.lastIndexOf('/') + 1);
validate();
return *this;
}
std::vector<String> TextFileBuffer::getLines(const String& separator, bool trim_tokens, bool allow_white_space_only_tokens)
{
if (!exists()) return { };
auto st = StringEditor(m_buffer);
return st.tokenize(separator, trim_tokens, allow_white_space_only_tokens).getRawData();
}
}

42
src/ostd/File.hpp Executable file
View file

@ -0,0 +1,42 @@
#ifndef __FILE_HPP__
#define __FILE_HPP__
#include <ostd/BaseObject.hpp>
#include <ostd/Types.hpp>
#include <filesystem>
#include <vector>
namespace ostd
{
class TextFileBuffer : public BaseObject
{
public:
inline TextFileBuffer(void) { invalidate(); setTypeName("ostd::TextFileBuffer"); }
inline TextFileBuffer(const std::filesystem::path& filePath) { open(filePath); }
TextFileBuffer& open(const std::filesystem::path& filePath);
inline const String& ext(void) const { return m_extension; }
inline const String& fullPath(void) const { return m_fullPath; }
inline const String& dirPath(void) const { return m_directoryPath; }
inline const String& dir(void) const { return m_directoryName; }
inline const String& fullName(void) const { return m_fullName; }
inline const String& name(void) const { return m_name; }
inline const String& rawContent(void) { return m_buffer; }
std::vector<String> getLines(const String& separator = "\n", bool trim_tokens = true, bool allow_white_space_only_tokens = false);
inline bool exists(void) { return isValid(); }
private:
String m_extension { "" };
String m_fullPath { "" };
String m_name { "" };
String m_fullName { "" };
String m_directoryPath { "" };
String m_directoryName { "" };
String m_buffer { "" };
};
}
#endif

16
src/ostd/Geometry.cpp Executable file
View file

@ -0,0 +1,16 @@
#include "Geometry.hpp"
#include <iostream>
#include "Utils.hpp"
namespace ostd
{
String Vec2::toString(void) const
{
return StringEditor("{ ").addf(x).add(", ").addf(y).add(" }").str();
}
String Vec3::toString(void) const
{
return StringEditor("{ ").addf(x).add(", ").addf(y).add(", ").addf(z).add(" }").str();
}
} //namesoace ox

354
src/ostd/Geometry.hpp Executable file
View file

@ -0,0 +1,354 @@
#ifndef __GEOMETRY_HPP__
#define __GEOMETRY_HPP__
#include <cmath>
#include <algorithm>
#include <cstdint>
#include <ostd/Types.hpp>
namespace ostd
{
class IOutputHandler;
template<class T>
class Point
{
public:
T x;
T y;
public:
inline Point(void) : x(0), y(0) {}
inline Point(T xx, T yy) : x(xx), y(yy) {}
template <class T2> inline Point(Point<T2> copy)
{
x = (T2)(copy.x);
y = (T2)(copy.y);
}
};
typedef Point<float> FPoint;
typedef Point<double> DPoint;
typedef Point<uint32_t> UIPoint;
typedef Point<uint64_t> UI64Point;
typedef Point<float> UI16Point;
typedef Point<uint8_t> UI8Point;
typedef Point<int32_t> IPoint;
typedef Point<int64_t> I64Point;
typedef Point<int16_t> I16Point;
typedef Point<int8_t> I8Point;
struct Vec2
{
//======================== Data ========================
float x;
float y;
//======================================================
//==================== Construction ====================
inline Vec2(float xx = 0, float yy = 0) : x(xx), y(yy) { }
inline Vec2(const Vec2& v2) { set(v2); }
inline Vec2& set(const Vec2& v2) { x = v2.x; y = v2.y; return *this; }
inline Vec2& set(float xx, float yy) { x = xx; y = yy; return *this; }
//======================================================
//================== Static Functions ==================
inline static Vec2 fromAngle(float angle) { return Vec2(std::cos(angle), std::sin(angle)); }
inline static float angleBetween(const Vec2& v1, const Vec2& v2) { return std::acos(v1.dot(v2) / (v1.mag() * v2.mag())); }
//======================================================
//===================== Conversion =====================
inline Vec2 toIsometric(void) const { return Vec2(x - y, (x + y) / 2.0f); }
inline Vec2 toCartesian(void) const { return Vec2((2 * y + x) / 2.0f, (2 * y - x) / 2.0f); }
String toString(void) const;
//======================================================
//===================== Operations =====================
inline float mag(void) const { return std::sqrt((x * x) + (y * y)); }
inline Vec2 add(Vec2 v2) const { return { x + v2.x, y + v2.y }; }
inline Vec2 add(float x2, float y2) const { return { x + x2, y + y2 }; }
inline Vec2 sub(Vec2 v2) const { return { x - v2.x, y - v2.y }; }
inline Vec2 sub(float x2, float y2) const { return { x - x2, y - y2 }; }
inline Vec2 mul(float scalar) const { return { x * scalar, y * scalar }; }
inline Vec2 div(float scalar) const { return { x / scalar, y / scalar }; }
inline Vec2 normalize(void) const { float m = _zp(mag()); return { x / m, y / m }; }
inline float dist(Vec2 v2) const { return std::sqrt((float)((v2.x - x) * (v2.x - x)) + ((v2.y - y) * (v2.y - y))); }
inline float heading(void) const { return std::atan2(y, x); }
inline Vec2 rotate(float angle) const { return Vec2(*this).rotate(angle); }
inline float dot(const Vec2& v2) const { return (x * v2.x) + (y * v2.y); }
inline float cross(const Vec2& v2) const { return (x * v2.y) - (v2.x * y); }
//======================================================
//===================== Modifiers ======================
inline Vec2& addm(const Vec2& v2) { x += v2.x; y += v2.y; return *this; }
inline Vec2& addm(const float& x2, const float& y2) { x += x2; y += y2; return *this; }
inline Vec2& subm(const Vec2& v2) { x -= v2.x; y -= v2.y; return *this; }
inline Vec2& subm(const float& x2, const float& y2) { x -= x2; y -= y2; return *this; }
inline Vec2& mulm(const float& scalar) { x *= scalar; y *= scalar; return *this; }
inline Vec2& divm(const float& scalar) { x /= scalar; y /= scalar; return *this; }
inline Vec2& normalizem(void) { float m = _zp(mag()); x /= m; y /= m; return *this; }
inline Vec2& setMag(const float& mag) { return normalizem().mulm(mag); }
inline Vec2& setHeading(const float& angle) { float m = mag(); set(m * std::cos(angle), m * std::sin(angle)); return *this; }
inline Vec2& rotate(const float& angle) { return setHeading(heading() + angle); }
inline Vec2& limit(const float& max) { float msq = mag(); msq *= msq; if (msq > (max * max)) divm(std::sqrt(msq)).mulm(max); return *this; }
//======================================================
//===================== Operators ======================
inline bool operator==(const Vec2& op2 ) const { return (x == op2.x && y == op2.y); }
inline bool operator!=(const Vec2& op2 ) const { return (x != op2.x && y != op2.y); }
inline Vec2 operator+ (const Vec2& op2 ) const { return add(op2); }
inline Vec2 operator- (const Vec2& op2 ) const { return sub(op2); }
inline Vec2 operator+ (const float& op2) const { return add(op2, op2); }
inline Vec2 operator- (const float& op2) const { return sub(op2, op2); }
inline Vec2 operator* (const float& op2) const { return mul(op2); }
inline Vec2 operator/ (const float& op2) const { return div(op2); }
inline Vec2& operator= (const Vec2& val ) { return set(val); }
inline Vec2& operator= (const float& val) { return set(val, val); }
inline Vec2& operator+=(const Vec2& op2 ) { return addm(op2); }
inline Vec2& operator-=(const Vec2& op2 ) { return subm(op2); }
inline Vec2& operator+=(const float& op2) { return addm(op2, op2); }
inline Vec2& operator-=(const float& op2) { return subm(op2, op2); }
inline Vec2& operator*=(const float& op2) { return mulm(op2); }
inline Vec2& operator/=(const float& op2) { return divm(op2); }
friend std::ostream& operator<<(std::ostream& out, const Vec2& val);
//======================================================
private:
inline float _zp(float n1) const { return (n1 == 0 ? 1 : n1); }
};
inline std::ostream& operator<<(std::ostream& out, const Vec2& val)
{
out << val.toString();
return out;
}
struct Vec3
{
inline Vec3(float xx = 0, float yy = 0, float zz = 0)
{
x = xx;
y = yy;
z = zz;
}
inline Vec3(const Vec2& xy, float _z = 0.0f) { x = xy.x; y = xy.y; z = _z; }
inline Vec2 xy(void) const { return Vec2(x, y); }
inline Vec2 yz(void) const { return Vec2(y, z); }
inline Vec2 zx(void) const { return Vec2(z, x); }
String toString(void) const;
inline bool operator==(const Vec3& op2 ) const { return (x == op2.x && y == op2.y && op2.z == z); }
inline bool operator!=(const Vec3& op2 ) const { return (x != op2.x && y != op2.y && op2.z != z); }
inline Vec3& operator+=(const Vec3& op2 ) { x += op2.x; y += op2.y; z += op2.z; return *this; }
friend std::ostream& operator<<(std::ostream& out, const Vec2& val);
float x;
float y;
float z;
};
inline std::ostream& operator<<(std::ostream& out, const Vec3& val)
{
out << val.toString();
return out;
}
struct Vec4
{
inline Vec4(float xx = 0, float yy = 0, float zz = 0, float ww = 0)
{
x = xx;
y = yy;
z = zz;
w = ww;
}
inline Vec4(const Vec2& xy, float _z = 0.0f, float _w = 0.0f) { x = xy.x; y = xy.y; z = _z; w = _w; }
inline Vec4(const Vec3& xyz, float _w = 0.0f) { x = xyz.x; y = xyz.y; z = xyz.z; w = _w; }
inline Vec4(const Vec2& xy, const Vec2& zw) { x = xy.x; y = xy.y; z = zw.x; w = zw.y; }
inline Vec2 xy(void) const { return Vec2(x, y); }
inline Vec2 yz(void) const { return Vec2(y, z); }
inline Vec2 zw(void) const { return Vec2(z, w); }
inline Vec2 wx(void) const { return Vec2(w, x); }
float x;
float y;
float z;
float w;
};
struct Triangle
{
Vec2 vA;
Vec2 vB;
Vec2 vC;
inline Triangle(void) {}
inline Triangle(Vec2 a, Vec2 b, Vec2 c)
{
vA = a;
vB = b;
vC = c;
}
inline Triangle(float ax, float ay, float bx, float by, float cx, float cy)
{
vA.x = ax;
vA.y = ay;
vB.x = bx;
vB.y = by;
vC.x = cx;
vC.y = cy;
}
bool contains(Vec2 p)
{
float d1, d2, d3;
bool has_neg, has_pos;
d1 = __sign(p, vA, vB);
d2 = __sign(p, vB, vC);
d3 = __sign(p, vC, vA);
has_neg = (d1 < 0) || (d2 < 0) || (d3 < 0);
has_pos = (d1 > 0) || (d2 > 0) || (d3 > 0);
return !(has_neg && has_pos);
}
private:
inline float __sign(Vec2 p1, Vec2 p2, Vec2 p3)
{
return (p1.x - p3.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p3.y);
}
};
class Rectangle
{
public:
inline Rectangle(void) : x(0), y(0), w(0), h(0) {}
inline Rectangle(float xx, float yy, float ww, float hh) : x(xx), y(yy), w(ww), h(hh) {}
inline Rectangle(float xw, float yh, bool position = true) { if (position) { x = xw; y = yh; } else { w = xw; h = yh; } }
inline Rectangle(float xx, float yy, Vec2 size) { x = xx; y = yy; w = size.x; h = size.y; }
inline Rectangle(Vec2 position, float ww, float hh) { x = position.x; y = position.y; w = ww; h = hh; }
inline Rectangle(Vec2 position, Vec2 size) { x = position.x; y = position.y; w = size.x; h = size.y; }
virtual ~Rectangle(void) = default;
inline virtual float getx(void) const { return x; }
inline virtual float gety(void) const { return y; }
inline virtual float getw(void) const { return w; }
inline virtual float geth(void) const { return h; }
inline virtual float getCenterX(void) const { return getx() + getw() / 2; }
inline virtual float getCenterY(void) const { return gety() + geth() / 2; }
inline virtual void setx(float xx) { x = xx; }
inline virtual void sety(float yy) { y = yy; }
inline virtual void setw(float ww) { w = ww; }
inline virtual void seth(float hh) { h = hh; }
inline virtual Vec2 getPosition(void) const { return Vec2(getx(), gety()); }
inline virtual Vec2 getSize(void) const { return Vec2(getw(), geth()); }
inline virtual Vec2 getCenter(void) const { return Vec2(getx() + getw() / 2, gety() + geth() / 2); }
inline virtual void setPosition(Vec2 pos) { setx(pos.x); sety(pos.y); }
inline virtual void setPosition(float xx, float yy) { setx(xx); sety(yy); }
inline virtual void setSize(Vec2 size) { setw(size.x); seth(size.y); }
inline virtual void setSize(float ww, float hh) { setw(ww); seth(hh); }
inline virtual void setBounds(float xx, float yy, float ww, float hh) { setx(xx); sety(yy); setw(ww); seth(hh); }
inline virtual float addx(float xx) { setx(getx() + xx); return getx(); }
inline virtual float addy(float yy) { sety(gety() + yy); return gety(); }
inline virtual Vec2 addPos(float xx, float yy) { return Vec2(addx(xx), addy(yy)); }
inline virtual Vec2 addPos(Vec2 pos) { return addPos(pos.x, pos.y); }
inline virtual float addw(float ww) { setw(getw() + ww); return getw(); }
inline virtual float addh(float hh) { seth(geth() + hh); return geth(); }
inline virtual Vec2 addSize(float ww, float hh) { return Vec2(addw(ww), addh(hh)); }
inline virtual Vec2 addSize(Vec2 size) { return addPos(size.x, size.y); }
inline virtual float subx(float xx) { setx(getx() - xx); return getx(); }
inline virtual float suby(float yy) { sety(gety() - yy); return gety(); }
inline virtual Vec2 subPos(float xx, float yy) { return Vec2(subx(xx), suby(yy)); }
inline virtual Vec2 subPos(Vec2 pos) { return subPos(pos.x, pos.y); }
inline virtual float subw(float ww) { setw(getw() - ww); return getw(); }
inline virtual float subh(float hh) { seth(geth() - hh); return geth(); }
inline virtual Vec2 subSize(float ww, float hh) { return Vec2(subw(ww), subh(hh)); }
inline virtual Vec2 subSize(Vec2 size) { return subPos(size.x, size.y); }
inline virtual float mulx(float xx) { setx(getx() * xx); return getx(); }
inline virtual float muly(float yy) { sety(gety() * yy); return gety(); }
inline virtual Vec2 mulPos(float xx, float yy) { return Vec2(mulx(xx), muly(yy)); }
inline virtual Vec2 mulPos(Vec2 pos) { return mulPos(pos.x, pos.y); }
inline virtual float mulw(float ww) { setw(getw() * ww); return getw(); }
inline virtual float mulh(float hh) { seth(geth() * hh); return geth(); }
inline virtual Vec2 mulSize(float ww, float hh) { return Vec2(mulw(ww), mulh(hh)); }
inline virtual Vec2 mulSize(Vec2 size) { return mulPos(size.x, size.y); }
inline virtual float divx(float xx) { setx(getx() / xx); return getx(); }
inline virtual float divy(float yy) { sety(gety() / yy); return gety(); }
inline virtual Vec2 divPos(float xx, float yy) { return Vec2(divx(xx), divy(yy)); }
inline virtual Vec2 divPos(Vec2 pos) { return divPos(pos.x, pos.y); }
inline virtual float divw(float ww) { setw(getw() / ww); return getw(); }
inline virtual float divh(float hh) { seth(geth() / hh); return geth(); }
inline virtual Vec2 divSize(float ww, float hh) { return Vec2(divw(ww), divh(hh)); }
inline virtual Vec2 divSize(Vec2 size) { return divPos(size.x, size.y); }
inline virtual Vec2 topLeft(void) const { return getPosition(); }
inline virtual Vec2 topRight(void) const { return Vec2(getx() + getw(), gety()); }
inline virtual Vec2 bottomLeft(void) const { return Vec2(getx(), gety() + geth()); }
inline virtual Vec2 bottomRight(void) const { return Vec2(getx() + getw(), gety() + geth()); }
inline virtual bool intersects(Rectangle rect, bool includeBounds = true) const
{
if (includeBounds)
{
if (x + w <= rect.x || x >= rect.x + rect.w)
return false;
if (y + h <= rect.y || y >= rect.y + rect.h)
return false;
}
else
{
if (x + w < rect.x || x > rect.x + rect.w)
return false;
if (y + h < rect.y || y > rect.y + rect.h)
return false;
}
return true;
}
inline virtual Rectangle getIntersection(Rectangle rect, bool includeBounds = true) const
{
if (!intersects(rect, includeBounds))
return Rectangle();
float leftX = std::max(x, rect.x);
float rightX = std::min(x + w, rect.x + rect.w);
float topY = std::max(y, rect.y);
float bottomY = std::min(y + h, rect.y + rect.h);
return { leftX, topY, rightX - leftX, bottomY - topY };
}
inline virtual bool contains(Vec2 p, bool includeBounds = false) const
{
if (includeBounds)
return p.x >= x && p.y >= y & p.x <= x + w && p.y <= y + h;
else
return p.x > x && p.y > y & p.x < x + w && p.y < y + h;
}
inline virtual bool contains(float xx, float yy, bool includeBounds = false) const { return contains({ xx, yy }); }
inline virtual float getDistance(Vec2 p) const { return sqrt(fabs((p.x - getx()) * (p.x - getx()) + (p.y - gety()) * (p.y - gety()))); }
public:
float x;
float y;
float w;
float h;
};
} // namespace ox
#endif

58
src/ostd/Logger.cpp Executable file
View file

@ -0,0 +1,58 @@
#include "Logger.hpp"
#include <cstdarg>
#include <cstring>
#include <iostream>
#include "TermColor.hpp"
#include "Utils.hpp"
namespace ostd
{
IOutputHandler* Logger::m_out = new ConsoleOutputHandler;
void Logger::__log_output(uint8_t log_level, String message, ...)
{
String level_str[6] = { "[ FATAL ]: ", "[ ERROR ]: ", "[ WARNING ]: ", "[ INFO ]: ", "[ DEBUG ]: ", "[ TRACE ]: " };
char buffer[4096];
std::memset(buffer, 0, sizeof(buffer));
__builtin_va_list arg_ptr;
va_start(arg_ptr, message);
vsnprintf(buffer, sizeof(buffer), message.c_str(), arg_ptr);
va_end(arg_ptr);
switch (log_level)
{
case tLogLevel::Fatal:
m_out->col("red");
break;
case tLogLevel::Error:
m_out->col("b-red");
break;
case tLogLevel::Warning:
m_out->col("b-magenta");
break;
case tLogLevel::Info:
m_out->col("cyan");
break;
case tLogLevel::Debug:
m_out->col("b-blue");
break;
case tLogLevel::Trace:
m_out->col("green");
break;
}
m_out->p(level_str[log_level]).p(buffer).reset().nl();
}
void Logger::destroy(void)
{
delete m_out;
}
void Logger::setOutputHandler(IOutputHandler& __destination)
{
m_out = &__destination; //TODO: Destroy old (only if still default)
}
} //namesoace ox

65
src/ostd/Logger.hpp Executable file
View file

@ -0,0 +1,65 @@
#ifndef __LOGGER_HPP__
#define __LOGGER_HPP__
#include <ostd/Types.hpp>
namespace ostd
{
struct tLogLevel
{
inline static const uint8_t Fatal = 0;
inline static const uint8_t Error = 1;
inline static const uint8_t Warning = 2;
inline static const uint8_t Info = 3;
inline static const uint8_t Debug = 4;
inline static const uint8_t Trace = 5;
};
class IOutputHandler;
class Logger
{
public:
static void __log_output(uint8_t log_level, String message, ...);
static void setOutputHandler(IOutputHandler& __destination);
static void destroy(void);
static inline IOutputHandler& getOutputHandler(void) { return *m_out; }
private:
static IOutputHandler* m_out;
};
} //namesoace ox
#define OX_LOG_WARN_ENABLED 1
#define OX_LOG_INFO_ENABLED 1
#define OX_LOG_DEBUG_ENABLED 1
#define OX_LOG_TRACE_ENABLED 1
#if OX_RELEASE == 1
#define OX_LOG_DEBUG_ENABLED 0
#define OX_LOG_TRACE_ENABLED 0
#endif
#define OX_FATAL(message, ...) ostd::Logger::__log_output(ostd::tLogLevel::Fatal, message, ##__VA_ARGS__)
#define OX_ERROR(message, ...) ostd::Logger::__log_output(ostd::tLogLevel::Error, message, ##__VA_ARGS__)
#if OX_LOG_WARN_ENABLED == 1
#define OX_WARN(message, ...) ostd::Logger::__log_output(ostd::tLogLevel::Warning, message, ##__VA_ARGS__)
#else
#define OX_WARN(message, ...)
#endif
#if OX_LOG_INFO_ENABLED == 1
#define OX_INFO(message, ...) ostd::Logger::__log_output(ostd::tLogLevel::Info, message, ##__VA_ARGS__)
#else
#define OX_INFO(message, ...)
#endif
#if OX_LOG_DEBUG_ENABLED == 1
#define OX_DEBUG(message, ...) ostd::Logger::__log_output(ostd::tLogLevel::Debug, message, ##__VA_ARGS__)
#else
#define OX_DEBUG(message, ...)
#endif
#if OX_LOG_TRACE_ENABLED == 1
#define OX_TRACE(message, ...) ostd::Logger::__log_output(ostd::tLogLevel::Trace, message, ##__VA_ARGS__)
#else
#define OX_TRACE(message, ...)
#endif
#endif

99
src/ostd/Logic.cpp Executable file
View file

@ -0,0 +1,99 @@
#include "Logic.hpp"
#include "Utils.hpp"
#include <bits/stdc++.h>
namespace ostd
{
bool LogicEvaluator::eval(String exp)
{
StringEditor se(exp);
se = se.replaceAll("true", "1");
se = se.replaceAll("false", "0");
se = se.replaceAll("and", "&");
se = se.replaceAll("or", "+");
se = se.replaceAll("xor", "^");
se = se.replaceAll("nand", "%");
se = se.replaceAll("nor", "*");
se = se.replaceAll("xnor", ">");
se = se.replaceAll("not", "!");
se = se.replaceAll(" ", "");
se = se.replaceAll("!1", "0");
se = se.replaceAll("!0", "1");
se = se.trim();
exp = se.str();
std::stack<bool> values;
std::stack<eLogicOp> ops;
char c = 0;
for (unsigned int i = 0; i < exp.length(); i++)
{
c = exp[i];
if (c == ' ' || c == '#') continue;
else if (c == '1' || c == '0') values.push(c == '1');
else if (c == ')')
{
while(!ops.empty() && ops.top() != eLogicOp::O_PARENTH)
{
bool val2 = values.top();
values.pop();
bool val1 = values.top();
values.pop();
eLogicOp op = ops.top();
ops.pop();
values.push(applyOp(val1, val2, op));
}
if(!ops.empty()) ops.pop();
if (!ops.empty())
{
if (ops.top() == eLogicOp::NOT)
{
ops.pop();
bool tmp = values.top();
values.pop();
values.push(!tmp);
}
}
}
else ops.push(parseOp(c));
}
while(!ops.empty())
{
bool val2 = values.top();
values.pop();
bool val1 = values.top();
values.pop();
eLogicOp op = ops.top();
ops.pop();
values.push(applyOp(val1, val2, op));
}
return values.top();
}
bool LogicEvaluator::applyOp(bool a, bool b, eLogicOp op)
{
switch(op)
{
case eLogicOp::AND: return (a && b);
case eLogicOp::OR: return (a || b);
case eLogicOp::NAND: return !(a && b);
case eLogicOp::NOR: return !(a || b);
case eLogicOp::XOR: return (a != b);
case eLogicOp::XNOR: return !(a != b);
default: return false;
}
}
eLogicOp LogicEvaluator::parseOp(char op)
{
if (op == '&') return eLogicOp::AND;
if (op == '+') return eLogicOp::OR;
if (op == '^') return eLogicOp::XOR;
if (op == '%') return eLogicOp::NAND;
if (op == '*') return eLogicOp::NOR;
if (op == '>') return eLogicOp::XNOR;
if (op == '!') return eLogicOp::NOT;
if (op == '(') return eLogicOp::O_PARENTH;
if (op == ')') return eLogicOp::C_PARENTH;
return eLogicOp::NONE;
}
}

Some files were not shown because too many files have changed in this diff Show more