YetAnotherForum
Welcome Guest Search | Active Topics | Log In | Register

[Sqrat] Setting instance of class member from C++ after instantiation
devlin
#1 Posted : Sunday, June 21, 2015 6:32:39 AM(UTC)
Rank: Member

Groups: Registered
Joined: 6/21/2015(UTC)
Posts: 10
Location: Sweden

Thanks: 0 times
Was thanked: 1 time(s) in 1 post(s)
Greetings!

I've been implementing Squirrel as the scripting system for my game - and so far so good. (wrote my own bindings at first, which worked - but swapped for Sqrat recently due to it being better in the long run for the project).

My problem:

I have a Player class, written in Squirrel.
Within each instance of this class, I would like to have a named variable of a class instance of a type created in C++ code.
I would like to update this variable with a reference to a c++ object.

Pseudo-code:
Code:


RootTable().Bind("Controller", Class<input::Controller>()
    .GlobalFunc("GetAxis", &input::getAxis)                // I use C-style functions on structs rather than C++-classes mostly
);


class Player
{
    Input = null;
    constructor() { Input = Controller(); }                 // passing the controller in via constructor works, this does not, nor setting is via c++ code later
}


void registerInput(Sqrat::Object &instance, input::Controller &c)
{
    Table(instance).SetInstance("Input", &c);              // also tried SetValue to no avail
}



The above doesn't work. I get the feeling that going the off-route via Table is the wrong approach (I use it to extend squirrel-classes from C++ before instantiating them though and that works).

Passing the controller in via the constructor works just fine - but surely there has to be a way to change such binding after instantiation and I'm just not finding it?
Like a Sqrat::Object.SetInstance function or similar.

Thanks in advance,
Johan
Zylann
#2 Posted : Sunday, June 21, 2015 1:23:48 PM(UTC)
Rank: Advanced Member

Groups: Registered
Joined: 6/25/2014(UTC)
Posts: 61
Location: France

Thanks: 1 times
Was thanked: 2 time(s) in 2 post(s)
It looks like you are mixing userdata and instance here...
A userdata just stores raw C++ data, instance has an associated userpointer and class letting method calls possible.

Do you mean the Input member is a userdata containing a pointer, rather than a class instance?
Then, when you call Controller() in Squirrel, you end up with an instance, which is not really the same thing.
SetInstance also expects an instance, not a userdata, so maybe you have to make it explicit by calling another method.
devlin
#3 Posted : Monday, June 22, 2015 1:34:16 PM(UTC)
Rank: Member

Groups: Registered
Joined: 6/21/2015(UTC)
Posts: 10
Location: Sweden

Thanks: 0 times
Was thanked: 1 time(s) in 1 post(s)
I'm sorry, but I don't really understand your reply.

If what you say is true - then what I would need is a Sqrat::Object::SetUserData function. (i.e: Set the userdata on slot "name" within the object (Table/Class)-instance I'm passing as my object)

Is that what you were referring to?
devlin
#4 Posted : Monday, June 22, 2015 4:20:05 PM(UTC)
Rank: Member

Groups: Registered
Joined: 6/21/2015(UTC)
Posts: 10
Location: Sweden

Thanks: 0 times
Was thanked: 1 time(s) in 1 post(s)
Basically, even if I do it this way:

Code:

// Squirrel

class Player
{
  Input = null;
  constructor(i) { Input = i; }

  ...
}



// C++
Sqrat::Object CreateInstance(const char* className)
{
    HSQUIRRELVM vm = Sqrat::DefaultVM::Get();
    Sqrat::PushVar(vm, Sqrat::RootTable(vm).GetSlot(className));
    sq_createinstance(vm, -1);
    Sqrat::Object instance = Sqrat::Var<Sqrat::Object>(vm, -1).value;
    sq_pop(vm, 2);
    return instance;
}

input::Controller player_controller;

RootTable().Bind("Controller", Class<input::Controller>()
...
);

Sqrat::Object i = script::CreateInstance("Player");
Sqrat::Function(i, "constructor").Execute(&player_controller);


I would love a way to set "Input" inside my Player instance directly to another input::Controller-pointer without having to write a Squirrel function for every thing I would like to change.

Something like a Sqrat::Object(i).SetUserPointer("name", &object); would be perfect.

Any hints on how to do this with sqrat? Or squirrel so I can write my own helper for it.

Thanks,
Johan
Zylann
#5 Posted : Tuesday, June 23, 2015 9:22:16 PM(UTC)
Rank: Advanced Member

Groups: Registered
Joined: 6/25/2014(UTC)
Posts: 61
Location: France

Thanks: 1 times
Was thanked: 2 time(s) in 2 post(s)
You mean that for a given Squirrel class instance, you want to set the user pointer so it will refer to a different C++ instance?
you could do that with sq_setinstanceup, but you'd have to be careful to not set a different C++ type, otherwise Squirrel will call wrong methods, depending on how you bound the class.
Just setting another Input instance seems more common.
I'm not sure to understand your use case actually :')
devlin
#6 Posted : Saturday, June 27, 2015 6:08:37 PM(UTC)
Rank: Member

Groups: Registered
Joined: 6/21/2015(UTC)
Posts: 10
Location: Sweden

Thanks: 0 times
Was thanked: 1 time(s) in 1 post(s)
Trying to summarize:

Instead of doing this (in every script):

Code:

// squirrel
class Smurf extends Behaviour
{
   transform = null;
   constructor(t) { transform = t; }

   function Update() { print(transform.x + ", " + transform.y); }
}

// c++ (instance of class created before-hand)
Sqrat::Function(instance, "constructor").Execute(&position);


It would be nice to be able to do this:
Code:

class Smurf extends Behaviour
{
   function Update() { print(transform.x + ", " + transform.y); }
}

// c++ (instance of class created before-hand)
instance.AddSlot("transform", &position);
instance.UpdateSlot("transform", &new_position);


etc.

Does that make it any clearer?
At least AddSlot to get away from all the boilerplate code in the first example, if UpdateSlot isn't possible to implement.
Zylann
#7 Posted : Saturday, June 27, 2015 11:55:36 PM(UTC)
Rank: Advanced Member

Groups: Registered
Joined: 6/25/2014(UTC)
Posts: 61
Location: France

Thanks: 1 times
Was thanked: 2 time(s) in 2 post(s)
Why not adding transform and constructor(t) into Behaviour?
Or do you actually want to modify the class dynamically?
Users browsing this topic
Guest
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.

Clean Slate theme by Jaben Cargman (Tiny Gecko)
Powered by YAF 1.9.4 | YAF © 2003-2010, Yet Another Forum.NET
This page was generated in 0.143 seconds.