How do fellow developers position widgets?

This forum is for developers of Rack Extensions to discuss the RE SDK, share code, and offer tips to other developers.
Post Reply
ForgottenClank
RE Developer
Posts: 128
Joined: 14 Nov 2018

19 Feb 2021

I am beginning to find it frustrating positioning the graphics in GIMP and then manually copying the coordinates into the device_2D.lua file. How do you handle this process? Are there any faster alternatives?

User avatar
Enlightenspeed
RE Developer
Posts: 1103
Joined: 03 Jan 2019

19 Feb 2021

ForgottenClank wrote:
19 Feb 2021
I am beginning to find it frustrating positioning the graphics in GIMP and then manually copying the coordinates into the device_2D.lua file. How do you handle this process? Are there any faster alternatives?
There's no particualarly quick way to do it that I'm aware of, so I just use the RE2DPreview image to get a rough idea of where it should be in device_2D.lua.

From there, if I want to tweak stuff I use the "live" GUI.lua file, so I can move things without having to constantly close/reopen Recon. This is located here:

C:\Users\<YourNameInBrightLightsHere>\AppData\Roaming\Propellerhead Software\RackExtensions_Dev

Remember that any changes you make here are not committed, so you should have both the live version and the real one open at the same time, remembering of course that the live file uses values that are 20% the size of the ones in device_2D; Since day one, near enough, I've been in the habit of formatting the device_2D values to suit this way of working.

So what you input in device_2D as:

local left_column_left = 27*5
local left_column_top = 7*5
OnOffSwitch = {offset = { left_column_left,left_column_top }, { path = "On_Off", frames = 4 }},


will show up in GUI.lua (after all parsing and merging with the hdgui_2D.lua file) as:

jbox.toggle_button{
transform = {27,7},
background = jbox.image_sequence{path = "Reason_GUI_On_Off", frames = 4},
value = "/custom_properties/OnOff",
tooltip_template = jbox.ui_text( "OnOff" ),
show_remote_box = true,
show_automation_rect = true,
},

You do your tweaking on the transform values and then just paste it back in, when ready. If you're using Notepad++ then you should get warnings on the live file if you overwrite it, so if you forget to copy something over you should still be able to edit it before it is lost.

Hope this helps,
Brian

ForgottenClank
RE Developer
Posts: 128
Joined: 14 Nov 2018

19 Feb 2021

Thanks for your input, Brian!
I actually think that my current approach might be faster for me because I can re-position the widgets and get instant feedback in GIMP without having to rebuild anything or having to re-open Recon. But I'll have to try your method!

User avatar
rcbuse
RE Developer
Posts: 1175
Joined: 16 Jan 2015
Location: SR388
Contact:

19 Feb 2021

Here is a little python script I wrote that helps me out. It evaluates and collapses down any calculations inside device_2d.lua

I run it as follows:

Code: Select all

python collapseCalcs.py GUI2D/device_2D.lua
Which allows me to write things like:

Code: Select all

ButtonTool0 =  { offset = {575+5*30, 200-10*5}, { path="SeedSwitch", frames = 2 }},
And then I run it every build and the file comes out:

Code: Select all

  ButtonTool0 =  { offset = {725, 150}, { path="SeedSwitch", frames = 2 }},
My device_2d.lua files used to get terrible.. like 200+100-30+5+20+50+10 with all the little tweaks.

The other thing I do is overlay a grid on my device background so I know how far I need to move something, like 10-20 pixels.
Attachments
collapseCalcs.zip
(491 Bytes) Downloaded 79 times

User avatar
Billy+
Posts: 4157
Joined: 09 Dec 2016

19 Feb 2021

And that's why your devices look so good :clap:

ForgottenClank
RE Developer
Posts: 128
Joined: 14 Nov 2018

19 Feb 2021

rcbuse wrote:
19 Feb 2021
Here is a little python script I wrote that helps me out. It evaluates and collapses down any calculations inside device_2d.lua

I run it as follows:

Code: Select all

python collapseCalcs.py GUI2D/device_2D.lua
Which allows me to write things like:

Code: Select all

ButtonTool0 =  { offset = {575+5*30, 200-10*5}, { path="SeedSwitch", frames = 2 }},
And then I run it every build and the file comes out:

Code: Select all

  ButtonTool0 =  { offset = {725, 150}, { path="SeedSwitch", frames = 2 }},
