mirror of
https://github.com/Sei-Lisa/LSL-PyOptimizer
synced 2025-07-01 23:58:20 +00:00
Change strategy for the checking of function input types.
Rather than assert that the types are correct, use the force type functions on the parameters: ff, fk, fs, q2f, v2f, and the new fi, fl. These functions have also been modified to ensure that the input type supports an implicit typecast to the target type and perform it, or emit ELSLInvalidType otherwise, rather than an assertion failure. fl in particular returns the original list if it isn't changed, or a copy if it is. A couple bugs were found in testfuncs.py as a result, which have been fixed as well. A test has been added to ensure that the exception that caught these bugs remains in place. The isxxxx functions are no longer necessary, so they are removed. Same goes for the painful cast handling process in foldconst, which was basically performing this task, and not necessarily well. This approach is much more robust and should have been used since the beginning, but I didn't figure it out then.
This commit is contained in:
parent
41d2c68cf8
commit
9e7a5d1cdf
5 changed files with 218 additions and 226 deletions
|
@ -262,30 +262,67 @@ def zstr(s):
|
||||||
return s
|
return s
|
||||||
return s.__class__(s[:zi])
|
return s.__class__(s[:zi])
|
||||||
|
|
||||||
|
def fi(x):
|
||||||
|
"""Force x to be an int"""
|
||||||
|
if type(x) != int or not (-2147483648 <= x <= 2147483647):
|
||||||
|
raise ELSLInvalidType
|
||||||
|
return x
|
||||||
|
|
||||||
def ff(x):
|
def ff(x):
|
||||||
"""Force x to be a float"""
|
"""Force x to be a float"""
|
||||||
|
if int != type(x) != float:
|
||||||
|
raise ELSLInvalidType
|
||||||
if type(x) != float:
|
if type(x) != float:
|
||||||
x = float(x)
|
return InternalTypecast(x, float, False, True)
|
||||||
return F32(x)
|
return F32(x)
|
||||||
|
|
||||||
def fk(k):
|
def fk(k):
|
||||||
"""Force k to be a key"""
|
"""Force k to be a key"""
|
||||||
|
if unicode != type(k) != Key:
|
||||||
|
raise ELSLInvalidType
|
||||||
if type(k) != Key:
|
if type(k) != Key:
|
||||||
k = Key(k)
|
k = InternalTypecast(k, Key, False, False)
|
||||||
return k
|
return k
|
||||||
|
|
||||||
def fs(s):
|
def fs(s):
|
||||||
"""Force s to be a string"""
|
"""Force s to be a string"""
|
||||||
|
if unicode != type(s) != Key:
|
||||||
|
raise ELSLInvalidType
|
||||||
if type(s) != unicode:
|
if type(s) != unicode:
|
||||||
s = unicode(s)
|
s = InternalTypecast(s, unicode, False, False)
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
def fl(L):
|
||||||
|
"""Force l to be a list, and its elements to have sane types."""
|
||||||
|
Lorig = L
|
||||||
|
if type(L) != list:
|
||||||
|
raise ELSLInvalidType
|
||||||
|
for i in xrange(len(L)):
|
||||||
|
t = type(L[i])
|
||||||
|
if t not in Types:
|
||||||
|
raise ELSLInvalidType
|
||||||
|
if t == Vector:
|
||||||
|
# copy on write
|
||||||
|
if L is Lorig:
|
||||||
|
L = L[:]
|
||||||
|
L[i] = v2f(L[i])
|
||||||
|
if t == Quaternion:
|
||||||
|
# copy on write
|
||||||
|
if L is Lorig:
|
||||||
|
L = L[:]
|
||||||
|
L[i] = q2f(L[i])
|
||||||
|
return L
|
||||||
|
|
||||||
def q2f(q):
|
def q2f(q):
|
||||||
|
if type(q) != Quaternion:
|
||||||
|
raise ELSLInvalidType
|
||||||
if type(q[0]) == type(q[1]) == type(q[2]) == type(q[3]) == float:
|
if type(q[0]) == type(q[1]) == type(q[2]) == type(q[3]) == float:
|
||||||
return q
|
return q
|
||||||
return Quaternion((ff(q[0]), ff(q[1]), ff(q[2]), ff(q[3])))
|
return Quaternion((ff(q[0]), ff(q[1]), ff(q[2]), ff(q[3])))
|
||||||
|
|
||||||
def v2f(v):
|
def v2f(v):
|
||||||
|
if type(v) != Vector:
|
||||||
|
raise ELSLInvalidType
|
||||||
if type(v[0]) == type(v[1]) == type(v[2]) == float:
|
if type(v[0]) == type(v[1]) == type(v[2]) == float:
|
||||||
return v
|
return v
|
||||||
return Vector((ff(v[0]), ff(v[1]), ff(v[2])))
|
return Vector((ff(v[0]), ff(v[1]), ff(v[2])))
|
||||||
|
@ -543,8 +580,8 @@ def InternalUTF8toString(s):
|
||||||
# type check. Same for llGetSubString and llList2List. They are all joined into
|
# type check. Same for llGetSubString and llList2List. They are all joined into
|
||||||
# one single function.
|
# one single function.
|
||||||
def InternalGetDeleteSubSequence(val, start, end, isGet):
|
def InternalGetDeleteSubSequence(val, start, end, isGet):
|
||||||
assert isinteger(start)
|
start = fi(start)
|
||||||
assert isinteger(end)
|
end = fi(end)
|
||||||
L = len(val)
|
L = len(val)
|
||||||
|
|
||||||
# Python does much of the same thing as LSL here, which helps a lot
|
# Python does much of the same thing as LSL here, which helps a lot
|
||||||
|
@ -800,27 +837,6 @@ def cond(x):
|
||||||
return len(x) > 1
|
return len(x) > 1
|
||||||
return bool(x) # works fine for int, float, string, list
|
return bool(x) # works fine for int, float, string, list
|
||||||
|
|
||||||
def isinteger(x):
|
|
||||||
return type(x) == int
|
|
||||||
|
|
||||||
def isfloat(x):
|
|
||||||
return type(x) == float
|
|
||||||
|
|
||||||
def isvector(x):
|
|
||||||
return type(x) == Vector and len(x) == 3 and type(x[0]) == type(x[1]) == type(x[2]) == float
|
|
||||||
|
|
||||||
def isrotation(x):
|
|
||||||
return type(x) == Quaternion and len(x) == 4 and type(x[0]) == type(x[1]) == type(x[2]) == type(x[3]) == float
|
|
||||||
|
|
||||||
def isstring(x):
|
|
||||||
return type(x) == unicode
|
|
||||||
|
|
||||||
def iskey(x):
|
|
||||||
return type(x) == Key
|
|
||||||
|
|
||||||
def islist(x):
|
|
||||||
return type(x) == list
|
|
||||||
|
|
||||||
def reduce(t):
|
def reduce(t):
|
||||||
t = F32(t)
|
t = F32(t)
|
||||||
if not t.is_integer():
|
if not t.is_integer():
|
||||||
|
@ -832,7 +848,7 @@ def reduce(t):
|
||||||
#
|
#
|
||||||
|
|
||||||
def llAbs(i):
|
def llAbs(i):
|
||||||
assert isinteger(i)
|
i = fi(i)
|
||||||
if i != -2147483648:
|
if i != -2147483648:
|
||||||
return abs(i)
|
return abs(i)
|
||||||
if lslcommon.LSO:
|
if lslcommon.LSO:
|
||||||
|
@ -841,27 +857,27 @@ def llAbs(i):
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
|
|
||||||
def llAcos(f):
|
def llAcos(f):
|
||||||
assert isfloat(f)
|
f = ff(f)
|
||||||
try:
|
try:
|
||||||
return F32(math.acos(f))
|
return F32(math.acos(f))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return NaN
|
return NaN
|
||||||
|
|
||||||
def llAngleBetween(r1, r2):
|
def llAngleBetween(r1, r2):
|
||||||
assert isrotation(r1)
|
r1 = q2f(r1)
|
||||||
assert isrotation(r2)
|
r2 = q2f(r2)
|
||||||
return llRot2Angle(div(qnz(r1), qnz(r2), f32=False))
|
return llRot2Angle(div(qnz(r1), qnz(r2), f32=False))
|
||||||
|
|
||||||
def llAsin(f):
|
def llAsin(f):
|
||||||
assert isfloat(f)
|
f = ff(f)
|
||||||
try:
|
try:
|
||||||
return F32(math.asin(f))
|
return F32(math.asin(f))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return NaN
|
return NaN
|
||||||
|
|
||||||
def llAtan2(y, x):
|
def llAtan2(y, x):
|
||||||
assert isfloat(y)
|
y = ff(y)
|
||||||
assert isfloat(x)
|
x = ff(x)
|
||||||
if math.isnan(x) and math.isnan(y):
|
if math.isnan(x) and math.isnan(y):
|
||||||
if math.copysign(1, x) == -1 and math.copysign(1, y) == -1:
|
if math.copysign(1, x) == -1 and math.copysign(1, y) == -1:
|
||||||
return -NaN
|
return -NaN
|
||||||
|
@ -873,9 +889,9 @@ def llAtan2(y, x):
|
||||||
return F32(math.atan2(y, x))
|
return F32(math.atan2(y, x))
|
||||||
|
|
||||||
def llAxes2Rot(fwd, left, up):
|
def llAxes2Rot(fwd, left, up):
|
||||||
assert isvector(fwd)
|
fwd = v2f(fwd)
|
||||||
assert isvector(left)
|
left = v2f(left)
|
||||||
assert isvector(up)
|
up = v2f(up)
|
||||||
|
|
||||||
# One of the hardest.
|
# One of the hardest.
|
||||||
|
|
||||||
|
@ -912,8 +928,8 @@ def llAxes2Rot(fwd, left, up):
|
||||||
|
|
||||||
|
|
||||||
def llAxisAngle2Rot(axis, angle):
|
def llAxisAngle2Rot(axis, angle):
|
||||||
assert isvector(axis)
|
axis = v2f(axis)
|
||||||
assert isfloat(angle)
|
angle = ff(angle)
|
||||||
axis = llVecNorm(axis, f32=False)
|
axis = llVecNorm(axis, f32=False)
|
||||||
if axis == ZERO_VECTOR:
|
if axis == ZERO_VECTOR:
|
||||||
angle = 0.
|
angle = 0.
|
||||||
|
@ -924,7 +940,7 @@ def llAxisAngle2Rot(axis, angle):
|
||||||
# NOTE: This one does not always return the same value in LSL. When it isn't
|
# NOTE: This one does not always return the same value in LSL. When it isn't
|
||||||
# deterministic, it raises ELSLCantCompute.
|
# deterministic, it raises ELSLCantCompute.
|
||||||
def llBase64ToInteger(s):
|
def llBase64ToInteger(s):
|
||||||
assert isstring(s)
|
s = fs(s)
|
||||||
if len(s) > 8:
|
if len(s) > 8:
|
||||||
return 0
|
return 0
|
||||||
s = b64_re.search(s).group()
|
s = b64_re.search(s).group()
|
||||||
|
@ -959,7 +975,7 @@ b64tos_re = re.compile(
|
||||||
)
|
)
|
||||||
|
|
||||||
def llBase64ToString(s):
|
def llBase64ToString(s):
|
||||||
assert isstring(s)
|
s = fs(s)
|
||||||
s = b64_re.search(s).group(0)
|
s = b64_re.search(s).group(0)
|
||||||
|
|
||||||
# llUnescapeURL and llBase64ToString behave differently.
|
# llUnescapeURL and llBase64ToString behave differently.
|
||||||
|
@ -995,7 +1011,7 @@ def llBase64ToString(s):
|
||||||
return InternalUTF8toString(bytes(byteseq))
|
return InternalUTF8toString(bytes(byteseq))
|
||||||
|
|
||||||
def llCSV2List(s):
|
def llCSV2List(s):
|
||||||
assert isstring(s)
|
s = fs(s)
|
||||||
|
|
||||||
bracketlevel = 0
|
bracketlevel = 0
|
||||||
lastwascomma = True # first space is eaten!!!
|
lastwascomma = True # first space is eaten!!!
|
||||||
|
@ -1025,13 +1041,13 @@ def llCSV2List(s):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def llCeil(f):
|
def llCeil(f):
|
||||||
assert isfloat(f)
|
f = ff(f)
|
||||||
if math.isnan(f) or math.isinf(f) or f >= 2147483648.0 or f < -2147483648.0:
|
if math.isnan(f) or math.isinf(f) or f >= 2147483648.0 or f < -2147483648.0:
|
||||||
return -2147483648
|
return -2147483648
|
||||||
return int(math.ceil(f))
|
return int(math.ceil(f))
|
||||||
|
|
||||||
def llCos(f):
|
def llCos(f):
|
||||||
assert isfloat(f)
|
f = ff(f)
|
||||||
if math.isinf(f):
|
if math.isinf(f):
|
||||||
return Indet
|
return Indet
|
||||||
if -9223372036854775808.0 < f < 9223372036854775808.0:
|
if -9223372036854775808.0 < f < 9223372036854775808.0:
|
||||||
|
@ -1040,21 +1056,21 @@ def llCos(f):
|
||||||
|
|
||||||
def llDeleteSubList(lst, start, end):
|
def llDeleteSubList(lst, start, end):
|
||||||
# This acts as llList2List if there's wraparound
|
# This acts as llList2List if there's wraparound
|
||||||
assert islist(lst)
|
lst = fl(lst)
|
||||||
return InternalGetDeleteSubSequence(lst, start, end, isGet=False)
|
return InternalGetDeleteSubSequence(lst, start, end, isGet=False)
|
||||||
|
|
||||||
def llDeleteSubString(s, start, end):
|
def llDeleteSubString(s, start, end):
|
||||||
# This acts as llGetSubString if there's wraparound
|
# This acts as llGetSubString if there's wraparound
|
||||||
assert isstring(s)
|
s = fs(s)
|
||||||
return InternalGetDeleteSubSequence(s, start, end, isGet=False)
|
return InternalGetDeleteSubSequence(s, start, end, isGet=False)
|
||||||
|
|
||||||
def llDumpList2String(lst, sep):
|
def llDumpList2String(lst, sep):
|
||||||
assert islist(lst)
|
lst = fl(lst)
|
||||||
assert isstring(sep)
|
sep = fs(sep)
|
||||||
return sep.join(InternalList2Strings(lst))
|
return sep.join(InternalList2Strings(lst))
|
||||||
|
|
||||||
def llEscapeURL(s):
|
def llEscapeURL(s):
|
||||||
assert isstring(s)
|
s = fs(s)
|
||||||
s = s.encode('utf8') # get bytes
|
s = s.encode('utf8') # get bytes
|
||||||
ret = u''
|
ret = u''
|
||||||
for c in s:
|
for c in s:
|
||||||
|
@ -1065,7 +1081,7 @@ def llEscapeURL(s):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def llEuler2Rot(v):
|
def llEuler2Rot(v):
|
||||||
assert isvector(v)
|
v = v2f(v)
|
||||||
c0 = math.cos(v[0]*0.5)
|
c0 = math.cos(v[0]*0.5)
|
||||||
s0 = math.sin(v[0]*0.5)
|
s0 = math.sin(v[0]*0.5)
|
||||||
c1 = math.cos(v[1]*0.5)
|
c1 = math.cos(v[1]*0.5)
|
||||||
|
@ -1098,19 +1114,19 @@ def llEuler2Rot(v):
|
||||||
return Quaternion(-f for f in r) if r[i] < 0 else Quaternion(r)
|
return Quaternion(-f for f in r) if r[i] < 0 else Quaternion(r)
|
||||||
|
|
||||||
def llFabs(f):
|
def llFabs(f):
|
||||||
assert isfloat(f)
|
f = ff(f)
|
||||||
if f == 0.0 or math.isnan(f): # llFabs(-0.0) is -0.0; llFabs(-nan) is -nan
|
if f == 0.0 or math.isnan(f): # llFabs(-0.0) is -0.0; llFabs(-nan) is -nan
|
||||||
return f
|
return f
|
||||||
return math.fabs(f)
|
return math.fabs(f)
|
||||||
|
|
||||||
def llFloor(f):
|
def llFloor(f):
|
||||||
assert isfloat(f)
|
f = ff(f)
|
||||||
if math.isnan(f) or math.isinf(f) or f >= 2147483648.0 or f < -2147483648.0:
|
if math.isnan(f) or math.isinf(f) or f >= 2147483648.0 or f < -2147483648.0:
|
||||||
return -2147483648
|
return -2147483648
|
||||||
return int(math.floor(f))
|
return int(math.floor(f))
|
||||||
|
|
||||||
def llFrand(lim):
|
def llFrand(lim):
|
||||||
assert isfloat(lim)
|
lim = ff(lim)
|
||||||
if math.isinf(lim):
|
if math.isinf(lim):
|
||||||
return 0.
|
return 0.
|
||||||
if abs(lim) < float.fromhex('0x1p-126'):
|
if abs(lim) < float.fromhex('0x1p-126'):
|
||||||
|
@ -1148,8 +1164,8 @@ def llGenerateKey():
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
|
|
||||||
def llGetListEntryType(lst, pos):
|
def llGetListEntryType(lst, pos):
|
||||||
assert islist(lst)
|
lst = fl(lst)
|
||||||
assert isinteger(pos)
|
pos = fi(pos)
|
||||||
try:
|
try:
|
||||||
return Types[type(lst[pos])]
|
return Types[type(lst[pos])]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
|
@ -1158,26 +1174,26 @@ def llGetListEntryType(lst, pos):
|
||||||
raise ELSLInvalidType
|
raise ELSLInvalidType
|
||||||
|
|
||||||
def llGetListLength(lst):
|
def llGetListLength(lst):
|
||||||
assert islist(lst)
|
lst = fl(lst)
|
||||||
return len(lst)
|
return len(lst)
|
||||||
|
|
||||||
def llGetSubString(s, start, end):
|
def llGetSubString(s, start, end):
|
||||||
assert isstring(s)
|
s = fs(s)
|
||||||
return InternalGetDeleteSubSequence(s, start, end, isGet=True)
|
return InternalGetDeleteSubSequence(s, start, end, isGet=True)
|
||||||
|
|
||||||
def llInsertString(s, pos, src):
|
def llInsertString(s, pos, src):
|
||||||
assert isstring(s)
|
s = fs(s)
|
||||||
assert isinteger(pos)
|
pos = fi(pos)
|
||||||
assert isstring(src)
|
src = fs(src)
|
||||||
if pos < 0: pos = 0 # llInsertString does not support negative indices
|
if pos < 0: pos = 0 # llInsertString does not support negative indices
|
||||||
return s[:pos] + src + s[pos:]
|
return s[:pos] + src + s[pos:]
|
||||||
|
|
||||||
def llIntegerToBase64(x):
|
def llIntegerToBase64(x):
|
||||||
assert isinteger(x)
|
x = fi(x)
|
||||||
return b64encode(chr((x>>24)&255) + chr((x>>16)&255) + chr((x>>8)&255) + chr(x&255)).decode('utf8')
|
return b64encode(chr((x>>24)&255) + chr((x>>16)&255) + chr((x>>8)&255) + chr(x&255)).decode('utf8')
|
||||||
|
|
||||||
def llList2CSV(lst):
|
def llList2CSV(lst):
|
||||||
assert islist(lst)
|
lst = fl(lst)
|
||||||
ret = []
|
ret = []
|
||||||
for elem in lst:
|
for elem in lst:
|
||||||
# This always uses LSO rules for float to string.
|
# This always uses LSO rules for float to string.
|
||||||
|
@ -1194,8 +1210,8 @@ def llList2CSV(lst):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def llList2Float(lst, pos):
|
def llList2Float(lst, pos):
|
||||||
assert islist(lst)
|
lst = fl(lst)
|
||||||
assert isinteger(pos)
|
pos = fi(pos)
|
||||||
try:
|
try:
|
||||||
elem = lst[pos]
|
elem = lst[pos]
|
||||||
if type(elem) == float:
|
if type(elem) == float:
|
||||||
|
@ -1207,8 +1223,8 @@ def llList2Float(lst, pos):
|
||||||
return 0.0
|
return 0.0
|
||||||
|
|
||||||
def llList2Integer(lst, pos):
|
def llList2Integer(lst, pos):
|
||||||
assert islist(lst)
|
lst = fl(lst)
|
||||||
assert isinteger(pos)
|
pos = fi(pos)
|
||||||
try:
|
try:
|
||||||
elem = lst[pos]
|
elem = lst[pos]
|
||||||
if type(elem) == int:
|
if type(elem) == int:
|
||||||
|
@ -1220,8 +1236,8 @@ def llList2Integer(lst, pos):
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def llList2Key(lst, pos):
|
def llList2Key(lst, pos):
|
||||||
assert islist(lst)
|
lst = fl(lst)
|
||||||
assert isinteger(pos)
|
pos = fi(pos)
|
||||||
try:
|
try:
|
||||||
elem = lst[pos]
|
elem = lst[pos]
|
||||||
if type(elem) == Key:
|
if type(elem) == Key:
|
||||||
|
@ -1235,16 +1251,16 @@ def llList2Key(lst, pos):
|
||||||
return Key(u'')
|
return Key(u'')
|
||||||
|
|
||||||
def llList2List(lst, start, end):
|
def llList2List(lst, start, end):
|
||||||
assert islist(lst)
|
lst = fl(lst)
|
||||||
assert isinteger(start)
|
start = fi(start)
|
||||||
assert isinteger(end)
|
end = fi(end)
|
||||||
return InternalGetDeleteSubSequence(lst, start, end, isGet=True)
|
return InternalGetDeleteSubSequence(lst, start, end, isGet=True)
|
||||||
|
|
||||||
def llList2ListStrided(lst, start, end, stride):
|
def llList2ListStrided(lst, start, end, stride):
|
||||||
assert islist(lst)
|
lst = fl(lst)
|
||||||
assert isinteger(start)
|
start = fi(start)
|
||||||
assert isinteger(end)
|
end = fi(end)
|
||||||
assert isinteger(stride)
|
stride = fi(stride)
|
||||||
stride = abs(stride) if stride != 0 else 1
|
stride = abs(stride) if stride != 0 else 1
|
||||||
L = len(lst)
|
L = len(lst)
|
||||||
if start < 0: start += L
|
if start < 0: start += L
|
||||||
|
@ -1260,13 +1276,13 @@ def llList2ListStrided(lst, start, end, stride):
|
||||||
return lst[start:end+1:stride]
|
return lst[start:end+1:stride]
|
||||||
|
|
||||||
def llList2Rot(lst, pos):
|
def llList2Rot(lst, pos):
|
||||||
assert islist(lst)
|
lst = fl(lst)
|
||||||
assert isinteger(pos)
|
pos = fi(pos)
|
||||||
try:
|
try:
|
||||||
elem = lst[pos]
|
elem = lst[pos]
|
||||||
if type(elem) == Quaternion:
|
if type(elem) == Quaternion:
|
||||||
# The list should not contain integer quaternion components, but
|
# The list should not contain integer quaternion components, but
|
||||||
# we don't control that here. Instead we return the integer-less
|
# we don't err here if not. Instead we return the integer-less
|
||||||
# quaternion when asked.
|
# quaternion when asked.
|
||||||
return q2f(elem)
|
return q2f(elem)
|
||||||
except IndexError:
|
except IndexError:
|
||||||
|
@ -1274,8 +1290,8 @@ def llList2Rot(lst, pos):
|
||||||
return ZERO_ROTATION
|
return ZERO_ROTATION
|
||||||
|
|
||||||
def llList2String(lst, pos):
|
def llList2String(lst, pos):
|
||||||
assert islist(lst)
|
lst = fl(lst)
|
||||||
assert isinteger(pos)
|
pos = fi(pos)
|
||||||
try:
|
try:
|
||||||
return InternalTypecast(lst[pos], unicode, InList=True, f32=True)
|
return InternalTypecast(lst[pos], unicode, InList=True, f32=True)
|
||||||
except IndexError:
|
except IndexError:
|
||||||
|
@ -1283,8 +1299,8 @@ def llList2String(lst, pos):
|
||||||
return u''
|
return u''
|
||||||
|
|
||||||
def llList2Vector(lst, pos):
|
def llList2Vector(lst, pos):
|
||||||
assert islist(lst)
|
lst = fl(lst)
|
||||||
assert isinteger(pos)
|
pos = fi(pos)
|
||||||
try:
|
try:
|
||||||
elem = lst[pos]
|
elem = lst[pos]
|
||||||
if type(elem) == Vector:
|
if type(elem) == Vector:
|
||||||
|
@ -1297,8 +1313,8 @@ def llList2Vector(lst, pos):
|
||||||
return ZERO_VECTOR
|
return ZERO_VECTOR
|
||||||
|
|
||||||
def llListFindList(lst, elems):
|
def llListFindList(lst, elems):
|
||||||
assert islist(lst)
|
lst = fl(lst)
|
||||||
assert islist(elems)
|
elems = fl(elems)
|
||||||
# NaN is found in floats, but not in vectors
|
# NaN is found in floats, but not in vectors
|
||||||
L1 = len(lst)
|
L1 = len(lst)
|
||||||
L2 = len(elems)
|
L2 = len(elems)
|
||||||
|
@ -1346,9 +1362,9 @@ def llListFindList(lst, elems):
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
def llListInsertList(lst, elems, pos):
|
def llListInsertList(lst, elems, pos):
|
||||||
assert islist(lst)
|
lst = fl(lst)
|
||||||
assert islist(elems)
|
elems = fl(elems)
|
||||||
assert isinteger(pos)
|
pos = fi(pos)
|
||||||
# Unlike llInsertString, this function does support negative indices.
|
# Unlike llInsertString, this function does support negative indices.
|
||||||
return lst[:pos] + elems + lst[pos:]
|
return lst[:pos] + elems + lst[pos:]
|
||||||
|
|
||||||
|
@ -1356,10 +1372,10 @@ def llListInsertList(lst, elems, pos):
|
||||||
#def llListRandomize(x):
|
#def llListRandomize(x):
|
||||||
|
|
||||||
def llListReplaceList(lst, elems, start, end):
|
def llListReplaceList(lst, elems, start, end):
|
||||||
assert islist(lst)
|
lst = fl(lst)
|
||||||
assert islist(elems)
|
elems = fl(elems)
|
||||||
assert isinteger(start)
|
start = fi(start)
|
||||||
assert isinteger(end)
|
end = fi(end)
|
||||||
L = len(lst)
|
L = len(lst)
|
||||||
if start < -L:
|
if start < -L:
|
||||||
# llListReplaceList([0,1,2,3],[5],-5,-5) should return [0,1,2,3]
|
# llListReplaceList([0,1,2,3],[5],-5,-5) should return [0,1,2,3]
|
||||||
|
@ -1374,9 +1390,9 @@ def llListReplaceList(lst, elems, start, end):
|
||||||
return lst[:start] + elems + lst[end+1:]
|
return lst[:start] + elems + lst[end+1:]
|
||||||
|
|
||||||
def llListSort(lst, stride, asc):
|
def llListSort(lst, stride, asc):
|
||||||
assert islist(lst)
|
lst = fl(lst)
|
||||||
assert isinteger(stride)
|
stride = fi(stride)
|
||||||
assert isinteger(asc)
|
asc = fi(asc)
|
||||||
lst = lst[:] # make a copy
|
lst = lst[:] # make a copy
|
||||||
L = len(lst)
|
L = len(lst)
|
||||||
broken = u'\ufb1a' > u'\U0001d41a' # that happens on Windows
|
broken = u'\ufb1a' > u'\U0001d41a' # that happens on Windows
|
||||||
|
@ -1422,8 +1438,8 @@ def llListSort(lst, stride, asc):
|
||||||
return lst
|
return lst
|
||||||
|
|
||||||
def llListStatistics(op, lst):
|
def llListStatistics(op, lst):
|
||||||
assert isinteger(op)
|
op = fi(op)
|
||||||
assert islist(lst)
|
lst = fl(lst)
|
||||||
|
|
||||||
nums = []
|
nums = []
|
||||||
# Extract numbers in reverse order. LIST_STAT_MEDIAN uses that.
|
# Extract numbers in reverse order. LIST_STAT_MEDIAN uses that.
|
||||||
|
@ -1495,26 +1511,26 @@ def llListStatistics(op, lst):
|
||||||
return 0.0
|
return 0.0
|
||||||
|
|
||||||
def llLog(f):
|
def llLog(f):
|
||||||
assert isfloat(f)
|
f = ff(f)
|
||||||
if math.isinf(f) and f < 0 or math.isnan(f) or f <= 0.0:
|
if math.isinf(f) and f < 0 or math.isnan(f) or f <= 0.0:
|
||||||
return 0.0
|
return 0.0
|
||||||
return F32(math.log(f))
|
return F32(math.log(f))
|
||||||
|
|
||||||
def llLog10(f):
|
def llLog10(f):
|
||||||
assert isfloat(f)
|
f = ff(f)
|
||||||
if math.isinf(f) and f < 0 or math.isnan(f) or f <= 0.0:
|
if math.isinf(f) and f < 0 or math.isnan(f) or f <= 0.0:
|
||||||
return 0.0
|
return 0.0
|
||||||
return F32(math.log10(f))
|
return F32(math.log10(f))
|
||||||
|
|
||||||
def llMD5String(s, salt):
|
def llMD5String(s, salt):
|
||||||
assert isstring(s)
|
s = fs(s)
|
||||||
assert isinteger(salt)
|
salt = fi(salt)
|
||||||
return hashlib.md5(zstr(s).encode('utf8') + b':' + bytes(salt)).hexdigest().decode('utf8')
|
return hashlib.md5(zstr(s).encode('utf8') + b':' + bytes(salt)).hexdigest().decode('utf8')
|
||||||
|
|
||||||
def llModPow(base, exp, mod):
|
def llModPow(base, exp, mod):
|
||||||
assert isinteger(base)
|
base = fi(base)
|
||||||
assert isinteger(exp)
|
exp = fi(exp)
|
||||||
assert isinteger(mod)
|
mod = fi(mod)
|
||||||
if not lslcommon.IsCalc:
|
if not lslcommon.IsCalc:
|
||||||
# This function has a delay, therefore it's not safe to compute it
|
# This function has a delay, therefore it's not safe to compute it
|
||||||
# unless in calculator mode.
|
# unless in calculator mode.
|
||||||
|
@ -1544,9 +1560,9 @@ def llModPow(base, exp, mod):
|
||||||
return S32(ret)
|
return S32(ret)
|
||||||
|
|
||||||
def llParseString2List(s, exc, inc, KeepNulls=False):
|
def llParseString2List(s, exc, inc, KeepNulls=False):
|
||||||
assert isstring(s)
|
s = fs(s)
|
||||||
assert islist(exc)
|
exc = fl(exc)
|
||||||
assert islist(inc)
|
inc = fl(inc)
|
||||||
if s == u'' and KeepNulls:
|
if s == u'' and KeepNulls:
|
||||||
return [s]
|
return [s]
|
||||||
exc = exc[:8]
|
exc = exc[:8]
|
||||||
|
@ -1569,8 +1585,8 @@ def llParseStringKeepNulls(s, exc, inc):
|
||||||
return llParseString2List(s, exc, inc, KeepNulls=True)
|
return llParseString2List(s, exc, inc, KeepNulls=True)
|
||||||
|
|
||||||
def llPow(base, exp):
|
def llPow(base, exp):
|
||||||
assert isfloat(base)
|
base = ff(base)
|
||||||
assert isfloat(exp)
|
exp = ff(exp)
|
||||||
try:
|
try:
|
||||||
# Python corner cases and LSL corner cases differ
|
# Python corner cases and LSL corner cases differ
|
||||||
|
|
||||||
|
@ -1599,19 +1615,19 @@ def llPow(base, exp):
|
||||||
return Indet
|
return Indet
|
||||||
|
|
||||||
def llRot2Angle(r):
|
def llRot2Angle(r):
|
||||||
assert isrotation(r)
|
r = q2f(r)
|
||||||
# Used by llAngleBetween.
|
# Used by llAngleBetween.
|
||||||
# Version based on research by Moon Metty, Miranda Umino and Strife Onizuka
|
# Version based on research by Moon Metty, Miranda Umino and Strife Onizuka
|
||||||
return F32(2.*math.atan2(math.sqrt(math.fsum((r[0]*r[0], r[1]*r[1], r[2]*r[2]))), abs(r[3])));
|
return F32(2.*math.atan2(math.sqrt(math.fsum((r[0]*r[0], r[1]*r[1], r[2]*r[2]))), abs(r[3])));
|
||||||
|
|
||||||
def llRot2Axis(r):
|
def llRot2Axis(r):
|
||||||
assert isrotation(r)
|
r = q2f(r)
|
||||||
if r[3] < 0:
|
if r[3] < 0:
|
||||||
return llVecNorm(Vector((-r[0], -r[1], -r[2])))
|
return llVecNorm(Vector((-r[0], -r[1], -r[2])))
|
||||||
return llVecNorm(Vector((r[0], r[1], r[2])))
|
return llVecNorm(Vector((r[0], r[1], r[2])))
|
||||||
|
|
||||||
def llRot2Euler(r):
|
def llRot2Euler(r):
|
||||||
assert isrotation(r)
|
r = q2f(r)
|
||||||
|
|
||||||
# Another one of the hardest. The formula for Z angle in the
|
# Another one of the hardest. The formula for Z angle in the
|
||||||
# singularity case was inspired by the viewer code.
|
# singularity case was inspired by the viewer code.
|
||||||
|
@ -1634,23 +1650,23 @@ def llRot2Euler(r):
|
||||||
)))
|
)))
|
||||||
|
|
||||||
def llRot2Fwd(r):
|
def llRot2Fwd(r):
|
||||||
assert isrotation(r)
|
r = q2f(r)
|
||||||
v = Vector((1., 0., 0.))
|
v = Vector((1., 0., 0.))
|
||||||
return llVecNorm(mul(v, qnz(r), f32=False))
|
return llVecNorm(mul(v, qnz(r), f32=False))
|
||||||
|
|
||||||
def llRot2Left(r):
|
def llRot2Left(r):
|
||||||
assert isrotation(r)
|
r = q2f(r)
|
||||||
v = Vector((0., 1., 0.))
|
v = Vector((0., 1., 0.))
|
||||||
return llVecNorm(mul(v, qnz(r), f32=False))
|
return llVecNorm(mul(v, qnz(r), f32=False))
|
||||||
|
|
||||||
def llRot2Up(r):
|
def llRot2Up(r):
|
||||||
assert isrotation(r)
|
r = q2f(r)
|
||||||
v = Vector((0., 0., 1.))
|
v = Vector((0., 0., 1.))
|
||||||
return llVecNorm(mul(v, qnz(r), f32=False))
|
return llVecNorm(mul(v, qnz(r), f32=False))
|
||||||
|
|
||||||
def llRotBetween(v1, v2):
|
def llRotBetween(v1, v2):
|
||||||
assert isvector(v1)
|
v1 = v2f(v1)
|
||||||
assert isvector(v2)
|
v2 = v2f(v2)
|
||||||
|
|
||||||
# Loosely based on the "Bad" reference implementation and
|
# Loosely based on the "Bad" reference implementation and
|
||||||
# on SL source code (pre Moon Metty's changes).
|
# on SL source code (pre Moon Metty's changes).
|
||||||
|
@ -1685,17 +1701,17 @@ def llRotBetween(v1, v2):
|
||||||
return Quaternion(F32((ortho[0] / m, ortho[1] / m, ortho[2] / m, 0.)))
|
return Quaternion(F32((ortho[0] / m, ortho[1] / m, ortho[2] / m, 0.)))
|
||||||
|
|
||||||
def llRound(f):
|
def llRound(f):
|
||||||
assert isfloat(f)
|
f = ff(f)
|
||||||
if math.isnan(f) or math.isinf(f) or f >= 2147483647.5 or f < -2147483648.0:
|
if math.isnan(f) or math.isinf(f) or f >= 2147483647.5 or f < -2147483648.0:
|
||||||
return -2147483648
|
return -2147483648
|
||||||
return int(math.floor(F32(f+0.5)))
|
return int(math.floor(F32(f+0.5)))
|
||||||
|
|
||||||
def llSHA1String(s):
|
def llSHA1String(s):
|
||||||
assert isstring(s)
|
s = fs(s)
|
||||||
return hashlib.sha1(s.encode('utf8')).hexdigest().decode('utf8')
|
return hashlib.sha1(s.encode('utf8')).hexdigest().decode('utf8')
|
||||||
|
|
||||||
def llSin(f):
|
def llSin(f):
|
||||||
assert isfloat(f)
|
f = ff(f)
|
||||||
if math.isinf(f):
|
if math.isinf(f):
|
||||||
return Indet
|
return Indet
|
||||||
if -9223372036854775808.0 < f < 9223372036854775808.0:
|
if -9223372036854775808.0 < f < 9223372036854775808.0:
|
||||||
|
@ -1703,23 +1719,23 @@ def llSin(f):
|
||||||
return f
|
return f
|
||||||
|
|
||||||
def llSqrt(f):
|
def llSqrt(f):
|
||||||
assert isfloat(f)
|
f = ff(f)
|
||||||
if f < 0.0:
|
if f < 0.0:
|
||||||
return Indet
|
return Indet
|
||||||
# LSL and Python both produce -0.0 when the input is -0.0.
|
# LSL and Python both produce -0.0 when the input is -0.0.
|
||||||
return F32(math.sqrt(f))
|
return F32(math.sqrt(f))
|
||||||
|
|
||||||
def llStringLength(s):
|
def llStringLength(s):
|
||||||
assert isstring(s)
|
s = fs(s)
|
||||||
return len(s)
|
return len(s)
|
||||||
|
|
||||||
def llStringToBase64(s):
|
def llStringToBase64(s):
|
||||||
assert isstring(s)
|
s = fs(s)
|
||||||
return b64encode(s.encode('utf8')).decode('utf8')
|
return b64encode(s.encode('utf8')).decode('utf8')
|
||||||
|
|
||||||
def llStringTrim(s, mode):
|
def llStringTrim(s, mode):
|
||||||
assert isstring(s)
|
s = fs(s)
|
||||||
assert isinteger(mode)
|
mode = fi(mode)
|
||||||
head = 0
|
head = 0
|
||||||
length = len(s)
|
length = len(s)
|
||||||
tail = length-1
|
tail = length-1
|
||||||
|
@ -1732,12 +1748,12 @@ def llStringTrim(s, mode):
|
||||||
return s[head:tail+1]
|
return s[head:tail+1]
|
||||||
|
|
||||||
def llSubStringIndex(s, pattern):
|
def llSubStringIndex(s, pattern):
|
||||||
assert isstring(s)
|
s = fs(s)
|
||||||
assert isstring(pattern)
|
pattern = fs(pattern)
|
||||||
return s.find(pattern)
|
return s.find(pattern)
|
||||||
|
|
||||||
def llTan(f):
|
def llTan(f):
|
||||||
assert isfloat(f)
|
f = ff(f)
|
||||||
if math.isinf(f):
|
if math.isinf(f):
|
||||||
return Indet
|
return Indet
|
||||||
if -9223372036854775808.0 < f < 9223372036854775808.0:
|
if -9223372036854775808.0 < f < 9223372036854775808.0:
|
||||||
|
@ -1745,19 +1761,19 @@ def llTan(f):
|
||||||
return f
|
return f
|
||||||
|
|
||||||
def llToLower(s):
|
def llToLower(s):
|
||||||
assert isstring(s)
|
s = fs(s)
|
||||||
if lslcommon.LSO:
|
if lslcommon.LSO:
|
||||||
return zstr(re.sub(u'[A-Z]', lambda x: x.group().lower(), s))
|
return zstr(re.sub(u'[A-Z]', lambda x: x.group().lower(), s))
|
||||||
return zstr(s.lower())
|
return zstr(s.lower())
|
||||||
|
|
||||||
def llToUpper(s):
|
def llToUpper(s):
|
||||||
assert isstring(s)
|
s = fs(s)
|
||||||
if lslcommon.LSO:
|
if lslcommon.LSO:
|
||||||
return zstr(re.sub(u'[a-z]', lambda x: x.group().upper(), s))
|
return zstr(re.sub(u'[a-z]', lambda x: x.group().upper(), s))
|
||||||
return zstr(s.upper())
|
return zstr(s.upper())
|
||||||
|
|
||||||
def llUnescapeURL(s):
|
def llUnescapeURL(s):
|
||||||
assert isstring(s)
|
s = fs(s)
|
||||||
ret = b''
|
ret = b''
|
||||||
L = len(s)
|
L = len(s)
|
||||||
i = 0
|
i = 0
|
||||||
|
@ -1788,8 +1804,8 @@ def llUnescapeURL(s):
|
||||||
return InternalUTF8toString(ret)
|
return InternalUTF8toString(ret)
|
||||||
|
|
||||||
def llVecDist(v1, v2):
|
def llVecDist(v1, v2):
|
||||||
assert isvector(v1)
|
v1 = v2f(v1)
|
||||||
assert isvector(v2)
|
v2 = v2f(v2)
|
||||||
# For improved accuracy, do the intermediate calcs as doubles
|
# For improved accuracy, do the intermediate calcs as doubles
|
||||||
vx = v1[0]-v2[0]
|
vx = v1[0]-v2[0]
|
||||||
vy = v1[1]-v2[1]
|
vy = v1[1]-v2[1]
|
||||||
|
@ -1797,19 +1813,19 @@ def llVecDist(v1, v2):
|
||||||
return F32(math.sqrt(math.fsum((vx*vx, vy*vy, vz*vz))))
|
return F32(math.sqrt(math.fsum((vx*vx, vy*vy, vz*vz))))
|
||||||
|
|
||||||
def llVecMag(v):
|
def llVecMag(v):
|
||||||
assert isvector(v)
|
v = v2f(v)
|
||||||
return F32(math.sqrt(math.fsum((v[0]*v[0], v[1]*v[1], v[2]*v[2]))))
|
return F32(math.sqrt(math.fsum((v[0]*v[0], v[1]*v[1], v[2]*v[2]))))
|
||||||
|
|
||||||
def llVecNorm(v, f32 = True):
|
def llVecNorm(v, f32 = True):
|
||||||
assert isvector(v)
|
v = v2f(v)
|
||||||
if v == ZERO_VECTOR:
|
if v == ZERO_VECTOR:
|
||||||
return v
|
return v
|
||||||
f = math.sqrt(math.fsum((v[0]*v[0], v[1]*v[1], v[2]*v[2])))
|
f = math.sqrt(math.fsum((v[0]*v[0], v[1]*v[1], v[2]*v[2])))
|
||||||
return F32(Vector((v[0]/f,v[1]/f,v[2]/f)), f32)
|
return F32(Vector((v[0]/f,v[1]/f,v[2]/f)), f32)
|
||||||
|
|
||||||
def llXorBase64(s, xor):
|
def llXorBase64(s, xor):
|
||||||
assert isstring(s)
|
s = fs(s)
|
||||||
assert isstring(xor)
|
xor = fs(xor)
|
||||||
|
|
||||||
# Xor the underlying bytes.
|
# Xor the underlying bytes.
|
||||||
|
|
||||||
|
@ -1854,8 +1870,8 @@ def llXorBase64(s, xor):
|
||||||
return b64encode(ret).decode('utf8')
|
return b64encode(ret).decode('utf8')
|
||||||
|
|
||||||
def llXorBase64Strings(s, xor):
|
def llXorBase64Strings(s, xor):
|
||||||
assert isstring(s)
|
s = fs(s)
|
||||||
assert isstring(xor)
|
xor = fs(xor)
|
||||||
|
|
||||||
if not lslcommon.IsCalc:
|
if not lslcommon.IsCalc:
|
||||||
# This function has a delay, therefore it's not safe to compute it
|
# This function has a delay, therefore it's not safe to compute it
|
||||||
|
@ -1897,8 +1913,8 @@ def llXorBase64Strings(s, xor):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def llXorBase64StringsCorrect(s, xor):
|
def llXorBase64StringsCorrect(s, xor):
|
||||||
assert isstring(s)
|
s = fs(s)
|
||||||
assert isstring(xor)
|
xor = fs(xor)
|
||||||
|
|
||||||
# Xor the underlying bytes but repeating the xor parameter pattern at the first zero (SCR-35).
|
# Xor the underlying bytes but repeating the xor parameter pattern at the first zero (SCR-35).
|
||||||
|
|
||||||
|
|
|
@ -18,10 +18,10 @@
|
||||||
# Extra functions that have predictable return values for certain arguments.
|
# Extra functions that have predictable return values for certain arguments.
|
||||||
|
|
||||||
from lslcommon import Key, Vector #, Quaternion
|
from lslcommon import Key, Vector #, Quaternion
|
||||||
from lslbasefuncs import ELSLCantCompute, isinteger, iskey, islist, \
|
from lslbasefuncs import ELSLCantCompute, fi,ff,fs,fk,v2f,q2f,fl, \
|
||||||
isvector, isstring, NULL_KEY, ZERO_VECTOR, ZERO_ROTATION, \
|
NULL_KEY, ZERO_VECTOR, ZERO_ROTATION, \
|
||||||
TOUCH_INVALID_TEXCOORD, cond
|
TOUCH_INVALID_TEXCOORD, cond
|
||||||
#isfloat, isrotation
|
ff, q2f # keep pyflakes happy as these are not used
|
||||||
|
|
||||||
TouchEvents = ('touch', 'touch_start', 'touch_end')
|
TouchEvents = ('touch', 'touch_start', 'touch_end')
|
||||||
DetectionEvents = ('touch', 'touch_start', 'touch_end',
|
DetectionEvents = ('touch', 'touch_start', 'touch_end',
|
||||||
|
@ -52,147 +52,147 @@ xp_error_messages = {
|
||||||
valid_inventory_kinds = frozenset((0, 1, 3, 5, 6, 7, 10, 13, 20, 21))
|
valid_inventory_kinds = frozenset((0, 1, 3, 5, 6, 7, 10, 13, 20, 21))
|
||||||
|
|
||||||
def llCloud(v):
|
def llCloud(v):
|
||||||
assert isvector(v)
|
v = v2f(v)
|
||||||
return 0.0
|
return 0.0
|
||||||
|
|
||||||
def llAvatarOnLinkSitTarget(link):
|
def llAvatarOnLinkSitTarget(link):
|
||||||
assert isinteger(link)
|
link = fi(link)
|
||||||
if link > 255 or link == -2147483648:
|
if link > 255 or link == -2147483648:
|
||||||
return Key(NULL_KEY)
|
return Key(NULL_KEY)
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
|
|
||||||
def llDetectedGrab(idx, event=None):
|
def llDetectedGrab(idx, event=None):
|
||||||
assert isinteger(idx)
|
idx = fi(idx)
|
||||||
if 0 <= idx <= 15 and (event == 'touch' or event is None):
|
if 0 <= idx <= 15 and (event == 'touch' or event is None):
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
return ZERO_VECTOR
|
return ZERO_VECTOR
|
||||||
|
|
||||||
def llDetectedGroup(idx, event=None):
|
def llDetectedGroup(idx, event=None):
|
||||||
assert isinteger(idx)
|
idx = fi(idx)
|
||||||
if 0 <= idx <= 15 and (event in DetectionEvents or event is None):
|
if 0 <= idx <= 15 and (event in DetectionEvents or event is None):
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def llDetectedKey(idx, event=None):
|
def llDetectedKey(idx, event=None):
|
||||||
assert isinteger(idx)
|
idx = fi(idx)
|
||||||
if 0 <= idx <= 15 and (event in DetectionEvents or event is None):
|
if 0 <= idx <= 15 and (event in DetectionEvents or event is None):
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
return Key(NULL_KEY)
|
return Key(NULL_KEY)
|
||||||
|
|
||||||
def llDetectedLinkNumber(idx, event=None):
|
def llDetectedLinkNumber(idx, event=None):
|
||||||
assert isinteger(idx)
|
idx = fi(idx)
|
||||||
if 0 <= idx <= 15 and (event in DetectionEvents or event is None):
|
if 0 <= idx <= 15 and (event in DetectionEvents or event is None):
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def llDetectedName(idx, event=None):
|
def llDetectedName(idx, event=None):
|
||||||
assert isinteger(idx)
|
idx = fi(idx)
|
||||||
if 0 <= idx <= 15 and (event in DetectionEvents or event is None):
|
if 0 <= idx <= 15 and (event in DetectionEvents or event is None):
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
return NULL_KEY
|
return NULL_KEY
|
||||||
|
|
||||||
def llDetectedOwner(idx, event=None):
|
def llDetectedOwner(idx, event=None):
|
||||||
assert isinteger(idx)
|
idx = fi(idx)
|
||||||
if 0 <= idx <= 15 and (event in DetectionEvents or event is None):
|
if 0 <= idx <= 15 and (event in DetectionEvents or event is None):
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
return Key(NULL_KEY)
|
return Key(NULL_KEY)
|
||||||
|
|
||||||
def llDetectedPos(idx, event=None):
|
def llDetectedPos(idx, event=None):
|
||||||
assert isinteger(idx)
|
idx = fi(idx)
|
||||||
if 0 <= idx <= 15 and (event in DetectionEvents or event is None):
|
if 0 <= idx <= 15 and (event in DetectionEvents or event is None):
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
return ZERO_VECTOR
|
return ZERO_VECTOR
|
||||||
|
|
||||||
def llDetectedRot(idx, event=None):
|
def llDetectedRot(idx, event=None):
|
||||||
assert isinteger(idx)
|
idx = fi(idx)
|
||||||
if 0 <= idx <= 15 and (event in DetectionEvents or event is None):
|
if 0 <= idx <= 15 and (event in DetectionEvents or event is None):
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
return ZERO_ROTATION
|
return ZERO_ROTATION
|
||||||
|
|
||||||
def llDetectedTouchBinormal(idx, event=None):
|
def llDetectedTouchBinormal(idx, event=None):
|
||||||
assert isinteger(idx)
|
idx = fi(idx)
|
||||||
if 0 <= idx <= 15 and (event in TouchEvents or event is None):
|
if 0 <= idx <= 15 and (event in TouchEvents or event is None):
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
return ZERO_VECTOR
|
return ZERO_VECTOR
|
||||||
|
|
||||||
def llDetectedTouchFace(idx, event=None):
|
def llDetectedTouchFace(idx, event=None):
|
||||||
assert isinteger(idx)
|
idx = fi(idx)
|
||||||
if 0 <= idx <= 15 and (event in TouchEvents or event is None):
|
if 0 <= idx <= 15 and (event in TouchEvents or event is None):
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
return -1 if event in DetectionEvents and 0 <= idx <= 15 else 0
|
return -1 if event in DetectionEvents and 0 <= idx <= 15 else 0
|
||||||
|
|
||||||
def llDetectedTouchNormal(idx, event=None):
|
def llDetectedTouchNormal(idx, event=None):
|
||||||
assert isinteger(idx)
|
idx = fi(idx)
|
||||||
if 0 <= idx <= 15 and (event in TouchEvents or event is None):
|
if 0 <= idx <= 15 and (event in TouchEvents or event is None):
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
return ZERO_VECTOR
|
return ZERO_VECTOR
|
||||||
|
|
||||||
def llDetectedTouchPos(idx, event=None):
|
def llDetectedTouchPos(idx, event=None):
|
||||||
assert isinteger(idx)
|
idx = fi(idx)
|
||||||
if 0 <= idx <= 15 and (event in TouchEvents or event is None):
|
if 0 <= idx <= 15 and (event in TouchEvents or event is None):
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
return ZERO_VECTOR
|
return ZERO_VECTOR
|
||||||
|
|
||||||
def llDetectedTouchST(idx, event=None):
|
def llDetectedTouchST(idx, event=None):
|
||||||
assert isinteger(idx)
|
idx = fi(idx)
|
||||||
if 0 <= idx <= 15 and (event in TouchEvents or event is None):
|
if 0 <= idx <= 15 and (event in TouchEvents or event is None):
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
return TOUCH_INVALID_TEXCOORD if event in DetectionEvents \
|
return TOUCH_INVALID_TEXCOORD if event in DetectionEvents \
|
||||||
and 0 <= idx <= 15 else ZERO_VECTOR
|
and 0 <= idx <= 15 else ZERO_VECTOR
|
||||||
|
|
||||||
def llDetectedTouchUV(idx, event=None):
|
def llDetectedTouchUV(idx, event=None):
|
||||||
assert isinteger(idx)
|
idx = fi(idx)
|
||||||
if 0 <= idx <= 15 and (event in TouchEvents or event is None):
|
if 0 <= idx <= 15 and (event in TouchEvents or event is None):
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
return TOUCH_INVALID_TEXCOORD if event in DetectionEvents \
|
return TOUCH_INVALID_TEXCOORD if event in DetectionEvents \
|
||||||
and 0 <= idx <= 15 else ZERO_VECTOR
|
and 0 <= idx <= 15 else ZERO_VECTOR
|
||||||
|
|
||||||
def llDetectedType(idx, event=None):
|
def llDetectedType(idx, event=None):
|
||||||
assert isinteger(idx)
|
idx = fi(idx)
|
||||||
if 0 <= idx <= 15 and (event in DetectionEvents or event is None):
|
if 0 <= idx <= 15 and (event in DetectionEvents or event is None):
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def llDetectedVel(idx, event=None):
|
def llDetectedVel(idx, event=None):
|
||||||
assert isinteger(idx)
|
idx = fi(idx)
|
||||||
if 0 <= idx <= 15 and (event in DetectionEvents or event is None):
|
if 0 <= idx <= 15 and (event in DetectionEvents or event is None):
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
return ZERO_VECTOR
|
return ZERO_VECTOR
|
||||||
|
|
||||||
def llEdgeOfWorld(v1, v2):
|
def llEdgeOfWorld(v1, v2):
|
||||||
assert isvector(v1)
|
v1 = v2f(v1)
|
||||||
assert isvector(v2)
|
v2 = v2f(v2)
|
||||||
if v2[0] == v2[1] == 0:
|
if v2[0] == v2[1] == 0:
|
||||||
return 1
|
return 1
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
|
|
||||||
def llGetAgentInfo(id):
|
def llGetAgentInfo(id):
|
||||||
assert iskey(id)
|
id = fk(id)
|
||||||
if not cond(id):
|
if not cond(id):
|
||||||
return 0
|
return 0
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
|
|
||||||
def llGetAgentLanguage(id):
|
def llGetAgentLanguage(id):
|
||||||
assert iskey(id)
|
id = fk(id)
|
||||||
if not cond(id):
|
if not cond(id):
|
||||||
return u''
|
return u''
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
|
|
||||||
def llGetAgentList(scope, options):
|
def llGetAgentList(scope, options):
|
||||||
assert isinteger(scope)
|
scope = fi(scope)
|
||||||
assert islist(options)
|
options = fl(options)
|
||||||
if scope not in (1, 2, 4):
|
if scope not in (1, 2, 4):
|
||||||
return [u'INVALID_SCOPE']
|
return [u'INVALID_SCOPE']
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
|
|
||||||
def llGetAgentSize(id):
|
def llGetAgentSize(id):
|
||||||
assert iskey(id)
|
id = fk(id)
|
||||||
if not cond(id):
|
if not cond(id):
|
||||||
return ZERO_VECTOR
|
return ZERO_VECTOR
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
|
|
||||||
def llGetAlpha(face):
|
def llGetAlpha(face):
|
||||||
assert isinteger(face)
|
face = fi(face)
|
||||||
if face > 8:
|
if face > 8:
|
||||||
return 1.0
|
return 1.0
|
||||||
# Negative face numbers return (float)llGetNumberOfSides(), which isn't
|
# Negative face numbers return (float)llGetNumberOfSides(), which isn't
|
||||||
|
@ -200,89 +200,89 @@ def llGetAlpha(face):
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
|
|
||||||
def llGetAnimation(id):
|
def llGetAnimation(id):
|
||||||
assert iskey(id)
|
id = fk(id)
|
||||||
if not cond(id):
|
if not cond(id):
|
||||||
return u''
|
return u''
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
|
|
||||||
def llGetAnimationList(id):
|
def llGetAnimationList(id):
|
||||||
assert iskey(id)
|
id = fk(id)
|
||||||
if not cond(id):
|
if not cond(id):
|
||||||
return []
|
return []
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
|
|
||||||
def llGetBoundingBox(id):
|
def llGetBoundingBox(id):
|
||||||
assert iskey(id)
|
id = fk(id)
|
||||||
if not cond(id):
|
if not cond(id):
|
||||||
return []
|
return []
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
|
|
||||||
def llGetColor(face):
|
def llGetColor(face):
|
||||||
assert isinteger(face)
|
face = fi(face)
|
||||||
if face > 8:
|
if face > 8:
|
||||||
return Vector((1.,1.,1.))
|
return Vector((1.,1.,1.))
|
||||||
# Returns face 0 when negative (can't be computed)
|
# Returns face 0 when negative (can't be computed)
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
|
|
||||||
def llGetDisplayName(id):
|
def llGetDisplayName(id):
|
||||||
assert iskey(id)
|
id = fk(id)
|
||||||
if not cond(id):
|
if not cond(id):
|
||||||
return u''
|
return u''
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
|
|
||||||
def llGetEnv(s):
|
def llGetEnv(s):
|
||||||
assert isstring(s)
|
s = fs(s)
|
||||||
if s not in GetEnvSettings:
|
if s not in GetEnvSettings:
|
||||||
return u""
|
return u""
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
|
|
||||||
def llGetExperienceErrorMessage(errno):
|
def llGetExperienceErrorMessage(errno):
|
||||||
assert isinteger(errno)
|
errno = fi(errno)
|
||||||
if errno < -1 or errno > 18:
|
if errno < -1 or errno > 18:
|
||||||
errno = -1
|
errno = -1
|
||||||
return xp_error_messages[errno]
|
return xp_error_messages[errno]
|
||||||
|
|
||||||
def llGetExperienceList(id):
|
def llGetExperienceList(id):
|
||||||
assert iskey(id)
|
id = fk(id)
|
||||||
# This function is not implemented and always returns empty list
|
# This function is not implemented and always returns empty list
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def llGetHTTPHeader(id, s):
|
def llGetHTTPHeader(id, s):
|
||||||
assert iskey(id)
|
id = fk(id)
|
||||||
assert isstring(s)
|
s = fs(s)
|
||||||
if not cond(id):
|
if not cond(id):
|
||||||
return u''
|
return u''
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
|
|
||||||
def llGetInventoryKey(s):
|
def llGetInventoryKey(s):
|
||||||
assert isstring(s)
|
s = fs(s)
|
||||||
if s == u'':
|
if s == u'':
|
||||||
return Key(NULL_KEY)
|
return Key(NULL_KEY)
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
|
|
||||||
def llGetInventoryName(kind, index):
|
def llGetInventoryName(kind, index):
|
||||||
assert isinteger(kind)
|
kind = fi(kind)
|
||||||
assert isinteger(index)
|
index = fi(index)
|
||||||
if kind != -1 and kind not in valid_inventory_kinds or index < 0:
|
if kind != -1 and kind not in valid_inventory_kinds or index < 0:
|
||||||
return u''
|
return u''
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
|
|
||||||
def llGetInventoryNumber(kind):
|
def llGetInventoryNumber(kind):
|
||||||
assert isinteger(kind)
|
kind = fi(kind)
|
||||||
if kind != -1 and kind not in valid_inventory_kinds:
|
if kind != -1 and kind not in valid_inventory_kinds:
|
||||||
return 0
|
return 0
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
|
|
||||||
def llGetInventoryPermMask(item, category):
|
def llGetInventoryPermMask(item, category):
|
||||||
assert isstring(item)
|
item = fs(item)
|
||||||
assert isinteger(category)
|
category = fi(category)
|
||||||
if category < 0 or category > 4 or item == u'':
|
if category < 0 or category > 4 or item == u'':
|
||||||
return 0
|
return 0
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
|
|
||||||
|
|
||||||
def llGetOwnerKey(id):
|
def llGetOwnerKey(id):
|
||||||
assert iskey(id)
|
id = fk(id)
|
||||||
if not cond(id):
|
if not cond(id):
|
||||||
return Key(NULL_KEY)
|
return Key(NULL_KEY)
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
|
|
|
@ -1115,32 +1115,7 @@ class foldconst(object):
|
||||||
# Call it
|
# Call it
|
||||||
fn = sym['Fn']
|
fn = sym['Fn']
|
||||||
args = [arg['value'] for arg in child]
|
args = [arg['value'] for arg in child]
|
||||||
argtypes = sym['ParamTypes']
|
assert len(args) == len(sym['ParamTypes'])
|
||||||
assert(len(args) == len(argtypes))
|
|
||||||
for argnum in range(len(args)):
|
|
||||||
# Adapt types of params
|
|
||||||
if argtypes[argnum] == 'string':
|
|
||||||
args[argnum] = lslfuncs.fs(args[argnum])
|
|
||||||
elif argtypes[argnum] == 'key':
|
|
||||||
args[argnum] = lslfuncs.fk(args[argnum])
|
|
||||||
elif argtypes[argnum] == 'float':
|
|
||||||
args[argnum] = lslfuncs.ff(args[argnum])
|
|
||||||
elif argtypes[argnum] == 'vector':
|
|
||||||
args[argnum] = lslfuncs.v2f(args[argnum])
|
|
||||||
elif argtypes[argnum] == 'quaternion':
|
|
||||||
args[argnum] = lslfuncs.q2f(args[argnum])
|
|
||||||
elif argtypes[argnum] == 'list':
|
|
||||||
# ensure vectors and quaternions passed to
|
|
||||||
# functions have only float components
|
|
||||||
assert type(args[argnum]) == list
|
|
||||||
# make a shallow copy
|
|
||||||
args[argnum] = args[argnum][:]
|
|
||||||
for i in range(len(args[argnum])):
|
|
||||||
if type(args[argnum][i]) == Quaternion:
|
|
||||||
args[argnum][i] = lslfuncs.q2f(args[argnum][i])
|
|
||||||
elif type(args[argnum][i]) == Vector:
|
|
||||||
args[argnum][i] = lslfuncs.v2f(args[argnum][i])
|
|
||||||
del argtypes
|
|
||||||
try:
|
try:
|
||||||
# May raise ELSLCantCompute
|
# May raise ELSLCantCompute
|
||||||
if name[:10] == 'llDetected':
|
if name[:10] == 'llDetected':
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
import re
|
import re
|
||||||
import math
|
import math
|
||||||
from lslcommon import *
|
from lslcommon import *
|
||||||
from lslbasefuncs import llStringTrim, isstring, islist, InternalTypecast
|
from lslbasefuncs import llStringTrim, fs, fl, InternalTypecast
|
||||||
|
|
||||||
# INCOMPATIBILITY NOTE: The JSON functions in SL have very weird behaviour
|
# INCOMPATIBILITY NOTE: The JSON functions in SL have very weird behaviour
|
||||||
# in corner cases. Despite our best efforts, that behaviour is not replicated
|
# in corner cases. Despite our best efforts, that behaviour is not replicated
|
||||||
|
@ -494,7 +494,7 @@ def InternalJson2Elem(json):
|
||||||
return json
|
return json
|
||||||
|
|
||||||
def llJson2List(json):
|
def llJson2List(json):
|
||||||
assert isstring(json)
|
json = fs(json)
|
||||||
json = llStringTrim(json, 3) # STRING_TRIM
|
json = llStringTrim(json, 3) # STRING_TRIM
|
||||||
|
|
||||||
if json == u'':
|
if json == u'':
|
||||||
|
@ -577,8 +577,8 @@ def llJson2List(json):
|
||||||
return [InternalJson2Elem(json)]
|
return [InternalJson2Elem(json)]
|
||||||
|
|
||||||
def llJsonGetValue(json, lst):
|
def llJsonGetValue(json, lst):
|
||||||
assert isstring(json)
|
json = fs(json)
|
||||||
assert islist(lst)
|
lst = fl(lst)
|
||||||
return InternalJsonFindValue(json, lst, ReturnsToken=False)
|
return InternalJsonFindValue(json, lst, ReturnsToken=False)
|
||||||
|
|
||||||
# llJsonSetValue was finally not implemented. This is a failed attempt
|
# llJsonSetValue was finally not implemented. This is a failed attempt
|
||||||
|
@ -613,9 +613,9 @@ def llJsonGetValue(json, lst):
|
||||||
|
|
||||||
|
|
||||||
def llJsonSetValue(json, lst, val):
|
def llJsonSetValue(json, lst, val):
|
||||||
assert isstring(json)
|
json = fs(json)
|
||||||
assert islist(lst)
|
lst = fl(lst)
|
||||||
assert isstring(val)
|
val = fs(val)
|
||||||
if lst == []:
|
if lst == []:
|
||||||
# [] replaces the entire string no matter if it was invalid
|
# [] replaces the entire string no matter if it was invalid
|
||||||
if val == JSON_DELETE:
|
if val == JSON_DELETE:
|
||||||
|
@ -631,16 +631,16 @@ def llJsonSetValue(json, lst, val):
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def llJsonValueType(json, lst):
|
def llJsonValueType(json, lst):
|
||||||
assert isstring(json)
|
json = fs(json)
|
||||||
assert islist(lst)
|
lst = fl(lst)
|
||||||
ret = InternalJsonFindValue(json, lst, ReturnsToken=True)
|
ret = InternalJsonFindValue(json, lst, ReturnsToken=True)
|
||||||
if ret == JSON_INVALID:
|
if ret == JSON_INVALID:
|
||||||
return ret
|
return ret
|
||||||
return ret[2]
|
return ret[2]
|
||||||
|
|
||||||
def llList2Json(kind, lst):
|
def llList2Json(kind, lst):
|
||||||
assert isstring(kind)
|
kind = fs(kind)
|
||||||
assert islist(lst)
|
lst = fl(lst)
|
||||||
|
|
||||||
if kind == JSON_OBJECT:
|
if kind == JSON_OBJECT:
|
||||||
ret = u'{'
|
ret = u'{'
|
||||||
|
|
|
@ -1381,9 +1381,10 @@ def do_tests():
|
||||||
test('llList2CSV(llParseStringKeepNulls(u"1abc2ab3abc4",[u"ab"],[u"ab"]))',
|
test('llList2CSV(llParseStringKeepNulls(u"1abc2ab3abc4",[u"ab"],[u"ab"]))',
|
||||||
u'1, c2, 3, c4')
|
u'1, c2, 3, c4')
|
||||||
test('llParseStringKeepNulls(u"",[],[])', [u""])
|
test('llParseStringKeepNulls(u"",[],[])', [u""])
|
||||||
test('llParseStringKeepNulls(u"",[],[""])', [u""])
|
shouldexcept('llParseStringKeepNulls(u"",[],[""])', ELSLInvalidType)
|
||||||
test('llParseStringKeepNulls(u"",[""],[])', [u""])
|
test('llParseStringKeepNulls(u"",[],[u""])', [u""])
|
||||||
test('llParseStringKeepNulls(u"",[""],[""])', [u""])
|
test('llParseStringKeepNulls(u"",[u""],[])', [u""])
|
||||||
|
test('llParseStringKeepNulls(u"",[u""],[u""])', [u""])
|
||||||
test('llParseString2List(u"",[],[])', [])
|
test('llParseString2List(u"",[],[])', [])
|
||||||
test('llParseString2List(u"",[],[u""])', [])
|
test('llParseString2List(u"",[],[u""])', [])
|
||||||
test('llParseString2List(u"",[u""],[])', [])
|
test('llParseString2List(u"",[u""],[])', [])
|
||||||
|
@ -1592,7 +1593,7 @@ def do_tests():
|
||||||
test(r'llJsonGetValue(u"{\"a\":[1],\"a\":[2],\"a\":[3]}", [u"a",0])', u'3')
|
test(r'llJsonGetValue(u"{\"a\":[1],\"a\":[2],\"a\":[3]}", [u"a",0])', u'3')
|
||||||
test(r'llJsonGetValue(u"{\"a\":[2,3,[4]],\"a\":1}", [u"a", 2, 0])', JSON_INVALID)
|
test(r'llJsonGetValue(u"{\"a\":[2,3,[4]],\"a\":1}", [u"a", 2, 0])', JSON_INVALID)
|
||||||
|
|
||||||
test(r'llJsonGetValue(u"{\"a\":1,}",["a"])', JSON_INVALID)
|
test(r'llJsonGetValue(u"{\"a\":1,}",[u"a"])', JSON_INVALID)
|
||||||
|
|
||||||
|
|
||||||
test(r'llJsonGetValue(u"[3,4,5,[6,7,8],:9,10]", [1])', JSON_INVALID) # *ing crap! ALL entries are tested before the result is returned...
|
test(r'llJsonGetValue(u"[3,4,5,[6,7,8],:9,10]", [1])', JSON_INVALID) # *ing crap! ALL entries are tested before the result is returned...
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue