Files
Hippolyzer/hippolyzer/lib/base/objects.py
2021-04-30 17:30:24 +00:00

266 lines
9.7 KiB
Python

"""
Copyright 2009, Linden Research, Inc.
See NOTICE.md for previous contributors
Copyright 2021, Salad Dais
All Rights Reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
"""
from typing import *
import lazy_object_proxy
from hippolyzer.lib.base.datatypes import Vector3, Quaternion, Vector4
class Object:
""" represents an Object
Initialize the Object class instance
>>> obj = Object()
"""
__slots__ = (
"LocalID",
"State",
"FullID",
"CRC",
"PCode",
"Material",
"ClickAction",
"Scale",
"ParentID",
"UpdateFlags",
"PathCurve",
"ProfileCurve",
"PathBegin",
"PathEnd",
"PathScaleX",
"PathScaleY",
"PathShearX",
"PathShearY",
"PathTwist",
"PathTwistBegin",
"PathRadiusOffset",
"PathTaperX",
"PathTaperY",
"PathRevolutions",
"PathSkew",
"ProfileBegin",
"ProfileEnd",
"ProfileHollow",
"TextureEntry",
"TextureAnim",
"NameValue",
"Data",
"Text",
"TextColor",
"MediaURL",
"PSBlock",
"ExtraParams",
"Sound",
"OwnerID",
"SoundGain",
"SoundFlags",
"SoundRadius",
"JointType",
"JointPivot",
"JointAxisOrAnchor",
"TreeSpecies",
"ObjectCosts",
"FootCollisionPlane",
"Position",
"Velocity",
"Acceleration",
"Rotation",
"AngularVelocity",
"CreatorID",
"GroupID",
"CreationDate",
"BaseMask",
"OwnerMask",
"GroupMask",
"EveryoneMask",
"NextOwnerMask",
"OwnershipCost",
"SaleType",
"SalePrice",
"AggregatePerms",
"AggregatePermTextures",
"AggregatePermTexturesOwner",
"Category",
"InventorySerial",
"ItemID",
"FolderID",
"FromTaskID",
"LastOwnerID",
"Name",
"Description",
"TouchName",
"SitName",
"TextureID",
"ChildIDs",
"Children",
"Parent",
"ScratchPad",
"__weakref__",
)
def __init__(self, *, ID=None, LocalID=None, State=None, FullID=None, CRC=None, PCode=None, Material=None,
ClickAction=None, Scale=None, ParentID=None, UpdateFlags=None, PathCurve=None, ProfileCurve=None,
PathBegin=None, PathEnd=None, PathScaleX=None, PathScaleY=None, PathShearX=None, PathShearY=None,
PathTwist=None, PathTwistBegin=None, PathRadiusOffset=None, PathTaperX=None, PathTaperY=None,
PathRevolutions=None, PathSkew=None, ProfileBegin=None, ProfileEnd=None, ProfileHollow=None,
TextureEntry=None, TextureAnim=None, NameValue=None, Data=None, Text=None, TextColor=None,
MediaURL=None, PSBlock=None, ExtraParams=None, Sound=None, OwnerID=None, SoundGain=None,
SoundFlags=None, SoundRadius=None, JointType=None, JointPivot=None, JointAxisOrAnchor=None,
FootCollisionPlane=None, Position=None, Velocity=None, Acceleration=None, Rotation=None,
AngularVelocity=None, TreeSpecies=None, ObjectCosts=None, ScratchPad=None):
""" set up the object attributes """
self.LocalID = LocalID or ID # U32
self.State = State # U8
self.FullID = FullID # LLUUID
self.CRC = CRC # U32 // TEMPORARY HACK FOR JAMES
self.PCode = PCode # U8
self.Material = Material # U8
self.ClickAction = ClickAction # U8
self.Scale = Scale # LLVector3
self.ParentID = ParentID # U32
# Actually contains a weakref proxy
self.Parent: Optional[Object] = None
self.UpdateFlags = UpdateFlags # U32 // U32, see object_flags.h
self.PathCurve = PathCurve # U8
self.ProfileCurve = ProfileCurve # U8
self.PathBegin = PathBegin # U16 // 0 to 1, quanta = 0.01
self.PathEnd = PathEnd # U16 // 0 to 1, quanta = 0.01
self.PathScaleX = PathScaleX # U8 // 0 to 1, quanta = 0.01
self.PathScaleY = PathScaleY # U8 // 0 to 1, quanta = 0.01
self.PathShearX = PathShearX # U8 // -.5 to .5, quanta = 0.01
self.PathShearY = PathShearY # U8 // -.5 to .5, quanta = 0.01
self.PathTwist = PathTwist # S8 // -1 to 1, quanta = 0.01
self.PathTwistBegin = PathTwistBegin # S8 // -1 to 1, quanta = 0.01
self.PathRadiusOffset = PathRadiusOffset # S8 // -1 to 1, quanta = 0.01
self.PathTaperX = PathTaperX # S8 // -1 to 1, quanta = 0.01
self.PathTaperY = PathTaperY # S8 // -1 to 1, quanta = 0.01
self.PathRevolutions = PathRevolutions # U8 // 0 to 3, quanta = 0.015
self.PathSkew = PathSkew # S8 // -1 to 1, quanta = 0.01
self.ProfileBegin = ProfileBegin # U16 // 0 to 1, quanta = 0.01
self.ProfileEnd = ProfileEnd # U16 // 0 to 1, quanta = 0.01
self.ProfileHollow = ProfileHollow # U16 // 0 to 1, quanta = 0.01
self.TextureEntry = TextureEntry # Variable 2
self.TextureAnim = TextureAnim # Variable 1
self.NameValue = NameValue # Variable 2
self.Data = Data # Variable 2
self.Text = Text # Variable 1 // llSetText() hovering text
self.TextColor = TextColor # Fixed 4 // actually, a LLColor4U
self.MediaURL = MediaURL # Variable 1 // URL for web page, movie, etc.
self.PSBlock = PSBlock # Variable 1
self.ExtraParams = ExtraParams or {} # Variable 1
self.Sound = Sound # LLUUID
self.OwnerID = OwnerID # LLUUID // HACK object's owner id, only set if non-null sound, for muting
self.SoundGain = SoundGain # F32
self.SoundFlags = SoundFlags # U8
self.SoundRadius = SoundRadius # F32 // cutoff radius
self.JointType = JointType # U8
self.JointPivot = JointPivot # LLVector3
self.JointAxisOrAnchor = JointAxisOrAnchor # LLVector3
self.TreeSpecies = TreeSpecies
self.ScratchPad = ScratchPad
self.ObjectCosts = ObjectCosts or {}
self.ChildIDs = []
# Same as parent, contains weakref proxies.
self.Children: List[Object] = []
# from ObjectUpdateCompressed
self.FootCollisionPlane: Optional[Vector4] = FootCollisionPlane
self.Position: Optional[Vector3] = Position
self.Velocity: Optional[Vector3] = Velocity
self.Acceleration: Optional[Vector3] = Acceleration
self.Rotation: Optional[Quaternion] = Rotation
self.AngularVelocity: Optional[Vector3] = AngularVelocity
# from ObjectProperties
self.CreatorID = None
self.GroupID = None
self.CreationDate = None
self.BaseMask = None
self.OwnerMask = None
self.GroupMask = None
self.EveryoneMask = None
self.NextOwnerMask = None
self.OwnershipCost = None
# TaxRate
self.SaleType = None
self.SalePrice = None
self.AggregatePerms = None
self.AggregatePermTextures = None
self.AggregatePermTexturesOwner = None
self.Category = None
self.InventorySerial = None
self.ItemID = None
self.FolderID = None
self.FromTaskID = None
self.LastOwnerID = None
self.Name = None
self.Description = None
self.TouchName = None
self.SitName = None
self.TextureID = None
@property
def RegionPosition(self) -> Vector3:
if not self.ParentID:
return self.Position
if not self.Parent:
raise ValueError("Can't calculate an orphan's RegionPosition")
# TODO: Cache this and dirty cache if ancestor updates pos?
return self.Parent.RegionPosition + (self.Position.rotated(self.Parent.RegionRotation))
@property
def RegionRotation(self) -> Quaternion:
if not self.ParentID:
return self.Rotation
if not self.Parent:
raise ValueError("Can't calculate an orphan's RegionRotation")
# TODO: Cache this and dirty cache if ancestor updates rot?
return self.Rotation * self.Parent.RegionRotation
def update_properties(self, properties: Dict[str, Any]) -> Set[str]:
""" takes a dictionary of attribute:value and makes it so """
updated_properties = set()
for key, val in properties.items():
if hasattr(self, key):
old_val = getattr(self, key, val)
# Don't check equality if we're using a lazy proxy,
# parsing is deferred until we actually use it.
is_proxy = isinstance(val, lazy_object_proxy.Proxy)
if is_proxy or old_val != val:
updated_properties.add(key)
setattr(self, key, val)
return updated_properties
def to_dict(self):
return {
x: getattr(self, x) for x in dir(self)
if not isinstance(getattr(self.__class__, x, None), property) and
not callable(getattr(self, x)) and not x.startswith("_")
}