Attract-Mode Support Forum

Attract-Mode Support => Scripting => Topic started by: liquid8d on June 15, 2015, 10:04:00 PM

Title: Discussion of creating Aspect-Aware Layouts
Post by: liquid8d on June 15, 2015, 10:04:00 PM
Continuing discussion of:
http://forum.attractmode.org/index.php?topic=272.0

I'd like to see a sort of unified way of designing layouts, ensuring they work well for all aspect ratios. Many people design their layouts with a single resolution / aspect in mind which will scale/stretch but not look as nice in other aspects / resolutions.

There's two things I'd like to see to help with this:

Storing 'set' values at the top of your layout, then set them from the variables in your layout code

Here's an example:
Code: [Select]
LAYOUT_SETTINGS <- {
   rotate_90 = {
      width = fe.layout.height,
      height = fe.layout.width,
      title = { x = 0, y = fe.layout.height / 1.08 },
      wheel = { x = 0, y = fe.layout.height / 1.20, x_divisor = 2.8 },
   },
   default = {
      width = fe.layout.width,
      height = fe.layout.height,
      title = { x = 0, y = fe.layout.height / 1.10 },
      wheel = { x = 0, y = fe.layout.height / 1.33, x_divisor = 2.4 },
   }
}

local values = LAYOUT_SETTINGS["default"];
if (( actual_rotation == RotateScreen.Left ) || ( actual_rotation == RotateScreen.Right )) values = LAYOUT_SETTINGS["rotate_90"];

//now we just reference values for everything when setting positions and sizes for objects...
title.x = values.title.x;
wheel.y = values.wheel.y;

This is a personal preference, but tables are a good way to store a lot of values and a lot of values within values without your code getting out of hand. It's is however important to be careful with table syntax and formatting it for good readability. It's  also better than arrays for readability because you will use word references like values.title.y instead of values[2][1]. You can also store alternate settings for your objects and keep the original values to reference back if needed.

You wouldn't have to use tables, but it's a good idea for all your initial values to be in one location, preferably at the top of the layout code.

Prepare layouts that will work in multiple aspects

Most major changes to your layout will probably be objects position and size.

If you go by my table suggestion, you can have a table that stores settings for each object at each individual aspect / resolution you want to support, then reference something like values[current_aspect].title.x in your code.

Otherwise, if you just keep all your settings in variables at the top, it will be easy to make a copy of your layout, store it as layout-altaspect.nut and adjust your variables to work with the new aspects / resolution.

Either way, we could make it easy to add a user config option of Aspect: standard,widescreen,etc. and use the correct values or load the appropriate layout.

Just some ideas I had when it comes to cleaning up code and making it easier to deal with multiple layout configurations. Perhaps a couple templates for creating multiple-aspect layouts would be helpful?

Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: verion on June 16, 2015, 01:18:43 AM
What I would like to use is some kind of mechanism that is working with responsive web pages.

align to left/right/top/bottom
center horizontally/center vertically.

Like with responsive webpages - you can design layout with that flexibility in mind - with object scaling related to screen width and wisely applied white (fill) space.

----

But of course this is more "lazy" approach - it can be combined with tables for fine tuning of the design. But more like overwriting the layout defaults (like in CSS).
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: Luke_Nukem on June 16, 2015, 03:47:16 AM
I just pushed some major changes to my github (https://github.com/Luke-Nukem/attract-extra/tree/master/layouts/swapper/).

The Swapper layout now uses a proof of concept way of doing a universal layout. It happens to highlight quite a few things that you need to do also.
One of those things is to make functions to update each object on your screen, as AM won't do it for you.

Another thing, "Align.Centre" won't work if you try and call it after setting a new screen width and height, so you'll have to do centering manually.

I'll probably do some more major hacking tomorrow. Out of time tonight, but at least I got this done.

(PS: I've created a "shaders" dir in my fork of attractmode-extras. They're all Mame usable shaders, but can easily be used in AM by just making sure you call;
Code: [Select]
                videoShader.set_param( "color_texture_sz", 640, 480 );
                videoShader.set_param( "color_texture_pow2_sz", 640, 480 );
                videoShader.set_texture_param( "mpass_texture" );
color_texture** should probably be set by something like video.width and video.height, but will need a callback to update it on each change)

Shader dir = https://github.com/Luke-Nukem/attract-extra/tree/master/layouts/shaders
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: liquid8d on June 16, 2015, 06:54:07 AM
Hah! You beat me to it :) I'll check out what you did in there in a bit.

verion,
The positioning you are talking about is doable - I have functions in my animate module that position an object at "topleft/center/bottomright", etc.. based on the layout width/height and the object width/height. It can be a bit complicated though and I also think that could limit design creativity:

https://raw.githubusercontent.com/liquid8d/attract-extra/master/extras/positions.png

I've also created functions to place things by percentages, but you would still have to have aspect / resolution specific percentages.


Here's what we have to deal with:
* Position
* Size
* Other object settings like Rotation/Skew/Pinch
* Font / Font Size
* Images
* Other non-object variables that might change dependent upon aspect or resolution

This is why I think it's best to specify values manually for each, and do it all in one spot. A default one can be used to "fall back" to. Kodi/XBMC uses a similar method to what I'm talking about, having folders for various aspects or resolutions - and it will pick and match the best one suited for the users resolution:
Quote
The order that XBMC looks for it's skin files are as follows:

    It first looks in the current screenmode folder (one of 1080i, 720p, NTSC16x9, NTSC, PAL16x9 or PAL)
    If the current screenmode is 1080i and there's no 1080i folder, it then looks in the 720p folder.
    Finally, it looks in the res folder.


Here's what I've come up with so far:
Code: [Select]
class UserConfig </ help="Intro Layout Options" />
{
</ label="Screenmode", help="Pick your preferred screen mode", options="4x3,720p,1080p" order=1 />
screenmode="4x3";
}

local config = fe.get_config();

print( "Using screen mode: " + config["screenmode"] + "\n" );
//set the width/height based on the choosen screen mode
fe.layout.width = config["screenmode"].width;
fe.layout.height = config["screenmode"].height;

//ResourcePath(file) will return the best path based on the user selected aspect/resolution
ResourcePath <- function( file ) {
    //here we can do a fallback match - exact, best match or default path
    return config["screenmode"] + "/" + file;
}

