Is this possible: a "translator" that exports XD elements to a given structure in XML format or equivalent

Exporting to HTML is nowadays common. It turns graphical elements to HTML-code (I am no programmer, so programmers and developers can surely describe this way nicer).

My question is whether it is possible to create exporter / “translator” that turns graphical elements to something else than HTML, if provided with a “translation table”, ie element A turns into this text-string, which in turn is encapsuled in this string, ending up in a new file format that has a certain “code layout”.

Basically I am thinking if it is possible to turn XD into a front-end for designing script code for 3dsmax that builds UI elements.
I am rather new in XD as well, so I havent seen the range of plugins, nor how they work. For example, is it common to create predefined objects in a plugin that you drag-drop into XD workspace, so that they serve as “translator” objects, ie this item will turn into this code.
Or would it be sufficient to create a translation table, so that if I have a native XD element, say text, it will turn into this element once exported to the target language.

Forgive me for this possibly poor description, but I still hope I made my question clear. Looking forward to a discussion :smiley:

2 Likes

First of all: Welcome to the forums :wave: :slightly_smiling_face:.

If I understand you correctly, you’re asking whether it is possible to convert an XD document (i.e., all the information about its content) into another technical file format, e.g., XML or similar.

If that is the question, then yes, is absolutely possible to do so. All the information (except for very few exceptions which aren’t in the APIs, yet, like the Grid options) about the document are accessible for plugins and, since JS is a turing-complete language, you can basically produce any output you want :wink:.

About the “how” (as you wrote that you’re no programmer, I don’t know if this will help you, but to make this a useful answer instead of yes, it’s possible, I’ll write it anyway :stuck_out_tongue_winking_eye:):

Since the scenegraph is already structured in a tree format (the RootNode has several children which again have children if they are Groups and all of them have properties, meaning you can just iterate over them recursively and thereby build your XML/whatever tree.

The one area where it could get a little more complicated will be images, I don’t know what your reqirements in that area are?

After that, you can simply generate your string from whatever file structure you chose and ask the user for a location to save it (const file = await require('uxp').storage.localFileSystem.getFileForSaving(...);) and save the file there (await file.write(myString);).

I hope this helps,
Best,
Pablo

3 Likes

Thank you Pablo for a very educational answer. Also, thanks for not cutting me off, but instead explaining bits of the “how” - that was indeed the answer I was looking for instead of just a “yes” or even worse “go read the SDK and find out yourself” :wink:

Since you’re good in explaining things, I take the chance and ask some more.

Does it mean you would need to create a “translation” table of some sort (forgive me my lack of proper terminology) - and how could a translation table look like?
If I wanted to use something else than the predefined elements (lines, text and so on), can plugins create an own set of objects, for the sake of limitation and simplicity; you would only be able to export “XML” of those predefined elements. Would that be possible?

To shed more light over the matter, I created a little demo (XD-file provided here since the forum didn’t allow me, a new user, to attach files). And a screen capture follows below:
image

In destination code (3dsMax), this would translate to something like this - never mind the missmatching values compared to the XD-design. I simply copy pasted the original code from 3dsMax to show you what it really looks like:

rollout RelaxPolygonDemo “Relax Polygon” width:310 height:275
(
slider ‘slider_amount’ “Amount:” pos:[10,15] width:200 height:44 range:[0.05,1,0.5] align:#left
editText ‘amount_value’ pos:[60,15] width:50 height:15 align:#left
slider ‘slider_iteration’ “Iteration:” pos:[10,70] width:200 height:44 range:[1,100,10] align:#left
editText ‘iteration_value’ pos:[60,70] width:50 height:15 align:#left

label ‘lbl_axis’ “Smooth axis” pos:[10,120] width:40 height:15 align:#left
checkbox ‘chk_x’ “x” pos:[60,120] width:29 height:15 align:#left
checkbox ‘chk_t’ “y” pos:[100,120] width:29 height:15 align:#left
checkbox ‘chk_z’ “z” pos:[140,120] width:29 height:15 align:#left

checkbox ‘chk_outer’ “Keep outer” pos:[114,140] width:77 height:15 checked:true align:#left
checkbox ‘chk_border’ “Keep border” pos:[12,140] width:82 height:15 checked:true align:#left

button ‘btn_relax’ “Relax” pos:[51,168] width:80 height:21 align:#left
)

1 Like

First of all: Let’s look at how it would be possible to translate the “raw” elements. For that, you’d create a function that “translates” an arbitrary SceneNode into your language of choice and calls itself (recursively) for all of its child nodes:

const scenegraph = require('scenegraph');

function translate(node) {
  let translation = '';

  if (node instanceof scenegraph.Artboard)
    translation += 'Artboard (' + node.fillEnabled + ',' // append any properties you need
  else if (node instanceof scenegraph.Text)
    translation += [...]
  [...]

  if (node.children) {
    translation += ' children:{'
    for (let childNode of node.children.items) {
      translation += translate(childNode);
    }
    translation += '}';
  }
  translation+=');'
}

const myResult = translate(scenegraph.root);

(the translation this would generate wouldn’t be very useful, but it demonstrates how it could work in theory :wink:)


Regarding your goal:

I would argue that this is (at some level) achievable, but provides a few challenges that won’t be easy to overcome:

  • you have to detect – how should I put it – what is what in your XD document and detect it. For example, you’d have to detect a button by “it’s a group with a rectangle that’s filled with this tone of gray and also contains a text node with this font family and font size” (similar things, yet it only gets more complicated, with the sliders and checkboxes. Every text that doesn’t belong to something like this is considered to be a label, like “Smooth”
  • you have to somehow detect things like the sliders range. Again: it’s possible. You have its current value, the width of the slider and the current position of the handle, meaning it is feasible to calculate it, but let me just say it’s (excuse the language) darn hard :stuck_out_tongue_winking_eye:

All in all, I’d say creating something like this would be possible, but I doubt the resulting quality would be worth the effort. Except if you have far too much money to pay a not too small team of developers to do it, all you (or me) might be able to achieve would be a rudimentary “design to code” system the quality of which wouldn’t be worth the effort.

You might be able to adjust he project so that your plugin knows beforehand which element is which and you can only move and resize elements created by your plugin (which “remembers”, through sceneNode.pluginData, that that’s a [slider/checkbox/whatever], but that still would be a big effort (and one where I’m not sure it would be worth it).

It is, as stated, possible to do all of this (in one way or another), but the further you go away from a structure that’s unlike the one in XD, the more complex it becomes. For something like your case, you have to extract, in a sense, implementation logic like checked:true, range:[0.05,1,0.5] and so on. All in all, it is therefore possible to achieve this, but if you want to put that much effort into something like this where, probably 50% of the time, the outputted code won’t be what you’re looking for, is up to you to decide :slightly_smiling_face:

I hope this helps,
Best,
Pablo

1 Like