Replies: 12 comments 18 replies
-
        
 From memory, there times where advanced feedbacks are used are: 
 For 1, we can ignore these, they should be migrated to boolean. I don't know if modules do 2&3 in the same feedback, hopefully not. Or if they do, then maybe any feedback should be able to produce these variables (including boolean feedbacks). We would then need somewhere to park feedbacks which are used just for their variables, but that should be solvable.  | 
  
Beta Was this translation helpful? Give feedback.
-
| 
         Some other things will 'break' as part of this The feedback 'use another buttons style' won't work fully, as one of those 'advanced' feedbacks. I expect we will leave this 'broken' when going across types, and add a new one for this new button type. The 'set button text' and similar api endpoints and actions wouldn't nicely translate across to this. We could take the opportunity to remove them, or we could expand them to allow choosing a layer index (which will be brittle) defaulting to the first text layer. I would lean towards removing them, everything they support will be possible with custom variables instead in this. Satellite API can provide text and text colour to clients. We need to define a rule on how those should be determined from a multi-layer button.  | 
  
Beta Was this translation helpful? Give feedback.
-
| 
         I appreciate this summary and it is mostly also what I'd suggest. 
 There's now not an answer for all of the open questions, but I tend to write too much and I think we'll find more solutions along the way if we agree first on the concept.  | 
  
Beta Was this translation helpful? Give feedback.
-
| 
         Something else to do as part of this: Stop using  Doing this is messy for presets, but if we do it at the same time as introducing a new preset type, we can leave the old behaviour for old presets, with new behaviour for new presets  | 
  
Beta Was this translation helpful? Give feedback.
-
        
 So far the topbar is a property of the canvas instead of an element. 
 which I think is a good summary of the options. I have another spanner to add to this; which is the question of how to handle existing configs (assuming we do manage to convert existing buttons across). If this is a property of the canvas, it is not that bad (like today), where the current global config will remain that they must correct manually and everything will be ok. But if this is an element, we would either need to start prompting for this, or we will import with the top bar shown (matching existing behaviour). So this has the potential to upset a bunch of users, and force a load of work on them to tidy up our assumptions. Because of this, and my other uncertainty about changing this to be an element, I am leaning towards keeping it as a property of the canvas/button for now. Changing it to be an element later on will be just as easy as making the change now, going the other way is much harder. Maybe the canvas should also get a property to control the height of the topbar, so that the user can still choose the size of it. Alternatively, having it as an element too I don't expect will be much work, most of the effort there will be making sure it behaves sensibly at different sizes. On a side note, I wonder if making it default hidden would have the side effect of it rarely being enabled. Do people want the statusbar there, or tolerate it because they don't realise they can change it?  | 
  
Beta Was this translation helpful? Give feedback.
-
        Solving 'advanced' feedbacksI don't think we have reached an agreement on how these should be handled in the new drawing. I think we do both agree that they should be replaced with a new feedback type, but haven't agreed on exactly that will be. For this, I think we should 'rush' to drop advanced feedbacks from the proposed 2.0 of the module api. I think it better to do it slightly prematurely (modules dont have to update immediately) than to have to keep support for the old advanced feedbacks for years. But short term, if we want to be able to push user configs across to the new buttons automatically, we will need to support these 'advanced' feedbacks in a reasonable way. My PitchThis feels messy, but not too horrific. So I am very open to other ideas. Somewhere would be a panel which allows for building a stack of these 'legacy' feedbacks. This panel should be clearly labelled as legacy/deprecated, with a warning that it should not be used if possible and will be removed in a future release. With this, I think that will preserve all behaviour in a backwards compatible way, and not be too invasive into the UX of the new system. I don't know where would be best to put this panel; Perhaps it should be an element type (limited to being added once), or this could go on the canvas element, or be its own tab (which could be used to nudge the users looking for feedbacks into the new flows, but could also have the opposite effect due to muscle memory), or something else. When it comes to migrating existing configs, I suspect we will need to handle two cases separately: 
  | 
  
Beta Was this translation helpful? Give feedback.
-
        New feedback typeWe agree that the 'advanced' feedback should be replaced with something new. #3314 introduced internally the concept of 'value' feedbacks. Those were made to be able to populate local-variables with user defined values/expressions or the result of a boolean feedback. So I suppose the question is whether we should simply allow modules to define these too. Modules could populate these values with either a simple primitive, or an object. Essentially, any type that we already allow for custom-varibles. With just this, it should be possible to replace 90% of the values that advanced feedbacks can currently produce, of course it will be up to the user to hook up the values it produces. We should define some rules, but It is up to them to decide how to format the output. We should also give some guidance on where to document the output structure. The one bit which is unhandled by this is feedbacks producing imageBuffers. The values from those would fit into this structure, but they also need to know the dimensions to draw at, so will need some extra thought. (See the next thread for my thoughts on these)  | 
  
