Author Topic: Dynamic change res  (Read 4720 times)

Luke_Nukem

  • Sr. Member
  • ****
  • Posts: 135
    • View Profile
    • Blogging about Rust lang
Dynamic change res
« on: June 05, 2014, 01:24:42 PM »
G'day guys.
Thought I'd share this little block with you all.

I wasn't very happy with how AttractMode was handling screen res and rotation, so I ended up brewing up what is just a large if-else block and some options.
This combined with positions/sizes that are divided from the layout width and height, actually becomes quite robust. The only hardcoded positions I tend to have now are a few text strings in corners, everything else is relative to width/height.

Maybe I missed it, but does AttractMode have an actual return global for when it is rotated?
It would be excellent to have this check the global and select the width/height accordingly.

Code: [Select]
class UserConfig {
</ label="Screen Size", help="Select the screen size",
options="1360x768,1280x1024,1280x768,1280x720" />
screenSize="1360x768";

</ label="Screen Rotate", help="Swap X/Y dimensions for rotated screens",
options="Yes,No" />
rotated="No";
}
local layoutSettings = fe.get_config();

if ( layoutSettings["screenSize"] == "1360x768" ){
if ( layoutSettings["rotated"] == "Yes") {
fe.layout.width=768;
fe.layout.height=1360;
}
else if ( layoutSettings["rotated"] == "No") {
fe.layout.width=1360;
fe.layout.height=768;
}
}
else if ( layoutSettings["screenSize"] == "1280x1024" ){
if ( layoutSettings["rotated"] == "Yes"){
fe.layout.width=1024;
fe.layout.height=1280;
}
else if ( layoutSettings["rotated"] == "No") {
fe.layout.width=1280;
fe.layout.height=1024;
}
}
else if ( layoutSettings["screenSize"] == "1280x768" ){
if ( layoutSettings["rotated"] == "Yes") {
fe.layout.width=768;
fe.layout.height=1280;
}
else if ( layoutSettings["rotated"] == "No") {
fe.layout.width=1280;
fe.layout.height=768;
}
}
else if ( layoutSettings["screenSize"] == "1280x720" ){
if ( layoutSettings["rotated"] == "Yes") {
fe.layout.width=720;
fe.layout.height=1280;
}
else if ( layoutSettings["rotated"] == "No") {
fe.layout.width=1280;
fe.layout.height=720;
}
}

liquid8d

  • Global Moderator
  • Sr. Member
  • *****
  • Posts: 442
    • View Profile
Re: Dynamic change res
« Reply #1 on: June 05, 2014, 03:36:53 PM »
Looks nice, I'll have to check this one out.. for now, you could probably check fe.layout.orient in onTick.

This would be a good reason to think about adding callbacks to AM. Just like how onTransition is triggered for transitions but for other events that occur so you don't have to keep checking them in onTick. I added generic callback functions in ExtendedObjects where anything that wants to can run something like 'ExtendedObjects.run_callback('onRotationChanged', params), then any .nut files or class can register and listen for that callback and act on it.

A bunch of other things could probably be added like ScreenSaverActive, onKeyPress, etc. with parameters included.

Luke_Nukem

  • Sr. Member
  • ****
  • Posts: 135
    • View Profile
    • Blogging about Rust lang
Re: Dynamic change res
« Reply #2 on: June 05, 2014, 05:40:24 PM »
I agree there.
Hmm, I'm having difficulty trying to work out how to get the value of the screen rotation...
It doesn't seem to be very open to script?

liquid8d

  • Global Moderator
  • Sr. Member
  • *****
  • Posts: 442
    • View Profile
Re: Dynamic change res
« Reply #3 on: June 06, 2014, 04:57:10 PM »
hmm, interesting... it doesn't seem to pick up rotations from the hotkeys, only if you change it from your layout (i.e. fe.layout.orient = RotateScreen.Right;) That seems like a bug.

