sbrl / Minetest-WorldEditAdditions

Extra tools and commands to extend WorldEdit for Minetest
https://worldeditadditions.mooncarrot.space/
Mozilla Public License 2.0
16 stars 3 forks source link

Selection Tools #27

Closed VorTechnix closed 3 years ago

VorTechnix commented 3 years ago

I don't know how easy these suggestions will be to implement or if some of them would be even possible without changing the main world edit mod but the current selection system is so frustrating I've decided to lay out my ideas and let you take or leave them (command names are placeholders--feel free to change them if you want).

  1. Temporary Saving and Retrieval of selections (until program close). The retrieval command would have an option to use the current Position 1 as the basis for the retrieved selection or to use the original coordinates. Syntax: //savesel <name> //getsel <name> [c(urrent)] //listsels. //listsels would return a list of the saved selections and their pos1 and pos2 coordinates.
  2. 5 and 6 point selections (6 for things like floating islands that have a bottom--otherwise the lowest of the 5 points would be the bottom). For spheres, floating islands and anything else with rounded edges and corners. With //fineset [1-6] you would be able to set the bounds of the final selection by punching nodes on the widest points and top (and optionally a 6th point on the bottom) of the thing you want to select and then the command would generate a selection box including those points. Putting a number after the command, e.g. //fineset 2, would allow to redefine that point by punching a different node and then change the selection box to fit the new point.
  3. Perfect 2 axis box and 3 axis cube selections based on the current Position 1. Syntax: //sbox [+/-]x/y/z [+/-]x/y/z <length>, //scube [+/-]x [+/-]y [+/-]z <length>. Examples: //sbox -x y 10, //scube x -y -z 7.

Let me know if you need any clarification or further detail. Also I'm learning lua bit by bit so hopefully I can start contributing some time in the future instead just dumping ideas.

sbrl commented 3 years ago

Ooooh, interesting ideas!

1

That should be relatively easy to implement. It wouldn't persist across server reboots though without getting into file io, which I haven't yet done in Minetest. Something I should consider doing.

This would be good for testing purposes too if it did persist across server reboots though.

2

This one sounds complicated, and may be best discussed in a separate issue.

Not sure I quite understand what you're going for there. Are you suggesting adding the ability to select an arbitrary 3D shape? Sounds hard to implement. However, have you seen //ellipsoidapply that I implemented relatively? It works like this:

//ellipsoidapply set dirt

....would have the same effect as doing //ellipsoid 4 5 6 dirt for example, just that //ellipsoidapply works with 2 points, and //ellipsoid works with just 1.

Big problems with adding the ability to select more than 2 points:

  1. All the existing commands are built to operate on up to 2 points defining a cuboid as a region, so they'd all need reimplementing. Same goes for WorldEdit itself.
  2. The maths behind determining if a point it inside a 3D geometric shape or not gets real tricky real fast.

However, implementing a wrapper command like //cubeapply (found in WorldEdit itself) or //ellipsoidapply (which I've implemented in WorldEditAdditions) would be much more doable, because we can keep a local copy of what everything looked like before, and use that to apply an arbitrary mask to any changes that are made.

Do you have any ideas for some syntax there - perhaps something like this?

//meshapply x1 y1 z1 x2 y2 z2 x3 y3 z3 x4 y4 z4 [.....] command_name [arguments]

....but I do think that is rather messy and difficult, because you'd have to determine the location for each of the points manually.

It would also probably some with the limitation that the mesh has to be convex I would assume, as detecting whether any given node is inside a concave shape is more difficult I think (collision detection is nasty like that).

Perhaps a special wand tool here would be helpful. I would have liked to add it to the existing long-range WorldEdit wand I've implemented, but unfortunately both left and right click are already used there, so I can't think of any other unused functionality there I could use to switch between modes, as the Minetest engine is rather limited in that regard.

Either way, it'd be great if you could expand on the idea - maybe draw a diagram or take some screenshots from Minetest to illustrate your point.

3

Interesting ideas here. Note that WorldEdit has a //cubeapply already that allows you to run a command on a cuboid-shaped area based on position 1:

//cubeapply 5 set dirt
//cubeapply 5 4 3 set dirt

A favourite of mine for defining areas is also a construct like this:

//multi //outset h 2 //set dirt

By combining //multi with the command I want to execute and //outset (e.g. //outset 4, or //outset h 4, or //outset v 5), I can define an arbitrary-shaped box and execute a command in one go.

Despite this, I can definitely see a use for implementing //sbox and //scube. I'd suggest using something like //srect though instead of //sbox, as the rect implies a 2D (i.e. 1 thick) selection area better. This shouldn't be too difficult to implement actually, so it should be a great first command to implement if you'd like.

How experienced are you at programming?

VorTechnix commented 3 years ago

Thanks for the feedback. Here's some clarification:

1

