Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - rand0m

Pages: [1] 2 3 ... 14
1
Does the PreserveArt module have a way to set trigger to Transition.EndNavigation?

I thought about implementing something similar myself, so I can have things positioned on the same axis. We now have fe.Image parameters pertaining to texture, subimg, and origin. I don’t really understand what they are. Can anyone give me a rundown of them?

liquid8d helped me out with this one, it required some modifications in the module file. The modified version is as follows (modifications are near the end):
Code: [Select]
/////////////////////////////////////////////////////////
//
// Attract-Mode Frontend - PreserveArt/PreserveImage Module
//
/////////////////////////////////////////////////////////
// PreserveArt - creates a surface with artwork that will fit or fill the specified dimensions.
// This preserves art aspect ratio, but gives option to anchor the art to one side of its dimensions.
//
// "fit" will ensure the entire artwork fits within the surface dimensions, then anchor to the specified side.
// "fill" will keep art aspect ratio, and anchor the art to the specified side.
//
// Usage:
// local img = PreserveImage( "bg.png", 0, 0, 640, 360 );
// img.set_fit_or_fill( "fill" );
// img.set_anchor( ::Anchor.Top );
//
// local art = PreserveArt( "snap", 0, 0, 320, 240 );
// art.set_fit_or_fill( "fit" );  // fit, fill or stretch
// art.set_anchor( ::Anchor.Bottom ); // Top, Left, Center, Centre, Right, Bottom
//

::Anchor <-
{
    Top = "Top",
    Left = "Left",
    Centre = "Center",
    Center = "Center",
    Right = "Right",
    Bottom = "Bottom",
}

class PreserveArt
{
    VERSION = 1.0;
    debug = false;
    surface = null;
    art = null;
    isArt = true;
    anchor = ::Anchor.Center;
    fit_or_fill = "fit";
    request_size = true;
   
    constructor( name, x, y, w, h, parent = ::fe )
    {
        surface = parent.add_surface( w, h );
        surface.x = x;
        surface.y = y;
        if ( debug ) surface.add_image( ::fe.script_dir + "pixel.png", 0, 0, surface.width, surface.height );
        art = ( isArt ) ? surface.add_artwork( name, 0, 0, w, h ) : surface.add_image( name, 0, 0, w, h );
        ::fe.add_transition_callback( this, "onTransition" );
        ::fe.add_ticks_callback( this, "onTick" );
    }
   
    function set_anchor( a )
    {
        anchor = a;
        request_size = true;
    }
    function set_fit_or_fill( f )
    {
        fit_or_fill = f;
        request_size = true;
    }
   
