Previous Thread
Next Thread
Print Thread
Joined: Feb 2014
Posts: 816
Likes: 30
G
Senior Member
OP Offline
Senior Member
G
Joined: Feb 2014
Posts: 816
Likes: 30
Hi guys,

After making a layout, it just seemed so hard to do something that was quite simple conceptually.

I'm not very good at editing XML text by hand, and I thought I'd play around with firefox a little.


So if I launch firefox and go to about:blank, I've got an empty page.

Then if I hit F12, I get the Developer Tools window.

Firefox won't let you open local files with XMLHttpRequest because of CORS blocking, so let's make a textarea and paste our xml into it:

in the console:


ta = document.createElement("textarea")
document.body.append(ta)

and you should have a textarea in your blank page now, it's a little small so go resize it.

[Linked Image from i.imgur.com]


Now locate a layout file in a text editor, select all the text and then paste it into the textarea.

so let's parse that xml:

par = new DOMParser()

>>> DOMParser { }

ser = new XMLSerializer

>>> XMLSerializer { }

xml = par.parseFromString(ta.value,"text/xml")

>>> XMLDocument { … }


and now you have magically parsed the xml into a DOM tree.

So you can access the elements with:

xml.querySelectorAll("element")

>>> NodeList(32) [ element, element, element, element, element, element, element, element, element, element, … ]


that returns a list of 32 elements, let's just focus on element 0:

xml.querySelectorAll("element")[0]

>>> <element name="devicetag_str" defstate="0">


so let's modify the name attribute:

xml.querySelectorAll("element")[0].setAttribute("name","was_devicetag_str")



ser.serializeToString(xml)

>>> <element name=\"was_devicetag_str\" defstate=\"0\">

so you can see that we have indeed modified the attribute name of the element.

and if you want to output the xml to your blank page, let's make another textarea and set the value to our serialized xml:

ta2 = document.createElement("textarea")
document.body.append(ta2)
ta2.value = ser.serializeToString(xml)


[Linked Image from i.imgur.com]


So let's try to make a new element and add it to the xml:

newelem = xml.createElement("element")
newelem.setAttribute("name","my_new_element")

newtext = xml.createElement("text")
newtext.setAttribute("string","a new string")
newelem.append(newtext)

xml.querySelector("mamelayout").prepend(newelem)


xml.querySelectorAll("element")[0]

>>> <element name="my_new_element">

ser.serializeToString(xml.querySelectorAll("element")[0])

>>> "<element name=\"my_new_element\"><text string=\"a new string\"/></element>"


[Linked Image from i.imgur.com]

So it's pretty easy to manipulate XML with javascript.


Next step is to try to make some resizable divs that would represent the various layout items like text and rect.

Another thing that's kinda cool to do is to open the xml file into firefox, then use the F12 developer tools to inspect the xml tree.

Joined: May 2009
Posts: 2,032
Likes: 66
J
Very Senior Member
Offline
Very Senior Member
J
Joined: May 2009
Posts: 2,032
Likes: 66
Yeah, what you describe is something that is "easy" to do, but requires a whole ton of actual work to do in a reasonable way, particularly for MAME's layout system.

It's something I have at the back of my mind every day, since making such a tool will eventually be necessary when MAME's UI system is updated to relatively modern hierarchical standards, as well as at my day job work, which is what the eventual UI system will be based on.

Joined: Oct 2006
Posts: 1,016
Likes: 21
S
Very Senior Member
Offline
Very Senior Member
S
Joined: Oct 2006
Posts: 1,016
Likes: 21
If memory serves, someone once made a simple MAME artwork creator tool that was WYSIWYG... Can't remember who, but third party obviously.

Definitely would be broken these days after the artwork system rewrite, but it would still work for old versions.

Pre-rewrite thoughts on creating such a user-friendly tool exists in https://github.com/mamedev/mame/issues/443

Another broken thing: https://mrdo.mameworld.info/mame_lay.php

Also broken: making MAME bezel artwork with Python: https://medium.com/@ericmulvihill/generating-mame-bezel-layouts-with-python-317f9dda2e6d / https://bitbucket.org/ericmulvihill/mame-bezel-layout-generator/src/master/

Joined: Feb 2014
Posts: 816
Likes: 30
G
Senior Member
OP Offline
Senior Member
G
Joined: Feb 2014
Posts: 816
Likes: 30
I'd actually be happy just to be able to load a picture and then put a few pushbuttons, leds, rect, disk and text elements on it, nothing too spectacular.

More complex stuff could just be represented by an empty rect as a placeholder, and then replace it in the xml by hand.

What I envisioned was to load an image of the panel and use that as a guide to reproduce the text, buttons and leds.