Maybe having saved selections persist across reboots could be turned on and off in a config file (which I'm going to officially ask for in a new post). I can think of many good reasons to make saves persist and not persist so leaving it up to the user might be the best idea.

Upon further consideration I think we should also make a configurable cap (default:10 maybe?) on the number of saved selections in order to prevent the list from becoming miles long when persist-on-reboot is enabled. When the cap is reached the behavior should be that the oldest saved selection would be removed to make room.

2

I think you misunderstood what I was trying to get at with this one. The idea was to create a standard 2 point selection big enough to encompass a target using 5-6 points selected on that target.

As it is right now it is very hard to select floating islands, rounded spires, or really anything that does not have corners that correspond to the widest parts of the target, in a single try without over selecting and having to contract the selection or under selecting and having to expand.

The basic parsing for the feature would be to simply find the minimum x y and z values of the 5 or 6 point cloud and assign them to the first point of the 2 point (normal) selection, then take the maximum x y and z values of the point cloud and assign them to point 2 of the normal selection.

I hope this clears things up and makes them simpler.

3

I like the //srect idea; it makes a lot of sense. As for why I want the feature it's simple: to quickly make perfect 45 deg. //lines. Now that I think about it though it might be nice to be able to set the angle (rounded to the nearest 5). Angle would be optional though and default to 45. So //srect [+/-]x/y/z [+/-]x/y/z <length> [<angle>].

As for implementing this feature I'd love to try my hand at it as long as you don't mind me possibly posting a few dumb questions in the process.

My Programming Experience

I've done front end development (html/xml/JSON/CSS/a lot of javascript) for about 2.5 years. I know just enough python to get myself in trouble and I've dabbled in a compiled language called haxe. A far as lua goes I'm green grass but I'm going to have to learn it sometime as I want to develop moddable games in the future.

sbrl commented 3 years ago

1

Sounds good. An LRU (least-recently-used) size-limited cache is probably what we want here. We can implement the LRU cache as a separate portable module and put it in a file like worldeditadditions/lib/helpers/lru_cache.lua, relative to the root of the repository.

2

Oh, I see what you mean there! That should be easy. We can implement a separate wand for that. I've already got an idea as to what it might look like.....

Please open a separate issue for this feature.

3

Not sure I understand what you mean by the angle there, but I assume you're referring to the new //line command somehow?

Anyway, sure thing! Give it a go. I don't check my GitHub notifications every day, so if you need to get hold of me sooner you can try taking over the Pepperminty Wiki Gitter lobby (another project of mine) and asking me to look at this issue if you need assistance implementing a feature here.

Nice! Javascript is one of my favourite languages. Oooh, I've heard of Haxe too. Never used it though. Lua is interesting because you'll find that the standard library is much slimmer than other languages, leaving you to do a lot of stuff yourself. Before doing so though, check these places to see if it's been done already:

Edit: I recommend implementing //srect in new file in worldeditadditions_commands/commands/select/srect.lua. It shouldn't need a counterpart in worldeditadditions/lib, because it doesn't modify the Minetest world (only the WorldEdit selected region).

Also, this snippet of lua might come in handy:

worldedit.pos1[name] = SOME_POS1_HERE
worldedit.pos2[name] = SOME_POS2_HERE
worldedit.marker_update(name)

worldedit.pos1[name] is how you access the pos1 for a user, and then you can re-render the region marker with worldedit.marker_update(name) (it took ages for me to look that one up).

Edit 2: Oh yeah, and Lua is great for embedding I've heard. Other lesser known alternatives exist too though, such as Wren - but Lua is the best-known one that people will most likely be familiar with (despite it's severe lack of standard library). LuaJIT is also worth a look - it's a runtime environment for Lua that provides higher performance.

VorTechnix commented 3 years ago

Alright here we go again:

1

LRU caching sounds like exactly what we need but I still think it would be nice to have the option to not cache saves or at least clear the cache on reboot.

2

New feature proposal coming up.

3

The angle idea is something for later once I have the basic functionality implemented... I'm not going to worry about it for now.

Also thanks for the snippets (although I kinda deduced them from other commands of the main world edit mod). Right now I'm drafting the //srect command in my sandbox mod and once it works there I'll fork this mod, copy paste, test again and pull request. Not sure if I'll do //scube at the same time or in a separate pull request.

And finally thanks for the tips about lua runtime environments. I'll be sure to look into that (I've been looking for a good CLE to test my lua scripts in).

It's kind of rare to meet someone who has heard of haxe so it's neat that you know of it. As for JS I use Node.js primarily and it's great for automation of repetitive tasks and general bot creation (although I hear python is even better but I don't know enough of the language to use it for that yet).

Do you have a Discord account? I'm on the unofficial minetest discord: https://discord.gg/Wr6eXU3.

sbrl commented 3 years ago

1

Yeah, a configuration setting to avoid serialising saved points to disk is a good idea.

2

Thanks :-)

3

Cool.

Yeah, I use Node.js extensively myself for my PhD. Python is cool too, but from my (limited) experience I much prefer the async/await syntax in Javascript as opposed to Python.

I do! And I think I'm in that discord already too lol :P

Edit: I can't find you in that discord though.

VorTechnix commented 3 years ago

Moving selection save/load to separate issue.