I also didn't realize this:
"a layout could provide a "layout.nut" for horizontal monitor orientations and a "layout-vert.nut" for vertical"

I need to mess with vertical layouts more.. I cheaped out and didn't get a rotating mount (expensive!) for the tv I am using, so I don't use vertical layouts :/

Luke_Nukem

  • Sr. Member
  • ****
  • Posts: 135
    • View Profile
    • Blogging about Rust lang
Re: Dynamic change res
« Reply #4 on: June 07, 2014, 02:32:36 PM »
I think you still have to manually activate those scipts with fe.do_nut.

I also rewrote the above code to be much more elegant;
Code: [Select]
local layoutSettings = fe.get_config();
switch (layoutSettings["screenSize"]){
case "1360x768":
switch (layoutSettings["rotated"]){
case "Yes": fe.layout.width=768; fe.layout.height=1360; break;
case "No" : fe.layout.width=1360; fe.layout.height=768; break;
}
break;
case "1280x1024":
switch (layoutSettings["rotated"]){
case "Yes": fe.layout.width=1024; fe.layout.height=1280; break;
case "No" : fe.layout.width=1280; fe.layout.height=1024; break;
}
break;
case "1280x768":
switch (layoutSettings["rotated"]){
case "Yes": fe.layout.width=768; fe.layout.height=1280; break;
case "No" : fe.layout.width=1280; fe.layout.height=768; break;
}
break;
case "1280x720":
switch (layoutSettings["rotated"]){
case "Yes": fe.layout.width=720; fe.layout.height=1280; break;
case "No" : fe.layout.width=1280; fe.layout.height=720; break;
}
break;
}


FOrmatting of it hasn't translated well to the forum though, it's just adding an extra tab to the case "No" line

raygun

  • Administrator
  • Sr. Member
  • *****
  • Posts: 383
    • View Profile
Re: Dynamic change res
« Reply #5 on: June 10, 2014, 10:30:54 PM »
hmm, interesting... it doesn't seem to pick up rotations from the hotkeys, only if you change it from your layout (i.e. fe.layout.orient = RotateScreen.Right;) That seems like a bug.

Not so much a bug as a yet to be implemented feature  :)  the orientation that you can set in the layout is the "base" orientation.  The hotkey toggles are added to that base (so if "90" is the base, toggling "rotate 90" back and forth will jump from 90 to 180 and back). I can certainly add a way to get the toggled rotation values from the layout as well... 

I also didn't realize this:
"a layout could provide a "layout.nut" for horizontal monitor orientations and a "layout-vert.nut" for vertical"

This is another feature that probably isn't explained well enough in the documentation.  But say for example if you have a layout with "layout.nut" and "layout-vert.nut" in the directory, then Attract-Mode defaults to using the "layout.nut" as the layout file.  There is a command that can be mapped in the frontend called "Toggle Layout" that when pressed will essentially cycle through all the .nut files that start with "layout"... so in this example the "Toggle Layout" command toggles between using the layout.nut and layout-vert.nut as the layout.  You could of course have any number of layout*.nut files to toggle between depending on what you are trying to do.

Oh and whatever .nut file was toggled to for the layout when you shutdown will be remembered and used the next time the layout is loaded...

This would be a good reason to think about adding callbacks to AM. Just like how onTransition is triggered for transitions but for other events that occur so you don't have to keep checking them in onTick. I added generic callback functions in ExtendedObjects where anything that wants to can run something like 'ExtendedObjects.run_callback('onRotationChanged', params), then any .nut files or class can register and listen for that callback and act on it.

A bunch of other things could probably be added like ScreenSaverActive, onKeyPress, etc. with parameters included.

It seems that adding another transition call for whenever a user action occurs could cover this... 

cools

  • Full Member
  • ***
  • Posts: 61
    • View Profile
Re: Dynamic change res
« Reply #6 on: July 03, 2014, 05:29:53 AM »
Here is how I'm handling resolution independence and rotation in an experiment.

