Instruction making rant


Instruction making rant
#1
I made two instruction for reasonably complex (but not even too big) Technic models, and the process is needlessly painful. So I have a couple of questions and a rant about the future of instruction making software. This is a completely newbie post, so I hope it does not sound too offensive. As English is not my native language it is a little hard for me to write criticism correctly, but I do recognize the seniority of the forum members about these matters. I certainly do not know much about the whole Ldraw software, so I would gladly read explanation why things are done the way they are done. Also some of my nitpicks may be explained by me failing to find some features.

Questions
  1. Is there a way to use buffer exchange without pain? How do you insert the BUFXCHG line? I know that you can insert it by dragging it from LDCad part bin (which usually inserts it in a wrong place) or write it manually in the source (which requires to reload the model). What is worse, if you apply buffer exchange to a submodel, you have to copy and flatten the whole submodel later (and also ignore it in PLI).
  2. What is the relation between Studio part library and LDraw? Do they just copy it or do they contribute something?
  3. Is there a way to show model from different angle easily? Currently the only way I know is copy the whole model as a subfile, ignore all the parts in the subfile and display it as a callout without arrows. This does not scale well: suppose you have to change something in the beginning of the model, then you'll have to change all the copies too.
Rant

In my opinion, if we want to keep anyone use open software and not Studio (which is also somewhat slow, buggy, closed-source and uses proprietary format), LPub3D and LDCad should be way better. My feeling is that now all new users come to Studio, as it is actually usable.

LDCad is really great, it works very fast, even with huge models and on weak computers, its GUI is really effective and documentation is good. I have only minor nitpicks about it:
  • You can't pin compass window. I don't really need the whole compass, it is too big anyway. But I do need the the ASR/NSR switch because if ASR is enabled you can lose current orientation by switching steps, so I constantly check the switch.
  • You need to go to the outer submodel to check the flexible part length
  • Flexible nets are not supported
  • I know you can make part bin with colors (even with counts, that is very cool, much faster than Studio), but it would be useful to quickly change color bin selection to only physically available colors for the part. Maybe even make such mode default, but quickly switchable to current mode.
At the same time, LPub3D experience is terrible, some of that is due to the current implementation and some is due to general design choices (IMHO).
The worst thing is speed. It usually take more than a full minute to render an new page after the next button click. Than is on a decent hardware IMO (quad-core i7-8650U, NVMe storage, more than enough RAM). "Convert to callout" can take several minutes, and even right mouse click can take several seconds to actually show the menu. LDCad is capable of displaying models in real time with reasonably high FPS, so that is definitely possible.

The whole thing is buggy, it crashes regularly, once it deleted a whole subfile. There are a lot of minor bugs in the current implementation, to name a few:
  • Part annotations do not show in callouts
  • Output depends on platform and environment
  • Incorrect BOM with REMOVE GROUP
  • BOM looks terrible compared to official ones (I tried many sorting options, it all looks wrong and unreadable)
  • Export to rebrickable and bricklink works not flawlessly
  • LPub crops images with small camera distance, so it is not possible to pan to specific part of a model
  • LPub inserts another submodel preview on every page of multi-page submodel if the page is a multi-step
  • Part annotations are only inserted once per part
  • Submodel-level colors work not quite the same way as they do in the official manuals
The whole LPub3D automatic layout and margin management is hard to use. Even small movement makes several elements to change position, so it is very hard to place elements, especially with enormous redraw times. I end up using absolute (page) position. The whole relative element placement is very frustrating, it is hard to control.

