2010年1月31日日曜日

Album (Book) script

//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.
 
 
//Keep closed position in memory, so as to not have the book slowly
//changing position as it get openned and closed because of math
//precission
vector initialPos;
rotation initialRot;
 
//Keep the cover's size in memory, we send it to newly rezzed pages
//so they adjust their size accordingly
vector coversize;
 
//List of keys of our pages, used to recognise messages aimed at us
//(allows several books to be used next to one another without interferences)
list page_keys;
//commands to send to a page
list page_commands;
 
integer page_listener_id = 0;
 
//Comments for each page, display next to pointer
//Filled from notecard
list pagecomments;
 
//Type of page naming.
integer pagenaming; //0=numerical 1=alphabetic order
list pagetexturenames = []; //used for alphabetic order
 
//notecard reading
integer line;
key queryid;
 
 
 
 
init()
{
initialPos = llGetPos();
initialRot = llGetRot();
page_keys = [];
page_commands = [];
pagecomments = [];
llListenRemove(page_listener_id);
page_listener_id = 0;
//tell backcovers that the book is closed
llMessageLinked(LINK_ALL_OTHERS, 0, "closed", NULL_KEY);
//tell cover to tell everyone its size
askCoverSize();
}
 
 
// 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()
{
//tell backcovers we are openning, backcover will turn transparent
llMessageLinked(LINK_ALL_OTHERS, 0, "open1", NULL_KEY);
//rotate book
llSetRot(llEuler2Rot(<0, 0, PI_BY_TWO>)*initialRot);
llSetRot(llEuler2Rot(<0, 0, PI>)*initialRot);
//tell backcovers we are open, backcover open version will turn visible
llMessageLinked(LINK_ALL_OTHERS, 0, "open", NULL_KEY);
}
 
 
//same, but closes
close()
{
//kill all pages in world
kill_all_pages();
//close book
//tell backcovers we are closing, backcover open version will turn transparent
llMessageLinked(LINK_ALL_OTHERS, 0, "close1", NULL_KEY);
//rotate book
llSetRot(llEuler2Rot(<0, 0, PI_BY_TWO>)*initialRot);
llSetRot(initialRot);
llSetPos(initialPos);
//tell backcovrs we are closed, backcover wil turn visible
llMessageLinked(LINK_ALL_OTHERS, 0, "closed", 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 = llGetRootRotation();
if (open)
{
//had a command so the page know its already on the left
setPageCommands(number, "alreadyopen");
}
else
{
//Page is open, rotate it on its z axis
tmprot = llEuler2Rot(<0, 0, PI>) * tmprot;
resetPageCommands(number);
}
 
llRezAtRoot("Page", llGetRootPosition(), 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 size
send_page_command(number, llList2CSV(["size", coversize]));
//set texture
list textures = texturesForPage(number);
key idtexture = llGetInventoryKey(llList2String(textures, 0));
if (idtexture != NULL_KEY)
{
send_page_command(number, "texturefront,"+(string)idtexture);
}
//textures must be copy mod transfer, or else it doesnt work
idtexture = llGetInventoryKey(llList2String(textures, 1));
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, llList2CSV([id,command]));
}
 
//Return texture name by its number
string textureNumber(integer number) {
if (pagenaming == 0) {
//numeric order, pages are named "page1" "page2" etc.
return "page"+(string)number;
} else {
return llList2String(pagetexturenames, number - 1);
}
}
 
 
//Read texture names for alphabetical mode
loadTextureList() {
integer nb = llGetInventoryNumber(INVENTORY_TEXTURE);
integer i;
pagetexturenames = [];
for (i = 0 ; i < nb ; i++) {
pagetexturenames = pagetexturenames + [llGetInventoryName(INVENTORY_TEXTURE, i)];
}
}
 
//return texture names that are supposed to go into page
list texturesForPage(integer pagenumber) {
return [textureNumber(pagenumber * 2 - 1), textureNumber(pagenumber * 2)];
}
 
 
//Check inventory to see if page exist
integer pageExists(integer pagenumber) {
list textures = texturesForPage(pagenumber);
if ((llGetInventoryType(llList2String(textures, 0)) == INVENTORY_TEXTURE) || (llGetInventoryType(llList2String(textures, 1)) == INVENTORY_TEXTURE)) {
//page exists
return 1;
} else {
//page doesn't exist (no texture to display)
return 0;
}
}
 
 
//Ask cover about its size
askCoverSize() {
llMessageLinked(LINK_ALL_OTHERS, 0, "get cover size", NULL_KEY);
}
 
 
//////////////////////
// States
//////////////////////
 
default
{
state_entry()
{
init();
}
 
on_rez(integer start_param)
{
init();
}
 
link_message(integer sender, integer num, string str, key id) {
//receive cover size
if (num == 10) {
coversize = (vector)str;
state readcomments;
}
}
 
changed(integer change) {
if ((change & CHANGED_SCALE) != 0) {
askCoverSize();
}
}
}
 
state readcomments {
state_entry() {
if (llGetInventoryType("Comments") != INVENTORY_NOTECARD) {
//No comments notecard
state readsettings;
} else {
line = 0;
queryid = llGetNotecardLine("Comments", line);
}
}
 
dataserver(key queryidarg, string data) {
if (queryidarg == queryid) {
if (data != EOF) {
//Read one comment, append to list
pagecomments = pagecomments + [data];
//read next
line++;
queryid = llGetNotecardLine("Comments", line);
} else {
//No more comments
state readsettings;
}
}
}
}
 
state readsettings {
state_entry() {
if (llGetInventoryType("Settings") != INVENTORY_NOTECARD) {
//No settings
state closed;
} else {
line = 0;
queryid = llGetNotecardLine("Settings", line);
}
}
 
dataserver(key queryidarg, string data) {
if (queryidarg == queryid) {
if (data != EOF) {
list settingline = llParseString2List(data,[":"],[]);
if (llList2String(settingline, 0) == "PageNaming") {
//alternate page naming
string naming = llList2String(settingline, 1);
if (naming == "alphabetical") {
pagenaming = 1;
loadTextureList();
} else if (naming == "numerical") {
pagenaming = 0;
} else {
llOwnerSay("Unknown PageNaming: " + naming);
}
}
//read next
line++;
queryid = llGetNotecardLine("Settings", line);
} else {
//No more settings
state closed;
}
}
}
}
 
state closed
{
touch_start(integer total_number)
{
open();
state opened;
}
 
moving_end()
{
//book moved, remember new pos
initialPos = llGetPos();
initialRot = llGetRot();
}
 
 
link_message(integer sender_number, integer number, string message, key id)
{
if (number == 10) {
//new cover size
coversize = (vector)message;
} else if (message == "user clicked cover")
{
//the cover tells us user clicked: open book
open();
state opened;
}
}
 
changed(integer change) {
if ((change & CHANGED_SCALE) != 0) {
//size changed, tell cover to tell everyone its new size
askCoverSize();
}
}
}
 
 
state opened
{
state_entry()
{
llListenRemove(page_listener_id);
page_listener_id = llListen(102, "", NULL_KEY, "");
rez_page(1, FALSE, "");
}
 
touch_start(integer total_number)
{
//user clicked book, close
close();
state closed;
}
 
link_message(integer sender_number, integer number, string message, key id)
{
if (number == 10) {
//new cover size
coversize = (vector)message;
} else if (message == "user clicked cover") {
//user clicked cover: close
close();
state closed;
}
}
 
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 displays 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 (pageExists(tmpnextpagenumber))
{
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 ( pageExists(tmpnextpagenumber) )
{
//tell next page to die
kill_page(tmpnextpagenumber);
}
}
}
 
moving_end()
{
//book moved, remember new pos ; rotate by PI so we remember closed pos
initialPos = llGetPos();
initialRot = llEuler2Rot(<0,0, - PI>) * llGetRot();
}
 
changed(integer change) {
if ((change & CHANGED_SCALE) != 0) {
//size changed, tell cover to tell everyone its new size
askCoverSize();
}
}
 
state_exit()
{
//clean up listener
llListenRemove(page_listener_id);
}
}

1 件のコメント:

  1. old type
    閉じたら位置が変更される?!詳しく見ておりません。
    現在普通、画像を先に読み込ませ、表示を早くするものがありますので参考まで

    返信削除