From aa2cdc9ff858cb94ea64f87a58d77d4fa3d252d9 Mon Sep 17 00:00:00 2001 From: Brent Yi Date: Fri, 8 Nov 2024 02:22:32 -0800 Subject: [PATCH] Fix array mutation bugs (#319) * Copy arrays passed as input * Fix shape changes --- src/viser/_scene_handles.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/viser/_scene_handles.py b/src/viser/_scene_handles.py index 280e2355..543d5a8e 100644 --- a/src/viser/_scene_handles.py +++ b/src/viser/_scene_handles.py @@ -71,7 +71,17 @@ def __setattr__(self, name: str, value: Any) -> None: elif current_value == value: return - setattr(handle._impl.props, name, value) + # Update the value. + if isinstance(value, np.ndarray): + assert value.dtype == current_value.dtype + if value.shape == current_value.shape: + current_value[:] = value + else: + setattr(handle._impl.props, name, value.copy()) + else: + # Non-array properties should be immutable, so no need to copy. + setattr(handle._impl.props, name, value) + handle._impl.api._websock_interface.queue_message( _messages.SceneNodeUpdateMessage(handle.name, {name: value}) ) @@ -171,7 +181,7 @@ def _make( assert isinstance(message, _messages.Message) api._websock_interface.queue_message(message) - out = cls(_SceneNodeHandleState(name, copy.copy(message.props), api)) + out = cls(_SceneNodeHandleState(name, copy.deepcopy(message.props), api)) api._handle_from_node_name[name] = out out.wxyz = wxyz @@ -198,7 +208,7 @@ def wxyz(self, wxyz: tuple[float, float, float, float] | np.ndarray) -> None: wxyz_array = np.asarray(wxyz) if np.allclose(wxyz_cast, self._impl.wxyz): return - self._impl.wxyz = wxyz_array + self._impl.wxyz[:] = wxyz_array self._impl.api._websock_interface.queue_message( _messages.SetOrientationMessage(self._impl.name, wxyz_cast) ) @@ -218,7 +228,7 @@ def position(self, position: tuple[float, float, float] | np.ndarray) -> None: position_array = np.asarray(position) if np.allclose(position_array, self._impl.position): return - self._impl.position = position_array + self._impl.position[:] = position_array self._impl.api._websock_interface.queue_message( _messages.SetPositionMessage(self._impl.name, position_cast) ) @@ -464,7 +474,7 @@ def wxyz(self, wxyz: tuple[float, float, float, float] | np.ndarray) -> None: wxyz_array = np.asarray(wxyz) if np.allclose(wxyz_cast, self._impl.wxyz): return - self._impl.wxyz = wxyz_array + self._impl.wxyz[:] = wxyz_array self._impl.websock_interface.queue_message( _messages.SetBoneOrientationMessage( self._impl.name, self._impl.bone_index, wxyz_cast @@ -486,7 +496,7 @@ def position(self, position: tuple[float, float, float] | np.ndarray) -> None: position_array = np.asarray(position) if np.allclose(position_array, self._impl.position): return - self._impl.position = position_array + self._impl.position[:] = position_array self._impl.websock_interface.queue_message( _messages.SetBonePositionMessage( self._impl.name, self._impl.bone_index, position_cast