まず、surface 用のスクリプトでは、size = <10.0, 10.0, 10.0> としておきます。
次に、20m cube を、8つの 10m cube に分解して、それぞれの cube の 3つの surface を作るスクリプトです。
vector size = <10.0, 10.0, 10.0>; integer rezParam; rezRectangle(string surface, vector pos, integer param) { llRezAtRoot(surface, pos, <0.0, 0.0, 0.0>, ZERO_ROTATION, param); } rezRectangles() { string surface = llGetInventoryName(INVENTORY_OBJECT, 0); vector pos = llGetPos(); if (rezParam & 1) { rezRectangle(surface, pos + <-size.x/2, 0.0, 0.0>, 1); } if (rezParam & 2) { rezRectangle(surface, pos + < size.x/2, 0.0, 0.0>, 1); } if (rezParam & 4) { rezRectangle(surface, pos + < 0.0,-size.y/2, 0.0>, 2); } if (rezParam & 8) { rezRectangle(surface, pos + < 0.0, size.y/2, 0.0>, 2); } if (rezParam & 16) { rezRectangle(surface, pos + < 0.0, 0.0,-size.z/2>, 3); } if (rezParam & 32) { rezRectangle(surface, pos + < 0.0, 0.0, size.z/2>, 3); } } setInvisible() { llSetScale(<0.01, 0.01, 0.01>); llSetAlpha(0.0, ALL_SIDES); } default { state_entry() { } touch_start(integer n) { if (rezParam > 0) { llRequestPermissions(llGetOwner(), PERMISSION_CHANGE_LINKS); } } on_rez(integer param) { rezParam = param; } run_time_permissions(integer perm) { if (perm & PERMISSION_CHANGE_LINKS) { rezRectangles(); setInvisible(); } } object_rez(key id) { llCreateLink(id, TRUE); } } |
これは、次のスクリプトを含むオブジェクトから、rez されますが、そのときのパラメータから、どの surface をつくるか決定します。例えば、21 = 1 + 4 + 16 の場合、1 により、X軸(東西)の西側の面を作成します。同様に、4 は Y軸(南北)の南側の面、... となります。
Rez のときには、パラメータを保存するだけで、実際には touch されてから、surface(s) を rez して、link します。これは、全体では 24 = 3 x 8 = 4 x 6 個の 10m x 10m surface になり、llCreateLink() は 1秒間 sleep するため、一気にすべて rez してしまうと、event queue が overflow してしまうためです。これは、複数のオブジェクトを link するときの重要な注意点で、できるだけ、使用時ではなく、事前にlink しておくことが大切です。このため、スクリプトを作成時用と使用時用の 2つを準備することになり、少し煩雑になってしまいます。
次に、上記のスクリプトを含む 8つのオブジェクトを生成するスクリプトです。
rezCube(string object, vector pos, integer param) { llRezObject(object, pos, <0.0, 0.0, 0.0>, ZERO_ROTATION, param); } rezCubes() { string object = llGetInventoryName(INVENTORY_OBJECT, 0); vector pos = llGetPos(); rezCubesX(object, pos, 0); } rezCubesX(string object, vector pos, integer param) { rezCubesY(object, pos + <-5.0, 0.0, 0.0>, param+1); rezCubesY(object, pos + < 5.0, 0.0, 0.0>, param+2); } rezCubesY(string object, vector pos, integer param) { rezCubesZ(object, pos + <0.0, -5.0, 0.0>, param+4); rezCubesZ(object, pos + <0.0, 5.0, 0.0>, param+8); } rezCubesZ(string object, vector pos, integer param) { rezCube(object, pos + <0.0, 0.0, -5.0>, param+16); rezCube(object, pos + <0.0, 0.0, 5.0>, param+32); } default { state_entry() { } touch_start(integer n) { key owner = llGetOwner(); integer i; for (i = 0; i < n; i++) { if (llDetectedKey(i) == owner) { rezCubes(); } } } } |
このスクリプトと、上記のスクリプトを含むオブジェクトをもつ prim を作成して、touch すると、それを中心に、立体的に 8つの prim が配置されるので、それぞれを順番に touch していくことにより、20m cube が作成されます。ただし、この時点では、8つの parts は link されていません。また、touch するときは、event queue が overflow しないように、あまり急ぎすぎては、いけません。
つづく
Tags: programming, second_life