User defined structs


#21

I have this as my String function:
() String [@cost.String + " " + @actor.String]

If I do:
println(mySortData) // prints correctly

but if I do:
println(mySortData.String) // prints “null” (null)

I want that latter case to work for doing things like:
println("Adding: " idx.String + " " + mySortData.String)

Is there a way to make this work?


#22

I was just pointing out those other classes for the names of operator methods. Yes there are few if any pure SkookumScript classes. Most classes are wrapped around existing C++ structures and some have a mix of script and C++.

As @GreatGuru was mentioning you need to create objects and bind the data members before you can assign something to them.

(SortData other) SortData
  [
  // bind to copy (could refer to same object instead)
  @cost : other.@cost!
  // bind to same actor (probably don't want to copy an actor)
  @actor : other.@actor

  this
  ]

EDIT: I meant to do a bind and not an assignment for the actor!


#23

The print() and println() methods actually take any number of objects of any type and it internally calls their String conversion methods to concatenate up a string.

So instead of

println("Adding: " idx.String + " " + mySortData.String)

You can just use:

println("Adding: " idx " " mySortData)

Easy-peasy.

I’m not sure why - println(mySortData.String) // prints "null" (null)
I’ll see if I can get the same result and look into it…


#24

I still can’t get this to work. I’m still getting null, null:

!myItem : SortData!
!itemList : SortData{}  
myltem.@cost := 5.0
myItem.@actor := @actor_list{0}
itemList.append(myItem!)
println(itemList)

my copy!

(SortData other) SortData [@cost : other.@cost! @actor := other.@actor this]

EDIT: also tried this copy:

(SortData other) SortData [ SortData@!() @cost := other.@cost @actor : other.@actor this]

my !()

() [@cost : 0.0 @actor : Actor!null]

my assign

(SortData other) SortData [@cost := other.@cost @actor := other.@actor this]

my @actor and @cost:

Real !@cost
Actor !@actor

SortData is parented to Object

Any ideas?

EDIT: I think my assignment operator is also broken:

!myItem : SortData!
myItem.@cost := 5.0
myItem.@actor := @actor_list{0}
!myVar : SortData!
myVar := myItem
println(myVar) // prints nil nil

Note, I understand this example is not the way I would do this sort of thing, it’s a use case for this issue.


#25

We just tried to reproduce both of your examples but both work fine for us. We have to dig deeper what might be the reason and get back to you tomorrow. Thanks for hanging in there!


#26

The only other factor is the function I’m running is a &blueprint function I’m triggering from a running game in Unreal. I have the function bound to a key.
When I put the same code in the Workbench, it works as expected.

Here’s the whole function (called testFunc and bound to the level blueprint of a vanilla third person project):

&blueprint
() 
  [
  !myItem : SortData!
  
  myItem.@cost := 5.0
  myItem.@actor := @actor_list{0}
  !myVar : SortData!
  myVar := myItem
  println(myVar)
  ]

note that replacing the assignment with this also makes it work as expected:

myVar.@cost := myItem.@cost
myVar.@actor : myItem.@actor

so for some reason := is not working correctly in this function, but works correctly in the Workbench

On the assign member function I added: println(“Here”)
Prints on workbench, doesn’t print when running from unreal


#27

Odd. Again, we did the same thing over here (created the &blueprint function and bound to a key) but it works fine.

Assigning the actor by value is probably the issue here, because of how Entity (UObject) references are internally represented. Some actors are assigned a unique instance object which cannot be copied or assigned. Using a bind (:) is the proper solution. If you bind (:) the actor variable instead of assigning (:=) it whenever you transfer it, does the problem go away?


#28

Actually, I just shut-off Unreal and Sk, re-launched them, then it worked as expected
¯\_(ツ)__/¯


#29

If I use bind for assignment, I’ll be keeping references, so when I move elements in a list, I get the wrong behavior:

&blueprint
() 
  [
  	!myItem : SortData!
   !itemList : SortData{}
  
   myItem.@cost := 5.0
   myItem.@actor : @actor_list{0}
   itemList.append(myItem!)
   myItem.@cost := 2.0
   myItem.@actor : @actor_list{1}
   itemList.append(myItem!)
   println(itemList) // prints @actor_list{1} for both list items
  ]

Copy:

(SortData other) SortData [ 
  SortData@!()
  @cost := other.@cost
  @actor : other.@actor
  this]

Assign:

(ThisClass_ entity) ThisClass_
  [
    @cost := entity.@cost
    @actor : entity.@actor
    this
  ]

EDIT: I guess I could fix the error by doing this:

myItem.@cost := 5.0
myItem.@actor : @actor_list{0}
itemList.append(myItem!)
myItem : SortData!
myItem.@cost := 2.0
myItem.@actor : @actor_list{1}
itemList.append(myItem!)
println(itemList) // prints correctly

Is that how I should work with actors and other big data structures?


#30

Well the most elegant would be actually to define the constructor of SortData like this:

(Real  cost  : 0.0
 Actor actor : Actor!null) 
  [
  @cost:  cost
  @actor: actor
  ]

and then define itemList like this:

!itemList: {SortData!(5.0 @actor_list{0}) SortData!(2.0 @actor_list{1})}

With the constructor having default arguments like that, you could still say just SortData! as well.


#31

Sure, that fixes that exact case, which is only meant to illustrate an issue. If those values came from a variable, rather than literals, then we could be back at having the same problem, depending on how it was used.

In general, the concern is that the time cost in ensuring every reference is handled properly, and finding ways around issues that arise from having everything be a reference will be high. Also the time spent tracking bugs down because someone missed something dealing with references could be high.

You guys were talking about an option to build constructor, copy and assign methods automatically. That might help with lowering mistakes made by the users.


#32

This is on our to do list and we aim to get it implemented sooner rather than later.

There have been several shipped AAA games built using SkookumScript without this functionality and their fairly large scripting teams didn’t have a bad experience in this area.

Regardless - we agree that a smart implementation of this will make things even better.