    function update()
    {
        if ( art.texture_width != 0 && art.texture_height != 0 )
        {
            request_size = false;
            local aspect = surface.width / surface.height.tofloat();
            local texture_aspect = art.texture_width / art.texture_height.tofloat();
           
            if ( fit_or_fill == "fit" )
            {
                if ( aspect > 1.0 )
                {
                    //wide
                    if ( texture_aspect > 1.0 )
                    {
                        print("wide, wide, fit");
                        art.width = surface.width;
                        art.height = art.width / texture_aspect;
                        if ( art.height > surface.height )
                        {
                            //reverse
                            art.height = surface.height;
                            art.width = art.height * texture_aspect;
                        }
                    } else
                    {
                        print("wide, tall, fit");
                        art.height = surface.height;
                        art.width = art.height * texture_aspect;
                        if ( art.width > surface.width )
                        {
                            //reverse
                            art.width = surface.width;
                            art.height = art.width / texture_aspect;
                        }
                    }
                } else
                {
                    //tall
                    if ( texture_aspect > 1.0 )
                    {
                        print("tall, wide, fit");
                        art.width = surface.width;
                        art.height = art.width / texture_aspect;
                        if ( art.height > surface.height )
                        {
                            //reverse
                            art.height = surface.height;
                            art.width = art.height * texture_aspect;
                        }
                    } else
                    {
                        print("tall, tall, fit");
                        art.height = surface.height;
                        art.width = art.height * texture_aspect;
                        if ( art.width > surface.width )
                        {
                            //reverse
                            art.width = surface.width;
                            art.height = art.width / texture_aspect;
                        }
                    }
                }
            } else if ( fit_or_fill == "fill" )
            {
                if ( aspect > 1.0 )
                {
                    //wide
                    if ( texture_aspect > 1.0 )
                    {
                        print("wide, wide, fill");
                        art.height = surface.height;
                        art.width = art.height * texture_aspect;
                        if ( art.width < surface.width )
                        {
                            //reverse
                            art.width = surface.width;
                            art.height = art.width / texture_aspect;
                        }
                    } else
                    {
                        print("wide, tall, fill");
                        art.width = surface.width;
                        art.height = art.width / texture_aspect;
                        if ( art.height < surface.height )
                        {
                            //reverse
                            art.height = surface.height;
                            art.width = art.height * texture_aspect;
                        }
                    }
                } else
                {
                    //tall
                    if ( texture_aspect > 1.0 )
                    {
                        print("tall, wide, fill");
                        art.width = surface.width;
                        art.height = art.width / texture_aspect;
                        if ( art.height < surface.height )
                        {
                            art.height = surface.height;
                            art.width = art.height * texture_aspect;
                        }
                    } else
                    {
                        print("tall, tall, fill");
                        art.height = surface.height;
                        art.width = art.height * texture_aspect;
                        if ( art.width < surface.width )
                        {
                            art.width = surface.width;
                            art.height = art.width / texture_aspect;
                        }
                    }
                }
            } else
            {
                //stretch
                art.preserve_aspect_ratio = false;
                art.width = surface.width;
                art.height = surface.height;           
            }
           
            switch ( anchor )
            {
                case ::Anchor.Left:
                    art.x = 0;
                    art.y = ( surface.height - art.height ) / 2;
                    break;
                case ::Anchor.Right:
                    art.x = surface.width - art.width;
                    art.y = ( surface.height - art.height ) / 2;
                    break;
                case ::Anchor.Top:
                    art.x = ( surface.width - art.width ) / 2;
                    art.y = 0;
                    break;
                case ::Anchor.Bottom:
                    art.x = ( surface.width - art.width ) / 2;
                    art.y = surface.height - art.height;
                    break;
                case ::Anchor.Center:
                default:
                    art.x = ( surface.width - art.width ) / 2;
                    art.y = ( surface.height - art.height ) / 2;
                    break;
            }
        } else
        {
            //fallback to preserve_aspect_ratio
            print("WARNING: FALLBACK TO PRESERVE_ASPECT_RATIO" );
            art.x = 0;
            art.y = 0;
            art.width = surface.width;
            art.height = surface.height;
            art.preserve_aspect_ratio = true;
        }
    }
   
    function _get( idx ) { return surface[idx]; }
// modified function to directly call trigger.EndNavigation, code by "liquid8d"
    function _set( idx, val )
    {
        if ( idx == "index_offset" ) art.index_offset = val; else if ( idx == "filter_offset" ) art.filter_offset = val; else if ( idx == "file_name" ) art.file_name = val; else if ( idx == "trigger" ) art.trigger = val; else surface[idx] = val;
    }
    function print( msg )
    {
        if ( debug ) ::print("PreserveArt: " + msg + "\n" );
    }
   
    function set_rgb( r, g, b ) { surface.set_rgb( r, g, b );
}
   
//Function added to support trigger.EndNavigation, code by "liquid8d"
function onTransition( ttype, var, ttime )
    {
if ( ttype == art.trigger ) request_size = true;
//        if ( ttype == Transition.StartLayout || ttype == Transition.ToNewList || ttype == Transition.FromOldSelection ) request_size = true;
    }
   
    function onTick( ttime )
    {
        if ( request_size && art.texture_width != 0 && art.texture_height != 0 ) update();
    }
}

class PreserveImage extends PreserveArt
{
    isArt = false;
}

Code being utilized in layout is:
Code: [Select]
local flyer = PreserveArt( "flyer", 691, 95, 802, 575 );
flyer.trigger = Transition.EndNavigation;
flyer.set_anchor( ::Anchor.Left );
flyer.preserve_aspect_ratio = true;
flyer.mipmap = true;