LPub multi-step layout and margins look very wrong (compare https://imgur.com/5DYF5Cx and https://i.imgur.com/kYRTVWf)

Lack of full spec does not help (https://trevorsandy.github.io/lpub3d/ass...mands.html is partially incorrect)

I believe if I had such problems with LPub it is hard to maintain so big thanks to Trevor for doing this. I opened several issues and made some minimal contributions on the Github and Trevor provided very quick answers and edits. But I spent some time even figuring out how to build it to make minimal changes to the code. I think simpler build process and more instructions would be helpful.

Future

As for the future of LPub and LDCad, I have some thoughts about features which would make the process easier and make some competition with Studio possible.

LPub3D default settings should follow current Lego visual language (colors, fonts, margins, rotation icon look, BOM sorting order, line width, which parts use annotations and which don't). The default output should look like 42111 instruction, not like some adhoc script output.

LDCad, preferably, should have ability to store zoom and pan steps and display them in same way in does with ROTSTEPs

Rotation icon should be inserted automatically if the next step is a ROTSTEP (with an option to suppress this default)

I'd like to make callouts with complex shape (see https://imgur.com/ixTDV8b) and more complex callout arrows (https://imgur.com/41eIKeo) easier. Also it would be nice to allow to have submodel last step and its application on same page with a divider, (see https://imgur.com/QGdf5kb)

Maybe subfile header should include part substitution info. As usually you don't need the whole flexibility of PLI BEGIN SUB, as you don't replace arbitrary subsets of a model with arbitrary parts, you only need to replace a submodel with bent part with it's original state. Moreover, even if the said submodel is used multiple times, it is always replaced with the same part. I know that LDCad has partName and partDescr metas (which are not used anyway), but this could also be used with universal joints, shock absorbers, hinges and other parts.

Both current possibilities to change assembled model, BUFEXCHG and REMOVE GROUP are hard to use (unless I am missing something) and limiting. Official instruction use them all the time, see the beginning of 42082 manual (https://imgur.com/jgzpMnd), it is quite time consuming to replicate such steps. Also sometimes you need to rotate parts of a model, move pins or connect cables or tubes. I don't have any ideas of a new syntax for this. Maybe the problem is that the current mechanism is too generic, as you really don't replace random parts with some other random parts, you only substitute the same parts with different positions, and you very rarely need to actually remove parts. I'm not saying saying it shouldn't be supported though

LDCad should have arrow generator, similar to current path generator, so that such arrows (https://imgur.com/bOJdK71) could be made easily.
Generally, there should be two kinds of arrows, "real arrows" and "sprite arrows" (I am not sure whether it is a correct name).
Real arrows should be parts, maintained and distributed officially by LDraw. As LDraw aims to make an official Lego part library with all (and only) official parts produced by Lego, it is reasonable to also maintain official design elements. Instruction designers will have a unified set of them, so they don't have to ship their custom arrows with the instruction. Big yellow arrows used to move parts of a model (https://imgur.com/D6iyDpb) should also be included as parts. Highlighting frames and circles such as https://imgur.com/Ag5Te9E could also be included.
Sprite arrows should be generated by LDCad (they could be straight, maybe aligned to relative grid or curved, exactly the same as paths like cables and tubes) and rendered by LPub in such way that the arrow always faces the camera and always has the same width.
Reply
RE: Instruction making rant
#2
It's kinda late here, so I'll look into the whole post tomorrow.

(2020-05-22, 23:30)Daniel R Wrote:
  1. Is there a way to use buffer exchange without pain? How do you insert the BUFXCHG line? I know that you can insert it by dragging it from LDCad part bin (which usually inserts it in a wrong place) or write it manually in the source (which requires to reload the model). What is worse, if you apply buffer exchange to a submodel, you have to copy and flatten the whole submodel later (and also ignore it in PLI).

You writing "which usually inserts it in a wrong place" makes me suspect you're not yet discovered the source window which allows inserting and moving of otherwise invisible content.

You open one with "views/new source window", and if needed dock it by holding down the ctrl key while moving it around.
Reply
RE: Instruction making rant
#4
I discovered the source window but as I already had a text editor with the model file opened, I didn't see value in it. It indeed does not reload the whole model when you reorder lines so thank you! It makes life better Smile
Reply
RE: Instruction making rant
#3
Quote:Is there a way to show model from different angle easily? Currently the only way I know is copy the whole model as a subfile, ignore all the parts in the subfile and display it as a callout without arrows. This does not scale well: suppose you have to change something in the beginning of the model, then you'll have to change all the copies too.
If I understand correctly what you want, you need to use ROTSTEP to change viewpoint of your current view. Note that ROTSTEP is to be placed at the END of the step you want to display with another viewpoint.


Quote:ASR/NSR switch because if ASR is enabled you can lose current orientation by switching steps, so I constantly check the switch.
That's something I almost never use... but there is a defined keyboard shortcut (b) that you can customize if needed.


Quote:Flexible nets are not supported
Tough problem, this has been asked for several times...


Quote:I know you can make part bin with colors (even with counts, that is very cool, much faster than Studio), but it would be useful to quickly change color bin selection to only physically available colors for the part. Maybe even make such mode default, but quickly switchable to current mode.
This needs a properly updated database of available colors for a given part. Possible by tapping in external inventories websites, but it create a dependancy to that website...


Quote:The worst thing is speed.
I definitely agree with you, but have you tried to use LPub3D native renderer? Not a panacea as it comes with some other issues (scaling management), but it's definitely faster. Still, it's still not that fast in some cases, I'm currently struggling with it for a model that includes large Technic baseplate: takes a while...
Reply
RE: Instruction making rant
#5
(2020-05-24, 7:05)Philippe Hurbain Wrote: If I understand correctly what you want, you need to use ROTSTEP to change viewpoint of your current view. Note that ROTSTEP is to be placed at the END of the step you want to display with another viewpoint.

No, I failed to explain what I want. See this page from 42082 instruction
[Image: 5mMaM7c.png]
The only way of producing this I know is to make a separate submodel with this view and display it as a callout without arrows. This is a very bad pattern, as it requires copying all the parts, making it hard to make changes in that part of the model.

Quote:That's something I almost never use... but there is a defined keyboard shortcut (b) that you can customize if needed.

That shortcut is partially the reason of my problem. I use it all the time, and, as I don't open the compass window to use it, I sometimes don't remember the current state of this switch. Because if it is on, you can lose your carefully chosen orientation by switching steps.


Quote:This needs a properly updated database of available colors for a given part. Possible by tapping in external inventories websites, but it create a dependancy to that website...


That is not a problem at all. What this needs is API support from LDCad, namely an ability to change color bin contents based on current selected part and external configuration. Also this should be quickly enough not to annoy the user by high latency but with the configuration file loaded and preprocessed in advance (on LDCad start) it should not be hard. The configuration file itself does not need to change more often than three or four times a year and its current version could be shipped with LDCad the same way the shadow files are shipped. The data itself can be easily grabbed from Rebrickable. Because this would be a plain text configuration file (as all LDCad configs are), the users can make updates themselves.


Quote:I definitely agree with you, but have you tried to use LPub3D native renderer? Not a panacea as it comes with some other issues (scaling management), but it's definitely faster. Still, it's still not that fast in some cases, I'm currently struggling with it for a model that includes large Technic baseplate: takes a while...

Yes, I use the native renderer. I used LDView previously as I couldn't use the native one due to some bug, but the bug was reported to Trevor and fixed. It still sometimes requires more than one full minute to show the next page
Reply
RE: Instruction making rant
#6
Quote:The only way of producing this I know is to make a separate submodel with this view and display it as a callout without arrows. This is a very bad pattern, as it requires copying all the parts, making it hard to make changes in that part of the model.
Got it. For this I make a snapshot of the needed area (generally with LDView) and insert the image in LPub3D. But that also duplicates data and also make changes tricky...

Quote:Yes, I use the native renderer. I used LDView previously as I couldn't use the native one due to some bug, but the bug was reported to Trevor and fixed. It still sometimes requires more than one full minute to show the next page
I solved my large technic baseplate (39369) problem by temporarily removing all of its subparts from Lpub3D library archive. This makes editing possible again, I'll restore these files for final rendering... and report the problem to Travis!
Reply
RE: Instruction making rant
#7
(2020-05-22, 23:30)Daniel R Wrote: The worst thing is speed.
I think the speed problem is more of a graphics card problem.  I use a slightly older notebook, and I don't care whether I use Native or LDView.  Both are equally fast (slow).  The only difference is that I have LDView running much, much more stable.  I also don't like the auto-zoom behavior of the native renderer.
If nothing goes right, go left.
Reply
RE: Instruction making rant
#8
Quote:Both are equally fast (slow)
For me, (and a friend who makes BIG Technic BIs) native renderer is MUCH faster (or should I say much less slow? Big Grin )
(2020-05-26, 6:40)Johann Eisner Wrote: I also don't like the auto-zoom behavior of the native renderer.
I hate it!!!
Reply
RE: Instruction making rant
#20
(2020-05-26, 6:40)Johann Eisner Wrote: I think the speed problem is more of a graphics card problem.

I assumed it is not a graphics card problem, as the task is quite simple and it is clearly possible to display models in real time. LDCad does it. But indeed, I currently do not have a proper video card (intel-whatever in 8650U does not count), so I would be glad if someone with one confirms that LPub3D can display 1000+ part models quickly
Reply
RE: Instruction making rant
#9
Hi Daniel, I see you are new here, so welcome to the LDraw community!

To answer some of you questions, here goes.

Buffer exchange is a pain, no way to soften that. Surely if you are depending on it heavily like in technic model instructions.
It originated from MLCad and was implemented later in LPub(3D) and LDCad.
To work with it and understand fully, please refer to one of the many tutorials that are out there, like mine: Blush
https://sites.google.com/view/workingwit...r-exchange

Maybe you can study my showcase Technic set 42061 - Telehandler model too.
https://sites.google.com/view/workingwit...d/showcase

These instructions feature some of your wishes and might answer some of your questions too, I think.

As for the software development: you know this is done by hobbyists and comes as is.
I do agree that there are missing features and some could be improved or added.
But we are dependent on the authors of the software and the amount of time and effort they are willing to put in to it.

Development of LDCad is still going strong.
Development of LPub3D has come to a hold it seems.

What version of LPub3D do you use? I do not experience that many crashes. In fact, almost none.

You say "LPub3D default settings should follow current Lego visual language". Why? If you want to mimic exact LEGO instructions you can make your own "template".
I have a whole set of standard settings I just copy in the LDraw file before I start editing in LPub.
But most of the time I try making my own style for instructions though.

Render speed: I start going through the whole model using the native renderer, not creating any callouts, multi step pages, etc. Just go through it to see if the whole building process seems logic. I try to make as much instruction logic while modelling.
Once that is done, I start thinking of callouts. I add the metacommands for those manually to speed things up. Much faster than directly in LPub.
Once happy with the way things look, I start using LDView as rendere and finish instructions. Then often edit the PDF or PNG's manually.

Callouts with complex shapes like your example won't be done any time soon. This is too complex. Again: we depent on the developer of LPub3D and like said that has come to a hold it seems.
Complex callout arrows can be done.

Submodel last step and its application on same page with a divider should somehow be possible, but I haven't figured that one out.

You state that BUFEXCHG and REMOVE GROUP are hard to use. You are right about that. These are very complex and advanced features and hard to learn techniques.

IMHO I think you expect too much of the software. We could never make official LEGO like instructions, but can get very close.

Still, your wishes and ideas are very good.
Jaco van der Molen
lpub.binarybricks.nl
Reply
RE: Instruction making rant
#10
(2020-05-26, 7:58)Jaco van der Molen Wrote: Buffer exchange is a pain, no way to soften that. Surely if you are depending on it heavily like in technic model instructions.
It originated from MLCad and was implemented later in LPub(3D) and LDCad.
To work with it and understand fully, please refer to one of the many tutorials that are out there, like mine: Blush
https://sites.google.com/view/workingwit...r-exchange

There's something I wonder about in that tutorial—you mention a couple of times that the BUFEXCH_STORE command is used to "store" the hovering parts in the buffer. But isn't it true that what's actually being stored is the view up until that point—in other words, everything before you start to add hovering parts?


So the sequence goes like this:
  • You build your model up to a certain point, then "store" that building state in the buffer, like a save point in a video game.
  • You add some new parts that you plan to change in some way later—move them, or not display them at all, etc. These are simply added to the building state you had so far.
  • You then "retrieve" the building state that you stored—essentially, you "revert" to the save point (losing all changes made since then).
  • You continue building from your saved state, first by adding those same new parts in their changed condition (moved, or just not shown, etc.).
Is that an accurate understanding of the process?

I see why it makes sense, though, to think of the hovering parts themselves—everything between the STORE and RETRIEVE commands, essentially—as being the "buffer". But maybe there are other use cases where it helps to go by the "save" and "revert" concept instead.
Reply
RE: Instruction making rant
#11
(2020-05-26, 16:53)N. W. Perry Wrote: ...but isn't it true that what's actually being stored is the view up until that point—in other words, everything before you start to add hovering parts?

I have absolutely no idea. Big Grin I've never fully understood how it works.
The way I describe it is my interpretation.

Only recently I discovered the usage of other letters the A for a buffer (see my showcase model for the Telehandler)

So I guess you can put it the way you say too. No clue however.
Maybe someone can enlighten us?
Jaco van der Molen
lpub.binarybricks.nl
Reply
RE: Instruction making rant
#12
(2020-05-26, 17:24)Jaco van der Molen Wrote: I have absolutely no idea. Big Grin I've never fully understood how it works.
The way I describe it is my interpretation.

Only recently I discovered the usage of other letters the A for a buffer (see my showcase model for the Telehandler)

So I guess you can put it the way you say too. No clue however.
Maybe someone can enlighten us?

Yep, buffer exchange and rotation matrices—the two holy grails of LDraw. ;-)

I have a specific use case in mind for buffer exchange, in fact, based on a recent convention in official building instructions. The habit these days is to show a sub-build of a model as part of the main step sequence, rather than a series of sub-steps. So for several steps in a row, the main model will be hidden while the sub-build is constructed, then the last step in that group will be placing the sub-build where it belongs in the main model.

So I'd like to work out how to achieve this in buffer exchange, which I assume is just a matter of using the CLEAR meta right after the first STORE command. (I should note that I don't actually create instructions; rather, I try to replicate the build process in the model file itself.)

EDIT: Actually, I guess not—LDCad doesn't seem to recognize the CLEAR meta. Instead, you'd put the STORE command at the very top of the model, before anything's added. Then once you get to the sub-build, you'd first STORE the build so far into a second (B) buffer), then insert a RETRIEVE A command to bring back that first (empty) build state.
Reply
RE: Instruction making rant
#15
(2020-05-26, 17:49)N. W. Perry Wrote: EDIT: Actually, I guess not—LDCad doesn't seem to recognize the CLEAR meta. Instead, you'd put the STORE command at the very top of the model, before anything's added. Then once you get to the sub-build, you'd first STORE the build so far into a second (B) buffer), then insert a RETRIEVE A command to bring back that first (empty) build state.

I never seen a CLEAR meta used with bufxchg, it isn't mentioned in MLCad documentation ether.

Is there any documentation available on its goal/usage, so I might add support for it in 1.7.
Reply
RE: Instruction making rant
#17
(2020-05-26, 20:30)Roland Melkert Wrote: I never seen a CLEAR meta used with bufxchg, it isn't mentioned in MLCad documentation ether.

Is there any documentation available on its goal/usage, so I might add support for it in 1.7.

All I know of it is what's in the official File Format, which is, in its entirety:

Quote:Clear

Clears the screen

Format:
0 CLEAR

This command causes all previous drawn sub-files and line types to be cleared (erased). Any following line types are drawn as normal.

But it seems like it should work, as:
Code:
<some building steps>
0 BUFEXCHG_STORE
0 STEP
0 CLEAR
<some new parts>
0 BUFEXCHG_RETRIEVE
<building continues…>

But my other way seems to work fine, too (storing the empty model and retrieving it when isolating a sub-build).
Reply
RE: Instruction making rant
#19
(2020-05-26, 21:03)N. W. Perry Wrote: All I know of it is what's in the official File Format, which is, in its entirety:


But it seems like it should work, as:
Code:
<some building steps>
0 BUFEXCHG_STORE
0 STEP
0 CLEAR
<some new parts>
0 BUFEXCHG_RETRIEVE
<building continues…>

But my other way seems to work fine, too (storing the empty model and retrieving it when isolating a sub-build).

O wait it's just 0 CLEAR I was thinking about 0 BUFXCHG CLEAR.

0 CLEAR is a very old (pre 3d card) meta.

It seems in LDCad you can also just use a BUFXCHG Z RETRIEVE (or some other unused latter). Not sure if that's standard behavior though. So I could probably add support for CLEAR by making it an alias for that using a 27th 'letter' Smile
Reply
RE: Instruction making rant
#23
(2020-05-26, 17:49)N. W. Perry Wrote: I have a specific use case in mind for buffer exchange, in fact, based on a recent convention in official building instructions. The habit these days is to show a sub-build of a model as part of the main step sequence, rather than a series of sub-steps. 

While you can replicate this with BUFEXCHG, LPub3D now has a setting to enable continuous step numbering, so you can use submodels as usual. I think it is much easier
Reply
RE: Instruction making rant
#43
(2020-05-27, 1:39)Daniel R Wrote: While you can replicate this with BUFEXCHG, LPub3D now has a setting to enable continuous step numbering, so you can use submodels as usual. I think it is much easier

Yes, you're right. I should add that I don't actually use LPub at all, so I'm looking at ways to do this in the model editor.
Reply
RE: Instruction making rant
#24
(2020-05-26, 17:24)Jaco van der Molen Wrote: Only recently I discovered the usage of other letters the A for a buffer (see my showcase model for the Telehandler)

I think you are referring to this fragment

Code:
1 71 0 0 -150 -1 0 0 0 0 1 0 1 0 92907.dat
0 BUFEXCHG A STORE
1 71 -40 -20 -130 1 0 0 0 1 0 0 0 1 4519.dat
1 71 -40 0 -130 1 0 0 0 1 0 0 0 1 4519.dat
0 STEP
0 !LPUB MULTI_STEP DIVIDER
1 72 0 0 0 0 0 -1 0 1 0 1 0 0 18942.dat
0 BUFEXCHG B STORE
0 !LPUB PART BEGIN IGN
1 4 -30 -20 -102 0 0 -1 -1 0 0 0 1 0 a4.ldr
0 !LPUB PART END
0 !LPUB PART BEGIN IGN
1 4 -30 0 -102 0 0 -1 -1 0 0 0 1 0 a4.ldr
0 !LPUB PART END
0 STEP
0 !LPUB MULTI_STEP END
0 BUFEXCHG B RETRIEVE
0 BUFEXCHG A RETRIEVE
0 !LPUB PLI BEGIN IGN
1 72 0 0 0 0 0 -1 0 1 0 1 0 0 18942.dat
1 71 0 0 -130 1 0 0 0 1 0 0 0 1 4519.dat
1 71 0 -20 -130 1 0 0 0 1 0 0 0 1 4519.dat
0 !LPUB PLI END
1 72 -25 60 -130 0 1 0 0 0 -1 -1 0 0 32250.dat
0 STEP

I think it doesn't make any sense here to use buffer B, it has no effect. Could you please explain this?

In fact, I cannot think of any reasonable use of multiple buffers
Reply
RE: Instruction making rant
#13
(2020-05-26, 16:53)N. W. Perry Wrote: Is that an accurate understanding of the process?
This is exactly how my mind sees Bufexchg process...
Reply
RE: Instruction making rant
#22
(2020-05-26, 7:58)Jaco van der Molen Wrote: To work with it and understand fully, please refer to one of the many tutorials that are out there, like mine: Blush
https://sites.google.com/view/workingwit...r-exchange

Maybe you can study my showcase Technic set 42061 - Telehandler model too.
https://sites.google.com/view/workingwit...d/showcase

I did study your tutorials, thank you very much for them! They are the best I could find. In fact, I used your arrows you shipped with your instruction package. I am not sure whether it would be of any interest, but the two instructions I mentioned in my first post are https://rebrickable.com/mocs/MOC-41774/G...herr-l550/ and a bigger Technic crane (2500+ parts, power functions, not published yet to Rebrickable, I hope it will be soon). I can share both of them with forum members if for some reason you would be interested

(2020-05-26, 7:58)Jaco van der Molen Wrote: What version of LPub3D do you use? I do not experience that many crashes. In fact, almost none.

I used the latest CI build from Github. It is true though that it crashes more than builds from some time ago.

(2020-05-26, 7:58)Jaco van der Molen Wrote: You say "LPub3D default settings should follow current Lego visual language". Why?

Because it would make our generated instructions look more professional as they would look closer to the real thing. Studio currently doesn't do this. I also have a set of settings which (almost) achieve this goal, I am just saying it should be the default. It is a minor point though

(2020-05-26, 7:58)Jaco van der Molen Wrote: ... I add the metacommands for those manually to speed things up...

I also converged to a similar process, after doing all the ROTSTEP's in LDCad, which is fast, I try to add callout, rotation icon and other metas in a text editor not to wait for the LPub to render the page.

(2020-05-26, 7:58)Jaco van der Molen Wrote: You state that BUFEXCHG and REMOVE GROUP are hard to use. You are right about that. These are very complex and advanced features and hard to learn techniques.

I am not saying they are hard to learn. I am saying the require a lot of manual work and lead to bad patterns. For example, if you need to attach a cable from a motor to a battery box, you need to remove the whole motor subassembly and flatten it in the step the cable gets connected. Same goes for rotating parts of a model. I think this is due to poor design of these functions (I know they are about a century old, nevertheless).


(2020-05-26, 7:58)Jaco van der Molen Wrote: IMHO I think you expect too much of the software

That is my problem indeed Smile
Reply
RE: Instruction making rant
#14
Over the years I've made many instructions, small and large and I agree with most of your points. Yes, making (large) instructions can be a (needless) pain sometimes.
I think most of them stem from endless backwards-compatibility and a lack of organized teamwork between LDCad and LPub3D.

LDraw is an old format, and lots of things work, no offense, kinda old-fashioned. And a lot of things stem from concepts made 15-20 years ago. LDraw is very focused on backwards-compatibility and that's a good thing, don't get me wrong. But sometimes, it becomes too much and there just has to be drawn a line somewhere. For example, in the case of buffer-exchange: just throw it out the window and start with something new. Thing is, it takes ages to draw that line, if at all. I mean, how long did it take to finally get texture-mapping spec fully done and working  Tongue Not to mention that an 'LDraw 2.0' discussion pops up every now and then for years I feel like, but it never leads to anything except discussions. We still don't have any official snapping-metadata right?

So, everything just goes along as it used to. And now it's getting passed by newer initiatives like stud.io or mecabricks. They're more modern, easier to work with, have a lower learning curve and have all kinds of fancy new features. Sure, it's certainly not as flexible as LDCad + LPub3D and that's the reason I still use that combination for everything I do, but it's not hard to imagine that with time there will be more feature-parity.

I've used LDraw for instructions for years and I see no reason to stop doing that for the years to come. But, I am used to it. I don't know any better. I know all the ins and outs, my workflow is 'perfected'. But it's also not hard to imagine that, as things currently go, it'll end at some point and I just have to move on to something else if things don't change.

But it's certainly not all hell and damnation. There is great improvement too. LPub3D has made some great progressions last years when Trevor took over the code. Compared to the old LPub4 it's miles better and I can't imagine using LPub 4 nowadays. LDCad brought new life into the LDraw CAD world, with fancy features and good support. This is not meant as a rant or anything, don't get me wrong. I love LDraw and it's all volunteering work of course and I have nothing to complain. The work that everybody puts into it is amazing.
Reply
RE: Instruction making rant
#16
(2020-05-26, 20:26)Merlijn Wissink Wrote: For example, in the case of buffer-exchange: just throw it out the window and start with something new.

Well, none of these META commands are official. Buffer exchange, for example, came from MLCad. Nothing is stopping someone from creating a new instruction language using LDraw as a base. The problem is that you have to do the legwork and actually create the program to go along with it and this is where things fall apart. I look forward to the day that another Kevin Clague comes along, has a need, and creates the successor to LPub.
Reply
RE: Instruction making rant
#18
(2020-05-26, 20:57)Orion Pobursky Wrote: Well, none of these META commands are official. Buffer exchange, for example, came from MLCad. Nothing is stopping someone from creating a new instruction language using LDraw as a base. The problem is that you have to do the legwork and actually create the program to go along with it and this is where things fall apart. I look forward to the day that another Kevin Clague comes along, has a need, and creates the successor to LPub.

The development of LPub3D indeed has come to a hold.
Has anyone heard from Travor Sandy lately?
Jaco van der Molen
lpub.binarybricks.nl
Reply
RE: Instruction making rant
#21
(2020-05-26, 20:26)Merlijn Wissink Wrote: So, everything just goes along as it used to. And now it's getting passed by newer initiatives like stud.io or mecabricks. They're more modern, easier to work with, have a lower learning curve and have all kinds of fancy new features. Sure, it's certainly not as flexible as LDCad + LPub3D and that's the reason I still use that combination for everything I do, but it's not hard to imagine that with time there will be more feature-parity.

With Studio at least, there's a serious caveat to go along with this assessment. When I started using it, I also thought it was the panacea it's often said to be. But before long, I ran into a pretty firm wall where I just couldn't go further with the program, because I'd either reached the limits of its capability, or needed a feature that simply does not work (*ahem*flexible parts*cough*). Combining those things with Studio's essentially closed-source nature, I just wasn't able to do enough poking around under the hood the way you can with a true LDraw program.

There seems to be a good-sized community of people using Studio who are in a similar boat. Many of them are not computer experts or developers at all and are attracted by Studio's robust feature set and user-friendly interface. They're often vaguely aware of LDraw but understand it to be a rather arcane, inaccessible system. But the problems and questions with Studio that arise are almost invariably ones that LDraw has already solved, and solved powerfully. So a lot of these users begin, reluctantly at first, turning from Studio to LDCad or LPub, rather than the other way around. And I think a fair number start to see that LDraw actually can be accessible, perhaps much more so than Studio, especially if you need to solve a problem yourself rather than waiting for someone else to do it.

But, your point is well taken that, if Studio does get an influx of interest and effort in its development, with the intent of making it a really top-tier piece of software, it could be better positioned to "corner the market" than trusty ol' LDraw.
Reply
RE: Instruction making rant
#25
(2020-05-26, 20:26)Merlijn Wissink Wrote: LDraw is an old format, and lots of things work, no offense, kinda old-fashioned. And a lot of things stem from concepts made 15-20 years ago. LDraw is very focused on backwards-compatibility and that's a good thing, don't get me wrong. But sometimes, it becomes too much and there just has to be drawn a line somewhere. For example, in the case of buffer-exchange: just throw it out the window and start with something new.

You know, I've often wondered why buffer exchange was such an awkward system. But then, I'm not a developer, so I don't always understand what it takes to do some of these things. Maybe it had to be this way, at least back then?

But yeah, it's not hard to envision something new. I can imagine a fairly simple set of commands that are easier for the user to grasp, and perhaps more targeted to specific use cases.

For the common problem of hovering parts, I feel like you'd just need something that affects the next line only, like:
0 !FLOAT [0 -20 0 1 0 0 0 1 0 0 0 1]
1 15 0 0 0 -[font=Courier New]1 0 0 0 1 0 0 0 -1 3001.dat

[/font]So the FLOAT command would provide a temporary pos/ori matrix, which would be applied to the part in the following type 1 line, up until the next STEP command. After that, it would be drawn in its normal position.

For parts that need to hover for more than one step, you could either devise a BEGIN and END system, or just add a parameter [n] to the FLOAT line, telling it to use that matrix for the next n steps. (And maybe a negative [n] could mean to hover until step number n is reached.)

You could also include a color reference in the FLOAT line, to allow the part to temporarily be shown in a different color, or even reference a different subfile—in short, an entire type 1 line to be used temporarily. And a good editing program could allow the option to automatically draw arrows or lines from the float position to the fixed location.

Now, for the other use case, of hiding the main model while focusing on a sub-build, you could use the existing CLEAR meta, and then add an UNCLEAR command, which would re-draw everything that had been erased by the previous CLEAR command. (Or you could use different names for these commands, like HIDE_ALL and UNHIDE_ALL.)

Again, it's easy to envision, but maybe hard to put into practice. I wouldn't be surprised if the way to do this behind the scenes is exactly what buffer exchange already does. But the syntax on the front end might be something a little more meaningful for the less-experienced user…or the ambitious MOCer who just want to create some kickass building instructions for his latest mecha or NCS masterpiece!  Wink
Reply
RE: Instruction making rant
#27
(2020-05-27, 3:14)N. W. Perry Wrote: For parts that need to hover for more than one step, you could either devise a BEGIN and END system, or just add a parameter [n] to the FLOAT line, telling it to use that matrix for the next n steps. (And maybe a negative [n] could mean to hover until step number n is reached.)

A very minor nitpick: I don't think [n] would be a good idea, as it is hardcoding, which we are trying to get rid of.
Reply
RE: Instruction making rant
#29
(2020-05-27, 16:01)Daniel R Wrote: A very minor nitpick: I don't think [n] would be a good idea, as it is hardcoding, which we are trying to get rid of.

What would be a better way?
Reply
RE: Instruction making rant
#31
(2020-05-27, 16:22)N. W. Perry Wrote: What would be a better way?

I described my vision (which is similar yours) in the following message. I am not saying it is the way, but I think it is easier to implement in LDCad and applies to more situations. On the other hand, it requires more boilerplate (all these group definitions) and maybe it is a bit less logical (because it requires first to place part in a wrong (temporary) location and only then move it to the correct location).

Specifically, I dislike the number of steps suggestion because steps order and count can change and you would need to correct all these numbers.
Reply
RE: Instruction making rant
#32
(2020-05-27, 16:32)Daniel R Wrote: I described my vision (which is similar yours) in the following message. I am not saying it is the way, but I think it is easier to implement in LDCad and applies to more situations. On the other hand, it requires more boilerplate (all these group definitions) and maybe it is a bit less logical (because it requires first to place part in a wrong (temporary) location and only then move it to the correct location).

The MOVE GROUP meta, you mean? Yes, I do see how that could apply to the same situation. But one of things I was thinking of with FLOAT is that it very simply addresses the common need to hover a single part. I actually took the presumption the "applies to more situations" would be objectionable rather than desirable, because as you note, it leads to fairly convoluted syntax situations, which is something we want to get away from with buffer exchange.

That being said, if you wanted to float multiple parts, you could always place a submodel in the following type 1 line. Or to make use of LDCad groups, perhaps there's a way to reference a group in a type 1 line—but another presumption I made (and didn't say out loud) is that we'd want to limit ourselves to one ref line per part used (to avoid having to adjust the parts list/BOM, etc.). With buffer exchange, you have to reference each part twice (or more).

