How to make a new class?

About advanced scenes, and the Thyme scripting language used in Algodoo.

How to make a new class?

Postby Fisher » Wed Jul 04, 2018 1:19 am

In my scenes, I am starting to use more and more global variables. I wonder if it is possible to create a new class so they wouldn't clutter up the namespace.
Fisher
 
Posts: 2
Joined: Wed Jul 04, 2018 1:08 am

Re: How to make a new class?

Postby Xray » Wed Aug 01, 2018 2:25 am

scene.my.variableName is the only way I know of to declare and to use global variables. And the odd behavior which is different from C++ and other well known languages is you can store any type of data in any class of variable at any time! So, for example, if an integer is stored in a particular variable, you can write over that integer with a float, a Boolean, or text without complaints from the interpreter! You can also mix data types in arrays.

Hope this helps.
User avatar
Xray
 
Posts: 489
Joined: Sun Jun 17, 2012 6:12 am
Location: USA

Re: How to make a new class?

Postby FRA32 » Tue Aug 21, 2018 9:14 pm

Unfortunally it is impossble to create new classes, HOWEVER you can actually get an existing class, store a copy of it, and then use that copy as your class. The only annoying side effect is that whatever fields were in the class are stuck in there, and I got the feeling that the classes actually collapse if you reload the scene. Try using an object's onDie event and do "scene.my.newclass = e", that will copy the class type object e from the (e)=>{ over to your variable, which can then be used as a kind of namespace. I would recommend also overriding "e.this" with undefined in order to clear the object data, which would just clutter up unneccesary space.
FRA32
 
Posts: 219
Joined: Wed Dec 03, 2014 9:51 pm

Re: How to make a new class?

Postby Xray » Wed Aug 22, 2018 8:07 am

FRA32 -- I understood that "class" was used only in object oriented program languages such as C++. Therefore, it doesn't make sense to try to create classes in Thyme scripting because it is not an object oriented programming language. Am I correct?
User avatar
Xray
 
Posts: 489
Joined: Sun Jun 17, 2012 6:12 am
Location: USA

Re: How to make a new class?

Postby FRA32 » Wed Aug 22, 2018 4:17 pm

That is only partially true. The thing is that there's the variable types that are accessible to us, i.e. int, bool etc., and then there's another variable type only creatable trough intrinsic ways, so in other words from within the source code of algodoo. This variable type is called "class object" according to one of the console errors when trying to create it, and it has the structure you see when you try to store entityByGeomId in a variable. Class object variables contain:

A kind of object description, which is a literal text assigned directly to the variable holding the class.
A key-value kind of data space, containing keys(so other variables) having more values assigned.

The object description can only be seen when converting a class object to a string. When you convert an "e" value to a string, you get the aforementioned description, which is "ClassObject with children:", followed by the contents of e. If you convert e.this/e.geom etc. to a string however, you only get the description, which is "box", "plane" etc., which is the reason why we can use e.geom+"" != "plane" ? {} : {}

I suspect that the toString is defaulted to print only the descriptor(i.e. "Box", "Laser", or "GUI" if you converted app.GUI), and the event variables are additionally configured to print their contents in this case.
ClassObjects are of Intrinsic origin, thus having special properties that are not influenced by thyme, however we get them passed to thyme for us to use in scripting, thus giving us variables with partially perplexing behavior, since the content of these variables is not thyme-defined, but can be interacted with nontheless, including reading/writing to them.
FRA32
 
Posts: 219
Joined: Wed Dec 03, 2014 9:51 pm

Re: How to make a new class?

Postby s_noonan » Tue Apr 07, 2020 2:12 pm

This is my take on Algodoo Thyme OOP:

Setting a "scene.my." variable equal to an object puts the object's properties and methods in root scope, which is bad practice. You can see this by doing this: set scene.my.var = entityByID(entityID) in some Algodoo object and then look at the resulting code in the saved .phz or .phn file.

The way around this is to save entityIDs, not entities, in "scene.my." variables. Class methods and variables can be created in a standard Algodoo objects (a box, for example) by using underscore variables that look like this: _someVariable. When using a box to create a custom class, the box can be invisible, collide with nothing, and be glued to the background. The box will be saved automatically with the scene. Since new entityIDs are generated each time a scene is opened, "onSpawn = (e)=>{scene.my.myClass = entityID}" needs to be added to the myClass box object before saving the scene. The class can then be referenced by setting a (non-root) variable equal to the variable like this: myClass := entityByID(scene.my.myClass). I usually set myClass = "" when I'm done using it, just to make sure that I don't create (unproven) memory leaks.

You can try out classes in a scene by creating (2) boxes; a class box and a test box. Glue each box to the background.

In the class box add the following code:
Code: Select all
_init := (instName)=>{
   onSpawn = (e)=>{};
   g := Scene.cloneEntityTo(entity, pos);
   eID := g.entityID;
   s = "scene.my." + instName + " := " + eID;
   eval(s);
   s := "g.onSpawn = (e)=>{scene.my." + instName + " = entityID}";
   eval(s);
   g._init = "NA";
   g.text = instName;
   g.pos = pos + [0.25000000, -0.25000000];
   g = "";
   onSpawn = (e)=>{
      scene.my.myClass = entityID
   };
   eID
};
_ra_len := (ra)=>{
   r := string.length(ra);
   r
};
_zyxw := 123;
onSpawn = (e)=>{
   scene.my.myClass = entityID
};
collideSet = 0;   
text = "myClass";


In the test box add the following code:
Code: Select all
onClick := (e)=>{
   myClass := scene.entityByID(scene.my.myClass);
   myClass._init("myInstance");
   myInstance := scene.entityByID(scene.my.myInstance);
   myInstance._zyxw = "Hello";
   myInstance.color = [1, 0.50000000, 0, 1];
   text = "" + myInstance._ra_len([1, 2, 3, 4, 5]);
   text = text + "\n" + myInstance._zyxw;
   myClass = "";
   myInstance = ""
};
text = "Tester Box:\nClick me to create an instance of he class that is on the right. Code is in the onClick event.";
collideSet = 0;


Save the scene and then open it. Click on the test box with the simulation running.
s_noonan
 
Posts: 60
Joined: Tue Mar 30, 2010 2:25 am

Re: How to make a new class?

Postby Kutis 96 » Tue Apr 07, 2020 9:56 pm

I've poked at this Algodoo class stuff a little today and earlier this week; as I came back to Algodoo again for some reason.

Here's a quick demo of what I've got:
Code: Select all
makething = {
    _ = alloc;
    _.thing = 3;
    _.getthing = null;
    _.setthing = null;
    _ -> {
      getthing = {thing};
      setthing = (n)=>{thing = n};
    };
    _
}


Now try this:
Code: Select all
a = makething; //constructor
b = makething; //again a constructor call
a.setthing(5);
b.getthing; //should still return the default 3
a.getthing; //should return the 5


This seems to work pretty well!


I've also made a simple and ugly map class, see the spoiler:
Spoiler: show
Code: Select all
makemap = ()=>{
    map = alloc;
    map._storage := [];
    map.get = null;
    map.add = null;
    map.remove = null;
   
    map -> {
        get = (id)=>{
            __found := undefined;
            for(string.length(_storage),
                (n)=>{_storage(n)(0) == id ? {__found = _storage(n)(1)} : {}});
            __found;
        };
        add = (id, value)=>{
            __newstorage := _storage;
            __storlen = string.length(_storage);
            __found = false;
            for(__storlen,
                (n)=>{_storage(n)(0) == id ? {
                    __newstorage = __newstorage(0..n-1) ++ [[id, value]] ++ __newstorage(n+1..__storlen-1);
                    __found = true;
                } : {}});
            !__found ? {
                __newstorage = __newstorage ++ [[id, value]];
            } : {};
            _storage = __newstorage;
            [id,value];
        };
        remove = (id)=>{
            __newstorage := _storage;
                    __storlen = string.length(_storage);
            __found = false;
            for(__storlen,
                (n)=>{_storage(n)(0) == id ? {
                    __newstorage = __newstorage(0..n-1) ++ __newstorage(n+1..__storlen-1);
                    __found = true;
                } : {}});
            _storage = __newstorage;
            __found;
        };
    };
    map;
};


And a demo:
Code: Select all
> m = makemap
unnamed
> m.add(2, "thing")
[2, thing]
> m.get(2)
thing
> m.add(3, "thing2")
[3, thing2]
> m.get(2)
thing
> m.get(3)
thing2
> m.remove(2)
true
> m.remove(2)
false
> m.get(2)
undefined
I'm back! (not really!)

I'm also making real hardware, sometimes.
User avatar
Kutis 96
 
Posts: 107
Joined: Mon Jun 28, 2010 7:49 pm
Location: Chasing red dots.


Return to Thyme scripting

Who is online

Users browsing this forum: No registered users and 1 guest

cron