I have made a script to manipulate objects with the keys and have extracted the essence of the problem here. Use the arrow keys LEFT and RIGHT to make the object rotate.
My problem is that the task continues and the object continues to rotate after i close the form.
So I can make many objects spin in the file… So how do I terminate this when I close the form?
import Rhino
import rhinoscriptsyntax as rs
import System.Windows.Forms as Forms
import math
# Global variables to store the current state
current_angle = 0 # Angle in degrees, 0 means facing "up" (positive Y direction)
move_forward = False
move_backward = False
turn_left = False
turn_right = False
def rotate_object(obj_id, angle):
"""Rotate the object to the given angle."""
# Find the object's centroid or a suitable rotation point
bbox=rs.BoundingBox(obj_id)
centroid = (bbox[0]+bbox[2])/2
# Apply the rotation transformation
rotation = Rhino.Geometry.Transform.Rotation(math.radians(angle), centroid)
rs.TransformObject(obj_id, rotation)
def update_movement(obj_id):
"""Update the object's movement based on the current key states."""
global current_angle
if turn_left:
current_angle += 1 # Turn left
if turn_right:
current_angle -= 1 # Turn right
# Rotate the object to face the current direction
rotate_object(obj_id, current_angle)
def on_key_down(sender, e):
"""Handle key press events."""
global move_forward, move_backward, turn_left, turn_right
if e.KeyCode == Forms.Keys.Left:
turn_left = True
elif e.KeyCode == Forms.Keys.Right:
turn_right = True
def on_key_up(sender, e):
"""Handle key release events."""
global move_forward, move_backward, turn_left, turn_right
if e.KeyCode == Forms.Keys.Left:
turn_left = False
elif e.KeyCode == Forms.Keys.Right:
turn_right = False
def main():
global obj_id
obj_id = rs.GetObject("Select an object to move")
if not obj_id:
return
# Create a form to capture key events
form = Forms.Form()
form.KeyPreview = True
form.KeyDown += on_key_down
form.KeyUp += on_key_up
# Configure the form to be visible
form.Text = "Car Simulator"
form.Width = 300
form.Height = 100
# Set up a timer to update the object's movement
timer = Forms.Timer()
timer.Interval = 10 # Update every 10 ms
timer.Tick += lambda sender, e: update_movement(obj_id)
timer.Start()
# Show the form normally (not minimized)
form.ShowInTaskbar = True
form.StartPosition = Forms.FormStartPosition.CenterScreen
# Run the form's main loop
form.ShowDialog()
if __name__ == "__main__":
main()
import Rhino
import rhinoscriptsyntax as rs
import System.Windows.Forms as Forms
import math
# Global variables to store the current state
current_angle = 0 # Angle in degrees, 0 means facing "up" (positive Y direction)
move_forward = False
move_backward = False
turn_left = False
turn_right = False
timer = None # Global timer variable
def rotate_object(obj_id, angle):
"""Rotate the object to the given angle."""
# Find the object's centroid or a suitable rotation point
bbox = rs.BoundingBox(obj_id)
centroid = (bbox[0]+bbox[2])/2
# Apply the rotation transformation
rotation = Rhino.Geometry.Transform.Rotation(math.radians(angle), centroid)
rs.TransformObject(obj_id, rotation)
def update_movement(obj_id):
"""Update the object's movement based on the current key states."""
global current_angle
if turn_left:
current_angle += 1 # Turn left
if turn_right:
current_angle -= 1 # Turn right
# Rotate the object to face the current direction
rotate_object(obj_id, current_angle)
def on_key_down(sender, e):
"""Handle key press events."""
global move_forward, move_backward, turn_left, turn_right
if e.KeyCode == Forms.Keys.Left:
turn_left = True
elif e.KeyCode == Forms.Keys.Right:
turn_right = True
def on_key_up(sender, e):
"""Handle key release events."""
global move_forward, move_backward, turn_left, turn_right
if e.KeyCode == Forms.Keys.Left:
turn_left = False
elif e.KeyCode == Forms.Keys.Right:
turn_right = False
def on_form_closing(sender, e):
"""Handle form closing event."""
global timer
if timer:
timer.Stop()
timer.Dispose()
def main():
global obj_id, timer
obj_id = rs.GetObject("Select an object to move")
if not obj_id:
return
# Create a form to capture key events
form = Forms.Form()
form.KeyPreview = True
form.KeyDown += on_key_down
form.KeyUp += on_key_up
form.FormClosing += on_form_closing
# Configure the form to be visible
form.Text = "Car Simulator"
form.Width = 300
form.Height = 100
# Set up a timer to update the object's movement
timer = Forms.Timer()
timer.Interval = 10 # Update every 10 ms
timer.Tick += lambda sender, e: update_movement(obj_id)
timer.Start()
# Show the form normally (not minimized)
form.ShowInTaskbar = True
form.StartPosition = Forms.FormStartPosition.CenterScreen
# Run the form's main loop
form.ShowDialog()
if __name__ == "__main__":
main()
I still need some help as I got this reply from McNeel tech support:
You didn’t still unsubscribe from the KeyDown and KeyUp event…
In any case, I would recommend posting this doubt in our official forum Discourse. You will find another power users who will help you solve your problem.
Kind regards,
So how do I unsubscribe KeyDown and KeyUp?
I thought this was linked to the form and closing the form would solve that by it self.
Any help is greatly appreciated.
I tried updating the definition for closing and please give info on what I need to close, dispose or unsubscribe here. Thanks!
Do I need to put “global” and then variable for all variables here too?
def on_form_closed(sender, e):
"""Handle the form closing event to properly dispose of resources."""
print("closing the form etc")
global timer
if timer:
timer.Stop()
timer.Dispose()
#Forms.Application.ExitThread() # Ensures that the form's thread is terminated
form.Dispose()
form = None
del form
del current_angle, move_forward, move_backward, turn_left, turn_right, trace_points, polyline_id
import Rhino
import rhinoscriptsyntax as rs
import System.Windows.Forms as Forms
import math
# Global variables to store the current state
current_angle = 0 # Angle in degrees, 0 means facing "up" (positive Y direction)
turn_left = False
turn_right = False
def rotate_object(obj_id, angle):
"""Rotate the object to the given angle."""
# Find the object's centroid or a suitable rotation point
bbox = rs.BoundingBox(obj_id)
centroid = (bbox[0] + bbox[2]) / 2
# Apply the rotation transformation
rotation = Rhino.Geometry.Transform.Rotation(math.radians(angle), centroid)
rs.TransformObject(obj_id, rotation)
def update_movement(obj_id):
"""Update the object's movement based on the current key states."""
global current_angle
if turn_left:
current_angle += 1 # Turn left
if turn_right:
current_angle -= 1 # Turn right
# Rotate the object to face the current direction
rotate_object(obj_id, current_angle)
def on_key_down(sender, e):
"""Handle key press events."""
global turn_left, turn_right
if e.KeyCode == Forms.Keys.Left:
turn_left = True
elif e.KeyCode == Forms.Keys.Right:
turn_right = True
def on_key_up(sender, e):
"""Handle key release events."""
global turn_left, turn_right
if e.KeyCode == Forms.Keys.Left:
turn_left = False
elif e.KeyCode == Forms.Keys.Right:
turn_right = False
def on_form_closed(sender, e):
"""Clean up resources when the form is closed."""
timer.Stop() # Stop the timer to prevent further updates
form.KeyDown -= on_key_down # Unsubscribe from events add all events that you use
form.KeyUp -= on_key_up
form.FormClosed -= on_form_closed # Unsubscribe from the form closed event
def main():
global obj_id, form, timer
obj_id = rs.GetObject("Select an object to move")
if not obj_id:
return
# Create a form to capture key events
form = Forms.Form()
form.KeyPreview = True
form.KeyDown += on_key_down
form.KeyUp += on_key_up
# Configure the form to be visible
form.Text = "Car Simulator"
form.Width = 300
form.Height = 100
# Set up a timer to update the object's movement
timer = Forms.Timer()
timer.Interval = 10 # Update every 10 ms
timer.Tick += lambda sender, e: update_movement(obj_id)
timer.Start()
# Handle form closed event
form.FormClosed += on_form_closed
# Show the form normally (not minimized)
form.ShowInTaskbar = True
form.StartPosition = Forms.FormStartPosition.CenterScreen
# Run the form's main loop
form.ShowDialog()
if __name__ == "__main__":
main()
Oh wow… So there really isn’t a “terminate form” function that releases all of the forms resources when the form is closed? No wonder why bugtracking takes so long and why software tends to become slower over time and needs to be restarted…
Thanks for your help, I will test it out.