possseidon / dang-lib Goto Github PK
View Code? Open in Web Editor NEWA C++ library, providing a variety of useful classes focused around game developement.
A C++ library, providing a variety of useful classes focused around game developement.
TODO
Currently bounds can only be iterated in reverse order, e.g. ibounds3
will iterate in ZYX
order:
for (auto vec : dmath::ibounds3{{2, 2, 2}})
std::cout << vec << '\n';
is equivalent to
for (int x = 0; x < 2; x++)
for (int y = 0; y < 2; y++)
for (int z = 0; z < 2; z++)
std::cout << "[" << x << ", " << y << ", " << z << "]\n";
and will output:
[0, 0, 0]
[0, 0, 1]
[0, 1, 0]
[0, 1, 1]
[1, 0, 0]
[1, 0, 1]
[1, 1, 0]
[1, 1, 1]
Different orders can currently be achieved by simply swizzling the iterated vector with the desired order, although it has to be specified in reverse, as vec.xyz()
is equivalent to just vec
and iterates as shown as ZYX
.
XYZ
, so that swizzling becomes more intuitive.
XYZ
or ZYX
is more intuitive as a default.x
, y
and z
, it iterates in ZYX
order.Keep in mind, that ZYX
is likely still going to be the most used scenario, as it is more cache friendly for an array int[x][y][z]
.
The more I write this and think about it, I might just leave it like it is, but keep it here, in case there is a better solution.
When possible, try to put the implementation of the ClassInfo
specialization in a .cpp file and instantiate them manually with the "template
..." syntax.
std::unique_ptr
std::shared_ptr
std::weak_ptr
TODO: Elaborate on how to implement that.
Since MultiTextureAtlas
is templated, it cannot be created dynamically with different sizes, which might be necessary in scripting or some other rare use cases in which the size is not known at compile time.
Therefore NamedMultiTextureAtlas
shall use string keys for the different SubTextures (using a map) and IndexedMultiTextureAtlas
shall use integer keys in the form of std::size_t
(using a vector).
The names/count should be given at construction however, as once the first texture is added, it does not make much sense to add another SubTexture afterwards, so we might as well give it directly at construction.
Property
class in dang-utils or similar.From the list above, these attributes are going to be required for a sprite shader:
vec3 pos;
vec4 tint;
vec2 texcoord1;
vec2 texcoord2;
float texture_fade;
float texture_opacity;
E.g. dmath.Line3
is still a proper table with all the functions and even creating instances works, but the instance itself just formats as [false, false]
and doesn't have any functions.
Something is very, very fishy.
The progress on Lua State and Thread related functions and also freestanding utility functions/macros.
lua_atpanic
used in State::replacePanicFunction
lua_close
used in OwnedState::close
lua_gc
used in State::gc
private helper functionlua_getallocf
used in State::getAllocator
lua_getextraspace
used in State::extraspace
- TODO: typesafetylua_newstate
used in OwnedState::OwnedState
lua_register
lua_setallocf
used in State::setAllocator
lua_setcstacklimit
lua_setwarnf
lua_version
used in State::version
lua_warning
luaL_checkversion
used in State::checkVersion
luaL_newstate
used in OwnedState::OwnedState
luaL_openlibs
used in State::openLibs
lua_isyieldable
used in State::isYieldable
lua_status
used in State::status
lua_numbertointeger
lua_upvalueindex
used in various places regarding upvalue indiceslua_typename
All in namespace dang::math::color
.
There are various representations that should be convertible to each other:
dang-lib/dang-gl/src/Camera.cpp
Line 149 in dbc32a5
The main problem here, is that numbers are implicitly converted to strings, which has to actually replace the value on the Lua stack in-place, which can lead to all kinds of trouble. It also prevents their respective wrapper functions from being marked as const
, even though only this single conversion actually has this problem.
Plan A would be to add new functions checkExact
and atExact
/toExact
, that only work for exact types. The state and index wrapper functions can be marked as const
.
The only real difference would be, that it prevents these implicit conversions:
of which only number to string is actually posing problems.
Additionally, maybe something like this could make sense:
void func(dlua::exact<std::string> must_be_string) {}
void func(dlua::exact<bool> must_be_boolean) {}
... but I'm not a 100% sure yet if that would be a great idea.
Plan B would be to ALWAYS use these exact conversions, since implicit conversions are rarely used like this anyways.
This also raises the question, if only the problematic number to string conversion should be disabled, or also string to number, which does not pose a problem. At the very least, any to boolean conversion should probably stay.
For a functional style of programming it is very useful to have access to all the methods directly.
For example, given a table values
of vec3
, if one would want to sort them by length, then this:
table.sort(values, by(vec3.getLength))
is a lot nicer (and more performant) than this:
table.sort(values, by(function(vector) return vector:getLength() end))
-- or
table.sort(values, by(vec3().getLength))
(Where by
returns a comparator based on the given projection function)
Currently all tiles of a texture atlas must have a unique string name, which can be inconvenient.
Thus, add the ability to create unnamed tiles as well.
TileData
into a vector of std::unique_ptr<TileData>
.name
field inside TileData
simply contains an empty string for these unnamed tiles.name
field inside TileData
into a (possibly null) pointer to the same string in the map to save space.The following pattern is heavily used in the current Lua bindings:
constexpr auto function = +[] {};
dlua::wrap<function>;
This is very convenient, as the full context of the class (for e.g. type aliases) is available inside the lambda.
This works fine on msvc and clang, but gcc gives an error, stating that the lambda cannot be used as it has no linkage - except it doesn't actually give this error at the moment. Everything compiles just fine with gcc... or does it?
The reason it compiles is the (un)lucky coincidence of:
Basically, upgrading gcc or moving the lambdas somewhere that isn't templated will (likely) cause the error.
There are several ways on how one can work around this issue.
std::function
The probably easiest fix would be to simply type-erase the lambda with a std::function
. This even has the benefit of having a nice signature when printing in Lua. However it comes with a decent performance hit.
Simply replacing the lambdas with free-standing functions e.g. right in front of the function in which they are used is generally a good alternative. Context from the class is lost however.
This way, context of the class can be retained. Implementations have to be put in the header however, although that is hopefully not a big deal.
This also has the added benefit of allowing for re-use of wrappers between e.g. methods()
and properties()
.
Another option would be to use proper static functions, but implementing them is very verbose, as the entire template header has to be repeated for each and every function.
Use static constexpr lambdas (approach 3) like so:
template <>
struct ClassInfo<Foo> {
static std::array<luaL_Reg> methods();
private:
static constexpr auto bar = +[] {};
};
template <>
std::array<luaL_Reg> ClassInfo<Foo>::methods()
{
return {reg<bar>("bar")};
}
If a lot of similar tiles are added to a texture atlas, multiple layers for the same tile size will be created. If a lot of random tiles are removed now, this is going to create a lot of unused space in all layers, which can only be reclaimed by actually using it for newly added tiles.
Therefore a deflate
function could try and reclaim all that unused space and shrink down the layer count.
Go through all tiles, call layerForTile
to find the smallest layer index and see if it is smaller than the current one, which means an earlier layer has space for this tile. If this is the case, remove it from the current layer and add it to that layer.
The most efficient way here, would be to start with the tiles in the last layer. Otherwise, a lot of tiles might get shifted along as new spaces keeps opening up in lower layers.
The order to process the layer itself in doesn't really matter all that much unless shrink_to_fit
is called on the tiles vector. Then back to front is favorable again.
The progress on Stack related Lua functions that do not mutate the Stack and can therefore be const
.
lua_absindex
lua_checkstack
used in State::checkPushable
lua_compare
used in State::compare
lua_dump
use in State::dump
lua_error
used indirectly in State::error
with a [[noreturn]]
wrapperlua_gettop
used once in State::State
and for LUA_MULTRET
callslua_isboolean
used in Convert<bool>
and State::isBoolean
lua_iscfunction
used in Convert<lua_CFunction>
and State::isCFunction
lua_isfunction
used in State::isFunction
lua_isinteger
used in State::isInteger
lua_islightuserdata
used in State::isLightUserdata
lua_isnil
used in ConvertNil
and State::isNil
lua_isnone
used in State::isNone
lua_isnoneornil
used in ConvertNil
, Convert<std::optional<T>>
and State::isNoneOrNil
lua_isnumber
used in ConvertFloatingPoint
and State::isNumber
lua_isstring
used in Convert<std::string>
, Convert<std::string_view>
and State::isString
lua_istable
used in State::isTable
lua_isthread
used in State::isThread
lua_isuserdata
used in State::isUserdata
lua_rawequal
lua_rawlen
used in State::rawLength
lua_toboolean
used in Convert<bool>
lua_tocfunction
used in Convert<lua_CFunction>
lua_tointeger
lua_tointegerx
used in ConvertIntegral
lua_tonumber
lua_tonumberx
used in ConvertFloatingPoint
lua_topointer
lua_tothread
lua_touserdata
only used in Convert::cleanup
currentlylua_type
used in various Convert
templates and State::type
luaL_argcheck
luaL_argerror
used in various Convert
templates and State::argError
luaL_argexpected
luaL_checkany
luaL_checkinteger
used in ConvertIntegral
luaL_checknumber
used in ConvertFloatingPoint
luaL_checkoption
used in Convert
for enumsluaL_checkstack
used in State::ensurePushable
and wrap
luaL_checktype
luaL_checkudata
used in Convert
for userdata, always failing, just to get a good error messageluaL_error
luaL_len
used in State::length
luaL_opt
luaL_optinteger
luaL_optnumber
luaL_setmetatable
luaL_testudata
used in Convert
for userdataluaL_typeerror
used indirectly in State::typeError
with a [[noreturn]]
wrapperluaL_typename
used in Convert<std::variant<T...>>
and State::typeName
luaL_unref
used in Reference::~Reference
dang-lib/dang-gl/src/Program.cpp
Line 19 in 441aeb7
Try to replace the existing manual dllexport
macro magic with GenerateExportHeader.
Basically create a new catching dlua::wrap that looks something like this:
try {
return dlua::wrap(...);
}
catch (const std::exception& e) {
// throw Lua error with e.what()
}
catch (...) {
// throw Lua error with generic message
}
Enums values can have various different layouts, of which only those that start at zero, and are consecutive, are currently supported for iteration, EnumArray
and EnumSet
. It should be possible to get other layouts to work efficiently for these use-cases as well.
Below a list of all the possible thinkable arrangements of enum values:
This is the most simple and most common way. Simply specializing EnumCount
allows:
EnumArray
.EnumSet
.Less common than the previous option, but thinkable. This can be solved in two ways:
EnumCount
that defaults to zero.I will try the first approach, unless I stumble upon problems with it.
Iteration and usage with EnumArray
and EnumSet
is still very straightforward.
This is getting a bit more tricky, but still solvable:
Instead of specializing EnumCount
, add a new EnumValues
to specialize and provide every single value, possibly as a template parameter.
EnumArray
might be a bit more tricky:
EnumSet
should mask on these values.
EnumArray
idea.EnumValues
EnumArray
and EnumSet
would not be feasible without the proposed mapping approach.EnumCount
.EnumValues
class that can be specialized to provide all values as template parameters.EnumArray
and EnumSet
to respect the "first value" and also work with EnumValues
.PackedEnumArray
and PackedEnumSet
, which, rather than having padding, map the enum values back and forth.Currently Xml Doc Comments are used for code documentation. They are extremely verbose and annoying to edit and maintain. Visual Studio uses them by default and generates them automatically for an entity (function, class, ...) when you type ///
in front of it.
There is a variety of different less verbose styles you can get Visual Studio to use:
/// <summary>
/// Adds two numbers.
/// </summary>
/// <param name="a">The first operand.</param>
/// <param name="b">The second operand.</param>
/// <returns>The sum of both operands.</returns>
int add(int a, int b);
/// @brief Adds two numbers.
/// @param a The first operand.
/// @param b The second operand.
/// @return The sum of both operands.
int add(int a, int b);
Alternatively //!
can also be used.
There is also two options using multi-line comments, (namely /**
and /*!
) but they don't auto-generate unfortunately.
That leaves Doxygen with style of ///
and //!
as the remaining possibilities of which I have chosen ///
because it's easier to type.
Another feature I had in Pengine in the form of "SubTextures".
This MultiTextureAtlas
should to not have a single texture, but instead have multiple, that all share their layout of all the images.
Give tiles an optional reference to a list of related tiles, which is especially useful for animations and fonts.
This list should be owned by the TextureAtlas itself and only be referenced by each and every SubTile that is part of the collection.
Related to #64. When running test-State.cpp tests with WSL gcc, catch2 reports 12 assertions less than when using Windows msvc or clang.
Find out why.
An easy way to check for discrepancies would be to run both tests with verbose output and compare those.
Currently max_layer_count_
is queried, but it's not actually used to check anything. (Great!)
Add these checks and throw an actual exception if this number exceeds this limit.
Think about maybe using return values (like std::expected
) over actual exceptions, but it's not something that should happen often, so exceptions are probably fine. The question is how expensive the try-catch
version of dlua::wrap
is, I should measure that. The "good-path" is usually pretty fast though, so it's likely okay to just use exceptions (and make sure not to forget to use the try-catch
version of dlua::wrap
).
Specialize ClassInfo
to support std::regex
and friends.
BitSetMeta
and friends provide a nice abstraction around any bitset that is stored in continuous memory.
Currently the naming is (mostly) consistent but there are some things I want to change.
camelCase
snake_case
snake_case_
with trailing underscorePascalCase
with a few exceptions:
lowercase
to stay consistent with GLSL (excluding geometry.h
)snake_case
plus _v
or _t
, staying consistent with STLTPascalCase
or just T
if appropriatev_snake_case
or just v
if appropriateAlso put this list somewhere in the repo.
Currently a TextureAtlas
stores all the image data forever. This is actually required, as new textures might be added later on, which might in turn require the underlying array texture to resize to fit all tiles, which then invalidates the already existing tiles.
However keeping all those textures around forever is quite expensive. Therefore a way to free all texture data should exist.
Of course, once all the textures are freed, no new textures can be added anymore, as this might require a resize again. To prevent this, upon freeing the textures the TextureAtlas
should be in a frozen state, preventing any further modification.
It is very rare, that you actually want to keep all the texture data around, once everything has been loaded and the array texture been generated. Freeing everything is almost always the right choice afterwards.
Simple implementation:
update
function, that only updates the texture without freeing any image data.freeze
function, that updates the texture and frees all image data.Idea without exceptions:
FrozenTextureAtlas
that is read-only.FrozenTextureAtlas
has an actual TextureAtlas
member variable, which gets moved in but only exposes const functions.
Additional afterthoughts:
std::variant
of various image formats or even just a bitfield for hit-tests.Image<bool>
specialization for that? Sounds like a neat idea.Yeah... TileHandles are pretty useless in their current form...
Implement some sort of sky-box.
This is regarding function names such as:
Vector::normalize();
From the name of the function, one might expect this to normalize the vector in place, however a new vector is returned instead. A better name (albeit slightly longer) would therefore be normalized
.
Go through the entirety of dang-math and fix the names.
Also update Lua bindings:
normalized
or solvable
.getNormalized
or isSolvable
methods to still allow use in a functional sense.Whenever a tile is removed, the corresponding layer might be completely empty. If this is the case, it should be removed instead of staying around forever, if no other tile is ever going to belong to a layer of this type.
position.z
by one.written
flag must be cleared.In Pengine a texture could come with a .info
file with the same name (json under the hood), which would describe, how the image should be split up.
There were various modes for different use cases:
Grid
Region
Font
This "info" structure should not be bound to a file format anymore and work standalone. Creating an actual file format for it is a separate issue.
The progress on Buffer related Lua functions.
luaL_addchar
luaL_addgsub
luaL_addsize
luaL_addlstring
luaL_addstring
luaL_buffaddr
luaL_buffinit
luaL_bufflen
luaL_buffinitsize
luaL_buffsub
luaL_prepbuffer
luaL_prepbuffsize
luaL_addvalue
luaL_pushresult
luaL_pushresultsize
Original title: "Make default constructor of all gl types do nothing and add "create" static functions."
Make them behave more like std::unique_ptr
basically.
The progress on functions, that belong to the Lua Debug library.
lua_gethook
lua_gethookcount
lua_gethookmask
lua_getinfo
lua_getlocal
lua_getstack
lua_getupvalue
lua_sethook
lua_setlocal
lua_setupvalue
lua_upvalueid
lua_upvaluejoin
bounds.h
consts.h
enums.h
-> lua-enums.h
geometry.h
-> lua-geometry.h
interpolation.h
marchingcubes.h
matrix.h
-> lua-vector-matrix.h
noise.h
(not commited yet)quaternion.h
utils.h
-> Currently doesn't have anything that can't be done with Lua's builtin math library.vector.h
-> lua-vector-matrix.h
OpenGL debug messages are not GLFW specific and therefore shouldn't be part of the GLFW Window class.
This also includes the different enumeration types for severity and such, which are currently declared in Window.h as well.
Some graphics cards might have a very big max size for 3D textures. If this is the case and a lot of textures are added to reach this maximum, this is at first not a problem.
The problem comes, when additionally a lot of other textures that all need their own layer get added. Each of these layers must be as big as this other huge layer (since that is how array textures work). Limiting this size up front, causing the many initial, same-sized textures to be split up over multiple layers can greatly reduce this cost.
The maximum size of 3D textures seems to generally be a lot smaller than 2D textures though (2048x2048 for me, which is also the minimum that the OpenGL 4.3 spec enforces; for 2D textures 16384x16384), but there might be some graphics card out there, that has a very big max-size but not enough memory to handle a lot of layers.
enum.h
event.h
metaclass.h
utils.h
TODO
The progress on Stack related Lua functions that mutate the Stack.
lua_arith
used in State::unary
, State::binary
and State::arith
lua_call
used in State::call
and State::callReturning
lua_callk
lua_concat
used in State::concat
lua_copy
used in State::replace
lua_createtable
used in State::pushTable
lua_getglobal
used in State::getGlobalWithType
lua_getfield
used in State::getTableWithType
lua_geti
used in State::getTableWithType
lua_getiuservalue
lua_getmetatable
used in State::getMetatable
lua_gettable
used in State::getTableWithType
lua_insert
(invalidates indices)lua_len
used in State::pushLength
lua_load
lua_newtable
lua_newthread
used in State::pushThread
lua_newuserdatauv
lua_next
used in State::next
lua_pcall
used in State::pcall
and State::pcallReturning
lua_pcallk
lua_pop
used in State::pop
lua_pushboolean
used in Convert<bool>
lua_pushcclosure
used in State::pushFunction
lua_pushcfunction
used in Convert<lua_CFunction>
lua_pushfstring
lua_pushglobaltable
used in State::pushGlobalTable
lua_pushinteger
used in ConvertIntegral
lua_pushlightuserdata
lua_pushliteral
lua_pushlstring
used in various string related Convert
templateslua_pushnil
used in ConvertNil
and Convert<std::optional<T>>
lua_pushnumber
used in ConvertFloatingPoint
lua_pushstring
used in Convert<const char*>
and Convert
for enumslua_pushthread
lua_pushvalue
used in ConvertIndex::push
lua_pushvfstring
lua_rawget
used in State::rawGetTableWithType
lua_rawgeti
used in State::rawGetTableWithType
lua_rawgetp
used in State::rawGetTableWithType
lua_rawset
used in State::rawSetTable
lua_rawseti
used in State::rawSetTable
lua_rawsetp
used in State::rawSetTable
lua_remove
used in State::remove
lua_replace
used in State::replace
lua_resetthread
lua_resume
lua_rotate
(invalidates indices)lua_setfield
used in State::setTable
lua_setglobal
used in State::setGlobal
and State::registerGlobal
lua_seti
used in State::setTable
lua_setiuservalue
lua_setmetatable
used in State::setMetatable
lua_settable
used in State::setTable
lua_settop
used in State::padWithNil
lua_stringtonumber
lua_toclose
used in State::toClose
lua_tolstring
used in Convert<std::string>
and Convert<std::string_view>
lua_tostring
lua_xmove
lua_yield
lua_yieldk
luaL_callmeta
used in State::callMeta
luaL_checklstring
used in Convert<std::string>
and Convert<std::string_view>
luaL_checkstring
luaL_dofile
luaL_dostring
luaL_execresult
luaL_fileresult
luaL_getmetafield
used in State::getMetaFieldWithType
and State::getMetaField
luaL_getmetatable
luaL_getsubtable
luaL_gsub
luaL_loadbuffer
luaL_loadbufferx
used in State::load
luaL_loadfile
luaL_loadfilex
luaL_loadstring
luaL_newlib
luaL_newlibtable
luaL_newmetatable
used in Convert
for userdataluaL_optlstring
luaL_optstring
luaL_pushfail
luaL_ref
used in Reference::Reference
luaL_requiref
used in State::openLib
, ::pushLib
, ::require
and ::pushRequire
luaL_setfuncs
luaL_tolstring
used in State::format
luaL_traceback
luaL_where
Maybe structure it somewhat similar to the old filters when the project still used a Visual Studio Solution instead of CMake.
TODO: Think of a good structure.
Add ClassInfo
specializations for all the STL containers.
Should be one-indexed to stay consistent with Lua.
std::array
std::vector
std::deque
std::forward_list
std::list
std::initializer_list
(not strictly a container)std::span
(C++20, also not strictly a container)std::set
std::multiset
std::map
std::multimap
std::unordered_set
std::unordered_multiset
std::unordered_map
std::unordered_multimap
std::stack
std::queue
std::priority_queue
Allow for conversion between Lua tables and varargs in various representations.
Even though it can be used to keep the stack clean, it is actually fairly inefficient to call lua_pop
for every single individual value. Instead ScopedStack
should be used, as it can clean up a whole bunch of leftover at once and is a lot simpler in general.
It should however still be possible to manually pop a single value without any additional cost, for cases in which the stack needs to be prevented from growing (because of a loop for example). Although, usually ScopedStack
is probably the better choice in those cases and the for
wrappers have this functionality built-in.
Therefore:
lua_...
function is responsible for it.pop()
function in addition to the existing popIfTop()
, that only does an assert(isTop())
.KISS! Don't overcomplicate stuff. The whole Lua library is already complicated enough.
Currently TextureAtlas
has a hard requirement on Texture2DArray
(and an OpenGL context because of max_array_texture_layers
and max_3d_texture_size
). The generation of the tiles should not have this requirement. This will also improve testability.
Idea on how to split this dependency out:
TextureAtlas
to TextureAtlasTiles
and get rid of the dependency on Texture2DArray
.context
to query max_array_texture_layers
and max_3d_texture_size
.
generateTexture
to updateTexture
and modify it in conjunction with TextureAtlas::Layer::drawTile(s)
.
std::function
with the same signature as Texture2DArray::modify
.TextureAtlas
class that aggregates this TextureAtlasTiles
together with an actual Texture2DArray
.TextureAtlasTiles
functions and forward the textures modify function to update
.max_array_texture_layers
and max_3d_texture_size
can be queried from the context again.A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.