Compare commits
10 Commits
15dc62a36c
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| fc45c3f91e | |||
| 6a0e0d0685 | |||
| e02e92db10 | |||
| b3b7688f76 | |||
| 0ceea230cf | |||
| 2dd5f3a648 | |||
| cf916951f0 | |||
| 5d78fd672e | |||
| a5856e3816 | |||
| 54476ffae4 |
10
.gitmodules
vendored
10
.gitmodules
vendored
@@ -16,6 +16,16 @@
|
||||
[submodule "_ThirdParty/imgui"]
|
||||
path = _ThirdParty/imgui
|
||||
url = https://github.com/ocornut/imgui.git
|
||||
branch = docking
|
||||
[submodule "_ThirdParty/fmt"]
|
||||
path = _ThirdParty/fmt
|
||||
url = https://github.com/fmtlib/fmt.git
|
||||
[submodule "_ThirdParty/json"]
|
||||
path = _ThirdParty/json
|
||||
url = https://github.com/nlohmann/json.git
|
||||
[submodule "_ThirdParty/nfd"]
|
||||
path = _ThirdParty/nfd
|
||||
url = https://github.com/btzy/nativefiledialog-extended.git
|
||||
[submodule "_ThirdParty/uuid"]
|
||||
path = _ThirdParty/uuid
|
||||
url = https://github.com/mariusbancila/stduuid.git
|
||||
|
||||
@@ -12,35 +12,48 @@ set (GLFW_BUILD_TESTS OFF)
|
||||
set (GLFW_BUILD_DOCS OFF)
|
||||
add_subdirectory(_ThirdParty/glfw)
|
||||
|
||||
add_subdirectory(_ThirdParty/spdlog)
|
||||
|
||||
set (ASSIMP_INSTALL OFF)
|
||||
add_subdirectory(_ThirdParty/assimp)
|
||||
|
||||
add_subdirectory(_ThirdParty/glm)
|
||||
|
||||
add_subdirectory(_ThirdParty/entt)
|
||||
|
||||
add_subdirectory(_ThirdParty/fmt)
|
||||
|
||||
include_directories(_ThirdParty/imgui/lib)
|
||||
file(GLOB_RECURSE IMGUI_SOURCES _ThirdParty/imgui/lib/*.cpp)
|
||||
include_directories(src/imgui)
|
||||
file(GLOB_RECURSE IMGUI_SOURCES src/imgui/*.cpp)
|
||||
|
||||
file(GLOB_RECURSE SOURCES ${CMAKE_SOURCE_DIR}/src/*.cpp)
|
||||
file(GLOB_RECURSE HEADERS ${CMAKE_SOURCE_DIR}/src/*.h)
|
||||
|
||||
add_subdirectory(_ThirdParty/entt)
|
||||
add_subdirectory(_ThirdParty/fmt)
|
||||
add_subdirectory(_ThirdParty/spdlog)
|
||||
set(JSON_BuildTests OFF CACHE INTERNAL "")
|
||||
add_subdirectory(_ThirdParty/json)
|
||||
add_subdirectory(_ThirdParty/uuid)
|
||||
add_subdirectory(_ThirdParty/nfd)
|
||||
|
||||
set (ASSIMP_INSTALL OFF)
|
||||
add_subdirectory(_ThirdParty/assimp)
|
||||
if(UNIX)
|
||||
find_path(UNZIP_PATH unzip.h PATHS
|
||||
/usr/include
|
||||
/usr/local/include)
|
||||
|
||||
if(NOT UNZIP_PATH)
|
||||
include_directories(/usr/include/minizip)
|
||||
endif()
|
||||
|
||||
target_compile_options(assimp PRIVATE
|
||||
-Wno-unused-but-set-variable
|
||||
)
|
||||
endif()
|
||||
|
||||
add_executable(${PROJECT_NAME}
|
||||
${IMGUI_SOURCES}
|
||||
${GLAD_SOURCE_DIR}/gl.c
|
||||
${SOURCES}
|
||||
${HEADERS})
|
||||
${HEADERS}
|
||||
src/ProjectManifestFile.cpp
|
||||
src/ProjectManifestFile.h)
|
||||
|
||||
add_custom_target(copy_resources
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/resources"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/resources"
|
||||
COMMENT "Copying resources..."
|
||||
)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} glfw spdlog assimp glm EnTT fmt)
|
||||
target_link_libraries(${PROJECT_NAME} glfw spdlog assimp glm EnTT fmt nfd uuid)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE ${ASSIMP_INCLUDE_INSTALL_DIR})
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE _ThirdParty/json/single_include)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE _ThirdParty/uuid/include)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE src)
|
||||
|
||||
@@ -1 +1,5 @@
|
||||
# b_engine
|
||||
# b_engine
|
||||
|
||||
### if on linux and using wayland:
|
||||
```cd _ThirdParty/nfd```
|
||||
```git submodule update --init```
|
||||
2
_ThirdParty/imgui
vendored
2
_ThirdParty/imgui
vendored
Submodule _ThirdParty/imgui updated: 80987f1c40...c51f1a6e47
1
_ThirdParty/json
vendored
Submodule
1
_ThirdParty/json
vendored
Submodule
Submodule _ThirdParty/json added at 630beaeb05
1
_ThirdParty/nfd
vendored
Submodule
1
_ThirdParty/nfd
vendored
Submodule
Submodule _ThirdParty/nfd added at c9cc7baf28
1
_ThirdParty/uuid
vendored
Submodule
1
_ThirdParty/uuid
vendored
Submodule
Submodule _ThirdParty/uuid added at 3afe7193fa
16
copy_imgui.sh
Executable file
16
copy_imgui.sh
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
IMGUI_SRC="./src/imgui"
|
||||
|
||||
mkdir -p $IMGUI_SRC
|
||||
|
||||
# copy the headers
|
||||
cp _ThirdParty/imgui/*.h $IMGUI_SRC
|
||||
cp _ThirdParty/imgui/backends/imgui_impl_glfw.h $IMGUI_SRC
|
||||
cp _ThirdParty/imgui/backends/imgui_impl_opengl3.h $IMGUI_SRC
|
||||
cp _ThirdParty/imgui/backends/imgui_impl_opengl3_loader.h $IMGUI_SRC
|
||||
|
||||
# copy the source files
|
||||
cp _ThirdParty/imgui/*.cpp $IMGUI_SRC
|
||||
cp _ThirdParty/imgui/backends/imgui_impl_glfw.cpp $IMGUI_SRC
|
||||
cp _ThirdParty/imgui/backends/imgui_impl_opengl3.cpp $IMGUI_SRC
|
||||
5
default_assets/shaders/phong.shader
Normal file
5
default_assets/shaders/phong.shader
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "phong",
|
||||
"vertex": "phong.vert",
|
||||
"fragment": "phong.frag"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 8.3 MiB After Width: | Height: | Size: 8.3 MiB |
@@ -1,12 +0,0 @@
|
||||
# Blender 3.6.0 MTL File: 'None'
|
||||
# www.blender.org
|
||||
|
||||
newmtl 01_-_Default.001
|
||||
Ns 10.000005
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.450000
|
||||
d 1.000000
|
||||
illum 1
|
||||
map_Kd Corvette_C4_Base_Color.png
|
||||
@@ -1,46 +0,0 @@
|
||||
# Blender v2.76 (sub 0) OBJ File: ''
|
||||
# www.blender.org
|
||||
mtllib cube.mtl
|
||||
o Cube
|
||||
v 1.000000 -1.000000 -1.000000
|
||||
v 1.000000 -1.000000 1.000000
|
||||
v -1.000000 -1.000000 1.000000
|
||||
v -1.000000 -1.000000 -1.000000
|
||||
v 1.000000 1.000000 -0.999999
|
||||
v 0.999999 1.000000 1.000001
|
||||
v -1.000000 1.000000 1.000000
|
||||
v -1.000000 1.000000 -1.000000
|
||||
vt 1.000000 0.333333
|
||||
vt 1.000000 0.666667
|
||||
vt 0.666667 0.666667
|
||||
vt 0.666667 0.333333
|
||||
vt 0.666667 0.000000
|
||||
vt 0.000000 0.333333
|
||||
vt 0.000000 0.000000
|
||||
vt 0.333333 0.000000
|
||||
vt 0.333333 1.000000
|
||||
vt 0.000000 1.000000
|
||||
vt 0.000000 0.666667
|
||||
vt 0.333333 0.333333
|
||||
vt 0.333333 0.666667
|
||||
vt 1.000000 0.000000
|
||||
vn 0.000000 -1.000000 0.000000
|
||||
vn 0.000000 1.000000 0.000000
|
||||
vn 1.000000 0.000000 0.000000
|
||||
vn -0.000000 0.000000 1.000000
|
||||
vn -1.000000 -0.000000 -0.000000
|
||||
vn 0.000000 0.000000 -1.000000
|
||||
usemtl Material
|
||||
s off
|
||||
f 2/1/1 3/2/1 4/3/1
|
||||
f 8/1/2 7/4/2 6/5/2
|
||||
f 5/6/3 6/7/3 2/8/3
|
||||
f 6/8/4 7/5/4 3/4/4
|
||||
f 3/9/5 7/10/5 8/11/5
|
||||
f 1/12/6 4/13/6 8/11/6
|
||||
f 1/4/1 2/1/1 4/3/1
|
||||
f 5/14/2 8/1/2 6/5/2
|
||||
f 1/12/3 5/6/3 2/8/3
|
||||
f 2/12/4 6/8/4 3/4/4
|
||||
f 4/13/5 3/9/5 8/11/5
|
||||
f 5/6/6 1/12/6 8/11/6
|
||||
73398
resources/male.obj
73398
resources/male.obj
File diff suppressed because it is too large
Load Diff
21
src/AssetRecord.h
Normal file
21
src/AssetRecord.h
Normal file
@@ -0,0 +1,21 @@
|
||||
//
|
||||
// Created by slinky on 5/14/26.
|
||||
//
|
||||
|
||||
#ifndef B_ENGINE_ASSETRECORD_H
|
||||
#define B_ENGINE_ASSETRECORD_H
|
||||
|
||||
#include <string>
|
||||
#include "uuid.h"
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
|
||||
struct AssetRecord {
|
||||
uuids::uuid uuid;
|
||||
std::string sourcePath;
|
||||
std::string cachePath;
|
||||
AssetType assetType;
|
||||
};
|
||||
|
||||
#endif //B_ENGINE_ASSETRECORD_H
|
||||
207
src/AssetRegistry.cpp
Normal file
207
src/AssetRegistry.cpp
Normal file
@@ -0,0 +1,207 @@
|
||||
//
|
||||
// Created by slinky on 5/14/26.
|
||||
//
|
||||
|
||||
#include "AssetRegistry.h"
|
||||
#include "AssetRecord.h"
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "MeshManager.h"
|
||||
#include "ModelImporter.h"
|
||||
#include "TextureManager.h"
|
||||
#include "uuid.h"
|
||||
#include "nlohmann/json.hpp"
|
||||
#include "spdlog/spdlog.h"
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
std::unordered_map<uuids::uuid, std::unique_ptr<AssetRecord>> AssetRegistry::_registry;
|
||||
|
||||
const std::unordered_set<std::string> TextureExtensions = {
|
||||
".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp", ".tiff"
|
||||
};
|
||||
|
||||
const std::unordered_set<std::string> ModelExtensions = {
|
||||
".obj", ".fbx", ".gltf", ".glb"
|
||||
};
|
||||
|
||||
const std::unordered_set<std::string> ShaderExtensions = {
|
||||
".vert", ".frag", ".glsl"
|
||||
};
|
||||
|
||||
AssetType check_asset_type(const Path& path) {
|
||||
if (!path.has_extension()) {
|
||||
return AssetType::UNKNOWN;
|
||||
}
|
||||
|
||||
if (fs::is_directory(path)) {
|
||||
return AssetType::DIRECTORY;
|
||||
}
|
||||
|
||||
if (TextureExtensions.contains(path.extension().string())) {
|
||||
return AssetType::TEXTURE;
|
||||
}
|
||||
|
||||
if (ModelExtensions.contains(path.extension().string())) {
|
||||
return AssetType::MODEL;
|
||||
}
|
||||
|
||||
if (ShaderExtensions.contains(path.extension().string())) {
|
||||
return AssetType::SHADER;
|
||||
}
|
||||
|
||||
return AssetType::UNKNOWN;
|
||||
}
|
||||
|
||||
uuids::uuid generate_uuid() {
|
||||
thread_local auto gen = [] {
|
||||
std::random_device rd;
|
||||
|
||||
auto seed_data =
|
||||
std::array<int, std::mt19937::state_size>{};
|
||||
|
||||
std::generate(seed_data.begin(),
|
||||
seed_data.end(),
|
||||
std::ref(rd));
|
||||
|
||||
std::seed_seq seq(seed_data.begin(), seed_data.end());
|
||||
|
||||
std::mt19937 engine(seq);
|
||||
|
||||
return uuids::uuid_random_generator{engine};
|
||||
}();
|
||||
|
||||
return gen();
|
||||
}
|
||||
|
||||
void AssetRegistry::read_directory(const Path& path) {
|
||||
fs::recursive_directory_iterator directory{path};
|
||||
std::vector<fs::directory_entry> entries;
|
||||
|
||||
for (const auto& entry : directory) {
|
||||
if (entry.exists()) {
|
||||
entries.push_back(entry);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& entry : entries) {
|
||||
if (entry.path().extension() == ".meta") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!generate_meta_file(entry.path())) {
|
||||
spdlog::error("Failed to generate meta file for {}", entry.path().string());
|
||||
continue;
|
||||
}
|
||||
|
||||
std::optional<AssetRecord> record = read_meta_file(entry.path());
|
||||
if (!record) {
|
||||
continue;
|
||||
}
|
||||
|
||||
_registry[record->uuid] = std::make_unique<AssetRecord>(*record);
|
||||
AssetRecord* asset = _registry[record->uuid].get();
|
||||
|
||||
load_asset(asset);
|
||||
|
||||
if (entry.is_directory()) {
|
||||
read_directory(entry.path());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AssetRegistry::does_meta_exist(const Path& path) {
|
||||
Path meta = path;
|
||||
meta += ".meta";
|
||||
return fs::exists(meta);
|
||||
}
|
||||
|
||||
std::optional<AssetRecord> AssetRegistry::read_meta_file(const Path &path) {
|
||||
Path meta = path;
|
||||
meta += ".meta";
|
||||
|
||||
if (!fs::exists(meta) && !generate_meta_file(path)) {
|
||||
return std::optional<AssetRecord>{};
|
||||
}
|
||||
|
||||
try {
|
||||
AssetRecord record;
|
||||
std::stringstream ss;
|
||||
std::ifstream file {meta};
|
||||
ss << file.rdbuf();
|
||||
file.close();
|
||||
|
||||
std::string metaContent = ss.str();
|
||||
json metaJson = json::parse(metaContent);
|
||||
|
||||
auto uuidString = metaJson["uuid"].get<std::string>();
|
||||
std::optional<uuids::uuid> uuid = uuids::uuid::from_string(uuidString);
|
||||
if (!uuid)
|
||||
{
|
||||
return std::optional<AssetRecord>{};
|
||||
}
|
||||
|
||||
record.uuid = *uuid;
|
||||
record.sourcePath = metaJson["sourcePath"].get<std::string>();
|
||||
record.assetType = static_cast<AssetType>(metaJson["assetType"].get<int>());
|
||||
|
||||
return std::optional{record};
|
||||
} catch (const std::exception& e) {
|
||||
spdlog::error("Failed to read meta file: {}", e.what());
|
||||
return std::optional<AssetRecord>{};
|
||||
}
|
||||
}
|
||||
|
||||
bool AssetRegistry::generate_meta_file(const Path& path) {
|
||||
Path meta = path;
|
||||
meta += ".meta";
|
||||
|
||||
if (fs::exists(meta)) return true;
|
||||
|
||||
try {
|
||||
nlohmann::json j;
|
||||
j["uuid"] = uuids::to_string(generate_uuid());
|
||||
j["sourcePath"] = path.string();
|
||||
j["assetType"] = check_asset_type(path);
|
||||
|
||||
std::ofstream file {meta};
|
||||
std::stringstream ss;
|
||||
ss << j.dump();
|
||||
file << ss.str();
|
||||
file.close();
|
||||
} catch (const std::exception& e) {
|
||||
spdlog::error("File exception while generating meta file: {}", e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AssetRegistry::load_asset(const AssetRecord* asset) {
|
||||
switch (asset->assetType) {
|
||||
case AssetType::SHADER:
|
||||
return;
|
||||
case AssetType::TEXTURE: {
|
||||
ResourceHandle handle;
|
||||
handle.assetUUID = asset->uuid;
|
||||
TextureManager::textures[handle] = TextureManager::load_from_file(asset->sourcePath);
|
||||
return;
|
||||
}
|
||||
case AssetType::MODEL: {
|
||||
std::vector<Mesh> meshes = ModelImporter::load_from_file(asset->sourcePath);
|
||||
for (int i = 0; i < meshes.size(); i++) {
|
||||
ResourceHandle meshHandle;
|
||||
meshHandle.assetUUID = asset->uuid;
|
||||
meshHandle.localId = i + 1;
|
||||
MeshManager::meshes[meshHandle] = std::make_unique<Mesh>(meshes[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
case AssetType::DIRECTORY:
|
||||
case AssetType::UNKNOWN:
|
||||
break;
|
||||
}
|
||||
}
|
||||
38
src/AssetRegistry.h
Normal file
38
src/AssetRegistry.h
Normal file
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// Created by slinky on 5/14/26.
|
||||
//
|
||||
|
||||
#ifndef B_ENGINE_ASSETREGISTRY_H
|
||||
#define B_ENGINE_ASSETREGISTRY_H
|
||||
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <string_view>
|
||||
#include <filesystem>
|
||||
|
||||
#include "AssetRecord.h"
|
||||
#include "uuid.h"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
using Directory = fs::recursive_directory_iterator;
|
||||
using Path = fs::path;
|
||||
|
||||
class AssetRegistry {
|
||||
public:
|
||||
static void read_directory(const Path& path);
|
||||
|
||||
static std::vector<AssetRecord*> get_records();
|
||||
static AssetRecord* get_record(uuids::uuid uuid);
|
||||
private:
|
||||
static std::unordered_map<uuids::uuid, std::unique_ptr<AssetRecord>> _registry;
|
||||
|
||||
static bool does_meta_exist(const Path& path);
|
||||
static std::optional<AssetRecord> read_meta_file(const Path& path);
|
||||
static bool generate_meta_file(const Path& path);
|
||||
static void load_asset(const AssetRecord* asset);
|
||||
};
|
||||
|
||||
|
||||
#endif //B_ENGINE_ASSETREGISTRY_H
|
||||
93
src/Camera.cpp
Normal file
93
src/Camera.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
//
|
||||
// Created by slinky on 5/3/26.
|
||||
//
|
||||
|
||||
#include "Camera.h"
|
||||
|
||||
#include "glm/ext/matrix_transform.hpp"
|
||||
#include "glm/ext/matrix_clip_space.hpp"
|
||||
|
||||
Camera::Camera(const glm::vec3 &pos, float pitch, float yaw, float aspectRatio) : _position(pos), _yaw(yaw), _pitch(pitch), _aspectRatio(aspectRatio) {
|
||||
update_camera_vectors();
|
||||
update_view();
|
||||
update_projection();
|
||||
}
|
||||
|
||||
const glm::mat4& Camera::view() const {
|
||||
return _view;
|
||||
}
|
||||
|
||||
const glm::mat4& Camera::projection() const {
|
||||
return _projection;
|
||||
}
|
||||
|
||||
const glm::vec3& Camera::position() const {
|
||||
return _position;
|
||||
}
|
||||
|
||||
glm::vec3 Camera::front() const {
|
||||
return glm::normalize(_front);
|
||||
}
|
||||
|
||||
glm::vec3 Camera::right() const {
|
||||
return glm::normalize(_right);
|
||||
}
|
||||
|
||||
glm::vec3 Camera::up() const {
|
||||
return glm::normalize(_up);
|
||||
}
|
||||
|
||||
float Camera::aspect_ratio() const {
|
||||
return _aspectRatio;
|
||||
}
|
||||
|
||||
void Camera::rotate_pitch(float offset) {
|
||||
_pitch += offset;
|
||||
|
||||
if (_pitch < MIN_PITCH) {
|
||||
_pitch = MIN_PITCH;
|
||||
}
|
||||
|
||||
if (_pitch > MAX_PITCH) {
|
||||
_pitch = MAX_PITCH;
|
||||
}
|
||||
|
||||
update_camera_vectors();
|
||||
update_view();
|
||||
}
|
||||
|
||||
void Camera::rotate_yaw(float offset) {
|
||||
_yaw += offset;
|
||||
update_camera_vectors();
|
||||
update_view();
|
||||
}
|
||||
|
||||
void Camera::translate(const glm::vec3& translation) {
|
||||
_position += translation;
|
||||
update_view();
|
||||
}
|
||||
|
||||
void Camera::update_aspect_ratio(float aspectRatio) {
|
||||
_aspectRatio = aspectRatio;
|
||||
_projection = glm::perspective(glm::radians(75.f), _aspectRatio, 0.1f, 100.0f);
|
||||
}
|
||||
|
||||
void Camera::update_camera_vectors() {
|
||||
_front = {};
|
||||
_front.x = cos(glm::radians(_yaw)) * cos(glm::radians(_pitch));
|
||||
_front.y = sin(glm::radians(_pitch));
|
||||
_front.z = sin(glm::radians(_yaw)) * cos(glm::radians(_pitch));
|
||||
|
||||
_front = glm::normalize(_front);
|
||||
|
||||
_right = glm::normalize(glm::cross(_front, WORLD_UP));
|
||||
_up = glm::normalize(glm::cross(_right, _front));
|
||||
}
|
||||
|
||||
void Camera::update_projection() {
|
||||
_projection = glm::perspective(glm::radians(75.f), _aspectRatio, 0.1f, 100.0f);
|
||||
}
|
||||
|
||||
void Camera::update_view() {
|
||||
_view = glm::lookAt(_position, _position + _front, _up);
|
||||
}
|
||||
@@ -12,29 +12,24 @@ constexpr float MIN_PITCH = -89.f;
|
||||
|
||||
constexpr glm::vec3 WORLD_UP = {0.0f, 1.0f, 0.0f};
|
||||
|
||||
enum CAMERA_MOVEMENT {
|
||||
FORWARD,
|
||||
BACKWARD,
|
||||
LEFT,
|
||||
RIGHT,
|
||||
UP,
|
||||
DOWN,
|
||||
};
|
||||
|
||||
class FreeCamera {
|
||||
class Camera {
|
||||
public:
|
||||
FreeCamera() = default;
|
||||
FreeCamera(const glm::vec3 &pos, float pitch, float yaw, float aspectRatio);
|
||||
Camera() = default;
|
||||
Camera(const glm::vec3 &pos, float pitch, float yaw, float aspectRatio);
|
||||
|
||||
[[nodiscard]] const glm::mat4& projection() const;
|
||||
[[nodiscard]] const glm::mat4& view() const;
|
||||
[[nodiscard]] const glm::vec3& position() const;
|
||||
[[nodiscard]] glm::vec3 front() const;
|
||||
[[nodiscard]] glm::vec3 up() const;
|
||||
[[nodiscard]] glm::vec3 right() const;
|
||||
[[nodiscard]] float aspect_ratio() const;
|
||||
|
||||
void update_aspect_ratio(float aspectRatio);
|
||||
void rotate_yaw(float offset);
|
||||
void rotate_pitch(float offset);
|
||||
|
||||
void move(CAMERA_MOVEMENT direction, float offset);
|
||||
void translate(const glm::vec3& direction);
|
||||
private:
|
||||
void update_camera_vectors();
|
||||
void update_projection();
|
||||
@@ -42,9 +37,9 @@ private:
|
||||
|
||||
glm::vec3 _position{};
|
||||
|
||||
glm::vec3 front{};
|
||||
glm::vec3 up{};
|
||||
glm::vec3 right{};
|
||||
glm::vec3 _front{};
|
||||
glm::vec3 _up{};
|
||||
glm::vec3 _right{};
|
||||
|
||||
glm::mat4 _view{};
|
||||
glm::mat4 _projection{};
|
||||
@@ -6,6 +6,7 @@
|
||||
#define B_ENGINE_COMPONENTS_H
|
||||
|
||||
#include "Model.h"
|
||||
#include "ResourceHandle.h"
|
||||
|
||||
#include "entt/entt.hpp"
|
||||
#include "glm/glm.hpp"
|
||||
@@ -17,6 +18,7 @@ namespace Components {
|
||||
glm::vec3 rotation{};
|
||||
glm::vec3 scale{};
|
||||
glm::mat4 model = glm::identity<glm::mat4>();
|
||||
bool dirty {true};
|
||||
};
|
||||
|
||||
struct Relationship {
|
||||
@@ -26,8 +28,8 @@ namespace Components {
|
||||
entt::entity next_sibling {entt::null};
|
||||
};
|
||||
|
||||
struct Drawable {
|
||||
std::shared_ptr<Model> model {nullptr};
|
||||
struct Mesh {
|
||||
ResourceHandle handle;
|
||||
};
|
||||
|
||||
struct DirectionalLight {
|
||||
@@ -40,6 +42,10 @@ namespace Components {
|
||||
struct Tag {
|
||||
std::string name;
|
||||
};
|
||||
|
||||
struct Material {
|
||||
ResourceHandle handle;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
9
src/DefaultResourceHandle.cpp
Normal file
9
src/DefaultResourceHandle.cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
//
|
||||
// Created by slinky on 5/18/26.
|
||||
//
|
||||
|
||||
#include "DefaultResourceHandles.h"
|
||||
|
||||
ResourceHandle DefaultResourceHandles::DEFAULT_DIFFUSE_TEXTURE = ResourceHandle { uuids::uuid::from_string("").value(), 0 };
|
||||
ResourceHandle DefaultResourceHandles::DEFAULT_SPECULAR_TEXTURE = ResourceHandle { uuids::uuid::from_string("").value(), 0 };
|
||||
ResourceHandle DefaultResourceHandles::DEFAULT_SHADER = ResourceHandle { uuids::uuid::from_string("").value(), 0 };
|
||||
16
src/DefaultResourceHandles.h
Normal file
16
src/DefaultResourceHandles.h
Normal file
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// Created by slinky on 5/18/26.
|
||||
//
|
||||
|
||||
#ifndef B_ENGINE_DEFAULTRESOURCEHANDLES_H
|
||||
#define B_ENGINE_DEFAULTRESOURCEHANDLES_H
|
||||
|
||||
#include "ResourceHandle.h"
|
||||
|
||||
struct DefaultResourceHandles {
|
||||
static ResourceHandle DEFAULT_DIFFUSE_TEXTURE;
|
||||
static ResourceHandle DEFAULT_SPECULAR_TEXTURE;
|
||||
static ResourceHandle DEFAULT_SHADER;
|
||||
};
|
||||
|
||||
#endif //B_ENGINE_DEFAULTRESOURCEHANDLES_H
|
||||
21
src/EditorContext.h
Normal file
21
src/EditorContext.h
Normal file
@@ -0,0 +1,21 @@
|
||||
//
|
||||
// Created by slinky on 5/11/26.
|
||||
//
|
||||
|
||||
#ifndef B_ENGINE_EDITORCONTEXT_H
|
||||
#define B_ENGINE_EDITORCONTEXT_H
|
||||
|
||||
#include "Scene.h"
|
||||
#include "GLFW/glfw3.h"
|
||||
|
||||
struct EditorContext {
|
||||
bool sceneViewerFocused = false;
|
||||
glm::vec2 viewportSize = glm::vec2 {};
|
||||
float viewportAspectRatio = 1;
|
||||
|
||||
Scene* scene {nullptr};
|
||||
GLFWwindow* window;
|
||||
entt::entity selectedEntity;
|
||||
};
|
||||
|
||||
#endif //B_ENGINE_EDITORCONTEXT_H
|
||||
@@ -1,99 +0,0 @@
|
||||
//
|
||||
// Created by slinky on 5/3/26.
|
||||
//
|
||||
|
||||
#include "FreeCamera.h"
|
||||
|
||||
#include "glm/ext/matrix_transform.hpp"
|
||||
#include "glm/ext/matrix_clip_space.hpp"
|
||||
|
||||
FreeCamera::FreeCamera(const glm::vec3 &pos, float pitch, float yaw, float aspectRatio) : _position(pos), _yaw(yaw), _pitch(pitch), _aspectRatio(aspectRatio) {
|
||||
update_camera_vectors();
|
||||
update_view();
|
||||
update_projection();
|
||||
}
|
||||
|
||||
const glm::mat4& FreeCamera::view() const {
|
||||
return _view;
|
||||
}
|
||||
|
||||
const glm::mat4& FreeCamera::projection() const {
|
||||
return _projection;
|
||||
}
|
||||
|
||||
const glm::vec3& FreeCamera::position() const {
|
||||
return _position;
|
||||
}
|
||||
|
||||
void FreeCamera::rotate_pitch(float offset) {
|
||||
_pitch += offset;
|
||||
|
||||
if (_pitch < MIN_PITCH) {
|
||||
_pitch = MIN_PITCH;
|
||||
}
|
||||
|
||||
if (_pitch > MAX_PITCH) {
|
||||
_pitch = MAX_PITCH;
|
||||
}
|
||||
|
||||
update_camera_vectors();
|
||||
update_view();
|
||||
}
|
||||
|
||||
void FreeCamera::rotate_yaw(float offset) {
|
||||
_yaw += offset;
|
||||
update_camera_vectors();
|
||||
update_view();
|
||||
}
|
||||
|
||||
void FreeCamera::move(CAMERA_MOVEMENT direction, float offset) {
|
||||
glm::vec3 finalDirection = {};
|
||||
|
||||
switch (direction) {
|
||||
case FORWARD:
|
||||
finalDirection = front;
|
||||
break;
|
||||
case BACKWARD:
|
||||
finalDirection = -front;
|
||||
break;
|
||||
case LEFT:
|
||||
finalDirection = -right;
|
||||
break;
|
||||
case RIGHT:
|
||||
finalDirection = right;
|
||||
break;
|
||||
case UP:
|
||||
finalDirection = up;
|
||||
break;
|
||||
case DOWN:
|
||||
finalDirection = -up;
|
||||
break;
|
||||
}
|
||||
|
||||
finalDirection = glm::normalize(finalDirection);
|
||||
_position += finalDirection * offset;
|
||||
_view = glm::lookAt(_position, _position + front, up);
|
||||
}
|
||||
|
||||
void FreeCamera::update_aspect_ratio(float aspectRatio) {
|
||||
_aspectRatio = aspectRatio;
|
||||
_projection = glm::perspective(glm::radians(75.f), _aspectRatio, 0.1f, 100.0f);
|
||||
}
|
||||
|
||||
void FreeCamera::update_camera_vectors() {
|
||||
front = {};
|
||||
front.x = cos(glm::radians(_yaw)) * cos(glm::radians(_pitch));
|
||||
front.y = sin(glm::radians(_pitch));
|
||||
front.z = sin(glm::radians(_yaw)) * cos(glm::radians(_pitch));
|
||||
|
||||
right = glm::normalize(glm::cross(front, WORLD_UP));
|
||||
up = glm::normalize(glm::cross(right, front));
|
||||
}
|
||||
|
||||
void FreeCamera::update_projection() {
|
||||
_projection = glm::perspective(glm::radians(75.f), _aspectRatio, 0.1f, 100.0f);
|
||||
}
|
||||
|
||||
void FreeCamera::update_view() {
|
||||
_view = glm::lookAt(_position, _position + front, up);
|
||||
}
|
||||
57
src/FreeCameraController.cpp
Normal file
57
src/FreeCameraController.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
//
|
||||
// Created by slinky on 5/11/26.
|
||||
//
|
||||
|
||||
#include "FreeCameraController.h"
|
||||
#include "InputManager.h"
|
||||
|
||||
void FreeCameraController::update(EditorContext &ctx) {
|
||||
checkInput = ctx.sceneViewerFocused;
|
||||
|
||||
if (!checkInput) return;
|
||||
|
||||
if (InputManager::check_action_performed("move_forward")) {
|
||||
const glm::vec3 translation = camera->front() * movement_speed;
|
||||
camera->translate(translation);
|
||||
}
|
||||
|
||||
if (InputManager::check_action_performed("move_backward")) {
|
||||
const glm::vec3 translation = camera->front() * -movement_speed;
|
||||
camera->translate(translation);
|
||||
}
|
||||
|
||||
if (InputManager::check_action_performed("move_left")) {
|
||||
const glm::vec3 translation = camera->right() * -movement_speed;
|
||||
camera->translate(translation);
|
||||
}
|
||||
|
||||
if (InputManager::check_action_performed("move_right")) {
|
||||
const glm::vec3 translation = camera->right() * movement_speed;
|
||||
camera->translate(translation);
|
||||
}
|
||||
|
||||
if (InputManager::check_action_performed("move_up")) {
|
||||
const glm::vec3 translation = camera->up() * movement_speed;
|
||||
camera->translate(translation);
|
||||
}
|
||||
|
||||
if (InputManager::check_action_performed("move_down")) {
|
||||
const glm::vec3 translation = camera->up() * -movement_speed;
|
||||
camera->translate(translation);
|
||||
}
|
||||
}
|
||||
|
||||
void FreeCameraController::on_mouse_delta(float xoff, float yoff) const {
|
||||
if (!checkInput) return;
|
||||
|
||||
camera->rotate_pitch(yoff * look_sensitivity);
|
||||
camera->rotate_yaw(xoff * look_sensitivity);
|
||||
}
|
||||
|
||||
void FreeCameraController::set_camera(Camera& c) {
|
||||
camera = &c;
|
||||
}
|
||||
|
||||
void FreeCameraController::release_camera() {
|
||||
camera = nullptr;
|
||||
}
|
||||
30
src/FreeCameraController.h
Normal file
30
src/FreeCameraController.h
Normal file
@@ -0,0 +1,30 @@
|
||||
//
|
||||
// Created by slinky on 5/11/26.
|
||||
//
|
||||
|
||||
#ifndef B_ENGINE_FREECAMERACONTROLLER_H
|
||||
#define B_ENGINE_FREECAMERACONTROLLER_H
|
||||
|
||||
#include "Camera.h"
|
||||
#include "EditorContext.h"
|
||||
|
||||
class FreeCameraController {
|
||||
public:
|
||||
FreeCameraController() = default;
|
||||
|
||||
void update(EditorContext& ctx);
|
||||
void on_mouse_delta(float xoff, float yoff) const;
|
||||
|
||||
void set_camera(Camera& c);
|
||||
void release_camera();
|
||||
|
||||
float movement_speed = .01;
|
||||
float look_sensitivity = .01;
|
||||
private:
|
||||
Camera* camera {nullptr};
|
||||
|
||||
bool checkInput = false;
|
||||
};
|
||||
|
||||
|
||||
#endif //B_ENGINE_FREECAMERACONTROLLER_H
|
||||
@@ -5,30 +5,24 @@
|
||||
#ifndef B_ENGINE_MATERIAL_H
|
||||
#define B_ENGINE_MATERIAL_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "Texture.h"
|
||||
#include "ResourceHandle.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct PhongProperties {
|
||||
glm::vec3 ambient;
|
||||
glm::vec3 diffuse;
|
||||
glm::vec3 specular;
|
||||
float shininess;
|
||||
} PhongProperties;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
std::shared_ptr<Texture> diffuse;
|
||||
std::shared_ptr<Texture> specular;
|
||||
std::shared_ptr<Texture> normal;
|
||||
|
||||
std::string name;
|
||||
|
||||
PhongProperties phong;
|
||||
} Material;
|
||||
struct Material{
|
||||
ResourceHandle diffuse;
|
||||
ResourceHandle specular;
|
||||
ResourceHandle normal;
|
||||
PhongProperties phong{};
|
||||
ResourceHandle shader;
|
||||
};
|
||||
|
||||
|
||||
#endif //B_ENGINE_MATERIAL_H
|
||||
93
src/MaterialFile.cpp
Normal file
93
src/MaterialFile.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
//
|
||||
// Created by slinky on 5/18/26.
|
||||
//
|
||||
|
||||
#include "MaterialFile.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "DefaultResourceHandles.h"
|
||||
#include "spdlog/spdlog.h"
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
std::optional<ResourceHandle> read_resource_handle(const json& j) {
|
||||
ResourceHandle handle;
|
||||
|
||||
if (j.is_null()) {
|
||||
return std::optional<ResourceHandle>();
|
||||
}
|
||||
|
||||
if (!j.contains("assetUUID")) {
|
||||
return std::optional<ResourceHandle>();
|
||||
}
|
||||
|
||||
auto uuidStr = j["assetUUID"].get<std::string>();
|
||||
auto uuid = uuids::uuid::from_string(uuidStr);
|
||||
if (!uuid.has_value()) {
|
||||
return std::optional<ResourceHandle>();
|
||||
}
|
||||
handle.assetUUID = *uuid;
|
||||
|
||||
if (!j.contains("localId")) {
|
||||
return std::optional<ResourceHandle>();
|
||||
}
|
||||
handle.localId = j["localId"].get<uint32_t>();
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
std::optional<Material> MaterialFile::load(std::string_view _path) {
|
||||
std::ifstream file;
|
||||
file.open(_path.data(), std::ios::in);
|
||||
if (!file.is_open()) {
|
||||
spdlog::error("failed to open project file {}", _path);
|
||||
return std::optional<Material>();
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
ss << file.rdbuf();
|
||||
|
||||
std::string fileData = ss.str();
|
||||
|
||||
try {
|
||||
auto data = json::parse(fileData);
|
||||
|
||||
|
||||
Material material;
|
||||
|
||||
// ---------------------------------
|
||||
// Texture/resource handles
|
||||
// ---------------------------------
|
||||
|
||||
material.diffuse = DefaultResourceHandles::DEFAULT_DIFFUSE_TEXTURE;
|
||||
if (auto diffuse = read_resource_handle(data["diffuse"]); diffuse.has_value()) {
|
||||
material.diffuse = *diffuse;
|
||||
}
|
||||
|
||||
material.normal = DefaultResourceHandles::DEFAULT_DIFFUSE_TEXTURE;
|
||||
if (auto normal = read_resource_handle(data["normal"]); normal.has_value()) {
|
||||
material.normal = *normal;
|
||||
}
|
||||
|
||||
material.specular = DefaultResourceHandles::DEFAULT_SPECULAR_TEXTURE;
|
||||
if (auto specular = read_resource_handle(data["specular"]); specular.has_value()) {
|
||||
material.specular = *specular;
|
||||
}
|
||||
|
||||
material.shader = DefaultResourceHandles::DEFAULT_SHADER;
|
||||
if (auto shader = read_resource_handle(data["shader"]); shader.has_value()) {
|
||||
material.shader = *shader;
|
||||
}
|
||||
|
||||
return material;
|
||||
} catch (const std::exception& e) {
|
||||
spdlog::error("Error reading material file: {}", e.what());
|
||||
return std::optional<Material>();
|
||||
}
|
||||
}
|
||||
|
||||
bool MaterialFile::save(std::string_view _path, Material *_project) {
|
||||
return true;
|
||||
}
|
||||
17
src/MaterialFile.h
Normal file
17
src/MaterialFile.h
Normal file
@@ -0,0 +1,17 @@
|
||||
//
|
||||
// Created by slinky on 5/18/26.
|
||||
//
|
||||
|
||||
#ifndef B_ENGINE_MATERIALFILE_H
|
||||
#define B_ENGINE_MATERIALFILE_H
|
||||
|
||||
#include "Material.h"
|
||||
|
||||
class MaterialFile {
|
||||
public:
|
||||
static std::optional<Material> load(std::string_view _path);
|
||||
static bool save(std::string_view _path, Material* _project);
|
||||
};
|
||||
|
||||
|
||||
#endif //B_ENGINE_MATERIALFILE_H
|
||||
7
src/MaterialManager.cpp
Normal file
7
src/MaterialManager.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
//
|
||||
// Created by slinky on 5/17/26.
|
||||
//
|
||||
|
||||
#include "MaterialManager.h"
|
||||
|
||||
std::unordered_map<ResourceHandle, std::unique_ptr<Material>> MaterialManager::materials = {};
|
||||
17
src/MaterialManager.h
Normal file
17
src/MaterialManager.h
Normal file
@@ -0,0 +1,17 @@
|
||||
//
|
||||
// Created by slinky on 5/17/26.
|
||||
//
|
||||
|
||||
#ifndef B_ENGINE_MATERIALMANAGER_H
|
||||
#define B_ENGINE_MATERIALMANAGER_Hs
|
||||
#include <unordered_map>
|
||||
|
||||
#include "Material.h"
|
||||
#include "ResourceHandle.h"
|
||||
|
||||
class MaterialManager {
|
||||
public:
|
||||
static std::unordered_map<ResourceHandle, std::unique_ptr<Material>> materials;
|
||||
};
|
||||
|
||||
#endif //B_ENGINE_MATERIALMANAGER_H
|
||||
@@ -21,7 +21,6 @@ public:
|
||||
GLuint vao = 0;
|
||||
GLuint ebo = 0;
|
||||
unsigned int numIndices = 0;
|
||||
unsigned int materialId = 0;
|
||||
};
|
||||
|
||||
#endif //B_ENGINE_MESH_H
|
||||
7
src/MeshManager.cpp
Normal file
7
src/MeshManager.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
//
|
||||
// Created by slinky on 5/17/26.
|
||||
//
|
||||
|
||||
#include "MeshManager.h"
|
||||
|
||||
std::unordered_map<ResourceHandle, std::unique_ptr<Mesh>> MeshManager::meshes;
|
||||
18
src/MeshManager.h
Normal file
18
src/MeshManager.h
Normal file
@@ -0,0 +1,18 @@
|
||||
//
|
||||
// Created by slinky on 5/17/26.
|
||||
//
|
||||
|
||||
#ifndef B_ENGINE_MESHMANAGER_H
|
||||
#define B_ENGINE_MESHMANAGER_H
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include "ResourceHandle.h"
|
||||
#include "Mesh.h"
|
||||
|
||||
class MeshManager {
|
||||
public:
|
||||
static std::unordered_map<ResourceHandle, std::unique_ptr<Mesh>> meshes;
|
||||
};
|
||||
|
||||
#endif //B_ENGINE_MESHMANAGER_H
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#include "ModelManager.h"
|
||||
#include "ModelImporter.h"
|
||||
|
||||
#include <assimp/Importer.hpp>
|
||||
#include <assimp/postprocess.h>
|
||||
@@ -15,15 +15,12 @@
|
||||
#include "TextureManager.h"
|
||||
#include "glm/ext/matrix_transform.hpp"
|
||||
|
||||
std::unordered_map<std::string, std::shared_ptr<Model>> ModelManager::models;
|
||||
|
||||
void process_ai_node(aiNode* node, const aiScene* scene, glm::mat4 transform, ModelNode& model);
|
||||
|
||||
void process_ai_mesh(const aiMesh* aiMesh, Mesh& mesh);
|
||||
|
||||
void process_ai_material(const aiMaterial* aiMat, Material& mat, const std::filesystem::path& modelDirectory);
|
||||
/*void process_ai_material(const aiMaterial* aiMat, Material& mat, const std::filesystem::path& modelDirectory);
|
||||
void process_ai_material_diffuse(const aiMaterial *aiMat, Material& mat, const std::filesystem::path& modelDirectory);
|
||||
void process_ai_material_specular(const aiMaterial *aiMat, Material& mat, const std::filesystem::path& modelDirectory);
|
||||
void process_ai_material_specular(const aiMaterial *aiMat, Material& mat, const std::filesystem::path& modelDirectory);*/
|
||||
|
||||
auto zUpMatrix = glm::mat4(
|
||||
1.0f, 0.0f, 0.0f, 0.0f, // Column 0
|
||||
@@ -32,7 +29,7 @@ auto zUpMatrix = glm::mat4(
|
||||
0.0f, 0.0f, 0.0f, 1.0f // Column 3
|
||||
);
|
||||
|
||||
std::shared_ptr<Model> ModelManager::load_from_file(std::string_view _path, bool zUp)
|
||||
std::vector<Mesh> ModelImporter::load_from_file(std::string_view _path, bool zUp)
|
||||
{
|
||||
Assimp::Importer importer;
|
||||
|
||||
@@ -44,39 +41,19 @@ std::shared_ptr<Model> ModelManager::load_from_file(std::string_view _path, bool
|
||||
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
|
||||
{
|
||||
spdlog::error("failed to load model {}: {}", _path, importer.GetErrorString());
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
auto model = std::make_shared<Model>();
|
||||
|
||||
const std::filesystem::path modelPath = {_path};
|
||||
for (unsigned int i = 0; i < scene->mNumMaterials; i++) {
|
||||
aiMaterial* aiMat = scene->mMaterials[i];
|
||||
aiString matName;
|
||||
if (aiMat->Get(AI_MATKEY_NAME, matName) && strcmp(matName.data, "DefaultMaterial") == 0) {
|
||||
continue;
|
||||
}
|
||||
Material mat{};
|
||||
process_ai_material(aiMat, mat, modelPath.parent_path());
|
||||
model->materials.push_back(std::make_shared<Material>(mat));
|
||||
}
|
||||
auto meshes = std::vector<Mesh>{};
|
||||
|
||||
for (unsigned int i = 0; i < scene->mNumMeshes; i++) {
|
||||
aiMesh* aiMesh = scene->mMeshes[i];
|
||||
Mesh mesh{};
|
||||
mesh.materialId = aiMesh->mMaterialIndex;
|
||||
process_ai_mesh(aiMesh, mesh);
|
||||
model->meshes.push_back(std::make_shared<Mesh>(mesh));
|
||||
meshes.push_back(mesh);
|
||||
}
|
||||
|
||||
auto transform = glm::identity<glm::mat4>();
|
||||
if (zUp) {
|
||||
transform = zUpMatrix;
|
||||
}
|
||||
|
||||
process_ai_node(scene->mRootNode, scene, transform, model->root);
|
||||
|
||||
return model;
|
||||
return meshes;
|
||||
}
|
||||
|
||||
void process_ai_node(aiNode* aiNode, const aiScene* scene, glm::mat4 transform, ModelNode& node)
|
||||
@@ -148,7 +125,7 @@ void process_ai_mesh(const aiMesh* aiMesh, Mesh& mesh)
|
||||
mesh = {positions, uvs, normals, indices};
|
||||
}
|
||||
|
||||
void process_ai_material(const aiMaterial* aiMat, Material& mat, const std::filesystem::path& modelDirectory) {
|
||||
/*void process_ai_material(const aiMaterial* aiMat, Material& mat, const std::filesystem::path& modelDirectory) {
|
||||
aiString matName;
|
||||
aiReturn ret = aiMat->Get(AI_MATKEY_NAME, matName);
|
||||
if (ret != AI_SUCCESS) {
|
||||
@@ -193,9 +170,9 @@ void process_ai_material(const aiMaterial* aiMat, Material& mat, const std::file
|
||||
mat.phong.diffuse = glm::vec3{diffuseColor.r, diffuseColor.g, diffuseColor.b};
|
||||
mat.phong.specular = glm::vec3{specularColor.r, specularColor.g, specularColor.b};
|
||||
mat.phong.shininess = shininess;
|
||||
}
|
||||
}*/
|
||||
|
||||
void process_ai_material_diffuse(const aiMaterial *aiMat, Material& mat, const std::filesystem::path& modelDirectory) {
|
||||
/*void process_ai_material_diffuse(const aiMaterial *aiMat, Material& mat, const std::filesystem::path& modelDirectory) {
|
||||
aiString aiTextureName;
|
||||
aiMat->GetTexture(aiTextureType_DIFFUSE, 0, &aiTextureName);
|
||||
std::string textureName = aiTextureName.C_Str();
|
||||
@@ -259,4 +236,4 @@ void process_ai_material_specular(const aiMaterial *aiMat, Material& mat, const
|
||||
} else {
|
||||
mat.specular = TextureManager::textures["default_specular"];
|
||||
}
|
||||
}
|
||||
}*/
|
||||
19
src/ModelImporter.h
Normal file
19
src/ModelImporter.h
Normal file
@@ -0,0 +1,19 @@
|
||||
//
|
||||
// Created by lbmas on 4/29/2026.
|
||||
//
|
||||
|
||||
#ifndef B_ENGINE_MODELIMPORTER_H
|
||||
#define B_ENGINE_MODELIMPORTER_H
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include "Model.h"
|
||||
|
||||
class ModelImporter
|
||||
{
|
||||
public:
|
||||
static std::vector<Mesh> load_from_file(std::string_view _path, bool zUp = false);
|
||||
};
|
||||
|
||||
|
||||
#endif //B_ENGINE_MODELIMPORTER_H
|
||||
@@ -1,22 +0,0 @@
|
||||
//
|
||||
// Created by lbmas on 4/29/2026.
|
||||
//
|
||||
|
||||
#ifndef B_ENGINE_MODELLOADER_H
|
||||
#define B_ENGINE_MODELLOADER_H
|
||||
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
|
||||
#include "Model.h"
|
||||
|
||||
class ModelManager
|
||||
{
|
||||
public:
|
||||
static std::unordered_map<std::string, std::shared_ptr<Model>> models;
|
||||
|
||||
static std::shared_ptr<Model> load_from_file(std::string_view _path, bool zUp = false);
|
||||
};
|
||||
|
||||
|
||||
#endif //B_ENGINE_MODELLOADER_H
|
||||
19
src/ProjectManifest.h
Normal file
19
src/ProjectManifest.h
Normal file
@@ -0,0 +1,19 @@
|
||||
//
|
||||
// Created by lbmas on 5/13/2026.
|
||||
//
|
||||
|
||||
#ifndef B_ENGINE_PROJECTMANIFEST_H
|
||||
#define B_ENGINE_PROJECTMANIFEST_H
|
||||
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
std::string name;
|
||||
std::string assetFolder;
|
||||
|
||||
std::filesystem::path projectDirectory;
|
||||
} ProjectManifest;
|
||||
|
||||
#endif //B_ENGINE_PROJECTMANIFEST_H
|
||||
38
src/ProjectManifestFile.cpp
Normal file
38
src/ProjectManifestFile.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// Created by slinky on 5/14/26.
|
||||
//
|
||||
|
||||
#include "ProjectManifestFile.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "spdlog/spdlog.h"
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
std::unique_ptr<ProjectManifest> ProjectManifestFile::load(std::string_view _path) {
|
||||
std::ifstream file;
|
||||
file.open(_path.data(), std::ios::in);
|
||||
if (!file.is_open()) {
|
||||
spdlog::error("failed to open project file {}", _path);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
ss << file.rdbuf();
|
||||
|
||||
std::string fileData = ss.str();
|
||||
|
||||
auto data = json::parse(fileData);
|
||||
|
||||
ProjectManifest manifest;
|
||||
manifest.name = data.at("name").get<std::string>();
|
||||
manifest.assetFolder = data.at("assetFolder").get<std::string>();
|
||||
|
||||
return std::make_unique<ProjectManifest>(manifest);
|
||||
}
|
||||
|
||||
bool ProjectManifestFile::save(std::string_view _path, ProjectManifest *_project) {
|
||||
return true;
|
||||
}
|
||||
19
src/ProjectManifestFile.h
Normal file
19
src/ProjectManifestFile.h
Normal file
@@ -0,0 +1,19 @@
|
||||
//
|
||||
// Created by slinky on 5/14/26.
|
||||
//
|
||||
|
||||
#ifndef B_ENGINE_PROJECTMANIFESTFILE_H
|
||||
#define B_ENGINE_PROJECTMANIFESTFILE_H
|
||||
|
||||
#include <string_view>
|
||||
#include <memory>
|
||||
|
||||
#include "ProjectManifest.h"
|
||||
|
||||
class ProjectManifestFile {
|
||||
public:
|
||||
static std::unique_ptr<ProjectManifest> load(std::string_view _path);
|
||||
static bool save(std::string_view _path, ProjectManifest* _project);
|
||||
};
|
||||
|
||||
#endif //B_ENGINE_PROJECTMANIFESTFILE_H
|
||||
36
src/ResourceHandle.h
Normal file
36
src/ResourceHandle.h
Normal file
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// Created by slinky on 5/17/26.
|
||||
//
|
||||
|
||||
#ifndef B_ENGINE_RESOURCEHANDLE_H
|
||||
#define B_ENGINE_RESOURCEHANDLE_H
|
||||
|
||||
#include "uuid.h"
|
||||
|
||||
struct ResourceHandle {
|
||||
uuids::uuid assetUUID;
|
||||
uint32_t localId = 0;
|
||||
|
||||
bool operator==(const ResourceHandle& other) const {
|
||||
return assetUUID == other.assetUUID && localId == other.localId;
|
||||
}
|
||||
|
||||
ResourceHandle() = default;
|
||||
|
||||
ResourceHandle(const uuids::uuid& uuid, int id) : assetUUID(uuid), localId(id) {}
|
||||
};
|
||||
|
||||
namespace std {
|
||||
template<>
|
||||
struct hash<ResourceHandle> {
|
||||
size_t operator()(const ResourceHandle& handle) const noexcept {
|
||||
// Use the UUID library's native hash function
|
||||
size_t h1 = std::hash<uuids::uuid>{}(handle.assetUUID);
|
||||
size_t h2 = std::hash<uint32_t>{}(handle.localId);
|
||||
|
||||
return h1 ^ h2 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif //B_ENGINE_RESOURCEHANDLE_H
|
||||
149
src/Scene.cpp
149
src/Scene.cpp
@@ -5,6 +5,11 @@
|
||||
#include "Scene.h"
|
||||
|
||||
#include "Components.h"
|
||||
|
||||
#include "MeshManager.h"
|
||||
#include "MaterialManager.h"
|
||||
#include "ShaderManager.h"
|
||||
|
||||
#include "fmt/format.h"
|
||||
|
||||
Scene::Scene() {
|
||||
@@ -18,11 +23,15 @@ entt::entity Scene::create_game_object() {
|
||||
}
|
||||
|
||||
entt::entity Scene::create_game_object(entt::entity parent) {
|
||||
if (parent == entt::null) {
|
||||
parent = root;
|
||||
}
|
||||
|
||||
const entt::entity entity = _registry.create();
|
||||
attach_component<Components::Transform>(entity);
|
||||
attach_component<Components::Relationship>(entity);
|
||||
auto& tag = attach_component<Components::Tag>(entity);
|
||||
tag.name = fmt::format("entity {0}", (int)entity);
|
||||
auto&[name] = attach_component<Components::Tag>(entity);
|
||||
name = fmt::format("entity {0}", static_cast<int>(entity));
|
||||
|
||||
add_child(parent, entity);
|
||||
|
||||
@@ -30,43 +39,98 @@ entt::entity Scene::create_game_object(entt::entity parent) {
|
||||
}
|
||||
|
||||
void Scene::update_transforms() {
|
||||
|
||||
std::vector<entt::entity> children = get_children(root);
|
||||
for (auto child: children) {
|
||||
update_transforms(child);
|
||||
}
|
||||
}
|
||||
|
||||
void Scene::draw_scene(ShaderProgram *shader) {
|
||||
auto view = _registry.view<Components::Transform, Components::Drawable>();
|
||||
for (auto e : view) {
|
||||
const auto& transform = view.get<Components::Transform>(e);
|
||||
shader->setMat4("model", transform.model);
|
||||
void Scene::update_transforms(entt::entity entity) {
|
||||
auto& transform = fetch_component<Components::Transform>(entity);
|
||||
|
||||
const auto& drawable = view.get<Components::Drawable>(e);
|
||||
const Model* model = drawable.model.get();
|
||||
for (const auto& mesh: drawable.model->meshes) {
|
||||
unsigned int materialId = mesh->materialId;
|
||||
if (materialId >= model->materials.size()) {
|
||||
materialId = 0;
|
||||
}
|
||||
if (!transform.dirty)
|
||||
return;
|
||||
|
||||
const std::shared_ptr<Material> mat = model->materials[materialId];
|
||||
glm::mat4 translation =
|
||||
glm::translate(glm::mat4(1.0f), transform.position);
|
||||
|
||||
shader->setVec3("phongAmbient", mat->phong.ambient);
|
||||
shader->setVec3("phongDiffuse", mat->phong.diffuse);
|
||||
shader->setVec3("phongSpecular", mat->phong.specular);
|
||||
shader->setFloat("phongShininess", mat->phong.shininess);
|
||||
glm::mat4 rotationX =
|
||||
glm::rotate(glm::mat4(1.0f), transform.rotation.x, glm::vec3(1,0,0));
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
const auto diffuse = mat->diffuse;
|
||||
diffuse->bind();
|
||||
shader->setInt("diffuseMap", 0);
|
||||
glm::mat4 rotationY =
|
||||
glm::rotate(glm::mat4(1.0f), transform.rotation.y, glm::vec3(0,1,0));
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
const auto specular = mat->specular;
|
||||
specular->bind();
|
||||
shader->setInt("specularMap", 1);
|
||||
glm::mat4 rotationZ =
|
||||
glm::rotate(glm::mat4(1.0f), transform.rotation.z, glm::vec3(0,0,1));
|
||||
|
||||
glBindVertexArray(mesh.get()->vao);
|
||||
glDrawElements(GL_TRIANGLES, mesh->numIndices, GL_UNSIGNED_INT, 0);
|
||||
glm::mat4 scaling =
|
||||
glm::scale(glm::mat4(1.0f), transform.scale);
|
||||
|
||||
glm::mat4 localModel =
|
||||
translation *
|
||||
rotationZ *
|
||||
rotationY *
|
||||
rotationX *
|
||||
scaling;
|
||||
|
||||
auto& rel = fetch_component<Components::Relationship>(entity);
|
||||
if (rel.parent != entt::null) {
|
||||
auto& parentTransform = fetch_component<Components::Transform>(rel.parent);
|
||||
transform.model = parentTransform.model * localModel;
|
||||
} else {
|
||||
transform.model = localModel;
|
||||
}
|
||||
|
||||
transform.dirty = false;
|
||||
|
||||
std::vector<entt::entity> children = get_children(entity);
|
||||
for (auto child: children) {
|
||||
update_transforms(child);
|
||||
}
|
||||
}
|
||||
|
||||
void Scene::draw_scene() {
|
||||
auto view = _registry.view<Components::Transform, Components::Mesh, Components::Material>();
|
||||
for (const auto e : view) {
|
||||
const auto&[matHandle] = view.get<Components::Material>(e);
|
||||
const auto* mat = MaterialManager::materials[matHandle].get();
|
||||
|
||||
auto* program = ShaderManager::shaders[mat->shader].get();
|
||||
|
||||
program->bind();
|
||||
program->setMat4("projection", activeCamera->projection());
|
||||
program->setMat4("view", activeCamera->view());
|
||||
program->setVec3("viewPosition", activeCamera->position());
|
||||
|
||||
auto dirLights = _registry.view<Components::DirectionalLight>();
|
||||
for (const auto e : dirLights) {
|
||||
auto dirLight = dirLights.get<Components::DirectionalLight>(e);
|
||||
program->setVec3("lightDirection", dirLight.direction);
|
||||
program->setVec3("lightAmbient", dirLight.ambient);
|
||||
program->setVec3("lightDiffuse", dirLight.diffuse);
|
||||
program->setVec3("lightSpecular", dirLight.specular);
|
||||
break;
|
||||
}
|
||||
|
||||
program->setVec3("phongAmbient", mat->phong.ambient);
|
||||
program->setVec3("phongDiffuse", mat->phong.diffuse);
|
||||
program->setVec3("phongSpecular", mat->phong.specular);
|
||||
program->setFloat("phongShininess", mat->phong.shininess);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
const auto diffuseHandle = mat->diffuse;
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
const auto specularHandle = mat->specular;
|
||||
|
||||
const auto& transform = view.get<Components::Transform>(e);
|
||||
program->setMat4("model", transform.model);
|
||||
|
||||
const auto&[meshHandle] = view.get<Components::Mesh>(e);
|
||||
const auto* mesh = MeshManager::meshes[meshHandle].get();
|
||||
|
||||
glBindVertexArray(mesh->vao);
|
||||
glDrawElements(GL_TRIANGLES, mesh->numIndices, GL_UNSIGNED_INT, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +138,17 @@ entt::entity Scene::get_root() const {
|
||||
return root;
|
||||
}
|
||||
|
||||
std::vector<entt::entity> Scene::get_children(entt::entity parent) {
|
||||
std::vector<entt::entity> children{};
|
||||
auto child = fetch_component<Components::Relationship>(parent).first_child;
|
||||
while (child != entt::null) {
|
||||
children.push_back(child);
|
||||
const auto& relationship = fetch_component<Components::Relationship>(child);
|
||||
child = relationship.next_sibling;
|
||||
}
|
||||
return children;
|
||||
}
|
||||
|
||||
void Scene::add_child(entt::entity parent, entt::entity child) {
|
||||
auto& parentRelationship = fetch_component<Components::Relationship>(parent);
|
||||
|
||||
@@ -85,15 +160,19 @@ void Scene::add_child(entt::entity parent, entt::entity child) {
|
||||
}
|
||||
|
||||
entt::entity lastSibling = parentRelationship.first_child;
|
||||
auto& lastSiblingRelationship = fetch_component<Components::Relationship>(lastSibling);
|
||||
while (lastSiblingRelationship.next_sibling != entt::null) {
|
||||
lastSibling = lastSiblingRelationship.next_sibling;
|
||||
lastSiblingRelationship = fetch_component<Components::Relationship>(lastSibling);
|
||||
auto* lastSiblingRelationship = &fetch_component<Components::Relationship>(lastSibling);
|
||||
while (lastSiblingRelationship->next_sibling != entt::null) {
|
||||
lastSibling = lastSiblingRelationship->next_sibling;
|
||||
lastSiblingRelationship = &fetch_component<Components::Relationship>(lastSibling);
|
||||
}
|
||||
lastSiblingRelationship.next_sibling = child;
|
||||
lastSiblingRelationship->next_sibling = child;
|
||||
|
||||
auto& childRelationship = fetch_component<Components::Relationship>(child);
|
||||
childRelationship.prev_sibling = lastSibling;
|
||||
childRelationship.next_sibling = entt::null;
|
||||
childRelationship.parent = parent;
|
||||
}
|
||||
|
||||
void Scene::set_active_camera(Camera *camera) {
|
||||
activeCamera = camera;
|
||||
}
|
||||
|
||||
14
src/Scene.h
14
src/Scene.h
@@ -5,6 +5,7 @@
|
||||
#ifndef B_ENGINE_SCENE_H
|
||||
#define B_ENGINE_SCENE_H
|
||||
|
||||
#include "Camera.h"
|
||||
#include "ShaderProgram.h"
|
||||
#include "entt/entt.hpp"
|
||||
|
||||
@@ -31,15 +32,26 @@ public:
|
||||
return _registry.get<T>(e);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool has_component(entt::entity e) {
|
||||
return _registry.all_of<T>(e);
|
||||
}
|
||||
|
||||
void update_transforms();
|
||||
void draw_scene(ShaderProgram* program);
|
||||
void draw_scene();
|
||||
|
||||
[[nodiscard]] entt::entity get_root() const;
|
||||
[[nodiscard]] std::vector<entt::entity> get_children(entt::entity parent);
|
||||
|
||||
void set_active_camera(Camera *camera);
|
||||
private:
|
||||
entt::registry _registry{};
|
||||
entt::entity root{entt::null};
|
||||
|
||||
void add_child(entt::entity parent, entt::entity child);
|
||||
void update_transforms(entt::entity parent);
|
||||
|
||||
Camera* activeCamera {nullptr};
|
||||
};
|
||||
|
||||
#endif //B_ENGINE_SCENE_H
|
||||
@@ -14,9 +14,9 @@
|
||||
void log_shader_compile_errors(GLuint shader, std::string_view shaderType);
|
||||
void log_program_compile_errors(GLuint program);
|
||||
|
||||
std::unordered_map<std::string, std::shared_ptr<ShaderProgram>> ShaderManager::shaders;
|
||||
std::unordered_map<ResourceHandle, std::unique_ptr<ShaderProgram>> ShaderManager::shaders;
|
||||
|
||||
std::shared_ptr<ShaderProgram> ShaderManager::load(std::string_view vertexPath, std::string_view fragmentPath)
|
||||
std::unique_ptr<ShaderProgram> ShaderManager::load(std::string_view vertexPath, std::string_view fragmentPath)
|
||||
{
|
||||
std::string vertexSource;
|
||||
std::string fragmentSource;
|
||||
@@ -24,8 +24,7 @@ std::shared_ptr<ShaderProgram> ShaderManager::load(std::string_view vertexPath,
|
||||
std::ifstream vertexFile {};
|
||||
std::ifstream fragmentFile {};
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
vertexFile.open(vertexPath.data());
|
||||
fragmentFile.open(fragmentPath.data());
|
||||
|
||||
@@ -39,8 +38,8 @@ std::shared_ptr<ShaderProgram> ShaderManager::load(std::string_view vertexPath,
|
||||
|
||||
vertexFile.close();
|
||||
fragmentFile.close();
|
||||
} catch (std::ifstream::failure& e) {
|
||||
spdlog::error("Failed to load shader program {}, {}: {}", vertexPath, fragmentPath, std::string(e.what()).c_str());
|
||||
} catch (std::fstream::failure& e) {
|
||||
spdlog::error("Failed to load shader program {}, {}: {}", vertexPath, fragmentPath, e.what());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -69,7 +68,7 @@ std::shared_ptr<ShaderProgram> ShaderManager::load(std::string_view vertexPath,
|
||||
glDeleteShader(vertex);
|
||||
glDeleteShader(fragment);
|
||||
|
||||
return std::make_shared<ShaderProgram>(ShaderProgram(shaderId));
|
||||
return std::make_unique<ShaderProgram>(shaderId);
|
||||
}
|
||||
|
||||
void log_shader_compile_errors(GLuint shader, std::string_view shaderType)
|
||||
|
||||
@@ -5,17 +5,17 @@
|
||||
#ifndef B_ENGINE_SHADERMANAGER_H
|
||||
#define B_ENGINE_SHADERMANAGER_H
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <memory>
|
||||
|
||||
#include "ResourceHandle.h"
|
||||
#include "ShaderProgram.h"
|
||||
|
||||
class ShaderManager {
|
||||
public:
|
||||
static std::unordered_map<std::string, std::shared_ptr<ShaderProgram>> shaders;
|
||||
static std::unordered_map<ResourceHandle, std::unique_ptr<ShaderProgram>> shaders;
|
||||
static std::unique_ptr<ShaderProgram> load(std::string_view vertexPath, std::string_view fragmentPath);
|
||||
|
||||
static std::shared_ptr<ShaderProgram> load(std::string_view vertexPath, std::string_view fragmentPath);
|
||||
};
|
||||
|
||||
#endif //B_ENGINE_SHADERMANAGER_H
|
||||
@@ -10,10 +10,9 @@
|
||||
|
||||
#include "glad/gl.h"
|
||||
|
||||
std::unordered_map<std::string, std::shared_ptr<Texture>> TextureManager::textures;
|
||||
std::unordered_map<ResourceHandle, std::unique_ptr<Texture>> TextureManager::textures;
|
||||
|
||||
std::shared_ptr<Texture> TextureManager::load_from_file(std::string_view filePath)
|
||||
{
|
||||
std::unique_ptr<Texture> TextureManager::load_from_file(const std::string_view filePath) {
|
||||
int width, height, channels;
|
||||
unsigned char *data = stbi_load(filePath.data(), &width, &height, &channels, 0);
|
||||
|
||||
@@ -38,10 +37,10 @@ std::shared_ptr<Texture> TextureManager::load_from_file(std::string_view filePat
|
||||
|
||||
stbi_image_free(data);
|
||||
|
||||
return std::make_shared<Texture>(textureID, filePath, width, height, channels);
|
||||
return std::make_unique<Texture>(textureID, filePath, width, height, channels);
|
||||
}
|
||||
|
||||
std::shared_ptr<Texture> TextureManager::load_from_data(unsigned char* data, int width, int height, int channels)
|
||||
std::unique_ptr<Texture> TextureManager::load_from_data(unsigned char* data, int width, int height, int channels)
|
||||
{
|
||||
unsigned int textureID = 0;
|
||||
glGenTextures(1, &textureID);
|
||||
@@ -57,5 +56,5 @@ std::shared_ptr<Texture> TextureManager::load_from_data(unsigned char* data, int
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, (GLint)format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
return std::make_shared<Texture>(textureID, "memory", width, height, channels);
|
||||
return std::make_unique<Texture>(textureID, "memory", width, height, channels);
|
||||
}
|
||||
@@ -8,14 +8,15 @@
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "ResourceHandle.h"
|
||||
#include "Texture.h"
|
||||
|
||||
class TextureManager {
|
||||
public:
|
||||
static std::unordered_map<std::string, std::shared_ptr<Texture>> textures;
|
||||
static std::unordered_map<ResourceHandle, std::unique_ptr<Texture>> textures;
|
||||
|
||||
static std::shared_ptr<Texture> load_from_file(std::string_view filePath);
|
||||
static std::shared_ptr<Texture> load_from_data(unsigned char* data, int width, int height, int channels);
|
||||
static std::unique_ptr<Texture> load_from_file(std::string_view filePath);
|
||||
static std::unique_ptr<Texture> load_from_data(unsigned char* data, int width, int height, int channels);
|
||||
};
|
||||
|
||||
#endif //B_ENGINE_TEXTUREMANAGER_H
|
||||
16
src/Types.h
Normal file
16
src/Types.h
Normal file
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// Created by slinky on 5/14/26.
|
||||
//
|
||||
|
||||
#ifndef B_ENGINE_TYPES_H
|
||||
#define B_ENGINE_TYPES_H
|
||||
|
||||
enum class AssetType {
|
||||
UNKNOWN = 0,
|
||||
DIRECTORY = 1,
|
||||
SHADER = 2,
|
||||
TEXTURE = 3,
|
||||
MODEL = 4
|
||||
};
|
||||
|
||||
#endif //B_ENGINE_TYPES_H
|
||||
88
src/UIManager.cpp
Normal file
88
src/UIManager.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
//
|
||||
// Created by slinky on 5/11/26.
|
||||
//
|
||||
|
||||
#include "UIManager.h"
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_glfw.h"
|
||||
#include "imgui_impl_opengl3.h"
|
||||
#include "imgui_internal.h"
|
||||
|
||||
std::unordered_map<std::string, std::shared_ptr<IUIPanel>> UIManager::uiPanels {};
|
||||
GLFWwindow* UIManager::window {nullptr};
|
||||
bool UIManager::updateDockspace {true};
|
||||
|
||||
void UIManager::init(GLFWwindow* _window) {
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
|
||||
|
||||
ImGui::StyleColorsDark();
|
||||
ImGui_ImplGlfw_InitForOpenGL(_window, true);
|
||||
ImGui_ImplOpenGL3_Init("#version 400");
|
||||
|
||||
window = _window;
|
||||
}
|
||||
|
||||
void UIManager::update(EditorContext& ctx) {
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
|
||||
ImGui::NewFrame();
|
||||
{
|
||||
ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;
|
||||
ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||||
ImGui::SetNextWindowPos(viewport->Pos);
|
||||
ImGui::SetNextWindowSize(viewport->Size);
|
||||
ImGui::SetNextWindowViewport(viewport->ID);
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
||||
window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
|
||||
window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
|
||||
|
||||
ImGui::Begin("b_engine dockspace", nullptr, window_flags);
|
||||
ImGui::PopStyleVar(2);
|
||||
|
||||
ImGuiID dockspace_id = ImGui::GetID("bengine_dockspace");
|
||||
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), ImGuiDockNodeFlags_None);
|
||||
|
||||
if (updateDockspace) {
|
||||
updateDockspace = false;
|
||||
|
||||
ImGui::DockBuilderRemoveNode(dockspace_id);
|
||||
ImGui::DockBuilderAddNode(dockspace_id, ImGuiDockNodeFlags_DockSpace);
|
||||
ImGui::DockBuilderSetNodeSize(dockspace_id, viewport->Size);
|
||||
|
||||
ImGuiID dock_main_id = dockspace_id;
|
||||
|
||||
const ImGuiID dock_id_left =
|
||||
ImGui::DockBuilderSplitNode(dock_main_id, ImGuiDir_Left, 0.2f, nullptr, &dock_main_id);
|
||||
const ImGuiID dock_id_right =
|
||||
ImGui::DockBuilderSplitNode(dock_main_id, ImGuiDir_Right, 0.25f, nullptr, &dock_main_id);
|
||||
|
||||
ImGui::DockBuilderDockWindow("Hierarchy", dock_id_left);
|
||||
ImGui::DockBuilderDockWindow("Inspector", dock_id_right);
|
||||
ImGui::DockBuilderDockWindow("Scene", dock_main_id);
|
||||
|
||||
ImGui::DockBuilderFinish(dockspace_id);
|
||||
}
|
||||
|
||||
for (const auto &panel: uiPanels | std::views::values) {
|
||||
if (!panel) continue;
|
||||
panel->update(ctx);
|
||||
}
|
||||
|
||||
ImGui::End(); // dockspace
|
||||
}
|
||||
ImGui::Render();
|
||||
}
|
||||
|
||||
void UIManager::draw() {
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
}
|
||||
42
src/UIManager.h
Normal file
42
src/UIManager.h
Normal file
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// Created by slinky on 5/11/26.
|
||||
//
|
||||
|
||||
#ifndef B_ENGINE_UIMANAGER_H
|
||||
#define B_ENGINE_UIMANAGER_H
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <functional>
|
||||
|
||||
#include "EditorContext.h"
|
||||
#include "GLFW/glfw3.h"
|
||||
#include "ui/IUIPanel.h"
|
||||
|
||||
class UIManager {
|
||||
public:
|
||||
static void init(GLFWwindow* _window);
|
||||
static void update(EditorContext& ctx);
|
||||
static void draw();
|
||||
|
||||
template<typename T = IUIPanel, typename... Args>
|
||||
static T* add_ui_panel(std::string_view id, Args &&... args) {
|
||||
uiPanels[std::string(id)] = std::make_shared<T>(std::forward<Args>(args)...);
|
||||
return dynamic_cast<T*>(uiPanels[std::string(id)].get());
|
||||
}
|
||||
|
||||
static std::shared_ptr<IUIPanel> get_ui_panel(std::string_view id) {
|
||||
if (const auto it = uiPanels.find(std::string(id)); it != uiPanels.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
private:
|
||||
static bool updateDockspace;
|
||||
static GLFWwindow* window;
|
||||
static std::unordered_map<std::string, std::shared_ptr<IUIPanel>> uiPanels;
|
||||
};
|
||||
|
||||
|
||||
#endif //B_ENGINE_UIMANAGER_H
|
||||
147
src/imgui/imconfig.h
Normal file
147
src/imgui/imconfig.h
Normal file
@@ -0,0 +1,147 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// DEAR IMGUI COMPILE-TIME OPTIONS
|
||||
// Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure.
|
||||
// You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions.
|
||||
//-----------------------------------------------------------------------------
|
||||
// A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/rebased branch with your modifications to it)
|
||||
// B) or '#define IMGUI_USER_CONFIG "my_imgui_config.h"' in your project and then add directives in your own file without touching this template.
|
||||
//-----------------------------------------------------------------------------
|
||||
// You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp
|
||||
// files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures.
|
||||
// Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts.
|
||||
// Call IMGUI_CHECKVERSION() from your .cpp file to verify that the data structures your files are using are matching the ones imgui.cpp is using.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
//---- Define assertion handler. Defaults to calling assert().
|
||||
// - If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement.
|
||||
// - Compiling with NDEBUG will usually strip out assert() to nothing, which is NOT recommended because we use asserts to notify of programmer mistakes.
|
||||
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
|
||||
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
|
||||
|
||||
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
|
||||
// Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
|
||||
// - Windows DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
|
||||
// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
|
||||
//#define IMGUI_API __declspec(dllexport) // MSVC Windows: DLL export
|
||||
//#define IMGUI_API __declspec(dllimport) // MSVC Windows: DLL import
|
||||
//#define IMGUI_API __attribute__((visibility("default"))) // GCC/Clang: override visibility when set is hidden
|
||||
|
||||
//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to clean your code of obsolete function/names.
|
||||
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
|
||||
//---- Disable all of Dear ImGui or don't implement standard windows/tools.
|
||||
// It is very strongly recommended to NOT disable the demo windows and debug tool during development. They are extremely useful in day to day work. Please read comments in imgui_demo.cpp.
|
||||
//#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty.
|
||||
//#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty.
|
||||
//#define IMGUI_DISABLE_DEBUG_TOOLS // Disable metrics/debugger and other debug tools: ShowMetricsWindow(), ShowDebugLogWindow() and ShowIDStackToolWindow() will be empty.
|
||||
|
||||
//---- Don't implement some functions to reduce linkage requirements.
|
||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a)
|
||||
//#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW)
|
||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a)
|
||||
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, IME).
|
||||
//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
|
||||
//#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS // Don't implement default platform_io.Platform_OpenInShellFn() handler (Win32: ShellExecute(), require shell32.lib/.a, Mac/Linux: use system("")).
|
||||
//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
|
||||
//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
|
||||
//#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
|
||||
//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
|
||||
//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
|
||||
//#define IMGUI_DISABLE_DEFAULT_FONT // Disable default embedded fonts (ProggyClean/ProggyForever), remove ~9 KB + ~14 KB from output binary. AddFontDefaultXXX() functions will assert.
|
||||
//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available
|
||||
|
||||
//---- Enable Test Engine / Automation features.
|
||||
//#define IMGUI_ENABLE_TEST_ENGINE // Enable imgui_test_engine hooks. Generally set automatically by include "imgui_te_config.h", see Test Engine for details.
|
||||
|
||||
//---- Include imgui_user.h at the end of imgui.h as a convenience
|
||||
// May be convenient for some users to only explicitly include vanilla imgui.h and have extra stuff included.
|
||||
//#define IMGUI_INCLUDE_IMGUI_USER_H
|
||||
//#define IMGUI_USER_H_FILENAME "my_folder/my_imgui_user.h"
|
||||
|
||||
//---- Pack vertex colors as BGRA8 instead of RGBA8 (to avoid converting from one to another). Need dedicated backend support.
|
||||
//#define IMGUI_USE_BGRA_PACKED_COLOR
|
||||
|
||||
//---- Use legacy CRC32-adler tables (used before 1.91.6), in order to preserve old .ini data that you cannot afford to invalidate.
|
||||
//#define IMGUI_USE_LEGACY_CRC32_ADLER
|
||||
|
||||
//---- Use 32-bit for ImWchar (default is 16-bit) to support Unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
|
||||
//#define IMGUI_USE_WCHAR32
|
||||
|
||||
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
|
||||
// By default the embedded implementations are declared static and not available outside of Dear ImGui sources files.
|
||||
//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
|
||||
//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
|
||||
//#define IMGUI_STB_SPRINTF_FILENAME "my_folder/stb_sprintf.h" // only used if IMGUI_USE_STB_SPRINTF is defined.
|
||||
//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
|
||||
//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
|
||||
//#define IMGUI_DISABLE_STB_SPRINTF_IMPLEMENTATION // only disabled if IMGUI_USE_STB_SPRINTF is defined.
|
||||
|
||||
//---- Use stb_sprintf.h for a faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined)
|
||||
// Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by stb_sprintf.h.
|
||||
//#define IMGUI_USE_STB_SPRINTF
|
||||
|
||||
//---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui)
|
||||
// Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided).
|
||||
// Note that imgui_freetype.cpp may be used _without_ this define, if you manually call ImFontAtlas::SetFontLoader(). The define is simply a convenience.
|
||||
// On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'.
|
||||
//#define IMGUI_ENABLE_FREETYPE
|
||||
|
||||
//---- Use FreeType + plutosvg or lunasvg to render OpenType SVG fonts (SVGinOT)
|
||||
// Only works in combination with IMGUI_ENABLE_FREETYPE.
|
||||
// - plutosvg is currently easier to install, as e.g. it is part of vcpkg. It will support more fonts and may load them faster. See misc/freetype/README for instructions.
|
||||
// - Both require headers to be available in the include path + program to be linked with the library code (not provided).
|
||||
// - (note: lunasvg implementation is based on Freetype's rsvg-port.c which is licensed under CeCILL-C Free Software License Agreement)
|
||||
//#define IMGUI_ENABLE_FREETYPE_PLUTOSVG
|
||||
//#define IMGUI_ENABLE_FREETYPE_LUNASVG
|
||||
|
||||
//---- Use stb_truetype to build and rasterize the font atlas (default)
|
||||
// The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend.
|
||||
//#define IMGUI_ENABLE_STB_TRUETYPE
|
||||
|
||||
//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
|
||||
// This will be inlined as part of ImVec2 and ImVec4 class declarations.
|
||||
/*
|
||||
#define IM_VEC2_CLASS_EXTRA \
|
||||
constexpr ImVec2(const MyVec2& f) : x(f.x), y(f.y) {} \
|
||||
operator MyVec2() const { return MyVec2(x,y); }
|
||||
|
||||
#define IM_VEC4_CLASS_EXTRA \
|
||||
constexpr ImVec4(const MyVec4& f) : x(f.x), y(f.y), z(f.z), w(f.w) {} \
|
||||
operator MyVec4() const { return MyVec4(x,y,z,w); }
|
||||
*/
|
||||
//---- ...Or use Dear ImGui's own very basic math operators.
|
||||
//#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
|
||||
//---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices.
|
||||
// Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices).
|
||||
// Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer.
|
||||
// Read about ImGuiBackendFlags_RendererHasVtxOffset for details.
|
||||
//#define ImDrawIdx unsigned int
|
||||
|
||||
//---- Override ImDrawCallback signature (will need to modify renderer backends accordingly)
|
||||
//struct ImDrawList;
|
||||
//struct ImDrawCmd;
|
||||
//typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data);
|
||||
//#define ImDrawCallback MyImDrawCallback
|
||||
|
||||
//---- Debug Tools: Macro to break in Debugger (we provide a default implementation of this in the codebase)
|
||||
// (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.)
|
||||
//#define IM_DEBUG_BREAK IM_ASSERT(0)
|
||||
//#define IM_DEBUG_BREAK __debugbreak()
|
||||
|
||||
//---- Debug Tools: Enable highlight ID conflicts _before_ hovering items. When io.ConfigDebugHighlightIdConflicts is set.
|
||||
// (THIS WILL SLOW DOWN DEAR IMGUI. Only use occasionally and disable after use)
|
||||
//#define IMGUI_DEBUG_HIGHLIGHT_ALL_ID_CONFLICTS
|
||||
|
||||
//---- Debug Tools: Enable slower asserts
|
||||
//#define IMGUI_DEBUG_PARANOID
|
||||
|
||||
//---- Tip: You can add extra functions within the ImGui:: namespace from anywhere (e.g. your own sources/header files)
|
||||
/*
|
||||
namespace ImGui
|
||||
{
|
||||
void MyFunction(const char* name, MyMatrix44* mtx);
|
||||
}
|
||||
*/
|
||||
24335
src/imgui/imgui.cpp
Normal file
24335
src/imgui/imgui.cpp
Normal file
File diff suppressed because it is too large
Load Diff
4516
src/imgui/imgui.h
Normal file
4516
src/imgui/imgui.h
Normal file
File diff suppressed because it is too large
Load Diff
11442
src/imgui/imgui_demo.cpp
Normal file
11442
src/imgui/imgui_demo.cpp
Normal file
File diff suppressed because it is too large
Load Diff
6786
src/imgui/imgui_draw.cpp
Normal file
6786
src/imgui/imgui_draw.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1727
src/imgui/imgui_impl_glfw.cpp
Normal file
1727
src/imgui/imgui_impl_glfw.cpp
Normal file
File diff suppressed because it is too large
Load Diff
73
src/imgui/imgui_impl_glfw.h
Normal file
73
src/imgui/imgui_impl_glfw.h
Normal file
@@ -0,0 +1,73 @@
|
||||
// dear imgui: Platform Backend for GLFW
|
||||
// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan, WebGPU..)
|
||||
// (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
|
||||
// (Requires: GLFW 3.0+. Prefer GLFW 3.3+/3.4+ for full feature support.)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Platform: Clipboard support.
|
||||
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
|
||||
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values are obsolete since 1.87 and not supported since 1.91.5]
|
||||
// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
||||
// [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors) with GLFW 3.1+. Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
// [X] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
|
||||
// [X] Multiple Dear ImGui contexts support.
|
||||
// Missing features or Issues:
|
||||
// [ ] Platform: Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround.
|
||||
// [ ] Platform: Missing ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress cursors.
|
||||
// [ ] Platform: Multi-viewport: Missing ImGuiBackendFlags_HasParentViewport support. The viewport->ParentViewportID field is ignored, and therefore io.ConfigViewportsNoDefaultParent has no effect either.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
struct GLFWwindow;
|
||||
struct GLFWmonitor;
|
||||
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks);
|
||||
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks);
|
||||
IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool install_callbacks);
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame();
|
||||
|
||||
// Emscripten related initialization phase methods (call after ImGui_ImplGlfw_InitForOpenGL)
|
||||
#ifdef __EMSCRIPTEN__
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_InstallEmscriptenCallbacks(GLFWwindow* window, const char* canvas_selector);
|
||||
//static inline void ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_selector) { ImGui_ImplGlfw_InstallEmscriptenCallbacks(nullptr, canvas_selector); } } // Renamed in 1.91.0
|
||||
#endif
|
||||
|
||||
// GLFW callbacks install
|
||||
// - When calling Init with 'install_callbacks=true': ImGui_ImplGlfw_InstallCallbacks() is called. GLFW callbacks will be installed for you. They will chain-call user's previously installed callbacks, if any.
|
||||
// - When calling Init with 'install_callbacks=false': GLFW callbacks won't be installed. You will need to call individual function yourself from your own GLFW callbacks.
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window);
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_RestoreCallbacks(GLFWwindow* window);
|
||||
|
||||
// GLFW callbacks options:
|
||||
// - Set 'chain_for_all_windows=true' to enable chaining callbacks for all windows (including secondary viewports created by backends or by user)
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_SetCallbacksChainForAllWindows(bool chain_for_all_windows);
|
||||
|
||||
// GLFW callbacks (individual callbacks to call yourself if you didn't install callbacks)
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused); // Since 1.84
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered); // Since 1.84
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y); // Since 1.87
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c);
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor* monitor, int event);
|
||||
|
||||
// GLFW helpers
|
||||
IMGUI_IMPL_API void ImGui_ImplGlfw_Sleep(int milliseconds);
|
||||
IMGUI_IMPL_API float ImGui_ImplGlfw_GetContentScaleForWindow(GLFWwindow* window);
|
||||
IMGUI_IMPL_API float ImGui_ImplGlfw_GetContentScaleForMonitor(GLFWmonitor* monitor);
|
||||
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
1150
src/imgui/imgui_impl_opengl3.cpp
Normal file
1150
src/imgui/imgui_impl_opengl3.cpp
Normal file
File diff suppressed because it is too large
Load Diff
69
src/imgui/imgui_impl_opengl3.h
Normal file
69
src/imgui/imgui_impl_opengl3.h
Normal file
@@ -0,0 +1,69 @@
|
||||
// dear imgui: Renderer Backend for modern OpenGL with shaders / programmatic pipeline
|
||||
// - Desktop GL: 2.x 3.x 4.x
|
||||
// - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0)
|
||||
// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture as texture identifier. Read the FAQ about ImTextureID/ImTextureRef!
|
||||
// [x] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset) [Desktop OpenGL only!]
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas (ImGuiBackendFlags_RendererHasTextures).
|
||||
// [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
|
||||
|
||||
// About WebGL/ES:
|
||||
// - You need to '#define IMGUI_IMPL_OPENGL_ES2' or '#define IMGUI_IMPL_OPENGL_ES3' to use WebGL or OpenGL ES.
|
||||
// - This is done automatically on iOS, Android and Emscripten targets.
|
||||
// - For other targets, the define needs to be visible from the imgui_impl_opengl3.cpp compilation unit. If unsure, define globally or in imconfig.h.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
// About GLSL version:
|
||||
// The 'glsl_version' initialization parameter should be nullptr (default) or a "#version XXX" string.
|
||||
// On computer platform the GLSL version default to "#version 130". On OpenGL ES 3 platform it defaults to "#version 300 es"
|
||||
// Only override if your GL version doesn't handle this GLSL version. See GLSL version table at the top of imgui_impl_opengl3.cpp.
|
||||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = nullptr);
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL3_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL3_NewFrame();
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data);
|
||||
|
||||
// (Optional) Called by Init/NewFrame/Shutdown
|
||||
IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateDeviceObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects();
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL3_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
// Configuration flags to add in your imconfig file:
|
||||
//#define IMGUI_IMPL_OPENGL_ES2 // Enable ES 2 (Auto-detected on Emscripten)
|
||||
//#define IMGUI_IMPL_OPENGL_ES3 // Enable ES 3 (Auto-detected on iOS/Android)
|
||||
|
||||
// You can explicitly select GLES2 or GLES3 API by using one of the '#define IMGUI_IMPL_OPENGL_LOADER_XXX' in imconfig.h or compiler command-line.
|
||||
#if !defined(IMGUI_IMPL_OPENGL_ES2) \
|
||||
&& !defined(IMGUI_IMPL_OPENGL_ES3)
|
||||
|
||||
// Try to detect GLES on matching platforms
|
||||
#if defined(__APPLE__)
|
||||
#include <TargetConditionals.h>
|
||||
#endif
|
||||
#if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV)) || (defined(__ANDROID__))
|
||||
#define IMGUI_IMPL_OPENGL_ES3 // iOS, Android -> GL ES 3, "#version 300 es"
|
||||
#elif defined(__EMSCRIPTEN__) || defined(__amigaos4__)
|
||||
#define IMGUI_IMPL_OPENGL_ES2 // Emscripten -> GL ES 2, "#version 100"
|
||||
#else
|
||||
// Otherwise imgui_impl_opengl3_loader.h will be used.
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
958
src/imgui/imgui_impl_opengl3_loader.h
Normal file
958
src/imgui/imgui_impl_opengl3_loader.h
Normal file
@@ -0,0 +1,958 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// About imgui_impl_opengl3_loader.h:
|
||||
//
|
||||
// We embed our own OpenGL loader to not require user to provide their own or to have to use ours,
|
||||
// which proved to be endless problems for users.
|
||||
// Our loader is custom-generated, based on gl3w but automatically filtered to only include
|
||||
// enums/functions that we use in our imgui_impl_opengl3.cpp source file in order to be small.
|
||||
//
|
||||
// YOU SHOULD NOT NEED TO INCLUDE/USE THIS DIRECTLY. THIS IS USED BY imgui_impl_opengl3.cpp ONLY.
|
||||
// THE REST OF YOUR APP SHOULD USE A DIFFERENT GL LOADER: ANY GL LOADER OF YOUR CHOICE.
|
||||
//
|
||||
// IF YOU GET BUILD ERRORS IN THIS FILE (commonly macro redefinitions or function redefinitions):
|
||||
// IT LIKELY MEANS THAT YOU ARE BUILDING 'imgui_impl_opengl3.cpp' OR INCLUDING 'imgui_impl_opengl3_loader.h'
|
||||
// IN THE SAME COMPILATION UNIT AS ONE OF YOUR FILE WHICH IS USING A THIRD-PARTY OPENGL LOADER.
|
||||
// (e.g. COULD HAPPEN IF YOU ARE DOING A UNITY/JUMBO BUILD, OR INCLUDING .CPP FILES FROM OTHERS)
|
||||
// YOU SHOULD NOT BUILD BOTH IN THE SAME COMPILATION UNIT.
|
||||
// BUT IF YOU REALLY WANT TO, you can '#define IMGUI_IMPL_OPENGL_LOADER_CUSTOM' and imgui_impl_opengl3.cpp
|
||||
// WILL NOT BE USING OUR LOADER, AND INSTEAD EXPECT ANOTHER/YOUR LOADER TO BE AVAILABLE IN THE COMPILATION UNIT.
|
||||
//
|
||||
// Regenerate with:
|
||||
// python3 gl3w_gen.py --output ../imgui/backends/imgui_impl_opengl3_loader.h --ref ../imgui/backends/imgui_impl_opengl3.cpp ./extra_symbols.txt
|
||||
//
|
||||
// More info:
|
||||
// https://github.com/dearimgui/gl3w_stripped
|
||||
// https://github.com/ocornut/imgui/issues/4445
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* This file was generated with gl3w_gen.py, part of imgl3w
|
||||
* (hosted at https://github.com/dearimgui/gl3w_stripped)
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __gl3w_h_
|
||||
#define __gl3w_h_
|
||||
|
||||
// Adapted from KHR/khrplatform.h to avoid including entire file.
|
||||
#ifndef __khrplatform_h_
|
||||
typedef float khronos_float_t;
|
||||
typedef signed char khronos_int8_t;
|
||||
typedef unsigned char khronos_uint8_t;
|
||||
typedef signed short int khronos_int16_t;
|
||||
typedef unsigned short int khronos_uint16_t;
|
||||
#ifdef _WIN64
|
||||
typedef signed long long int khronos_intptr_t;
|
||||
typedef signed long long int khronos_ssize_t;
|
||||
#else
|
||||
typedef signed long int khronos_intptr_t;
|
||||
typedef signed long int khronos_ssize_t;
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
typedef signed __int64 khronos_int64_t;
|
||||
typedef unsigned __int64 khronos_uint64_t;
|
||||
#elif (defined(__clang__) || defined(__GNUC__)) && (__cplusplus < 201100)
|
||||
#include <stdint.h>
|
||||
typedef int64_t khronos_int64_t;
|
||||
typedef uint64_t khronos_uint64_t;
|
||||
#else
|
||||
typedef signed long long khronos_int64_t;
|
||||
typedef unsigned long long khronos_uint64_t;
|
||||
#endif
|
||||
#endif // __khrplatform_h_
|
||||
|
||||
#ifndef __gl_glcorearb_h_
|
||||
#define __gl_glcorearb_h_ 1
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/*
|
||||
** Copyright 2013-2020 The Khronos Group Inc.
|
||||
** SPDX-License-Identifier: MIT
|
||||
**
|
||||
** This header is generated from the Khronos OpenGL / OpenGL ES XML
|
||||
** API Registry. The current version of the Registry, generator scripts
|
||||
** used to make the header, and the header can be found at
|
||||
** https://github.com/KhronosGroup/OpenGL-Registry
|
||||
*/
|
||||
#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#ifndef APIENTRY
|
||||
#define APIENTRY
|
||||
#endif
|
||||
#ifndef APIENTRYP
|
||||
#define APIENTRYP APIENTRY *
|
||||
#endif
|
||||
#ifndef GLAPI
|
||||
#define GLAPI extern
|
||||
#endif
|
||||
/* glcorearb.h is for use with OpenGL core profile implementations.
|
||||
** It should should be placed in the same directory as gl.h and
|
||||
** included as <GL/glcorearb.h>.
|
||||
**
|
||||
** glcorearb.h includes only APIs in the latest OpenGL core profile
|
||||
** implementation together with APIs in newer ARB extensions which
|
||||
** can be supported by the core profile. It does not, and never will
|
||||
** include functionality removed from the core profile, such as
|
||||
** fixed-function vertex and fragment processing.
|
||||
**
|
||||
** Do not #include both <GL/glcorearb.h> and either of <GL/gl.h> or
|
||||
** <GL/glext.h> in the same source file.
|
||||
*/
|
||||
/* Generated C header for:
|
||||
* API: gl
|
||||
* Profile: core
|
||||
* Versions considered: .*
|
||||
* Versions emitted: .*
|
||||
* Default extensions included: glcore
|
||||
* Additional extensions included: _nomatch_^
|
||||
* Extensions removed: _nomatch_^
|
||||
*/
|
||||
#ifndef GL_VERSION_1_0
|
||||
typedef void GLvoid;
|
||||
typedef unsigned int GLenum;
|
||||
|
||||
typedef khronos_float_t GLfloat;
|
||||
typedef int GLint;
|
||||
typedef int GLsizei;
|
||||
typedef unsigned int GLbitfield;
|
||||
typedef double GLdouble;
|
||||
typedef unsigned int GLuint;
|
||||
typedef unsigned char GLboolean;
|
||||
typedef khronos_uint8_t GLubyte;
|
||||
#define GL_COLOR_BUFFER_BIT 0x00004000
|
||||
#define GL_FALSE 0
|
||||
#define GL_TRUE 1
|
||||
#define GL_TRIANGLES 0x0004
|
||||
#define GL_ONE 1
|
||||
#define GL_SRC_ALPHA 0x0302
|
||||
#define GL_ONE_MINUS_SRC_ALPHA 0x0303
|
||||
#define GL_FRONT 0x0404
|
||||
#define GL_BACK 0x0405
|
||||
#define GL_FRONT_AND_BACK 0x0408
|
||||
#define GL_POLYGON_MODE 0x0B40
|
||||
#define GL_CULL_FACE 0x0B44
|
||||
#define GL_DEPTH_TEST 0x0B71
|
||||
#define GL_STENCIL_TEST 0x0B90
|
||||
#define GL_VIEWPORT 0x0BA2
|
||||
#define GL_BLEND 0x0BE2
|
||||
#define GL_SCISSOR_BOX 0x0C10
|
||||
#define GL_SCISSOR_TEST 0x0C11
|
||||
#define GL_UNPACK_ROW_LENGTH 0x0CF2
|
||||
#define GL_UNPACK_ALIGNMENT 0x0CF5
|
||||
#define GL_PACK_ALIGNMENT 0x0D05
|
||||
#define GL_MAX_TEXTURE_SIZE 0x0D33
|
||||
#define GL_TEXTURE_2D 0x0DE1
|
||||
#define GL_UNSIGNED_BYTE 0x1401
|
||||
#define GL_UNSIGNED_SHORT 0x1403
|
||||
#define GL_UNSIGNED_INT 0x1405
|
||||
#define GL_FLOAT 0x1406
|
||||
#define GL_RGBA 0x1908
|
||||
#define GL_FILL 0x1B02
|
||||
#define GL_VENDOR 0x1F00
|
||||
#define GL_RENDERER 0x1F01
|
||||
#define GL_VERSION 0x1F02
|
||||
#define GL_EXTENSIONS 0x1F03
|
||||
#define GL_NEAREST 0x2600
|
||||
#define GL_LINEAR 0x2601
|
||||
#define GL_TEXTURE_MAG_FILTER 0x2800
|
||||
#define GL_TEXTURE_MIN_FILTER 0x2801
|
||||
#define GL_TEXTURE_WRAP_S 0x2802
|
||||
#define GL_TEXTURE_WRAP_T 0x2803
|
||||
#define GL_REPEAT 0x2901
|
||||
typedef void (APIENTRYP PFNGLPOLYGONMODEPROC) (GLenum face, GLenum mode);
|
||||
typedef void (APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
typedef void (APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
|
||||
typedef void (APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
|
||||
typedef void (APIENTRYP PFNGLCLEARPROC) (GLbitfield mask);
|
||||
typedef void (APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
|
||||
typedef void (APIENTRYP PFNGLDISABLEPROC) (GLenum cap);
|
||||
typedef void (APIENTRYP PFNGLENABLEPROC) (GLenum cap);
|
||||
typedef void (APIENTRYP PFNGLFLUSHPROC) (void);
|
||||
typedef void (APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param);
|
||||
typedef void (APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
|
||||
typedef GLenum (APIENTRYP PFNGLGETERRORPROC) (void);
|
||||
typedef void (APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *data);
|
||||
typedef const GLubyte *(APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
|
||||
typedef GLboolean (APIENTRYP PFNGLISENABLEDPROC) (GLenum cap);
|
||||
typedef void (APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glPolygonMode (GLenum face, GLenum mode);
|
||||
GLAPI void APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
GLAPI void APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
|
||||
GLAPI void APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
|
||||
GLAPI void APIENTRY glClear (GLbitfield mask);
|
||||
GLAPI void APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
|
||||
GLAPI void APIENTRY glDisable (GLenum cap);
|
||||
GLAPI void APIENTRY glEnable (GLenum cap);
|
||||
GLAPI void APIENTRY glFlush (void);
|
||||
GLAPI void APIENTRY glPixelStorei (GLenum pname, GLint param);
|
||||
GLAPI void APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
|
||||
GLAPI GLenum APIENTRY glGetError (void);
|
||||
GLAPI void APIENTRY glGetIntegerv (GLenum pname, GLint *data);
|
||||
GLAPI const GLubyte *APIENTRY glGetString (GLenum name);
|
||||
GLAPI GLboolean APIENTRY glIsEnabled (GLenum cap);
|
||||
GLAPI void APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
#endif
|
||||
#endif /* GL_VERSION_1_0 */
|
||||
#ifndef GL_VERSION_1_1
|
||||
typedef khronos_float_t GLclampf;
|
||||
typedef double GLclampd;
|
||||
#define GL_TEXTURE_BINDING_2D 0x8069
|
||||
typedef void (APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices);
|
||||
typedef void (APIENTRYP PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
|
||||
typedef void (APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture);
|
||||
typedef void (APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures);
|
||||
typedef void (APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices);
|
||||
GLAPI void APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
|
||||
GLAPI void APIENTRY glBindTexture (GLenum target, GLuint texture);
|
||||
GLAPI void APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures);
|
||||
GLAPI void APIENTRY glGenTextures (GLsizei n, GLuint *textures);
|
||||
#endif
|
||||
#endif /* GL_VERSION_1_1 */
|
||||
#ifndef GL_VERSION_1_2
|
||||
#define GL_CLAMP_TO_EDGE 0x812F
|
||||
#endif /* GL_VERSION_1_2 */
|
||||
#ifndef GL_VERSION_1_3
|
||||
#define GL_TEXTURE0 0x84C0
|
||||
#define GL_ACTIVE_TEXTURE 0x84E0
|
||||
typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glActiveTexture (GLenum texture);
|
||||
#endif
|
||||
#endif /* GL_VERSION_1_3 */
|
||||
#ifndef GL_VERSION_1_4
|
||||
#define GL_BLEND_DST_RGB 0x80C8
|
||||
#define GL_BLEND_SRC_RGB 0x80C9
|
||||
#define GL_BLEND_DST_ALPHA 0x80CA
|
||||
#define GL_BLEND_SRC_ALPHA 0x80CB
|
||||
#define GL_FUNC_ADD 0x8006
|
||||
typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
|
||||
typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
|
||||
GLAPI void APIENTRY glBlendEquation (GLenum mode);
|
||||
#endif
|
||||
#endif /* GL_VERSION_1_4 */
|
||||
#ifndef GL_VERSION_1_5
|
||||
typedef khronos_ssize_t GLsizeiptr;
|
||||
typedef khronos_intptr_t GLintptr;
|
||||
#define GL_ARRAY_BUFFER 0x8892
|
||||
#define GL_ELEMENT_ARRAY_BUFFER 0x8893
|
||||
#define GL_ARRAY_BUFFER_BINDING 0x8894
|
||||
#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
|
||||
#define GL_STREAM_DRAW 0x88E0
|
||||
typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
|
||||
typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
|
||||
typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
|
||||
typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
|
||||
typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glBindBuffer (GLenum target, GLuint buffer);
|
||||
GLAPI void APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers);
|
||||
GLAPI void APIENTRY glGenBuffers (GLsizei n, GLuint *buffers);
|
||||
GLAPI void APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
|
||||
GLAPI void APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
|
||||
#endif
|
||||
#endif /* GL_VERSION_1_5 */
|
||||
#ifndef GL_VERSION_2_0
|
||||
typedef char GLchar;
|
||||
typedef khronos_int16_t GLshort;
|
||||
typedef khronos_int8_t GLbyte;
|
||||
typedef khronos_uint16_t GLushort;
|
||||
#define GL_BLEND_EQUATION_RGB 0x8009
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
|
||||
#define GL_BLEND_EQUATION_ALPHA 0x883D
|
||||
#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
|
||||
#define GL_FRAGMENT_SHADER 0x8B30
|
||||
#define GL_VERTEX_SHADER 0x8B31
|
||||
#define GL_COMPILE_STATUS 0x8B81
|
||||
#define GL_LINK_STATUS 0x8B82
|
||||
#define GL_INFO_LOG_LENGTH 0x8B84
|
||||
#define GL_CURRENT_PROGRAM 0x8B8D
|
||||
#define GL_UPPER_LEFT 0x8CA2
|
||||
typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);
|
||||
typedef void (APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
|
||||
typedef void (APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
|
||||
typedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
|
||||
typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
|
||||
typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);
|
||||
typedef void (APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
|
||||
typedef void (APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
|
||||
typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
|
||||
typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
|
||||
typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);
|
||||
typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
|
||||
typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
|
||||
typedef void (APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
|
||||
typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
|
||||
typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
|
||||
typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params);
|
||||
typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void **pointer);
|
||||
typedef GLboolean (APIENTRYP PFNGLISPROGRAMPROC) (GLuint program);
|
||||
typedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
|
||||
typedef void (APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
|
||||
typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
|
||||
typedef void (APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
|
||||
typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
|
||||
typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
|
||||
GLAPI void APIENTRY glAttachShader (GLuint program, GLuint shader);
|
||||
GLAPI void APIENTRY glCompileShader (GLuint shader);
|
||||
GLAPI GLuint APIENTRY glCreateProgram (void);
|
||||
GLAPI GLuint APIENTRY glCreateShader (GLenum type);
|
||||
GLAPI void APIENTRY glDeleteProgram (GLuint program);
|
||||
GLAPI void APIENTRY glDeleteShader (GLuint shader);
|
||||
GLAPI void APIENTRY glDetachShader (GLuint program, GLuint shader);
|
||||
GLAPI void APIENTRY glDisableVertexAttribArray (GLuint index);
|
||||
GLAPI void APIENTRY glEnableVertexAttribArray (GLuint index);
|
||||
GLAPI GLint APIENTRY glGetAttribLocation (GLuint program, const GLchar *name);
|
||||
GLAPI void APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params);
|
||||
GLAPI void APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
|
||||
GLAPI void APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params);
|
||||
GLAPI void APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
|
||||
GLAPI GLint APIENTRY glGetUniformLocation (GLuint program, const GLchar *name);
|
||||
GLAPI void APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params);
|
||||
GLAPI void APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer);
|
||||
GLAPI GLboolean APIENTRY glIsProgram (GLuint program);
|
||||
GLAPI void APIENTRY glLinkProgram (GLuint program);
|
||||
GLAPI void APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
|
||||
GLAPI void APIENTRY glUseProgram (GLuint program);
|
||||
GLAPI void APIENTRY glUniform1i (GLint location, GLint v0);
|
||||
GLAPI void APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
|
||||
GLAPI void APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
|
||||
#endif
|
||||
#endif /* GL_VERSION_2_0 */
|
||||
#ifndef GL_VERSION_2_1
|
||||
#define GL_PIXEL_UNPACK_BUFFER 0x88EC
|
||||
#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
|
||||
#endif /* GL_VERSION_2_1 */
|
||||
#ifndef GL_VERSION_3_0
|
||||
typedef khronos_uint16_t GLhalf;
|
||||
#define GL_MAJOR_VERSION 0x821B
|
||||
#define GL_MINOR_VERSION 0x821C
|
||||
#define GL_NUM_EXTENSIONS 0x821D
|
||||
#define GL_FRAMEBUFFER_SRGB 0x8DB9
|
||||
#define GL_VERTEX_ARRAY_BINDING 0x85B5
|
||||
typedef void (APIENTRYP PFNGLGETBOOLEANI_VPROC) (GLenum target, GLuint index, GLboolean *data);
|
||||
typedef void (APIENTRYP PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint *data);
|
||||
typedef const GLubyte *(APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index);
|
||||
typedef void (APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array);
|
||||
typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays);
|
||||
typedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI const GLubyte *APIENTRY glGetStringi (GLenum name, GLuint index);
|
||||
GLAPI void APIENTRY glBindVertexArray (GLuint array);
|
||||
GLAPI void APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint *arrays);
|
||||
GLAPI void APIENTRY glGenVertexArrays (GLsizei n, GLuint *arrays);
|
||||
#endif
|
||||
#endif /* GL_VERSION_3_0 */
|
||||
#ifndef GL_VERSION_3_1
|
||||
#define GL_VERSION_3_1 1
|
||||
#define GL_PRIMITIVE_RESTART 0x8F9D
|
||||
#endif /* GL_VERSION_3_1 */
|
||||
#ifndef GL_VERSION_3_2
|
||||
#define GL_VERSION_3_2 1
|
||||
typedef struct __GLsync *GLsync;
|
||||
typedef khronos_uint64_t GLuint64;
|
||||
typedef khronos_int64_t GLint64;
|
||||
#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
|
||||
#define GL_CONTEXT_PROFILE_MASK 0x9126
|
||||
typedef void (APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
|
||||
typedef void (APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
|
||||
#endif
|
||||
#endif /* GL_VERSION_3_2 */
|
||||
#ifndef GL_VERSION_3_3
|
||||
#define GL_VERSION_3_3 1
|
||||
#define GL_SAMPLER_BINDING 0x8919
|
||||
typedef void (APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers);
|
||||
typedef void (APIENTRYP PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint *samplers);
|
||||
typedef void (APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler);
|
||||
typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glGenSamplers (GLsizei count, GLuint *samplers);
|
||||
GLAPI void APIENTRY glDeleteSamplers (GLsizei count, const GLuint *samplers);
|
||||
GLAPI void APIENTRY glBindSampler (GLuint unit, GLuint sampler);
|
||||
GLAPI void APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param);
|
||||
#endif
|
||||
#endif /* GL_VERSION_3_3 */
|
||||
#ifndef GL_VERSION_4_1
|
||||
typedef void (APIENTRYP PFNGLGETFLOATI_VPROC) (GLenum target, GLuint index, GLfloat *data);
|
||||
typedef void (APIENTRYP PFNGLGETDOUBLEI_VPROC) (GLenum target, GLuint index, GLdouble *data);
|
||||
#endif /* GL_VERSION_4_1 */
|
||||
#ifndef GL_VERSION_4_3
|
||||
typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
|
||||
#endif /* GL_VERSION_4_3 */
|
||||
#ifndef GL_VERSION_4_5
|
||||
#define GL_CLIP_ORIGIN 0x935C
|
||||
typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKI_VPROC) (GLuint xfb, GLenum pname, GLuint index, GLint *param);
|
||||
typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKI64_VPROC) (GLuint xfb, GLenum pname, GLuint index, GLint64 *param);
|
||||
#endif /* GL_VERSION_4_5 */
|
||||
#ifndef GL_ARB_bindless_texture
|
||||
typedef khronos_uint64_t GLuint64EXT;
|
||||
#endif /* GL_ARB_bindless_texture */
|
||||
#ifndef GL_ARB_cl_event
|
||||
struct _cl_context;
|
||||
struct _cl_event;
|
||||
#endif /* GL_ARB_cl_event */
|
||||
#ifndef GL_ARB_clip_control
|
||||
#define GL_ARB_clip_control 1
|
||||
#endif /* GL_ARB_clip_control */
|
||||
#ifndef GL_ARB_debug_output
|
||||
typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
|
||||
#endif /* GL_ARB_debug_output */
|
||||
#ifndef GL_EXT_EGL_image_storage
|
||||
typedef void *GLeglImageOES;
|
||||
#endif /* GL_EXT_EGL_image_storage */
|
||||
#ifndef GL_EXT_direct_state_access
|
||||
typedef void (APIENTRYP PFNGLGETFLOATI_VEXTPROC) (GLenum pname, GLuint index, GLfloat *params);
|
||||
typedef void (APIENTRYP PFNGLGETDOUBLEI_VEXTPROC) (GLenum pname, GLuint index, GLdouble *params);
|
||||
typedef void (APIENTRYP PFNGLGETPOINTERI_VEXTPROC) (GLenum pname, GLuint index, void **params);
|
||||
typedef void (APIENTRYP PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, GLint *param);
|
||||
typedef void (APIENTRYP PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, void **param);
|
||||
#endif /* GL_EXT_direct_state_access */
|
||||
#ifndef GL_NV_draw_vulkan_image
|
||||
typedef void (APIENTRY *GLVULKANPROCNV)(void);
|
||||
#endif /* GL_NV_draw_vulkan_image */
|
||||
#ifndef GL_NV_gpu_shader5
|
||||
typedef khronos_int64_t GLint64EXT;
|
||||
#endif /* GL_NV_gpu_shader5 */
|
||||
#ifndef GL_NV_vertex_buffer_unified_memory
|
||||
typedef void (APIENTRYP PFNGLGETINTEGERUI64I_VNVPROC) (GLenum value, GLuint index, GLuint64EXT *result);
|
||||
#endif /* GL_NV_vertex_buffer_unified_memory */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef GL3W_API
|
||||
#define GL3W_API
|
||||
#endif
|
||||
|
||||
#ifndef __gl_h_
|
||||
#define __gl_h_
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define GL3W_OK 0
|
||||
#define GL3W_ERROR_INIT -1
|
||||
#define GL3W_ERROR_LIBRARY_OPEN -2
|
||||
#define GL3W_ERROR_OPENGL_VERSION -3
|
||||
|
||||
typedef void (*GL3WglProc)(void);
|
||||
typedef GL3WglProc (*GL3WGetProcAddressProc)(const char *proc);
|
||||
|
||||
/* gl3w api */
|
||||
GL3W_API int imgl3wInit(void);
|
||||
GL3W_API int imgl3wInit2(GL3WGetProcAddressProc proc);
|
||||
GL3W_API void imgl3wShutdown(void);
|
||||
GL3W_API int imgl3wIsSupported(int major, int minor);
|
||||
GL3W_API GL3WglProc imgl3wGetProcAddress(const char *proc);
|
||||
|
||||
/* gl3w internal state */
|
||||
union ImGL3WProcs {
|
||||
GL3WglProc ptr[63];
|
||||
struct {
|
||||
PFNGLACTIVETEXTUREPROC ActiveTexture;
|
||||
PFNGLATTACHSHADERPROC AttachShader;
|
||||
PFNGLBINDBUFFERPROC BindBuffer;
|
||||
PFNGLBINDSAMPLERPROC BindSampler;
|
||||
PFNGLBINDTEXTUREPROC BindTexture;
|
||||
PFNGLBINDVERTEXARRAYPROC BindVertexArray;
|
||||
PFNGLBLENDEQUATIONPROC BlendEquation;
|
||||
PFNGLBLENDEQUATIONSEPARATEPROC BlendEquationSeparate;
|
||||
PFNGLBLENDFUNCSEPARATEPROC BlendFuncSeparate;
|
||||
PFNGLBUFFERDATAPROC BufferData;
|
||||
PFNGLBUFFERSUBDATAPROC BufferSubData;
|
||||
PFNGLCLEARPROC Clear;
|
||||
PFNGLCLEARCOLORPROC ClearColor;
|
||||
PFNGLCOMPILESHADERPROC CompileShader;
|
||||
PFNGLCREATEPROGRAMPROC CreateProgram;
|
||||
PFNGLCREATESHADERPROC CreateShader;
|
||||
PFNGLDELETEBUFFERSPROC DeleteBuffers;
|
||||
PFNGLDELETEPROGRAMPROC DeleteProgram;
|
||||
PFNGLDELETESAMPLERSPROC DeleteSamplers;
|
||||
PFNGLDELETESHADERPROC DeleteShader;
|
||||
PFNGLDELETETEXTURESPROC DeleteTextures;
|
||||
PFNGLDELETEVERTEXARRAYSPROC DeleteVertexArrays;
|
||||
PFNGLDETACHSHADERPROC DetachShader;
|
||||
PFNGLDISABLEPROC Disable;
|
||||
PFNGLDISABLEVERTEXATTRIBARRAYPROC DisableVertexAttribArray;
|
||||
PFNGLDRAWELEMENTSPROC DrawElements;
|
||||
PFNGLDRAWELEMENTSBASEVERTEXPROC DrawElementsBaseVertex;
|
||||
PFNGLENABLEPROC Enable;
|
||||
PFNGLENABLEVERTEXATTRIBARRAYPROC EnableVertexAttribArray;
|
||||
PFNGLFLUSHPROC Flush;
|
||||
PFNGLGENBUFFERSPROC GenBuffers;
|
||||
PFNGLGENSAMPLERSPROC GenSamplers;
|
||||
PFNGLGENTEXTURESPROC GenTextures;
|
||||
PFNGLGENVERTEXARRAYSPROC GenVertexArrays;
|
||||
PFNGLGETATTRIBLOCATIONPROC GetAttribLocation;
|
||||
PFNGLGETERRORPROC GetError;
|
||||
PFNGLGETINTEGERVPROC GetIntegerv;
|
||||
PFNGLGETPROGRAMINFOLOGPROC GetProgramInfoLog;
|
||||
PFNGLGETPROGRAMIVPROC GetProgramiv;
|
||||
PFNGLGETSHADERINFOLOGPROC GetShaderInfoLog;
|
||||
PFNGLGETSHADERIVPROC GetShaderiv;
|
||||
PFNGLGETSTRINGPROC GetString;
|
||||
PFNGLGETSTRINGIPROC GetStringi;
|
||||
PFNGLGETUNIFORMLOCATIONPROC GetUniformLocation;
|
||||
PFNGLGETVERTEXATTRIBPOINTERVPROC GetVertexAttribPointerv;
|
||||
PFNGLGETVERTEXATTRIBIVPROC GetVertexAttribiv;
|
||||
PFNGLISENABLEDPROC IsEnabled;
|
||||
PFNGLISPROGRAMPROC IsProgram;
|
||||
PFNGLLINKPROGRAMPROC LinkProgram;
|
||||
PFNGLPIXELSTOREIPROC PixelStorei;
|
||||
PFNGLPOLYGONMODEPROC PolygonMode;
|
||||
PFNGLREADPIXELSPROC ReadPixels;
|
||||
PFNGLSAMPLERPARAMETERIPROC SamplerParameteri;
|
||||
PFNGLSCISSORPROC Scissor;
|
||||
PFNGLSHADERSOURCEPROC ShaderSource;
|
||||
PFNGLTEXIMAGE2DPROC TexImage2D;
|
||||
PFNGLTEXPARAMETERIPROC TexParameteri;
|
||||
PFNGLTEXSUBIMAGE2DPROC TexSubImage2D;
|
||||
PFNGLUNIFORM1IPROC Uniform1i;
|
||||
PFNGLUNIFORMMATRIX4FVPROC UniformMatrix4fv;
|
||||
PFNGLUSEPROGRAMPROC UseProgram;
|
||||
PFNGLVERTEXATTRIBPOINTERPROC VertexAttribPointer;
|
||||
PFNGLVIEWPORTPROC Viewport;
|
||||
} gl;
|
||||
};
|
||||
|
||||
GL3W_API extern union ImGL3WProcs imgl3wProcs;
|
||||
|
||||
/* OpenGL functions */
|
||||
#define glActiveTexture imgl3wProcs.gl.ActiveTexture
|
||||
#define glAttachShader imgl3wProcs.gl.AttachShader
|
||||
#define glBindBuffer imgl3wProcs.gl.BindBuffer
|
||||
#define glBindSampler imgl3wProcs.gl.BindSampler
|
||||
#define glBindTexture imgl3wProcs.gl.BindTexture
|
||||
#define glBindVertexArray imgl3wProcs.gl.BindVertexArray
|
||||
#define glBlendEquation imgl3wProcs.gl.BlendEquation
|
||||
#define glBlendEquationSeparate imgl3wProcs.gl.BlendEquationSeparate
|
||||
#define glBlendFuncSeparate imgl3wProcs.gl.BlendFuncSeparate
|
||||
#define glBufferData imgl3wProcs.gl.BufferData
|
||||
#define glBufferSubData imgl3wProcs.gl.BufferSubData
|
||||
#define glClear imgl3wProcs.gl.Clear
|
||||
#define glClearColor imgl3wProcs.gl.ClearColor
|
||||
#define glCompileShader imgl3wProcs.gl.CompileShader
|
||||
#define glCreateProgram imgl3wProcs.gl.CreateProgram
|
||||
#define glCreateShader imgl3wProcs.gl.CreateShader
|
||||
#define glDeleteBuffers imgl3wProcs.gl.DeleteBuffers
|
||||
#define glDeleteProgram imgl3wProcs.gl.DeleteProgram
|
||||
#define glDeleteSamplers imgl3wProcs.gl.DeleteSamplers
|
||||
#define glDeleteShader imgl3wProcs.gl.DeleteShader
|
||||
#define glDeleteTextures imgl3wProcs.gl.DeleteTextures
|
||||
#define glDeleteVertexArrays imgl3wProcs.gl.DeleteVertexArrays
|
||||
#define glDetachShader imgl3wProcs.gl.DetachShader
|
||||
#define glDisable imgl3wProcs.gl.Disable
|
||||
#define glDisableVertexAttribArray imgl3wProcs.gl.DisableVertexAttribArray
|
||||
#define glDrawElements imgl3wProcs.gl.DrawElements
|
||||
#define glDrawElementsBaseVertex imgl3wProcs.gl.DrawElementsBaseVertex
|
||||
#define glEnable imgl3wProcs.gl.Enable
|
||||
#define glEnableVertexAttribArray imgl3wProcs.gl.EnableVertexAttribArray
|
||||
#define glFlush imgl3wProcs.gl.Flush
|
||||
#define glGenBuffers imgl3wProcs.gl.GenBuffers
|
||||
#define glGenSamplers imgl3wProcs.gl.GenSamplers
|
||||
#define glGenTextures imgl3wProcs.gl.GenTextures
|
||||
#define glGenVertexArrays imgl3wProcs.gl.GenVertexArrays
|
||||
#define glGetAttribLocation imgl3wProcs.gl.GetAttribLocation
|
||||
#define glGetError imgl3wProcs.gl.GetError
|
||||
#define glGetIntegerv imgl3wProcs.gl.GetIntegerv
|
||||
#define glGetProgramInfoLog imgl3wProcs.gl.GetProgramInfoLog
|
||||
#define glGetProgramiv imgl3wProcs.gl.GetProgramiv
|
||||
#define glGetShaderInfoLog imgl3wProcs.gl.GetShaderInfoLog
|
||||
#define glGetShaderiv imgl3wProcs.gl.GetShaderiv
|
||||
#define glGetString imgl3wProcs.gl.GetString
|
||||
#define glGetStringi imgl3wProcs.gl.GetStringi
|
||||
#define glGetUniformLocation imgl3wProcs.gl.GetUniformLocation
|
||||
#define glGetVertexAttribPointerv imgl3wProcs.gl.GetVertexAttribPointerv
|
||||
#define glGetVertexAttribiv imgl3wProcs.gl.GetVertexAttribiv
|
||||
#define glIsEnabled imgl3wProcs.gl.IsEnabled
|
||||
#define glIsProgram imgl3wProcs.gl.IsProgram
|
||||
#define glLinkProgram imgl3wProcs.gl.LinkProgram
|
||||
#define glPixelStorei imgl3wProcs.gl.PixelStorei
|
||||
#define glPolygonMode imgl3wProcs.gl.PolygonMode
|
||||
#define glReadPixels imgl3wProcs.gl.ReadPixels
|
||||
#define glSamplerParameteri imgl3wProcs.gl.SamplerParameteri
|
||||
#define glScissor imgl3wProcs.gl.Scissor
|
||||
#define glShaderSource imgl3wProcs.gl.ShaderSource
|
||||
#define glTexImage2D imgl3wProcs.gl.TexImage2D
|
||||
#define glTexParameteri imgl3wProcs.gl.TexParameteri
|
||||
#define glTexSubImage2D imgl3wProcs.gl.TexSubImage2D
|
||||
#define glUniform1i imgl3wProcs.gl.Uniform1i
|
||||
#define glUniformMatrix4fv imgl3wProcs.gl.UniformMatrix4fv
|
||||
#define glUseProgram imgl3wProcs.gl.UseProgram
|
||||
#define glVertexAttribPointer imgl3wProcs.gl.VertexAttribPointer
|
||||
#define glViewport imgl3wProcs.gl.Viewport
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef IMGL3W_IMPL
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define GL3W_ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
|
||||
#if defined(_WIN32)
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#endif
|
||||
#include <windows.h>
|
||||
|
||||
static HMODULE libgl = NULL;
|
||||
typedef PROC(__stdcall* GL3WglGetProcAddr)(LPCSTR);
|
||||
static GL3WglGetProcAddr wgl_get_proc_address;
|
||||
|
||||
static int open_libgl(void)
|
||||
{
|
||||
libgl = LoadLibraryA("opengl32.dll");
|
||||
if (!libgl)
|
||||
return GL3W_ERROR_LIBRARY_OPEN;
|
||||
wgl_get_proc_address = (GL3WglGetProcAddr)GetProcAddress(libgl, "wglGetProcAddress");
|
||||
return GL3W_OK;
|
||||
}
|
||||
|
||||
static void close_libgl(void) { FreeLibrary(libgl); libgl = NULL; }
|
||||
static GL3WglProc get_proc(const char *proc)
|
||||
{
|
||||
GL3WglProc res;
|
||||
res = (GL3WglProc)wgl_get_proc_address(proc);
|
||||
if (!res)
|
||||
res = (GL3WglProc)GetProcAddress(libgl, proc);
|
||||
return res;
|
||||
}
|
||||
#elif defined(__APPLE__)
|
||||
#include <dlfcn.h>
|
||||
|
||||
static void *libgl = NULL;
|
||||
static int open_libgl(void)
|
||||
{
|
||||
libgl = dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY | RTLD_LOCAL);
|
||||
if (!libgl)
|
||||
return GL3W_ERROR_LIBRARY_OPEN;
|
||||
return GL3W_OK;
|
||||
}
|
||||
|
||||
static void close_libgl(void) { dlclose(libgl); libgl = NULL; }
|
||||
|
||||
static GL3WglProc get_proc(const char *proc)
|
||||
{
|
||||
GL3WglProc res;
|
||||
*(void **)(&res) = dlsym(libgl, proc);
|
||||
return res;
|
||||
}
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
|
||||
static void* libgl; // OpenGL library
|
||||
static void* libglx; // GLX library
|
||||
static void* libegl; // EGL library
|
||||
static GL3WGetProcAddressProc gl_get_proc_address;
|
||||
|
||||
static void close_libgl(void)
|
||||
{
|
||||
if (libgl) {
|
||||
dlclose(libgl);
|
||||
libgl = NULL;
|
||||
}
|
||||
if (libegl) {
|
||||
dlclose(libegl);
|
||||
libegl = NULL;
|
||||
}
|
||||
if (libglx) {
|
||||
dlclose(libglx);
|
||||
libglx = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int is_library_loaded(const char* name, void** lib)
|
||||
{
|
||||
#if defined(__HAIKU__)
|
||||
*lib = NULL; // no support for RTLD_NOLOAD on Haiku.
|
||||
#else
|
||||
*lib = dlopen(name, RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
|
||||
#endif
|
||||
return *lib != NULL;
|
||||
}
|
||||
|
||||
static int open_libs(void)
|
||||
{
|
||||
// On Linux we have two APIs to get process addresses: EGL and GLX.
|
||||
// EGL is supported under both X11 and Wayland, whereas GLX is X11-specific.
|
||||
|
||||
libgl = NULL;
|
||||
libegl = NULL;
|
||||
libglx = NULL;
|
||||
|
||||
// First check what's already loaded, the windowing library might have
|
||||
// already loaded either EGL or GLX and we want to use the same one.
|
||||
|
||||
if (is_library_loaded("libEGL.so.1", &libegl) ||
|
||||
is_library_loaded("libGLX.so.0", &libglx)) {
|
||||
libgl = dlopen("libOpenGL.so.0", RTLD_LAZY | RTLD_LOCAL);
|
||||
if (libgl)
|
||||
return GL3W_OK;
|
||||
else
|
||||
close_libgl();
|
||||
}
|
||||
|
||||
if (is_library_loaded("libGL.so", &libgl))
|
||||
return GL3W_OK;
|
||||
if (is_library_loaded("libGL.so.1", &libgl))
|
||||
return GL3W_OK;
|
||||
if (is_library_loaded("libGL.so.3", &libgl))
|
||||
return GL3W_OK;
|
||||
|
||||
// Neither is already loaded, so we have to load one. Try EGL first
|
||||
// because it is supported under both X11 and Wayland.
|
||||
|
||||
// Load OpenGL + EGL
|
||||
libgl = dlopen("libOpenGL.so.0", RTLD_LAZY | RTLD_LOCAL);
|
||||
libegl = dlopen("libEGL.so.1", RTLD_LAZY | RTLD_LOCAL);
|
||||
if (libgl && libegl)
|
||||
return GL3W_OK;
|
||||
else
|
||||
close_libgl();
|
||||
|
||||
// Fall back to legacy libGL, which includes GLX
|
||||
// While most systems use libGL.so.1, NetBSD seems to use that libGL.so.3. See https://github.com/ocornut/imgui/issues/6983
|
||||
libgl = dlopen("libGL.so", RTLD_LAZY | RTLD_LOCAL);
|
||||
if (!libgl)
|
||||
libgl = dlopen("libGL.so.1", RTLD_LAZY | RTLD_LOCAL);
|
||||
if (!libgl)
|
||||
libgl = dlopen("libGL.so.3", RTLD_LAZY | RTLD_LOCAL);
|
||||
|
||||
if (libgl)
|
||||
return GL3W_OK;
|
||||
|
||||
return GL3W_ERROR_LIBRARY_OPEN;
|
||||
}
|
||||
|
||||
static int open_libgl(void)
|
||||
{
|
||||
int res = open_libs();
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
if (libegl)
|
||||
*(void**)(&gl_get_proc_address) = dlsym(libegl, "eglGetProcAddress");
|
||||
else if (libglx)
|
||||
*(void**)(&gl_get_proc_address) = dlsym(libglx, "glXGetProcAddressARB");
|
||||
else
|
||||
*(void**)(&gl_get_proc_address) = dlsym(libgl, "glXGetProcAddressARB");
|
||||
|
||||
if (!gl_get_proc_address) {
|
||||
close_libgl();
|
||||
return GL3W_ERROR_LIBRARY_OPEN;
|
||||
}
|
||||
|
||||
return GL3W_OK;
|
||||
}
|
||||
|
||||
static GL3WglProc get_proc(const char* proc)
|
||||
{
|
||||
GL3WglProc res = NULL;
|
||||
|
||||
// Before EGL version 1.5, eglGetProcAddress doesn't support querying core
|
||||
// functions and may return a dummy function if we try, so try to load the
|
||||
// function from the GL library directly first.
|
||||
if (libegl)
|
||||
*(void**)(&res) = dlsym(libgl, proc);
|
||||
|
||||
if (!res)
|
||||
res = gl_get_proc_address(proc);
|
||||
|
||||
if (!libegl && !res)
|
||||
*(void**)(&res) = dlsym(libgl, proc);
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct { int major, minor; } version;
|
||||
|
||||
static int parse_version(void)
|
||||
{
|
||||
if (!glGetIntegerv)
|
||||
return GL3W_ERROR_INIT;
|
||||
glGetIntegerv(GL_MAJOR_VERSION, &version.major);
|
||||
glGetIntegerv(GL_MINOR_VERSION, &version.minor);
|
||||
if (version.major == 0 && version.minor == 0)
|
||||
{
|
||||
// Query GL_VERSION in desktop GL 2.x, the string will start with "<major>.<minor>"
|
||||
if (const char* gl_version = (const char*)glGetString(GL_VERSION))
|
||||
sscanf(gl_version, "%d.%d", &version.major, &version.minor);
|
||||
}
|
||||
if (version.major < 2)
|
||||
return GL3W_ERROR_OPENGL_VERSION;
|
||||
return GL3W_OK;
|
||||
}
|
||||
|
||||
static void load_procs(GL3WGetProcAddressProc proc);
|
||||
static void clear_procs();
|
||||
|
||||
int imgl3wInit(void)
|
||||
{
|
||||
int res = open_libgl();
|
||||
if (res)
|
||||
return res;
|
||||
atexit(close_libgl);
|
||||
return imgl3wInit2(get_proc);
|
||||
}
|
||||
|
||||
int imgl3wInit2(GL3WGetProcAddressProc proc)
|
||||
{
|
||||
load_procs(proc);
|
||||
return parse_version();
|
||||
}
|
||||
|
||||
void imgl3wShutdown(void)
|
||||
{
|
||||
close_libgl();
|
||||
clear_procs();
|
||||
}
|
||||
|
||||
int imgl3wIsSupported(int major, int minor)
|
||||
{
|
||||
if (major < 2)
|
||||
return 0;
|
||||
if (version.major == major)
|
||||
return version.minor >= minor;
|
||||
return version.major >= major;
|
||||
}
|
||||
|
||||
GL3WglProc imgl3wGetProcAddress(const char *proc) { return get_proc(proc); }
|
||||
|
||||
static const char *proc_names[] = {
|
||||
"glActiveTexture",
|
||||
"glAttachShader",
|
||||
"glBindBuffer",
|
||||
"glBindSampler",
|
||||
"glBindTexture",
|
||||
"glBindVertexArray",
|
||||
"glBlendEquation",
|
||||
"glBlendEquationSeparate",
|
||||
"glBlendFuncSeparate",
|
||||
"glBufferData",
|
||||
"glBufferSubData",
|
||||
"glClear",
|
||||
"glClearColor",
|
||||
"glCompileShader",
|
||||
"glCreateProgram",
|
||||
"glCreateShader",
|
||||
"glDeleteBuffers",
|
||||
"glDeleteProgram",
|
||||
"glDeleteSamplers",
|
||||
"glDeleteShader",
|
||||
"glDeleteTextures",
|
||||
"glDeleteVertexArrays",
|
||||
"glDetachShader",
|
||||
"glDisable",
|
||||
"glDisableVertexAttribArray",
|
||||
"glDrawElements",
|
||||
"glDrawElementsBaseVertex",
|
||||
"glEnable",
|
||||
"glEnableVertexAttribArray",
|
||||
"glFlush",
|
||||
"glGenBuffers",
|
||||
"glGenSamplers",
|
||||
"glGenTextures",
|
||||
"glGenVertexArrays",
|
||||
"glGetAttribLocation",
|
||||
"glGetError",
|
||||
"glGetIntegerv",
|
||||
"glGetProgramInfoLog",
|
||||
"glGetProgramiv",
|
||||
"glGetShaderInfoLog",
|
||||
"glGetShaderiv",
|
||||
"glGetString",
|
||||
"glGetStringi",
|
||||
"glGetUniformLocation",
|
||||
"glGetVertexAttribPointerv",
|
||||
"glGetVertexAttribiv",
|
||||
"glIsEnabled",
|
||||
"glIsProgram",
|
||||
"glLinkProgram",
|
||||
"glPixelStorei",
|
||||
"glPolygonMode",
|
||||
"glReadPixels",
|
||||
"glSamplerParameteri",
|
||||
"glScissor",
|
||||
"glShaderSource",
|
||||
"glTexImage2D",
|
||||
"glTexParameteri",
|
||||
"glTexSubImage2D",
|
||||
"glUniform1i",
|
||||
"glUniformMatrix4fv",
|
||||
"glUseProgram",
|
||||
"glVertexAttribPointer",
|
||||
"glViewport",
|
||||
};
|
||||
|
||||
GL3W_API union ImGL3WProcs imgl3wProcs;
|
||||
|
||||
static void load_procs(GL3WGetProcAddressProc proc)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < GL3W_ARRAY_SIZE(proc_names); i++)
|
||||
imgl3wProcs.ptr[i] = proc(proc_names[i]);
|
||||
}
|
||||
|
||||
static void clear_procs()
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < GL3W_ARRAY_SIZE(proc_names); i++)
|
||||
imgl3wProcs.ptr[i] = nullptr;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
4319
src/imgui/imgui_internal.h
Normal file
4319
src/imgui/imgui_internal.h
Normal file
File diff suppressed because it is too large
Load Diff
4665
src/imgui/imgui_tables.cpp
Normal file
4665
src/imgui/imgui_tables.cpp
Normal file
File diff suppressed because it is too large
Load Diff
11095
src/imgui/imgui_widgets.cpp
Normal file
11095
src/imgui/imgui_widgets.cpp
Normal file
File diff suppressed because it is too large
Load Diff
627
src/imgui/imstb_rectpack.h
Normal file
627
src/imgui/imstb_rectpack.h
Normal file
@@ -0,0 +1,627 @@
|
||||
// [DEAR IMGUI]
|
||||
// This is a slightly modified version of stb_rect_pack.h 1.01.
|
||||
// Grep for [DEAR IMGUI] to find the changes.
|
||||
//
|
||||
// stb_rect_pack.h - v1.01 - public domain - rectangle packing
|
||||
// Sean Barrett 2014
|
||||
//
|
||||
// Useful for e.g. packing rectangular textures into an atlas.
|
||||
// Does not do rotation.
|
||||
//
|
||||
// Before #including,
|
||||
//
|
||||
// #define STB_RECT_PACK_IMPLEMENTATION
|
||||
//
|
||||
// in the file that you want to have the implementation.
|
||||
//
|
||||
// Not necessarily the awesomest packing method, but better than
|
||||
// the totally naive one in stb_truetype (which is primarily what
|
||||
// this is meant to replace).
|
||||
//
|
||||
// Has only had a few tests run, may have issues.
|
||||
//
|
||||
// More docs to come.
|
||||
//
|
||||
// No memory allocations; uses qsort() and assert() from stdlib.
|
||||
// Can override those by defining STBRP_SORT and STBRP_ASSERT.
|
||||
//
|
||||
// This library currently uses the Skyline Bottom-Left algorithm.
|
||||
//
|
||||
// Please note: better rectangle packers are welcome! Please
|
||||
// implement them to the same API, but with a different init
|
||||
// function.
|
||||
//
|
||||
// Credits
|
||||
//
|
||||
// Library
|
||||
// Sean Barrett
|
||||
// Minor features
|
||||
// Martins Mozeiko
|
||||
// github:IntellectualKitty
|
||||
//
|
||||
// Bugfixes / warning fixes
|
||||
// Jeremy Jaussaud
|
||||
// Fabian Giesen
|
||||
//
|
||||
// Version history:
|
||||
//
|
||||
// 1.01 (2021-07-11) always use large rect mode, expose STBRP__MAXVAL in public section
|
||||
// 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles
|
||||
// 0.99 (2019-02-07) warning fixes
|
||||
// 0.11 (2017-03-03) return packing success/fail result
|
||||
// 0.10 (2016-10-25) remove cast-away-const to avoid warnings
|
||||
// 0.09 (2016-08-27) fix compiler warnings
|
||||
// 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0)
|
||||
// 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0)
|
||||
// 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort
|
||||
// 0.05: added STBRP_ASSERT to allow replacing assert
|
||||
// 0.04: fixed minor bug in STBRP_LARGE_RECTS support
|
||||
// 0.01: initial release
|
||||
//
|
||||
// LICENSE
|
||||
//
|
||||
// See end of file for license information.
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// INCLUDE SECTION
|
||||
//
|
||||
|
||||
#ifndef STB_INCLUDE_STB_RECT_PACK_H
|
||||
#define STB_INCLUDE_STB_RECT_PACK_H
|
||||
|
||||
#define STB_RECT_PACK_VERSION 1
|
||||
|
||||
#ifdef STBRP_STATIC
|
||||
#define STBRP_DEF static
|
||||
#else
|
||||
#define STBRP_DEF extern
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct stbrp_context stbrp_context;
|
||||
typedef struct stbrp_node stbrp_node;
|
||||
typedef struct stbrp_rect stbrp_rect;
|
||||
|
||||
typedef int stbrp_coord;
|
||||
|
||||
#define STBRP__MAXVAL 0x7fffffff
|
||||
// Mostly for internal use, but this is the maximum supported coordinate value.
|
||||
|
||||
STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
|
||||
// Assign packed locations to rectangles. The rectangles are of type
|
||||
// 'stbrp_rect' defined below, stored in the array 'rects', and there
|
||||
// are 'num_rects' many of them.
|
||||
//
|
||||
// Rectangles which are successfully packed have the 'was_packed' flag
|
||||
// set to a non-zero value and 'x' and 'y' store the minimum location
|
||||
// on each axis (i.e. bottom-left in cartesian coordinates, top-left
|
||||
// if you imagine y increasing downwards). Rectangles which do not fit
|
||||
// have the 'was_packed' flag set to 0.
|
||||
//
|
||||
// You should not try to access the 'rects' array from another thread
|
||||
// while this function is running, as the function temporarily reorders
|
||||
// the array while it executes.
|
||||
//
|
||||
// To pack into another rectangle, you need to call stbrp_init_target
|
||||
// again. To continue packing into the same rectangle, you can call
|
||||
// this function again. Calling this multiple times with multiple rect
|
||||
// arrays will probably produce worse packing results than calling it
|
||||
// a single time with the full rectangle array, but the option is
|
||||
// available.
|
||||
//
|
||||
// The function returns 1 if all of the rectangles were successfully
|
||||
// packed and 0 otherwise.
|
||||
|
||||
struct stbrp_rect
|
||||
{
|
||||
// reserved for your use:
|
||||
int id;
|
||||
|
||||
// input:
|
||||
stbrp_coord w, h;
|
||||
|
||||
// output:
|
||||
stbrp_coord x, y;
|
||||
int was_packed; // non-zero if valid packing
|
||||
|
||||
}; // 16 bytes, nominally
|
||||
|
||||
|
||||
STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes);
|
||||
// Initialize a rectangle packer to:
|
||||
// pack a rectangle that is 'width' by 'height' in dimensions
|
||||
// using temporary storage provided by the array 'nodes', which is 'num_nodes' long
|
||||
//
|
||||
// You must call this function every time you start packing into a new target.
|
||||
//
|
||||
// There is no "shutdown" function. The 'nodes' memory must stay valid for
|
||||
// the following stbrp_pack_rects() call (or calls), but can be freed after
|
||||
// the call (or calls) finish.
|
||||
//
|
||||
// Note: to guarantee best results, either:
|
||||
// 1. make sure 'num_nodes' >= 'width'
|
||||
// or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1'
|
||||
//
|
||||
// If you don't do either of the above things, widths will be quantized to multiples
|
||||
// of small integers to guarantee the algorithm doesn't run out of temporary storage.
|
||||
//
|
||||
// If you do #2, then the non-quantized algorithm will be used, but the algorithm
|
||||
// may run out of temporary storage and be unable to pack some rectangles.
|
||||
|
||||
STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem);
|
||||
// Optionally call this function after init but before doing any packing to
|
||||
// change the handling of the out-of-temp-memory scenario, described above.
|
||||
// If you call init again, this will be reset to the default (false).
|
||||
|
||||
|
||||
STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic);
|
||||
// Optionally select which packing heuristic the library should use. Different
|
||||
// heuristics will produce better/worse results for different data sets.
|
||||
// If you call init again, this will be reset to the default.
|
||||
|
||||
enum
|
||||
{
|
||||
STBRP_HEURISTIC_Skyline_default=0,
|
||||
STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default,
|
||||
STBRP_HEURISTIC_Skyline_BF_sortHeight
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// the details of the following structures don't matter to you, but they must
|
||||
// be visible so you can handle the memory allocations for them
|
||||
|
||||
struct stbrp_node
|
||||
{
|
||||
stbrp_coord x,y;
|
||||
stbrp_node *next;
|
||||
};
|
||||
|
||||
struct stbrp_context
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
int align;
|
||||
int init_mode;
|
||||
int heuristic;
|
||||
int num_nodes;
|
||||
stbrp_node *active_head;
|
||||
stbrp_node *free_head;
|
||||
stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2'
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPLEMENTATION SECTION
|
||||
//
|
||||
|
||||
#ifdef STB_RECT_PACK_IMPLEMENTATION
|
||||
#ifndef STBRP_SORT
|
||||
#include <stdlib.h>
|
||||
#define STBRP_SORT qsort
|
||||
#endif
|
||||
|
||||
#ifndef STBRP_ASSERT
|
||||
#include <assert.h>
|
||||
#define STBRP_ASSERT assert
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define STBRP__NOTUSED(v) (void)(v)
|
||||
#define STBRP__CDECL __cdecl
|
||||
#else
|
||||
#define STBRP__NOTUSED(v) (void)sizeof(v)
|
||||
#define STBRP__CDECL
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
STBRP__INIT_skyline = 1
|
||||
};
|
||||
|
||||
STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic)
|
||||
{
|
||||
switch (context->init_mode) {
|
||||
case STBRP__INIT_skyline:
|
||||
STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight);
|
||||
context->heuristic = heuristic;
|
||||
break;
|
||||
default:
|
||||
STBRP_ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem)
|
||||
{
|
||||
if (allow_out_of_mem)
|
||||
// if it's ok to run out of memory, then don't bother aligning them;
|
||||
// this gives better packing, but may fail due to OOM (even though
|
||||
// the rectangles easily fit). @TODO a smarter approach would be to only
|
||||
// quantize once we've hit OOM, then we could get rid of this parameter.
|
||||
context->align = 1;
|
||||
else {
|
||||
// if it's not ok to run out of memory, then quantize the widths
|
||||
// so that num_nodes is always enough nodes.
|
||||
//
|
||||
// I.e. num_nodes * align >= width
|
||||
// align >= width / num_nodes
|
||||
// align = ceil(width/num_nodes)
|
||||
|
||||
context->align = (context->width + context->num_nodes-1) / context->num_nodes;
|
||||
}
|
||||
}
|
||||
|
||||
STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i < num_nodes-1; ++i)
|
||||
nodes[i].next = &nodes[i+1];
|
||||
nodes[i].next = NULL;
|
||||
context->init_mode = STBRP__INIT_skyline;
|
||||
context->heuristic = STBRP_HEURISTIC_Skyline_default;
|
||||
context->free_head = &nodes[0];
|
||||
context->active_head = &context->extra[0];
|
||||
context->width = width;
|
||||
context->height = height;
|
||||
context->num_nodes = num_nodes;
|
||||
stbrp_setup_allow_out_of_mem(context, 0);
|
||||
|
||||
// node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly)
|
||||
context->extra[0].x = 0;
|
||||
context->extra[0].y = 0;
|
||||
context->extra[0].next = &context->extra[1];
|
||||
context->extra[1].x = (stbrp_coord) width;
|
||||
context->extra[1].y = (1<<30);
|
||||
context->extra[1].next = NULL;
|
||||
}
|
||||
|
||||
// find minimum y position if it starts at x1
|
||||
static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste)
|
||||
{
|
||||
stbrp_node *node = first;
|
||||
int x1 = x0 + width;
|
||||
int min_y, visited_width, waste_area;
|
||||
|
||||
STBRP__NOTUSED(c);
|
||||
|
||||
STBRP_ASSERT(first->x <= x0);
|
||||
|
||||
#if 0
|
||||
// skip in case we're past the node
|
||||
while (node->next->x <= x0)
|
||||
++node;
|
||||
#else
|
||||
STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency
|
||||
#endif
|
||||
|
||||
STBRP_ASSERT(node->x <= x0);
|
||||
|
||||
min_y = 0;
|
||||
waste_area = 0;
|
||||
visited_width = 0;
|
||||
while (node->x < x1) {
|
||||
if (node->y > min_y) {
|
||||
// raise min_y higher.
|
||||
// we've accounted for all waste up to min_y,
|
||||
// but we'll now add more waste for everything we've visited
|
||||
waste_area += visited_width * (node->y - min_y);
|
||||
min_y = node->y;
|
||||
// the first time through, visited_width might be reduced
|
||||
if (node->x < x0)
|
||||
visited_width += node->next->x - x0;
|
||||
else
|
||||
visited_width += node->next->x - node->x;
|
||||
} else {
|
||||
// add waste area
|
||||
int under_width = node->next->x - node->x;
|
||||
if (under_width + visited_width > width)
|
||||
under_width = width - visited_width;
|
||||
waste_area += under_width * (min_y - node->y);
|
||||
visited_width += under_width;
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
*pwaste = waste_area;
|
||||
return min_y;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int x,y;
|
||||
stbrp_node **prev_link;
|
||||
} stbrp__findresult;
|
||||
|
||||
static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height)
|
||||
{
|
||||
int best_waste = (1<<30), best_x, best_y = (1 << 30);
|
||||
stbrp__findresult fr;
|
||||
stbrp_node **prev, *node, *tail, **best = NULL;
|
||||
|
||||
// align to multiple of c->align
|
||||
width = (width + c->align - 1);
|
||||
width -= width % c->align;
|
||||
STBRP_ASSERT(width % c->align == 0);
|
||||
|
||||
// if it can't possibly fit, bail immediately
|
||||
if (width > c->width || height > c->height) {
|
||||
fr.prev_link = NULL;
|
||||
fr.x = fr.y = 0;
|
||||
return fr;
|
||||
}
|
||||
|
||||
node = c->active_head;
|
||||
prev = &c->active_head;
|
||||
while (node->x + width <= c->width) {
|
||||
int y,waste;
|
||||
y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste);
|
||||
if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL
|
||||
// bottom left
|
||||
if (y < best_y) {
|
||||
best_y = y;
|
||||
best = prev;
|
||||
}
|
||||
} else {
|
||||
// best-fit
|
||||
if (y + height <= c->height) {
|
||||
// can only use it if it first vertically
|
||||
if (y < best_y || (y == best_y && waste < best_waste)) {
|
||||
best_y = y;
|
||||
best_waste = waste;
|
||||
best = prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
prev = &node->next;
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
best_x = (best == NULL) ? 0 : (*best)->x;
|
||||
|
||||
// if doing best-fit (BF), we also have to try aligning right edge to each node position
|
||||
//
|
||||
// e.g, if fitting
|
||||
//
|
||||
// ____________________
|
||||
// |____________________|
|
||||
//
|
||||
// into
|
||||
//
|
||||
// | |
|
||||
// | ____________|
|
||||
// |____________|
|
||||
//
|
||||
// then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned
|
||||
//
|
||||
// This makes BF take about 2x the time
|
||||
|
||||
if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) {
|
||||
tail = c->active_head;
|
||||
node = c->active_head;
|
||||
prev = &c->active_head;
|
||||
// find first node that's admissible
|
||||
while (tail->x < width)
|
||||
tail = tail->next;
|
||||
while (tail) {
|
||||
int xpos = tail->x - width;
|
||||
int y,waste;
|
||||
STBRP_ASSERT(xpos >= 0);
|
||||
// find the left position that matches this
|
||||
while (node->next->x <= xpos) {
|
||||
prev = &node->next;
|
||||
node = node->next;
|
||||
}
|
||||
STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
|
||||
y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
|
||||
if (y + height <= c->height) {
|
||||
if (y <= best_y) {
|
||||
if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
|
||||
best_x = xpos;
|
||||
//STBRP_ASSERT(y <= best_y); [DEAR IMGUI]
|
||||
best_y = y;
|
||||
best_waste = waste;
|
||||
best = prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
tail = tail->next;
|
||||
}
|
||||
}
|
||||
|
||||
fr.prev_link = best;
|
||||
fr.x = best_x;
|
||||
fr.y = best_y;
|
||||
return fr;
|
||||
}
|
||||
|
||||
static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height)
|
||||
{
|
||||
// find best position according to heuristic
|
||||
stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height);
|
||||
stbrp_node *node, *cur;
|
||||
|
||||
// bail if:
|
||||
// 1. it failed
|
||||
// 2. the best node doesn't fit (we don't always check this)
|
||||
// 3. we're out of memory
|
||||
if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) {
|
||||
res.prev_link = NULL;
|
||||
return res;
|
||||
}
|
||||
|
||||
// on success, create new node
|
||||
node = context->free_head;
|
||||
node->x = (stbrp_coord) res.x;
|
||||
node->y = (stbrp_coord) (res.y + height);
|
||||
|
||||
context->free_head = node->next;
|
||||
|
||||
// insert the new node into the right starting point, and
|
||||
// let 'cur' point to the remaining nodes needing to be
|
||||
// stitched back in
|
||||
|
||||
cur = *res.prev_link;
|
||||
if (cur->x < res.x) {
|
||||
// preserve the existing one, so start testing with the next one
|
||||
stbrp_node *next = cur->next;
|
||||
cur->next = node;
|
||||
cur = next;
|
||||
} else {
|
||||
*res.prev_link = node;
|
||||
}
|
||||
|
||||
// from here, traverse cur and free the nodes, until we get to one
|
||||
// that shouldn't be freed
|
||||
while (cur->next && cur->next->x <= res.x + width) {
|
||||
stbrp_node *next = cur->next;
|
||||
// move the current node to the free list
|
||||
cur->next = context->free_head;
|
||||
context->free_head = cur;
|
||||
cur = next;
|
||||
}
|
||||
|
||||
// stitch the list back in
|
||||
node->next = cur;
|
||||
|
||||
if (cur->x < res.x + width)
|
||||
cur->x = (stbrp_coord) (res.x + width);
|
||||
|
||||
#ifdef _DEBUG
|
||||
cur = context->active_head;
|
||||
while (cur->x < context->width) {
|
||||
STBRP_ASSERT(cur->x < cur->next->x);
|
||||
cur = cur->next;
|
||||
}
|
||||
STBRP_ASSERT(cur->next == NULL);
|
||||
|
||||
{
|
||||
int count=0;
|
||||
cur = context->active_head;
|
||||
while (cur) {
|
||||
cur = cur->next;
|
||||
++count;
|
||||
}
|
||||
cur = context->free_head;
|
||||
while (cur) {
|
||||
cur = cur->next;
|
||||
++count;
|
||||
}
|
||||
STBRP_ASSERT(count == context->num_nodes+2);
|
||||
}
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
|
||||
{
|
||||
const stbrp_rect *p = (const stbrp_rect *) a;
|
||||
const stbrp_rect *q = (const stbrp_rect *) b;
|
||||
if (p->h > q->h)
|
||||
return -1;
|
||||
if (p->h < q->h)
|
||||
return 1;
|
||||
return (p->w > q->w) ? -1 : (p->w < q->w);
|
||||
}
|
||||
|
||||
static int STBRP__CDECL rect_original_order(const void *a, const void *b)
|
||||
{
|
||||
const stbrp_rect *p = (const stbrp_rect *) a;
|
||||
const stbrp_rect *q = (const stbrp_rect *) b;
|
||||
return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
|
||||
}
|
||||
|
||||
STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
|
||||
{
|
||||
int i, all_rects_packed = 1;
|
||||
|
||||
// we use the 'was_packed' field internally to allow sorting/unsorting
|
||||
for (i=0; i < num_rects; ++i) {
|
||||
rects[i].was_packed = i;
|
||||
}
|
||||
|
||||
// sort according to heuristic
|
||||
STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare);
|
||||
|
||||
for (i=0; i < num_rects; ++i) {
|
||||
if (rects[i].w == 0 || rects[i].h == 0) {
|
||||
rects[i].x = rects[i].y = 0; // empty rect needs no space
|
||||
} else {
|
||||
stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
|
||||
if (fr.prev_link) {
|
||||
rects[i].x = (stbrp_coord) fr.x;
|
||||
rects[i].y = (stbrp_coord) fr.y;
|
||||
} else {
|
||||
rects[i].x = rects[i].y = STBRP__MAXVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// unsort
|
||||
STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order);
|
||||
|
||||
// set was_packed flags and all_rects_packed status
|
||||
for (i=0; i < num_rects; ++i) {
|
||||
rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL);
|
||||
if (!rects[i].was_packed)
|
||||
all_rects_packed = 0;
|
||||
}
|
||||
|
||||
// return the all_rects_packed status
|
||||
return all_rects_packed;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
------------------------------------------------------------------------------
|
||||
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.
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
1527
src/imgui/imstb_textedit.h
Normal file
1527
src/imgui/imstb_textedit.h
Normal file
File diff suppressed because it is too large
Load Diff
5085
src/imgui/imstb_truetype.h
Normal file
5085
src/imgui/imstb_truetype.h
Normal file
File diff suppressed because it is too large
Load Diff
256
src/main.cpp
256
src/main.cpp
@@ -5,28 +5,33 @@
|
||||
|
||||
#include "glm/glm.hpp"
|
||||
#include "glm/ext/matrix_clip_space.hpp"
|
||||
#include "glm/ext/matrix_transform.hpp"
|
||||
|
||||
#include "entt/entt.hpp"
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "Components.h"
|
||||
#include "FreeCamera.h"
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_glfw.h"
|
||||
#include "imgui_impl_opengl3.h"
|
||||
#include "InputManager.h"
|
||||
#include "AssetRegistry.h"
|
||||
#include "stb_image.h"
|
||||
|
||||
#include "Model.h"
|
||||
#include "ModelManager.h"
|
||||
#include "Camera.h"
|
||||
#include "EditorContext.h"
|
||||
#include "FreeCameraController.h"
|
||||
#include "InputManager.h"
|
||||
#include "ProjectManifest.h"
|
||||
#include "ProjectManifestFile.h"
|
||||
#include "Scene.h"
|
||||
#include "ShaderManager.h"
|
||||
#include "ShaderProgram.h"
|
||||
#include "Texture.h"
|
||||
#include "TextureManager.h"
|
||||
|
||||
#include "fmt/base.h"
|
||||
#include "UIManager.h"
|
||||
#include "ui/UIEntityInspector.h"
|
||||
#include "ui/UIMenuBar.h"
|
||||
#include "ui/UISceneGraph.h"
|
||||
#include "ui/UISceneViewer.h"
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
#include "MeshManager.h"
|
||||
|
||||
const char* B_ENGINE_VERSION = "v0.0.3";
|
||||
|
||||
GLFWwindow* gWindow = nullptr;
|
||||
int gWindowWidth = 1920;
|
||||
@@ -39,9 +44,13 @@ float gAspectRatio = 0.f;
|
||||
|
||||
float gMouseSensitivity = 0.1f;
|
||||
|
||||
FreeCamera gCamera {};
|
||||
std::unique_ptr<ProjectManifest> gCurrentProject {nullptr};
|
||||
|
||||
Scene gScene{};
|
||||
EditorContext gEditorCtx{};
|
||||
|
||||
Camera gCamera {};
|
||||
FreeCameraController gEditorCameraController{};
|
||||
|
||||
void glfw_error_callback(int error, const char* description);
|
||||
void glfw_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);
|
||||
@@ -50,21 +59,19 @@ void glfw_framebuffer_size_callback(GLFWwindow* window, int width, int height);
|
||||
void init_glfw();
|
||||
void create_main_window();
|
||||
void load_gl();
|
||||
void load_imgui();
|
||||
void init_camera();
|
||||
void load_default_textures();
|
||||
void load_shaders();
|
||||
void load_inputs();
|
||||
void load_default_models();
|
||||
void init_editor_camera();
|
||||
void loop();
|
||||
void draw_ui();
|
||||
|
||||
void create_entity(entt::entity parent);
|
||||
void open_project(std::string_view _path);
|
||||
|
||||
auto xAxis = glm::vec3{1.f, 0.f, 0.f};
|
||||
auto yAxis = glm::vec3{0.f, 1.f, 0.f};
|
||||
auto zAxis = glm::vec3{0.f, 0.f, 1.f};
|
||||
|
||||
int main() {
|
||||
spdlog::info("b_engine v0.0.3 start");
|
||||
spdlog::info("b_engine {} start", B_ENGINE_VERSION);
|
||||
|
||||
init_glfw();
|
||||
|
||||
@@ -72,35 +79,34 @@ int main() {
|
||||
|
||||
load_gl();
|
||||
|
||||
load_imgui();
|
||||
|
||||
init_camera();
|
||||
|
||||
stbi_set_flip_vertically_on_load(true);
|
||||
|
||||
load_default_textures();
|
||||
|
||||
load_shaders();
|
||||
|
||||
load_inputs();
|
||||
|
||||
load_default_models();
|
||||
UIManager::init(gWindow);
|
||||
auto* menuBar = UIManager::add_ui_panel<UIMenuBar>("menu_bar");
|
||||
menuBar->create_entity = create_entity;
|
||||
menuBar->open_project = open_project;
|
||||
UIManager::add_ui_panel<UISceneViewer>("scene_viewer");
|
||||
UIManager::add_ui_panel<UISceneGraph>("scene_graph");
|
||||
UIManager::add_ui_panel<UIEntityInspector>("entity_inspector");
|
||||
|
||||
entt::entity dirLight = gScene.create_game_object();
|
||||
auto& [direction, ambient, diffuse, specular] = gScene.attach_component<Components::DirectionalLight>(dirLight);
|
||||
direction = {1, -1, 1};
|
||||
ambient = {0.3f, 0.3f, 0.3f};
|
||||
diffuse = {0.5f, 0.5f, 0.5f};
|
||||
specular = {1.0f, 1.0f, 1.0f};
|
||||
gEditorCameraController.set_camera(gCamera);
|
||||
gEditorCameraController.look_sensitivity = 0.2;
|
||||
gEditorCameraController.movement_speed = 0.2;
|
||||
InputManager::add_mouse_listener([](float xoff, float yoff) {
|
||||
gEditorCameraController.on_mouse_delta(xoff, yoff);
|
||||
});
|
||||
|
||||
auto& tag = gScene.fetch_component<Components::Tag>(dirLight);
|
||||
tag.name = "directional light";
|
||||
gEditorCtx.scene = &gScene;
|
||||
gEditorCtx.window = gWindow;
|
||||
gEditorCtx.selectedEntity = entt::null;
|
||||
|
||||
loop();
|
||||
|
||||
ShaderManager::shaders.clear();
|
||||
TextureManager::textures.clear();
|
||||
ModelManager::models.clear();
|
||||
MeshManager::meshes.clear();
|
||||
|
||||
glfwDestroyWindow(gWindow);
|
||||
glfwTerminate();
|
||||
@@ -118,8 +124,7 @@ void glfw_framebuffer_size_callback(GLFWwindow *window, int width, int height) {
|
||||
gCamera.update_aspect_ratio(gAspectRatio);
|
||||
}
|
||||
|
||||
void init_glfw()
|
||||
{
|
||||
void init_glfw() {
|
||||
if (!glfwInit()) {
|
||||
spdlog::error("could not initialize glfw");
|
||||
std::exit(1);
|
||||
@@ -135,7 +140,8 @@ void init_glfw()
|
||||
|
||||
void create_main_window()
|
||||
{
|
||||
gWindow = glfwCreateWindow(gWindowWidth, gWindowHeight, "b_engine v0.0.3", nullptr, nullptr);
|
||||
std::string title = fmt::format("b_engine {}", B_ENGINE_VERSION);
|
||||
gWindow = glfwCreateWindow(gWindowWidth, gWindowHeight, title.c_str(), nullptr, nullptr);
|
||||
if (!gWindow) {
|
||||
spdlog::error("failed to create glfw window");
|
||||
std::exit(1);
|
||||
@@ -147,10 +153,6 @@ void create_main_window()
|
||||
glfwSetCursorPosCallback(gWindow, InputManager::mouse_pos_callback);
|
||||
|
||||
glfwSetFramebufferSizeCallback(gWindow, glfw_framebuffer_size_callback);
|
||||
|
||||
#ifndef GLFW_CONTEXT_DEBUG
|
||||
glfwSetInputMode(gWindow, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
#endif
|
||||
}
|
||||
|
||||
void load_gl()
|
||||
@@ -171,44 +173,10 @@ void load_gl()
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
}
|
||||
|
||||
void load_imgui() {
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
|
||||
ImGui::StyleColorsDark();
|
||||
ImGui_ImplGlfw_InitForOpenGL(gWindow, true);
|
||||
ImGui_ImplOpenGL3_Init("#version 330");
|
||||
}
|
||||
|
||||
void init_camera() {
|
||||
gCamera = {{5.f, 5.f, 5.f}, 0, 0, gAspectRatio};
|
||||
void init_editor_camera() {
|
||||
gCamera = {{10.f, 10.f, 10.f}, 0, 0, gAspectRatio};
|
||||
gCamera.rotate_yaw(-135.f);
|
||||
gCamera.rotate_pitch(-35.f);
|
||||
|
||||
InputManager::add_mouse_listener([](float xoff, float yoff) {
|
||||
gCamera.rotate_yaw(xoff * gMouseSensitivity);
|
||||
gCamera.rotate_pitch(yoff * gMouseSensitivity);
|
||||
});
|
||||
}
|
||||
|
||||
void load_default_textures() {
|
||||
spdlog::info("creating default textures");
|
||||
|
||||
unsigned char defaultDiffuseData[4] = {static_cast<unsigned char>(255), 255, 255, 255};
|
||||
TextureManager::textures["default_diffuse"] = TextureManager::load_from_data(reinterpret_cast<unsigned char*>(&defaultDiffuseData), 1, 1, 4);
|
||||
|
||||
unsigned char defaultSpecularData[4] = {static_cast<unsigned char>(64), 64, 64, 255};
|
||||
TextureManager::textures["default_specular"] = TextureManager::load_from_data(reinterpret_cast<unsigned char*>(&defaultSpecularData), 1, 1, 4);
|
||||
}
|
||||
|
||||
void load_shaders() {
|
||||
spdlog::info("compiling shaders");
|
||||
ShaderManager::shaders["phong_shader"] = ShaderManager::load("./resources/standard.vert", "./resources/standard.frag");
|
||||
if (ShaderManager::shaders["phong_shader"] == nullptr)
|
||||
{
|
||||
spdlog::error("failed to compile phong shader");
|
||||
std::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void load_inputs() {
|
||||
@@ -218,119 +186,57 @@ void load_inputs() {
|
||||
InputManager::generate_input_action("move_left", {{GLFW_KEY_A, KEY_DOWN}});
|
||||
InputManager::generate_input_action("move_up", {{GLFW_KEY_SPACE, KEY_DOWN}});
|
||||
InputManager::generate_input_action("move_down", {{GLFW_KEY_LEFT_SHIFT, KEY_DOWN}});
|
||||
InputManager::generate_input_action("exit_application", {{GLFW_KEY_ESCAPE, KEY_DOWN}});
|
||||
}
|
||||
|
||||
void load_default_models() {
|
||||
spdlog::info("loading default models");
|
||||
ModelManager::models["cube"] = ModelManager::load_from_file("./resources/cube.obj");
|
||||
ModelManager::models["vette"] = ModelManager::load_from_file("./resources/c4/C4Fixed.obj");
|
||||
ModelManager::models["male"] = ModelManager::load_from_file("./resources/male.obj");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
while (!glfwWindowShouldClose(gWindow)) {
|
||||
// input
|
||||
glfwPollEvents();
|
||||
|
||||
// check inputs
|
||||
if (InputManager::check_action_performed("exit_application")) {
|
||||
glfwSetWindowShouldClose(gWindow, true);
|
||||
continue;
|
||||
// update
|
||||
UIManager::update(gEditorCtx);
|
||||
gEditorCameraController.update(gEditorCtx);
|
||||
|
||||
if (gCamera.aspect_ratio() != gEditorCtx.viewportAspectRatio) {
|
||||
gCamera.update_aspect_ratio(gEditorCtx.viewportAspectRatio);
|
||||
}
|
||||
|
||||
if (InputManager::check_action_performed("move_forward")) {
|
||||
gCamera.move(FORWARD, .05);
|
||||
gScene.update_transforms();
|
||||
|
||||
const auto* uiScenePanel = dynamic_cast<UISceneViewer*>(UIManager::get_ui_panel("scene_viewer").get());
|
||||
if (uiScenePanel) {
|
||||
uiScenePanel->bind_fbo();
|
||||
}
|
||||
|
||||
if (InputManager::check_action_performed("move_backward")) {
|
||||
gCamera.move(BACKWARD, .05);
|
||||
}
|
||||
|
||||
if (InputManager::check_action_performed("move_left")) {
|
||||
gCamera.move(LEFT, .05);
|
||||
}
|
||||
|
||||
if (InputManager::check_action_performed("move_right")) {
|
||||
gCamera.move(RIGHT, .05);
|
||||
}
|
||||
|
||||
if (InputManager::check_action_performed("move_up")) {
|
||||
gCamera.move(UP, .05);
|
||||
}
|
||||
|
||||
if (InputManager::check_action_performed("move_down")) {
|
||||
gCamera.move(DOWN, .05);
|
||||
}
|
||||
|
||||
draw_ui();
|
||||
|
||||
// gl frame prep
|
||||
// draw
|
||||
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
|
||||
const auto shader = ShaderManager::shaders["phong_shader"];
|
||||
shader->bind();
|
||||
shader->setMat4("projection", gCamera.projection());
|
||||
shader->setMat4("view", gCamera.view());
|
||||
shader->setVec3("viewPosition", gCamera.position());
|
||||
|
||||
gScene.draw_scene(shader.get());
|
||||
gScene.draw_scene();
|
||||
|
||||
glBindVertexArray(0);
|
||||
ShaderProgram::unbind();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
// gl end frame stuff
|
||||
UIManager::draw();
|
||||
|
||||
// end frame
|
||||
glfwSwapBuffers(gWindow);
|
||||
}
|
||||
}
|
||||
|
||||
void draw_ui() {
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
{
|
||||
if (ImGui::Begin("Scene")) {
|
||||
ImGui::Text("Scene");
|
||||
const auto root = gScene.get_root();
|
||||
auto entity = gScene.fetch_component<Components::Relationship>(root).first_child;
|
||||
while (entity != entt::null) {
|
||||
const auto&[name] = gScene.fetch_component<Components::Tag>(entity);
|
||||
std::string text = fmt::format(" {0}", name);
|
||||
ImGui::Text((char*)text.data());
|
||||
entity = gScene.fetch_component<Components::Relationship>(entity).next_sibling;
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
void create_entity(entt::entity parent) {
|
||||
gScene.create_game_object(parent);
|
||||
}
|
||||
|
||||
if (ImGui::BeginMainMenuBar()) {
|
||||
if (ImGui::BeginMenu("File")) {
|
||||
if (ImGui::MenuItem("New Scene", "Ctrl+N")) {
|
||||
/* Handle New File logic */
|
||||
}
|
||||
if (ImGui::MenuItem("Open Scene", "Ctrl+O")) {
|
||||
/* Handle Open logic */
|
||||
}
|
||||
ImGui::Separator(); // Adds a visual line between sections
|
||||
if (ImGui::MenuItem("Save", "Ctrl+S")) {
|
||||
/* Handle Save logic */
|
||||
}
|
||||
if (ImGui::MenuItem("Exit", "Alt+F4")) {
|
||||
/* Handle Exit logic */
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
void open_project(std::string_view _path) {
|
||||
const std::filesystem::path projectFilePath {_path};
|
||||
gCurrentProject = ProjectManifestFile::load(_path);
|
||||
gCurrentProject->projectDirectory = projectFilePath.parent_path();
|
||||
|
||||
if (ImGui::BeginMenu("Scene")) {
|
||||
if (ImGui::MenuItem("New Scene Object")) {
|
||||
gScene.create_game_object();
|
||||
// Do other stuff here, open this entity in the entity editor, etc...
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
ImGui::EndMainMenuBar();
|
||||
}
|
||||
}
|
||||
ImGui::Render();
|
||||
}
|
||||
std::filesystem::path assetPath = gCurrentProject->projectDirectory.append(gCurrentProject->assetFolder);
|
||||
AssetRegistry::read_directory(assetPath);
|
||||
|
||||
const std::string title = fmt::format("project \"{}\" | b_engine {}", gCurrentProject->name, B_ENGINE_VERSION);
|
||||
glfwSetWindowTitle(gWindow, title.c_str());
|
||||
}
|
||||
|
||||
18
src/ui/IUIPanel.h
Normal file
18
src/ui/IUIPanel.h
Normal file
@@ -0,0 +1,18 @@
|
||||
//
|
||||
// Created by slinky on 5/11/26.
|
||||
//
|
||||
|
||||
#ifndef B_ENGINE_IUIPANEL_H
|
||||
#define B_ENGINE_IUIPANEL_H
|
||||
|
||||
#include "EditorContext.h"
|
||||
|
||||
class IUIPanel {
|
||||
public:
|
||||
virtual ~IUIPanel() = default;
|
||||
virtual void update(EditorContext& context) = 0;
|
||||
bool IsOpen = true;
|
||||
bool HasFocus = true;
|
||||
};
|
||||
|
||||
#endif //B_ENGINE_IUIPANEL_H
|
||||
63
src/ui/UIEntityInspector.cpp
Normal file
63
src/ui/UIEntityInspector.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
//
|
||||
// Created by slinky on 5/11/26.
|
||||
//
|
||||
|
||||
#include "UIEntityInspector.h"
|
||||
|
||||
#include "Components.h"
|
||||
#include "imgui.h"
|
||||
#include "glm/gtc/type_ptr.hpp"
|
||||
|
||||
void UIEntityInspector::update(EditorContext &ctx) {
|
||||
ImGui::Begin("Inspector");
|
||||
|
||||
if (ctx.selectedEntity == entt::null)
|
||||
{
|
||||
ImGui::TextDisabled("No entity selected");
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
Scene* scene = ctx.scene;
|
||||
auto entity = ctx.selectedEntity;
|
||||
|
||||
if (scene->has_component<Components::Tag>(entity))
|
||||
{
|
||||
auto& [name] = scene->fetch_component<Components::Tag>(entity);
|
||||
|
||||
char buffer[256]{};
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
strncpy(buffer, name.c_str(), sizeof(buffer) - 1);
|
||||
|
||||
if (ImGui::InputText("Tag", buffer, sizeof(buffer)))
|
||||
{
|
||||
name = std::string(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (scene->has_component<Components::Transform>(entity))
|
||||
{
|
||||
auto& transform = scene->fetch_component<Components::Transform>(entity);
|
||||
ImGui::Text("Transform");
|
||||
|
||||
if (ImGui::DragFloat3("Position", glm::value_ptr(transform.position), 0.1f))
|
||||
{
|
||||
transform.dirty = true;
|
||||
}
|
||||
|
||||
if (ImGui::DragFloat3("Rotation", glm::value_ptr(transform.rotation), 0.05f))
|
||||
{
|
||||
transform.dirty = true;
|
||||
}
|
||||
|
||||
if (ImGui::DragFloat3("Scale", glm::value_ptr(transform.scale), 0.1f))
|
||||
{
|
||||
transform.dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
17
src/ui/UIEntityInspector.h
Normal file
17
src/ui/UIEntityInspector.h
Normal file
@@ -0,0 +1,17 @@
|
||||
//
|
||||
// Created by slinky on 5/11/26.
|
||||
//
|
||||
|
||||
#ifndef B_ENGINE_UIENTITYINSPECTOR_H
|
||||
#define B_ENGINE_UIENTITYINSPECTOR_H
|
||||
|
||||
#include "EditorContext.h"
|
||||
#include "IUIPanel.h"
|
||||
|
||||
class UIEntityInspector : public IUIPanel {
|
||||
public:
|
||||
void update(EditorContext& ctx) override;
|
||||
};
|
||||
|
||||
|
||||
#endif //B_ENGINE_UIENTITYINSPECTOR_H
|
||||
55
src/ui/UIMenuBar.cpp
Normal file
55
src/ui/UIMenuBar.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
//
|
||||
// Created by slinky on 5/11/26.
|
||||
//
|
||||
|
||||
#include "UIMenuBar.h"
|
||||
#include "UIManager.h"
|
||||
#include "UISceneGraph.h"
|
||||
|
||||
#include "imgui.h"
|
||||
|
||||
#include "nfd.h"
|
||||
|
||||
void UIMenuBar::update(EditorContext &context) {
|
||||
if (ImGui::BeginMainMenuBar()) {
|
||||
if (ImGui::BeginMenu("File")) {
|
||||
if (ImGui::MenuItem("New Project")) {
|
||||
}
|
||||
if (ImGui::MenuItem("Open Project")) {
|
||||
NFD_Init();
|
||||
|
||||
nfdu8char_t *outPath;
|
||||
nfdu8filteritem_t filters[1] = { { "b_engine project files", "json" } };
|
||||
nfdopendialogu8args_t args = {0};
|
||||
args.filterList = filters;
|
||||
args.filterCount = 1;
|
||||
nfdresult_t result = NFD_OpenDialogU8_With(&outPath, &args);
|
||||
|
||||
if (result == NFD_OKAY && open_project)
|
||||
{
|
||||
open_project(outPath);
|
||||
NFD_FreePathU8(outPath);
|
||||
}
|
||||
|
||||
NFD_Quit();
|
||||
}
|
||||
ImGui::Separator(); // Adds a visual line between sections
|
||||
if (ImGui::MenuItem("Save", "Ctrl+S")) {
|
||||
}
|
||||
if (ImGui::MenuItem("Exit", "Alt+F4")) {
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Scene")) {
|
||||
if (ImGui::MenuItem("New Scene Object")) {
|
||||
const auto* sceneGraph = dynamic_cast<UISceneGraph*>(UIManager::get_ui_panel("scene_graph").get());
|
||||
if (sceneGraph) {
|
||||
create_entity(context.selectedEntity);
|
||||
}
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
ImGui::EndMainMenuBar();
|
||||
}
|
||||
}
|
||||
19
src/ui/UIMenuBar.h
Normal file
19
src/ui/UIMenuBar.h
Normal file
@@ -0,0 +1,19 @@
|
||||
//
|
||||
// Created by slinky on 5/11/26.
|
||||
//
|
||||
|
||||
#ifndef B_ENGINE_UIMENUBAR_H
|
||||
#define B_ENGINE_UIMENUBAR_H
|
||||
|
||||
#include "IUIPanel.h"
|
||||
|
||||
class UIMenuBar : public IUIPanel {
|
||||
public:
|
||||
void update(EditorContext &context) override;
|
||||
|
||||
std::function<void(entt::entity)> create_entity;
|
||||
std::function<void(std::string_view path)> open_project;
|
||||
};
|
||||
|
||||
|
||||
#endif //B_ENGINE_UIMENUBAR_H
|
||||
53
src/ui/UISceneGraph.cpp
Normal file
53
src/ui/UISceneGraph.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// Created by slinky on 5/11/26.
|
||||
//
|
||||
|
||||
#include "UISceneGraph.h"
|
||||
|
||||
#include "Components.h"
|
||||
#include "imgui.h"
|
||||
#include "Scene.h"
|
||||
|
||||
void UISceneGraph::update(EditorContext &ctx) {
|
||||
ImGui::Begin("Hierarchy");
|
||||
|
||||
if (ImGui::IsWindowHovered() && ImGui::IsMouseClicked(ImGuiMouseButton_Left))
|
||||
{
|
||||
ctx.selectedEntity = entt::null;
|
||||
}
|
||||
|
||||
Scene* scene = ctx.scene;
|
||||
if (!scene) return;
|
||||
|
||||
draw_children(scene->get_root(), scene, ctx);
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void UISceneGraph::draw_children(entt::entity parent, Scene *scene, EditorContext& ctx) {
|
||||
std::vector<entt::entity> children = scene->get_children(parent);
|
||||
for (const auto e : children) {
|
||||
const auto& rel = scene->fetch_component<Components::Relationship>(e);
|
||||
ImGuiTreeNodeFlags flags =
|
||||
ImGuiTreeNodeFlags_OpenOnArrow |
|
||||
ImGuiTreeNodeFlags_SpanFullWidth;
|
||||
|
||||
if (rel.first_child == entt::null) {
|
||||
flags |= ImGuiTreeNodeFlags_Leaf;
|
||||
}
|
||||
|
||||
const auto& [name] = scene->fetch_component<Components::Tag>(e);
|
||||
if (ImGui::TreeNodeEx((void*)(intptr_t)e, flags, "%s", name.data()))
|
||||
{
|
||||
draw_children(e, scene, ctx);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
if (ImGui::IsItemClicked())
|
||||
{
|
||||
ctx.selectedEntity = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
20
src/ui/UISceneGraph.h
Normal file
20
src/ui/UISceneGraph.h
Normal file
@@ -0,0 +1,20 @@
|
||||
//
|
||||
// Created by slinky on 5/11/26.
|
||||
//
|
||||
|
||||
#ifndef B_ENGINE_UISCENEGRAPH_H
|
||||
#define B_ENGINE_UISCENEGRAPH_H
|
||||
|
||||
#include "IUIPanel.h"
|
||||
#include "Scene.h"
|
||||
|
||||
#include "entt/entt.hpp"
|
||||
|
||||
class UISceneGraph : public IUIPanel {
|
||||
public:
|
||||
void update(EditorContext& ctx) override;
|
||||
private:
|
||||
void draw_children(entt::entity e, Scene* scene, EditorContext& ctx);
|
||||
};
|
||||
|
||||
#endif //B_ENGINE_UISCENEGRAPH_H
|
||||
88
src/ui/UISceneViewer.cpp
Normal file
88
src/ui/UISceneViewer.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
//
|
||||
// Created by slinky on 5/11/26.
|
||||
//
|
||||
|
||||
#include "UISceneViewer.h"
|
||||
|
||||
#include "GLFW/glfw3.h"
|
||||
|
||||
UISceneViewer::UISceneViewer() {
|
||||
create_scene_framebuffer();
|
||||
resize_scene_framebuffer(1, 1);
|
||||
}
|
||||
|
||||
void UISceneViewer::update(EditorContext& ctx) {
|
||||
ImGui::Begin("Scene");
|
||||
|
||||
const ImVec2 viewportSize = ImGui::GetContentRegionAvail();
|
||||
if (viewportSize.x > 0.0f && viewportSize.y > 0.0f)
|
||||
{
|
||||
if (sceneViewportSize.x != viewportSize.x ||
|
||||
sceneViewportSize.y != viewportSize.y)
|
||||
{
|
||||
sceneViewportSize = viewportSize;
|
||||
resize_scene_framebuffer((int)sceneViewportSize.x, (int)sceneViewportSize.y);
|
||||
|
||||
ctx.viewportSize = {sceneViewportSize.x, sceneViewportSize.y};
|
||||
ctx.viewportAspectRatio = sceneViewportSize.x / sceneViewportSize.y;
|
||||
}
|
||||
|
||||
ImGui::Image(
|
||||
sceneRenderTexture,
|
||||
viewportSize,
|
||||
ImVec2(0, 1),
|
||||
ImVec2(1, 0)
|
||||
);
|
||||
|
||||
bool hovered = ImGui::IsItemHovered();
|
||||
if (hovered && ImGui::IsMouseClicked(ImGuiMouseButton_Left))
|
||||
{
|
||||
capturedMouse = true;
|
||||
ctx.sceneViewerFocused = true;
|
||||
|
||||
glfwSetInputMode(ctx.window,
|
||||
GLFW_CURSOR,
|
||||
GLFW_CURSOR_DISABLED);
|
||||
}
|
||||
|
||||
if (capturedMouse && ImGui::IsMouseReleased(ImGuiMouseButton_Right))
|
||||
{
|
||||
capturedMouse = false;
|
||||
ctx.sceneViewerFocused = false;
|
||||
|
||||
glfwSetInputMode(ctx.window,
|
||||
GLFW_CURSOR,
|
||||
GLFW_CURSOR_NORMAL);
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void UISceneViewer::bind_fbo() const {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
}
|
||||
|
||||
void UISceneViewer::create_scene_framebuffer() {
|
||||
glGenFramebuffers(1, &fbo);
|
||||
resize_scene_framebuffer(1, 1);
|
||||
}
|
||||
|
||||
void UISceneViewer::resize_scene_framebuffer(int width, int height) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
|
||||
glGenTextures(1, &sceneRenderTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, sceneRenderTexture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, sceneRenderTexture, 0);
|
||||
|
||||
glGenRenderbuffers(1, &rbo);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
}
|
||||
38
src/ui/UISceneViewer.h
Normal file
38
src/ui/UISceneViewer.h
Normal file
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// Created by slinky on 5/11/26.
|
||||
//
|
||||
|
||||
#ifndef B_ENGINE_UISCENEVIEWER_H
|
||||
#define B_ENGINE_UISCENEVIEWER_H
|
||||
|
||||
#include "glad/gl.h"
|
||||
#include "imgui.h"
|
||||
#include "IUIPanel.h"
|
||||
|
||||
#include "Scene.h"
|
||||
#include "Camera.h"
|
||||
|
||||
class UISceneViewer : public IUIPanel {
|
||||
public:
|
||||
UISceneViewer();
|
||||
|
||||
void update(EditorContext& ctx) override;
|
||||
|
||||
void bind_fbo() const;
|
||||
private:
|
||||
ImVec2 sceneViewportSize = { 0.0f, 0.0f };
|
||||
GLuint sceneRenderTexture = 0;
|
||||
GLuint fbo = 0;
|
||||
GLuint rbo = 0;
|
||||
|
||||
Scene* scene = nullptr;
|
||||
Camera* camera = nullptr;
|
||||
|
||||
bool capturedMouse = false;
|
||||
|
||||
void create_scene_framebuffer();
|
||||
void resize_scene_framebuffer(int width, int height);
|
||||
};
|
||||
|
||||
|
||||
#endif //B_ENGINE_UISCENEVIEWER_H
|
||||
Reference in New Issue
Block a user