Skip to content

Instantly share code, notes, and snippets.

@masterpoppy
Created April 27, 2017 14:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save masterpoppy/52139ebf25ebfc8565ddd7d42c4d2aca to your computer and use it in GitHub Desktop.
Save masterpoppy/52139ebf25ebfc8565ddd7d42c4d2aca to your computer and use it in GitHub Desktop.
// ************************************
// Attachment Analyzer.lsl
// 2017-03-29 MasterPoppy
// ************************************
key url_request;
string URI;
string HTML_BODY =
"<!DOCTYPE html>
<html>
<head>
<meta charset='UTF-8'>
<script type='text/javascript' src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.7/semantic.min.js'></script>
<link rel='stylesheet' type='text/css' href='https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.7/semantic.min.css' />
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery.tablesorter/2.28.3/js/jquery.tablesorter.min.js'></script>
<style type='text/css'>
@import url(http://fonts.googleapis.com/earlyaccess/notosansjp.css);
html, body {
background-color: #000000;
}
html, body, .ui, .item {
font-family: 'Noto Sans', 'Noto Sans Japanese', arial, helvetica, 'hiragino kaku gothic pro', meiryo, 'MS PGothic';
}
.ui,
.item,
.ui.header,
.ui.table,
.ui.top.attached.segment {
font-size: 1.3rem;
}
.ui.container {
padding-top: 2px;
width: 100vw;
}
.ui.bottom.attached.segment {
height: calc(100vh - 115px);
overflow-y: auto;
}
.ui.inverted.sortable.table thead th {
color: rgba(255,255,255,.9);
}
#field1 > div {
background-color: rgba(255,255,255,.08);
}
#field1 > div > i {
color: #ffffff;
}
#field1 > div > div {
background-color: #333333;
}
#field1 > div > div > div {
color: #dddddd;
border-color: #666666;
}
table > thead > tr,
table > thead > tr > th > div{
text-align: center;
}
#targetlist tbody tr:hover {
cursor: pointer;
}
</style>
<script>
var option;
var param = [1, 2, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19, 30, 31, 34];
$(document).ready(function() {
$('.dimmer').dimmer('show');
$.ajax({
'type': 'POST',
'url': location.href,
'data': 'loadoption'
}).done(function(data) {
option = data.split(',');
$('.ui.fluid.dropdown').dropdown('set selected',option);
render_table(option);
load('owner');
$('.ui.fluid.dropdown').change(function() {
option = $('select').val();
$.ajax({
'type': 'POST',
'url': location.href,
'data': JSON.stringify({
'saveoption': option.join(',')
})
})
render_table(option);
});
});
}, false);
function load(target) {
$('.dimmer').dimmer('show');
$('#field1,#username').show();
$('#error2').text('');
$('#field2,#error').hide();
$('#scan').html('<b>Scan</b>');
$('#datatable>tbody').empty();
mode = 0;
$.ajax({
'type': 'POST',
'url': location.href,
'data': JSON.stringify({
'getlist': target
})
}).done(function(data) {
$('#username').html('<i></i>' + data.name).children().addClass('user icon');
$.each(data.list, function(i, val1){
$.ajax({
'type': 'POST',
'url': location.href,
'data': JSON.stringify({
'detail': val1
})
}).done(function(response) {
var tr = $('<tr></tr>');
$.each(response, function(j, val2) {
if (j == 8) {
val2 = 'secondlife:///app/agent/' + val2 + '/about';
tr.append($('<td value=' + j + '></td>').html($('<a></a>').attr({href: val2}).html($('<i></i>').addClass('user icon'))));
} else {
tr.append($('<td value=' + j + '></td>').text(val2));
}
});
$('#datatable>tbody').append(tr.hide().fadeIn(250));
var sum = [ 9, 10, 11, 12, 13, 14, 15, 16, 30, 31, 34 ];
$.each(sum, function(k, val3) {
var total = 0;
var result = {};
$('#datatable>tbody>tr').each(function(l, val4) {
point = $(this).find('td[value=' + val3 + ']').text();
point = point.split(' ');
total += parseFloat(point[0]);
});
var unit = '';
if(point[1]) {
unit = ' ' + point[1];
}
if(val3 == 12){
total = total.toFixed(3);
}
if(val3 == 15){
total = total.toFixed(6);
}
$('#datatable>tfoot>tr>th[value=' + val3 + ']').text(total + unit);
});
$('#datatable').trigger('update', [true]);
render_table(option);
if( i == data.list.length - 1){
$('.dimmer').dimmer('hide');
}
});
});
}).fail(function(data) {
$('#error2').text(data.status + ':' + data.statusText);
$('#error').show();
$('.dimmer').dimmer('hide');
});
}
function tablesort() {
$('#datatable').trigger('update', [true]);
}
function render_table(cfg) {
$('#datatable>thead>tr>th,#datatable>tbody>tr>td,#datatable>tfoot>tr>th').hide();
$.each(cfg, function(i, val) {
$('thead>tr>th[value=' + val + ']').show();
$('tbody>tr>td[value=' + val + ']').show();
$('tfoot>tr>th[value=' + val + ']').show();
});
}
var mode = 0;
$(function() {
$('#datatable').tablesorter({
widgets: ['columns']
});
$('#targetlist').tablesorter({
widgets: ['columns']
});
$('.ui.fluid.dropdown').dropdown();
$('#scan').click(function() {
mode = 1 - mode;
$('#error').hide();
if (mode) {
$('.dimmer').dimmer('show');
$('#scan').html('<b>Back</b>');
$('#field1,#username').hide();
$('#field2').show();
$('#targetlist>tbody').empty();
$.ajax({
'type': 'POST',
'url': location.href,
'data': 'scan'
}).done(function(data) {
$.each(data, function(i, val) {
$('#targetlist>tbody')
.append(
$('<tr></tr>')
.attr({
value: val.key
})
.append($('<td></td>').text(val.name))
.append($('<td></td>').text(val.range))
.append($('<td></td>').text(val.attach))
.append($('<td></td>').text(val.renderweight))
.append($('<td></td>').text(val.scriptmemory))
.append($('<td></td>').text(val.scripttime))
.click(function(e) {
load($(this).attr('value'));
})
);
});
$('#targetlist').trigger('update', [true]);
$('.dimmer').dimmer('hide');
});
} else {
$('.dimmer').dimmer('show');
$('#scan').html('<b>Scan</b>');
$('#field1,#username').show();
$('#field2').hide();
$('.dimmer').dimmer('hide');
}
});
$('#minimize').on('click', function() {
$.ajax({
'type': 'POST',
'url': location.href,
'data': 'minimize'
});
});
});
$(document).on('wheel', function(e) {
e.preventDefault();
$('#area').animate({ scrollTop: $('#area').scrollTop() + 28 * Math.sign(e.originalEvent.deltaY) }, 10);
return false;
});
</script>
</head>
<body>
<div id='main' class='ui container'>
<div id='id-header' class='ui top attached inverted segment'>
<h3>Attachment Analyzer</h3>
</div>
<div class='ui middle attached inverted menu'>
<div class='menu'>
<a id='scan' class='item'><b>Scan</b></a>
</div>
<div class='menu'>
<div id='username' class='item'><i class='user icon'></i>USRNAME</div>
</div>
<div class='right menu'>
<a id='minimize' class='item'><b>Minimize</b></a>
</div>
</div>
<div id='area' class='ui bottom attached inverted segment'>
<div class='ui dimmer show'>
<div class='ui text loader'>Loading</div>
</div>
<div id='field1'>
<select name='parameter' multiple='' class='ui inverted fluid dropdown'>
<option value=''>Parameter</option>
<option value='1'>Object Name</option>
<option value='2'>Object Desc</option>
<option value='8'>Creator</option>
<option value='9'>Running Script</option>
<option value='10'>Total Script</option>
<option value='11'>Script Memory</option>
<option value='12'>Script Time</option>
<option value='13'>Prim Equivalence</option>
<option value='14'>Server Cost</option>
<option value='15'>Streaming Cost</option>
<option value='16'>Physics Cost</option>
<option value='19'>Attached Point</option>
<option value='30'>Prim Count</option>
<option value='31'>Total Inventory</option>
<option value='34'>Temp Attached</option>
</select>
<table id='datatable' class='ui sortable celled padded inverted table'>
<thead>
<tr>
<th value='1'>Object Name</th>
<th value='2'>Object Desc</th>
<th value='8'>Creator</th>
<th value='9'>Running Script</th>
<th value='10'>Total Script</th>
<th value='11'>Script Memory</th>
<th value='12'>Script Time</th>
<th value='13'>Prim Equivalence</th>
<th value='14'>Server Cost</th>
<th value='15'>Streaming Cost</th>
<th value='16'>Physics Cost</th>
<th value='19'>Attached Point</th>
<th value='30'>Prim Count</th>
<th value='31'>Total Inventory</th>
<th value='34'>Temp Attached</th>
</tr>
</thead>
<tbody></tbody>
<tfoot>
<tr>
<th value='1'>Total</th>
<th value='2'></th>
<th value='8'></th>
<th value='9'>-</th>
<th value='10'>-</th>
<th value='11'>-</th>
<th value='12'>-</th>
<th value='13'>-</th>
<th value='14'>-</th>
<th value='15'>-</th>
<th value='16'>-</th>
<th value='19'></th>
<th value='30'>-</th>
<th value='31'>-</th>
<th value='34'>-</th>
</tr>
</tfoot>
</table>
</div>
<div id='field2' hidden>
<table id='targetlist' class='ui sortable celled padded inverted selectable table'>
<thead>
<tr>
<th class='collapsing'>Name</th>
<th>Range</th>
<th>Attachment</th>
<th>Render Weight</th>
<th>Script Memory</th>
<th>Script Time</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
<div id='error' class='ui negative message' hidden>
<div id='error1' class='header'>Error</div>
<p id='error2'></p>
</div>
</div>
</div>
</body>
</html>
";
string attach_point;
list list_attach_point = [
"1", "Chest / Sternum",
"2", "Head",
"3", "Left Shoulder",
"4", "Right Shoulder",
"5", "Left Hand",
"6", "Right Hand",
"7", "Left Foot",
"8", "Right Foot",
"9", "Back",
"10", "Pelvis",
"11", "Mouth",
"12", "Chin",
"13", "Left Ear",
"14", "Right Ear",
"15", "Left Eye",
"16", "Right Eye",
"17", "Nose",
"18", "Right Upper Arm",
"19", "Right Lower Arm",
"20", "Left Upper Arm",
"21", "Left Lower Arm",
"22", "Right Hip",
"23", "Right Upper Leg",
"24", "Right Lower Leg",
"25", "Left Hip",
"26", "Left Upper Leg",
"27", "Left Lower Leg",
"28", "Belly / Stomach / Tummy",
"29", "Left Pectoral",
"30", "Right Pectoral",
"39", "Neck",
"40", "Avatar Center / Root",
"41", "Left Ring Finger",
"42", "Right Ring Finger",
"43", "Tail Base",
"44", "Tail Tip",
"45", "Left Wing",
"46", "Right Wing",
"47", "Jaw",
"48", "Left Ear (extended)",
"49", "Right Ear (extended)",
"50", "Left Eye (extended)",
"51", "Right Eye (extended)",
"52", "Tongue",
"53", "Groin",
"54", "Left Hind Foot",
"55", "Right Hind Foot"
];
key owner;
on()
{
llSetLinkPrimitiveParamsFast(LINK_THIS, [
PRIM_SIZE, <0.040, 0.800, 1.600>,
PRIM_ROT_LOCAL, llEuler2Rot( <0, 0, 0> )
]);
}
off()
{
list current = llGetLinkPrimitiveParams(LINK_THIS, [PRIM_SIZE,PRIM_POS_LOCAL]);
llSetLinkPrimitiveParamsFast(LINK_THIS, [
PRIM_SIZE, <0.040, 0.160, 0.040>,
PRIM_ROT_LOCAL, llEuler2Rot( <0, -PI_BY_TWO, 0> )
]);
}
string check_memory()
{
float freemem = 64.0 - llGetFreeMemory() / 1024.0;
return (string)freemem + " / 64 kbyte (" + llDeleteSubString((string)(0.01 * (float)llFloor(10000 * (freemem / 64.0))), -4 , -1) + " %)";
}
default
{
state_entry()
{
if(llGetAttached()){
url_request = llRequestURL();
owner = llGetOwner();
attach_point = llList2Json(JSON_OBJECT, list_attach_point);
list_attach_point = [];
}
}
attach(key attached)
{
llResetScript();
}
touch_end(integer index)
{
on();
}
changed(integer change)
{
if(change & CHANGED_REGION || change & CHANGED_REGION_START){
llReleaseURL(URI);
url_request = llRequestURL();
}
else if(change & CHANGED_OWNER){
llSetText("1,8,12,15,19", ZERO_VECTOR, 0);
on();
}
}
http_request(key id, string method, string body)
{
if (url_request == id)
{
url_request = "";
if (method == URL_REQUEST_GRANTED){
URI = body;
//llOwnerSay(URI);
//llSetObjectDesc(URI);
integer status = llSetLinkMedia(LINK_THIS, 4, [
PRIM_MEDIA_HOME_URL, body,
PRIM_MEDIA_CURRENT_URL, body,
PRIM_MEDIA_AUTO_ZOOM, TRUE,
PRIM_MEDIA_AUTO_PLAY, TRUE,
PRIM_MEDIA_AUTO_SCALE, FALSE,
PRIM_MEDIA_WIDTH_PIXELS, 1024,
PRIM_MEDIA_HEIGHT_PIXELS, 1024,
PRIM_MEDIA_PERMS_INTERACT, PRIM_MEDIA_PERM_NONE,
PRIM_MEDIA_PERMS_CONTROL, PRIM_MEDIA_PERM_NONE
]);
llSetTimerEvent(15.0);
}
}
else{
if(method == "GET" || method == "HEAD"){
llSetTimerEvent(0);
llSetContentType(id, CONTENT_TYPE_HTML);
if(HTML_BODY != ""){
llHTTPResponse(id, 200, HTML_BODY);
HTML_BODY = "";
}
else{
llHTTPResponse(id, 200, "<font face='Arial'>Restarting Script...</font>");
llResetScript();
}
}
else if(method == "POST"){
string json;
integer i;
integer j;
integer k;
list param = [1, 2, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19, 30, 31, 34];
integer total_param = llGetListLength(param);
list AttachedList;
list data;
integer p;
string val;
string temp;
string load = llJsonGetValue(body, ["load"]);
string getlist = llJsonGetValue(body, ["getlist"]);
string detail = llJsonGetValue(body, ["detail"]);
string saveoption = llJsonGetValue(body, ["saveoption"]);
if(body == "scan"){
list agent = llGetAgentList(AGENT_LIST_REGION, []);
vector pos = llGetPos();
integer scantotal = llGetListLength(agent);
data = [];
for(i = 0; i < scantotal; i++){
key uuid = llList2Key(agent, i);
list value = llGetObjectDetails(uuid, [OBJECT_POS]);
data += [ llVecDist(pos, llList2Vector(value, 0) ), uuid ];
}
data = llList2List(llListSort(data, 2, TRUE),0, 2 * 12 - 1);
json = "{}";
for(i = 0; i < llGetListLength(data) / 2; i++){ //16
//for(i = 0; i < 12; i++){ //16
key uuid = llList2Key(data, 2 * i + 1);
list value = llGetObjectDetails(uuid, [OBJECT_RENDER_WEIGHT, OBJECT_SCRIPT_MEMORY, OBJECT_SCRIPT_TIME]);
json = llJsonSetValue(json, [JSON_APPEND],
llList2Json(JSON_OBJECT, [
"range", llDeleteSubString((string)llList2Float(data, 2 * i + 0), -5, -1) + " m",
"name", llGetDisplayName(uuid) + " (" + llGetUsername(uuid) + ")",
"key", uuid,
"attach", llGetListLength(llGetAttachedList(uuid)),
"renderweight", llList2Integer(value, 0),
"scriptmemory", (string)(llList2Integer(value, 1) / 1024) + " kbyte",
"scripttime", llDeleteSubString((string)(1000 * llList2Float(value, 2)), -3 , -1) + " msec"
] )
);
}
data = [];
llSetContentType(id, CONTENT_TYPE_JSON);
llHTTPResponse(id, 200, json);
json = "{}";
}
else if(body == "minimize"){
off();
}
else if(body == "loadoption"){
string cfg = llList2String(llGetLinkPrimitiveParams(LINK_THIS, [PRIM_TEXT]), 0);
if(cfg == ""){
cfg = "1,9,12,15,19";
llSetText(cfg, ZERO_VECTOR, 0);
}
llSetContentType(id, CONTENT_TYPE_TEXT);
llHTTPResponse(id, 200, cfg);
}
else if(saveoption != JSON_INVALID){
llSetText(saveoption, ZERO_VECTOR, 0);
}
else if(getlist != JSON_INVALID){
if(getlist == "owner"){
load = (string)owner;
AttachedList = llGetAttachedList(owner);
}
else{
AttachedList = llGetAttachedList((key)getlist);
}
json = llJsonSetValue(json, ["list"], llList2Json(JSON_ARRAY, AttachedList) );
if(getlist == "owner"){
getlist = (string)owner;
}
json = llJsonSetValue(json, ["name"], llGetDisplayName((key)getlist));
llSetContentType(id, CONTENT_TYPE_JSON);
llHTTPResponse(id, 200, json);
}
else if(detail != JSON_INVALID){
data = llGetObjectDetails((key)detail, param);
for(i = 0; i < total_param; i++){
p = llList2Integer(param, i);
val = llList2String(data, i);
if(p == OBJECT_ATTACHED_POINT){
val = llJsonGetValue(attach_point, [val]);
}
else if(p == OBJECT_SCRIPT_MEMORY){
val = (string)((integer)val / 1024) + " kbyte";
}
else if(p == OBJECT_SCRIPT_TIME){
val = llDeleteSubString((string)(1000 * (float)val), -3 , -1) + " msec";
}
json = llJsonSetValue(json, [(string)p], val);
}
llSetContentType(id, CONTENT_TYPE_JSON);
llHTTPResponse(id, 200, json);
json = "";
}
else{
llSay(DEBUG_CHANNEL, llList2CSV(llJson2List(body)));
llSetContentType(id, CONTENT_TYPE_TEXT);
llHTTPResponse(id, 500, "Internal Server Error");
}
}
}
}
timer()
{
string lang = llGetAgentLanguage(owner);
if(lang == "ja"){
llRegionSayTo(owner, 0,
"画面が切り替わらないときはメディア再生のチェックが入っているか確認してもう一度HUDをタッチしてください。 "
+"メディア再生にチェックをいれても切り替わらないときはさらに自動再生のチェックをいれてください。 "
+"くわしい解説はこちらのURLを参照してください。 https://gyazo.com/1ae8b76e311c23820b7e3de7496c1901"
);
}
else{
llRegionSayTo(owner, 0,
"Confirm that `Media` checkbox is enabled and touch HUD again if screen does not switch. "
+"If screen will not switch in spite of `Media` checkbox enabled, enable Auto-Play checkbox additionally. "
+"Refer to following URL for the detail instruction. https://gyazo.com/b72373407667625aaf7798bc30fc09a5"
);
}
llSetTimerEvent(0);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment