Jump to content

Official documentation


Josh
 Share

Recommended Posts

To conclude this long discussion.

Here is my opinion.

 

1 All members should be either private or protected

2 Retrieving a member should be done using a GetXXXX() const method

3 Setting a member should be done using a SetXXXX( const& value ) method

4 Queering an object state should be done by calling a bool IsXXXX() const method

5 Destructors should ALWAYS be virtual.

6 Public members should NEVER be allowed.

Roland Strålberg
Website: https://rstralberg.com

Link to comment
Share on other sites

More ideas, polymorph methods for identified data types:

Position pos=Vec3(0,0,1);
Rotation rot=Vec3(80,0,0);

cube.Set(pos);
cube.Set(rot);
cube.Add(pos);
cube.Add(rot);
cube.Subtract(pos);
pos=cube.Get();
rot=cube.Get();
rot=cube.Get(POSITION); // forcing to get position data into Rotation object

Ryzen 9 RX 6800M ■ 16GB XF8 Windows 11 ■
Ultra ■ LE 2.53DWS 5.6  Reaper ■ C/C++ C# ■ Fortran 2008 ■ Story ■
■ Homepage: https://canardia.com ■

Link to comment
Share on other sites

You could if it was return a pointer to the object and not a const, but probably wouldn't want to do that.

 

I just hope the whole Create() thing from LEO goes away. I was never a fan of that. In any C++ library I have never seen anything like that. If you want to create something after a certain part of code runs you either place it after that code OR use pointers. There is nothing confusing about:

 

Cube* cube;
...

cube = new Cube(...);

 

That's how it should work. Not this:

 

Cube cube;

cube.Create(...);

 

or any kind of weird CREATENOW thing in the ctor. That's my vote anyway.

Link to comment
Share on other sites

The problem with pointers is that you can't use "." to seperate methods, but you need to use that ugly "->". In addition with references you can't have NULL pointers or pointers which point to a sensitive location which will crash the program and could even destroy your whole computer, so it's also more safe to avoid pointers.

Ryzen 9 RX 6800M ■ 16GB XF8 Windows 11 ■
Ultra ■ LE 2.53DWS 5.6  Reaper ■ C/C++ C# ■ Fortran 2008 ■ Story ■
■ Homepage: https://canardia.com ■

Link to comment
Share on other sites

You could if it was return a pointer to the object and not a const, but probably wouldn't want to do that.

 

I just hope the whole Create() thing from LEO goes away. I was never a fan of that. In any C++ library I have never seen anything like that. If you want to create something after a certain part of code runs you either place it after that code OR use pointers. There is nothing confusing about:

 

Cube* cube;
...

cube = new Cube(...);

 

That's how it should work. Not this:

 

Cube cube;

cube.Create(...);

 

or any kind of weird CREATENOW thing in the ctor. That's my vote anyway.

 

Yes Rick. Absolutely correct. That was how I wanted to design LEO from start,

but I was voted down on that one. Maybe we could get it the proper way in LE3

 

And -> is a beautiful as . :)

Roland Strålberg
Website: https://rstralberg.com

Link to comment
Share on other sites

Queering an object state?

 

I will disagree in that public members are very useful, i.e.:

x = entity.position.x;

 

Some of Mika's suggestions are cool, but it's a lot of work to declare all those overloaded methods, especially since all functions have to be declared three times (the function, the header, and the luabind structure). I think the Get/Set method should be what we do everything in, and if we add other niceties for convenience, we will deal with it then.

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

In addition with references you can't have NULL pointers or pointers which point to a sensitive location which will crash the program and could even destroy your whole computer, so it's also more safe to avoid pointers.

 

Holy cow. I've been using pointers for 10 years now and have never had my computer destroyed :)

 

Smart pointers could be used. The whole Create(CREATENOW) thing is just an ugly design. I'll take an ugly operator over an ugly design :P

Link to comment
Share on other sites

How is Position and Rotation declared above ?

They are own classes:

class Rotation:public Vec3{};

Maybe it would work also as typedef, if C++ can distinguish Rotation from Vec3 in polymorph class methods:

typedef Vec3 Rotation;

Ryzen 9 RX 6800M ■ 16GB XF8 Windows 11 ■
Ultra ■ LE 2.53DWS 5.6  Reaper ■ C/C++ C# ■ Fortran 2008 ■ Story ■
■ Homepage: https://canardia.com ■

Link to comment
Share on other sites

Hmmm.. Wish I could write in Swedish.

 

What I mean is when you checks the state of an object as in

 

entity.IsVisible() ;

 

Here you don't get a value, you get an answer on a question about the object state.

 

I think you mean 'querying' not queering... thats a whole different concept... :)

Win7 64bit / Intel i7-2600 CPU @ 3.9 GHz / 16 GB DDR3 / NVIDIA GeForce GTX 590

LE / 3DWS / BMX / Hexagon

macklebee's channel

Link to comment
Share on other sites

I'm just joshing you, Roland.

 

References seem good for classes like Vec3's, where you have a lot of temporary objects you want collected when they are no longer in use.

 

Pointers seem more suited to objects that get created and deleted infrequently, like entities. Since references can't be NULL, it makes commands like TFormPoint() very awkward, where one of the arguments can be NULL. There is a way around that, by declaring an overloaded version that accepts an integer. However, my experience is memory management is more trouble than it saves when used for objects that have lots of connections that have to be manually removed when they are deleted. Oh yeah, and you can't make a list of references.

 

Math classes like Vec3's, AABB's, Mat4's, etc. will not be exported in the library for use with external languages. The external language will be responsible for creating these, and they can either be a block of memory the appropriate length, or an actual structure. All the library cares about is that you send it a pointer to a memory position with enough space to read or write the number of floats it needs. This is how the DLL works now.

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

Oh yeah, and you can't make a list of references.

Of course you can, and it's much faster than making manually a list with pointers:

vector<Model> models;

Some guy measured that for example the .Sort() method of a vector is about 25 times faster than QuickSort. It uses different sort algorithms and chooses the fastest depending on the data structure.

Ryzen 9 RX 6800M ■ 16GB XF8 Windows 11 ■
Ultra ■ LE 2.53DWS 5.6  Reaper ■ C/C++ C# ■ Fortran 2008 ■ Story ■
■ Homepage: https://canardia.com ■

Link to comment
Share on other sites

Reply #5 explains it very well:

No point in making an array if the things you want to put in there actually dont exist.

Using vector, you only create elements which actually exist. There is no need to have a list of things which don't even exist. You can pass a reference to models (of type vector<Model>) to any function, and it will know it is a list of objects. If it's empty, that's fine, if it has content, that's OK too, but I don't want to get a list with empty elements.

 

Again, it's not needed at all to have a list of references, since it would mean that you have the memory for the references somewhere else (also in a list). But vector IS the actual memory, so you can say:

#include <string>
#include <vector>
using namespace std;

class Model
{
string name;
public:
virtual void SetName(const string& name)
{
	this->name=name;
}
virtual const string& GetName(void) const
{
	return name;
}
};

void populate(vector<Model> &models)
{
Model m;
m.SetName("Ferrari");
models.push_back(m);
m.SetName("Lamborghini");
models.push_back(m);
}

void print(vector<Model> &models)
{
vector<Model>::iterator models_it;
int i=0;
for( models_it=models.begin(); models_it!=models.end(); models_it++ )
{
	printf("Model %d: %s\n", ++i, (*models_it).GetName().c_str() );
}
}

int main(void)
{
vector<Model> models;
populate(models);
print(models);
}

Now your vector contains two models, and you don't have to care what memory they use, the vector has it. The temporary m object is then destroyed after the populate() function ends, so you don't have to care about its memory either.