So perhaps that could be another parameter in the FLOAT line itself—i.e., "float the next part referenced and any group it's part of"?

Quote:Specifically, I dislike the number of steps suggestion because steps order and count can change and you would need to correct all these numbers.

Yes, of course either the software or the user would have to keep track of that. Of course, the parameter would be configurable, so at the end of your workflow you could easily adjust a part's float settings. Anyway, I think the general preference would be towards including an option and letting the user disable it if need be, rather than just denying the option in the first place.

To be sure, perhaps the parameter argument is not the best solution. Would your MOVE GROUP command have some way to handle multi-step hovering, or would it just not allow for this possibility?
Reply
RE: Instruction making rant
#33
(2020-05-27, 16:55)N. W. Perry Wrote: I actually took the presumption the "applies to more situations" would be objectionable rather than desirable

That is correct. Nevertheless, there should be some mechanism for all use cases. Maybe there should be different mechanisms, I don't know. These use cases are:
  • Simple hovering of parts used in this step [Image: S8uIABU.png]
  • Movement of parts attached some time ago [Image: HT5kQIb.png]
  • Connection of flexible parts ends
Unfortunately, sometimes you need to rotate of move several parts which were not a submodel and we not attached in a single step. I am not saying that this should be done using group. In fact, maybe my suggested solution should not support multi-part groups at all. Indeed, this can be done by creating (automatically) one single-part group per part being moved. I only suggested LDCad groups as a way to reference previously added parts.

