Skip to content

Commit

Permalink
Merge pull request #24 from sean1832/dev
Browse files Browse the repository at this point in the history
Light Deserialization and Performance Enhancements with CRC16 Optimization
  • Loading branch information
sean1832 authored Oct 4, 2024
2 parents 45fb01d + 2880a59 commit 4d43081
Show file tree
Hide file tree
Showing 21 changed files with 547 additions and 159 deletions.
5 changes: 5 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"files.associations": {
"stdint.h": "c"
}
}
2 changes: 1 addition & 1 deletion portal/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
bl_info = {
"name": "Portal",
"author": "Zeke Zhang",
"version": (0, 1, 2),
"version": (0, 2, 0),
"blender": (4, 2, 0),
"category": "System",
"location": "View3D > Sidebar > Portal",
Expand Down
Binary file added portal/bin/crc16-ccitt.dll
Binary file not shown.
139 changes: 75 additions & 64 deletions portal/data_struct/color.py
Original file line number Diff line number Diff line change
@@ -1,80 +1,91 @@
from typing import Tuple
from enum import Enum
from typing import Tuple, Union


class ColorType(Enum):
RGB = "rgb"
RGBA = "rgba"


class Color:
def __init__(self, r: int, g: int, b: int, a: float = 1.0) -> None:
"""Initialize a Color object with RGB and alpha values."""
self.r = r
self.g = g
self.b = b
self.a = a
"""Initialize a Color object with RGB and optional alpha values."""
self.r = self._validate_color_value(r, "r")
self.g = self._validate_color_value(g, "g")
self.b = self._validate_color_value(b, "b")
self.a = self._validate_alpha_value(a)

def to_hex(self) -> str:
"""Convert the color to a hexadecimal string."""
return f"#{self.r:02x}{self.g:02x}{self.b:02x}"

def to_tuple(self) -> Tuple[int, int, int, float]:
"""Return the color as a tuple of (r, g, b, a)."""
return (self.r, self.g, self.b, self.a)
@staticmethod
def _validate_color_value(value: int, component: str) -> int:
"""Ensure color component (r, g, b) is a valid integer in range [0, 255]."""
if not isinstance(value, int):
raise TypeError(f"Component '{component}' must be an integer.")
if not 0 <= value <= 255:
raise ValueError(f"Component '{component}' must be between 0 and 255.")
return value

def to_normalized_tuple(self) -> Tuple[float, float, float, float]:
"""Return the color as a normalized tuple of (r, g, b, a)."""
return (self.r / 255, self.g / 255, self.b / 255, self.a)
@staticmethod
def _validate_alpha_value(value: float) -> float:
"""Ensure alpha component (a) is a valid float in range [0.0, 1.0]."""
if not isinstance(value, (float, int)):
raise TypeError("Alpha must be a float or int.")
value = float(value)
if not 0.0 <= value <= 1.0:
raise ValueError("Alpha must be between 0.0 and 1.0.")
return value

def to_hex(self, type: Union[ColorType, str] = ColorType.RGBA) -> str:
"""Convert color to hexadecimal string (RGB or RGBA)."""
type = type.lower() if isinstance(type, str) else type.value
if type == "rgb":
return f"#{self.r:02X}{self.g:02X}{self.b:02X}"
elif type == "rgba":
alpha_int = int(round(self.a * 255))
return f"#{self.r:02X}{self.g:02X}{self.b:02X}{alpha_int:02X}"
else:
raise ValueError("Invalid color type. Use 'rgb' or 'rgba'.")

def to_tuple(self, type: Union[ColorType, str] = ColorType.RGBA, normalize: bool = False) -> Union[Tuple[int, int, int], Tuple[int, int, int, float]]:
"""Return the color as an (r, g, b) or (r, g, b, a) tuple, optionally normalized."""
type = type.lower() if isinstance(type, str) else type.value
if type == "rgb":
result = (self.r, self.g, self.b)
else:
result = (self.r, self.g, self.b, self.a)

if normalize:
return tuple(x / 255 for x in result) if type == "rgb" else (result[0] / 255, result[1] / 255, result[2] / 255, self.a)

return result

def __str__(self) -> str:
"""Return the string representation of the color."""
return f"Color({self.r}, {self.g}, {self.b}, {self.a})"
return f"Color(r={self.r}, g={self.g}, b={self.b}, a={self.a})"

def __repr__(self) -> str:
return self.__str__()

class ColorFactory:
@staticmethod
def from_hex(hex_str: str) -> Color:
"""Create a Color object from a hexadecimal string."""
def from_hex(hex_str: str) -> "Color":
"""Create a Color from a hexadecimal string (#RRGGBB or #RRGGBBAA)."""
if not hex_str.startswith("#") or len(hex_str) not in (7, 9):
raise ValueError("Hex string must start with '#' and be 7 or 9 characters long.")
hex_str = hex_str.lstrip("#")
return Color(*[int(hex_str[i : i + 2], 16) for i in (0, 2, 4)])

@staticmethod
def from_rgb(r: int, g: int, b: int, a: float = 1.0) -> Color:
"""Create a Color object from RGB and alpha values."""
r, g, b = (int(hex_str[i:i + 2], 16) for i in (0, 2, 4))
a = int(hex_str[6:8], 16) / 255.0 if len(hex_str) == 8 else 1.0
return Color(r, g, b, a)

@staticmethod
def from_tuple(color_tuple: Tuple[int, int, int, float]) -> Color:
"""Create a Color object from a tuple of (r, g, b, a)."""
return Color(*color_tuple)
def from_tuple(color_tuple: Union[Tuple[int, int, int], Tuple[int, int, int, float]]) -> "Color":
"""Create a Color from an (r, g, b) or (r, g, b, a) tuple."""
if len(color_tuple) not in (3, 4):
raise ValueError("Tuple must have 3 or 4 elements.")
return Color(*color_tuple) if len(color_tuple) == 3 else Color(*color_tuple[:3], color_tuple[3])

@staticmethod
def from_normalized_tuple(color_tuple: Tuple[float, float, float, float]) -> Color:
"""Create a Color object from a normalized tuple of (r, g, b, a)."""
return Color(*(int(x * 255) for x in color_tuple))


class ColorDecorator:
def __init__(self, color: Color) -> None:
"""Initialize a ColorDecorator with a Color object."""
self._color = color

def to_hex(self) -> str:
"""Convert the decorated color to a hexadecimal string."""
return self._color.to_hex()

def to_tuple(self) -> Tuple[int, int, int, float]:
"""Return the decorated color as a tuple of (r, g, b, a)."""
return self._color.to_tuple()

def __str__(self) -> str:
"""Return the string representation of the decorated color."""
return str(self._color)


class AlphaColorDecorator(ColorDecorator):
def __init__(self, color: Color, alpha: float) -> None:
"""Initialize an AlphaColorDecorator with a Color object and an alpha value."""
super().__init__(color)
self._color.a = alpha


# Example usage:
# color1 = ColorFactory.from_hex("#ff5733")
# color2 = ColorFactory.from_rgb(255, 87, 51)
# decorated_color = AlphaColorDecorator(color1, 0.5)
# print(decorated_color)
def from_normalized_tuple(color_tuple: Union[Tuple[float, float, float], Tuple[float, float, float, float]]) -> "Color":
"""Create a Color from a normalized (0.0-1.0) tuple."""
if len(color_tuple) not in (3, 4):
raise ValueError("Normalized tuple must have 3 or 4 elements.")
r, g, b = (int(round(x * 255)) for x in color_tuple[:3])
a = color_tuple[3] if len(color_tuple) == 4 else 1.0
return Color(r, g, b, a)
Loading

0 comments on commit 4d43081

Please sign in to comment.