Skip to content

Commit

Permalink
Version 0.19 is here! Please check CHANGELOG.md for all the changes.
Browse files Browse the repository at this point in the history
  • Loading branch information
TerensTare committed Apr 19, 2021
1 parent ec23c12 commit fad3edf
Show file tree
Hide file tree
Showing 38 changed files with 1,375 additions and 365 deletions.
40 changes: 40 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,46 @@
All changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## [0.1.0a19]
### Added
- `tnt::unroll` on `types/TypeUtils.hpp`, which emulates a partially unrolled loop.
- `json/JsonEnum.hpp`, which adds support for automatically generating json bindings for desired enum types on request. For enabling automatic enum bindings, please modify `tnt::enum_traits<T>` from `types/EnumTraits.hpp` to `true` for your enum `T` like this:
```cpp
enum my_enum { /* some custom values */ };

#include "types/EnumTraits.hpp" // needed for tnt::enum_traits

template <>
struct tnt::enum_traits<my_enum>
{
inline static constexpr my_enum count = my_enum::count; // change this if your enum doesn't have count at the end as a "sentinel"
inline static constexpr bool jsonable = true;
};
```
- `tnt::enum_sentinel<T>`, a variable template that signalises "end of parsing" to enum-stringifying functions on `mirror/Light.hpp`. It can be specialised for your custom enums, and it defaults to `T::count`.
- `tnt::enum_name` for getting a string representation of an enum's name either at compile time or run time.
- `tnt::enum_value` for getting an concrete enum value from a string representation either at compile time or run time.
- Support for `tnt::task<void>`.
- `mirror/Light.hpp` which contains some basic reflection facilities. `tnt::type_name` and `tnt::value_name` now live there.
- `tnt::conceptify` on `types/TypeUtils.hpp`, which helps convert simple type traits to concepts without you needing to write `requires`.
### Changed
- Reduced template instantiations on the new type lists implementation. You can find them on `types/TypeLists.hpp`.
- Improved `tnt::range` to cover some corner cases.
- `tnt::enums` now returns an array of pairs containing the name and the value of the enum.
- `tnt::Vector` is now trivially default constructible. Also the constructor which has a single parameter is now explicit.
- `include/json/*`'s folder files now have a corresponding source file on `src/json`. Also the "registration" technique is changed, but shouldn't affect the code that uses these files.
- `tnt::doo::system_base<T>::clear` now works even if `T` doesn't provide a `clear` method by calling `remove` on each object on `T::active`. Also `tnt::doo::system` doesn't `require` types to provide a `clear` method anymore.
- Methods of `tnt::system<T>` are now conditionally `noexcept` depending on the implementation of these methods on `T`.
### Deprecated
- `tnt::Expected`. Use `tnt::expected` from the same file instead as it offers exceptionless error handling and `constexpr` usage.
### Removed
- Old typelists implementation. It is replaced by the implementation that was previously found on folder `exp`.
- `[[deprecated]]` functions on `tnt::doo::physics_sys`.
## [0.1.0a18]
### Added
- `operator==` for `tnt::bit_mask` types.
Expand Down
46 changes: 17 additions & 29 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ file(
src/core/*.cpp
src/fileIO/*.cpp
src/ImGui/ImGui.cpp
src/json/*.cpp
src/ldtk/*.cpp
src/math/*.cpp
src/pcg/*.cpp
src/tolua/*.cpp
Expand All @@ -122,10 +124,8 @@ add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES})
add_library(TnT::TnT ALIAS TnT)

target_compile_definitions(
${PROJECT_NAME} PUBLIC
TNT_BUILD SOL_PRINT_ERRORS=1 SOL_NO_EXCEPTIONS=1
$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:TNT_PROFILING # When in Debug or RelWithDebInfo build, enable profiling
FMT_COMPILE_TIME_CHECKS=1)
${PROJECT_NAME} PUBLIC TNT_BUILD SOL_PRINT_ERRORS=1 SOL_NO_EXCEPTIONS=1 $<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:TNT_PROFILING # When in Debug or RelWithDebInfo build, enable profiling
FMT_COMPILE_TIME_CHECKS=1)

set_target_properties(
${PROJECT_NAME}
Expand All @@ -135,20 +135,19 @@ set_target_properties(

target_link_libraries(
${PROJECT_NAME}
PRIVATE SDL2::SDL2
SDL2::SDL2main
SDL2::SDL2_image
SDL2::SDL2_mixer
SDL2::SDL2_net
SDL2::SDL2_ttf
${LUA_LIBRARIES}
sol2::sol2
fmt::fmt
nlohmann_json
nlohmann_json::nlohmann_json
# utility targets
project_warnings
project_config)
PUBLIC SDL2::SDL2
SDL2::SDL2main
SDL2::SDL2_image
SDL2::SDL2_mixer
SDL2::SDL2_net
SDL2::SDL2_ttf
${LUA_LIBRARIES}
sol2::sol2
fmt::fmt
nlohmann_json
nlohmann_json::nlohmann_json
# utility targets
PRIVATE project_warnings project_config)

target_include_directories(
${PROJECT_NAME}
Expand Down Expand Up @@ -244,17 +243,6 @@ if(BUILD_EDITOR)
target_link_libraries(
TnTEditor
PRIVATE TnT::TnT
SDL2::SDL2
SDL2::SDL2main
SDL2::SDL2_image
SDL2::SDL2_mixer
SDL2::SDL2_net
SDL2::SDL2_ttf
${LUA_LIBRARIES}
sol2::sol2
fmt::fmt
nlohmann_json
nlohmann_json::nlohmann_json
unofficial::nativefiledialog::nfd
# utility targets
project_warnings
Expand Down
30 changes: 21 additions & 9 deletions include/async/CoUtils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,37 @@
#include <iterator>
#include "async/Generator.hpp"

// clang-format off
namespace tnt
{
namespace detail
{
template <typename T, typename U>
using diff_type = decltype(std::declval<U>() - std::declval<T>());

template <typename T, typename D>
concept advancable_from = requires(T &t, D const d) { std::ranges::advance(t, d); };
}

/// @brief co_yield all the elements within the range [min_, max_) while walking with a certain step on python style.
/// @tparam T The type of min_.
/// @tparam U The type of max_. Same as T by default.
/// @param min_ The first element to co_yield.
/// @param max_ The element one past the range.
/// @param step The number that will be added to min_ each call. Defaults to 1.
template <std::incrementable T, typename U = T>
requires std::equality_comparable_with<T, U>
[[nodiscard]] tnt::generator<T> range(T min_, U max_,
decltype(std::declval<U>() - std::declval<T>()) step =
decltype(std::declval<U>() - std::declval<T>()){1})
template <std::incrementable T, std::equality_comparable_with<T> U = T>
[[nodiscard]] tnt::generator<T> range(
T min_, U max_, detail::diff_type<T, U> step = detail::diff_type<T, U>{1})
{
for (; min_ != max_; min_ += step)
co_yield min_;
if constexpr (detail::advancable_from<T, detail::diff_type<T, U>>)
for (; min_ != max_; std::ranges::advance(min_, step))
co_yield min_;
else if constexpr (std::integral<T> && std::integral<U>)
for (; std::cmp_not_equal(min_, max_); min_ += step) // just in case
co_yield min_;
else
for (; min_ != max_; min_ += step)
co_yield min_;
}
} // namespace tnt
// clang-format on

#endif //!TNT_COROUTINES_UTILITIES_HPP
2 changes: 2 additions & 0 deletions include/async/Generator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,9 @@ struct std::coroutine_traits<tnt::generator<T, Alloc>, std::allocator_arg_t, All
using promise_type = typename tnt::generator<T, Alloc>::promise_type;
};

#ifndef DOXYGEN_SHOULD_SKIP_THIS
template <std::copyable T, tnt::detail::allocator_for<std::byte> Alloc>
inline constexpr bool std::ranges::enable_view<tnt::generator<T, Alloc>> = true;
#endif

#endif //!TNT_ASYNCHRONOUS_COROUTINE_GENERATOR_HPP
49 changes: 42 additions & 7 deletions include/async/Task.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,22 @@
// make await_resume return sth.
// custom allocators.
// test.

// TODO(maybe): specialisation for task<void> ??
// task<void> and task<T&>

namespace tnt
{
// thx Lewiss Baker and Kirit Sælensminde
// https://lewissbaker.github.io/2020/05/11/understanding_symmetric_transfer
// https://kirit.com/How%20C%2B%2B%20coroutines%20work/A%20more%20realistic%20coroutine
template <typename T>
template <typename T = void>
class task final
{
struct void_promise;
struct value_promise;

public:
struct promise_type;
using promise_type = std::conditional_t<
std::is_void_v<T>, void_promise, value_promise>;
struct awaiter;

task(task const &) = delete;
Expand Down Expand Up @@ -59,22 +62,54 @@ namespace tnt
};

template <typename T>
struct task<T>::promise_type final
struct task<T>::void_promise final
{
struct final_awaiter final
{
constexpr bool await_ready() const noexcept { return false; }
constexpr void await_resume() const noexcept {}

inline std::coroutine_handle<> await_suspend(std::coroutine_handle<void_promise> handle) const noexcept
{
return handle.promise().ctx;
}
};

constexpr void return_void() noexcept {}

inline task<T> get_return_object() noexcept
{
return task<T>{std::coroutine_handle<void_promise>::from_promise(*this)};
}

constexpr std::suspend_always initial_suspend() const noexcept { return {}; }
constexpr final_awaiter final_suspend() const noexcept { return {}; }

[[noreturn]] inline void unhandled_exception() const noexcept { std::terminate(); }

private:
std::coroutine_handle<> ctx;

friend task<T>;
};

template <typename T>
struct task<T>::value_promise final
{
struct final_awaiter final
{
constexpr bool await_ready() const noexcept { return false; }
constexpr void await_resume() const noexcept {}

inline std::coroutine_handle<> await_suspend(std::coroutine_handle<promise_type> handle) const noexcept
inline std::coroutine_handle<> await_suspend(std::coroutine_handle<value_promise> handle) const noexcept
{
return handle.promise().ctx;
}
};

inline task<T> get_return_object() noexcept
{
return task<T>{std::coroutine_handle<promise_type>::from_promise(*this)};
return task<T>{std::coroutine_handle<value_promise>::from_promise(*this)};
}

constexpr std::suspend_always initial_suspend() const noexcept { return {}; }
Expand Down
9 changes: 0 additions & 9 deletions include/doo_ecs/Physics.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,6 @@ namespace tnt::doo
/// to be relative to the position of the body.
void add_object(object const &id, physics_comp const &body);

/// @brief Apply the given force to the object with the given id.
/// @param id The id of the object.
/// @param force The force to apply to the object.
[[deprecated("is deprecated. Use operator+= on ::force[id] instead.")]] void addForce(object const &id, tnt::Vector const &force_) noexcept;

/// @brief Add a force that would be applied to each object when Update is called.
/// @param force The force to be applied.
[[deprecated("is deprecated. Use operator+= on ::totalForce instead.")]] void addGlobalForce(tnt::Vector const &force_) noexcept;

/// @brief Update the physics data of the object with the given id.
/// @param id The id of the object to update.
/// @param time_ The time that passed since the last update call.
Expand Down
16 changes: 0 additions & 16 deletions include/doo_ecs/Scripts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,6 @@
// TODO:
// find a way to support script reloading.
// remove unnecessary #include-s.
// load custom Lua bindings for each objects from json or code.

namespace tnt::lua
{
NLOHMANN_JSON_SERIALIZE_ENUM(
lib, {{lib::audio, "audio"},
{lib::core, "core"},
{lib::imgui, "imgui"},
{lib::input, "input"},
{lib::math, "math"},
{lib::rect, "rect"},
{lib::utils, "utils"},
{lib::vector, "vector"},
{lib::window, "window"}})
}

namespace tnt::doo
{
Expand All @@ -36,7 +21,6 @@ namespace tnt::doo
/// @brief The name of the *.lua script to attach to the next object.
/// @param id The id of the object to add to the scripting system.
/// @param filename The name of the .lua script file.
/// @param libs The desired libraries you need for this object. Defaults to @ref tnt::lua::lib::core.
void add_object(object const &id, std::string_view filename);

/// @brief Run `init()` from the object's lua script. If no function named init() is found, it does nothing.
Expand Down
27 changes: 19 additions & 8 deletions include/doo_ecs/System.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
// TODO:
// noexcept
// draw_imgui
// if the system provides remove and active, but not clear, declare clear to be remove on each object

// TODO(maybe):
// store base() in a member reference ??
Expand All @@ -35,7 +34,6 @@ namespace tnt::doo
typename T::component const& c) {
{ t.add_object(o, c) } -> detail::void_type;
{ t.remove(o) } -> detail::void_type;
{ t.clear() } -> detail::void_type;
{ t.Update(o, 1.f) } -> detail::void_type;

{ t.from_json(o, j) } -> detail::void_type;
Expand All @@ -60,41 +58,54 @@ namespace tnt::doo
/// @brief Add the data of the object with given id to the system.
/// @param id The id of the object.
/// @param c The component data.
inline void add_object(object const &id, component const &c)
inline void add_object(object const &id, component const &c) noexcept(
noexcept(this->base().add_object(id, c)))
{
this->base().add_object(id, c);
}

/// @brief Update the data of the desired object.
/// @param id The id of the object.
/// @param time_ The time elapsed since the last Update call.
inline void Update(object const &id, float time_)
inline void Update(object const &id, float time_) noexcept(
noexcept(this->base().Update(id, time_)))
{
this->base().Update(id, time_);
}

/// @brief Remove the data of the desired object from the system.
/// @param id The id of the object to remove.
inline void remove(object const &id)
inline void remove(object const &id) noexcept(
noexcept(this->base().remove(id)))
{
this->base().remove(id);
}

/// @brief Remove the data of all the objects from the system.
inline void clear() noexcept(noexcept(base().clear())) { this->base().clear(); }
inline void clear()
{
if constexpr (requires { this->base().clear(); })
this->base().clear();
else
for (auto const &active = this->base().active;
auto const &o : active)
this->base().remove(o);
}

/// @brief Load the data of an object from a json chunk.
/// @param id The id of the desired object.
/// @param j The json chunk containing the data of the component.
inline void from_json(object const &id, nlohmann::json const &j)
inline void from_json(object const &id, nlohmann::json const &j) noexcept(
noexcept(this->base().from_json(id, j)))
{
this->base().from_json(id, j);
}

/// @brief Serialize the component data of the given object to a json chunk.
/// @param id The id of the desired object.
/// @param j The json chunk where the data will be stored.
inline void to_json(object const &id, nlohmann::json &j)
inline void to_json(object const &id, nlohmann::json &j) noexcept(
noexcept(this->base().to_json(id, j)))
{
this->base().to_json(id, j);
}
Expand Down
Loading

0 comments on commit fad3edf

Please sign in to comment.