(2020-05-27, 16:55)N. W. Perry Wrote: we'd want to limit ourselves to one ref line per part used (to avoid having to adjust the parts list/BOM, etc.). With buffer exchange, you have to reference each part twice (or more)

I don't quite understand you here, sorry. Perhaps you could elaborate a little bit? 
But yes, my suggestion implies that parts are only moved not added, so no new parts appear in the PLI of the step with movement and the BOM counts should be correct.

(2020-05-27, 16:55)N. W. Perry Wrote: Would your MOVE GROUP command have some way to handle multi-step hovering, or would it just not allow for this possibility?

Yes. My suggestion is that you first add you part in the hovering position (and it is counted for that step's part list), then you add a step or a number of steps (maybe even finish this submodel and go to the outer one), then you decide that part should be moved, then you switch to "move mode" of LDCad and move the part as if you were just adjusting its original position. LDCad then would add a group definition to the step the part originally appeared and a MOVE GROUP meta to the current step. When you would go to some following steps, LDCad would keep track of all MOVE GROUP metas and display the part in its correct (updated) location, very similar to the way it currently handles buffer exchange.

(2020-05-27, 16:55)N. W. Perry Wrote: Yes, of course either the software or the user would have to keep track of that. Of course, the parameter would be configurable, so at the end of your workflow you could easily adjust a part's float settings

Maybe you could explain how that interface could look?
Reply
RE: Instruction making rant
#36
(2020-05-27, 17:38)Daniel R Wrote:
  • Movement of parts attached some time ago
  • [Image: HT5kQIb.png]
  • Connection of flexible parts ends

This can be done with REMOVE GROUP using MLCad Group meta.

See my old tutorial on that:
https://sites.google.com/site/workingwithlpub/general/advanced-techniques/metacommands/remove-group

And thread here: https://forums.ldraw.org/thread-22216.html
Jaco van der Molen
lpub.binarybricks.nl
Reply
RE: Instruction making rant
#39
(2020-05-27, 19:33)Jaco van der Molen Wrote: This can be done with REMOVE GROUP using MLCad Group meta.

I know of that command and I did use it in my instruction (once again thank you for your tutorials!). The problems with REMOVE GROUP are that it is not supported in LDCad, it is not possible to remove a group from a submodel and you are required to copy all the parts after you remove something. All in all, REMOVE GROUP requires too much manual labor, so that you try to avoid it if possible (at least I do), that's why I am suggesting to design some alternative
Reply
RE: Instruction making rant
#42
(2020-05-27, 17:38)Daniel R Wrote: That is correct. Nevertheless, there should be some mechanism for all use cases. Maybe there should be different mechanisms, I don't know. These use cases are:
  • Simple hovering of parts used in this step
  • Movement of parts attached some time ago
  • Connection of flexible parts ends

Yep, all of these would be handled by my imaginary FLOAT command. :-) Let's say that we allow a complete type 1 line to follow the meta, plus an optional step parameter, and is followed by another type 1 line; so:

0 !FLOAT <color> x' y' z' a' b' c' d' e' f' g' h' i' <file> (n)
1 <color> x y z a b c d e f g h i <file>

For simple hovering, you'd just change the x'y'z' triplet in the float line (the position).