//Store all SETTINGS for each aspect / resolution you want to support here
// This might be as simple as object property values or your own varibles that might
// determine a change in a layout based on aspect / resolution
SETTINGS <- {
    //every setting MUST be defined in default (this will be the fallback value)
    "default": {
        "width": 640,
        "height": 480,
        "logo": { src = ResourcePath("bg.png"), x = 0, y = 0, width = fe.layout.width, height = fe.layout.height },
        "title": { x = 0, y = 450, width = 640, height = 30 },
        "snap": { x = 0, y = 0 }
        "fontName": "Arial",
        "animate_wheel": false
    },
    //aspect-resolution specific values can be added for each
    "720p": {
        "width": 1280,
        "height": 720,
        "title": { x = 0, y = 0, width = 1280, height = 30 },
        "animate_wheel": true
    },
    "1080p": {
        "width": 1920,
        "height": 1080
    }
}

//Based on the requested aspect-resolution, the correct settings from above will be stored here
Setting <- {}
foreach ( name, val in SETTINGS[ config["screenmode"] ] )
{
    //here we can do a fallback match - exact, best match or default value
    Setting[name] <- val;
}


/////////////////////////////////////////////////////////////////////////////
// Now we start 'coding' our layout. Just use Setting.? to access any properties
// or variables we configured
//
// This part could just be in the screen mode folder and we could just do this to end the main layout.nut file:
// fe.do_nut( Resource( "layout.nut" ) );
/////////////////////////////////////////////////////////////////////////////
local logo = fe.add_image( Setting.logo.src, Setting.logo.x, Setting.logo.y, Setting.logo.width, Setting.logo.height );
local title = fe.add_text( "[Title]", Setting.title.x, Setting.title.y, Setting.title.width, Setting.title.height );

I could put a lot of the excess stuff here in a module and the user would just include the module, add their settings and be up and running.

* In the SETTINGS table, you set default values and then any aspect-resolution dependent values
* It would automatically fallback to the best match from all your settings.
* All values would be available via Setting.value - for example Setting.title.width would return 1280 for the 720p mode and 640 for the 4x3 mode.

That's still a WIP that would be based on what we discuss here, but hopefully it's clear enough. I don't want to make it MORE difficult to support mutiple setups - it should be MUCH LESS difficult.


Let me know what you think!
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: omegaman on June 16, 2015, 07:50:35 AM
Hi all!
I've been busy, so I thought it was important to catch up on this topic and offer my 2 cents worth. It’s my basic understanding that when designing layouts for all screen resolutions you do it in terms of pixels or percentages. With the latter being the preferred method. Once that is decided, you need to determine what will be the lowest screen resolution that is supported. For example, if you decide that 640x480 will be the lowest res that anyone would use in their layouts you would design all your graphic elements at this resolution. Using these methods you should be able to scale up to whatever resolution along as it’s in the same aspect like 4:3 or 16x9.

And, this is essentially what I do in my layouts now except that I use pixel position. I design a layout based on either 1024x768 or 1024x1024 res and scale from there. Though, the robospin theme was done at the latter resolution and probably should have been done in 1024x768.  Regardless, my layouts will scale proportionally and look good enough, at least to my eyes. Check out my grey theme or robospin to get an idea of what I’m talking about. 

Now, all that said and to Liquid8’s point. There is no doubt that using percentages and tables are going to be the more eloquent solution. Maybe, something like a table supporting all resolutions with width and height @ 100% or whatever percent you want.  Then you would use fixed measurements for rows and columns. Something like first and last columns given fixed measurements of px. The middle column would be given no measurement and would scale to fit page. And, all the rows would have a fixed height except for the content row. This based on  stuff I’ve read on website design.

No matter what method you use, I think there will always be some stretching based on the aspect ratios, though a table or grid would definitely minimize this. It is the nature of the beast.
IMHO, wide screen resolutions are just ugly for arcade layouts. And, the only thing that even remotely looks good using them are grid type layouts.   
This is my 2 cents worth.




Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: omegaman on June 16, 2015, 07:51:40 AM
Responsive web pages still have there issues as well.
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: verion on June 16, 2015, 08:28:46 AM
@omegaman

Quote
For example, if you decide that 640x480 will be the lowest res that anyone would use in their layouts you would design all your graphic elements at this resolution.

And not the oposite? Shoot for highest possible resolution and scale down? Like designing for 1280 x 1024 and scale down to 640x480. Bitmaps scales down perfectly without loosing quality. Scaling up is not that great.

EDIT: Ahhhh... Now I get it - You should aim for the lowest resolution in terms of SIZE and VISIBILITY of the elements displayed on the screen. Going from hi-res to low-res can result in the whole interface being too small. I can (and should) design in hi-res but I should keep in mind how it will look on low-res screen.

----

I agree that some stretching is ok. But stretching from 16:9 to 16:10 or the other way.
Not from 4:3 to 16:9 - that is too much (for me - of course).

----

@ Luke-Nukem, Liquid8d

That looks very promising.
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: Luke_Nukem on June 16, 2015, 07:18:05 PM
I've just made a big push to Git. https://github.com/Luke-Nukem/attract-extra/tree/master/layouts/rotating_basic

New layout, uses the bg art from basic as an example.
It's a really good example of scaling a single layout, with fixed aspect ratio. Can someone test and confirm that it does indeed scale to other resolutions okay?

I've basically made one main piece of art, the bg.png. This one scales to each resolution and rotation, while keeping the correct aspect ratio for itself.
Every other bit of art, surfaces, videos, text, all base their co-ordinates and width/height on the BG art, via a set of ratios.

In theory, the same methods I've used here, should also work well for going in the other direction. I.e from larger art to smaller, since everything is getting their settings off the one art bit.

The only thing I'm really worried about is;
Code: [Select]
//gameList.charsize = 26;
gameList.charsize = (overlay.height / 18.6);
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: Luke_Nukem on June 16, 2015, 10:32:18 PM
I have also made another layout based on the last one, but using a different BG for horizontal/vertical orientations.

Everything should scale nicely.
https://github.com/Luke-Nukem/attract-extra/tree/master/layouts/rotating_new
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: verion on June 17, 2015, 03:20:59 AM
I don't know what to expect - but it looks like this on 4:3 and 16:9 screen.
Something is wrong.
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: Luke_Nukem on June 17, 2015, 04:46:27 AM
Thanks dude. Should be an easy fix, but will need to do it tomorrow.