Beta Was this translation helpful? Give feedback.
-
        Handling imageBuffersIn the old flow, buttons were drawn at one size. So feedbacks were able to produce an imageBuffer and it would match the button size for drawing. For any 'advanced' feedbacks in the backwards compatibility flow, it would be good enough to simply do a 'fit' draw of the buffer resized to match the space. It won't look the best in all cases, but its good enough. But what should the new approach be? At the beginning of this overhaul, I was thinking that we could figure out what sizes of the buffer we need and tell the module about 'virtual instances' of a feedback to collect renders at all the needed sizes. But that only works if we know that a feedback needs to know about the dimensions and will produce an image buffer. It won't work once we stuff that value into a variable, as by doing that we lose the ability to alias the value to the correct bitmap. The other problem is that the bitmaps may not be drawn at full size, with the positioning available for each element, we don't know what resolution we need until it gets drawn. And it could change for each draw, we can't really preempt what we will need. So I don't have any good ideas right now on how to support these. It feels like part of the solution is to have a dedicated feedback type for this, and a 'connection imagebuffer' element type, which is where these feedbacks will be used. In that way we avoid issues with aliasing of values, and it allows us to do any 'virtual instance' stuff we want to get multiple renders. As long as we preserve aspect ratio, is drawing 1:1 pixel size important? Perhaps we can preempt the resolution by saying that if the size is an expression we always ask for canvas size (possibly with user a aspect ratio override)? I have a bunch of thoughts here, but no clear plan on how to handle these. Input is very much appreciated  | 
  
Beta Was this translation helpful? Give feedback.
-
| 
         While the Layer idea is thought about - any chance we could also have the ability of adding button Boarders - a bit like you can do in Excel with cells. That way, when working with multiple devices on one streamdeck page, you can visibly separate the button areas per device/connection - leaving colours for feedback.  | 
  
Beta Was this translation helpful? Give feedback.
-
| 
         Proposed element types (originally posted #3299 (comment)) Let's collect some ideas for elements to see how tey can build a useful set with distinct functionality. 
 Medium priority 
 Low priority 
 Any more? All elements should have a Name/ID, Show/hide toggle, opacity and draw mode.  | 
  
Beta Was this translation helpful? Give feedback.
-
| 
         I just stumbled upon this, so I thought I would share my complex button example: I have a "hot bar" page where every button can be 1 out of 80-90 different button types. When a button is "not assigned" it shows an "x". When you press it, it takes you to another page with a bunch of different actions (multi-page). When you choose one, it takes you back to the original page and "assigns" that action to that button. When you press it again, it does that operation. Where this gets complex is every button on the "hot bar" page has ~80 feedbacks. Each operation has a unique png icon to represent the operation. So I basically have 80 * 20 conditions and pngs. So the 80 images are repeated on every button as a feedback. That's a lot of duplication. If that sounds complicated, it is. I have a script that generates a companion config file just to import all of this. I say 80-90 because new operations get added over time. When a new operation is added, I have to rebuild my import file and import it. What would have made this far easier is if  What makes my use-case even more complex is for every button I have to create a global variable to store the operation's id, which is fed into a module that does the prescribed operation. Does this new feedback system make this use-case easier? I also think your work with local variables might also be very useful for me because I could store the operation id within the button itself instead of creating a global variable. Which means I could potentially duplicate buttons and move them around. The only thing that I would need is a way to address the button and set its local variable externally because I need to set the value from the "chooser" pages. Which brings up another thing for me, I wish a module could ether have full control over a button (define a new button type) or even have full control over a page and the buttons on it to create some sort of ui. I've clumsily done this with import file generator, but it would be nice if I could build a module to handle all that. You may ask 'why not use the companion ui to configure the buttons?'. The reason is you have to be able to configure button operations on the fly, quickly, without clicking thru a ui on the screen. Being able to tap two buttons to configure is convenient, and you can do it with muscle memory. On the same page, I have buttons that will clear out an entire row (or the page itself) so they can be re-assigned.  | 
  
Beta Was this translation helpful? Give feedback.
-
        
 Have you considered using a single  
 Personally I'm against this, it's beyond the scope of what a module should be doing, and if a module needs to manipulate buttons/pages perhaps it shouldn't be a module but instead integrated into Companion either directly or as an external app.  | 
  
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
For anyone stumbling upon this curious about what this is;
We want your examples for complex buttons or weird scenarios that are hard to do in the current system.
There are a few threads around different aspects of this already, but things have changed in companion since they were opened and there are additional requirements now.
The ones I found: #262, a snippet of #2387, #2237, #3067, #2367
I want to focus on the aspects of:
A lot of this builds heavily on what @dnmeid has already written, primarily around adding layers.
I think that doing anything around this is going to 'break' advanced feedbacks, because they are very tied to the current structure of properties we use for drawing. This structure has become a bit of a mess as new bits have been added over time, but has been unable to be tidied up the layout due to it being used in feedbacks and the module-api.
I would propose that this would probably be best achieved as a new button type. We wouldn't touch existing buttons (for now), once this is done we could look at auto converting some/all existing buttons across, but I expect that not everything will translate perfectly.
This way, we don't break things for existing users, and don't limit ourselves by trying to minimise this breakage.
We can then drop the old rendering in a future major version, or sooner if we can figure out acceptable automatic translation.
I feel like this should be implemented largely in the open in main, rather than hidden on a branch until it is complete. We can label the new type as alpha/beta, and if we want to do a stable release we could leave it in or hide the ui option
Layers
As has already been proposed, I agree that buttons should have layers. I would suggest that each layer should do a single thing, ie, a layer can be a png layer or a text layer. This will allow us to add more options within each layer without making the ui too cluttered. And at the same time, we can add new layer types without cluttering up the ui,
The user should be free to add and remove as many layers as they like into this stack, the one they will not be able to remove is the fixed background layer which will be where the background colour is set.
UI clutter is a big concern I have around improving the drawing, the existing style properties don't feel very organised and any changes to the current system feel like they will make it worse unless we can categorise things better..
Once we have this structure, adding many of the things from https://github.com/thedist/companion-module-utils would be much simpler, as they would be their own layer types.
A thought for myself, perhaps we could utilise the layering for some extra performance enhancements? We could draw each layer as its own bitmap and then flatten afterwards. Doing this is excessive, but we could utilise it for any costly layers, or to avoid repeating ourselves too much when it comes to gifs or frequent redraws. Not in scope of this, but something to think about in the future.
What about feedbacks
Now for one of the more radical ideas I have here; we should move the feedbacks to be defined as part of this layering.
For boolean feedbacks, this would be a pretty trivial way of adding an enable rule on each layer. This will likely need a way of linking layers to accommodate this fully, or a way of defining some 'button local' variables based on feedbacks. I am not sure on the best approach here.
For 'advanced' feedbacks, as written above I dont think these will translate well to this new model. I would be tempted to call these 'legacy feedbacks', and be able to mark layers as 'override for legacy feedbacks'. And at the same time, define a new 'advanced' feedback type which would fit better into this model.
I forgot to consider here that feedbacks override the defaults currently..
Perhaps then each layer type should have its own feedback stack to allow applying overrides to itself? That feels like it will be a bit clunky, but if we encourage doing it via local variables (or only allow via local variables?), to be able to share feedbacks across layers then it wouldnt be terrible? Definitely better than forcing enabling/disabling of layers
I am very open to ideas here
Aspect ratios
Finally, we need to be able to handle different aspect ratios of buttons. The Stream Deck Studio has slightly widescreen buttons that we 'letterbox', the Neo has the lcd strip that we ignore, the Plus has the LCD strip that we leave space around each button, the loupedecks have vertical strips that we ignore, and more quirks will come in the future.
I am not 100% sure how this should work, but I think long term we need to allow the user control over how different aspect ratios render.
The MVP could be to just perform the same operations on the different aspect ratio, and hope it works out. This will likely do for many users, as they will likely only look at buttons on one type of surface. We would need to figure out how to show this to them in the UI, but I dont think that is in scope of this task.
For a proper solution, I feel like we would need to have a separate stack of layers to draw, but that will get tedious if you just need to tweak one thing. Perhaps they share a stack and layers can be marked as 'only for X', and 'except for X'. I'm not sure, and I think it would be best to leave this to a follow up task.
The UI
I am not sold on these ideas, just my immediate thoughts for future me.
For showing this in the UI, I think this would be a case of adding this as a new tab in the action step tab list. Probably as the first and default tab.
The 'progress' and 'rotary actions' toggles should probably be moved to an 'options'/'settings' tab there too.
This tab could be split with the top portion showing a larger preview of the button, with a layer list beside it.
With the editor for the currently selected layer below.
Beta Was this translation helpful? Give feedback.
All reactions