Troy McConaghy's Holo-Emitter
From DuoGrid
| This Asset is currently available. |
| Service | Link |
|---|---|
| In-world (MG) | Infotainment Island (86,128,31) |
| In-world (TG) | [Under work] |
| OnRez Shops | --- |
| SL Exchange | --- |
| Do-It-Yourself | Available |
Contents |
Asset Documentation
Introduction
In Star Trek, there's something called a holodeck, which is a room where you can simulate just about anything, from a beach resort to a spaceship. You just tell the computer what you want and it appears. The things that appear are holograms and they are generated by so-called holo-emitters. I made something similar for SL. You click the holo-emitter, it gives you a menu of scenes, you pick a scene and it appears. Simple.
I made it so that the scene can be spread out over an entire sim. That way, you could easily change the sim (e.g. from a city to a meadow) to suit your mood. You could also use the holo-emitter system to move scenes from one part of a sim to another part – since the objects in a scene move relative to the holo-emitter. You'd just pack up the scene at its original location, move the holo-emitter, and rez the scene again at the new location.
My holo-emitter system is free and open source (GPL 2.0), so you can read and change the scripts to suit your needs.
Basics
The holo-emitter (an object) contains a set of scene-containers (also objects). Each scene-container contains a set of objects (the objects that make up a scene). In order to use my holo-emitter system, your scene must be made up of objects that you can modify and copy. To repeat: you must be able to modify and copy every object in your scenes. (You don't need to be able to sell/transfer though, unless you want to give or sell the loaded holo-emitter to someone else in the future.) When you click the holo-emitter, it looks at its contents (scene-containers) and uses that to give you a menu of scenes bases on the names of those scene-containers. When you select a particular scene, the holo-emitter rezzes that scene-container. The scene-container then rezzes all objects in its contents and then vanishes. The contents fly to their proper position then stop. Voila! Now let's go through the steps to pack a scene into a scene-container object and then put the scenecontainer object into a holo-emitter object.
Packing-up A Scene
- Rez an object which will serve as your holo-emitter. Any object will do, provided that you can modify it.
- You may want to change the name of your holo-emitter object to “Holo-Emitter” or something like that.
- Copy the script named “Holo-Emitter Script” into your holo-emitter object's contents (by dragging it from your inventory into the contents of your holo-emitter object).
- You could have built your scene (a set of objects in the same sim as your holo-emitter object) before Step 1, but if you didn't then build it now.
- You should link together as many of the objects in your scene as you can. This will make your scene rez faster later on.
- For each object in your scene, copy “Object Script A” into the object's contents, and copy “Object Script B” into the object's contents.
- For each object in your scene, take the object into your inventory (by right-clicking it and selecting “Take”). NOTE: Don't select multiple objects and “Take” them all into your inventory at once; take them into your inventory one at a time.
- Rez an object which will serve as the scene-container for your scene. Any object will do, provided that you can modify it.
- Rename the scene-container object “Scene1” or something like that. Keep the name short (10 characters or fewer), because it will be used by the holo-emitter when giving you the menu of scenes later on.
- Make sure the scene-container object has modify and copy permissions (by checking those boxes on the General tab in the Edit window). [Note: I'm not sure if this step is necessary all the time. Use your judgment.]
- Copy the script named “Scene-Container Script” from your inventory into the contents of the scene-container object.
- For each scene object in your inventory, copy the object into the contents of the scene-container object (by dragging it from your inventory into the scene-container object's contents).
- CRITICAL STEP: While editing the scene-container object, go to the General tab in the Edit window and change the Description to “live” (without the quotes). This activates the scene container so that when it gets rezzed, it automatically rezzes all its contents and then deletes itself. [Note: You can make it stop doing that by changing the Description to something else.]
- Take the scene-container object into your inventory.
- Copy the scene-container object from your inventory into the holo-emitter object.
That's all. Next time you click the holo-emitter object, it will automatically detect the new scenecontainer object and add it to the menu of scenes.
How to Add/Remove Objects from a Scene-Container
- Copy the scene-container object from the holo-emitter's contents to your inventory.
- Right-click on the scene-container object in your inventory and select “Properties”.
- Change the Description to something other than “live”.
- Rez the scene-container object.
- Edit the scene-container object and go to the Contents tab.
- To remove objects, just right-click them in the Contents and select Delete.
- To add objects, do as in Steps 6, 7 and 12 from the previous set of instructions.
- Take the scene-container object back into your inventory. Maybe give it a new name to help you keep organized. (To do that, right-click it in your inventory and select Rename.)
- Delete the old scene-container object from the holo-emitter's contents (Right-click it then select Delete).
- Copy the new scene-container object to the holo-emitter's contents.
Important Notes
Limitations on Number of Objects or Scenes
Scenes can have any number of objects. Of course, the more objects there are in a scene, the longer it will take for it to rez. (Note: there is a built-in, hardwired delay between the rezzing of each object in a scene.) A holo-emitter can also hold any number of scene-container objects, but only the first eleven will show up in the blue pop-up dialog box when you click the holo-emitter (and the twelfth button will always say 'Clear'). Feel free to change the holo-emitter script so that more scenes could be chosen (e.g. maybe change it to have a hierarchical menu or use chat commands instead).
Object centers can't go underground
If you move the holo-emitter so that an object in a scene at the new location would have its center under the ground, then that object will not go to their correct position (relative to the holo-emitter) – the object's center will go to a point on the ground near the correct position instead. This happens because an object can't move itself so that its center is below ground level.
Object centers can't go into other sims
If you move the holo-emitter so that an object in a scene at the new location would have its center outside the current sim, then the object will try to move itself there, but it will probably fail and end up in your “Lost And Found” folder (in your inventory).
Watch out if there are two of more holo-emitters in the same sim
If you have two or more holo-emitters in the same sim, then there will be crosstalk and it won't be pretty! That doesn't mean it's impossible. To have two or more holo-emitters in the same sim, you just need to edit the “Global constants” section at the start of each script (for those that have one). Change the channel numbers and make sure they are consistent (e.g. HE_channel must have the same value in all scripts). A copy of the Global constants section of the “Holo-Emitter Script” is shown below: // Global constants - should be changed if there are any other holo-emitters in the sim, both here and in all other scripts integer delete_channel = -3423489; integer menu_channel = -1847395; integer HE_channel = -9385735;
Remove Object Script B to make an object permanent
If you don't want an object in a scene to vanish when you select “Clear” or when a new scene is chosen, then remove Object Script B from the object's inventory. Object Script B is pretty simple: it just listens for a special command (on the delete_channel) to tell it to delete the object in which it is contained.
Asset DIY Instructions
Please read the associated documentation before and after recreating this Asset yourself.
Originally written by "Troy McConaghy".
There are four scripts that work together to make the holo-emitter system work. They are named:
- Holo-Emitter Script
- Scene-Container Script
- Object Script A
- Object Script B
Please make sure you have all four scripts or the system won't work. The source code for those scripts (version 1.0) is below. Note that they are all open source (GPL 2.0).
Holo-Emitter Script
// Holo-Emitter Script
// Part of Troy McConaghy's Holo-Emitter System
//
// Copyright (C) 2007 by Troy McConaghy (Troy McLuhan in Second Life)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You can get a copy of the GNU General Public License at
// http://www.gnu.org/licenses/gpl.txt
// or by writing to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
// Global constants - should be changed if there are any other holo-emitters in the
sim, both here and in all other scripts
integer delete_channel = -3423489;
integer menu_channel = -1847395;
integer HE_channel = -9385735;
// Global variables
list options;
integer menu_listen;
clear_scene()
{
llRegionSay(delete_channel, "delete"); // Sends a "delete" message to the
entire sim on the delete_channel
}
default
{
state_entry()
{
llSay(0,"Ready");
llListen(HE_channel,"",NULL_KEY,"ping");
}
touch_start(integer total_number)
{
// Generate the menu of scenes by scanning the holo-emitter's inventory
options = ["Clear"]; // even if there are no scenes in the holo-emitter,
one option is always to clear the scene
integer num_scenes = llGetInventoryNumber(INVENTORY_OBJECT); // = number of
objects in the holo-emitter's inventory
if (num_scenes>0)
{
integer scene_nbr;
for (scene_nbr=0; scene_nbr<num_scenes; scene_nbr++)
{
options = options + [llGetInventoryName(INVENTORY_OBJECT,
scene_nbr)]; // appends another scene to the list of options
}
}
llDialog(llDetectedKey(0), "Select the scene you would like to see:",
options, menu_channel);
menu_listen = llListen(menu_channel, "", NULL_KEY, "");
}
listen(integer channel, string name, key id, string message)
{
if ((channel==HE_channel) && (message=="ping"))
{
//llSay(0,"I heard a ping, so I'm replying with my position now (on the
HE_channel).");
vector HE_pos = llGetPos(); // = holo-emitter position <x,y,z>
string str =
(string)HE_pos.x+","+(string)HE_pos.y+","+(string)HE_pos.z;
llRegionSay(HE_channel, str);
//llSay(0,"My position string is "+str);
}
else if (channel==menu_channel)
{
if (message=="Clear")
{
clear_scene();
}
else // message = the name of the scene-container to rez
{
clear_scene();
llRezAtRoot(message, <0.0,0.0,9.0>+llGetPos(), ZERO_VECTOR,
ZERO_ROTATION, 1);
}
llListenRemove(menu_listen);
}
}
}
Scene-Container Script
// Scene-Container Script
// Part of Troy McConaghy's Holo-Emitter System
//
// Copyright (C) 2007 by Troy McConaghy (Troy McLuhan in Second Life)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You can get a copy of the GNU General Public License at
// http://www.gnu.org/licenses/gpl.txt
// or by writing to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
default
{
on_rez(integer start_param)
{
string obj_desc = llToLower(llGetObjectDesc()); // = object description
string, made lowercase
//llSay(0, "obj_desc = "+obj_desc);
if (obj_desc == "live") // then the scene-container is live, so rez all of
its contents then delete the scene-container
{
integer num_obj = llGetInventoryNumber(INVENTORY_OBJECT); // = number
of objects in the scene-container's inventory
//llSay(0, "Number of objects in my inventory = "+(string)num_obj);
if (num_obj>0)
{
integer obj;
for (obj=0; obj<num_obj; obj++)
{
//llSay(0, "Rezzing obj with inventory index = "+(string)obj);
llRezAtRoot(llGetInventoryName(INVENTORY_OBJECT, obj),
<0.0,0.0,1.0>+llGetPos(), ZERO_VECTOR, ZERO_ROTATION, 0);
llSleep(0.5);
}
//llSay(0, "Done rezzing all objects in inventory");
}
llSleep(10.0);
llDie();
}
// If the scene-container is not live, then control now passes to the
state_entry() event handler
}
state_entry()
{
llSay(0,"You can now add and remove objects from my inventory.");
}
}
Object Script A
// Object Script A
// Part of Troy McConaghy's Holo-Emitter System
//
// Copyright (C) 2007 by Troy McConaghy (Troy McLuhan in Second Life)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You can get a copy of the GNU General Public License at
// http://www.gnu.org/licenses/gpl.txt
// or by writing to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
// Global constants - should be changed if there are any other holo-emitters in the
sim, both here and in all other scripts
integer HE_channel = -9385735;
// Global variables
vector rel_pos;
rotation rot;
goto( vector destpos )
{ //Based on warpPos
//R&D by Keknehv Psaltery, 05/25/2006
//with a little pokeing by Strife, and a bit more
//some more munging by Talarus Luan
//Final cleanup by Keknehv Psaltery
// Compute the number of jumps necessary
integer jumps = (integer)(llVecDist(destpos, llGetPos()) / 10.0) + 1;
// Try and avoid stack/heap collisions
if (jumps > 100 )
jumps = 100; // 1km should be plenty
list rules = [ PRIM_POSITION, destpos ]; //The start for the rules list
integer count = 1;
while ( ( count = count << 1 ) < jumps)
rules = (rules=[]) + rules + rules; //should tighten memory use.
llSetPrimitiveParams( rules + llList2List( rules, (count - jumps) << 1,
count) );
}
ping()
{
llRegionSay(HE_channel, "ping"); // Sends out a ping on the HE_channel to
determine the holo-emitter's position
}
default
{
on_rez(integer start_param)
{
state repos;
}
state_entry()
{
// This event is triggered if this script is dragged from inventory to the
contents of an object
llListen(HE_channel, "", NULL_KEY, "");
ping();
llSetTimerEvent(2.0); // Just in case the first ping isn't heard, more are
sent out until one gets heard
}
timer()
{
ping();
}
listen(integer channel, string name, key id, string message)
{
if (channel==HE_channel)
{
llSetTimerEvent(0.0); // Turns off the timed pings, since a ping was
heard and a reply has been received
vector pos = llGetPos();
if (pos.z <= llGround(ZERO_VECTOR))
{
string obj_name = llGetObjectName();
llSay(0,"WARNING! The center of the object "+obj_name+" is below
ground level.");
llSay(0,"The holo-emitter system won't be able to put it back
there");
llSay(0,"because it can only place objects whose center is above
ground level.");
}
list pos_list = llCSV2List(message);
vector HE_pos = <llList2Float(pos_list,0), llList2Float(pos_list,1),
llList2Float(pos_list,2)>;
rel_pos = pos - HE_pos;
//llSay(0,"pos = "+(string)pos+", HE_pos = "+(string)HE_pos+", rel_pos
= "+(string)rel_pos);
rot = llGetRot();
//llSay(0, "I stored my position in rot, rot = "+(string)rot);
state await_rerez;
}
}
}
state await_rerez
{
state_entry()
{
llSay(0,"You can now take me into your inventory and then put me in a
scene-container from there.");
}
on_rez(integer start_param)
{
state repos;
}
}
state repos
{
state_entry()
{
//llSay(0,"Now in state repos");
llListen(HE_channel, "", NULL_KEY, "");
ping();
llSetTimerEvent(2.0); // Just in case the first ping isn't heard, more are
sent out until one gets heard
}
timer()
{
ping();
}
listen(integer channel, string name, key id, string message)
{
if (channel==HE_channel)
{
llSetTimerEvent(0.0); // Turns off the timed pings, since a ping was
heard and a reply has been received
list pos_list = llCSV2List(message);
vector HE_pos = <llList2Float(pos_list,0), llList2Float(pos_list,1),
llList2Float(pos_list,2)>;
vector pos = HE_pos + rel_pos;
llSetRot(rot);
goto(pos);
llSetRot(rot);
goto(pos);
llSetRot(rot);
goto(pos);
llSetRot(rot);
// Now that the object is positioned, this script isn't needed anymore,
so remove this script from the object's inventory
llRemoveInventory(llGetScriptName());
}
}
}
Object Script B
// Object Script B
// Part of Troy McConaghy's Holo-Emitter System
//
// Copyright (C) 2007 by Troy McConaghy (Troy McLuhan in Second Life)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You can get a copy of the GNU General Public License at
// http://www.gnu.org/licenses/gpl.txt
// or by writing to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
// Global constants - should be changed if there are any other holo-emitters in the
sim, both here and in all other scripts
integer delete_channel = -3423489;
default
{
state_entry()
{
llListen(delete_channel, "", NULL_KEY, "delete");
}
listen(integer channel, string name, key id, string message)
{
llDie();
}
}
You can read the source here.

