skypjack / entt

Gaming meets modern C++ - a fast and reliable entity component system (ECS) and much more
https://github.com/skypjack/entt/wiki
MIT License
10.05k stars 881 forks source link

Is it possible to call functions from components? #997

Closed 0LGL0 closed 1 year ago

0LGL0 commented 1 year ago

I would like to know if it is possible to call functions from components. If so, why is my function not working? Here is my function: https://gist.github.com/0LGL0/9a32dda2b822cbc045ed7153387045c7

My function is needed to copy one component passed to the template to a passed entity with the same component. Here is the "hasAllComponents" function: https://gist.github.com/0LGL0/a8597d58cba50e45330ada311153582c. This is the "GetComponent" function: https://gist.github.com/0LGL0/08e5e801701af65e19cfd7d53bbe3c04. An example of one of my components (they all contain the "clone" function): https://gist.github.com/0LGL0/03b4bd8f8bde99ad36312c9e429e63a3. And the function where I call the "copyComponent" function: https://gist.github.com/0LGL0/c8df1666e2fcdc864fa5678cb4c39525.

"visit" is my function, which simply iterates through all the components that I have and passes to the lambda function argument only those components that are in this entity

skypjack commented 1 year ago

I would like to know if it is possible to call functions from components.

I barely get what you mean but yeah, I don't see the problem. EnTT doesn't really care about what you do with your components. When you get them, you've no limits:

auto &component = registry.get<Type>(entity);
// do what you like with your component here

As for your question:

why is my function not working?

It's almost impossible to say what's wrong in your code without a repro. I'm sorry. That being said, it's very likely that EnTT isn't your problem here.

0LGL0 commented 1 year ago

