The sphere contains two scripts:
/////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2022 - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// default { state_entry() { llTargetOmega(<0,0,1>, 1.0/86400, 1.0); } }
The hologram script is an integration of various Wizardry and Steamworks technologies and is mainly responsible for displaying textures out of the primitive's inventory for both the sphere and the clouds:
ASCENDING
flag), used to display the textures in alphabetical order for ease of use,Furthermore, the exact same script is used in both the sphere and the cloud part of the build. In order to distinguish between the sphere and the cloud, the hologram script uses the distance from the centre of the collector build and then sets the textures appropriately.
/////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2022 - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// integer wasMenuIndex = 0; list wasDialogMenu(list input, list actions, string direction) { integer cut = 11 - wasListCountExclude(actions, [""]); if(direction == ">" && (wasMenuIndex+1)*cut+wasMenuIndex+1 < llGetListLength(input)) { ++wasMenuIndex; jump slice; } if(direction == "<" && wasMenuIndex-1 >= 0) { --wasMenuIndex; jump slice; } @slice; integer multiple = wasMenuIndex*cut; input = llList2List(input, multiple+wasMenuIndex, multiple+cut+wasMenuIndex); input = wasListMerge(input, actions, ""); return input; } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// integer wasListCountExclude(list input, list exclude) { if(llGetListLength(input) == 0) { return 0; } if(llListFindList(exclude, (list)llList2String(input, 0)) == -1) { return 1 + wasListCountExclude(llDeleteSubList(input, 0, 0), exclude); } return wasListCountExclude(llDeleteSubList(input, 0, 0), exclude); } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// list wasListMerge(list l, list m, string merge) { if(llGetListLength(l) == 0 && llGetListLength(m) == 0) { return []; } string a = llList2String(m, 0); if(a != merge) { return [ a ] + wasListMerge(l, llDeleteSubList(m, 0, 0), merge); } return [ llList2String(l, 0) ] + wasListMerge( llDeleteSubList(l, 0, 0), llDeleteSubList(m, 0, 0), merge ); } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// integer stringComparer(string a, string b, integer ASCENDING) { list alph = [ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" ]; integer l = llListFindList( alph, [ llToLower(a) ] ); integer r = llListFindList( alph, [ llToLower(b) ] ); if(ASCENDING) { return l > r; } return l <= r; } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// list wasDualQuicksort(list a, list b) { if(llGetListLength(a) <= 1) return a+b; list pivot_a = llList2List(a, 0, 0); a = llDeleteSubList(a, 0, 0); list pivot_b = llList2List(b, 0, 0); b = llDeleteSubList(b, 0, 0); list less = []; list less_b = []; list more = []; list more_b = []; do { if(stringComparer(llList2String(a, 0), llList2String(pivot_a, 0), TRUE) == TRUE) { less += llList2List(a, 0, 0); less_b += llList2List(b, 0, 0); jump continue; } more += llList2List(a, 0, 0); more_b += llList2List(b, 0, 0); @continue; a = llDeleteSubList(a, 0, 0); b = llDeleteSubList(b, 0, 0); } while(llGetListLength(a)); return wasDualQuicksort(less, less_b) + pivot_a + pivot_b + wasDualQuicksort(more, more_b); } list menu = []; list text = []; key H = "45f7539c-3ba8-af15-e010-4a99581308f8"; key L = "0de3e8fa-efc5-7696-8ea2-0d734306b322"; key B = "cf85a515-0c52-f081-dada-0ff66b681048"; default { state_entry() { integer count = llGetInventoryNumber(INVENTORY_TEXTURE); integer i = 0; do { string name = llGetInventoryName( INVENTORY_TEXTURE, i ); menu += llGetSubString(name, 0, 8); text += name; } while(++i < count); list result = wasDualQuicksort(menu, text); menu = llList2ListStrided( result, 0, llGetListLength( result ) - 1, 2 ); text = llList2ListStrided( llDeleteSubList( result, 0, 0 ), 0, llGetListLength( result ) - 1, 2 ); vector this = llGetLocalPos(); if(this.z < 0) { llSetTexture(L, ALL_SIDES); } if(this.z > 0) { llSetTexture(H, ALL_SIDES); } if(llGetListLength(menu) == 0) { return; } state dialog; } on_rez(integer num) { llResetScript(); } attach(key id) { llResetScript(); } changed(integer change) { if(change & CHANGED_INVENTORY) { llResetScript(); } } } state dialog { touch_start(integer num) { llParticleSystem([]); llSetTexture(B, ALL_SIDES); integer channel = (integer)("0x8" + llGetSubString(llGetKey(), 0, 6)); llListen( channel, "", llGetOwner(), "" ); llDialog( llGetOwner(), "Please select a texture.\n", wasDialogMenu( menu, ["↺", "emp", "↻"], "" ), channel ); llSetTimerEvent(60); } listen(integer channel, string name, key id, string message) { if(message == "emp") { llParticleSystem([]); vector this = llGetLocalPos(); if(this.z < 0) { llSetTexture(L, ALL_SIDES); } if(this.z > 0) { llSetTexture(H, ALL_SIDES); } if(llGetListLength(menu) == 0) { return; } return; } if(message == "↺") { llSetTimerEvent(60); llDialog( id, "Please select a texture.", wasDialogMenu( menu, ["↺", "emp", "↻"], "<" ), channel ); return; } if(message == "↻") { llSetTimerEvent(60); llDialog( id, "Please select a texture.", wasDialogMenu( menu, ["↺", "emp", "↻"], ">" ), channel ); return; } integer x = llListFindList(menu, [ message ]); if(x == -1) { llDialog( llGetOwner(), "Please select a texture.\n", wasDialogMenu( menu, ["↺ ", "emp", "↻"], "" ), channel ); return; } vector this = llGetLocalPos(); if(this.z < 0) { llSetTexture(L, ALL_SIDES); } if(this.z > 0) { llSetTexture(H, ALL_SIDES); } if(llGetListLength(menu) == 0) { return; } string texture = llList2String(text, x); llParticleSystem( [ PSYS_SRC_TEXTURE, texture, PSYS_PART_START_SCALE, < .7, .7, 0 >, 6, < .7, .7, 0 >, PSYS_PART_START_COLOR, <1, 1, 1>, PSYS_PART_END_COLOR, <1, 1, 1>, PSYS_PART_START_ALPHA, .1, PSYS_PART_END_ALPHA, .002, PSYS_SRC_BURST_PART_COUNT, 0x7FFFFFFF, PSYS_PART_MAX_AGE, 0.2, PSYS_SRC_MAX_AGE, 0, PSYS_SRC_PATTERN, (integer)4, PSYS_SRC_BURST_SPEED_MIN, 0, PSYS_SRC_BURST_SPEED_MAX, 0, PSYS_SRC_ANGLE_BEGIN, (float)0.03 * 3.141593, PSYS_SRC_ANGLE_END, (float)0 * 3.141593, 8, ZERO_VECTOR, PSYS_PART_FLAGS, (integer)(0 | 1 | PSYS_PART_EMISSIVE_MASK) ] ); } timer() { llSetTimerEvent(0); vector this = llGetLocalPos(); if(this.z < 0) { llSetTexture(L, ALL_SIDES); } if(this.z > 0) { llSetTexture(H, ALL_SIDES); } if(llGetListLength(menu) == 0) { return; } } on_rez(integer num) { llResetScript(); } attach(key id) { llResetScript(); } changed(integer change) { if(change & CHANGED_INVENTORY) { llResetScript(); } } }
There are three deliberately hardcoded textures within the hologram script in order to not interfere with the primitive's inventory that is used only for textures that the user places inside.
key H = "45f7539c-3ba8-af15-e010-4a99581308f8"; key L = "0de3e8fa-efc5-7696-8ea2-0d734306b322"; key B = "cf85a515-0c52-f081-dada-0ff66b681048";