Part was through building a module to report aspect ratio.
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: Luke_Nukem on June 17, 2015, 04:52:04 AM
Actually, in set_overlay.nut, in function overlayUpdate_Horz change this line;

    local ratio = fe.layout.height / overlay_horz.texture_height;

To;

local ratio = fe.layout.height / overlay_horz.texture_width;
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: verion on June 17, 2015, 05:10:12 AM
Nope. It doesn't fix that.
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: omegaman on June 17, 2015, 05:55:33 AM
verion-

Well, it's my understanding that you always start with a minimum resolution. And, I think that is because most PC users use 1024x768 or greater. I see what you are getting at though. Why don't you test it with roboskin? Just set your resolution to a maxium then tweak the layout.nut to the new size and see how it scales down. I would backup the original .nut though.
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: omegaman on June 17, 2015, 06:54:39 AM
Luke-

My newer layouts already scale based on the base resolution the layout was designed for. The only thing I see that you are doing differently - and, forgive my ignorance on this, is you are creating a function for the math and calling other .nuts with the pixel position based on the BG. That and you can switch from horizontal to vertical which is nice. But, will this code scale much better than what I'm doing below. This is more for learning than a critique.     



class UserConfig {
   </ label="SpinWheel", help="The artwork to spin", options="marquee,wheel" /> orbit_art="wheel";
   </ label="Display Flyer", help="Display the flyer/game box in background.", options="Yes,No" /> enable_flyer="Yes";
   </ label="Enable Background", help="Enable/Disable background", options="Yes,No" /> enable_BG="Yes";
   </ label="Enable BG mask", help="Enable/Disable mask", options="Yes,No" /> enable_BG_mask="Yes";
   </ label="Enable Year", help="Enable/Disable year", options="Yes,No" /> enable_year="Yes";
}

local config = fe.get_config();
local flx = fe.layout.width;
local fly = fe.layout.height;
local flw = fe.layout.width;
local flh = fe.layout.height;
fe.layout.font="coolvetica";

//load animate module
fe.load_module("animate");

//background image
if (config.enable_BG == "Yes") {
fe.add_image( "bg.png", flx*0.0, fly*0.0, flw, flh);
}

//background mask
if (config.enable_BG_mask == "Yes") {
fe.add_image( "mask.png", flx*0.0, fly*0.0, flw, flh);
}

//property animation for snap
local snap = fe.add_artwork("snap", flx*0.1, fly/3, flw/2.8, flh/2.3);                   
snap.preserve_aspect_ratio = false;

local pos_cfg = { when = Transition.ToNewSelection,
     property = "position",
    start = { x = -flx*1.0, y = fly/3.5 },
    end = { x = flx*0.1, y = fly/3 }, time = 1000 }

animation.add( PropertyAnimation( snap, pos_cfg ) );

//Display flyer on right
if (config.enable_flyer == "Yes") {
local flyer = fe.add_artwork("flyer", flx/1.7, fly/3.9, flw/3.6, flh/1.8);                   
flyer.rotation = 3

local alpha_cfg = {
    when = Transition.ToNewSelection,
    property = "alpha",
    start = 0,
    end = 150,
    time = 1000
}
animation.add( PropertyAnimation( flyer, alpha_cfg ) );

local pos_cfg = { when = Transition.ToNewSelection,
     property = "position",
    start = { x = flx*8.0, y = fly/3.8 },
    end = { x = flx/1.7, y = fly/3.9 }, time = 1000 }

animation.add( PropertyAnimation( flyer, pos_cfg ) );
}


local title = fe.add_text("[Title]", flx*0.0, fly/1.25, flw, flh*0.025);
title.set_rgb( 220, 220, 220 );
//title.align = Align.Right;

local scale_cfg =
{ when = Transition.ToNewSelection,
 property = "scale",
 start = 1.0,
 end = 1.5,
 time = 1500 }

animation.add( PropertyAnimation( title, scale_cfg ) );

local pos_cfg = { when = Transition.ToNewSelection,
     property = "position",
    start = { x = flx*0.0, y = fly/1 +100 },
    end = { x = flx*0.0, y = fly/1.25 }, time = 1000 }

animation.add( PropertyAnimation( title, pos_cfg ) );
 
//text stuff

 
if (config.enable_year == "Yes") {
//local yearshadow = fe.add_text( "[Year]", flx*0.42, fly/8, flw*0.4, flh*0.08 );
//yearshadow.set_rgb( 10, 10, 10 );
//yearshadow.align = Align.Left;
//yearshadow.rotation = 0;

local year = fe.add_text( "[Year]", flx*0.41, fly/95, flw*0.4, flh*0.08 );
year.set_rgb( 255, 255, 255 );
year.align = Align.Left;
year.rotation = 0;
year.alpha = 220;

animation.add( PropertyAnimation( year, {
when = Transition.ToNewSelection,
property = "y",
start = -180, end = year.y,
tween = Tween.Bounce,
time = 2500 } ) );

local pos_cfg = { when = Transition.ToNewSelection,
     property = "position",
    start = { x = flx*0.41, y = -fly*0.5  },
    end = { x = flx*0.41, y = fly/95 }, time = 1000 }
     animation.add( PropertyAnimation( year, pos_cfg ) );
}

local msgplay = fe.add_text( "Played :" , flx*0.9, fly*0.01, flw*0.3, flh*0.026 );
msgplay.set_rgb( 255, 255, 255 );
msgplay.align = Align.Left;   

local play = fe.add_text( "[PlayedCount]", flx*0.96, fly*0.01, flw*0.3, flh*0.026 );
play.set_rgb( 255, 255, 255 );
play.align = Align.Left;   

local filter = fe.add_text( "[ListFilterName]: [ListEntry]-[ListSize]", flx*0.01, fly*0.01, flw*0.3, flh*0.026 );
filter.set_rgb( 255, 255, 255 );
filter.align = Align.Left;
filter.rotation = 0;

fe.load_module( "conveyor" );
fe.load_module( "fade" );

class SimpleArtStrip extends Conveyor
{
   m_x=0; m_y=0; m_width=0; m_height=0; m_x_span=0; m_y_span=0;