For movement of parts attached earlier, change the position (x'y'z') or orientation (a'…i') matrix in front of each such part. To un-rotate them at a certain step, enter a negative number for n, so if the parts are moved into position in step 32, then enter -32 for n.

(A disadvantage is that this only allows for parts to be moved or rotated once. Assigning some kind of ID to each FLOAT command could be a way around that.)

For connecting flexible part ends, you'd provide a different file reference in the FLOAT line. So if you wanted a 12L flex axle, you'd reference 32200.dat in the FLOAT line, and in the following line use your LDCad path reference (say, "technicFlexAxle-1.ldr").

Quote:Unfortunately, sometimes you need to rotate of move several parts which were not a submodel and we not attached in a single step. I am not saying that this should be done using group. In fact, maybe my suggested solution should not support multi-part groups at all. Indeed, this can be done by creating (automatically) one single-part group per part being moved. I only suggested LDCad groups as a way to reference previously added parts.

Yeah, as you see above, this would be handled by putting the same -n in front of each part wherever it's added. A good editing program could recognize all parts with the same -n and allow you to change them all at once.

Quote:I don't quite understand you here, sorry. Perhaps you could elaborate a little bit?

With buffer exchange, you add each hovering part to the model twice: once in its hovering position, and again in its final one. As you've noted, this throws off the count for that part in the PLI/BOM, requiring further commands to offset it. With FLOAT, you add the part only once, and just modify its position (etc.) temporarily.

Quote:Yes. My suggestion is that you first add you part in the hovering position (and it is counted for that step's part list), then you add a step or a number of steps (maybe even finish this submodel and go to the outer one), then you decide that part should be moved, then you switch to "move mode" of LDCad and move the part as if you were just adjusting its original position. LDCad then would add a group definition to the step the part originally appeared and a MOVE GROUP meta to the current step. When you would go to some following steps, LDCad would keep track of all MOVE GROUP metas and display the part in its correct (updated) location, very similar to the way it currently handles buffer exchange.

Got it. That's similar to how FLOAT could work, if you put in some kind of ID. Maybe not as complex as "move mode", but perhaps also not as powerful.

Quote:Maybe you could explain how that interface could look?

Well, if we take the existing part properties dialog in LDCad, imagine a new "float" panel (or tab) in that dialog. You'd have a checkbox to enable "float", which inserts the meta command. That could invoke a new matrix, color reference, and part reference field in the dialog, where'd you enter the floating values. Also, imagine two additional checkboxes, either "Float for next _ steps" or "Float until step number _", which adds the n parameter.

At the same time, you'd probably want some way to visually edit the float position/orientation, perhaps by invoke "float" mode with a hotkey or menu command, or from the editing compass, or perhaps up with normal and nested modes. Maybe the part would show in a sort of transparent, "ghost-like" way as you move it around in float mode.

Now of course, let me be clear that I'm going about this completely backwards by thinking about the end result rather than how it's actually achieved, so I really don't know how easy this would actually be to pull off. Shy But the main thing here is to look at the problem of buffer exchange and how it could be made more understandable by the user. Theoretically, you could just keep using the exact buffer exchange method "under the hood" and just change how the user interacts with it, but I feel like FLOAT has the advantage of requiring far fewer changes in the code.
Reply
RE: Instruction making rant
#49
(2020-05-27, 22:14)N. W. Perry Wrote: Assigning some kind of ID to each FLOAT command could be a way around that.
Exactly. That is what I was aiming for with groups.

(2020-05-27, 22:14)N. W. Perry Wrote: Well, if we take the existing part properties dialog in LDCad, imagine a new "float" panel (or tab) in that dialog. You'd have a checkbox to enable "float", which inserts the meta command. That could invoke a new matrix, color reference, and part reference field in the dialog, where'd you enter the floating values. Also, imagine two additional checkboxes, either "Float for next _ steps" or "Float until step number _", which adds the n parameter.

At the same time, you'd probably want some way to visually edit the float position/orientation, perhaps by invoke "float" mode with a hotkey or menu command, or from the editing compass, or perhaps up with normal and nested modes. Maybe the part would show in a sort of transparent, "ghost-like" way as you move it around in float mode.

The only thing you did not address is that the number n needs to be (manually) changed if you insert a step in the middle. Therefore, perhaps, instead of hardcoding the step number one should insert some kind of marker in the target step... And here, after this change, we would be describing roughly the same system, with differences in whether to use a new meta for ID or reuse the group meta and where to describe modified part position. Both of them are very minor ones
Reply
RE: Instruction making rant
#55
(2020-05-28, 13:43)Daniel R Wrote: The only thing you did not address is that the number n needs to be (manually) changed if you insert a step in the middle.

Why would it have to be changed manually? The program could automatically account for step inserts that affect any active float commands (and whether it does so could be a user-configurable option). So the reason I don't address it is that the software would. (EDIT: This is expanded on in another reply.)

That's not to say I still think this is the best way, as it's clear there are advantages to the ID and target method. I guess I'm just not understanding the drawback about manual editing. After all, everything in the code needs to be edited if it's changed, but if for example we move or rotate a part, we rely on the software to handle it, we don't worry that we'd have to manually edit the matrix! :-)
Reply
RE: Instruction making rant
#40
I proposed a BUFFER END a long time ago already: https://github.com/trevorsandy/lpub3d/issues/43
Never really led anywhere.
Reply
RE: Instruction making rant
#44
(2020-05-27, 20:24)Merlijn Wissink Wrote: I proposed a BUFFER END a long time ago already: https://github.com/trevorsandy/lpub3d/issues/43
Never really led anywhere.

I'm having trouble understanding the problem as described. It says "everything after the start command is placed in the buffer"—but really, it's everything before the start (STORE) command that's buffered, no? Then when you RETRIEVE it, that's basically like the end command already. Or am I getting something mixed up?
Reply
RE: Instruction making rant
#45
(2020-05-27, 22:37)N. W. Perry Wrote: I'm having trouble understanding the problem as described. It says "everything after the start command is placed in the buffer"—but really, it's everything before the start (STORE) command that's buffered, no? Then when you RETRIEVE it, that's basically like the end command already. Or am I getting something mixed up?

It's been a little while since I last used buffer exchange, but I'm pretty sure everything after the STORE command is what is buffered.

In any case, an example for the problem described there. Imagine you're making instructions for which need a part in a temporary positions for a certain number of steps. Everything after the STORE command will be removed once RETRIEVE is called. So, if you add temporary part in step 20, then in steps 21-24 you add other ('normal') parts and then call RETRIEVE in step 25 to place the temporary part in the final positions, all the other parts in steps 21-24 will be removed too, because the STORE command never ends (until RETRIEVE).

Due to this limitation, buffer exchange cannot work through multiple steps. If you want to do that with the current implementation, you'd have to repeat the same STORE/RETRIEVE over multiple steps.
Reply
RE: Instruction making rant
#46
(2020-05-28, 8:45)Merlijn Wissink Wrote: Due to this limitation, buffer exchange cannot work through multiple steps. If you want to do that with the current implementation, you'd have to repeat the same STORE/RETRIEVE over multiple steps.
As you say, it does work but you must "re-add" all parts between store and retrieve after the retrieve (tedious I agree). What really annoys me is "submodel wih moving parts" (eg. submodel where you must push pins after attaching to the main model), I have no other solution than to make two different submodels Sad
Reply
RE: Instruction making rant
#47
(2020-05-28, 11:51)Philippe Hurbain Wrote: As you say, it does work but you must "re-add" all parts between store and retrieve after the retrieve (tedious I agree). What really annoys me is "submodel wih moving parts" (eg. submodel where you must push pins after attaching to the main model), I have no other solution than to make two different submodels Sad

I also only know this way.
If nothing goes right, go left.
Reply
RE: Instruction making rant
#51
(2020-05-28, 11:51)Philippe Hurbain Wrote: As you say, it does work but you must "re-add" all parts between store and retrieve after the retrieve (tedious I agree). What really annoys me is "submodel wih moving parts" (eg. submodel where you must push pins after attaching to the main model), I have no other solution than to make two different submodels Sad

So the command would have to be placed in the submodel, and would apply indefinitely (n=0, perhaps)…then be released somehow in the containing model. Maybe a FLOAT | UNFLOAT pair would allow this, and it looks like you would need to use an ID system to keep track of them. This could be similar to how LDCad handles group IDs (with local and global ones), so that they can be recursive.

My first thought was to make n take the form (a,b,c…), where each member in the set refers to a higher containing model. So if you had a sub-submodel, you could float a part in the sub-submodel, as well as in its containing submodel, then release it in the main model by having a setting of (0,0,2). (The 2 means the part is released in the step after the submodel is placed.)

But that method wouldn't allow for multiple instances of a submodel. With UNFLOAT, as with FLOAT, it would apply only to the next type 1 line, so it would release the floating part only in that instance of the submodel.
Reply
RE: Instruction making rant
#52
(2020-05-28, 15:32)N. W. Perry Wrote: My first thought was to make n take the form (a,b,c…), where each member in the set refers to a higher containing model. So if you had a sub-submodel, you could float a part in the sub-submodel, as well as in its containing submodel, then release it in the main model by having a setting of (0,0,2). (The 2 means the part is released in the step after the submodel is placed.)

But that method wouldn't allow for multiple instances of a submodel. With UNFLOAT, as with FLOAT, it would apply only to the next type 1 line, so it would release the floating part only in that instance of the submodel.

This syntax also does not allow to edit instruction easily. Suppose you move some subassembly into a new subfile. Then you would have to think whether to edit this tuples or not. That is manual editing, which is error-prone and time-consuming. I suggest marking the target step instead of hard-coding numbers in the first step.
Reply
RE: Instruction making rant
#53
(2020-05-28, 15:53)Daniel R Wrote: This syntax also does not allow to edit instruction easily. Suppose you move some subassembly into a new subfile. Then you would have to think whether to edit this tuples or not. That is manual editing, which is error-prone and time-consuming. I suggest marking the target step instead of hard-coding numbers in the first step.

On the other hand, at least it's edit-able. If you get into recursive IDs, then manual editing—or rather, user comprehensibility—get a bit muddier.

But why would it have to be manual editing? There's nothing about this idea that says it has to be; I'm always assuming that editing programs would (continue to) provide a good user interface to the underlying commands. At the same time, it is a goal to have the syntax be more human-digestible than the current system of buffer exchange. And of course, manual editing will still always be an option; and if that's the case, I think recursive IDs would be far more error-prone and time consuming to manually edit than simple command line parameters. Wink

Be that as it may, it does seem clear that ID'd command pairs are necessary once we get into submodels, so the tuples would probably never become necessary. (Only unless you wanted to offer the option of a simpler syntax for when recursive IDs aren't necessary. To that end, the ID itself could be an optional parameter; if absent, the program would use the command line parameter to release the float, and if present, the software would automatically generate a paired UNFLOAT command and use that instead. Although that may be a bit like installing a steam engine in an automobile as a fallback for the internal combustion engine!)
Reply
RE: Instruction making rant
#54
(2020-05-28, 16:37)N. W. Perry Wrote: But why would it have to be manual editing? There's nothing about this idea that says it has to be; I'm always assuming that editing programs would (continue to) provide a good user interface to the underlying commands.

By manual I meant "requiring human intervention", not "requiring to edit text file without visual editor". Suppose you have a FLOAT with n=3. Then you insert a step after this one. Now the part unfloats in the step previous to the original one. And it needs a human to correct that.
I can't think how a good editor would help here (but maybe it could! would you offer an explanation? Smile
Reply
RE: Instruction making rant
#56
(2020-05-28, 16:47)Daniel R Wrote: By manual I meant "requiring human intervention", not "requiring to edit text file without visual editor". Suppose you have a FLOAT with n=3. Then you insert a step after this one. Now the part unfloats in the step previous to the original one. And it needs a human to correct that.
I can't think how a good editor would help here (but maybe it could! would you offer an explanation? Smile

I imagine the program would have to store a list of each float command, the step number in which it's placed, and the step number in which it's released. So if a float command is placed in step s and has n=3, that means it's released in step number <s+2>, or <s+(n-1)>. This is how the editor would know whether to draw the part in its floating position, or its permanent one, according to the step number currently being viewed.

Whenever a step is inserted, the program would check the list of float commands and see whether the new step falls within any range of <s> and <s+(n-1)>. If so, it would automatically increment n, or ignore it, or ask the user, according to the configured preference.
Reply
RE: Instruction making rant
#50
(2020-05-28, 8:45)Merlijn Wissink Wrote: It's been a little while since I last used buffer exchange, but I'm pretty sure everything after the STORE command is what is buffered.

And of course, the fact that it's not clear to a bunch of us which way it works is exactly why the topic's come up. :-)

For whatever it's worth, the MLCad spec is a bit vague, but describes it this way:

The buffer command either stores an image or retrieves a stored image. The image is taken from the actual view and when restored put in there.
[…]
You first create the model completely without the [hovering part]. Then you save an image of the current view, and after that you put the [hovering part] above the model. When the user continues drawing you retrieve the previously saved image and redraw the [hovering part] in it’s[sic] final position.

In his tutorial, which I'm pretty sure is where I first learned about buffer excahnge, Willy says:

MLCad allows to save up to 26 display states during the View Mode and to retrieve them at a later moment. Selecting A from the drop-down box [to insert the STORE command] and hitting OK will save the display state up to this point in an internal memory named A.

But, I should add that I've never used either MLCad or LPub, and other programs might process the buffer exchange commands a different way than by placing a saved view state into a memory buffer. And of course, from the user's perspective, the real action is what happens between the commands, and it is the user's experience that we're exploring, after all!

Quote:In any case, an example for the problem described there. Imagine you're making instructions for which need a part in a temporary positions for a certain number of steps. Everything after the STORE command will be removed once RETRIEVE is called. So, if you add temporary part in step 20, then in steps 21-24 you add other ('normal') parts and then call RETRIEVE in step 25 to place the temporary part in the final positions, all the other parts in steps 21-24 will be removed too, because the STORE command never ends (until RETRIEVE).

Oh yes, I see what you mean now. I agree that it would be nice not to have to re-insert any parts, including the ones that are being moved. My FLOAT method would do that, since it only affects the next line. And it works similarly to your END idea, except that FLOAT automatically lasts for just a single step, unless you specify otherwise with the n parameter.
Reply
RE: Instruction making rant
#57
(2020-05-28, 14:45)N. W. Perry Wrote: Oh yes, I see what you mean now. I agree that it would be nice not to have to re-insert any parts, including the ones that are being moved. My FLOAT method would do that, since it only affects the next line. And it works similarly to your END idea, except that FLOAT automatically lasts for just a single step, unless you specify otherwise with the n parameter.

