This script goes into the cylindrical prim used as an axe for the pages
CODE
//Prim book scripts, animate a 3d prim book
//Copyright (C) 2005 Issarlk
//
//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 should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
vector initialPos;
rotation initialRot;
//the variable where we store the back cover link number
integer backcover_link_number = 0;
//the back cover key
key backcover_key = NULL_KEY;
list page_keys = [];
list page_commands = [];
integer page_listener_id = 0;
//Put the number of page here, a page is a two sided sheet of paper (bad name)
integer number_of_pages = 2;
//Comments for each page, display next to pointer
list pagecomments = [
"The pink unicorn in the sky. ",
"Wolf guy needing yet more relaxation after a swim.",
"Green aired feline.",
"Sexy rabbit with guns."
];
init()
{
initialPos = llGetPos();
initialRot = llGetRot();
backcover_link_number = 0;
backcover_key = NULL_KEY;
page_keys = [];
page_commands = [];
llListenRemove(page_listener_id);
page_listener_id = 0;
//we need perm to change link, so we delink the backcover before rotating to open book
//in hindsight, two backcover turning visible / invisible would be simpler
//
// known bug: if owner is not around, it doesnt delink and everything rotate...
//
if ((llGetPermissions() & PERMISSION_CHANGE_LINKS) == 0)
{
llRequestPermissions(llGetOwner(), PERMISSION_CHANGE_LINKS);
}
llMessageLinked(LINK_ALL_OTHERS, 0, "send backcover link number", NULL_KEY);
}
// utility functions to manage an array of pages and their info
setPage(integer number, key id)
{
resetPage(number);
page_keys = llListInsertList(page_keys, [number, id], llGetListLength(page_keys));
}
resetPage(integer number)
{
integer tmppagepos = llListFindList(page_keys, [number]);
if (tmppagepos != -1)
{
page_keys = llDeleteSubList(page_keys, tmppagepos, tmppagepos+1);
}
}
key getPage(integer number)
{
integer tmppagepos = llListFindList(page_keys, [number]);
return llList2Key(page_keys, tmppagepos+1);
}
integer getPageNumber(key id)
{
integer tmppagepos = llListFindList(page_keys, [id]);
if (tmppagepos == -1)
{
llWhisper(0, "error, number of page "+ (string)id + " not fouund");
}
return llList2Integer(page_keys, tmppagepos - 1);
}
integer hasPageCommands(integer number)
{
if (llListFindList(page_commands, [number]) == -1)
{
return FALSE;
}
else
{
return TRUE;
}
}
setPageCommands(integer number, string commands)
{
resetPageCommands(number);
page_commands = llListInsertList(page_commands, [number, commands], llGetListLength(page_commands));
}
string getPageCommands(integer number)
{
integer tmppagepos = llListFindList(page_commands, [number]);
return llList2String(page_commands, tmppagepos+1);
}
resetPageCommands(integer number)
{
integer tmppagepos = llListFindList(page_commands, [number]);
if (tmppagepos != -1)
{
page_commands = llDeleteSubList(page_commands, tmppagepos, tmppagepos+1);
}
}
//in case two book are near, check if an id we hear talking is one of our page
integer isOurPage(key id)
{
if (llListFindList(page_keys, [id]) == -1)
{
//not one of our pages
return FALSE;
}
else
{
//one of our pages
return TRUE;
}
}
//open book
open()
{
if (backcover_key != NULL_KEY && backcover_link_number != 0)
{
//leave back cover on the ground
llBreakLink(backcover_link_number);
backcover_link_number = 0;
}
//rotate
llSetRot(llEuler2Rot(<0, 0, PI_BY_TWO>)*initialRot);
llSetRot(llEuler2Rot(<0, 0, PI>)*initialRot);
if (backcover_key != NULL_KEY)
{
//relink backcover
llCreateLink(backcover_key, TRUE);
//ask the back cover to send us its link number
llMessageLinked(LINK_ALL_OTHERS, 0, "send backcover link number", NULL_KEY);
}
llSetTimerEvent(0.2);
}
//same, but closes
close()
{
//kill all pages
llSetTimerEvent(0.5);
//close book
if (backcover_key != NULL_KEY && backcover_link_number != 0)
{
llBreakLink(backcover_link_number);
backcover_link_number = 0;
}
llSetRot(llEuler2Rot(<0, 0, PI_BY_TWO>)*initialRot);
llSetRot(initialRot);
llSetPos(initialPos);
if (backcover_key != NULL_KEY)
{
llCreateLink(backcover_key, TRUE);
//ask the back cover to send us its link number
llMessageLinked(LINK_ALL_OTHERS, 0, "send backcover link number", NULL_KEY);
}
}
//rez a page
//number is number of page
//open tells if page is on the left (when you browse the book backward) or the righ (normal reading)
//commands is various commands to send to the page, not used
rez_page(integer number, integer open, string commands)
{
rotation tmprot;
if (open)
{
tmprot = llGetRot();
//had a command so the page know its already on the left
setPageCommands(number, "alreadyopen");
}
else
{
tmprot = initialRot;
resetPageCommands(number);
}
//0.205 depends on the size of the book... to change for different sizes (PITA)
llRezObject("Page", initialPos + <0.205, 0, 0>, ZERO_VECTOR, tmprot, number);
}
//kill a page that is no longer visible.
kill_page(integer number)
{
//tell it to die
llWhisper(101,(string)getPage(number)+",die");
//remove from lists
resetPage(number);
resetPageCommands(number);
}
//cleanup when book closes
kill_all_pages()
{
integer i;
for (i=llGetListLength(page_keys) - 2 ; i >= 0 ; i-=2)
{
kill_page(llList2Integer(page_keys, i));
}
}
//send commands to a page, to tell it which texture to use and so on
send_page_commands(integer number)
{
//send page commands
if (hasPageCommands(number))
{
string commands = getPageCommands(number);
send_page_command(number, commands);
}
//set texture
key idtexture = llGetInventoryKey("page"+(string)number);
if (idtexture != NULL_KEY)
{
send_page_command(number, "texturefront,"+(string)idtexture);
}
//textures must be copy mod transfer, or else it doesnt work
idtexture = llGetInventoryKey("page"+(string)number+"b");
if (idtexture != NULL_KEY)
{
send_page_command(number, "textureback,"+(string)idtexture);
}
integer nbofcom = llGetListLength(pagecomments);
//send page descriptions
if ((number - 1)*2 < nbofcom)
{
send_page_command(number, "descfront,"+llList2String(pagecomments, (number - 1)*2));
}
if ((number - 1)*2+1 < nbofcom)
{
send_page_command(number, "descback,"+llList2String(pagecomments, (number - 1)*2+1));
}
}
send_page_command(integer number, string command)
{
key id = getPage(number);
llWhisper(101, (string)id+","+command);
}
default
{
state_entry()
{
init();
}
on_rez(integer start_param)
{
init();
}
run_time_permissions(integer perm)
{
//ask for perm
if ((perm & PERMISSION_CHANGE_LINKS) != 0)
{
state closed;
}
}
link_message(integer sender_number, integer number, string message, key id)
{
if (message == "backcover ready")
{
//store backcover link id
backcover_link_number = number;
backcover_key = llGetLinkKey(backcover_link_number);
}
}
}
state closed
{
touch_start(integer total_number)
{
open();
state opened;
}
moving_end()
{
initialPos = llGetPos();
initialRot = llGetRot();
}
link_message(integer sender_number, integer number, string message, key id)
{
if (message == "user clicked cover")
{
//the cover tells us user clicked: open book
open();
state opened;
}
else if (message == "backcover ready")
{
//store backcover link id
backcover_link_number = number;
backcover_key = llGetLinkKey(backcover_link_number);
}
}
timer()
{
//dead code?
llSetTimerEvent(0.0);
kill_all_pages();
}
}
state opened
{
touch_start(integer total_number)
{
//user clicked book, close
close();
state closed;
}
link_message(integer sender_number, integer number, string message, key id)
{
if (message == "user clicked cover")
{
//user clicked cover: close
close();
state closed;
}
else if (message == "backcover ready")
{
//store backcover link id
backcover_link_number = number;
backcover_key = llGetLinkKey(backcover_link_number);
}
}
timer()
{
llSetTimerEvent(0.0);
rez_page(1, FALSE, "");
}
object_rez(key id)
{
//page rezed, put it in our array
string tmpobjname = llKey2Name(id);
//page number is in its name
integer pagenumber = (integer)llGetSubString(tmpobjname, 5, -1);
setPage(pagenumber, id);
//send commands to page so it display the good texture and descriptions
send_page_commands(pagenumber);
}
listen(integer channel, string name, key id, string message)
{
//skip if not sent by one of our pages
if (!isOurPage(id))
{
return;
}
integer tmppagenumber = getPageNumber(id);
//one of our pages tell us something
if (llGetSubString(message, 0, 9) == "pageopened")
{
//The page has been flipped to the left, time to display next one
//rez next page
integer tmpnextpagenumber = tmppagenumber + 1;
if (tmpnextpagenumber <= number_of_pages)
{
rez_page(tmpnextpagenumber, FALSE, "");
}
integer tmppreviouspagenumber = tmppagenumber - 1;
if ( tmppreviouspagenumber > 0)
{
//tell previous page to die, it is no longer visible
kill_page(tmppreviouspagenumber);
}
}
else if (llGetSubString(message, 0, 9) == "pageclosed")
{
//The page has been flipped to the right, time to display the previous one
//rez previous page
integer tmppreviouspagenumber = tmppagenumber - 1;
if (tmppreviouspagenumber > 0)
{
rez_page(tmppreviouspagenumber, TRUE, "");
}
integer tmpnextpagenumber = tmppagenumber + 1;
if ( tmpnextpagenumber <= number_of_pages )
{
//tell next page to die
kill_page(tmpnextpagenumber);
}
}
}
moving_start()
{
//close the book when moved
close();
state closed;
}
state_entry()
{
llListenRemove(page_listener_id);
page_listener_id = llListen(102, "", NULL_KEY, "");
}
state_exit()
{
//clean up listener
if (page_listener_id == 0)
{
llListenRemove(page_listener_id);
}
}
}
This one in the cover
CODE
//Prim book scripts, animate a 3d prim book
//Copyright (C) 2005 Issarlk
//
//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 should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
default
{
touch_start(integer total_number)
{
llMessageLinked(LINK_ROOT, 0, "user clicked cover", NULL_KEY);
}
}