   constructor( artwork_label, num_objs, x, y, width, height, pad=0 )
   {
      base.constructor();
      local my_list = [];
      for ( local i=0; i<num_objs; i++ )
         my_list.push( SimpleArtStripSlot(this,artwork_label) );
      set_slots( my_list );

      m_x=x+pad/2; m_y=y+pad/2;
      if ( width < height )
      {
         m_x_span=0;
         m_y_span=height;
         m_width=width-pad;
         m_height=height/m_objs.len()-pad;
      }
      else
      {
         m_x_span=width;
         m_y_span=0;
         m_width=width/m_objs.len()-pad;
         m_height=height-pad;
      }

      reset_progress();
   }
};

local my_strip = SimpleArtStrip( "wheel", 5, flx*0.0, fly*0.85 fe.layout.width/1.0, fe.layout.height/7.0, 1 );
my_strip.alpha = 255;

//marquee property animation
local marquee = fe.add_artwork("marquee", flx/4.6, fly/8, flw/1.8, flh/4.5);
local alpha_cfg = {
    when = Transition.ToNewSelection,
    property = "alpha",
    start = 40,
    end = 220,
    time = 1000
}
animation.add( PropertyAnimation( marquee, alpha_cfg ) );

local pos_cfg = { when = Transition.ToNewSelection,
     property = "position",
    start = { x = flx/4.6, y = -fly*0.5 },
    end = { x = flx/4.6, y = fly/8 }, time = 1000 }

animation.add( PropertyAnimation( marquee, pos_cfg ) );

             
local message = fe.add_text("Ready Player", flx*0.0, fly*0.4, fe.layout.width,80);
message.alpha = 0;
message.style = Style.Bold;

// Transitions
fe.add_transition_callback( "fancy_transitions" );

function fancy_transitions( ttype, var, ttime ) {
 switch ( ttype )
 {
 case Transition.StartLayout:
 case Transition.ToNewList:
 case Transition.ToNewSelection:
 case Transition.EndLayout:
  break;

 case Transition.FromGame:
  if ( ttime < 255 )
  {
   foreach (o in fe.obj)
    o.alpha = ttime;
    message.alpha = 0;     
     return true;
  }
  else
  {
   foreach (o in fe.obj)
    o.alpha = 255;
   message.alpha = 0;
 }
  break;
   
 case Transition.EndLayout:
  if ( ttime < 255 )
  {
   foreach (o in fe.obj)
    o.alpha = 255 - ttime;
   message.alpha = 0;
     return true;
  }
  else
  {
   foreach (o in fe.obj)
     o.alpha = 255;
    message.alpha = 0;
  }
  break;
     
 case Transition.ToGame:
  if ( ttime < 255 )
  {
   foreach (o in fe.obj)
    o.alpha = 255 - ttime;
    message.alpha = ttime;
    return true;
  }   
  break;
 }
 return false;
}
 
   
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: verion on June 17, 2015, 09:24:02 AM
@ omegaman

Quote
Why don't you test it with roboskin?

I've actually done exactly that. I've upscaled and cleaned up cab image in 4xHD resolution (2x 1080p in height). And it scales up as good as scales down - beautifully. It is because you've designed and coded it resolution independent.

But I'm using it in 4:3 window, because in 16:10 aspect it looks too stretched. I'll convert it to 16:9/10, but for now I'm keeping it 4:3, so you can use my graphics after we sort out that pinching, skewing quirks.

Actually this makes me think if really universal (4:3 / 16:9) layout is possible - the one that looks good in both aspects. Because even if robospin would scale like responsive website - that would leave too much empty space in the middle.
On the mockup above - I'm simply cheating: making cab and wheel bigger and cutting the bottom for 16:9 layout. So it's not that automatic - it still needs separate "designs" for different layouts.
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: liquid8d on June 17, 2015, 09:36:30 AM
Without reading them in detailed atm, looks like you are both multiplying based on the aspect, right? My concern there is you might not always want an object to be the same fixed scale for one aspect as you do another. Of course, you could do an if/else or something, but again you are going to be searching all through your code to change things.

Scaling up or down is nice, but if you are using the same values you multiply the aspect by, things are still being "stretched" on different aspects, right? That's another reason why I suggested fixed settings for different aspects, but having a 'default' that it falls back on. The default value could be aspect * defaultvalue, but then if you wanted you could specify different values for other aspects / resolutions.

Code: [Select]
SETTINGS <- {
    //every setting MUST be defined in default (this will be the fallback value)
    "default": {
        "width": 640,
        "height": 480,
        "logo": { src = ResourcePath("bg.png"), x = 0, y = 0, width = aspect * 1.0, height = aspect * 1.0 },
        "title": { x = 0, y = aspect * 0.02, width = aspect * 1.0, height = aspect * 0.1 },
        "fontName": "Arial",
        "animate_wheel": false
    },
    //aspect-resolution specific values can be added for each
    "720p": {
        "width": 1280,
        "height": 720,
        "title": { x = 0, y = 0, width = 1280, height = 30 },
        "animate_wheel": true
    },
    "1080p": {
        "width": 1920,
        "height": 1080
    }
}
local title = fe.add_text( "[Title]", Setting.title.x, Setting.title.y, Setting.title.width, Setting.title.height );

If you use this, all your values are in one spot and the add_text is not very confusing because it's just whatever value is in Settings. Plus this would allow you to automatically pull resources from a ResourcePath("4x3/bg.png") for aspect specific resources. You can have a nice wide bg for widescreen and a fitting standard aspect for 4:3.

Again, a lot of this is personal preference. I think it will save a lot of headache when you want to adjust the look of the theme if you have all your settings in one spot. It would allow users to go in and adjust to their liking and you could easily make variations with a multiple settings tables, using the correct values based on a config option.
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: omegaman on June 17, 2015, 10:13:08 AM
Liquid-

I do like your idea of having a fallback value. Definitely, makes the code easier to read and make changes on the fly.
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: liquid8d on June 17, 2015, 10:53:05 AM
Think I got something really sweet almost worked out :) Try to have an initial version ready sometime today.
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: Luke_Nukem on June 17, 2015, 01:40:31 PM
Nope. It doesn't fix that.

