#How to copy arrays without referencing them

68 messages · Page 1 of 1 (latest)

fiery tundra
#

Hi folks!

Im going a bit crazy with this, maybe you can help.
Im doing some custom functions to help myself work with Animation curves. Thye have a quite annoying formatting so I want to streamline it.

{
    var _source,_index,_name

    _source            = animcurve_get_channel(curve, channel)
    _index            = animcurve_get_channel_index(curve, _source.name)

    curve.channels[_index].points = new_points
    
    return
}

The problem is that if new_points is a local variable, it will break the reference inside the curve once the event or the function is finished.

How can I get around this? array_copy doesn't seem to work directly on the channels[i].points

thanks!

restive bough
brittle tulipBOT
#

This function clones the value you pass it and returns the new clone.

Arguments
value: The value to clone
depth: OPTIONAL The maximum depth level to clone the variable, in case this is e.g. a nested struct. The default is 128, the maximum possible value.

fiery tundra
#

yeah all of the array entries have a struct which is the animation curve point struct

restive bough
#

then variable clone may work

fiery tundra
#

thanks! will try

#

I guess I need to run it for each array index?

restive bough
#

no, it will copy the whole enchilada at once

fiery tundra
#

then its not working

restive bough
#

can you show how you were using array copy in code as well as this new one?

fiery tundra
#
{
    var _source,_index,_name

    _source            = animcurve_get_channel(curve, channel)
    _index            = animcurve_get_channel_index(curve, _source.name)

    curve.channels[_index].points = variable_clone(new_points)
    
    return
}```

``` Entry 0 in array passed to points property is not a point
 at gml_Script_animcurve_points_set (line 190) -     curve.channels[_index].points = variable_clone(new_points)
############################################################################################
gml_Script_animcurve_points_set (line 190)
gml_Object_Test_Me_KeyPress_65 (line 7) - animcurve_points_set(sys.stencil_profile,"a",point_c)
restive bough
#

hmm, if each index is layers deep and you need a per point, then you probably would need to clone each point in new point

#

so I guess you were right originally, I just didn't know how you were doing this

fiery tundra
#

I've deleted the array copy but it was somehing like

array_copy(curve.channels[_index].points,0,new_points,0,array_length(new_points))

restive bough
#

is each new point index a struct or what is it?

restive bough
#

each entry rather

fiery tundra
#

yeah, they have a posx and value keys, maybe something else internally that is not open as they need to be created specially with animcurve_point_new()

restive bough
#

then yea you'd have to copy each entry at the specific index as well

fiery tundra
#

cursed

restive bough
#

oh actually no

#

hmm

fiery tundra
#

getting inside the curves assets is a whole another level of pain

restive bough
#

channels is the array right?

#

so it would've been...

#
array_copy(curve.channels,0,new_points,0,array_length(new_points))
#

not the specific index, you do it all at once

fiery tundra
#

so channels contains an array with channel structs, and with a points array, which contains individula point structs

restive bough
#

and new points has the same no?

#

oh so points is the array?

fiery tundra
#

curve
---> channels [
channel {
some trash, points[{posx,value} ,{posx,value} ,{posx,value}]
}
]

restive bough
#

so points is an array with arrays

fiery tundra
#

array with structs, sorry

restive bough
#

oh with structs

#

and new points has structs only?

fiery tundra
#

yeah, might have some hidden variables ( Im assuming it has bezier points that are not exposed )

restive bough
#

you may have to manually do it for each index

fiery tundra
#

If you ever opened a mechanical clock and springs and parts went flying and you couldnt put it back together, thats the experience of messing with animation curves

restive bough
#

yea I've dealt with them a bit, just not extensively

fiery tundra
#

but I would like for it to be more standalone than that if possible. Im guessing it should be possible

restive bough
#

is there a reason you can't just clone new_points in a var at the top?

fiery tundra
#

maybe I will try an array for each and do variable clone on them

fiery tundra
restive bough
#

how about a static then?

#

and just replace the statics contents as needed

fiery tundra
#

wouldnt that work just for a single curve project wide?

#

I think the problem is that the channels[_i].points is somewhat protected

restive bough
#

statics can be changed, they're not exactly constants in GM

brittle tulipBOT
#

This function returns the struct containing the channel data for the channel specified in an animation curve asset or struct (as returned by animcurve_get).

Arguments
curve_struct_or_id: The ID or struct pointer of the animation curve to target
channel_name_or_index: The channel name (a string) or the channel index (an integer).

fiery tundra
#

The points member only allows you to get and set the array variable. You cannot run on the points array to modify it.

To modify the points array, store it in a variable, which will create a copy. Then modify that copy with the array functions, and apply that copy back to the points member in the struct.

var _points_copy = channel_struct.points;

array_delete(_points_copy, 0, 1);

channel_struct.points = _points_copy;

restive bough
#

thats a real pain

fiery tundra
#

it is so complicated. Im glad to hear someone else saying this though, I was starting to feel dumb as hell lol

restive bough
#

yea so you have to copy the points array to be able to modify it at all

#

so you need to clone this first:

var temp = variable_clone(curve.channels[_index].points);

modify temp, and then set temp back to points

fiery tundra
#

but what if I want to replace the contents completely

#

do I array_resize to 0, then to length , then fill index by index?

restive bough
#

I think just doing:

curve.channels[_index].points = temp;

should be enough

#

even though it seems like it would be a shallow copy, I don't think GM considers it as one since its a var; at least I never had issues with it, so take it with a grain of salt

fiery tundra
#

mh, I'll try tomorrow. Thanks!

fiery tundra
#

It doesnt seem to work, I get an error message saying that the first element of the array is not a point. Perhaps the variable_clone function doesnt copy all the elements that should be present in a point

#

passing it straight as a local var works until the var is garbage collected (maybe a couple frames) and then there is a silent crash

fiery tundra
#

assigning from a local var outside of a function works perfectly fine too

var point_a = animcurve_get_channel(ac_Shape,"Circle")
var point_b = animcurve_get_channel(ac_Shape,"Letter_P")

var point_c = animcurve_points_additive(point_a,point_b)
point_c = animcurve_points_normalize(point_c)

var _channel = animcurve_get_channel(sys.stencil_profile,"a")

_channel.points = point_c
#

actually doing this instead

function animcurve_points_set(curve, channel, new_points) 
{
    var _source,_index,_name, array_clone

    _source            = animcurve_get_channel(curve, channel)

    _source    .points = new_points
    
    return
}

works perfectly fine

#

actually it seems to crap out too