agraef / pd-lua

Lua bindings for Pd, updated for Lua 5.3+
https://agraef.github.io/pd-lua/
GNU General Public License v2.0
47 stars 10 forks source link

Expose API for setting pd object arguments #38

Closed timothyschoen closed 6 months ago

timothyschoen commented 6 months ago

One thing I was missing when creating my own GUI objects, was the ability to store persistent state. I can attach it to [else/args] and create custom functions to set/get state, but that's kind of a hassle compared to being able to do it directly from pdlua.

This PR adds the pd.Class:set_args(atoms) function, which allows you to set the object's creation arguments. So you can do something like this:

function circle:initialize(sel, atoms)
     if #atoms >= 1 then
         self.slider_position = f
     end
end

function example:in_1_float(f)
    self.slider_position = f
    -- pass argument list, this will be passed in as "atoms" when you next create the object
    self:set_args({self.slider_position})
end

Sorry for all the last minute additions! I've been playing with it a lot for the last few days, so I keep finding stuff that could be improved ;)

Currently you're also allowed to use set_args() with non-gui objects, though I wouldn't recommend it.

(I also put some of my new functions in pd.lua in a more logical order)

agraef commented 6 months ago

I'm not sure I understand how this works. AFAICT, this modifies the binbuf of an object, so if you save the patch, the creation arguments set with set_args will be recorded in the patch file?

Do you have a working example with patch and pd_lua source so that I can test it?

agraef commented 6 months ago

Sorry, I obviously don't understand how this is supposed to work, but I can't make it do anything. I modified your example to this:

local circle = pd.Class:new():register("circle")

function circle:initialize(sel, atoms)
   self.inlets = 1
   self.outlets = 1
   if #atoms >= 1 then
      self.slider_position = atoms[1]
   end
   return true
end

function circle:in_1_float(f)
   self.slider_position = f
   -- pass argument list, this will be passed in as "atoms" when you next create the object
   self:set_args({self.slider_position})
end

function circle:in_1_bang()
   self:outlet(1, "float", {self.slider_position})
end

And here's my test patch, running in vanilla with pd-lua from this branch loaded:

image

I can send float values into the circle objects all day long, but AFAICT it doesn't have any observable effect whatsoever on the creation args.

Are you sure that you're modifying the right binbuf there? Am I missing something?

timothyschoen commented 6 months ago

I'm not sure I understand how this works. AFAICT, this modifies the binbuf of an object, so if you save the patch, the creation arguments set with set_args will be recorded in the patch file?

Yep, that's exactly how it works. The goal is to be able to do argument saving in the same way pure-data does for its own GUI objects. If you look at the saved patch with a [bng], you'll see:

#X obj 28 82 bng 30 250 50 0 empty empty empty 10 7 0 10

This is used (as you probably know) to store object colors/sends/receives/etc. This PR allows you to store stuff in the same way for pdlua objects.

Looks like I actually did disable it for non-GUI objects. If I remove that line, it will work on non-guis too, though the new argument will only show up after reloading the patch:

https://github.com/agraef/pd-lua/assets/44585538/9cffb29c-974e-4481-90fa-d97fc9f3787f

I'm not sure if we want to allow this for non-GUI objects too. It works fine, but it feels more confusing than with GUI objects, where the arguments are not visible anyway.

agraef commented 6 months ago

Yes, please enable it for non-guis. This should be useful for all kinds of Lua objects. You don't need to use it for non-guis if you find it confusing. ;-) That should be up to the user IMHO.

Can you please commit that change and also add a little example patch which demonstrates the feature? Then I'll merge.

timothyschoen commented 6 months ago

Yes, please enable it for non-guis. This should be useful for all kinds of Lua objects. You don't need to use it for non-guis if you find it confusing. ;-) That should be up to the user IMHO.

Can you please commit that change and also add a little example patch which demonstrates the feature? Then I'll merge.

Will do!

timothyschoen commented 6 months ago

I've added an example for setting/loading state, which is a version of my circle slider, simplified so it works better as an example. It will remember the slider position and color when you save/reload or copy/paste the object.

Note that my new example uses "g:" instead of "g.", because my other open PR needs to be merged anyway.

agraef commented 6 months ago

Ok, I'm going to merge this after #42, once you remove the draft status from it.

agraef commented 6 months ago

Looking good. Merged, thanks!