2
Themes / Re: PICKnMIX - unibios neogeo inspired layout
« on: May 07, 2019, 11:44:37 PM »
Great Job Keil!

3
Themes / Re: Chicuelo Mix Theme Release (v1.1.1)
« on: May 07, 2019, 11:32:22 PM »
Hi rand0m and thank you so much for reply and all the hints. Will start doing more tests. :) 

In this print from a few days ago I added art and info for PC games and opted to take out the bottom info at the time until a better solution arrived, in this case your hints and instructions. Can't wait to test it and share some results. It really looks so nice and clean the theme, really love it. :)

PS: I'm noticing something peculiar when I use Chicuelo prominently. The display menu stops remembering the last system selected when you quit AM and most times it chooses a random system when I go back to AM. Maybe just a coincidence? Is there a way in AM to reset display menu memory just in case for testing?

This happened to me too after I added collections and custom favorites. Its just a hunch but I think if an item is listed in multiple places AM exhibits this behavior (not returning to parent folder).

4
Themes / Re: Chicuelo Mix Theme Release (v1.1.1)
« on: May 03, 2019, 12:54:54 PM »
1. Two-tier menu is possible but you will have to manually add that info in layout since AM won't be able to grab that info from Arcades/Computers etc romlists. The top info panel, lets call it headline can be added similarly to how platform menu items operate in main layout i.e.

Code: [Select]
//Headlines
function headlines()
{
if (fe.game_info( Info.Title ) == "Arcades") return "COIN OPERATED CABINETS";
else if (fe.game_info( Info.Title ) == "Computers") return "COMPUTER SYSTEMS";
else if (fe.game_info( Info.Title ) == "Consoles") return "CONSOLE SYSTEMS";
else if (fe.game_info( Info.Title ) == "Handhelds") return "HANDHELD SYSTEMS";
else if (fe.game_info( Info.Title ) == "Favorites") return "FAVORITE GAMES";
else if( fe.game_info( Info.Title ) == "Collections") return "CUSTOM COLLECTIONS";
else if (fe.game_info( Info.Title ) == "Exit Attract-Mode") return "SHUT-DOWN MENU";
else if (fe.game_info( Info.Title ) != "Arcades" || "Computers" || "Consoles" || "Handhelds" || "Favorites" || "Collections" || "Exit Attract-Mode" ) return "";
}
local headlines = fe.add_text("[!headlines]", 155, 221, 580, 100);
headlines.font= "Roboto-Medium.ttf";
headlines.align = Align.Centre;
headlines.word_wrap = true;
headlines.charsize = 30;
headlines.set_rgb(129, 129, 129);

Instead of Arcades/ Computers use the "Title" of system directly. e.g. "Arcade (MAME)", "Super Nintendo" and list the System info after "return" like 128 Bit Console etc (you can also add year here, manually).


2- I have not been able to get the "total games in system" to work,  IMHO there is currently no way to get it from AM directly. Perhaps a table with permanent values can be created but that is beyond my skill level. You can manually add "total # of games" in this part of code >

Code: [Select]
function listsize()
{
if (fe.game_info( Info.Title ) == "Arcades") return "[ListSize]" + " Systems" + " Available";
else if (fe.game_info( Info.Title ) == "Computers") return "[ListSize]" + " Systems" + " Available";
else if (fe.game_info( Info.Title ) == "Consoles") return "[ListSize]" + " Systems" + " Available";
else if (fe.game_info( Info.Title ) == "Handhelds") return "[ListSize]" + " Systems" + " Available";
else if (fe.game_info( Info.Title ) == "Favorites") return "[ListSize]" + " Games" + " Available";
else if (fe.game_info( Info.Title ) == "Collections") return "[ListSize]" + " Collections" + " Available";
else if (fe.game_info( Info.Title ) == "Exit Attract-Mode") return "";
else if (fe.game_info( Info.Title ) != "Arcades" || "Computers" || "Consoles" || "Handhelds" || "Favorites" || "Collections" || "Exit Attract-Mode" ) return "[ListSize]" + " Games" + " Available";
}
local listsize = fe.add_text("[!listsize]", 230, 680, 420, 300);
listsize.font= "Roboto-Medium.ttf";
listsize.align = Align.Centre;
listsize.word_wrap = true;
listsize.charsize = 30;
listsize.set_rgb(79, 81, 89);