My device_2d.lua files used to get terrible.. like 200+100-30+5+20+50+10 with all the little tweaks.

The other thing I do is overlay a grid on my device background so I know how far I need to move something, like 10-20 pixels.
Those are some cool ideas. Thanks for sharing!
I am honestly considering making a tool for visually positioning widgets where the coordinates automatically get updated in the device_2D.lua file. But my inexperience with standalone software is scaring me. If anyone has inputs on that I'd be happy to hear them.

User avatar
selig
RE Developer
Posts: 11685
Joined: 15 Jan 2015
Location: The NorthWoods, CT, USA

19 Feb 2021

I just create the panel graphics at the 5x pixel resolution thus can type values directly from the objects on the layout into the .lua file.

I also started doing something new for my current project (only the second I developed in the 2D workflow), declaring values in the beginning of the 2D.lua file, which can act sort of like groups. For example, if I have two rows of knobs as on a current device under development, I have two values at the start that set that level, example highrow (high row) and lowrow (low row). This allows adjusting one variable to move all knobs/buttons using that variable up/down if need be as if they are grouped.

Example:
highrow = 185
leftEdgeA = 585
knobStride = 200
HighButton = 230
buttonStride = 150

Button 1
offset = { buttonLeft1, HighButton },
Button 2
offset = { buttonLeft1 + buttonStride, HighButton },
Knob 1
offset = { leftEdgeA, highrow },
Knob 2
offset = { leftEdgeA + knobStride, highrow },
Knob 3
offset = { leftEdgeA + knobStride * 2, highrow },
Knob 4
offset = { leftEdgeA + knobStride * 3, highrow },

As you can see, you can use simple maths on your declared variables to position the elements and be able to edit things later if necessary (as it sometime is, even with the best planning), so there are lots of ways to use this concept creatively.
Of course you still have to adjust labels on the panel graphics if you use that approach for text labels…
Selig Audio, LLC

ForgottenClank
RE Developer
Posts: 128
Joined: 14 Nov 2018

19 Feb 2021

selig wrote:
19 Feb 2021
I just create the panel graphics at the 5x pixel resolution thus can type values directly from the objects on the layout into the .lua file.
This is definitely a great technique! I guess I just go through too many stages of graphics changes where it starts to become a hassle.

User avatar
pongasoft
RE Developer
Posts: 478
Joined: 21 Apr 2016
Location: Las Vegas
Contact:

20 Feb 2021

No matter the solution, editing the GUI part of a RE is very cumbersome, labor intensive and error prone because there is no UI tool that helps you (like the built-in editor in VST3/VSTGUI).

User avatar
rcbuse
RE Developer
Posts: 1175
Joined: 16 Jan 2015
Location: SR388
Contact:

21 Feb 2021

pongasoft wrote:
20 Feb 2021
No matter the solution, editing the GUI part of a RE is very cumbersome, labor intensive and error prone because there is no UI tool that helps you (like the built-in editor in VST3/VSTGUI).
I've had to write a ton of python to do the tedious stuff and stop me from going insane. To name a few:
Populate the property_tag's in motherboard and generate a c++ Constants.h file
Generate the ui_groups based on property name
Generate all the texts.lua strings based on property names
Generate all the remote names (normal,8,4) based on property names
Generate all the midi cc's and remote entries
Generate the realtime_controller based on the motherboard entries
Generate the HandleDiffs(const TJBox_PropertyDiff iPropertyDiffs[], TJBox_UInt32 iDiffCount) based on the motherboard and tags and type

User avatar
Enlightenspeed
RE Developer
Posts: 1103
Joined: 03 Jan 2019

21 Feb 2021

rcbuse wrote:
21 Feb 2021
pongasoft wrote:
20 Feb 2021
No matter the solution, editing the GUI part of a RE is very cumbersome, labor intensive and error prone because there is no UI tool that helps you (like the built-in editor in VST3/VSTGUI).
I've had to write a ton of python to do the tedious stuff and stop me from going insane. To name a few:
Populate the property_tag's in motherboard and generate a c++ Constants.h file
Generate the ui_groups based on property name
Generate all the texts.lua strings based on property names
Generate all the remote names (normal,8,4) based on property names
Generate all the midi cc's and remote entries
Generate the realtime_controller based on the motherboard entries
Generate the HandleDiffs(const TJBox_PropertyDiff iPropertyDiffs[], TJBox_UInt32 iDiffCount) based on the motherboard and tags and type
I'm probably going to do this before I start my first 'serious' project, as it will get too labour intensive to do so otherwise. Not sure yet whether to do it in Python or to build it as a Windows Desktop App in VS. Probably the Remote entries is the bit that gets on my nerves the most as it tends to be done last.
Last edited by Enlightenspeed on 21 Feb 2021, edited 1 time in total.