Turns out I didn't push my latest changes upstream. Should be fixed now I think.
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: Luke_Nukem on June 17, 2015, 01:44:28 PM
Without reading them in detailed atm, looks like you are both multiplying based on the aspect, right? My concern there is you might not always want an object to be the same fixed scale for one aspect as you do another. Of course, you could do an if/else or something, but again you are going to be searching all through your code to change things.

Scaling up or down is nice, but if you are using the same values you multiply the aspect by, things are still being "stretched" on different aspects, right? That's another reason why I suggested fixed settings for different aspects, but having a 'default' that it falls back on. The default value could be aspect * defaultvalue, but then if you wanted you could specify different values for other aspects / resolutions.

This is the exact reason I've done the rotating_new layout the way I have. It should be completely resolution and aspect independent now.
You can quickly test it by inserting something like;
Code: [Select]
fe.layout.width = 1024;
fe.layout.height = 768;
In the layout near the top.

The only problem I can see that might possibly pop up is if someone is using a rotated windows desktop. But hopefully this is nearly nobody.
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: Luke_Nukem on June 17, 2015, 01:49:34 PM
Luke-

My newer layouts already scale based on the base resolution the layout was designed for. The only thing I see that you are doing differently - and, forgive my ignorance on this, is you are creating a function for the math and calling other .nuts with the pixel position based on the BG. That and you can switch from horizontal to vertical which is nice. But, will this code scale much better than what I'm doing below. This is more for learning than a critique.     


Man, you have got to use pastebin.com or github, or the /code tags. Code in forums does not work well.
The main difference, and probably the biggest difference, is that by making all my object placements depend on the *.png overlay art, they will scale correctly to the correct places on that piece of art (hopefully now, every time.)

It also occurs to me that perhaps rendering everything on to a base surface, and scaling just that surface could work just as well.

PS: I also like to try and *modularise* my code where possible. It helps with reading, compartmentalising , and also has the added bonus of being easy to debug and easy to reuse.
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: liquid8d on June 17, 2015, 02:13:37 PM
Luke,

Here's a quick version of what I'm talking about just for your wheel.nut.. but I would do settings across the board in one spot and for different aspects:

Code: [Select]
local s = {
    "message": { x = 0, y = 0, w = fe.layout.width, h = 80, alpha = 0, style = Style.Bold }
    "wheel": {
        "horizontal": { x = 1.83, y = 7.5, w = 2.46, h = 6.72 }
        "vertical": { x = 7.16, y = 21.3, w = 1.36, h = 5.25 }
    }
}

local message = fe.add_text("LOADING",s.message.x,s.message.y,s.message.w,s.message.h);
message.alpha = s.message.alpha;
message.style = s.message.style;

local wheel = fe.add_artwork(wheelArt, 0, 0);

function wheelUpdate( rotation )
{
    // Set wheel size.
    wheel.width = overlay_horz.width / s.wheel[rotation].w ;
    wheel.height = overlay_horz.height / s.wheel[rotation].h;
    // This keeps the original ratio
    //if (wheel.texture_height != 0 && wheel.texture_width != 0)
    //{
    //    wheel.width = (wheel.height * (wheel.texture_height / wheel.texture_width));
    //}           
    wheel.x = overlay_horz.x + (overlay_horz.width / s.wheel[rotation].x);
    wheel.y = overlay_horz.y + (overlay_horz.height / s.wheel[rotation].y);
   
    wheel.shader = titleShader;
}


function wheelFresh( ttype, var, ttime )
{
    local actual_rotation = (fe.layout.base_rotation + fe.layout.toggle_rotation)%4;   
    if (ttype == Transition.ToNewSelection || Transition.FromOldSelection)
    {
        if (( actual_rotation == RotateScreen.Left ) || ( actual_rotation == RotateScreen.Right ))
        {
            wheelUpdate("vertical");
        }
        else
        {
            wheelUpdate("horizontal");
        }
    }
    return false;
}
fe.add_transition_callback( "wheelFresh" );

Now you could make future changes to adjust the message or wheel size and position without hunting code. And the way I'm working on, those would be the defaults, but you'd also be able to have aspect or resolution specific settings. Even better, I'm doing it where you can have multiple 'skins', so you could have one that has the wheel on the left or right, one that has the wheel on the top or bottom, etc..
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: Luke_Nukem on June 17, 2015, 02:26:05 PM
Luke,

Here's a quick version of what I'm talking about just for your wheel.nut.. but I would do settings across the board in one spot and for different aspects:
** snip **
Now you could make future changes to adjust the message or wheel size and position without hunting code. And the way I'm working on, those would be the defaults, but you'd also be able to have aspect or resolution specific settings. Even better, I'm doing it where you can have multiple 'skins', so you could have one that has the wheel on the left or right, one that has the wheel on the top or bottom, etc..

I did think about doing that. But I'm not about to start making different skins etc, to me it makes more sense to just use different layouts instead of trying to lump everything into one layout. That would make it easier to manage settings and so on too, especially for multiple emu/lists. I could see the convenience of using tables (They get called dictionaries in Python. Was hard to switch to Squirrel after 6 months of studying that), but they just didn't make any sense to me to use in what I was doing, as all objects are specific to the overlay graphic in use.
If I thought I was going to be code hunting, then yeah, tables/dictionaries would be used, but since I split everything into their own scripts, it's just a piece of cake to modify stuff (and reuse code).

The one drawback with doing so much stuff in script, is settings management.
For example you have 3 lists, and you use the one layout for each list, change a setting in the layout for one list and it affects all 3 lists. I suppose you could just make multiple copies of the layout...

***Lastly, I just trialled my code with a large background png, it scales up and down beautifully!
Setting the height to fe height (for horizontal) or width to fe height (for vertical), and scaling the image by using a ratio calculated from its base size, is the magic that does that. Then setting object placements by using the background image works perfectly every time.

