Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Discussion: Land Editor

Landing Normandy
Proposing 4968
Join date: 28 Nov 2005
Posts: 240
11-13-2006 05:54
This has been done before but I had to have a go myself. The whole thing took 5mins, with the exception of getting it to sit on the floor properly. Thanks to Strife Onizuka for setting me straight in world on that one.

This is a GUI powered landscaping tool. You click it to set parameters, and then once running you stick it in EDIT so you can drag it around. When done, click STOP to, erm, stop it!

There is a HELP notecard included so I'll provide the text for that should anyone care. The HELP button won't do anything without it in the prim. The prim should set itself up for you.

Can I please point out that while I'm happy for this script to be used and distributed in your own work, can you please ensure that you credit both myself and Strife, and if you're copying the script completely, can you ensure that the object is free, and full mod/copy/trans, as the original that I pass on in world is. Thank you

CODE
integer CHANNEL;
integer ACTION;
integer SIZE;

string MAIN_MENU_STRING;
string SIZE_MENU_STRING;

list MAIN_MENU = [ "Level", "Raise", "Lower", "Smooth", "Noise", "Revert", "Size", "Stop", "Help", "Ground"];
list SIZE_MENU = [ "Small (2x2)", "Medium (4x4)", "Large (8x8)", "Back" ];

default
{
state_entry()
{

llSetPrimitiveParams([PRIM_COLOR, ALL_SIDES, <1, 0, 0>, 0.5, PRIM_SIZE, <3, 3, 0.5>]);
//ACTION = LAND_LEVEL;
//SIZE = LAND_SMALL_BRUSH;
MAIN_MENU_STRING = "Pick a tool or size of tool";
SIZE_MENU_STRING = "Pick size of tool or back to return";
CHANNEL = llFloor(llFrand(100000.0)) + 1000;
llListen(CHANNEL, "", NULL_KEY, "");
}

touch_start(integer num_detected)
{
if (llDetectedOwner(0) == llGetOwner())
{
llDialog(llDetectedKey(0), MAIN_MENU_STRING, MAIN_MENU, CHANNEL);
}
}

listen(integer CHANNEL, string name, key id, string message)
{
if (llListFindList(MAIN_MENU + SIZE_MENU, [message]) != -1) // verify dialog choice
{
if (message == "Size")
{
llDialog(id, SIZE_MENU_STRING, SIZE_MENU, CHANNEL);
}

if (message == "Help")
{
llGiveInventory(id, "Land Leveller");
}

if (message == "Level")
{
ACTION = LAND_LEVEL;
llSetTimerEvent(0.1);
}

if (message == "Raise")
{
ACTION = LAND_RAISE;
llSetTimerEvent(0.1);
}

if (message == "Lower")
{
ACTION = LAND_LOWER;
llSetTimerEvent(0.1);
}

if (message == "Smooth")
{
ACTION = LAND_SMOOTH;
llSetTimerEvent(0.1);
}

if (message == "Noise")
{
ACTION = LAND_NOISE;
llSetTimerEvent(0.1);
}

if (message == "Revert")
{
ACTION = LAND_REVERT;
llSetTimerEvent(0.1);
}

if (message == "Small (2x2)")
{
SIZE = LAND_SMALL_BRUSH;
llSetPrimitiveParams([PRIM_COLOR, ALL_SIDES, <1, 0, 0>, 0.5, PRIM_SIZE, <3, 3, 0.5>]);
}

if (message == "Medium (4x4)")
{
SIZE = LAND_MEDIUM_BRUSH;
llSetPrimitiveParams([PRIM_COLOR, ALL_SIDES, <0, 1, 0>, 0.5, PRIM_SIZE, <5, 5, 0.5>]);
}

if (message == "Large (8x8)")
{
SIZE = LAND_LARGE_BRUSH;
llSetPrimitiveParams([PRIM_COLOR, ALL_SIDES, <0, 0, 1>, 0.5, PRIM_SIZE, <9, 9, 0.5>]);
}

if (message == "Stop")
{
llSetTimerEvent(0);
}

if (message == "Ground")
{
// THIS PORTION BY STRIFE ONIZUKA //
float height = llGround(ZERO_VECTOR);
vector pos = llGetPos();
integer count = llCeil(llFabs(height - pos.z) / 10.0);
pos.z = height;
for(;count;--count)
llSetPos(pos);
// THANK YOU STRIFE! //
llSay(0, "Now at ground level");
ACTION = LAND_LEVEL;
llSetTimerEvent(0.1);
}
}
}

timer()
{
llModifyLand((integer)ACTION, (integer)SIZE);
llSetTimerEvent(0.1);
}
}