@skypjack, then here's the output from Visual Studio: Build started... 1>------ Build started: Project: Hyko, Configuration: Debug x64 ------ 1>D:\VisualStudio_Integrade\MSBuild\Microsoft\VC\v170\Microsoft.CppBuild.targets(502,5): warning MSB8004: Intermediate Directory does not end with a trailing slash. This build instance will add the slash as it is required to allow proper evaluation of the Intermediate Directory. 1>D:\VisualStudio_Integrade\MSBuild\Microsoft\VC\v170\Microsoft.CppBuild.targets(503,5): warning MSB8004: Output Directory does not end with a trailing slash. This build instance will add the slash as it is required to allow proper evaluation of the Output Directory. 1>Scene.cpp 1>C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\shared\minwindef.h(130,1): warning C4005: 'APIENTRY': macro redefinition 1>D:\C++\Hyko_Engine\libs\GLAD\include\glad\glad.h(32,1): message : see previous definition of 'APIENTRY' 1>D:\C++\Hyko_Engine\Hyko\src\Engine\Scene\Scene.cpp(80,57): warning C4267: 'return': conversion from 'size_t' to 'int', possible loss of data 1>D:\C++\Hyko_Engine\Hyko\src\libSource\entt\entt.hpp(1801,32): error C2338: static_assert failed: 'Ill-formed request' 1>D:\C++\Hyko_Engine\Hyko\src\libSource\entt\entt.hpp(1904,114): message : see reference to function template instantiation 'auto entt::internal::uses_allocator_construction::args<Allocator,Hyko::Entity&>(const Allocator &,Hyko::Entity &) noexcept' being compiled 1> with 1> [ 1> Allocator=std::allocator 1> ] 1>D:\C++\Hyko_Engine\Hyko\src\libSource\entt\entt.hpp(18414,1): message : see reference to function template instantiation 'Type entt::uninitialized_construct_using_allocator<Hyko::TagComponent,std::allocator,Hyko::Entity&>(Type ,const Allocator &,Hyko::Entity &)' being compiled 1> with 1> [ 1> Type=Hyko::TagComponent, 1> Allocator=std::allocator 1> ] 1>D:\C++\Hyko_Engine\Hyko\src\libSource\entt\entt.hpp(18809,1): message : see reference to function template instantiation 'entt::internal::sparse_set_iterator<std::vector<entt::entity,std::allocator>> entt::basic_storage<Type,Entity,Allocator,void>::emplace_element<Hyko::Entity&>(const Entity,const bool,Hyko::Entity &)' being compiled 1> with 1> [ 1> Entity=entt::entity, 1> Type=Hyko::TagComponent, 1> Allocator=std::allocator 1> ] 1>D:\C++\Hyko_Engine\Hyko\src\libSource\entt\entt.hpp(18102,1): message : see reference to function template instantiation 'Hyko::TagComponent &entt::basic_storage<Type,Entity,Allocator,void>::emplace<Hyko::Entity&>(const entt::entity,Hyko::Entity &)' being compiled 1> with 1> [ 1> Type=Hyko::TagComponent, 1> Entity=entt::entity, 1> Allocator=std::allocator 1> ] 1>D:\C++\Hyko_Engine\Hyko\src\libSource\entt\entt.hpp(18104,22): message : see reference to function template instantiation 'Hyko::TagComponent &entt::basic_storage<Type,Entity,Allocator,void>::emplace<Hyko::Entity&>(const entt::entity,Hyko::Entity &)' being compiled 1> with 1> [ 1> Type=Hyko::TagComponent, 1> Entity=entt::entity, 1> Allocator=std::allocator 1> ] 1>D:\C++\Hyko_Engine\Hyko\src\libSource\entt\entt.hpp(35245,1): message : see reference to function template instantiation 'Hyko::TagComponent &entt::sigh_storage_mixin<entt::basic_storage<Type,Entity,Allocator,void>>::emplace<Hyko::Entity&>(const entt::entity,Hyko::Entity &)' being compiled 1> with 1> [ 1> Type=Hyko::TagComponent, 1> Entity=entt::entity, 1> Allocator=std::allocator 1> ] 1>D:\C++\Hyko_Engine\Hyko\src\Engine\Scene\Entity\Entity.h(23,3): message : see reference to function template instantiation 'Hyko::TagComponent &entt::basic_registry<entt::entity,std::allocator>::emplace<comp,Hyko::Entity&>(const entt::entity,Hyko::Entity &)' being compiled 1> with 1> [ 1> Entity=entt::entity 1> ] 1>D:\C++\Hyko_Engine\Hyko\src\Engine\Scene\Scene.cpp(49,9): message : see reference to function template instantiation 'T &Hyko::Entity::addComponent<comp,Hyko::Entity&>(Hyko::Entity &)' being compiled 1> with 1> [ 1> T=comp 1> ] 1>D:\C++\Hyko_Engine\Hyko\src\Engine\Scene\Entity\Entity.h(49,3): message : see reference to function template instantiation 'void Hyko::Scene::copyEntity::::operator ()(const _T1) const' being compiled 1> with 1> [ 1> T=Hyko::TagComponent, 1> _T1=Hyko::TagComponent 1> ] 1>D:\C++\Hyko_Engine\Hyko\src\Engine\Scene\Scene.cpp(49,10): message : see reference to function template instantiation 'void Hyko::Entity::visit<Hyko::Scene::copyEntity::>(Func)' being compiled 1> with 1> [ 1> Func=Hyko::Scene::copyEntity:: 1> ] 1>D:\C++\Hyko_Engine\Hyko\src\libSource\entt\entt.hpp(1806,36): error C2338: static_assert failed: 'Ill-formed request' 1>D:\C++\Hyko_Engine\Hyko\src\libSource\entt\entt.hpp(1905,71): error C2661: 'Hyko::TagComponent::TagComponent': no overloaded function takes 2 arguments 1>D:\C++\Hyko_Engine\Hyko\src\libSource\entt\entt.hpp(1905,71): message : while trying to match the argument list '(Hyko::Entity, const std::allocator)' 1>D:\VisualStudio_Integrade\VC\Tools\MSVC\14.34.31933\include\type_traits(1470,1): message : see reference to function template instantiation 'auto entt::uninitialized_construct_using_allocator::::operator ()<Hyko::Entity&,const Allocator&>(Hyko::Entity &,const Allocator &) const' being compiled 1> with 1> [ 1> Allocator=std::allocator 1> ] 1>D:\VisualStudio_Integrade\VC\Tools\MSVC\14.34.31933\include\tuple(878,26): message : see reference to function template instantiation 'decltype(auto) std::_Apply_impl<_Ty,std::tuple<Hyko::Entity &,const Allocator &>,0,1>(_Callable &&,_Tuple &&,std::integer_sequence<size_t,0,1>) noexcept()' being compiled 1> with 1> [ 1> _Ty=entt::uninitialized_construct_using_allocator::, 1> Allocator=std::allocator, 1> _Callable=entt::uninitialized_construct_using_allocator::, 1> _Tuple=std::tuple<Hyko::Entity &,const std::allocator &> 1> ] 1>D:\VisualStudio_Integrade\VC\Tools\MSVC\14.34.31933\include\tuple(884,26): message : see reference to function template instantiation 'decltype(auto) std::apply<entt::uninitialized_construct_using_allocator::,std::tuple<Hyko::Entity &,const Allocator &>>(_Callable &&,_Tuple &&) noexcept()' being compiled 1> with 1> [ 1> Allocator=std::allocator, 1> _Callable=entt::uninitialized_construct_using_allocator::, 1> _Tuple=std::tuple<Hyko::Entity &,const std::allocator &> 1> ] 1>D:\VisualStudio_Integrade\VC\Tools\MSVC\14.34.31933\include\tuple(879,25): error C2672: 'invoke': no matching overloaded function found 1>D:\VisualStudio_Integrade\VC\Tools\MSVC\14.34.31933\include\type_traits(1566,19): message : could be 'unknown-type std::invoke(_Callable &&,_Ty1 &&,_Types2 &&...) noexcept()' 1>D:\VisualStudio_Integrade\VC\Tools\MSVC\14.34.31933\include\type_traits(1560,19): message : or 'unknown-type std::invoke(_Callable &&) noexcept()' 1>D:\VisualStudio_Integrade\VC\Tools\MSVC\14.34.31933\include\tuple(879,25): message : 'unknown-type std::invoke(_Callable &&) noexcept()': expects 1 arguments - 3 provided 1>D:\C++\Hyko_Engine\Hyko\src\libSource\entt\entt.hpp(1905,22): error C2440: 'return': cannot convert from 'void' to 'Type ' 1> with 1> [ 1> Type=Hyko::TagComponent 1> ] 1>D:\C++\Hyko_Engine\Hyko\src\libSource\entt\entt.hpp(1905,22): message : Expressions of type void cannot be converted to other types 1>D:\C++\Hyko_Engine\Hyko\src\libSource\entt\entt.hpp(1905,71): error C2661: 'Hyko::TransformComponent::TransformComponent': no overloaded function takes 2 arguments 1>D:\C++\Hyko_Engine\Hyko\src\libSource\entt\entt.hpp(1905,71): message : while trying to match the argument list '(Hyko::Entity, const std::allocator)' 1>D:\VisualStudio_Integrade\VC\Tools\MSVC\14.34.31933\include\type_traits(1470,1): message : see reference to function template instantiation 'auto entt::uninitialized_construct_using_allocator::::operator ()<Hyko::Entity&,const Allocator&>(Hyko::Entity &,const Allocator &) const' being compiled 1> with 1> [ 1> Allocator=std::allocator 1> ] 1>D:\VisualStudio_Integrade\VC\Tools\MSVC\14.34.31933\include\tuple(878,26): message : see reference to function template instantiation 'decltype(auto) std::_Apply_impl<_Ty,std::tuple<Hyko::Entity &,const Allocator &>,0,1>(_Callable &&,_Tuple &&,std::integer_sequence<size_t,0,1>) noexcept()' being compiled 1> with 1> [ 1> _Ty=entt::uninitialized_construct_using_allocator::, 1> Allocator=std::allocator, 1> _Callable=entt::uninitialized_construct_using_allocator::, 1> _Tuple=std::tuple<Hyko::Entity &,const std::allocator &> 1> ] 1>D:\VisualStudio_Integrade\VC\Tools\MSVC\14.34.31933\include\tuple(884,26): message : see reference to function template instantiation 'decltype(auto) std::apply<entt::uninitialized_construct_using_allocator::,std::tuple<Hyko::Entity &,const Allocator &>>(_Callable &&,_Tuple &&) noexcept()' being compiled 1> with 1> [ 1> Allocator=std::allocator, 1> _Callable=entt::uninitialized_construct_using_allocator::, 1> _Tuple=std::tuple<Hyko::Entity &,const std::allocator &> 1> ] 1>D:\C++\Hyko_Engine\Hyko\src\libSource\entt\entt.hpp(1905,22): error C2440: 'return': cannot convert from 'void' to 'Type ' 1> with 1> [ 1> Type=Hyko::TransformComponent 1> ] 1>D:\C++\Hyko_Engine\Hyko\src\libSource\entt\entt.hpp(1905,22): message : Expressions of type void cannot be converted to other types 1>D:\C++\Hyko_Engine\Hyko\src\libSource\entt\entt.hpp(1905,71): error C2661: 'Hyko::SpriteComponent::SpriteComponent': no overloaded function takes 2 arguments 1>D:\C++\Hyko_Engine\Hyko\src\libSource\entt\entt.hpp(1905,71): message : while trying to match the argument list '(Hyko::Entity, const std::allocator)' 1>D:\VisualStudio_Integrade\VC\Tools\MSVC\14.34.31933\include\type_traits(1470,1): message : see reference to function template instantiation 'auto entt::uninitialized_construct_using_allocator::::operator ()<Hyko::Entity&,const Allocator&>(Hyko::Entity &,const Allocator &) const' being compiled 1> with 1> [ 1> Allocator=std::allocator 1> ] 1>D:\VisualStudio_Integrade\VC\Tools\MSVC\14.34.31933\include\tuple(878,26): message : see reference to function template instantiation 'decltype(auto) std::_Apply_impl<_Ty,std::tuple<Hyko::Entity &,const Allocator &>,0,1>(_Callable &&,_Tuple &&,std::integer_sequence<size_t,0,1>) noexcept()' being compiled 1> with 1> [ 1> _Ty=entt::uninitialized_construct_using_allocator::, 1> Allocator=std::allocator, 1> _Callable=entt::uninitialized_construct_using_allocator::, 1> _Tuple=std::tuple<Hyko::Entity &,const std::allocator &> 1> ] 1>D:\VisualStudio_Integrade\VC\Tools\MSVC\14.34.31933\include\tuple(884,26): message : see reference to function template instantiation 'decltype(auto) std::apply<entt::uninitialized_construct_using_allocator::,std::tuple<Hyko::Entity &,const Allocator &>>(_Callable &&,_Tuple &&) noexcept()' being compiled 1> with 1> [ 1> Allocator=std::allocator, 1> _Callable=entt::uninitialized_construct_using_allocator::, 1> _Tuple=std::tuple<Hyko::Entity &,const std::allocator &> 1> ] 1>D:\C++\Hyko_Engine\Hyko\src\libSource\entt\entt.hpp(1905,22): error C2440: 'return': cannot convert from 'void' to 'Type *' 1> with 1> [ 1> Type=Hyko::SpriteComponent 1> ] 1>D:\C++\Hyko_Engine\Hyko\src\libSource\entt\entt.hpp(1905,22): message : Expressions of type void cannot be converted to other types 1>EditorComponentSettings.cpp 1>D:\C++\Hyko_Engine\Hyko\src\Engine\UI\Editor\MainEditorUI\EditorToolbar.h(31,18): warning C4244: 'initializing': conversion from 'float' to 'int', possible loss of data 1>D:\C++\Hyko_Engine\Hyko\src\Engine\UI\Editor\MainEditorUI\EditorComponentSettings.h(27,28): warning C4099: 'Hyko::TagComponent': type name first seen using 'struct' now seen using 'class' 1>D:\C++\Hyko_Engine\Hyko\src\Engine\Scene\Entity\Components.h(100,9): message : see declaration of 'Hyko::TagComponent' 1>main.cpp 1>D:\C++\Hyko_Engine\Hyko\src\GL\Window\window.h(19,2): warning C4091: 'static ': ignored on left of 'WindowData' when no variable is declared 1>D:\C++\Hyko_Engine\Hyko\src\GL\Framebuffer.h(15,12): warning C4244: 'initializing': conversion from 'const float' to 'short', possible loss of data 1>D:\C++\Hyko_Engine\Hyko\src\GL\Framebuffer.h(15,29): warning C4244: 'initializing': conversion from 'const float' to 'short', possible loss of data 1>D:\C++\Hyko_Engine\Hyko\src\Engine\UI\Editor\MainEditorUI\EditorToolbar.h(31,18): warning C4244: 'initializing': conversion from 'float' to 'int', possible loss of data 1>D:\C++\Hyko_Engine\Hyko\src\Engine\UI\Editor\MainEditorUI\EditorComponentSettings.h(27,28): warning C4099: 'Hyko::TagComponent': type name first seen using 'struct' now seen using 'class' 1>D:\C++\Hyko_Engine\Hyko\src\Engine\Scene\Entity\Components.h(100,9): message : see declaration of 'Hyko::TagComponent' 1>D:\C++\Hyko_Engine\Hyko\src\Engine\UI\EngineUILayer.h(56,40): warning C4244: 'return': conversion from 'int' to 'float', possible loss of data 1>C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\shared\minwindef.h(130,1): warning C4005: 'APIENTRY': macro redefinition 1>D:\C++\Hyko_Engine\libs\GLAD\include\glad\glad.h(32,1): message : see previous definition of 'APIENTRY' 1>Generating Code... 1>D:\C++\Hyko_Engine\Hyko\src\Engine\UI\Editor\MainEditorUI\EditorComponentSettings.h(56): warning C4715: 'Hyko::EComponentSettings::componentDeleteMenu': not all control paths return a value 1>D:\C++\Hyko_Engine\Hyko\src\Engine\UI\Editor\MainEditorUI\EditorComponentSettings.h(56): warning C4715: 'Hyko::EComponentSettings::componentDeleteMenu': not all control paths return a value 1>D:\C++\Hyko_Engine\Hyko\src\Engine\UI\Editor\MainEditorUI\EditorComponentSettings.h(56): warning C4715: 'Hyko::EComponentSettings::componentDeleteMenu': not all control paths return a value 1>Done building project "Hyko.vcxproj" -- FAILED. ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========.