In place or [ListSize] use actual number e.g. if a System with Title Super Nintendo has 200 roms then:

Code: [Select]
if (fe.game_info( Info.Title ) == "Super Nintendo") return "200" + " Games" + " Available";
Best of luck with your build :D

5
Scripting / Re: module location?
« on: April 17, 2019, 02:34:22 PM »
Im really confused about what you are confused about.

I think Jedione wants the module code as a part of layout.nut (not external) and he is wondering how to call a module (use its function) if its coded into layout.nut. Script won't help if I am correct in my assumption since they are also external.

6
Scripting / Re: module location?
« on: April 17, 2019, 02:33:18 PM »
Im really confused about what you are confused about.

I think Jedione wants the module code as a part of layout.nut (not external) and he is wondering how to call a module (use its function) if its in layout.nut. Script won't help if I am correct in my assumption since they are also external.

7
Themes / Re: Snes Mini Simple - WIP
« on: April 16, 2019, 01:39:55 PM »
Good job and welcome to Am forums!

8
Themes / Re: Chicuelo Mix Theme Release (v1.1.0)
« on: April 15, 2019, 08:03:35 AM »
Chicuelo Mix Complete v1.1.1 (Bug Fix)

Additions

    - Added arrow effect for D-pad, requested by forum member Enkak. Arrow effect on pressing "Up" or "Down" should now work with Keyboard, gamepad stick and gamepad D-pad.

Bug Fixes

    - Made a mistake in layout_games.nut by calling [DisplayName] instead of [DisplayType]. Thanks to Enkak for find the bug.

Link: https://github.com/randombyt/Chicuelo-Mix/releases

Warning Please don't paste this on top of a pre-configured Attract-Mode installation as it will overwrite files. It is mainly for fresh installation of Attract-Mode (which is portable thus you can have any number of installations on single rig) where you paste it on top of Attract-Mode and have everything in order and configured.

If you only want the layout/ theme then "layouts/Chicuelo Mix" contains everything needed by the layout to work so you should paste this folder in "AM/layouts".

9
Themes / Re: Chicuelo Mix Theme Release (v1.1.0)
« on: April 15, 2019, 08:01:18 AM »
I can confirm that it works now with the updated code that you gave, both with d-pad and analog. :)

A quick question: what's the difference between DisplayType and DisplayName?

I ask because in the new version of the theme, in layout_games.nut, for the system logos you have DisplayType in line 55 and noticed that the system logo didn't appear in the frontend. But if I change it to DisplayName the logo appears as it should near the games story.

Cheers and thank you again for all your efforts. :)

TY, released a bug fix version for DisplayType and also added D-Pad support guess it'll come in handy for most of the users.

10
Scripting / Re: advanced progres bar
« on: April 15, 2019, 07:34:38 AM »
This is all good if your list is always sorted by name. If you have filters sorted by different criteria it gets tricky really fast. The magic token [OrderValue] can't be retrieved through fe.game_info, so one has to tweak the "first letter" function to keep track of this, and for years sorting an entirely new list should be used with years and not letters.

[SortName] works if we use it to get text directly but can't get in through game info.

11
Themes / Re: Chicuelo Mix Theme Release (v1.1.0)
« on: April 15, 2019, 07:07:58 AM »
Thank you for the new update. :)

Noticed that arrow blink effect doesn't work if you use the d-pad, only with the analog button.

Thanks, please copy the following code and paste it in place of original (starts at line 45) and check if it works:

Code: [Select]
function tick_up(ttime){
    (fe.get_input_state("Up") || fe.get_input_state("Joy0 Up") || fe.get_input_state("Joy0 PovYpos")) ? image_up.visible = true : image_up.visible = false;
}

function tick_down(ttime){
    (fe.get_input_state("Down") || fe.get_input_state("Joy0 Down") || fe.get_input_state("Joy0 PovYneg")) ? image_down.visible = true : image_down.visible = false;
}