Code: [Select]
local flw = fe.layout.width;
local flh = fe.layout.height;
// Uncomment if monitor is rotated to preserve aspect ratios correctly.
//fe.layout.orient=RotateScreen.Right;
if (fe.layout.orient==RotateScreen.Right) {
 fe.layout.width = flh;
 fe.layout.height = flw;
 flw = fe.layout.width;
 flh = fe.layout.height;
}

local tlw = flw*0.75;
local tlh = flh*0.75;

local tilem = fe.add_surface( tlw, tlh);
local tilel = fe.add_surface( tlw, tlh);
local tiler = fe.add_surface( tlw, tlh);

tilem.alpha = 255;
tilel.alpha = 128;
tiler.alpha = 128;

tilem.set_pos ( flw*0.125, flh*0.125);
tilel.set_pos ( tilem.x-tlw, tilem.y);
tiler.set_pos ( tilem.x+tlw, tilem.y);

local snx=0-(tlw*0.125);
local sny=0-(tlh*0.125);
local snw=tlw*1.25;
local snh=tlh*1.25;
local wlw=tlw*0.75;
local wlh=tlh*0.2;
local wlx=tlw*0.125;
local wly=0;

local tsl = tilel.add_artwork( "snap", snx, sny, snw, snh);
local wll = tilel.add_artwork( "wheel", wlx, wly, wlw, wlh);
tsl.index_offset = -1;
wll.index_offset = -1;
wll.preserve_aspect_ratio = true;
local tsm = tilem.add_artwork( "snap", snx, sny, snw, snh);
local wlm = tilem.add_artwork( "wheel", wlx, wly, wlw, wlh);
wlm.preserve_aspect_ratio = true;
local tsr = tiler.add_artwork( "snap", snx, sny, snw, snh);
local wlr = tiler.add_artwork( "wheel", wlx, wly, wlw, wlh);
tsr.index_offset = 1;
wlr.index_offset = 1;
wlr.preserve_aspect_ratio = true;

cools

  • Full Member
  • ***
  • Posts: 61
    • View Profile
Re: Dynamic change res
« Reply #7 on: July 03, 2014, 08:23:11 AM »
Actually this is better.

Code: [Select]
local flw = fe.layout.width;
local flh = fe.layout.height;
// Rows must be either 3 or 5
local rows = 3;
local aspect = flw/flh;
local cols = rows * aspect;
local tlw = flw/cols;
local adw=0;

// Uncomment if monitor is rotated to preserve aspect ratios correctly.
//fe.layout.orient=RotateScreen.Right;
if (fe.layout.orient==RotateScreen.Right) {
 fe.layout.width = flh;
 fe.layout.height = flw;
 flw = fe.layout.width;
 flh = fe.layout.height;
 aspect = flh/flw;
 cols = rows * aspect;
 tlw = flw/cols;
 adw=flw-tlw;
}

local tlh = flh/rows;

local adx=tlw;
local ady=0;
local adh=flh;

local advert = fe.add_artwork( "flyer", adx, ady, adw, adh)
advert.preserve_aspect_ratio = true;

local tilep2 = fe.add_surface(tlw, tlh);
local tilep1 = fe.add_surface(tlw, tlh);
local tiles = fe.add_surface(tlw, tlh);
local tilen1 = fe.add_surface(tlw, tlh);
local tilen2 = fe.add_surface(tlw, tlh);

tilep2.alpha = 64;
tilep1.alpha = 128;     
tiles.alpha = 255;
tilen1.alpha = 128;
tilen2.alpha = 64;

tiles.set_pos ( 0, (flh*0.5)-(tlh*0.5));
tilep1.set_pos ( tiles.x, tiles.y-tlh);
tilep2.set_pos ( tiles.x, tiles.y-tlh-tlh); 
tilen1.set_pos ( tiles.x, tiles.y+tlh);
tilen2.set_pos ( tiles.x, tiles.y+tlh+tlh);

local snx=0-(tlw*0.125);
local sny=0-(tlh*0.125);
local snw=tlw*1.25;
local snh=tlh*1.25;
local wlw=tlw*0.9;
local wlh=tlh*0.9;
local wlx=tlw*0.05;
local wly=0;

local tp2 = tilep2.add_artwork( "snap", snx, sny, snw, snh);
local wp2 = tilep2.add_artwork( "wheel", wlx, wly, wlw, wlh);
tp2.index_offset = -2;
wp2.index_offset = -2;
wp2.preserve_aspect_ratio = true;
local tp1 = tilep1.add_artwork( "snap", snx, sny, snw, snh);
local wp1 = tilep1.add_artwork( "wheel", wlx, wly, wlw, wlh);
tp1.index_offset = -1;
wp1.index_offset = -1;
wp1.preserve_aspect_ratio = true;
local tss = tiles.add_artwork( "snap", snx, sny, snw, snh);
local wls = tiles.add_artwork( "wheel", wlx, wly, wlw, wlh);
wls.preserve_aspect_ratio = true;
local tn1 = tilen1.add_artwork( "snap", snx, sny, snw, snh);
local wn1 = tilen1.add_artwork( "wheel", wlx, wly, wlw, wlh);
tn1.index_offset = 1;
wn1.index_offset = 1;
wn1.preserve_aspect_ratio = true;
local tn2 = tilen2.add_artwork( "snap", snx, sny, snw, snh);
local wn2 = tilen2.add_artwork( "wheel", wlx, wly, wlw, wlh);
tn2.index_offset = 2;
tn2.index_offset = 2;
wn2.preserve_aspect_ratio = true;

(I know I should pull out tile creation into a class but this will do for now)

Luke_Nukem

  • Sr. Member
  • ****
  • Posts: 135
    • View Profile
    • Blogging about Rust lang
Re: Dynamic change res
« Reply #8 on: July 03, 2014, 05:36:06 PM »
That's what I tried first cools.
Unfortunately, it didn't seem to pick up when it was rotated or not...

Might have another crack at it some time. Been too busy building machines to do much more scripting.

raygun

  • Administrator
  • Sr. Member
  • *****
  • Posts: 383
    • View Profile
Re: Dynamic change res
« Reply #9 on: July 03, 2014, 11:21:51 PM »
Ok, if you update to master on github I've updated Attract-Mode to allow you to get the actual rotation state at any given time.

In a layout script, the following code will give you the actual rotation:

Code: [Select]
local actual_rotation = ( fe.layout.base_rotation + fe.layout.toggle_rotation ) % 4;
"actual_rotation" will be equal to one of the following:

RotateScreen.None
RotateScreen.Right
RotateScreen.Flip
RotateScreen.Left

Oh and the screen width and screen height are available in the "ScreenWidth" and "ScreenHeight" constants (in case you missed it at the bottom of the layouts documentation).

So where "actual_rotation" is RotateScreen.Right or RotateScreen.Left, setting the layout *width*=ScreenHeight and layout *height*=ScreenWidth should get you going with the correct aspect ratio for vertical setups... (at least that is the intention!)

cools

  • Full Member
  • ***
  • Posts: 61
    • View Profile
Re: Dynamic change res
« Reply #10 on: July 05, 2014, 01:27:39 AM »
That's what I tried first cools.
Unfortunately, it didn't seem to pick up when it was rotated or not...

Might have another crack at it some time. Been too busy building machines to do much more scripting.

Strange, it works for me.

Being able to get the actual rotation will be useful :) trying to make something that is resolution and rotation independent.

raygun

  • Administrator
  • Sr. Member
  • *****
  • Posts: 383
    • View Profile
Re: Dynamic change res
« Reply #11 on: July 08, 2014, 09:19:10 AM »
Being able to get the actual rotation will be useful :)

better late than never!  :)