TextureEntry -> TextureEntryCollection, improve .realize()
The "TextureEntry" name from the message template is kind of a misnomer, the field actually includes multiple TextureEntries.
This commit is contained in:
@@ -27,7 +27,7 @@ from mitmproxy.http import HTTPFlow
|
||||
from hippolyzer.lib.base.datatypes import UUID
|
||||
from hippolyzer.lib.base.jp2_utils import BufferedJp2k
|
||||
from hippolyzer.lib.base.multiprocessing_utils import ParentProcessWatcher
|
||||
from hippolyzer.lib.base.templates import TextureEntry
|
||||
from hippolyzer.lib.base.templates import TextureEntryCollection
|
||||
from hippolyzer.lib.proxy.addon_utils import AssetAliasTracker, BaseAddon, GlobalProperty, AddonProcess
|
||||
from hippolyzer.lib.proxy.http_flow import HippoHTTPFlow
|
||||
from hippolyzer.lib.base.message.message import Message
|
||||
@@ -148,7 +148,7 @@ class MonochromeAddon(BaseAddon):
|
||||
message["RegionInfo"][field_name] = tracker.get_alias_uuid(val)
|
||||
|
||||
@staticmethod
|
||||
def _make_te_monochrome(tracker: AssetAliasTracker, parsed_te: TextureEntry):
|
||||
def _make_te_monochrome(tracker: AssetAliasTracker, parsed_te: TextureEntryCollection):
|
||||
# Need a deepcopy because TEs are owned by the ObjectManager
|
||||
# and we don't want to change the canonical view.
|
||||
parsed_te = copy.deepcopy(parsed_te)
|
||||
|
||||
@@ -14,7 +14,7 @@ from PySide6.QtGui import QImage
|
||||
from hippolyzer.lib.base.datatypes import UUID, Vector3, Quaternion
|
||||
from hippolyzer.lib.base.helpers import to_chunks
|
||||
from hippolyzer.lib.base.message.message import Block, Message
|
||||
from hippolyzer.lib.base.templates import ObjectUpdateFlags, PCode, MCode, MultipleObjectUpdateFlags, TextureEntry
|
||||
from hippolyzer.lib.base.templates import ObjectUpdateFlags, PCode, MCode, MultipleObjectUpdateFlags, TextureEntryCollection
|
||||
from hippolyzer.lib.client.object_manager import ObjectEvent, UpdateType
|
||||
from hippolyzer.lib.proxy.addon_utils import BaseAddon
|
||||
from hippolyzer.lib.proxy.addons import AddonManager
|
||||
@@ -124,7 +124,7 @@ class PixelArtistAddon(BaseAddon):
|
||||
y = i // width
|
||||
obj = created_prims[prim_idx]
|
||||
# Set a blank texture on all faces
|
||||
te = TextureEntry()
|
||||
te = TextureEntryCollection()
|
||||
te.Textures[None] = UUID('5748decc-f629-461c-9a36-a35a221fe21f')
|
||||
# Set the prim color to the color from the pixel
|
||||
te.Color[None] = pixel_color
|
||||
|
||||
@@ -71,7 +71,7 @@ class Object(recordclass.datatuple): # type: ignore
|
||||
ProfileBegin: Optional[int] = None
|
||||
ProfileEnd: Optional[int] = None
|
||||
ProfileHollow: Optional[int] = None
|
||||
TextureEntry: Optional[tmpls.TextureEntry] = None
|
||||
TextureEntry: Optional[tmpls.TextureEntryCollection] = None
|
||||
TextureAnim: Optional[tmpls.TextureAnim] = None
|
||||
NameValue: Optional[Any] = None
|
||||
Data: Optional[Any] = None
|
||||
@@ -294,7 +294,7 @@ def normalize_object_update_compressed_data(data: bytes):
|
||||
compressed["SoundRadius"] = 0.0
|
||||
compressed["Sound"] = UUID()
|
||||
if compressed["TextureEntry"] is None:
|
||||
compressed["TextureEntry"] = tmpls.TextureEntry()
|
||||
compressed["TextureEntry"] = tmpls.TextureEntryCollection()
|
||||
|
||||
object_data = {
|
||||
"PSBlock": ps_block.value,
|
||||
|
||||
@@ -1063,6 +1063,23 @@ class PackedTERotation(se.QuantizedFloat):
|
||||
|
||||
@dataclasses.dataclass
|
||||
class TextureEntry:
|
||||
"""Representation of a TE for a single face. Not sent over the wire."""
|
||||
Textures: UUID = UUID('89556747-24cb-43ed-920b-47caed15465f')
|
||||
Color: bytes = b"\xff\xff\xff\xff"
|
||||
ScalesS: float = 1.0
|
||||
ScalesT: float = 1.0
|
||||
OffsetsS: float = 0.0
|
||||
OffsetsT: float = 0.0
|
||||
# In radians
|
||||
Rotation: float = 0.0
|
||||
MediaFlags: Optional[MediaFlags] = None
|
||||
BasicMaterials: Optional[BasicMaterials] = None
|
||||
Glow: int = 0
|
||||
Materials: UUID = UUID.ZERO
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class TextureEntryCollection:
|
||||
Textures: Dict[_TE_FIELD_KEY, UUID] = _te_field(
|
||||
# Plywood texture
|
||||
se.UUID, first=True, default=UUID('89556747-24cb-43ed-920b-47caed15465f'))
|
||||
@@ -1080,6 +1097,7 @@ class TextureEntry:
|
||||
MEDIA_FLAGS,
|
||||
default_factory=lambda: MediaFlags(WebPage=False, TexGen=TexGen.DEFAULT, _Unused=0),
|
||||
)
|
||||
# TODO: dequantize
|
||||
Glow: Dict[_TE_FIELD_KEY, int] = _te_field(se.U8, default=0)
|
||||
Materials: Dict[_TE_FIELD_KEY, UUID] = _te_field(se.UUID, optional=True, default=UUID.ZERO)
|
||||
|
||||
@@ -1087,21 +1105,16 @@ class TextureEntry:
|
||||
"""Return `self` regardless of whether this is lazy wrapped object or not"""
|
||||
return self
|
||||
|
||||
def realize(self, num_faces: int):
|
||||
def realize(self, num_faces: int) -> List[TextureEntry]:
|
||||
"""
|
||||
Turn the "default" vs "exception cases" wire format TE representation to per-face lookups
|
||||
|
||||
Makes it easier to just index into a list of offsets with a face number.
|
||||
Returns something like:
|
||||
{
|
||||
"OffsetsS": [0.5, 0.2, ...],
|
||||
...
|
||||
}
|
||||
Makes it easier to get all TE details associated with a specific face
|
||||
"""
|
||||
as_dict = {}
|
||||
as_dicts = [dict() for _ in range(num_faces)]
|
||||
for key, vals in dataclasses.asdict(self).items():
|
||||
# Fill all of the faces in this key with the default value stored in the TE
|
||||
key_arr = as_dict[key] = [vals[None]] * num_faces
|
||||
# Fill give all faces the default value for this key
|
||||
for te in as_dicts:
|
||||
te[key] = vals[None]
|
||||
# Walk over the exception cases and replace the default value
|
||||
for face_nums, val in vals.items():
|
||||
# Default case already handled
|
||||
@@ -1110,11 +1123,11 @@ class TextureEntry:
|
||||
for face_num in face_nums:
|
||||
if face_num >= num_faces:
|
||||
raise ValueError(f"Bad value for num_faces? {face_num} >= {num_faces}")
|
||||
key_arr[face_num] = val
|
||||
return as_dict
|
||||
as_dicts[face_num][key] = val
|
||||
return [TextureEntry(**x) for x in as_dicts]
|
||||
|
||||
|
||||
TE_SERIALIZER = se.Dataclass(TextureEntry)
|
||||
TE_SERIALIZER = se.Dataclass(TextureEntryCollection)
|
||||
|
||||
|
||||
@se.subfield_serializer("ObjectUpdate", "ObjectData", "TextureEntry")
|
||||
|
||||
@@ -4,7 +4,7 @@ import unittest
|
||||
import hippolyzer.lib.base.serialization as se
|
||||
from hippolyzer.lib.base.datatypes import UUID
|
||||
from hippolyzer.lib.base.message.message_formatting import HumanMessageSerializer
|
||||
from hippolyzer.lib.base.templates import TextureEntrySubfieldSerializer, TEFaceBitfield, TextureEntry, PackedTERotation
|
||||
from hippolyzer.lib.base.templates import TextureEntrySubfieldSerializer, TEFaceBitfield, TextureEntryCollection, PackedTERotation
|
||||
|
||||
EXAMPLE_TE = b'\x89UgG$\xcbC\xed\x92\x0bG\xca\xed\x15F_\x08\xca*\x98:\x18\x02,\r\xf4\x1e\xc6\xf5\x91\x01]\x83\x014' \
|
||||
b'\x00\x90i+\x10\x80\xa1\xaa\xa2g\x11o\xa8]\xc6\x00\x00\x00\x00\x00\x00\x00\x00\x80?\x00\x00\x00\x80?' \
|
||||
@@ -19,9 +19,10 @@ class TemplateTests(unittest.TestCase):
|
||||
self.assertEqual(EXAMPLE_TE, serialized)
|
||||
|
||||
def test_realize_te(self):
|
||||
deserialized: TextureEntry = TextureEntrySubfieldSerializer.deserialize(None, EXAMPLE_TE)
|
||||
realized = deserialized.realize(num_faces=4)
|
||||
self.assertEqual(UUID('ca2a983a-1802-2c0d-f41e-c6f591015d83'), realized["Textures"][3])
|
||||
deserialized: TextureEntryCollection = TextureEntrySubfieldSerializer.deserialize(None, EXAMPLE_TE)
|
||||
realized = deserialized.realize(4)
|
||||
self.assertEqual(UUID('ca2a983a-1802-2c0d-f41e-c6f591015d83'), realized[3].Textures)
|
||||
self.assertEqual(UUID('89556747-24cb-43ed-920b-47caed15465f'), realized[1].Textures)
|
||||
with self.assertRaises(ValueError):
|
||||
deserialized.realize(3)
|
||||
|
||||
@@ -72,7 +73,7 @@ class TemplateTests(unittest.TestCase):
|
||||
self.assertEqual(pod_te, deser)
|
||||
|
||||
def test_textureentry_defaults(self):
|
||||
te = TextureEntry()
|
||||
te = TextureEntryCollection()
|
||||
self.assertEqual(UUID('89556747-24cb-43ed-920b-47caed15465f'), te.Textures[None])
|
||||
|
||||
def test_textureentry_rotation_packing(self):
|
||||
|
||||
Reference in New Issue
Block a user