EDIT::
On second thoughts. Using tables/dicts enables use of *generic* functions in some cases (but not all), and this appeals to my minimalist nature. (Thanks for pointing them out again. I'd grown to dislike them due to the data management stuff I had to do at Uni).
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: liquid8d on June 17, 2015, 04:15:10 PM
I see what you mean... what if you could just do this?

Code: [Select]
//My Settings
Skin.store( "msg_x", 0 );
Skin.store( "msg_y", 0 );
Skin.store( "msg_w", 500);
Skin.store( "msg_h", 30 );

//My Objects
local message = fe.add_text("LOADING", Skin.msg_x, Skin.msg_y, Skin.msg_w, Skin.msg_h );

Storing the variables in tables can be done in the module, it can be made very easy for the layout dev.. in fact, that's what I already do with the animate module.

As far as 'skins', you wouldn't have to have more than the main one. Although they could be completely different layouts in one, usually it would used for the same layout but some altered resources or location/sizes for each skin.

Code: [Select]
Settings.add( "Skin 1", "bg_src", "bg1.png" );
Settings.add( "Skin 2", "bg_src", "bg2.png" );

//Skin is a reference to whatever skin option the user has chosen in Layout Options
//no need for if ( config["skin"] == "Skin 1") add this, else add this
local bg = fe.add_image( Skin.bg_src, Skin.bg_x, Skin.bg_y, Skin.bg_w, Skin.bg_h );

You can certainly just create a copy of a layout, make the minor change. But if you plan on updating that layout in the future, any code changes have to be kept in sync across them all.
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: Luke_Nukem on June 17, 2015, 04:23:52 PM
That could work I guess. Though I'm going to leave settings management for another day.

My main focus at the moment is making as generic as possible, a rotating and scaling layout. That part is done, so now I just need to finish off including aspect ratios.
So far the biggest problem I've got is it isn't easy to pass an object reference to a function. I still have to rely on the clunky if/else (this == "string") { } and so on.

Unless I've completely missed something....?


I'm really wishing we had Python instead of squirrel now, I'm much more familiar with that. Sod it, I'm going to start using class based programming for layouts. It's a hell of a lot easier to manage.
As for copying layouts. I was meaning more for the end user. Not for settings in actual script, but for any that we write out.
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: liquid8d on June 17, 2015, 04:35:07 PM
So far the biggest problem I've got is it isn't easy to pass an object reference to a function. I still have to rely on the clunky if/else (this == "string") { } and so on.

I'm really wishing we had Python instead of squirrel now, then I could use class based programming and just parse in a config file for each layout/rotation/aspect straight into a nice tidy array.

Squirrel supports classes..
https://electricimp.com/docs/squirrel/squirrelcrib/#crib_objects

As for object references - I *think* sending objects to functions is a reference? I hope so because I do a lot of it. Classes (and Arrays) in the script are converted to a table, so I think it just uses a reference to the table.


Couple thoughts/questions..

I don't full comprehend what is wanted here with here for aspect vs. resolutions. Do we only care about aspect - and if so what is the proper fallback order: 16:10 -> 16:9 -> 4:3? If we care about resolutions, which resolutions are which aspect and are there "odd" aspects out there that we do care about? Obviously I can look these up, just curious on everyone's thoughts.

With regards to rotation, can that just be categorized as a reverse aspect - i.e. 3:4? If the Rotation option in AM rotates the layout - and rotation is just the reverse width/height, what are you accomplishing with your version? I don't deal with that much right now, since I don't use vertical layouts.

AM already stretches your layout automatically to whatever resolution the user has. Would we like to be able to "fit" a 4x3 layout, into 16:9 (it would scale to match height and fit in the center)? Or just stretch, but use aspect specific resources?
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: Luke_Nukem on June 17, 2015, 05:24:26 PM
liquid8d. Just been browsing through the SQ reference, saw the classes. Everything seems similar to Python in some ways.

Do you know off the top of your head if something like;
Code: [Select]
bg_object = fe.add_image(blaaaah);
function test(thisobj)
{
   if (thisobj == bg_object)
   {
       bg_object.x = 666;
       **more stuff;
   }
}
test(bg_object);
Will work? Because I've been trying variations on that theme for a few hours now, and it doesn't seem to pass references, and I can't see any documentation that suggests it happens.

You pretty much got it in one. I've done my layouts that way to prevent the stretching of the layout. Using the same code, I can include 16:9 and 16:10 layouts in the same, and switch to the correct one depending on AM's starting res. And if it's built for only 4:3, then it won't stretch to ugly proportions on a 16:9 or 16:10.

That's my own goal. Along with sharing all that I do, hence the reason I'm not bothering with much extraneous stuff atm.

Going by the work I did at Uni, using a class based setup, combined with being modularised, should achieve the goal of being universal.
So what I intend to do is make a very small set of functions that take a set of parameters like object x,y,w,h,  and returns new x,y,w,h based on the fe.layout dimensions and aspect of the chosen reference size (which could be an image, surface, or just a tuple).
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: Luke_Nukem on June 17, 2015, 06:07:50 PM
This is an example of the way i would do it;

Code: [Select]
// Use to create objects for each res/aspect
// by passing in required x,y,w,d and a
// reference for resolution such as art/surface.
class MarqueeArt
{
    constructor(orientation, aspect,x,y,w,h,refRes)
    {
        descriptor = "MarqueeArt";
        art = fe.add_artwork( wheelArt, 0, 0);
        orientation = orientation;  // Should be labels only
        aspect = aspect;            // and used to determine
        x = x;                      // which obj to update
        y = y;
        w = w;
        h = h;
        refRes = refRes; // Should probably be a global?
        visible = true;
    }
    update()
    {
        art.x = refRes.x + (refRes.width / (x / refRes.width));
        art.y = refRes.y + (refRes.height / (y / refRes.height));
        art.width = refRes.width / (w / refRes.width);
        art.height = refRes.height / (h / refRes.width);
    }
    setVisible(flag)
    {
        if (flag == true) { art.alpha = 255; }
        else if flag == false; { art.alpha = 0; }
    }
}
//////
function updateMarqueeArt(orientation, aspect)
{
    foreach (obj in objectList)
    {
        if (obj.orientation == orientation
              && obj.aspect == aspect)
        {
            obj.update();
            obj.setVisible(true);
        }
        else
        {
            obj.setVisible(false);
        }
    }
}

So for each orientation and aspect, just create a new object from the class by using the input parameters, and store that object in a global objectList.
When it comes time to switching to a new orientation or aspect, you would pass those details to the update function, and it would then update those objects only, and set all others to be invisible.

I haven't tried that code yet as I'm still conceptualising it all. But it's really feeling like the correct way to do it, makes it much more dynamic and data driven.

Thoughts?
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: liquid8d on June 17, 2015, 06:26:33 PM
I'm not sure in what scenario you are using it in that it doesn't, but it worked for me. thisobj = obj is comparing instances of the object. If yours isn't working, it seems like the instance you are passing to the function is not the same object instance?

I did this:
Code: [Select]
local bg = fe.add_image( Skin.bg.src, Skin.bg.x, Skin.bg.y, Skin.bg.width, Skin.bg.height );

function doit( obj )
{
   print( "obj: " + obj + "\n" );
   print( "bg: " + bg + "\n" );
   if ( obj == bg ) print( "match!" );
}

doit(bg);


and got this:
Code: [Select]
obj: (instance : 0x000000000443B1D0)
bg: (instance : 0x000000000443B1D0)
match!

However, I'm not sure on the scope when you do it from a class. I do similar stuff to what you are talking about in my animate module and what I was doing with extended objects..

AnimationCore + Animation classes (which are my base classes):
https://github.com/liquid8d/attract-extra/blob/master/modules/animate.nut

PropertyAnimation,SpriteAnimation and ParticleAnimations (which are my extended classes):
https://github.com/liquid8d/attract-extra/tree/master/modules/animate

This one might be better for you. I've suspended work because it got a bit complex and I'm focusing on animate right now, but ExtendedObjects (both base + extended classes in there) did mostly what you are talking about:
https://github.com/liquid8d/attract-extra/blob/master/modules/extended/extended.nut

I might have a bit much in there, but you'll be able to see how the classes work compared to python. I've found there is some advantages of tables vs. classes, but I'll let you decide on that :) A quick thing though about classes - make sure you set any variables to null and initialize them in the constructor unless you want them shared across instances of the same class:

Code: [Select]
class MyClass
{
   sharedArray = [ "One", "Two" ];
   instanceArray = null;
   constructor( x, y )
   {
      instanceArray = [ "InstanceOne", "InstanceTwo" ];
   }
}

I think that may only apply to arrays, tables or other class instances, but I can't remember at the moment..
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: Luke_Nukem on June 17, 2015, 09:22:01 PM
Wow... This. had. me. SWEARING LIKE FUCK!!!

(overlay_vert.width * (overlay_vert.texture_height / overlay_vert.texture_width))

is... NOT EQUAL TO;

(overlay_vert.width * overlay_vert.texture_height / overlay_vert.texture_width)

The first one output only the very first variable. It DOESN'T do the division first. Or anything in parentheses AT ALL!!!!! (But, (x*y) - (g/i) does work).
Just have to rely on operator precedence.. Fuck me.. I was bashing my head over this for a good half hour. I can finally fix that damned layout to display on 4:3 properly, only problem is it reverts back to stretched on 16:9 or 16:10. So i'll just have to hurry up and finish the graphics that will be used for resolution, umm... resolution. Reference!

Why was I writing my code like that? Habit born from making code easier to read at a glance.

edit:
Okay, update. It's nested ( x * ( g * h) ) that is the problem. Which is really fucking stupid.
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: liquid8d on June 17, 2015, 10:01:45 PM
I haven't had any operator precedence issues that I can think of. So if everything is in parenthesis it's calculating from left to right? I suck at math, I was smashing my head when converting some of the animate equations... :)
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: Luke_Nukem on June 17, 2015, 10:15:45 PM
I haven't had any operator precedence issues that I can think of. So if everything is in parenthesis it's calculating from left to right? I suck at math, I was smashing my head when converting some of the animate equations... :)