12
Themes / Re: Chicuelo Mix Theme Release (v1.0.0)
« on: April 15, 2019, 02:14:43 AM »
Chicuelo Mix Complete v1.1.0 Released!

    1. Added some new system flyers/ controllers images which were added in original theme by Chicuelo.
    2. Added an indicator bar/ progress bar on left of gamelist.
    3. Arrow blink effect was not working with gamepad input, fixed that.
    4. Tweaked some items on Trigger.EndNavigation for better performance. Couldn't get most text items on End.Navigation as they were derieved from functions and code refused to work with them :D perhaps in next version.

Warning Please don't paste this on top of a pre-configured Attract-Mode installation as it will overwrite files. It is mainly for fresh installation of Attract-Mode (which is portable thus you can have any number of installations on single rig) where you paste it on top of Attract-Mode and have everything in order and configured.

If you only want the layout/ theme then "layouts/Chicuelo Mix" contains everything needed by the layout to work so you paste this folder in "AM/layouts".

Link: https://github.com/randombyt/Chicuelo-Mix/releases

[Note: Kiel's was very helpful in getting the arrow effect to work with both keyboard and gamepad input! TY]

13
Scripting / Re: advanced progres bar
« on: April 14, 2019, 09:20:12 PM »
Here is the code I am using
Code: [Select]
//Indicator Bar
local indicator_bar = fe.add_image( "images/indicator_bar.png", 36, 180, 12,760 );
local indicator_graph = fe.add_image( "images/indicator_graph.png", 38, 180, 8, 760 );
local indicator_position = fe.add_image( "images/circle.png", 20, 0, 42, 42 );

Indicator_bar is the outline in red color, indicator_graph is the red filler, its a pixel 1x1 and indicator_position is the circle where first alphabet of title is displayed.

Code: [Select]
//Get First Letter of Title and Adjust Non-Alphabetical Chars
function first_letter ()
{
local first_char = rstrip(fe.game_info(Info.Title)).slice(0,1);
local expression = regexp("[a-zA-Z]");
if (expression.match(first_char) == true) return first_char
else return "#";
}

Keil made this part, its function is to display every Alphabet (A-Z) as it is and display every Non-Alphabet (0-9, symbols) as "#". This follows the same scheme most often applied in emulation related websites/ apps, it keeps things organized (e.g. much better suited for scrolling by next/ previous letter) and user knows exactly where an item could be found. I was using a very long/ blunt code before, listing every non-alphabet character. This code works beautifully, thanks Keil :D and welcome back.

Code: [Select]
local indicator_text = fe.add_text( "[!first_letter]",22, 0, 40, 40);
indicator_text.font="BebasNeue Book.ttf";
indicator_text.set_rgb(193,9,16);
indicator_text.style = Style.Bold;
indicator_text.align = Align.MiddleCentre;
indicator_text.charsize = 38;

This displays the first character of title on Indicator_position (circle), we get the "[!first_letter]" from Keil's reg expression code, rest is simple text manipulation.

Code: [Select]
function on_indextransition( ttype, var, ttime )
{
   indicator_graph.height = (indicator_bar.height)/(fe.list.size) * (fe.list.index+1)
   indicator_position.y = (indicator_bar.height - 34)/(fe.list.size) * (fe.list.index+1) + 176
   indicator_text.y = (indicator_bar.height - 34)/(fe.list.size) * (fe.list.index+1) + 176
}
fe.add_transition_callback( this, "on_indextransition" )

This is the main code which adjusts indicator bar location, I have added (-34) and ( +176) to get a desired result but its a temporary fix.

14
Themes / Re: RetroMania Theme (Fork of RetroMode)
« on: April 12, 2019, 10:27:56 PM »
Progress/ Indicator Bar Update: https://www.youtube.com/watch?v=bZ9CDi08Vec

(Its on left of gamelist)

15
Scripting / Re: advanced progres bar
« on: April 12, 2019, 10:26:47 PM »
Good job Jedione. I also worked on indicator/ progress bar last week for RetroMania theme. Check it out > https://www.youtube.com/watch?v=bZ9CDi08Vec

Pages: [1] 2 3 ... 14