2008年03月05日
便利で危険なObjectZoomer
オブジェクトのサイズを自在に変更できるスクリプトです。
便利かなと思って使って見ましたが・・・
ちょっと使い方を間違うとオブジェクトがボコボコになってしまうこともw
大事なものに使うときはコピーをとってからにしてください。
まったく責任は持てませんので・・・
使い方は、プリムのコンテンツにこのスクリプトを入れて、
チャットからコマンドを入力します。
複数のプリムから成るオブジェクトでは、全部のプリムのコンテンツの中に入れます。
(プリム数が多いと実はこれがけっこう大変です。)
たくさん子プリムがあるときは、一度持ち物の中にスクリプトを作っておいて、
それをプリムのコンテンツにドラッグした方が便利そうです。
コマンドは、チャットから
/22 magnify=数値
指定した倍率で拡大縮小します。2は2倍、0.5は半分になります。
/22 size=数値
親プリムのサイズx,y,zで一番大きいものが指定した数値(メートル)になるようにします。
0.3は30センチ、5は5メートルです。
/22 remove
このスクリプトをプリムから取り除きます。
/22 info
含まれるすべてのプリムの番号、サイズ、位置、ローテーションなどの情報をオーナーにsayします。
/22 ch=番号
入力チャンネルを変更します。
ミスが起こりやすい点。
・このスクリプトをremoveするのを忘れて、
他のオブジェクトにコマンドを出したつもりが違うもののサイズも変わってビックリ。
・拡大とサイズ指定を勘違いしてとんでもなく大きく(小さく)してしまう。
・親プリムを基準にして拡大縮小するが、親といいながら実はオブジェクトの中で
一番小さかったりする場合は勘違いしやすい。
・縮小で小さいプリムが計算上1cm未満なるときや、
拡大で大きいプリムが計算上10メートルを超えるときに、
拡大縮小がうまくいかずに各オブジェクトの比率がおかしくなってしまう。
指定を勘違いしたときに起こしやすいが警告もなにも出ない。
しかもオブジェクトはボコボコに。
//ObjectZoomer.lsl ver1.0
integer LMN_SAY_INF = -9990010;
integer LMN_REMOVE_INVENTORY = -9990020;
integer LMN_MAGNIFY = -9990030;
integer chatcomandchannel = 22;
integer chatHandle;
integer isIntOrFloat(string s) {
s = llStringTrim(s,STRING_TRIM);
integer decimalPoint = llSubStringIndex(s,".");
integer sLen = llStringLength(s);
if (decimalPoint == -1) {
return isNum(s);
} else {
if (decimalPoint==0 ) { // e.g. .123
return isNum(llGetSubString(s, decimalPoint+1,sLen-1));
} else if (decimalPoint ==sLen-1) { // e.g. 123.
return isNum(llGetSubString(s, 0,decimalPoint-1));
} else {
string s1 = llGetSubString(s, 0, decimalPoint-1);
if (llSubStringIndex(s1," ")!=-1) { //search invalid sapces
return FALSE;
}
string s2 = llGetSubString(s, decimalPoint+1,sLen-1);
if (llSubStringIndex(s2," ")!=-1) { //search invalid sapces
return FALSE;
}
return isNum(s1) && isNum(s2);
}
}
}
integer isNum(string str){
integer int = (integer)str;
if(str == (string)int ) {
return TRUE;
} else {
return FALSE;
}
}
startListen() {
removeListen(); //append
llOwnerSay("PrimName=" + llGetObjectName()
+ " channel=" + (string)chatcomandchannel +" is opened." );
chatHandle = llListen(chatcomandchannel , "", llGetOwner(), "");
}
removeListen() {
if (chatHandle!=0) {
llOwnerSay("PrimName=" + llGetObjectName() + " channel="
+ (string)chatcomandchannel + " is closed.");
llListenRemove(chatHandle);
chatHandle = 0;
}
}
command(string message) {
if (llToLower(llGetSubString(message,0, 7))=="magnify=") {
string operand = llGetSubString(message, 8, llStringLength(message)-1);
if (isIntOrFloat(operand)) {
llMessageLinked(LINK_SET, LMN_MAGNIFY, operand, NULL_KEY);
return;
}
} else if (llToLower(llGetSubString(message,0, 4))=="size=") {
string operand = llGetSubString(message, 5, llStringLength(message)-1);
if (isIntOrFloat(operand)) {
float size = (float)operand;
vector v = llGetScale();
float max = v.x;
if (v.y > max) max=v.y;
if (v.z > max) max=v.z;
float mag = size / max;
llMessageLinked(LINK_SET, LMN_MAGNIFY,(string)mag , NULL_KEY);
return;
}
} else if (llToLower(llGetSubString(message,0, 5))=="remove") {
llMessageLinked(LINK_SET, LMN_REMOVE_INVENTORY, "", NULL_KEY);
return;
} else if (llToLower(llGetSubString(message,0, 3))=="info") {
llMessageLinked(LINK_SET, LMN_SAY_INF, "", NULL_KEY);
return;
} else if (llToLower(llGetSubString(message,0, 2))=="ch=") {
string operand = llGetSubString(message, 3, llStringLength(message)-1);
if (isNum(operand)) {
chatcomandchannel = (integer)operand;
if ( chatcomandchannel >=1 && chatcomandchannel<=99) {
startListen();
return;
}
}
}
llOwnerSay("\"" + message + "\"" + " is an invalid command. ");
}
integer getLastNumericIdx(string s) {
integer i;
integer j;
integer idx = -1;
for (j=0;j< llStringLength(s);j++) {
for (i=0;i<10;i++) {
string ss =llGetSubString(s, j, j);
integer pos = llSubStringIndex(ss, (string)i);
if (pos!=-1) {
idx = pos+j;
}
}
}
return idx;
}
string getCoreScriptName(string s) {
integer idx = llStringLength(s);
while (idx!=-1) {
s = llGetSubString(s, 0, idx-1);
idx = getLastNumericIdx(s);
}
return llStringTrim(s, STRING_TRIM_TAIL);
}
default {
state_entry() {
//Prevent duplicate of this script in a prim. When this script is dragged, previous same script will be removed.
//When same name script put into a content of prims, new script name will be "foo 1".
string scriptName = llGetScriptName();
string coreName = getCoreScriptName(scriptName);
integer i;
for (i=0;i<2;i++) {
string tail = " " + (string)i;
if (i==0) {
tail = "";
}
string name = coreName + tail;
if ( (scriptName!=name) && ( llGetInventoryType(name) == INVENTORY_SCRIPT) ) {
llRemoveInventory(name);
}
}
llMessageLinked(llGetLinkNumber(), LMN_SAY_INF, "", NULL_KEY);
// 0 is single prime object. 1 is parent prim of an object. Greater Equal 2 is child prim of an object.
// Child prims does not listen. Parent prim listens a chat command. A Parent prim notify a command to child prim by a message link.
if (llGetLinkNumber()<2) {
startListen();
}
}
on_rez(integer sparam) { //rez, attach, log in
// 0 is single prime object. 1 is parent prim of an object. Greater Equal 2 is child prim of an object.
if ( llGetLinkNumber()<2) {
startListen();
}
}
listen(integer channel, string name, key id, string message) {
if (channel == chatcomandchannel ) {
command(message);
}
}
//In the case of an object has many prims, if many links are breaked, many child prims will be parents and listeners.
//Many listeners burden a SIM. So these codes are removed.
//~ changed(integer change) {
//~ // linked/unlinked/sat on
//~ if (change & CHANGED_LINK) {
//~ // 0 is single prime object. 1 is parent prim of an object. Greater Equal 2 is a child prim of an object.
//~ if (llGetLinkNumber()<2) {
//~ startListen();
//~ } else {
//~ removeListen();
//~ }
//~ }
//~ }
link_message(integer sender_num, integer num, string str, key id) {
if (num==LMN_SAY_INF) {
llOwnerSay("info\n**PrimName=" + llGetObjectName() + " Script=" + llGetScriptName() + " LinkNo="
+ (string)llGetLinkNumber()
+ "\n**Gpos " + (string)llGetPos()
+ "\n**Lpos " + (string)llGetLocalPos()
+ "\n**Scale " + (string)llGetScale()
+ "\n**Rot " + (string)(llRot2Euler(llGetRot())*RAD_TO_DEG)
);
} else if (num==LMN_REMOVE_INVENTORY) {
llOwnerSay("Script \"" + llGetScriptName() + "\" is removed from " + llGetObjectName());
removeListen();
llRemoveInventory(llGetScriptName());
} else if (num==LMN_MAGNIFY) {
float mag = (float)str;
vector s = llGetScale();
s.x *= mag;
s.y *= mag;
s.z *= mag;
llSetScale(s);
if (llGetLinkNumber()>1) {
vector p = llGetLocalPos();
p.x *= mag;
p.y *= mag;
p.z *= mag;
llSetPos(p);
}
}
}
}

この記事へのトラックバックURL
http://tanakaakio.slmame.com/t163024