And also I use C++ 17

skypjack commented 1 year ago

I'm sorry but I'm not supposed to look into pages of VS errors and fix user code to be honest. If you've a minimal repro to run on godbolt (which also includes EnTT, see the link on the README), I can quickly give it a glance though.

0LGL0 commented 1 year ago

Sorry, but in godbolt there is only entt 3.6.0, and I have version 3.11.0 and, accordingly, some functions that are in entt 3.11.0 are missing. But still, here is the minimum code: https://godbolt.org/z/e819z5br5 . However, I want to say right away that it may not be possible to run this code (at least here). Also, just in case, I will give you a link to the repository of this project on GitHub. https://github.com/0LGL0/Hyko_Engine.git

skypjack commented 1 year ago

You can pick the trunk version on godbolt, it's the most recent one. 👍 See here. The problem is that I can't reproduce your error anyway. The code compiles fine. Although, at first glance, I bet on the fact that your types aren't movable nor fully copyable. For example:

struct TransformComponent {
    // ...

    TransformComponent() = default;

     TransformComponent(glm::mat4 transform)
        : Transform(transform){}

    TransformComponent(const TransformComponent& copy)
        : Transform(copy.Transform), translate(copy.translate), scale(copy.scale), rotAngle(copy.rotAngle) {}

    // ...
};

As you can see, the type has neither the move constructor nor the move operator. Similarly, it has a copy constructor but still no copy operator. Try to fix it and recompile. If the problem persists, please, provide me with a minimal reproducible example that fails to compile.

0LGL0 commented 1 year ago

here: https://godbolt.org/z/7Wrsz9xWj . However, if you still can't figure out what the problem is, I can provide you with a zip archive with the project (this project is fully open on GitHub), but there will be files for Visual Studio (2022). I hope this helps, because the same compilation errors were output to the godbolt console as in Visual Studio. I also created a move constructor and operators. And yes, errors of this type: "error: no matching constructor for initialization of 'Hyko::TransformComponent' " appeared after I added the move constructor and operators

Innokentiy-Alaytsev commented 1 year ago

You have an error at line 317:

copy.addComponent<comp>(copy);

should be:

copy.addComponent<comp>();
0LGL0 commented 1 year ago

@Innokentiy-Alaytsev, Sorry, but I can't check it right now. Although I can see that this is an error, but perhaps this is not the only reason for compilation errors. But thanks for the help. I'll be able to check it out soon

Innokentiy-Alaytsev commented 1 year ago

It compiles with the error fixed. At least Clang 16.0 compiles it.

0LGL0 commented 1 year ago

This is good news. But mobile godbolt didn't work, that's why I can't check it.

Innokentiy-Alaytsev commented 1 year ago

https://godbolt.org/z/s76rzr19M

0LGL0 commented 1 year ago

I'm sorry I accidentally put a dislike :|. I didn't want

Innokentiy-Alaytsev commented 1 year ago

Oh, don't worry, stay where you are, S.W.A.T team is on the way.

skypjack commented 1 year ago

So, here we are with another non-repro?

0LGL0 commented 1 year ago

Yes, everything works, thank you so much for your help. And I'm sorry for my inattention

0LGL0 commented 1 year ago

@skypjack, i'm so sorry

0LGL0 commented 1 year ago

By the way, can I make my visit function better?

skypjack commented 1 year ago

What is it trying to achieve exactly @0LGL0 copying a component?

0LGL0 commented 1 year ago

@skypjack, I'm doing all this for my 2D game engine. I want to copy the entities of the scene using "Ctrl+ C" and "Ctrl + V".

skypjack commented 1 year ago

You can use the value and push from the base class of the storage then (the sparse set). They return and accept a void pointer, that is an opaque pointer to the element assigned to the entity. You can get the value from the source and push it on the destination.

That being said, your implementation is also fine, so 🤷‍♂️ as you prefer.

0LGL0 commented 1 year ago

Well, I wouldn't say that my implementation is good, since it depends on me, that is, if I add a new component, then I will have to add a new check to the "visit" function, and I may forget to do it, and then suffer thinking why my code doesn't work. Also, I don't think that such an abundance of if statements will benefit my engine in terms of performance. But thanks for the help

skypjack commented 1 year ago

It's a well encapsulated function. This kind of things rarely poses a problem to the dev because you can easily rework them later on without affecting the whole codebase. Therefore, if it gets the job done today and it's good enough for your current purposes, why not? 🤷‍♂️ Anyway, you can make it opaque and avoid the type list using value and push functions. 👍

That being said, what about the original issue? I still don't have a way to reproduce it and I'm tempted to close it as invalid.

0LGL0 commented 1 year ago

Here is a link to the problematic code: https://godbolt.org/z/7Wrsz9xWj . However, the problem has already been solved, and I have released a commit with copying scene objects for my engine. The problem was my inattention, namely in line 317 (where it was necessary to write "copy.AddComponent()")