try this;
Code: [Select]
local x = 1027/(640/250);
print(x);
It should return 401.17. But instead it spits out 513. So NONE of the calculations I've been doing are any fucking good...

EDIT:
Oh hell no... 640/250 = 2 in SQ, and 2.56 on my calculator. There's the problem, floating point calculation. This is seriously stupid shit.
Solution is to write every single number as a float, so x = 1024.0, y = 666.6
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: liquid8d on June 17, 2015, 11:01:31 PM
Doh! I didn't think about the float value, but when you are operating with all integers,  it will return an integer. I think this is typical in languages where you don't declare variables types. I thought that's how it works in python too.

Your previous example:
local x = 1027/(640/250);

That's doing 640/250 which results in 2.56 (but it will get an integer, so you only get 2 ). 1027/2 is 513.2 but you'll only get 513.

You only need one number to be a float on your variable though.. and you can use .tofloat() on it. Try:

Code: [Select]
(overlay_vert.width * overlay_vert.texture_height / overlay_vert.texture_width.tofloat())

I can't remember but it might need to be one of the division numbers to force the division result to be a float, then the multiplication will get you a float.
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: Luke_Nukem on June 18, 2015, 12:00:14 AM
Na it's not like that in Python. In fact Python is a seriously bloody good, logical language. I might even have a look at converting AM to Python at some point.
Operations of this sort in Python will always give you a float, unless you do something like
Code: [Select]
x = int(1024/(640/26)Which will give you 41.6, truncated to 41. The calculation will always be done in floating point precision.

The way Squirrel does it? Is just bloody stupid. Far too prone to errors like what I just had. And you know what? I couldn't find a damn single bit of information on this problem.

In the end it's just easier to type all my numbers with as 1024.0, 256.0 512.0 etc..
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: liquid8d on June 18, 2015, 04:23:30 AM
I don't have anything against Python... they changed it in 3:

Code: [Select]
Python 2.7.6 (default, Nov 10 2013, 19:24:24) [MSC v.1500 64 bit (AMD64)] on win
32
Type "help", "copyright", "credits" or "license" for more information.
>>> print  5 * (2 / 5)
0
>>> print  5.0 * (2 / 5)
0.0
>>> print  5 * (2.0 / 5)
2.0
>>>

Code: [Select]
C:\Python34>python
Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:43:06) [MSC v.1600 32 bit (In
tel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> print ( 5 * ( 2 / 5 ) )
2.0
>>>

Supposedly, you could use // to force float, but that didnt't work for me in 2.7.6
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: Luke_Nukem on June 18, 2015, 01:37:05 PM
I don't know why anyone would want to continue using Python v2.7. It's old, it's clunky, it's also getting support dropped soon. v3.x is fantastic, and has a hell of a lot of very good improvements.

///
I'll see if I can attempt a good description of the framework I've come up with. My proof of concept is working extremely well so far.
///

Each object is instantiated by a class. There are two main types of objects; backgrounds, and "everything else".

When each object is created,  it is created with parameters.
Starting with backgrounds, "ID, art, orientation, aspect".
All others are created with "ID, orientation, aspect, x, y, w, h, reference Res", and a slight variation on that for text.

The "other" objects are linked to the background they were set up with, via sharing the same ID, and also being passed the resolution they were originally set up in. (Now, the reason for passing the res, is so it can be floating point. I'd prefer to just grab the bg.art.texture_width etc, but it's been too unreliable if all numbers end up being ints. Besides, this way allows you to scale the BG up later if everything is retaining the same placements)

All objects are appended to a global object list.

Each "tick", the object list is iterated through, an the objects update function called, but only if it matches the current aspect + orientation, otherwise the obj.update is skipped and set invisible.

So using the module I'm developing to grab the aspect ratio, combined with orientation and auto object linking, I can easily create a layout that caters for the 6 different use cases.
I'll eventually chunk the object setups into separate config files, so that all that needs to be done is just design the layout graphics, stick the object types and coords/dimensions/links in a config, and let my scripts do the work.

This will be good mostly only for simple layouts that use existing stock AM features.
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: Luke_Nukem on June 18, 2015, 02:06:36 PM
Quite seriously, the difference between;
Code: [Select]
(art.height * art.texture_width / art.texture_height)and
Code: [Select]
(art.height * (art.texture_width / art.texture_height));is really starting to piss me off.

Lets say that equates to 1080 * (1920 / 1080)
That returns 1920 right?
The form using nested ( ) returns 1080 because (1920/1080) = 1.77.
AND
The operator precedence is fucked! division should always be done before multiplication, so the entire equation is fucked and no good for anything.

The only solution is to use something like;
Code: [Select]
(art.height * (art.texture_width * 1.0 / art.texture_height));This is not acceptable for a language used by computers.

Test code::
Code: [Select]
local x = 1080*(1920/1080);
print("1080*(1920/1080) = "+x+"\n");
x = 1080 * 1920 / 1080;
print("1080 * 1920 / 1080 = "+x+"\n");
x = 1080*(1920*1.0/1080);
print("1080*(1920*1.0/1080 = "+x+"\n");
x = 1920*1.0/1080;
print("1920*1.0/1080 = "+x+"\n");
x = 1920/1080;
print("1920/1080 = "+x+"\n");
x = 1080*x;
print("x*1080 = "+x+"\n");
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: verion on June 18, 2015, 04:19:23 PM
Since I can’t help you guys with coding - I’ve designed simple layout to show how aspect-aware layout could look in practice.

See separate thread:
http://forum.attractmode.org/index.php?topic=277.0
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: Luke_Nukem on June 18, 2015, 09:14:33 PM
Here's a quick demo of what I've done. http://youtu.be/KkYFcZ3IygY (http://youtu.be/KkYFcZ3IygY).

Mind the shitty programmer graphics.  :P

(Videos playing will come soon. As I'm trying to do a universal class for it where there's only one instance of the video, but multiple settings to switch through).

Eventually I will make this one big universal class, to be used with just basic layouts consisting of only the main elements, such as video, screens, listbox, text, and perhaps sounds. Plus a way to load in from a single setting file per aspect+orientation.
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: liquid8d on June 18, 2015, 09:57:24 PM
Code: [Select]
local x = 1080*(1920/1080);
print("1080*(1920/1080) = "+x+"\n");
x = 1080 * 1920 / 1080;
print("1080 * 1920 / 1080 = "+x+"\n");
x = 1080*(1920*1.0/1080);
print("1080*(1920*1.0/1080 = "+x+"\n");
x = 1920*1.0/1080;
print("1920*1.0/1080 = "+x+"\n");
x = 1920/1080;
print("1920/1080 = "+x+"\n");
x = 1080*x;
print("x*1080 = "+x+"\n");

All of those results are correct, based on where your parenthesis are and the fact that using integers with no float will result in an integer value.

Division doesn't happen before multiplication, unless parenthesis alters it - they have the same rank and order is left to right in the equation in PEMDAS.

Code: [Select]
1080*(1920/1080) = 1080     (parenthesis first - and without a float, 1920/1080 = 1 - INTEGER )
1080 * 1920 / 1080 = 1920   (left to right - multiply, then divide - this is correct and different from above because all numbers and result are INTEGER)
1080*(1920*1.0/1080) = 1920  (parens first, left to right - multiply, then divide, then multiply by 1080)
1920*1.0/1080 = 1.77778     ( left to right, multiply (you get a FLOAT), then divide - result is a FLOAT
1920/1080 = 1               ( because dividing two integers results in an INTEGER, unless you force one to a float
x*1080 = 1080               ( just 1080, because the last x was 1 )

When you are dividing, just use .tofloat() on the value you are dividing by and you should get the numbers you expected.
Title: Re: Discussion of creating Aspect-Aware Layouts
Post by: Luke_Nukem on June 18, 2015, 10:47:10 PM
Yes I know the results are correct. But I also believe that when you are working with any computer language, you should be defaulted to floats, unless explicitly specifying integers.
In C/C++ when you do calculations with any variable specified as an int, then you get the results expected, because you declare your types etc.

But when it comes to a typeless language, it should definitely always default to floats, unless specified. The only time I've every really used a form of integer only calculation, is with the modulus operator. And that's in C/C++, Python, and Squirrel (Even Ruby + PHP, I've used all of these languages).

Imagine if a standard calculator defaulted everything to integers only...

Do you know how long it took me to find the "tointeger()" and "tofloat()" functions? Try searching "typecast", or "type cast" in the official reference. You won't get a single result.

And I've *always* gone by PEDMAS, not PEMDAS. But either are equivalent, and produce the same results. Man, this whole default to integer thing seriously messed with my head, trying to figure out why things were going batshit. (See this for why I am frustrated Link (https://robbinshomeschool.wordpress.com/2013/10/08/bedmas-vs-pemdas-again/)

Until Squirrel defaults to floats, it's much safer to write all numbers as xxx.0, that reduces the chances of an error due to a misplaced "tofloat()" to next to nil.