User avatar
orthodox
RE Developer
Posts: 2286
Joined: 22 Jan 2015
Location: 55°09'24.5"N 37°27'41.4"E

21 Feb 2021

I once tried writing JS scripts that could generate both lua layout files and Photoshop documents from one source file, it even worked, but I found it more complex and time consuming than doing it manually. So I've given up on attempts to ease my editing process.
I still use scripting in other areas, like generating C++ constant arrays in WolframScript or automating build process in Perl.

User avatar
Billy+
Posts: 4157
Joined: 09 Dec 2016

21 Feb 2021

rcbuse wrote:
21 Feb 2021

I've had to write a ton of python to do the tedious stuff and stop me from going insane. To name a few:
Populate the property_tag's in motherboard and generate a c++ Constants.h file
Generate the ui_groups based on property name
Generate all the texts.lua strings based on property names
Generate all the remote names (normal,8,4) based on property names
Generate all the midi cc's and remote entries
Generate the realtime_controller based on the motherboard entries
Generate the HandleDiffs(const TJBox_PropertyDiff iPropertyDiffs[], TJBox_UInt32 iDiffCount) based on the motherboard and tags and type
Seems like you have a lot of great tools that would go very nicely with re cmake :- viewtopic.php?f=61&t=7518553

User avatar
Enlightenspeed
RE Developer
Posts: 1103
Joined: 03 Jan 2019

22 Feb 2021

orthodox wrote:
21 Feb 2021
I once tried writing JS scripts that could generate both lua layout files and Photoshop documents from one source file, it even worked, but I found it more complex and time consuming than doing it manually. So I've given up on attempts to ease my editing process.
I still use scripting in other areas, like generating C++ constant arrays in WolframScript or automating build process in Perl.
Yeah, doing it in either Java or Javascript would do I suppose. I think NetBeans still has that GUI editor thing for Swing, actually, so that would be a pretty simple way of doing it. That said, thinking of this way of doing it just pushes me back toward doing it as a Windows Desktop App.

User avatar
orthodox
RE Developer
Posts: 2286
Joined: 22 Jan 2015
Location: 55°09'24.5"N 37°27'41.4"E

11 May 2021

Now I've developed a way to generate the device_2D.lua layout definition together with the widget images from one script. It is particularly useful if most of the images can be drawn with graphics primitives. The script is in Wolfram (Mathematica) language, which has functions for drawing graphics among other things. Now I can use underlying backgrounds from the place I am drawing a widget at, combine multiple labels in one image and much more. All the layout coordinates are defined only once, in one source file, and the script generates both widget png filmstrips and device_2D.lua and the panel preview from it in 10 seconds.
The source definition looks like this:

Code: Select all

(*= Layout definition =*)
MyPanels = {
	"front" -> {
		"S_backdrop" -> {
			ImgLoad["Panel_front"]
		}
		, {
			ImgPos[{540,110}]
			, {
				ImgPos[{0,0}]
				, {
					ImgPos[{128,-38}], ImgDim[{40,18}]
					, { ImgHide[]
						, ImgDraw[Function[DrawGraphics[{}]]]
						, "S_button_align_gain" -> ImgSave["ButtonAlign"]
					}
					, { UseBack[]
						, ImgDraw[Function[DrawGraphics[ButtonWithText["ALIGN",0]]]]
						, "S_button_align_gain_off" -> ImgSave["ButtonAlignOff"]
					}
					, { UseBack[], ImgHide[]
						, ImgDraw[Function[DrawGraphics[ButtonWithText["ALIGN",1]]]]
						, "S_button_align_gain_on" -> ImgSave["ButtonAlignOn"]
					}
				}
			}
...

Post Reply
  • Information
  • Who is online

    Users browsing this forum: No registered users and 2 guests