I think no matter the implementation or how it works, there must be an explicit end to whatever 'store' command is being used. Implicit ends are just too vague and keep too many edge cases open. For example, what *if* you actually want to hide/move all parts placed in multiple previous steps?

I feel like people are overthinking it a bit. What does buffer exchange (or, at least a replacement for it, whatever you wanna call it) need to do?
  • Simply put: it needs to place parts in temporary positions, with the ability to either hide them (arrows, helper parts) or place them in a final position.
What are the major limitations that the current implementation has (without hacking or abusing the system of course)?
  • It doesn't work through multiple steps.
  • It doesn't work through submodels.
  • A part has only two states: start and end (you can't have a part go through multiple positions until final position).
How can this be solved? Simply place both all positions of the part(s) together in the same command and give the command an (optional?) name to call. This takes care of all the above points and is much more robust (assuming good software implementation of course).

Let's make an example. I'm just using semi-random terminology here, probably can be improved, but it's not about the specifics here Wink

Code:
0 BUFFER DEF START "Name"
// parts
0 BUFFER POS
// parts
0 BUFFER POS
// parts
0 BUFFER DEF END

The idea here is, a BUFFER command (I still don't like the name, but I can't come up with a better one) has a required START and END. If there are no POS arguments within the buffer, this means that once the BUFFER is 'retrieved' all parts disappear, e.g. for using arrows or helper parts. The POS commands are used to place bricks in their next or final position. There can be multiple POS commands for various positions. There is also a name for the buffer definition. I guess this can be either an explicit string name, or just an integer ID or even A/B/C... like current buffer exchange.

How to use it further on the model? I can think of various options. For example, simply:

Code:
0 BUFFER "Name" NEXT

This moves the previously defined buffer to its next position (the next POS command, if any).

This takes care of all the above defined points:
  • Parts can be placed in temporary positions, and they can be moved to another positions, or disappear.
  • It works through multiple steps, because there is an explicit start and end and a name to call the buffer.
  • It works through submodels, because there is a name to call the buffer and the next positions are stored within the buffer (no need to rely on any meta-steps within the submodel that then need to be hidden or whatever)
  • A part can have multiple states instead of one or two.
  • And as a bonus, because all positions are defined together, it's very simple (relatively) to edit any of the parts within the buffer because they are grouped together.
Reply
RE: Instruction making rant
#58
I like the idea with NEXT. But would you allow the parts in between the POS sections to be different (like different count or different references)? Because if so, what would you display in the PLI (and on which step)?
Reply
RE: Instruction making rant
#59
(2020-05-31, 12:38)Daniel R Wrote: I like the idea with NEXT. But would you allow the parts in between the POS sections to be different (like different count or different references)? Because if so, what would you display in the PLI (and on which step)?

My idea was that the PLI would be based on the first (mandatory) set of pieces (thus, the ones before any optional POS commands). Any new pieces that appear in extra POS commands should be ignored in the PLI. They shouldn't be there in the first place anyway, but it can be gracefully handled by simply not showing them in PLI (they will of course show up in the assembly).

If you're hinting towards adding pieces to an existing buffer that need to be replaced together (e.g. you're adding a door to a model, then attach pieces to the door in the next step and only then close the door in the third step), that is indeed something that I honestly haven't thought about in my initial post. That's a good point  Undecided 

I think the most logical way to solve that with the idea I posted above is by simply using multiple buffer definitions.

Thus, something like this:
Code:
0 BUFFER DEF START A
// Door in open position
0 BUFFER POS
// Door in closed position
0 BUFFER DEF END

0 STEP

0 BUFFER DEF START B
// Parts attached to open door
0 BUFFER POS
// Parts attached to closed door
0 BUFFER DEF END

0 STEP

0 BUFFER A NEXT
0 BUFFER B NEXT

Or, maybe by extending the buffer definition in some way, maybe something like this:

Code:
0 BUFFER DEF START A
// Door in open position
0 BUFFER POS
// Door in closed position
0 BUFFER DEF END

0 STEP

0 BUFFER EXT START A
// Parts attached to open door
0 BUFFER POS
// Parts attached to closed door
0 BUFFER EXT END

0 STEP

0 BUFFER A NEXT


I personally like the first one more, because it leaves less room for error. Though, it does make me wonder how that would need to be implemented in CAD software, since it's difficult to place parts in their final positions, while the final position of the previous buffer isn't visible yet (if that sentence makes sense, maybe I should make a visual example?). On the other hand, I don't know how much of an edge case this is, because I think most buffers will be used for simple stuff. On the other, other hand a more flexible buffer exchange like this with support for multiple positions of course might make more complicated buffer exchanges possible so...

If anyone has any good or better ideas, sure post them  Smile
Reply
RE: Instruction making rant
#60
(2020-05-31, 13:17)Merlijn Wissink Wrote: If anyone has any good or better ideas, sure post them  Smile

I have posted my suggested syntax in this topic. It is not ideal either as honestly is requires more boilerplate i.e. compared to the yours (and also I have not received any other comments but I'm sure there'll be other issues). But it addresses several issues I see here.

(2020-05-31, 13:17)Merlijn Wissink Wrote: They shouldn't be there in the first place anyway, but it can be gracefully handled by simply not showing them in PLI.

In my opinion that is not a good behaviors for an interface. If something should not be used, it should not be allowed by the compiler. And moreover, the syntax should not encourage you to write something which should not be used. Here you suggest that "// parts" are most likely Ldraw type 1 lines, that is, references. That allows to have different sets of references in different sections (which, again, I think should be prohibited by the compiler or LDCad). That's why I suggest a "MOVE GROUP" meta which is not a type 1 line and inherently does not allow to change parts used.