Ryzen 9 RX 6800M ■ 16GB XF8 Windows 11 ■
Ultra ■ LE 2.53DWS 5.6  Reaper ■ C/C++ C# ■ Fortran 2008 ■ Story ■
■ Homepage: https://canardia.com ■

Link to comment
Share on other sites

@Josh: regarding the class properties in C# it works as Roland said, that is a simple assigning of a value and of course you cannot specify more than one value in an assign statement.

 

For your example of modifying Position and for the "presumed" split of a "command", I can agree with the wrapper way of dividing Position from GlobalPosition because I think they are conceptually separate both as values and as mean. This however involves only class implementation and structure due to different point of view.

 

The Position and GlobalPosition properties are defined in this way:

 

public Vector3 Position
{
get
{
	float[] position = new float[3];
	Core.EntityPosition(this.Pointer, position, 0);
	return new Vector3(position);
}
set
{
	Core.PositionEntity(this.Pointer, value.ToFloatArray(), 0);
}
}
public Vector3 GlobalPosition
{
get
{
	float[] position = new float[3];
	Core.EntityPosition(this.Pointer, position, 1);
	return new Vector3(position);
}
set
{
	Core.PositionEntity(this.Pointer, value.ToFloatArray(), 1);
}
}

 

To modify the position it works as C++ (more/less):

// This way
entity.Position = new Vector3(1,1,1);
// or this way
entity.Position.X = 1;
entity.Position.Y = 1;
entity.Position.Z = 1;

 

As you see they however call the core EntityPosition with different global parameter, because as you have C++ and LEO way of programming also here you can use only the Core (yes we can rename this class as we like [with Refactoring we can do something like this with a single replace on all the project files automatically] but Engine is already a defined class which handles the Process and Terminate commands) methods (as C++) or OOP way (as LEO). I find the OOP way of the current wrapper very convenient and well organized in its structure even if the commands are not equals to LEO implementation (many things are named and organized in a more human readable form so anyone can easily find what he's looking also without any manual).

 

What first I generally see and try to achieve for first in the code is elegance and readability and not only a bunch of functions to do everything. That's why I generally prefer too (as who first wrote the wrapper) to add an easy to remember and understand named property than remember that one function with a different valued parameter change its scope.

?? FRANCESCO CROCETTI ??

http://skaredcreations.com

Link to comment
Share on other sites

This is a little off topic. But after watching Aggror's Lua tutorials, I seems like I can even begin to understand what the C# and C++ code is doing even without taking lessons in it. Weird.

Core I5 2.67 / 16GB RAM / GTX 670

Zbrush/ Blender / Photoshop CS6 / Renoise / Genetica / Leadwerks 3

Link to comment
Share on other sites

This is a little off topic. But after watching Aggror's Lua tutorials, I seems like I can even begin to understand what the C# and C++ code is doing even without taking lessons in it. Weird.

It's not wierd at all. For a non-programmer, the first level of awareness comes from understanding how programming works at all. The second level of awareness comes from understanding how OOP works at all. Once you understand those, you understand all programming languages more or less.

Ryzen 9 RX 6800M ■ 16GB XF8 Windows 11 ■
Ultra ■ LE 2.53DWS 5.6  Reaper ■ C/C++ C# ■ Fortran 2008 ■ Story ■
■ Homepage: https://canardia.com ■

Link to comment
Share on other sites

ZioRed, your design is fine for version 2.x. For version 3.0 I think I want a 1:1 ratio with the commands, but that's not your responsibility. You are of course welcome to help plan the syntax in whatever capacity you feel like.

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

I agree on the concept of Object myObject = new Object1(); instead of object = CreateObject().

 

It is a personal choice though:

New programmers will probably like the CreateObject() command because it is a slightly more obvious command. More experienced programmers will like the resemblance with the C# like structure.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   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.

 Share

×
×
  • Create New...