Jump to content
Search In
  • More options...
Find results that contain...
Find results in...

Better Intellisense in Ultra Engine


Josh

645 views

Ultra Engine makes much better use of class encapsulation with strict public / private / protected members. This makes it so you can only access parts of the API you are meant to use, and prevents confusion about what is and isn't supported. I've also moved all internal engine commands into separate namespaces so you don't have to worry about what a RenderMesh or PhysicsNode does. These classes won't appear in the intellisense suggestions unless you were to add "using namespace UltraRender" to your code, which you should never do.

There's still a lot of extra stuff intellisense shows you from Windows headers and other things:

notsimple.thumb.png.0beb414acdeb9f29b063e823707ab6fe.png

Using the __INTELLISENSE__ macro in Visual Studio, I was able to trick the intellisense compiler into skipping include files that link to third party libraries and system headers the user doesn't need to worry about. This strips all the unnecessary stuff out of the API, leaving just basic C++ commands, some STL classes, and the Ultra Engine API. With all the garbage removed, the API seems much friendlier:

simple.thumb.png.ca3fa73542d45ab3d332009856bb5db6.png

This is one more detail that I feel helps make C++ with Ultra Engine about as easy as C# programming. You can disable this feature by adding _ULTRA_SIMPLE_API=0 in your project macros.

  • Like 4
  • Thanks 1

13 Comments


Recommended Comments

Keeping everything structured and separate with a public only api is a real good step forward. This will make access to other languages much easier as you just need toward the public interface. But you need to keep in mind that the integration of some third party code especially in Vulkan may need some access to some lowlevel details, eg.: the Vulkan context these pointers should be made public in some way as well. Otherwise I really like the way ultraengine is structured..

  • Upvote 1
Link to comment
12 hours ago, reepblue said:

Will this update trickle down to the app kit? Interested giving this a peak.

The full engine will be out soon enough, with all the functionality of UAK included.

12 hours ago, klepto2 said:

Keeping everything structured and separate with a public only api is a real good step forward. This will make access to other languages much easier as you just need toward the public interface. But you need to keep in mind that the integration of some third party code especially in Vulkan may need some access to some lowlevel details, eg.: the Vulkan context these pointers should be made public in some way as well. Otherwise I really like the way ultraengine is structured..

Each threaded system has its own API, and these are usually not so friendly to use. The commands are like RenderNode::SetOrientation(matrix, position, quaternion, scale, color) and have strict rules on how they should be used. And they are also in a bit of flux.

Any custom Vulkan code would need to be run in a callback, since all rendering is taking place asynchronously. It will be interesting to see what kinds of things advanced devs would like to do with it once they start using it.

Link to comment

I came across a lot 3rd party libs (eg: nvidias waveworks or shader libs, eg: vkFFt) need at least access to the vkInstance.  If the vkInstance is known everything else can created in the app context. 

Link to comment

@klepto2 Communication between threads is very interesting. Each system has a command buffer you add instructions to like this:

commandbuffer->AddCommand(std::bind(&RenderMaterial::SetColor, rendermaterial, color));

It can also use lambda functions, but I try to avoid them because they are difficult to debug.

The World::Render method signals a semaphore that tells the rendering thread "another batch of command is ready, whenever you are". Then the rendering thread executes them all like this:

for (const auto& func : commands)
{
    func();
}

That's how every system works, rendering, physics, animation, navigation, etc.

It would be entirely possible to do something like this:

commandbuffer->AddCommand(std::bind(&WaveWorks::Initialize, vkinstance));
commandbuffer->AddCommand(std::bind(&WaveWorks::Update, waveworksinstance));

And that code would get executed in the rendering thread, along with whatever else was going on.

  • Like 1
  • Thanks 1
Link to comment

That is all I needed to know :) 

It looks very promising, and I am curious to see how it all works together.

Link to comment

I think I messed up a bit. C++ modules are probably a better way to control what gets exposed. Instead of this:

#include "UltraEngine.h"

using namespace UltraEngine;

int main(int argc, const char* argv[])
{
...

Your code will look like this:

import UltraEngine;

using namespace UltraEngine;

int main(int argc, const char* argv[])
{
...

And there is no need for any header files for the engine library at all. Hopefully. These are quite new and I'm not completely sure how they work.

Link to comment

To build C++ modules, all exported classes and functions go in a single .ixx file like this:

#include "UltraEngine.h"

export module UltraEngine;

namespace UltraEngine
{
	//Export classes
	export Entity;
	export World;
	export Display;
	export Window;

	//Export enums
	export WindowStyles;

	//Export functions
	export std::shared_ptr<World> CreateWorld();
	export std::vector<std::shared_ptr<Display> > GetDisplays();
	export shared_ptr<Window> CreateWindow(const WString&, const int, const int, const int, const int, shared_ptr<Display>, const WindowStyles);

	//Export overloaded function
	extern shared_ptr<Window> CreateWindow(const WString&, const int, const int, const int, const int, shared_ptr<Window>, const WindowStyles);
}

It looks like default arguments are supported, so everything looks good:

https://developercommunity.visualstudio.com/t/default-arguments-in-member-functions-do-not-work/77201

Link to comment

I've investigated these completely, and my conclusion right now is that C++20 modules are completely broken in Visual Studio. If you put a module in a static library and then import that lib into another project, you will get an undefined reference linking error for the simplest function, if it isn't written in the .ixx file. If you just declare the function (like a header) then it links and runs fine. I even downloaded the 2022 preview version, and the behavior is exactly the same.

It does look like modules do exactly what I want, Microsoft just doesn't have them working right yet.

Link to comment

I see the examples are updated to use the module approach, so I assume you got it working. Did you try this on macOS and Linux yet? 

Link to comment

The documentation display just does a search and replace when the file is loaded, so I can switch it back and forth very easily. These don't appear to be working in Visual Studio yet.

Link to comment
Guest
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...