(2020-05-31, 13:17)Merlijn Wissink Wrote: (you're adding a door to a model, then attach pieces to the door in the next step and only then close the door in the third step)

That is the case I was thinking about, yes. However rare, I think it should be supported.

(2020-05-31, 13:17)Merlijn Wissink Wrote: I think the most logical way to solve that with the idea I posted above is by simply using multiple buffer definitions.

That is fine but bloats the code, requiring unnecessary many intermediate buffers in case there are many steps in between. Also making it very hard for manual editing.
Use of groups solves this, as it is allowed to add parts to existing group in many places (on different steps).

(2020-05-31, 13:17)Merlijn Wissink Wrote: Or, maybe by extending the buffer definition in some way, maybe something like this

That is essentially what I propose but again, without new type 1 lines with new positions, but with new command which only allows to set new position.

(2020-05-31, 13:17)Merlijn Wissink Wrote: I personally like the first one more, because it leaves less room for error.
I am not sure how Smile



I would also love to hear any suggestions and critics
Reply
RE: Instruction making rant
#63
(2020-05-31, 13:51)Daniel R Wrote: Here you suggest that "// parts" are most likely Ldraw type 1 lines, that is, references. That allows to have different sets of references in different sections (which, again, I think should be prohibited by the compiler or LDCad). That's why I suggest a "MOVE GROUP" meta which is not a type 1 line and inherently does not allow to change parts used.

Now that I look again, it may actually be the opposite problem: the parts are only placed in commented ("//') lines that would be ignored in programs not supporting the buffer metas. They are never explicitly placed in the model as type 1 lines, so would simply be missing if viewed in another program.

I agree that there should be one, and only one, type 1 line for each instance of a part or submodel (or group) in a model. This reduces code bloat from repeated type 1 lines, and also means the PLI would by default display the actual piece count.
[/quote]
Reply
RE: Instruction making rant
#62
(2020-05-31, 13:17)Merlijn Wissink Wrote: If you're hinting towards adding pieces to an existing buffer that need to be replaced together (e.g. you're adding a door to a model, then attach pieces to the door in the next step and only then close the door in the third step), that is indeed something that I honestly haven't thought about in my initial post. That's a good point  Undecided 

This is no problemo for FLOAT. The code would look like this:

Code:
0 !FLOAT [id=a]
// Door in open position
1 [door in closed position]

0 STEP

0 !FLOAT [id=b]
// Part attached to open door
1 [part attached to closed door]
0 !FLOAT [id=c]
// Part attached to open door
1 [part attached to closed door]

0 STEP

0 !UNFLOAT [a]
0 !UNFLOAT [b]
0 !UNFLOAT [c]

Obviously that's very bloaty, but that's why we have groups. So FLOAT should be able to reference a group just as well as a part or submodel, and thus eliminate all those extra FLOAT commands (but replace them with grouping metas). That would look like this:

Code:
0 !FLOAT
// [color] [matrix] [group id=a] <-- matrix here is door group in open position
0 GROUP_NEXT [id=a] <-- simplified pseudo-code for LDCad's group meta
1 [door in closed position]

0 STEP

0 GROUP_NEXT [a]
1 [part attached to door]
0 GROUP_NEXT [a]
1 [part attached to door]

0 STEP

0 !UNFLOAT [group id=a]
Reply
RE: Instruction making rant
#61
(2020-05-31, 7:45)Merlijn Wissink Wrote: I think no matter the implementation or how it works, there must be an explicit end to whatever 'store' command is being used. Implicit ends are just too vague and keep too many edge cases open. For example, what *if* you actually want to hide/move all parts placed in multiple previous steps?

I agree. I think it's clear by now that an END is necessary to allow nesting across submodels, etc. The question remaining is simply what the fallback behavior would be if a START is added without an END, and/or what the default location of an END would be for programs that automatically generate the pair.

Quote:I feel like people are overthinking it a bit. What does buffer exchange (or, at least a replacement for it, whatever you wanna call it) need to do?
  • Simply put: it needs to place parts in temporary positions, with the ability to either hide them (arrows, helper parts) or place them in a final position.
What are the major limitations that the current implementation has (without hacking or abusing the system of course)?
  • It doesn't work through multiple steps.
  • It doesn't work through submodels.
  • A part has only two states: start and end (you can't have a part go through multiple positions until final position).

Well, I'm not sure whether I believe in the concept of over-thinking. Wink But what is possible is that some of our previous thoughts can now be dismissed. I can say that your list of considerations is pretty much identical to mine. I would also add the following two requirements for what the replacement would need to do:
  • There should only be as many file references (type 1 lines) as are actually used in the model
  • It should be easily understandable to the user what the syntax is and how the commands work in the code
What other avenues have we considered that can now be discounted?

Quote:How can this be solved? Simply place both all positions of the part(s) together in the same command and give the command an (optional?) name to call. This takes care of all the above points and is much more robust (assuming good software implementation of course).

Yes, again I fully agree. This is how my idea of FLOAT works.

Quote:Let's make an example. I'm just using semi-random terminology here, probably can be improved, but it's not about the specifics here Wink

Code:
0 BUFFER DEF START "Name"
// parts
0 BUFFER POS
// parts
0 BUFFER POS
// parts
0 BUFFER DEF END

Same example using my envisioned syntax:

Code:
0 !FLOAT [id=x] [color] [matrix] [file reference]
1 [file reference line-part or submodel]

0 !FLOAT [x] [new color] [new matrix] [new file reference]

0 !FLOAT [x] [new color] [new matrix] [new file reference]

0 !UNFLOAT [x]

No reason it couldn't be done your way, where the arguments to FLOAT are a separate, commented line rather than command line parameters. And the parameters could be mutually optional, so you provide only what's changed (position, or color, or file reference) instead of the whole line.

Quote:The idea here is, a BUFFER command (I still don't like the name, but I can't come up with a better one)…

Why not FLOAT? Possible conflict with the mathematical meaning?

Quote:…has a required START and END. If there are no POS arguments within the buffer, this means that once the BUFFER is 'retrieved' all parts disappear, e.g. for using arrows or helper parts. The POS commands are used to place bricks in their next or final position. There can be multiple POS commands for various positions. There is also a name for the buffer definition. I guess this can be either an explicit string name, or just an integer ID or even A/B/C... like current buffer exchange.

How to use it further on the model? I can think of various options. For example, simply:

Code:
0 BUFFER "Name" NEXT

This moves the previously defined buffer to its next position (the next POS command, if any).

For my system, you'd just call a new FLOAT command on the same id, and provide whatever has changed in the arguments to that new command (new color, new rotation matrix, etc.). I would think you can even hide a part by specifying an invisible color.

Quote:This takes care of all the above defined points:
  • Parts can be placed in temporary positions, and they can be moved to another positions, or disappear.
  • It works through multiple steps, because there is an explicit start and end and a name to call the buffer.
  • It works through submodels, because there is a name to call the buffer and the next positions are stored within the buffer (no need to rely on any meta-steps within the submodel that then need to be hidden or whatever)
  • A part can have multiple states instead of one or two.
  • And as a bonus, because all positions are defined together, it's very simple (relatively) to edit any of the parts within the buffer because they are grouped together.

This is good, we seem to be on the same page. My idea and yours work almost exactly the same way, the only difference is in our names for things. Smile
Reply
RE: Instruction making rant
#64
(2020-05-31, 18:54)N. W. Perry Wrote: Same example using my envisioned syntax:

Code:
0 !FLOAT [id=x] [color] [matrix] [file reference]
1 [file reference line-part or submodel]

0 !FLOAT [x] [new color] [new matrix] [new file reference]

0 !FLOAT [x] [new color] [new matrix] [new file reference]

0 !UNFLOAT [x]

Now I like this, with explicit UNFLOAT marker in the target step instead of step counting Smile With support for both parts and groups this is reasonably succinct and powerful.

Moreover, if I understand correctly that the first (and only) type 1 is describing the part in its final position, while all the FLOAT lines describe intermediate positions, this syntax solves the problem of compatibility with other editors which do not support this meta (that is a problem for BUFEXCHG, REMOVE GROUP and two other suggestions in this thread). I didn't think about it before, this is cool.

(2020-05-31, 18:54)N. W. Perry Wrote: And the parameters could be mutually optional, so you provide only what's changed (position, or color, or file reference) instead of the whole line.

I support making them optional. Also it would be a good thing to discourage users from actually changing reference and color. By the way, I can't find any reasonable use for change of color. Is there one? I am not saying it should not be supported.

After some thought I understood that it sometimes necessary to replace the reference: this is needed for flexible parts. Because moving path points by some FLOAT/MOVEGROUP would work only in simple cases, in more complex cases you would need different number of path points, therefore, new submodel. It is still not clear how the fallback code should be handled in case we allow to FLOAT individual path points.
Reply
RE: Instruction making rant
#65
(2020-06-02, 21:26)Daniel R Wrote: I support making them optional. Also it would be a good thing to discourage users from actually changing reference and color. By the way, I can't find any reasonable use for change of color. Is there one? I am not saying it should not be supported.

After some thought I understood that it sometimes necessary to replace the reference: this is needed for flexible parts. Because moving path points by some FLOAT/MOVEGROUP would work only in simple cases, in more complex cases you would need different number of path points, therefore, new submodel. It is still not clear how the fallback code should be handled in case we allow to FLOAT individual path points.

Inventing new metas might be fun, but these kinds of metas (begin end etc) are a nightmare to parse while reading LDraw content.

It is mentioned above the new meta should be able to reference groups, but personally I think it should be an extension on existing existing group mechanics.

This will make parsing the meta alot easier, even more so if you limit to a single one using a submeta.

e.g.

Code:
0 STEP
0 !SOMENEWMETA FLOAT [target=engineBlock] [pos=100 100 100] [color=4] [ori=1 0 0 0 1 0 0 0 1]
........
0 STEP
0 !SOMENEWMETA FLOAT [target=engineBlock]

Where "engineBlock" is a group name.

The first float 'overrides' position, color and rotation. Just use the parameters which are needed all others initialize with the current values.

The second float uses all default parameters, so it returns the group to its original place, color and rotation.

And if the thing you are floating is a single, once used reference, you could also do something like:

0 !SOMENEWMETA FLOAT [targetKind=ldrRef] [target=3001.dat] [pos=100 100 100] [color=4] [ori=1 0 0 0 1 0 0 0 1]

This implies that if omitted the targetKind parameter defaults to "group"

my 2cts
Reply
RE: Instruction making rant
#66
(2020-06-02, 22:12)Roland Melkert Wrote: Inventing new metas might be fun, but these kinds of metas (begin end etc) are a nightmare to parse while reading LDraw content.

This discussion may be confusing but I think it arrived to a one or two new metas (depending on whether to support only groups or groups and simple references too) which do not behave like a begin and end but only affect one next line.
Reply
RE: Instruction making rant
#67
(2020-06-02, 21:26)Daniel R Wrote: Moreover, if I understand correctly that the first (and only) type 1 is describing the part in its final position, while all the FLOAT lines describe intermediate positions, this syntax solves the problem of compatibility with other editors which do not support this meta (that is a problem for BUFEXCHG, REMOVE GROUP and two other suggestions in this thread). I didn't think about it before, this is cool.

Yes, exactly. With only one type 1 line per instance of the part, then with editors that don't support the meta, the worst case scenario is your model just displays as finished. It bothered me about buffer exchange that it hardcodes parts into the file that don't actually appear in the model.


Quote:I support making them optional. Also it would be a good thing to discourage users from actually changing reference and color. By the way, I can't find any reasonable use for change of color. Is there one? I am not saying it should not be supported.

I haven't thought of a reason for color, but somebody someday might want to be able to, and as it's just a single integer, it's not any trouble to include the possibility. And I can't immediately see a reason to specifically exclude the possibility; what would it break?

(Actually, there is one reason I thought of: use an invisible color to temporarily hide the part. But there are probably better ways to achieve this.)

Quote:After some thought I understood that it sometimes necessary to replace the reference: this is needed for flexible parts. Because moving path points by some FLOAT/MOVEGROUP would work only in simple cases, in more complex cases you would need different number of path points, therefore, new submodel. It is still not clear how the fallback code should be handled in case we allow to FLOAT individual path points.

Yes, flexible parts was the use case for changing the reference. I hadn't thought about using FLOAT commands inside flexible path subfiles, but I suppose you could. My first thought is that you would just have different subfiles for different states of the flexible part, but if we follow on to Roland's suggested structure, perhaps you could allow path caps and path points as possible target types for FLOAT.

As for the fallback, I think it would just continue to describe the part in its finished state. If you're using an editor that doesn't understand FLOAT, then you're already ignoring all but the final positions of things, so there'd be no need to provide fallback code for interim states of flexible parts.

(2020-06-02, 22:12)Roland Melkert Wrote: Inventing new metas might be fun, but these kinds of metas (begin end etc) are a nightmare to parse while reading LDraw content.

It is mentioned above the new meta should be able to reference groups, but personally I think it should be an extension on existing existing group mechanics.

This will make parsing the meta alot easier, even more so if you limit to a single one using a submeta.

That's helpful to know, since as I say, I don't necessarily understand all that goes into making these things work. I'm just able to picture how I'd like them to be. :-) But it did seem to me that having a single command would be easier to parse than keeping track of possibly-nested pairs of commands (like with multiple buffers currently).

It makes sense to build off the existing groups structure; since they are recursive, then FLOAT would be, too—you would still be able to have different float states across submodels, no? But I didn't want to assume that it would be directly based on LDCad, so I imagined the syntax as a similar but separate system.

Quote:The first float 'overrides' position, color and rotation. Just use the parameters which are needed all others initialize with the current values.

The second float uses all default parameters, so it returns the group to its original place, color and rotation.

"Override" is a good term to describe the purpose of the meta. Perhaps that could be its name?

I like the elegance of just omitting all parameters to return everything to its default. That supports the idea of making them optional; just include what you want to change. It also keeps the code tidy.

(2020-06-02, 23:44)Daniel R Wrote: This discussion may be confusing but I think it arrived to a one or two new metas (depending on whether to support only groups or groups and simple references too) which do not behave like a begin and end but only affect one next line.

I had one other meta in mind, to handle the HIDEALL scenario (where the main model is temporarily hidden to isolate a sub-build that is not a submodel). That doesn't necessarily have to be part of this line of inquiry, although perhaps it could exists as a second submeta to OVERRIDE.
Reply
RE: Instruction making rant
#68
(2020-06-02, 22:12)Roland Melkert Wrote:
Code:
0 STEP
0 !SOMENEWMETA FLOAT [target=engineBlock] [pos=100 100 100] [color=4] [ori=1 0 0 0 1 0 0 0 1]
........
0 STEP
0 !SOMENEWMETA FLOAT [target=engineBlock]

Where "engineBlock" is a group name.

The first float 'overrides' position, color and rotation. Just use the parameters which are needed all others initialize with the current values.

The second float uses all default parameters, so it returns the group to its original place, color and rotation.

And if the thing you are floating is a single, once used reference, you could also do something like:

0 !SOMENEWMETA FLOAT [targetKind=ldrRef] [target=3001.dat] [pos=100 100 100] [color=4] [ori=1 0 0 0 1 0 0 0 1]

This implies that if omitted the targetKind parameter defaults to "group"

my 2cts

Idea: Suppose you want to float a single instance of a multiple-used reference?

Perhaps it could be that if targetKind is omitted and target is not, then target is assumed to refer to a group name and the float command acts on that group. (Presumably a group ID could also be given, helpful if a group name is later changed.)

If targetKind and target are both omitted, then the float command acts on (and only on) the following type 1 line.

Alternatively (or additionally), there could be a targetKind value of "next" that would do the same thing.

And for targetKind=ldrRef, perhaps that could be assumed whenever the value of target ends with .ldr or .dat. What I'm getting at is that the targetKind parameter could often be omitted altogether, and its value determined by other context. That makes hand-editing a little quicker (and the targetKind parameter could always be auto-generated upon saving).


So in summary, what possible values for targetKind are there?
  • "group" (default if the value of target is a group name or ID)
  • "ldrRef" (default if the value of target ends with .ldr or .dat)—this acts on all instances of the specified part or submodel
  • "next" (default if target parameter is absent)—this acts on the following type 1 line only, and could also be extended to apply to path point or path cap metas if placed within a flexible content section
Others? Perhaps "step"—acting on any float-able objects up to the next STEP command? Indeed, this could conceivably replace ROTSTEP altogether. And if there are other LPub-type metas used, like callouts or sub-builds, they could also be positioned using float commands. (I know there's a difference between rotating the view and rotating the parts themselves, but perhaps the latter makes more sense for an editing tool anyway.)
Reply
RE: Instruction making rant
#26
(2020-05-26, 7:58)Jaco van der Molen Wrote: IMHO I think you expect too much of the software. We could never make official LEGO like instructions, but can get very close.

Perhaps I do expect too much of the software. But I'd like to have a usable and open alternative to Studio and I'd like to make the instruction making process easier and more appealing to new users.

(2020-05-26, 20:26)Merlijn Wissink Wrote: LDraw is an old format, and lots of things work, no offense, kinda old-fashioned. And a lot of things stem from concepts made 15-20 years ago. LDraw is very focused on backwards-compatibility and that's a good thing, don't get me wrong. 

Maybe I am wrong here, but I think we can allow more breaking changes than other areas (see python2), as instructions mostly do not have any dependencies and I think mostly are started as new projects. So it is more acceptable to introduce some new syntax. Again, maybe I am wrong here.

I tried reporting all the bugs to LPub3D github and suggesting minor edits but I think there are some design flaws which have to be addressed first. I would love to contribute to LDCad code but it is closed and I respect this Roland's decision. Still, if this changes I would gladly contribute there (for instance, I can do some minor features which are thought to be necessary).

When I read Roland's suggestion to support all LPub metas, I immediately pictured a new edit mode in LDCad, similar to view or nested mode, where steps represent instruction pages and you can combine 2d editing by dragging inventory and callout baloons, arrows, dividers and labels with 3d editing of the actual model and camera position. But then I thought that supporting all LPub3D commands would not be a good idea. Some of them are frustrating (see my comments about auto layout and relative element placement above) and some are leaky abstractions.

So I came to this forum because, as I understand, this is the place where the LDraw and LDCad development is planned. I think it would make sense to discuss this new syntax as I am not sure about the best design.

So while some parts of my first post are suggestions for the next LDCad version, namely
  • Some way to make the ASR/NSR indicator always visible
  • Make flexible part length visible inside the nested submodel
  • Support to change color bin contents based on current selected part and external configuration
  • Arrow generator

and some parts are suggestions to LDraw community, namely
  • Include arrows in the official library
  • Make convention to include the substitute part name in the subfile header (see arguments for this in the first post)

most of them are suggestions to discuss some new syntax.

The ability to store zoom and pan steps could be implemented as an extension to ROTSTEPs. Also this could be thought not as pan and zoom but as camera center and camera distance. For instance

Code:
0 ROTSTEP 23 45 0 ABS CENTER 1 2 10 ABS DISTANCE 200 ABS

or

Code:
0 ROTSTEP 0 0 0 REL CENTER 0 0 0 REL DISTANCE 20 REL

just to zoom in a little. Maybe this is a bad suggestion, but I think it would make sense to edit this things in a true 3D editor, not in some kind of instruction generating program (whatever that would be).

As for buffer exchange and remove group alternative, I think it should be less flexible.
Maybe it should reuse existing LDCad grouping capabilities, maybe like this

Code:
0 !LDCAD MOVE GROUP "group name" x y z a b c d e f g h i

This would not create any new parts but would move existing (which is what we do in real life).

In fact, I am thinking about new LDCad mode, let's call it provisionally "move mode", in which moving parts would not move them in the model but instead would insert these line in the current step and also would add GROUP_NXT and GROUP_DEF lines automatically should one attempt to move parts which were not in group. For clarity, you can prohibit adding new parts in this mode. Some kind of REMOVE GROUP statement should also be supported and interactively displayed by LDCad but the necessity for it would be much less with the ability to move groups.

With this suggestion it is not quite clear how multi-part groups should be handled. Perhaps they should be moved and rotated as a whole, using group center.

Ideally, if a group is a flexible path start, MOVE GROUP statement should regenerate the whole path. But what should happen to the fallback code in this case?

Of course, for this to work flawlessly it should be possible to move and remove groups in subfiles (for instance, you have a subassembly with a flexible part and later you want to connect its end somewhere). So a "nested move mode" is also needed.


Maybe all this was already discussed (could you please refer me to that discussion?). Otherwise, what do you think?
Reply
RE: Instruction making rant
#28
(2020-05-27, 15:48)Daniel R Wrote: So while some parts of my first post are suggestions for the next LDCad version, namely
  • Some way to make the ASR/NSR indicator always visible
  • Make flexible part length visible inside the nested submodel
  • Support to change color bin contents based on current selected part and external configuration
  • Arrow generator

Note that I did make the suggestion in the LDCad thread about displaying flexible part length. I'd been thinking of it for a few days before you mentioned it, so I thought the time was right. :-)
Reply
RE: Instruction making rant
#38
Thank you Smile
Reply
RE: Instruction making rant
#34
(2020-05-27, 15:48)Daniel R Wrote: I would love to contribute to LDCad code but it is closed and I respect this Roland's decision. Still, if this changes I would gladly contribute there (for instance, I can do some minor features which are thought to be necessary).
I'm not sure if people would be that happy working on LDCad code as I like to do things the hard way.

Meaning I wrote my own support library (strings, lists etc) minimizing std usage as I kinda hate bloat-y templates.

Also when I started the project (in C++) I came from years of Delphi programming so there are noticeable programming style differences along the way as I picked up some new c++ tricks etc  Big Grin

(2020-05-27, 15:48)Daniel R Wrote: 0 ROTSTEP 23 45 0 ABS CENTER 1 2 10 ABS DISTANCE 200 ABS

I kinda like this idea, I'm just wondering if some existing (strict) parsers might reject these lines breaking backwards compatibility. But you are right about it being a nonissue when only using it in new projects.

(2020-05-27, 15:48)Daniel R Wrote: Maybe it should reuse existing LDCad grouping capabilities, maybe like this

There could be all kinds of meta data added to groups as the current group meta uses a forward compatible format ([prop=value] list)
Reply
RE: Instruction making rant
#37
(2020-05-27, 17:41)Roland Melkert Wrote: I'm not sure if people would be that happy working on LDCad code as I like to do things the hard way

Okay. Feel free to make a private Github repo if you change your mind about this Smile

I also would be very glad if you post your opinion on some of the other suggestions above.
Reply
RE: Instruction making rant
#41
(2020-05-27, 19:58)Daniel R Wrote: I also would be very glad if you post your opinion on some of the other suggestions above.

I would very much like to add support for (a subset of) LPUB metas in LDCad 1.7, maybe add a special "Instructions" mode to the top right session panel as suggested elsewhere in this thread.

But as I don't make instructions and have very little experience with LPub myself, I would need some pointers on which metas to support first.

Also documentation on the lpub meta spec seems to be very fragmented / hard to find.

Once supported some of the more common tasks (adding callouts etc) can be handled with macro's (technically they already can) while seeing the result without having to use LPub.

You would still need LPub(3d) to generate the final pdf.

This is all some distance in the future though, as I fist want to do some fun things with interactive animation (the main reason I started a 1.7 version).

So maybe 1.7 Alfa 3 or even the first beta at the earliest.

This said nothing is set in stone, I tend to change direction quite often while working on the project Smile
Reply
RE: Instruction making rant
#30
I have long considered writing anything here.
I am personally very satisfied with the programs.
Of course there are always improvements and I think
every programmer has his own way of writing programs,
but don't forget that this is a page,
where all users sacrifice their free time and make everything free of charge.
The other way around, not even the multi-million dollar Micro.... Corporation manages to write software,
which enables all users to work efficiently because everyone has a slightly different approach.
Improvements or changes are not always a step forward.
If really so many "new" commands should be programmed in LDCad,
then LPub3D must also be adapted to support it.
I've seen MLCad and LPub evolve into LDCad and LPub3D,
and at the beginning I couldn’t imagine changing at all.
Old school MLCad/LPub user. Cool 
So I get along very well with the BUFEXCHG command,
because let's face it, how often is it really used in a model?
I'm currently drawing a Technic MOC with about 14,000 parts, (yes 14 thousand)
and maybe needed the command 5 times.
And I still believe that the MOC is buildable.
There are always ways to solve problems.
If nothing goes right, go left.
Reply
RE: Instruction making rant
#35
(2020-05-27, 16:32)Johann Eisner Wrote: Where all users sacrifice their free time and make everything free of charge.

Certainly. I understand this and do not ask anyone to implement some changes for me. I am sorry if I have sounded this way.
Nevertheless I personally would rather spend my free time on improving this software than doing something utterly meaningless such as waiting for LPub to display new page, correcting wrong callout arrows or moving parts manually with buffer exchange.

(2020-05-27, 16:32)Johann Eisner Wrote: I'm currently drawing a Technic MOC with about 14,000 parts, (yes 14 thousand)

That is very cool! Do you use LPub3D to make callout arrows? What is your typical wait time to display next page?


(2020-05-27, 16:32)Johann Eisner Wrote: And I still believe that the MOC is buildable.

That may be true, but the question is not how many times BUFEXCHG is unavoidable, but how many times you would like to use it because it is appropriate. For example, how many times it is used in a official instruction. And the answer, for example for the beginning of 42082 instruction, is that there are more buffer exchanges than pages.

Moreover, I think we limit ourselves and change the way we produce instructions due to technical difficulty of some commands. At least I do. So I think I would use it much more often if it was an easier process.
Reply
RE: Instruction making rant
#48
(2020-05-27, 18:58)Daniel R Wrote: Certainly. I understand this and do not ask anyone to implement some changes for me. I am sorry if I have sounded this way.

It shouldn't have been a reproach from me either.

(2020-05-27, 18:58)Daniel R Wrote: That is very cool! Do you use LPub3D to make callout arrows? What is your typical wait time to display next page?

In the meantime, I need about 20 - 30 seconds only if I change an arrow. To load a page with the main model (e.g. a new page), It takes about 3 minutes. This could be due to the special LDView render metas, or my very old notebook.

(2020-05-27, 18:58)Daniel R Wrote: Moreover, I think we limit ourselves and change the way we produce instructions due to technical difficulty of some commands. At least I do. So I think I would use it much more often if it was an easier process.

I agree with you.
If nothing goes right, go left.
Reply
« Next Oldest | Next Newest »



Forum Jump:


Users browsing this thread: 2 Guest(s)