And the notecard (to be called Land Leveller unless you've changed the script)

From: someone
This is the HELP notecard for Landing Normandy's LAND LEVELLER utility

The Land Leveller is a single object that you can move around your land and will terraform it for you. As default it operates on a small 2x2m tool and is only operable by the owner.

To use it you will need to edit it to drag it around, but first select the tools you want. Click it and note the menu.

The tools work as follows:

LEVEL: Levels the terrain with each call, raising it up to the current height of the object's center (even if already level).
RAISE: Raises the terrain with each call, up to the current height of the object's center.
LOWER: Lowers the terrain with each call, down to zero height.
SMOOTH: Smooths the terrain.
NOISE: Randomizes (adds noise to) the terrain.
REVERT: Revert terrain to state to how it was when first created

You also have a SIZE option, STOP and GROUND:

SIZE: Allows you to pick the size of the tool you want to use. Options are 2x2m, 4x4m and 8x8m. This is the same as the standard SL Land Editting Tool Sizes. Note, SL does not allow 1m tools at this point.
STOP: Stops the current tool
GROUND: Drops the tool to ground level, ideal when you want to level the rest of the plot to the same as wht is under the tool right now.

Thanks to Strife Onizuka for the GROUND portion of the tool, I couldn't get it to quite work properly.

This is a free tool, therefore I don't do warranty. If it doesn't work for you I'm sorry, I don't know why, it works for everyone else who has tried it to this point.

If you paid for this you should ask for your money back!


I would LOVE to see what other people have come up with regards this kinda thing
_____________________
<VOTE PROPOSITION 4968/>
http://jira.secondlife.com/browse/VWR-4968
For SecondLife Builders who need better mapping for better building
Nada Epoch
The Librarian
Join date: 4 Nov 2002
Posts: 1,423
Original Thread
11-14-2006 12:24
/15/4e/148705/1.html
_____________________
i've got nothing. ;)
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
11-14-2006 14:53
Nice script Landing!!!
Demonstrates menus in an easy to understand format for the new ones here also.
_____________________
I (who is a she not a he) reserve the right to exercise selective comprehension of the OP's question at anytime.
From: someone
I am still around, just no longer here. See you across the aisle. Hope LL burns in hell for archiving this forum
ed44 Gupte
Explorer (Retired)
Join date: 7 Oct 2005
Posts: 638
11-14-2006 17:11
Hi Landing,

I published one of my earliest attempts at this at:
/54/98/100256/1.html
The idea wsa to pick a wanted height and travel a zigzag pattern to achieve that.
I did try to make a better version, but that is on the back burner for now.

One prob is that the raise and lower only do 0.2 M at a time. Another is that the effects of these actions is much wider than the size of the shovel.

There is also a very simple script (not mine, *sigh*) floating around the place with a very simple level command only, which you use in much the same way (but no menu). Great for levelling land!


A more useful tool might be one that reads a contour map from a notecard and compares it with actual heights in an area using llGround (offset). The tool would then race off to the spot with the largest deviation from the contour map and raise and lower that bit. This could be repeated thousands of times until the land matched the wanted contours.

You might have to read the contours into lists on a separate script to hold the lists of coordinates and wanted heights (each could be one vector) and use messagelinked to ask for a vector where (x, y) to do the next action (height from z).

I might get around to this one day, but I would be very pleased if someone took this idea and ran with it. As a shameless plug, I do have a mapper for sale that uses llGround to provide a contour map of an area, and little white spikes (beacons) to tell you visually what height they are at (they are ground level seeking moving spikes).

Just some thoughts.

Ed
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
11-14-2006 22:35
Dont remember where but I saw one that was a little ride on Bulldozer....

I like Ed44's Contour Map drive idea, post height grid type thing?
ed44 Gupte
Explorer (Retired)
Join date: 7 Oct 2005
Posts: 638
11-15-2006 04:00
Sorry, could not help myself. The script was too wild for my purpose and I have added some mods to give me more control over it.

The dialog box will let you tell the bot to double or half the time between commands. I have set that start time to 1 second to begin with.

Floating text above the bot shows the current action, the current ground level beneath it, and the time between applying the action. Make sure you are close enough to see that text.

I think the next step will be to put it into a linked set with some prim buttons to provide movement without requiring edit mode.

The stop button is still in the middle of the dialog box and can be pretty important if you panic and the bot is getting away from you. I now remember why in my original bot (a year ago or so) I used start-touch to call llDie. The menu came up automatically when you rezzed it.

Have fun!

CODE

integer CHANNEL;
integer ACTION = -1;
integer SIZE;

float repeatTime = 1;

string MAIN_MENU_STRING;
string SIZE_MENU_STRING;

list MAIN_MENU = [ "Level", "Raise", "Lower", "Smooth", "Noise", "Revert",
"Size", "Stop", "Help", "Ground", "Slower", "Faster"];
list SIZE_MENU = [ "Small (2x2)", "Medium (4x4)", "Large (8x8)", "Back" ];

string getSelectedAction () {
if (ACTION == LAND_LEVEL)
return "LEVEL";
if (ACTION == LAND_RAISE)
return "RAISE";
if (ACTION == LAND_LOWER)
return "LOWER";
if (ACTION == LAND_SMOOTH)
return "SMOOTH";
if (ACTION == LAND_NOISE)
return "NOISE";
if (ACTION == LAND_REVERT)
return "REVERT";
return "";
}



showMenu (string prompt, list options) {
llDialog(llGetOwner(), prompt, options, CHANNEL);
}


setSmallBrush () {
llSetPrimitiveParams([PRIM_COLOR, ALL_SIDES, <1, 0, 0>, 0.5, PRIM_SIZE, <3, 3, 0.5>]);
}


showFloatingText (){
vector pos = llGetPos();
string s = "Ground at " + (string) llGround (ZERO_VECTOR) +
"\nLand Editor at " + (string) pos.z +
"\nAction = " + getSelectedAction () +
"\nRepeat Rate is once per " + (string) repeatTime + " seconds";
llSetText (s, <1,1,1>, 1);
//llOwnerSay (s); // for development debug or record
}




default
{
on_rez (integer i) {
llResetScript ();
}

state_entry()
{
setSmallBrush ();
//ACTION = LAND_LEVEL;
SIZE = LAND_SMALL_BRUSH;
MAIN_MENU_STRING = "Pick a tool or size of tool";
SIZE_MENU_STRING = "Pick size of tool or back to return";
CHANNEL = llFloor(llFrand(100000.0)) + 1000;
llListen(CHANNEL, "", NULL_KEY, "");
showFloatingText ();

}

touch_start(integer num_detected)
{
if (llDetectedOwner(0) == llGetOwner())
{

showMenu(MAIN_MENU_STRING, MAIN_MENU);
}
}

listen(integer CHANNEL, string name, key id, string message)
{

//llOwnerSay ("message = " + message);

if (message == "Size")
{
showMenu(SIZE_MENU_STRING, SIZE_MENU);
return;
}

if (message == "Help")
{
llGiveInventory(id, "Land Leveller");
showMenu(MAIN_MENU_STRING, MAIN_MENU);
return;
}

if (message == "Level")
{
ACTION = LAND_LEVEL;
showFloatingText ();
showMenu(MAIN_MENU_STRING, MAIN_MENU);
llSetTimerEvent(repeatTime);
return;
}

if (message == "Raise")
{
ACTION = LAND_RAISE;
showFloatingText ();
showMenu(MAIN_MENU_STRING, MAIN_MENU);
llSetTimerEvent(repeatTime);
return;
}

if (message == "Lower")
{
ACTION = LAND_LOWER;
showFloatingText ();
showMenu(MAIN_MENU_STRING, MAIN_MENU);
llSetTimerEvent(repeatTime);
return;
}

if (message == "Smooth")
{
ACTION = LAND_SMOOTH;
showFloatingText ();
showMenu(MAIN_MENU_STRING, MAIN_MENU);
llSetTimerEvent(repeatTime);
return;
}

if (message == "Noise")
{
ACTION = LAND_NOISE;
showFloatingText ();
showMenu(MAIN_MENU_STRING, MAIN_MENU);
llSetTimerEvent(repeatTime);
return;
}

if (message == "Revert")
{
ACTION = LAND_REVERT;
llSetTimerEvent(repeatTime);
showFloatingText ();
showMenu(MAIN_MENU_STRING, MAIN_MENU);
return;
}

if (message == "Small (2x2)")
{
SIZE = LAND_SMALL_BRUSH;
setSmallBrush ();
llSetPrimitiveParams([PRIM_COLOR, ALL_SIDES, <1, 0, 0>, 0.5, PRIM_SIZE, <3, 3, 0.5>]);
showMenu(MAIN_MENU_STRING, MAIN_MENU);
return;
}

if (message == "Medium (4x4)")
{
SIZE = LAND_MEDIUM_BRUSH;
llSetPrimitiveParams([PRIM_COLOR, ALL_SIDES, <0, 1, 0>, 0.5, PRIM_SIZE, <5, 5, 0.5>]);
showMenu(MAIN_MENU_STRING, MAIN_MENU);
return;
}

if (message == "Large (8x8)")
{
SIZE = LAND_LARGE_BRUSH;
llSetPrimitiveParams([PRIM_COLOR, ALL_SIDES, <0, 0, 1>, 0.5, PRIM_SIZE, <9, 9, 0.5>]);
showMenu(MAIN_MENU_STRING, MAIN_MENU);
return;
}

if (message == "Stop")
{
llSetTimerEvent(0);
ACTION = -1;
showFloatingText ();
showMenu(MAIN_MENU_STRING, MAIN_MENU);
return;
}

if (message == "Back")
{
showMenu(MAIN_MENU_STRING, MAIN_MENU);
return;
}

if (message == "Slower")
{
repeatTime *= 2;
llSetTimerEvent(repeatTime);
showFloatingText ();
showMenu(MAIN_MENU_STRING, MAIN_MENU);
return;
}

if (message == "Faster")
{
repeatTime /= 2;
llSetTimerEvent(repeatTime);
showFloatingText ();
showMenu(MAIN_MENU_STRING, MAIN_MENU);
return;
}

if (message == "Ground")
{
// THIS PORTION BY STRIFE ONIZUKA //
float height = llGround(ZERO_VECTOR);
vector pos = llGetPos();
integer count = llCeil(llFabs(height - pos.z) / 10.0);
pos.z = height;
for(;count;--count)
llSetPos(pos);
// THANK YOU STRIFE! //
llOwnerSay ("Now at ground level");
showFloatingText ();
showMenu(MAIN_MENU_STRING, MAIN_MENU);
return;
}

llOwnerSay ("Got bad commmand - " + message);
}


timer()
{
if (ACTION > 0)
llModifyLand((integer)ACTION, (integer) SIZE);

showFloatingText ();
}
}
Landing Normandy
Proposing 4968
Join date: 28 Nov 2005
Posts: 240
11-20-2006 08:14
Hey, mod away, that's why I posted it! I'm not expert at this stuff and I wrote it as simply as I could so it would be easy to understand for a n00b too. The bit that Strife donated wan't put in where advised, it was supposed to go in as a seperate function but since it was only called once I just put it down in the place you see it now.

I've had a couple of ideas for expanding it too, like the ability to have more of them stuck together to work beyond the 8x8m limit. Reason being that I gave a copy to a friend who needs to level a whole island, she has asked for a larger tool because it's still taking too long this way. :(

I also thought about an 'orbitting child' that could create round areas, or at least as best as SL can handle round land. theory being that say you want a 10m dia circle, you could rez a prim that moves out and uses the small brush, it then rotates around the parent. Lower the radius that it operates on and you can fill in the circle. I guess it would be possible to even create a large spiralling tower, though I don't know how SL would handle that!

Interesting times eh? He he
_____________________
<VOTE PROPOSITION 4968/>
http://jira.secondlife.com/browse/VWR-4968
For SecondLife Builders who need better mapping for better building
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
11-20-2006 09:09
Here is another interesting variation you can look at.
CODE

list menu = ["On", "Lower", "Raise", "Level", "Noise", "Smooth", "Revert", "Brush Size", "Height"];
list brush_menu = ["Small", "Medium", "Large"];
list height_menu = ["Height On", "Height Off"];
list greater_menu = ["Less Then", "Greater Then"];
list on = ["On"];
list off = ["Off"];
float height = 21;
integer height_on = 0;
string height_on2;
integer chan = -98;
integer mod;
string mod2;
integer brush;
string brush2;
integer greater;
float ground;
integer cnt = 0;
integer me_say;


show_dialog(){
llDialog(llGetOwner(), mod2 + ", " + brush2 + "\n " + height_on2, menu, chan);
}

default{
state_entry(){
llSetTimerEvent(0.0);
}
touch_start(integer touches){
llDialog(llGetOwner(), "Options", menu, chan);
llListen( chan, "", llGetOwner(), "" );
}
listen( integer channel, string name, key id, string message ){
if(channel == 0){
height = (float)message;
}
if(message == "On"){
menu = llListReplaceList(menu, off, 0, 0);
show_dialog();
llSetTimerEvent(0.3);
}
else if(message == "Off"){
menu = llListReplaceList(menu, on, 0, 0);
show_dialog();
llSetTimerEvent(0.0);
}
else if(message == "Lower"){
mod = LAND_LOWER;
mod2 = "Lower";
show_dialog();
}
else if(message == "Raise"){
mod = LAND_RAISE;
mod2 = "Raise";
show_dialog();
}
else if(message == "Level"){
mod = LAND_LEVEL;
mod2 = "Level";
show_dialog();
}
else if(message == "Noise"){
mod = LAND_NOISE;
mod2 = "Noise";
show_dialog();
}
else if(message == "Smooth"){
mod = LAND_SMOOTH;
mod2 = "Smooth";
show_dialog();
}
else if(message == "Revert"){
mod = LAND_REVERT;
mod2 = "Revert";
show_dialog();
}
else if(message == "Brush Size"){
llDialog(llGetOwner(), "Options", brush_menu, chan);
}
else if(message == "Small"){
brush = LAND_SMALL_BRUSH;
brush2 = "Small Brush";
show_dialog();
}
else if(message == "Medium"){
brush = LAND_MEDIUM_BRUSH;
brush2 = "Medium Brush";
show_dialog();
}
else if(message == "Large"){
brush = LAND_LARGE_BRUSH;
brush2 = "Large Brush";
show_dialog();
}
else if(message == "Height"){
llDialog(llGetOwner(), "Options", height_menu, chan);
}
else if(message == "Height On"){
height_on = 1;
me_say = llListen( 0, "", llGetOwner(), "" );
llDialog(llGetOwner(), "Only work if...." + "\n" + "enter height in chat window then choose option", greater_menu, chan);
}
else if(message == "Height Off"){
height_on = 0;
height_on2 = "Height Off";
show_dialog();
}
else if(message == "Greater Then"){
greater = 2;
height_on2 = "Will modify if land is greater then = " + (string)height + " meters";
llListenRemove(me_say);
show_dialog();
}
else if(message == "Less Then"){
greater = 3;
height_on2 = "Will modify if land is less then = " + (string)height + " meters";
llListenRemove(me_say);
show_dialog();
}
}
timer(){
cnt += 1;
ground = llGround(ZERO_VECTOR);
if(cnt == 10){
llOwnerSay((string)ground);
cnt = 0;
}
else if(height_on == 0){
llModifyLand(mod, brush);
}
else if(height_on == 1){
if(greater == 2){
if(ground >= height){
llModifyLand(mod, brush);
}
}
else if(greater == 3){
if(ground <= height){
llModifyLand(mod, brush);
}
}
}
}
}
_____________________
I (who is a she not a he) reserve the right to exercise selective comprehension of the OP's question at anytime.
From: someone
I am still around, just no longer here. See you across the aisle. Hope LL burns in hell for archiving this forum
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
11-20-2006 09:40
I have been think of making another script to feed commands in along the lines of ed44 Gupte's. Fractal Patterns, alien crop circles.
_____________________
I (who is a she not a he) reserve the right to exercise selective comprehension of the OP's question at anytime.
From: someone
I am still around, just no longer here. See you across the aisle. Hope LL burns in hell for archiving this forum
ed44 Gupte
Explorer (Retired)
Join date: 7 Oct 2005
Posts: 638
11-20-2006 17:48
Terraforming can be very frustrating because the effects of these actions is much wider than the size of the shovel. The actual raw map has a one meter resolution but but it does not seem to work the same way in the east west as it does north south.

I ahve seen some discussion by Andrew Linden about streaming the ground data without compression, but I don't know if that eventuated and how the compression algorithm would affect this stuff. It might be good to know how the smoothing between adjacent points (1 M apart) is actually done.

Rainsing and lowering each move the ground by .2M, but the boundaries are not well defined.

You really need to have a pattern in mind and then make thousands of very small adjustments to make that pattern.


Have fun!
ed44 Gupte
Explorer (Retired)
Join date: 7 Oct 2005
Posts: 638
11-22-2006 03:02
Linden Answers has a post by Kelly Linden where he explains, in a fuzzy way, the complexity of the ground array: /139/73/150066/1.html

Talking about the llModifyLand () call he says: "I'm sorry I can't break down what this function does exactly in mathematical terms for you."

It seems to me that this is a forgotten area in sl design. Be nice to get that actual code!

With non-linear instrumentation readings I used to calibrate fifth order polynomial correction software to provide linear readings. Really need something like that here.
Eristic Strangelove
Registered User
Join date: 16 Nov 2005
Posts: 39
BTO Holes?
08-31-2007 11:27
Is it possible to use a terraforming script like this to make a 'Custom Hole Creator'?

For example, I have an idea for a hot tub (no, not another steaming box, a really good one!) and it would look best sunk into the ground, partially at least. So would it be possible to make a terraforming bot that would create the hole to the right size to fit the tub, assuming the land allows the normal +/-4m change?

I'm thinking of something I could ship with the pack for customers to install their own tub really easily. Maybe a frame set to the right size that they could place on the ground in position - then a little bot that ran around inside the frame lowering the land?

Is that feasible?
Lee Ponzu
What Would Steve Do?
Join date: 28 Jun 2006
Posts: 1,770
Sort of...
08-31-2007 12:08
The ground is represented by a 1m x 1m grid. So it is hard to make a 2m circular hole, for example. Extreme case of the jaggies. Rectangular holes can be more precise.

You might also make the hole too big, and then fill it in with prim dirt, and then dig into that.

lee
Eristic Strangelove
Registered User
Join date: 16 Nov 2005
Posts: 39
08-31-2007 15:16
From: Lee Ponzu
The ground is represented by a 1m x 1m grid. So it is hard to make a 2m circular hole, for example. Extreme case of the jaggies. Rectangular holes can be more precise.


Actually, for my needs, precision isn't a big issue - you wouldn't see the actual hole sides, you'll see my hot-tub walls. I would just need something to make a hole vaguely the right size (slightly bigger than the tub) and rectangular would be perfect.