Just for fun, I found the largest mame lay file in src/mame/layout to see if it would parse in firefox and it did just fine. Apparently, it was made with MFME2MAME, which I guess was translated from an MFME layout. (The website mfme2mame.org doesn't exist anymore.)

Code
<!--  ****************************************************  -->
<!--  * This MAME layout file was generated by MFME2MAME *  -->
<!--  * Please visit mfme2mame.org for more information. *  -->
<!--  ****************************************************  -->


I got a div to move around, it's quite fun to play with firefox divs, entering commands from Firefox's developer tools console:


With some javascript code from https://codepen.io/jkasun/pen/QrLjXP
(modified a little to take into account setting a margin on the div)


Code
function dragMouseDown(e) {
    elmnt = this;
       e = e || window.event;
    // get the mouse cursor position at startup:
    pos3 = e.clientX;
    pos4 = e.clientY;
    document.onmouseup = closeDragElement;
    // call a function whenever the cursor moves:
    document.onmousemove = elementDrag;
  }

  function elementDrag(e) {
    if (!elmnt) {
      return;
    }

    e = e || window.event;
    // calculate the new cursor position:
    pos1 = pos3 - e.clientX;
    pos2 = pos4 - e.clientY;
    pos3 = e.clientX;
    pos4 = e.clientY;
    // set the element's new position:
    elmnt.style.top = elmnt.offsetTop - pos2 - parseInt(window.getComputedStyle(elmnt).marginTop) + "px";
    elmnt.style.left = elmnt.offsetLeft - pos1 - parseInt(window.getComputedStyle(elmnt).marginLeft)+ "px";
  }

  function closeDragElement() {
    /* stop moving when mouse button is released:*/
    document.onmouseup = null;
    document.onmousemove = null;
  }

Just assigning the dragMouseDown function to the onmousedown event will make the item draggable.

Code
newitem = document.createElement("div")
newitem.classList.add("textitem")
newitem.innerHTML = "NonBreaking&nbsp;Space"
newitem.style.position = "absolute"
newitem.style.top = "500px"
newitem.style.left = "500px"
document.body.append(newitem)

newitem.onmousedown = dragMouseDown

newitem.style.fontFamily = "Arial"
newitem.style.fontSize = "40px"


[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]

Joined: Feb 2014
Posts: 816
Likes: 30
G
Senior Member
OP Offline
Senior Member
G
Joined: Feb 2014
Posts: 816
Likes: 30
I wanted to play with svgs in layouts and in firefox.

Svgs can be used in a layout element with an image tag and an internal data tag.

I took the mame logo and loaded it into inkscape. Right clicking on it and selecting "Trace Bitmap" will allow me to make an svg object. Then you can copy it to the clipboard and paste it into LeafPad as text. (I had to use the program CopyQ because sometimes it wouldn't paste directly in.)

[Linked Image from i.imgur.com]

[Linked Image from i.imgur.com]




So first, let's find an example of an embedded svg in mame's src/mame/layout directory:

grep -r svg src/mame/layout
Code
src/mame/layout/tx81z.lay: <svg xmlns="http://www.w3.org/2000/svg" width="66.43" height="68.45">
src/mame/layout/tx81z.lay: </svg>

        <element name="arrow">
                <image>
                <data>
                        <![CDATA[
                                <svg xmlns="http://www.w3.org/2000/svg" width="66.43" height="68.45">
                                <polygon fill="none" stroke="#FFFFFF" stroke-width="3" stroke-miterlimit="10" points="57.53,15.86 57.53,3.45 4.02,34.1 57.97,65 57.97,52.59 64.43,52.59 64.43,15.86 "/>
                                </svg>
                        ]]>
                </data>
                </image>
        </element>

so if I strip out the svg part I get
Code
   <image>
                <data>
                        <![CDATA[
                            
                        ]]>
                </data>
                </image>
and then I can paste in the svg generated from the trace into a "pushbutton" element in my existing layout:

Code
	<element name="pushbutton_rect" defstate="0">
		<rect state="0">
			<color red="0.0" green="0.0" blue="0.0" />
		</rect>
		<rect state="0">
			<bounds x="0.02" y="0.02" width=".96" height="0.96" />
			<color red="0.92" green="0.91" blue="0.75" />
		</rect>
      <image>
                <data>
                        <![CDATA[
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   version="1.1"
   id="svg959"
   width="450"
   height="149.99998">
... (it's quite long)
</svg>
                   
                        ]]>
                </data>
                </image>
	</element>


Now my pushbuttons have a mame logo on them:

[Linked Image from i.imgur.com]



So can we display the svg in firefox? yes!

Go to an about:blank page and hit f12, then you can

create an svg element with createElement NS:
Code
mysvg = document.createElementNS("http://www.w3.org/2000/svg","svg")
Now use backticks to do a multiline string so you can paste the svg text

Code
mysvg.innerHTML = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www
... (very long)


Code
document.body.append(mysvg)
mysvg.style.width ="500px"
mysvg.style.height = "200px"
mysvg.style.transform = "rotate(30deg)"
mysvg.style.position = "absolute"
mysvg.style.top = "100px"

[Linked Image from i.imgur.com]

use backticks:

[Linked Image from i.imgur.com]
[Linked Image from i.imgur.com]


[Linked Image from i.imgur.com]

Joined: Feb 2014
Posts: 816
Likes: 30
G
Senior Member
OP Offline
Senior Member
G
Joined: Feb 2014
Posts: 816
Likes: 30

Joined: May 2009
Posts: 2,032
Likes: 66
J
Very Senior Member
Offline
Very Senior Member
J
Joined: May 2009
Posts: 2,032
Likes: 66
The aspect ratio on those MAME logos is fucked, though.

I've been doing UI coding for the past 4 years at my day job, and even wrote the UI system that we're using for our current title that's in the works.

What you want to do is look at what scaling factor is necessary to make the image fit along either axis, choose whichever one is less, and then use that scaling factor on both axes so that you don't screw up the aspect ratio.


Link Copied to Clipboard
Who's Online Now
1 members (R. Belmont), 19 guests, and 3 robots.
Key: Admin, Global Mod, Mod
ShoutChat
Comment Guidelines: Do post respectful and insightful comments. Don't flame, hate, spam.
Forum Statistics
Forums9
Topics9,085
Posts119,077
Members5,014
Most Online890
Jan 17th, 2020
Our Sponsor
These forums are sponsored by Superior Solitaire, an ad-free card game collection for macOS and iOS. Download it today!

Superior Solitaire
Forum hosted by www.retrogamesformac.com