Refactor 11 more tests to mcrfpy.step() pattern
Converted from Timer-based async to step()-based sync: - test_simple_callback.py - test_empty_animation_manager.py - test_frame_clipping.py - test_frame_clipping_advanced.py - test_grid_children.py - test_color_helpers.py - test_no_arg_constructors.py - test_properties_quick.py - test_simple_drawable.py - test_python_object_cache.py - WORKING_automation_test_example.py Only 4 tests remain with Timer-based patterns (2 are headless detection tests that may require special handling). 🤖 Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Frack <frack@goblincorps.dev> Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
bb86cece2b
commit
be450286f8
12 changed files with 867 additions and 866 deletions
|
|
@ -1,47 +1,11 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Example of CORRECT test pattern using timer callbacks for automation"""
|
||||
"""Example of CORRECT test pattern using mcrfpy.step() for automation
|
||||
Refactored from timer-based approach to synchronous step() pattern.
|
||||
"""
|
||||
import mcrfpy
|
||||
from mcrfpy import automation
|
||||
from datetime import datetime
|
||||
|
||||
def run_automation_tests(timer, runtime):
|
||||
"""This runs AFTER the game loop has started and rendered frames"""
|
||||
print("\n=== Automation Test Running (1 second after start) ===")
|
||||
|
||||
# NOW we can take screenshots that will show content!
|
||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
filename = f"WORKING_screenshot_{timestamp}.png"
|
||||
|
||||
# Take screenshot - this should now show our red frame
|
||||
result = automation.screenshot(filename)
|
||||
print(f"Screenshot taken: {filename} - Result: {result}")
|
||||
|
||||
# Test clicking on the frame
|
||||
automation.click(200, 200) # Click in center of red frame
|
||||
|
||||
# Test keyboard input
|
||||
automation.typewrite("Hello from timer callback!")
|
||||
|
||||
# Take another screenshot to show any changes
|
||||
filename2 = f"WORKING_screenshot_after_click_{timestamp}.png"
|
||||
automation.screenshot(filename2)
|
||||
print(f"Second screenshot: {filename2}")
|
||||
|
||||
print("Test completed successfully!")
|
||||
print("\nThis works because:")
|
||||
print("1. The game loop has been running for 1 second")
|
||||
print("2. The scene has been rendered multiple times")
|
||||
print("3. The RenderTexture now contains actual rendered content")
|
||||
|
||||
# Cancel this timer so it doesn't repeat
|
||||
timer.stop()
|
||||
|
||||
# Optional: exit after a moment
|
||||
def exit_game(t, r):
|
||||
print("Exiting...")
|
||||
mcrfpy.exit()
|
||||
global exit_timer
|
||||
exit_timer = mcrfpy.Timer("exit", exit_game, 500, once=True)
|
||||
import sys
|
||||
|
||||
# This code runs during --exec script execution
|
||||
print("=== Setting Up Test Scene ===")
|
||||
|
|
@ -49,6 +13,8 @@ print("=== Setting Up Test Scene ===")
|
|||
# Create scene with visible content
|
||||
timer_test_scene = mcrfpy.Scene("timer_test_scene")
|
||||
timer_test_scene.activate()
|
||||
mcrfpy.step(0.01) # Initialize scene
|
||||
|
||||
ui = timer_test_scene.children
|
||||
|
||||
# Add a bright red frame that should be visible
|
||||
|
|
@ -60,23 +26,57 @@ ui.append(frame)
|
|||
|
||||
# Add text
|
||||
caption = mcrfpy.Caption(pos=(150, 150),
|
||||
text="TIMER TEST - SHOULD BE VISIBLE",
|
||||
text="STEP TEST - SHOULD BE VISIBLE",
|
||||
fill_color=mcrfpy.Color(255, 255, 255))
|
||||
caption.font_size = 24
|
||||
frame.children.append(caption)
|
||||
|
||||
# Add click handler to demonstrate interaction
|
||||
click_received = False
|
||||
def frame_clicked(x, y, button):
|
||||
global click_received
|
||||
click_received = True
|
||||
print(f"Frame clicked at ({x}, {y}) with button {button}")
|
||||
|
||||
frame.on_click = frame_clicked
|
||||
|
||||
print("Scene setup complete. Setting timer for automation tests...")
|
||||
print("Scene setup complete.")
|
||||
|
||||
# THIS IS THE KEY: Set timer to run AFTER the game loop starts
|
||||
automation_test_timer = mcrfpy.Timer("automation_test", run_automation_tests, 1000, once=True)
|
||||
# Step to render the scene
|
||||
mcrfpy.step(0.1)
|
||||
|
||||
print("Timer set. Game loop will start after this script completes.")
|
||||
print("Automation tests will run 1 second later when content is visible.")
|
||||
print("\n=== Automation Test Running ===")
|
||||
|
||||
# Script ends here - game loop starts next
|
||||
# NOW we can take screenshots that will show content!
|
||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
filename = f"WORKING_screenshot_{timestamp}.png"
|
||||
|
||||
# Take screenshot - this should now show our red frame
|
||||
result = automation.screenshot(filename)
|
||||
print(f"Screenshot taken: {filename} - Result: {result}")
|
||||
|
||||
# Test clicking on the frame
|
||||
automation.click(200, 200) # Click in center of red frame
|
||||
|
||||
# Step to process the click
|
||||
mcrfpy.step(0.1)
|
||||
|
||||
# Test keyboard input
|
||||
automation.typewrite("Hello from step-based test!")
|
||||
|
||||
# Step to process keyboard input
|
||||
mcrfpy.step(0.1)
|
||||
|
||||
# Take another screenshot to show any changes
|
||||
filename2 = f"WORKING_screenshot_after_click_{timestamp}.png"
|
||||
automation.screenshot(filename2)
|
||||
print(f"Second screenshot: {filename2}")
|
||||
|
||||
print("Test completed successfully!")
|
||||
print("\nThis works because:")
|
||||
print("1. mcrfpy.step() advances simulation synchronously")
|
||||
print("2. The scene renders during step() calls")
|
||||
print("3. The RenderTexture contains actual rendered content")
|
||||
|
||||
print("PASS")
|
||||
sys.exit(0)
|
||||
|
|
|
|||
|
|
@ -1,182 +1,181 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test #94: Color helper methods - from_hex, to_hex, lerp
|
||||
Refactored to use mcrfpy.step() for synchronous execution.
|
||||
"""
|
||||
|
||||
import mcrfpy
|
||||
import sys
|
||||
|
||||
def test_color_helpers(timer, runtime):
|
||||
"""Test Color helper methods"""
|
||||
|
||||
all_pass = True
|
||||
|
||||
# Test 1: from_hex with # prefix
|
||||
try:
|
||||
c1 = mcrfpy.Color.from_hex("#FF0000")
|
||||
assert c1.r == 255 and c1.g == 0 and c1.b == 0 and c1.a == 255, f"from_hex('#FF0000') failed: {c1}"
|
||||
print("+ Color.from_hex('#FF0000') works")
|
||||
except Exception as e:
|
||||
print(f"x Color.from_hex('#FF0000') failed: {e}")
|
||||
all_pass = False
|
||||
|
||||
# Test 2: from_hex without # prefix
|
||||
try:
|
||||
c2 = mcrfpy.Color.from_hex("00FF00")
|
||||
assert c2.r == 0 and c2.g == 255 and c2.b == 0 and c2.a == 255, f"from_hex('00FF00') failed: {c2}"
|
||||
print("+ Color.from_hex('00FF00') works")
|
||||
except Exception as e:
|
||||
print(f"x Color.from_hex('00FF00') failed: {e}")
|
||||
all_pass = False
|
||||
|
||||
# Test 3: from_hex with alpha
|
||||
try:
|
||||
c3 = mcrfpy.Color.from_hex("#0000FF80")
|
||||
assert c3.r == 0 and c3.g == 0 and c3.b == 255 and c3.a == 128, f"from_hex('#0000FF80') failed: {c3}"
|
||||
print("+ Color.from_hex('#0000FF80') with alpha works")
|
||||
except Exception as e:
|
||||
print(f"x Color.from_hex('#0000FF80') failed: {e}")
|
||||
all_pass = False
|
||||
|
||||
# Test 4: from_hex error handling
|
||||
try:
|
||||
c4 = mcrfpy.Color.from_hex("GGGGGG")
|
||||
print("x from_hex should fail on invalid hex")
|
||||
all_pass = False
|
||||
except ValueError as e:
|
||||
print("+ Color.from_hex() correctly rejects invalid hex")
|
||||
|
||||
# Test 5: from_hex wrong length
|
||||
try:
|
||||
c5 = mcrfpy.Color.from_hex("FF00")
|
||||
print("x from_hex should fail on wrong length")
|
||||
all_pass = False
|
||||
except ValueError as e:
|
||||
print("+ Color.from_hex() correctly rejects wrong length")
|
||||
|
||||
# Test 6: to_hex without alpha
|
||||
try:
|
||||
c6 = mcrfpy.Color(255, 128, 64)
|
||||
hex_str = c6.to_hex()
|
||||
assert hex_str == "#FF8040", f"to_hex() failed: {hex_str}"
|
||||
print("+ Color.to_hex() works")
|
||||
except Exception as e:
|
||||
print(f"x Color.to_hex() failed: {e}")
|
||||
all_pass = False
|
||||
|
||||
# Test 7: to_hex with alpha
|
||||
try:
|
||||
c7 = mcrfpy.Color(255, 128, 64, 127)
|
||||
hex_str = c7.to_hex()
|
||||
assert hex_str == "#FF80407F", f"to_hex() with alpha failed: {hex_str}"
|
||||
print("+ Color.to_hex() with alpha works")
|
||||
except Exception as e:
|
||||
print(f"x Color.to_hex() with alpha failed: {e}")
|
||||
all_pass = False
|
||||
|
||||
# Test 8: Round-trip hex conversion
|
||||
try:
|
||||
original_hex = "#ABCDEF"
|
||||
c8 = mcrfpy.Color.from_hex(original_hex)
|
||||
result_hex = c8.to_hex()
|
||||
assert result_hex == original_hex, f"Round-trip failed: {original_hex} -> {result_hex}"
|
||||
print("+ Hex round-trip conversion works")
|
||||
except Exception as e:
|
||||
print(f"x Hex round-trip failed: {e}")
|
||||
all_pass = False
|
||||
|
||||
# Test 9: lerp at t=0
|
||||
try:
|
||||
red = mcrfpy.Color(255, 0, 0)
|
||||
blue = mcrfpy.Color(0, 0, 255)
|
||||
result = red.lerp(blue, 0.0)
|
||||
assert result.r == 255 and result.g == 0 and result.b == 0, f"lerp(t=0) failed: {result}"
|
||||
print("+ Color.lerp(t=0) returns start color")
|
||||
except Exception as e:
|
||||
print(f"x Color.lerp(t=0) failed: {e}")
|
||||
all_pass = False
|
||||
|
||||
# Test 10: lerp at t=1
|
||||
try:
|
||||
red = mcrfpy.Color(255, 0, 0)
|
||||
blue = mcrfpy.Color(0, 0, 255)
|
||||
result = red.lerp(blue, 1.0)
|
||||
assert result.r == 0 and result.g == 0 and result.b == 255, f"lerp(t=1) failed: {result}"
|
||||
print("+ Color.lerp(t=1) returns end color")
|
||||
except Exception as e:
|
||||
print(f"x Color.lerp(t=1) failed: {e}")
|
||||
all_pass = False
|
||||
|
||||
# Test 11: lerp at t=0.5
|
||||
try:
|
||||
red = mcrfpy.Color(255, 0, 0)
|
||||
blue = mcrfpy.Color(0, 0, 255)
|
||||
result = red.lerp(blue, 0.5)
|
||||
# Expect roughly (127, 0, 127)
|
||||
assert 126 <= result.r <= 128 and result.g == 0 and 126 <= result.b <= 128, f"lerp(t=0.5) failed: {result}"
|
||||
print("+ Color.lerp(t=0.5) returns midpoint")
|
||||
except Exception as e:
|
||||
print(f"x Color.lerp(t=0.5) failed: {e}")
|
||||
all_pass = False
|
||||
|
||||
# Test 12: lerp with alpha
|
||||
try:
|
||||
c1 = mcrfpy.Color(255, 0, 0, 255)
|
||||
c2 = mcrfpy.Color(0, 255, 0, 0)
|
||||
result = c1.lerp(c2, 0.5)
|
||||
assert 126 <= result.r <= 128 and 126 <= result.g <= 128 and result.b == 0, f"lerp color components failed"
|
||||
assert 126 <= result.a <= 128, f"lerp alpha failed: {result.a}"
|
||||
print("+ Color.lerp() with alpha works")
|
||||
except Exception as e:
|
||||
print(f"x Color.lerp() with alpha failed: {e}")
|
||||
all_pass = False
|
||||
|
||||
# Test 13: lerp clamps t < 0
|
||||
try:
|
||||
red = mcrfpy.Color(255, 0, 0)
|
||||
blue = mcrfpy.Color(0, 0, 255)
|
||||
result = red.lerp(blue, -0.5)
|
||||
assert result.r == 255 and result.g == 0 and result.b == 0, f"lerp(t<0) should clamp to 0"
|
||||
print("+ Color.lerp() clamps t < 0")
|
||||
except Exception as e:
|
||||
print(f"x Color.lerp(t<0) failed: {e}")
|
||||
all_pass = False
|
||||
|
||||
# Test 14: lerp clamps t > 1
|
||||
try:
|
||||
red = mcrfpy.Color(255, 0, 0)
|
||||
blue = mcrfpy.Color(0, 0, 255)
|
||||
result = red.lerp(blue, 1.5)
|
||||
assert result.r == 0 and result.g == 0 and result.b == 255, f"lerp(t>1) should clamp to 1"
|
||||
print("+ Color.lerp() clamps t > 1")
|
||||
except Exception as e:
|
||||
print(f"x Color.lerp(t>1) failed: {e}")
|
||||
all_pass = False
|
||||
|
||||
# Test 15: Practical use case - gradient
|
||||
try:
|
||||
start = mcrfpy.Color.from_hex("#FF0000") # Red
|
||||
end = mcrfpy.Color.from_hex("#0000FF") # Blue
|
||||
|
||||
# Create 5-step gradient
|
||||
steps = []
|
||||
for i in range(5):
|
||||
t = i / 4.0
|
||||
color = start.lerp(end, t)
|
||||
steps.append(color.to_hex())
|
||||
|
||||
assert steps[0] == "#FF0000", "Gradient start should be red"
|
||||
assert steps[4] == "#0000FF", "Gradient end should be blue"
|
||||
assert len(set(steps)) == 5, "All gradient steps should be unique"
|
||||
|
||||
print("+ Gradient generation works correctly")
|
||||
except Exception as e:
|
||||
print(f"x Gradient generation failed: {e}")
|
||||
all_pass = False
|
||||
|
||||
print(f"\n{'PASS' if all_pass else 'FAIL'}")
|
||||
sys.exit(0 if all_pass else 1)
|
||||
|
||||
# Run test
|
||||
# Initialize scene
|
||||
test = mcrfpy.Scene("test")
|
||||
test_timer = mcrfpy.Timer("test", test_color_helpers, 100, once=True)
|
||||
test.activate()
|
||||
mcrfpy.step(0.01)
|
||||
|
||||
all_pass = True
|
||||
|
||||
# Test 1: from_hex with # prefix
|
||||
try:
|
||||
c1 = mcrfpy.Color.from_hex("#FF0000")
|
||||
assert c1.r == 255 and c1.g == 0 and c1.b == 0 and c1.a == 255, f"from_hex('#FF0000') failed: {c1}"
|
||||
print("+ Color.from_hex('#FF0000') works")
|
||||
except Exception as e:
|
||||
print(f"x Color.from_hex('#FF0000') failed: {e}")
|
||||
all_pass = False
|
||||
|
||||
# Test 2: from_hex without # prefix
|
||||
try:
|
||||
c2 = mcrfpy.Color.from_hex("00FF00")
|
||||
assert c2.r == 0 and c2.g == 255 and c2.b == 0 and c2.a == 255, f"from_hex('00FF00') failed: {c2}"
|
||||
print("+ Color.from_hex('00FF00') works")
|
||||
except Exception as e:
|
||||
print(f"x Color.from_hex('00FF00') failed: {e}")
|
||||
all_pass = False
|
||||
|
||||
# Test 3: from_hex with alpha
|
||||
try:
|
||||
c3 = mcrfpy.Color.from_hex("#0000FF80")
|
||||
assert c3.r == 0 and c3.g == 0 and c3.b == 255 and c3.a == 128, f"from_hex('#0000FF80') failed: {c3}"
|
||||
print("+ Color.from_hex('#0000FF80') with alpha works")
|
||||
except Exception as e:
|
||||
print(f"x Color.from_hex('#0000FF80') failed: {e}")
|
||||
all_pass = False
|
||||
|
||||
# Test 4: from_hex error handling
|
||||
try:
|
||||
c4 = mcrfpy.Color.from_hex("GGGGGG")
|
||||
print("x from_hex should fail on invalid hex")
|
||||
all_pass = False
|
||||
except ValueError as e:
|
||||
print("+ Color.from_hex() correctly rejects invalid hex")
|
||||
|
||||
# Test 5: from_hex wrong length
|
||||
try:
|
||||
c5 = mcrfpy.Color.from_hex("FF00")
|
||||
print("x from_hex should fail on wrong length")
|
||||
all_pass = False
|
||||
except ValueError as e:
|
||||
print("+ Color.from_hex() correctly rejects wrong length")
|
||||
|
||||
# Test 6: to_hex without alpha
|
||||
try:
|
||||
c6 = mcrfpy.Color(255, 128, 64)
|
||||
hex_str = c6.to_hex()
|
||||
assert hex_str == "#FF8040", f"to_hex() failed: {hex_str}"
|
||||
print("+ Color.to_hex() works")
|
||||
except Exception as e:
|
||||
print(f"x Color.to_hex() failed: {e}")
|
||||
all_pass = False
|
||||
|
||||
# Test 7: to_hex with alpha
|
||||
try:
|
||||
c7 = mcrfpy.Color(255, 128, 64, 127)
|
||||
hex_str = c7.to_hex()
|
||||
assert hex_str == "#FF80407F", f"to_hex() with alpha failed: {hex_str}"
|
||||
print("+ Color.to_hex() with alpha works")
|
||||
except Exception as e:
|
||||
print(f"x Color.to_hex() with alpha failed: {e}")
|
||||
all_pass = False
|
||||
|
||||
# Test 8: Round-trip hex conversion
|
||||
try:
|
||||
original_hex = "#ABCDEF"
|
||||
c8 = mcrfpy.Color.from_hex(original_hex)
|
||||
result_hex = c8.to_hex()
|
||||
assert result_hex == original_hex, f"Round-trip failed: {original_hex} -> {result_hex}"
|
||||
print("+ Hex round-trip conversion works")
|
||||
except Exception as e:
|
||||
print(f"x Hex round-trip failed: {e}")
|
||||
all_pass = False
|
||||
|
||||
# Test 9: lerp at t=0
|
||||
try:
|
||||
red = mcrfpy.Color(255, 0, 0)
|
||||
blue = mcrfpy.Color(0, 0, 255)
|
||||
result = red.lerp(blue, 0.0)
|
||||
assert result.r == 255 and result.g == 0 and result.b == 0, f"lerp(t=0) failed: {result}"
|
||||
print("+ Color.lerp(t=0) returns start color")
|
||||
except Exception as e:
|
||||
print(f"x Color.lerp(t=0) failed: {e}")
|
||||
all_pass = False
|
||||
|
||||
# Test 10: lerp at t=1
|
||||
try:
|
||||
red = mcrfpy.Color(255, 0, 0)
|
||||
blue = mcrfpy.Color(0, 0, 255)
|
||||
result = red.lerp(blue, 1.0)
|
||||
assert result.r == 0 and result.g == 0 and result.b == 255, f"lerp(t=1) failed: {result}"
|
||||
print("+ Color.lerp(t=1) returns end color")
|
||||
except Exception as e:
|
||||
print(f"x Color.lerp(t=1) failed: {e}")
|
||||
all_pass = False
|
||||
|
||||
# Test 11: lerp at t=0.5
|
||||
try:
|
||||
red = mcrfpy.Color(255, 0, 0)
|
||||
blue = mcrfpy.Color(0, 0, 255)
|
||||
result = red.lerp(blue, 0.5)
|
||||
# Expect roughly (127, 0, 127)
|
||||
assert 126 <= result.r <= 128 and result.g == 0 and 126 <= result.b <= 128, f"lerp(t=0.5) failed: {result}"
|
||||
print("+ Color.lerp(t=0.5) returns midpoint")
|
||||
except Exception as e:
|
||||
print(f"x Color.lerp(t=0.5) failed: {e}")
|
||||
all_pass = False
|
||||
|
||||
# Test 12: lerp with alpha
|
||||
try:
|
||||
c1 = mcrfpy.Color(255, 0, 0, 255)
|
||||
c2 = mcrfpy.Color(0, 255, 0, 0)
|
||||
result = c1.lerp(c2, 0.5)
|
||||
assert 126 <= result.r <= 128 and 126 <= result.g <= 128 and result.b == 0, f"lerp color components failed"
|
||||
assert 126 <= result.a <= 128, f"lerp alpha failed: {result.a}"
|
||||
print("+ Color.lerp() with alpha works")
|
||||
except Exception as e:
|
||||
print(f"x Color.lerp() with alpha failed: {e}")
|
||||
all_pass = False
|
||||
|
||||
# Test 13: lerp clamps t < 0
|
||||
try:
|
||||
red = mcrfpy.Color(255, 0, 0)
|
||||
blue = mcrfpy.Color(0, 0, 255)
|
||||
result = red.lerp(blue, -0.5)
|
||||
assert result.r == 255 and result.g == 0 and result.b == 0, f"lerp(t<0) should clamp to 0"
|
||||
print("+ Color.lerp() clamps t < 0")
|
||||
except Exception as e:
|
||||
print(f"x Color.lerp(t<0) failed: {e}")
|
||||
all_pass = False
|
||||
|
||||
# Test 14: lerp clamps t > 1
|
||||
try:
|
||||
red = mcrfpy.Color(255, 0, 0)
|
||||
blue = mcrfpy.Color(0, 0, 255)
|
||||
result = red.lerp(blue, 1.5)
|
||||
assert result.r == 0 and result.g == 0 and result.b == 255, f"lerp(t>1) should clamp to 1"
|
||||
print("+ Color.lerp() clamps t > 1")
|
||||
except Exception as e:
|
||||
print(f"x Color.lerp(t>1) failed: {e}")
|
||||
all_pass = False
|
||||
|
||||
# Test 15: Practical use case - gradient
|
||||
try:
|
||||
start = mcrfpy.Color.from_hex("#FF0000") # Red
|
||||
end = mcrfpy.Color.from_hex("#0000FF") # Blue
|
||||
|
||||
# Create 5-step gradient
|
||||
steps = []
|
||||
for i in range(5):
|
||||
t = i / 4.0
|
||||
color = start.lerp(end, t)
|
||||
steps.append(color.to_hex())
|
||||
|
||||
assert steps[0] == "#FF0000", "Gradient start should be red"
|
||||
assert steps[4] == "#0000FF", "Gradient end should be blue"
|
||||
assert len(set(steps)) == 5, "All gradient steps should be unique"
|
||||
|
||||
print("+ Gradient generation works correctly")
|
||||
except Exception as e:
|
||||
print(f"x Gradient generation failed: {e}")
|
||||
all_pass = False
|
||||
|
||||
print(f"\n{'PASS' if all_pass else 'FAIL'}")
|
||||
sys.exit(0 if all_pass else 1)
|
||||
|
|
|
|||
|
|
@ -1,20 +1,28 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test if AnimationManager crashes with no animations
|
||||
Refactored to use mcrfpy.step() for synchronous execution.
|
||||
"""
|
||||
|
||||
import mcrfpy
|
||||
import sys
|
||||
|
||||
print("Creating empty scene...")
|
||||
test = mcrfpy.Scene("test")
|
||||
test.activate()
|
||||
|
||||
print("Scene created, no animations added")
|
||||
print("Starting game loop in 100ms...")
|
||||
print("Advancing simulation with step()...")
|
||||
|
||||
def check_alive(timer, runtime):
|
||||
print(f"Timer fired at {runtime}ms - AnimationManager survived!")
|
||||
mcrfpy.Timer("exit", lambda t, r: mcrfpy.exit(), 100, once=True)
|
||||
# Step multiple times to simulate game loop running
|
||||
# If AnimationManager crashes with empty state, this will fail
|
||||
try:
|
||||
for i in range(10):
|
||||
mcrfpy.step(0.1) # 10 steps of 0.1s = 1 second simulated
|
||||
|
||||
mcrfpy.Timer("check", check_alive, 1000, once=True)
|
||||
print("If this crashes immediately, AnimationManager has an issue with empty state")
|
||||
print("AnimationManager survived 10 steps with no animations!")
|
||||
print("PASS")
|
||||
sys.exit(0)
|
||||
except Exception as e:
|
||||
print(f"FAIL: AnimationManager crashed: {e}")
|
||||
sys.exit(1)
|
||||
|
|
|
|||
|
|
@ -1,135 +1,118 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Test UIFrame clipping functionality"""
|
||||
"""Test UIFrame clipping functionality
|
||||
Refactored to use mcrfpy.step() for synchronous execution.
|
||||
"""
|
||||
|
||||
import mcrfpy
|
||||
from mcrfpy import Color, Frame, Caption
|
||||
from mcrfpy import Color, Frame, Caption, automation
|
||||
import sys
|
||||
|
||||
# Module-level state to avoid closures
|
||||
_test_state = {}
|
||||
|
||||
def take_second_screenshot(timer, runtime):
|
||||
"""Take final screenshot and exit"""
|
||||
timer.stop()
|
||||
from mcrfpy import automation
|
||||
automation.screenshot("frame_clipping_animated.png")
|
||||
print("\nTest completed successfully!")
|
||||
print("Screenshots saved:")
|
||||
print(" - frame_clipping_test.png (initial state)")
|
||||
print(" - frame_clipping_animated.png (with animation)")
|
||||
sys.exit(0)
|
||||
|
||||
def animate_frames(timer, runtime):
|
||||
"""Animate frames to demonstrate clipping"""
|
||||
timer.stop()
|
||||
scene = test.children
|
||||
# Move child frames
|
||||
parent1 = scene[0]
|
||||
parent2 = scene[1]
|
||||
parent1.children[1].x = 50
|
||||
parent2.children[1].x = 50
|
||||
global screenshot2_timer
|
||||
screenshot2_timer = mcrfpy.Timer("screenshot2", take_second_screenshot, 500, once=True)
|
||||
|
||||
def test_clipping(timer, runtime):
|
||||
"""Test that clip_children property works correctly"""
|
||||
timer.stop()
|
||||
|
||||
print("Testing UIFrame clipping functionality...")
|
||||
|
||||
scene = test.children
|
||||
|
||||
# Create parent frame with clipping disabled (default)
|
||||
parent1 = Frame(pos=(50, 50), size=(200, 150),
|
||||
fill_color=Color(100, 100, 200),
|
||||
outline_color=Color(255, 255, 255),
|
||||
outline=2)
|
||||
parent1.name = "parent1"
|
||||
scene.append(parent1)
|
||||
|
||||
# Create parent frame with clipping enabled
|
||||
parent2 = Frame(pos=(300, 50), size=(200, 150),
|
||||
fill_color=Color(200, 100, 100),
|
||||
outline_color=Color(255, 255, 255),
|
||||
outline=2)
|
||||
parent2.name = "parent2"
|
||||
parent2.clip_children = True
|
||||
scene.append(parent2)
|
||||
|
||||
# Add captions to both frames
|
||||
caption1 = Caption(text="This text should overflow the frame bounds", pos=(10, 10))
|
||||
caption1.font_size = 16
|
||||
caption1.fill_color = Color(255, 255, 255)
|
||||
parent1.children.append(caption1)
|
||||
|
||||
caption2 = Caption(text="This text should be clipped to frame bounds", pos=(10, 10))
|
||||
caption2.font_size = 16
|
||||
caption2.fill_color = Color(255, 255, 255)
|
||||
parent2.children.append(caption2)
|
||||
|
||||
# Add child frames that extend beyond parent bounds
|
||||
child1 = Frame(pos=(150, 100), size=(100, 100),
|
||||
fill_color=Color(50, 255, 50),
|
||||
outline_color=Color(0, 0, 0),
|
||||
outline=1)
|
||||
parent1.children.append(child1)
|
||||
|
||||
child2 = Frame(pos=(150, 100), size=(100, 100),
|
||||
fill_color=Color(50, 255, 50),
|
||||
outline_color=Color(0, 0, 0),
|
||||
outline=1)
|
||||
parent2.children.append(child2)
|
||||
|
||||
# Add caption to show clip state
|
||||
status = Caption(text=f"Left frame: clip_children={parent1.clip_children}\n"
|
||||
f"Right frame: clip_children={parent2.clip_children}",
|
||||
pos=(50, 250))
|
||||
status.font_size = 14
|
||||
status.fill_color = Color(255, 255, 255)
|
||||
scene.append(status)
|
||||
|
||||
# Add instructions
|
||||
instructions = Caption(text="Left: Children should overflow (no clipping)\n"
|
||||
"Right: Children should be clipped to frame bounds\n"
|
||||
"Press 'c' to toggle clipping on left frame",
|
||||
pos=(50, 300))
|
||||
instructions.font_size = 12
|
||||
instructions.fill_color = Color(200, 200, 200)
|
||||
scene.append(instructions)
|
||||
|
||||
# Take screenshot
|
||||
from mcrfpy import automation
|
||||
automation.screenshot("frame_clipping_test.png")
|
||||
|
||||
print(f"Parent1 clip_children: {parent1.clip_children}")
|
||||
print(f"Parent2 clip_children: {parent2.clip_children}")
|
||||
|
||||
# Test toggling clip_children
|
||||
parent1.clip_children = True
|
||||
print(f"After toggle - Parent1 clip_children: {parent1.clip_children}")
|
||||
|
||||
# Verify the property setter works
|
||||
try:
|
||||
parent1.clip_children = "not a bool"
|
||||
print("ERROR: clip_children accepted non-boolean value")
|
||||
except TypeError as e:
|
||||
print(f"PASS: clip_children correctly rejected non-boolean: {e}")
|
||||
|
||||
# Start animation after a short delay
|
||||
global animate_timer
|
||||
animate_timer = mcrfpy.Timer("animate", animate_frames, 100, once=True)
|
||||
|
||||
def handle_keypress(key, modifiers):
|
||||
if key == "c":
|
||||
scene = test.children
|
||||
parent1 = scene[0]
|
||||
parent1.clip_children = not parent1.clip_children
|
||||
print(f"Toggled parent1 clip_children to: {parent1.clip_children}")
|
||||
|
||||
# Main execution
|
||||
print("Creating test scene...")
|
||||
test = mcrfpy.Scene("test")
|
||||
test.activate()
|
||||
test.on_key = handle_keypress
|
||||
test_clipping_timer = mcrfpy.Timer("test_clipping", test_clipping, 100, once=True)
|
||||
print("Test scheduled, running...")
|
||||
mcrfpy.step(0.01) # Initialize
|
||||
|
||||
print("Testing UIFrame clipping functionality...")
|
||||
|
||||
scene = test.children
|
||||
|
||||
# Create parent frame with clipping disabled (default)
|
||||
parent1 = Frame(pos=(50, 50), size=(200, 150),
|
||||
fill_color=Color(100, 100, 200),
|
||||
outline_color=Color(255, 255, 255),
|
||||
outline=2)
|
||||
parent1.name = "parent1"
|
||||
scene.append(parent1)
|
||||
|
||||
# Create parent frame with clipping enabled
|
||||
parent2 = Frame(pos=(300, 50), size=(200, 150),
|
||||
fill_color=Color(200, 100, 100),
|
||||
outline_color=Color(255, 255, 255),
|
||||
outline=2)
|
||||
parent2.name = "parent2"
|
||||
parent2.clip_children = True
|
||||
scene.append(parent2)
|
||||
|
||||
# Add captions to both frames
|
||||
caption1 = Caption(text="This text should overflow the frame bounds", pos=(10, 10))
|
||||
caption1.font_size = 16
|
||||
caption1.fill_color = Color(255, 255, 255)
|
||||
parent1.children.append(caption1)
|
||||
|
||||
caption2 = Caption(text="This text should be clipped to frame bounds", pos=(10, 10))
|
||||
caption2.font_size = 16
|
||||
caption2.fill_color = Color(255, 255, 255)
|
||||
parent2.children.append(caption2)
|
||||
|
||||
# Add child frames that extend beyond parent bounds
|
||||
child1 = Frame(pos=(150, 100), size=(100, 100),
|
||||
fill_color=Color(50, 255, 50),
|
||||
outline_color=Color(0, 0, 0),
|
||||
outline=1)
|
||||
parent1.children.append(child1)
|
||||
|
||||
child2 = Frame(pos=(150, 100), size=(100, 100),
|
||||
fill_color=Color(50, 255, 50),
|
||||
outline_color=Color(0, 0, 0),
|
||||
outline=1)
|
||||
parent2.children.append(child2)
|
||||
|
||||
# Add caption to show clip state
|
||||
status = Caption(text=f"Left frame: clip_children={parent1.clip_children}\n"
|
||||
f"Right frame: clip_children={parent2.clip_children}",
|
||||
pos=(50, 250))
|
||||
status.font_size = 14
|
||||
status.fill_color = Color(255, 255, 255)
|
||||
scene.append(status)
|
||||
|
||||
# Add instructions
|
||||
instructions = Caption(text="Left: Children should overflow (no clipping)\n"
|
||||
"Right: Children should be clipped to frame bounds",
|
||||
pos=(50, 300))
|
||||
instructions.font_size = 12
|
||||
instructions.fill_color = Color(200, 200, 200)
|
||||
scene.append(instructions)
|
||||
|
||||
# Step to render
|
||||
mcrfpy.step(0.1)
|
||||
|
||||
# Take screenshot
|
||||
automation.screenshot("frame_clipping_test.png")
|
||||
|
||||
print(f"Parent1 clip_children: {parent1.clip_children}")
|
||||
print(f"Parent2 clip_children: {parent2.clip_children}")
|
||||
|
||||
# Test toggling clip_children
|
||||
parent1.clip_children = True
|
||||
print(f"After toggle - Parent1 clip_children: {parent1.clip_children}")
|
||||
|
||||
# Verify the property setter works
|
||||
test_passed = True
|
||||
try:
|
||||
parent1.clip_children = "not a bool"
|
||||
print("ERROR: clip_children accepted non-boolean value")
|
||||
test_passed = False
|
||||
except TypeError as e:
|
||||
print(f"PASS: clip_children correctly rejected non-boolean: {e}")
|
||||
|
||||
# Animate frames (move children)
|
||||
parent1.children[1].x = 50
|
||||
parent2.children[1].x = 50
|
||||
|
||||
# Step to render animation
|
||||
mcrfpy.step(0.1)
|
||||
|
||||
# Take second screenshot
|
||||
automation.screenshot("frame_clipping_animated.png")
|
||||
|
||||
print("\nTest completed successfully!")
|
||||
print("Screenshots saved:")
|
||||
print(" - frame_clipping_test.png (initial state)")
|
||||
print(" - frame_clipping_animated.png (with animation)")
|
||||
|
||||
if test_passed:
|
||||
print("PASS")
|
||||
sys.exit(0)
|
||||
else:
|
||||
print("FAIL")
|
||||
sys.exit(1)
|
||||
|
|
|
|||
|
|
@ -1,105 +1,95 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Advanced test for UIFrame clipping with nested frames"""
|
||||
"""Advanced test for UIFrame clipping with nested frames
|
||||
Refactored to use mcrfpy.step() for synchronous execution.
|
||||
"""
|
||||
|
||||
import mcrfpy
|
||||
from mcrfpy import Color, Frame, Caption, Vector
|
||||
from mcrfpy import Color, Frame, Caption, Vector, automation
|
||||
import sys
|
||||
|
||||
def test_nested_clipping(timer, runtime):
|
||||
"""Test nested frames with clipping"""
|
||||
timer.stop()
|
||||
|
||||
print("Testing advanced UIFrame clipping with nested frames...")
|
||||
|
||||
# Create test scene
|
||||
scene = test.children
|
||||
|
||||
# Create outer frame with clipping enabled
|
||||
outer = Frame(pos=(50, 50), size=(400, 300),
|
||||
fill_color=Color(50, 50, 150),
|
||||
outline_color=Color(255, 255, 255),
|
||||
outline=3)
|
||||
outer.name = "outer"
|
||||
outer.clip_children = True
|
||||
scene.append(outer)
|
||||
|
||||
# Create inner frame that extends beyond outer bounds
|
||||
inner = Frame(pos=(200, 150), size=(300, 200),
|
||||
fill_color=Color(150, 50, 50),
|
||||
outline_color=Color(255, 255, 0),
|
||||
outline=2)
|
||||
inner.name = "inner"
|
||||
inner.clip_children = True # Also enable clipping on inner frame
|
||||
outer.children.append(inner)
|
||||
|
||||
# Add content to inner frame that extends beyond its bounds
|
||||
for i in range(5):
|
||||
caption = Caption(text=f"Line {i+1}: This text should be double-clipped", pos=(10, 30 * i))
|
||||
caption.font_size = 14
|
||||
caption.fill_color = Color(255, 255, 255)
|
||||
inner.children.append(caption)
|
||||
|
||||
# Add a child frame to inner that extends way out
|
||||
deeply_nested = Frame(pos=(250, 100), size=(200, 150),
|
||||
fill_color=Color(50, 150, 50),
|
||||
outline_color=Color(255, 0, 255),
|
||||
outline=2)
|
||||
deeply_nested.name = "deeply_nested"
|
||||
inner.children.append(deeply_nested)
|
||||
|
||||
# Add status text
|
||||
status = Caption(text="Nested clipping test:\n"
|
||||
"- Blue outer frame clips red inner frame\n"
|
||||
"- Red inner frame clips green deeply nested frame\n"
|
||||
"- All text should be clipped to frame bounds",
|
||||
pos=(50, 380))
|
||||
status.font_size = 12
|
||||
status.fill_color = Color(200, 200, 200)
|
||||
scene.append(status)
|
||||
|
||||
# Test render texture size handling
|
||||
print(f"Outer frame size: {outer.w}x{outer.h}")
|
||||
print(f"Inner frame size: {inner.w}x{inner.h}")
|
||||
|
||||
# Dynamically resize frames to test RenderTexture recreation
|
||||
def resize_test(timer, runtime):
|
||||
timer.stop()
|
||||
print("Resizing frames to test RenderTexture recreation...")
|
||||
outer.w = 450
|
||||
outer.h = 350
|
||||
inner.w = 350
|
||||
inner.h = 250
|
||||
print(f"New outer frame size: {outer.w}x{outer.h}")
|
||||
print(f"New inner frame size: {inner.w}x{inner.h}")
|
||||
|
||||
# Take screenshot after resize
|
||||
global screenshot_resize_timer
|
||||
screenshot_resize_timer = mcrfpy.Timer("screenshot_resize", take_resize_screenshot, 500, once=True)
|
||||
|
||||
def take_resize_screenshot(timer, runtime):
|
||||
timer.stop()
|
||||
from mcrfpy import automation
|
||||
automation.screenshot("frame_clipping_resized.png")
|
||||
print("\nAdvanced test completed!")
|
||||
print("Screenshots saved:")
|
||||
print(" - frame_clipping_resized.png (after resize)")
|
||||
sys.exit(0)
|
||||
|
||||
# Take initial screenshot
|
||||
from mcrfpy import automation
|
||||
automation.screenshot("frame_clipping_nested.png")
|
||||
print("Initial screenshot saved: frame_clipping_nested.png")
|
||||
|
||||
# Schedule resize test
|
||||
global resize_test_timer
|
||||
resize_test_timer = mcrfpy.Timer("resize_test", resize_test, 1000, once=True)
|
||||
|
||||
# Main execution
|
||||
print("Creating advanced test scene...")
|
||||
test = mcrfpy.Scene("test")
|
||||
test.activate()
|
||||
mcrfpy.step(0.01)
|
||||
|
||||
# Schedule the test
|
||||
test_nested_clipping_timer = mcrfpy.Timer("test_nested_clipping", test_nested_clipping, 100, once=True)
|
||||
print("Testing advanced UIFrame clipping with nested frames...")
|
||||
|
||||
print("Advanced test scheduled, running...")
|
||||
# Create test scene
|
||||
scene = test.children
|
||||
|
||||
# Create outer frame with clipping enabled
|
||||
outer = Frame(pos=(50, 50), size=(400, 300),
|
||||
fill_color=Color(50, 50, 150),
|
||||
outline_color=Color(255, 255, 255),
|
||||
outline=3)
|
||||
outer.name = "outer"
|
||||
outer.clip_children = True
|
||||
scene.append(outer)
|
||||
|
||||
# Create inner frame that extends beyond outer bounds
|
||||
inner = Frame(pos=(200, 150), size=(300, 200),
|
||||
fill_color=Color(150, 50, 50),
|
||||
outline_color=Color(255, 255, 0),
|
||||
outline=2)
|
||||
inner.name = "inner"
|
||||
inner.clip_children = True # Also enable clipping on inner frame
|
||||
outer.children.append(inner)
|
||||
|
||||
# Add content to inner frame that extends beyond its bounds
|
||||
for i in range(5):
|
||||
caption = Caption(text=f"Line {i+1}: This text should be double-clipped", pos=(10, 30 * i))
|
||||
caption.font_size = 14
|
||||
caption.fill_color = Color(255, 255, 255)
|
||||
inner.children.append(caption)
|
||||
|
||||
# Add a child frame to inner that extends way out
|
||||
deeply_nested = Frame(pos=(250, 100), size=(200, 150),
|
||||
fill_color=Color(50, 150, 50),
|
||||
outline_color=Color(255, 0, 255),
|
||||
outline=2)
|
||||
deeply_nested.name = "deeply_nested"
|
||||
inner.children.append(deeply_nested)
|
||||
|
||||
# Add status text
|
||||
status = Caption(text="Nested clipping test:\n"
|
||||
"- Blue outer frame clips red inner frame\n"
|
||||
"- Red inner frame clips green deeply nested frame\n"
|
||||
"- All text should be clipped to frame bounds",
|
||||
pos=(50, 380))
|
||||
status.font_size = 12
|
||||
status.fill_color = Color(200, 200, 200)
|
||||
scene.append(status)
|
||||
|
||||
# Test render texture size handling
|
||||
print(f"Outer frame size: {outer.w}x{outer.h}")
|
||||
print(f"Inner frame size: {inner.w}x{inner.h}")
|
||||
|
||||
# Step to render
|
||||
mcrfpy.step(0.1)
|
||||
|
||||
# Take initial screenshot
|
||||
automation.screenshot("frame_clipping_nested.png")
|
||||
print("Initial screenshot saved: frame_clipping_nested.png")
|
||||
|
||||
# Dynamically resize frames to test RenderTexture recreation
|
||||
print("Resizing frames to test RenderTexture recreation...")
|
||||
outer.w = 450
|
||||
outer.h = 350
|
||||
inner.w = 350
|
||||
inner.h = 250
|
||||
print(f"New outer frame size: {outer.w}x{outer.h}")
|
||||
print(f"New inner frame size: {inner.w}x{inner.h}")
|
||||
|
||||
# Step to render resize
|
||||
mcrfpy.step(0.1)
|
||||
|
||||
# Take screenshot after resize
|
||||
automation.screenshot("frame_clipping_resized.png")
|
||||
|
||||
print("\nAdvanced test completed!")
|
||||
print("Screenshots saved:")
|
||||
print(" - frame_clipping_nested.png (initial)")
|
||||
print(" - frame_clipping_resized.png (after resize)")
|
||||
|
||||
print("PASS")
|
||||
sys.exit(0)
|
||||
|
|
|
|||
|
|
@ -1,129 +1,125 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Test Grid.children collection - Issue #132"""
|
||||
"""Test Grid.children collection - Issue #132
|
||||
Refactored to use mcrfpy.step() for synchronous execution.
|
||||
"""
|
||||
import mcrfpy
|
||||
from mcrfpy import automation
|
||||
import sys
|
||||
|
||||
def take_screenshot(timer, runtime):
|
||||
"""Take screenshot after render completes"""
|
||||
timer.stop()
|
||||
automation.screenshot("test_grid_children_result.png")
|
||||
|
||||
print("Screenshot saved to test_grid_children_result.png")
|
||||
print("PASS - Grid.children test completed")
|
||||
sys.exit(0)
|
||||
|
||||
def run_test(timer, runtime):
|
||||
"""Main test - runs after scene is set up"""
|
||||
timer.stop()
|
||||
|
||||
# Get the scene UI
|
||||
ui = test.children
|
||||
|
||||
# Create a grid without texture (uses default 16x16 cells)
|
||||
print("Test 1: Creating Grid with children...")
|
||||
grid = mcrfpy.Grid(grid_size=(20, 15), pos=(50, 50), size=(320, 240))
|
||||
grid.fill_color = mcrfpy.Color(30, 30, 60)
|
||||
ui.append(grid)
|
||||
|
||||
# Verify entities and children properties exist
|
||||
print(f" grid.entities = {grid.entities}")
|
||||
print(f" grid.children = {grid.children}")
|
||||
|
||||
# Test 2: Add UIDrawable children to the grid
|
||||
print("\nTest 2: Adding UIDrawable children...")
|
||||
|
||||
# Speech bubble style caption - positioned in grid-world pixels
|
||||
# At cell (5, 3) which is 5*16=80, 3*16=48 in pixels
|
||||
caption = mcrfpy.Caption(text="Hello!", pos=(80, 48))
|
||||
caption.fill_color = mcrfpy.Color(255, 255, 200)
|
||||
caption.outline = 1
|
||||
caption.outline_color = mcrfpy.Color(0, 0, 0)
|
||||
grid.children.append(caption)
|
||||
print(f" Added caption at (80, 48)")
|
||||
|
||||
# A highlight circle around cell (10, 7) = (160, 112)
|
||||
# Circle needs center, not pos
|
||||
circle = mcrfpy.Circle(center=(168, 120), radius=20,
|
||||
fill_color=mcrfpy.Color(255, 255, 0, 100),
|
||||
outline_color=mcrfpy.Color(255, 255, 0),
|
||||
outline=2)
|
||||
grid.children.append(circle)
|
||||
print(f" Added highlight circle at (168, 120)")
|
||||
|
||||
# A line indicating a path from (2,2) to (8,6)
|
||||
# In pixels: (32, 32) to (128, 96)
|
||||
line = mcrfpy.Line(start=(32, 32), end=(128, 96),
|
||||
color=mcrfpy.Color(0, 255, 0), thickness=3)
|
||||
grid.children.append(line)
|
||||
print(f" Added path line from (32,32) to (128,96)")
|
||||
|
||||
# An arc for range indicator at (15, 10) = (240, 160)
|
||||
arc = mcrfpy.Arc(center=(240, 160), radius=40, start_angle=0, end_angle=270,
|
||||
color=mcrfpy.Color(255, 0, 255), thickness=4)
|
||||
grid.children.append(arc)
|
||||
print(f" Added range arc at (240, 160)")
|
||||
|
||||
# Test 3: Verify children count
|
||||
print(f"\nTest 3: Verifying children count...")
|
||||
print(f" grid.children count = {len(grid.children)}")
|
||||
assert len(grid.children) == 4, f"Expected 4 children, got {len(grid.children)}"
|
||||
|
||||
# Test 4: Children should be accessible by index
|
||||
print("\nTest 4: Accessing children by index...")
|
||||
child0 = grid.children[0]
|
||||
print(f" grid.children[0] = {child0}")
|
||||
child1 = grid.children[1]
|
||||
print(f" grid.children[1] = {child1}")
|
||||
|
||||
# Test 5: Modify a child's position (should update in grid)
|
||||
print("\nTest 5: Modifying child position...")
|
||||
original_pos = (caption.pos.x, caption.pos.y)
|
||||
caption.pos = mcrfpy.Vector(90, 58)
|
||||
new_pos = (caption.pos.x, caption.pos.y)
|
||||
print(f" Moved caption from {original_pos} to {new_pos}")
|
||||
|
||||
# Test 6: Test z_index for children
|
||||
print("\nTest 6: Testing z_index ordering...")
|
||||
# Add overlapping elements with different z_index
|
||||
frame1 = mcrfpy.Frame(pos=(150, 80), size=(40, 40))
|
||||
frame1.fill_color = mcrfpy.Color(255, 0, 0, 200)
|
||||
frame1.z_index = 10
|
||||
grid.children.append(frame1)
|
||||
|
||||
frame2 = mcrfpy.Frame(pos=(160, 90), size=(40, 40))
|
||||
frame2.fill_color = mcrfpy.Color(0, 255, 0, 200)
|
||||
frame2.z_index = 5 # Lower z_index, rendered first (behind)
|
||||
grid.children.append(frame2)
|
||||
print(f" Added overlapping frames: red z=10, green z=5")
|
||||
|
||||
# Test 7: Test visibility
|
||||
print("\nTest 7: Testing child visibility...")
|
||||
frame3 = mcrfpy.Frame(pos=(50, 150), size=(30, 30))
|
||||
frame3.fill_color = mcrfpy.Color(0, 0, 255)
|
||||
frame3.visible = False
|
||||
grid.children.append(frame3)
|
||||
print(f" Added invisible blue frame (should not appear)")
|
||||
|
||||
# Test 8: Pan the grid and verify children move with it
|
||||
print("\nTest 8: Testing pan (children should follow grid camera)...")
|
||||
# Center the view on cell (10, 7.5) - default was grid center
|
||||
grid.center = (160, 120) # Center on pixel (160, 120)
|
||||
print(f" Centered grid on (160, 120)")
|
||||
|
||||
# Test 9: Test zoom
|
||||
print("\nTest 9: Testing zoom...")
|
||||
grid.zoom = 1.5
|
||||
print(f" Set zoom to 1.5")
|
||||
|
||||
print(f"\nFinal children count: {len(grid.children)}")
|
||||
|
||||
# Schedule screenshot for next frame
|
||||
mcrfpy.Timer("screenshot", take_screenshot, 100, once=True)
|
||||
|
||||
# Create a test scene
|
||||
print("Creating test scene...")
|
||||
test = mcrfpy.Scene("test")
|
||||
test.activate()
|
||||
mcrfpy.step(0.01) # Initialize
|
||||
|
||||
# Schedule test to run after game loop starts
|
||||
mcrfpy.Timer("test", run_test, 50, once=True)
|
||||
# Get the scene UI
|
||||
ui = test.children
|
||||
|
||||
# Test 1: Creating Grid with children
|
||||
print("Test 1: Creating Grid with children...")
|
||||
grid = mcrfpy.Grid(grid_size=(20, 15), pos=(50, 50), size=(320, 240))
|
||||
grid.fill_color = mcrfpy.Color(30, 30, 60)
|
||||
ui.append(grid)
|
||||
|
||||
# Verify entities and children properties exist
|
||||
print(f" grid.entities = {grid.entities}")
|
||||
print(f" grid.children = {grid.children}")
|
||||
|
||||
# Test 2: Add UIDrawable children to the grid
|
||||
print("\nTest 2: Adding UIDrawable children...")
|
||||
|
||||
# Speech bubble style caption - positioned in grid-world pixels
|
||||
# At cell (5, 3) which is 5*16=80, 3*16=48 in pixels
|
||||
caption = mcrfpy.Caption(text="Hello!", pos=(80, 48))
|
||||
caption.fill_color = mcrfpy.Color(255, 255, 200)
|
||||
caption.outline = 1
|
||||
caption.outline_color = mcrfpy.Color(0, 0, 0)
|
||||
grid.children.append(caption)
|
||||
print(f" Added caption at (80, 48)")
|
||||
|
||||
# A highlight circle around cell (10, 7) = (160, 112)
|
||||
# Circle needs center, not pos
|
||||
circle = mcrfpy.Circle(center=(168, 120), radius=20,
|
||||
fill_color=mcrfpy.Color(255, 255, 0, 100),
|
||||
outline_color=mcrfpy.Color(255, 255, 0),
|
||||
outline=2)
|
||||
grid.children.append(circle)
|
||||
print(f" Added highlight circle at (168, 120)")
|
||||
|
||||
# A line indicating a path from (2,2) to (8,6)
|
||||
# In pixels: (32, 32) to (128, 96)
|
||||
line = mcrfpy.Line(start=(32, 32), end=(128, 96),
|
||||
color=mcrfpy.Color(0, 255, 0), thickness=3)
|
||||
grid.children.append(line)
|
||||
print(f" Added path line from (32,32) to (128,96)")
|
||||
|
||||
# An arc for range indicator at (15, 10) = (240, 160)
|
||||
arc = mcrfpy.Arc(center=(240, 160), radius=40, start_angle=0, end_angle=270,
|
||||
color=mcrfpy.Color(255, 0, 255), thickness=4)
|
||||
grid.children.append(arc)
|
||||
print(f" Added range arc at (240, 160)")
|
||||
|
||||
# Test 3: Verify children count
|
||||
print(f"\nTest 3: Verifying children count...")
|
||||
print(f" grid.children count = {len(grid.children)}")
|
||||
if len(grid.children) != 4:
|
||||
print(f"FAIL: Expected 4 children, got {len(grid.children)}")
|
||||
sys.exit(1)
|
||||
|
||||
# Test 4: Children should be accessible by index
|
||||
print("\nTest 4: Accessing children by index...")
|
||||
child0 = grid.children[0]
|
||||
print(f" grid.children[0] = {child0}")
|
||||
child1 = grid.children[1]
|
||||
print(f" grid.children[1] = {child1}")
|
||||
|
||||
# Test 5: Modify a child's position (should update in grid)
|
||||
print("\nTest 5: Modifying child position...")
|
||||
original_pos = (caption.pos.x, caption.pos.y)
|
||||
caption.pos = mcrfpy.Vector(90, 58)
|
||||
new_pos = (caption.pos.x, caption.pos.y)
|
||||
print(f" Moved caption from {original_pos} to {new_pos}")
|
||||
|
||||
# Test 6: Test z_index for children
|
||||
print("\nTest 6: Testing z_index ordering...")
|
||||
# Add overlapping elements with different z_index
|
||||
frame1 = mcrfpy.Frame(pos=(150, 80), size=(40, 40))
|
||||
frame1.fill_color = mcrfpy.Color(255, 0, 0, 200)
|
||||
frame1.z_index = 10
|
||||
grid.children.append(frame1)
|
||||
|
||||
frame2 = mcrfpy.Frame(pos=(160, 90), size=(40, 40))
|
||||
frame2.fill_color = mcrfpy.Color(0, 255, 0, 200)
|
||||
frame2.z_index = 5 # Lower z_index, rendered first (behind)
|
||||
grid.children.append(frame2)
|
||||
print(f" Added overlapping frames: red z=10, green z=5")
|
||||
|
||||
# Test 7: Test visibility
|
||||
print("\nTest 7: Testing child visibility...")
|
||||
frame3 = mcrfpy.Frame(pos=(50, 150), size=(30, 30))
|
||||
frame3.fill_color = mcrfpy.Color(0, 0, 255)
|
||||
frame3.visible = False
|
||||
grid.children.append(frame3)
|
||||
print(f" Added invisible blue frame (should not appear)")
|
||||
|
||||
# Test 8: Pan the grid and verify children move with it
|
||||
print("\nTest 8: Testing pan (children should follow grid camera)...")
|
||||
# Center the view on cell (10, 7.5) - default was grid center
|
||||
grid.center = (160, 120) # Center on pixel (160, 120)
|
||||
print(f" Centered grid on (160, 120)")
|
||||
|
||||
# Test 9: Test zoom
|
||||
print("\nTest 9: Testing zoom...")
|
||||
grid.zoom = 1.5
|
||||
print(f" Set zoom to 1.5")
|
||||
|
||||
print(f"\nFinal children count: {len(grid.children)}")
|
||||
|
||||
# Step to render everything
|
||||
mcrfpy.step(0.1)
|
||||
|
||||
# Take screenshot
|
||||
automation.screenshot("test_grid_children_result.png")
|
||||
print("Screenshot saved to test_grid_children_result.png")
|
||||
|
||||
print("PASS - Grid.children test completed")
|
||||
sys.exit(0)
|
||||
|
|
|
|||
|
|
@ -2,90 +2,94 @@
|
|||
"""
|
||||
Test that all UI classes can be instantiated without arguments.
|
||||
This verifies the fix for requiring arguments even with safe default constructors.
|
||||
Refactored to use mcrfpy.step() for synchronous execution.
|
||||
"""
|
||||
|
||||
import mcrfpy
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
def test_ui_constructors(timer, runtime):
|
||||
"""Test that UI classes can be instantiated without arguments"""
|
||||
|
||||
print("Testing UI class instantiation without arguments...")
|
||||
|
||||
# Test UICaption with no arguments
|
||||
try:
|
||||
caption = mcrfpy.Caption()
|
||||
print("PASS: Caption() - Success")
|
||||
print(f" Position: ({caption.x}, {caption.y})")
|
||||
print(f" Text: '{caption.text}'")
|
||||
assert caption.x == 0.0
|
||||
assert caption.y == 0.0
|
||||
assert caption.text == ""
|
||||
except Exception as e:
|
||||
print(f"FAIL: Caption() - {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
# Test UIFrame with no arguments
|
||||
try:
|
||||
frame = mcrfpy.Frame()
|
||||
print("PASS: Frame() - Success")
|
||||
print(f" Position: ({frame.x}, {frame.y})")
|
||||
print(f" Size: ({frame.w}, {frame.h})")
|
||||
assert frame.x == 0.0
|
||||
assert frame.y == 0.0
|
||||
assert frame.w == 0.0
|
||||
assert frame.h == 0.0
|
||||
except Exception as e:
|
||||
print(f"FAIL: Frame() - {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
# Test UIGrid with no arguments
|
||||
try:
|
||||
grid = mcrfpy.Grid()
|
||||
print("PASS: Grid() - Success")
|
||||
print(f" Grid size: {grid.grid_x} x {grid.grid_y}")
|
||||
print(f" Position: ({grid.x}, {grid.y})")
|
||||
assert grid.grid_x == 1
|
||||
assert grid.grid_y == 1
|
||||
assert grid.x == 0.0
|
||||
assert grid.y == 0.0
|
||||
except Exception as e:
|
||||
print(f"FAIL: Grid() - {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
# Test UIEntity with no arguments
|
||||
try:
|
||||
entity = mcrfpy.Entity()
|
||||
print("PASS: Entity() - Success")
|
||||
print(f" Position: ({entity.x}, {entity.y})")
|
||||
assert entity.x == 0.0
|
||||
assert entity.y == 0.0
|
||||
except Exception as e:
|
||||
print(f"FAIL: Entity() - {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
# Test UISprite with no arguments (if it has a default constructor)
|
||||
try:
|
||||
sprite = mcrfpy.Sprite()
|
||||
print("PASS: Sprite() - Success")
|
||||
print(f" Position: ({sprite.x}, {sprite.y})")
|
||||
assert sprite.x == 0.0
|
||||
assert sprite.y == 0.0
|
||||
except Exception as e:
|
||||
print(f"FAIL: Sprite() - {e}")
|
||||
# Sprite might still require arguments, which is okay
|
||||
|
||||
print("\nAll tests complete!")
|
||||
|
||||
# Exit cleanly
|
||||
sys.exit(0)
|
||||
|
||||
# Create a basic scene so the game can start
|
||||
# Initialize scene
|
||||
test = mcrfpy.Scene("test")
|
||||
test.activate()
|
||||
mcrfpy.step(0.01)
|
||||
|
||||
# Schedule the test to run after game initialization
|
||||
test_timer = mcrfpy.Timer("test", test_ui_constructors, 100, once=True)
|
||||
print("Testing UI class instantiation without arguments...")
|
||||
|
||||
all_pass = True
|
||||
|
||||
# Test UICaption with no arguments
|
||||
try:
|
||||
caption = mcrfpy.Caption()
|
||||
print("PASS: Caption() - Success")
|
||||
print(f" Position: ({caption.x}, {caption.y})")
|
||||
print(f" Text: '{caption.text}'")
|
||||
assert caption.x == 0.0
|
||||
assert caption.y == 0.0
|
||||
assert caption.text == ""
|
||||
except Exception as e:
|
||||
print(f"FAIL: Caption() - {e}")
|
||||
traceback.print_exc()
|
||||
all_pass = False
|
||||
|
||||
# Test UIFrame with no arguments
|
||||
try:
|
||||
frame = mcrfpy.Frame()
|
||||
print("PASS: Frame() - Success")
|
||||
print(f" Position: ({frame.x}, {frame.y})")
|
||||
print(f" Size: ({frame.w}, {frame.h})")
|
||||
assert frame.x == 0.0
|
||||
assert frame.y == 0.0
|
||||
assert frame.w == 0.0
|
||||
assert frame.h == 0.0
|
||||
except Exception as e:
|
||||
print(f"FAIL: Frame() - {e}")
|
||||
traceback.print_exc()
|
||||
all_pass = False
|
||||
|
||||
# Test UIGrid with no arguments
|
||||
try:
|
||||
grid = mcrfpy.Grid()
|
||||
print("PASS: Grid() - Success")
|
||||
print(f" Grid size: {grid.grid_x} x {grid.grid_y}")
|
||||
print(f" Position: ({grid.x}, {grid.y})")
|
||||
assert grid.grid_x == 1
|
||||
assert grid.grid_y == 1
|
||||
assert grid.x == 0.0
|
||||
assert grid.y == 0.0
|
||||
except Exception as e:
|
||||
print(f"FAIL: Grid() - {e}")
|
||||
traceback.print_exc()
|
||||
all_pass = False
|
||||
|
||||
# Test UIEntity with no arguments
|
||||
try:
|
||||
entity = mcrfpy.Entity()
|
||||
print("PASS: Entity() - Success")
|
||||
print(f" Position: ({entity.x}, {entity.y})")
|
||||
assert entity.x == 0.0
|
||||
assert entity.y == 0.0
|
||||
except Exception as e:
|
||||
print(f"FAIL: Entity() - {e}")
|
||||
traceback.print_exc()
|
||||
all_pass = False
|
||||
|
||||
# Test UISprite with no arguments (if it has a default constructor)
|
||||
try:
|
||||
sprite = mcrfpy.Sprite()
|
||||
print("PASS: Sprite() - Success")
|
||||
print(f" Position: ({sprite.x}, {sprite.y})")
|
||||
assert sprite.x == 0.0
|
||||
assert sprite.y == 0.0
|
||||
except Exception as e:
|
||||
print(f"FAIL: Sprite() - {e}")
|
||||
# Sprite might still require arguments, which is okay
|
||||
|
||||
print("\nAll tests complete!")
|
||||
|
||||
if all_pass:
|
||||
print("PASS")
|
||||
sys.exit(0)
|
||||
else:
|
||||
print("FAIL")
|
||||
sys.exit(1)
|
||||
|
|
|
|||
|
|
@ -1,57 +1,67 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Quick test of drawable properties"""
|
||||
"""Quick test of drawable properties
|
||||
Refactored to use mcrfpy.step() for synchronous execution.
|
||||
"""
|
||||
import mcrfpy
|
||||
import sys
|
||||
|
||||
def test_properties(timer, runtime):
|
||||
timer.stop()
|
||||
|
||||
print("\n=== Testing Properties ===")
|
||||
|
||||
# Test Frame
|
||||
try:
|
||||
frame = mcrfpy.Frame(pos=(10, 10), size=(100, 100))
|
||||
print(f"Frame visible: {frame.visible}")
|
||||
frame.visible = False
|
||||
print(f"Frame visible after setting to False: {frame.visible}")
|
||||
|
||||
print(f"Frame opacity: {frame.opacity}")
|
||||
frame.opacity = 0.5
|
||||
print(f"Frame opacity after setting to 0.5: {frame.opacity}")
|
||||
|
||||
bounds = frame.get_bounds()
|
||||
print(f"Frame bounds: {bounds}")
|
||||
|
||||
frame.move(5, 5)
|
||||
bounds2 = frame.get_bounds()
|
||||
print(f"Frame bounds after move(5,5): {bounds2}")
|
||||
|
||||
print("✓ Frame properties work!")
|
||||
except Exception as e:
|
||||
print(f"✗ Frame failed: {e}")
|
||||
|
||||
# Test Entity
|
||||
try:
|
||||
entity = mcrfpy.Entity()
|
||||
print(f"\nEntity visible: {entity.visible}")
|
||||
entity.visible = False
|
||||
print(f"Entity visible after setting to False: {entity.visible}")
|
||||
|
||||
print(f"Entity opacity: {entity.opacity}")
|
||||
entity.opacity = 0.7
|
||||
print(f"Entity opacity after setting to 0.7: {entity.opacity}")
|
||||
|
||||
bounds = entity.get_bounds()
|
||||
print(f"Entity bounds: {bounds}")
|
||||
|
||||
entity.move(3, 3)
|
||||
print(f"Entity position after move(3,3): ({entity.x}, {entity.y})")
|
||||
|
||||
print("✓ Entity properties work!")
|
||||
except Exception as e:
|
||||
print(f"✗ Entity failed: {e}")
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
# Initialize scene
|
||||
test = mcrfpy.Scene("test")
|
||||
test_properties_timer = mcrfpy.Timer("test_properties", test_properties, 100, once=True)
|
||||
test.activate()
|
||||
mcrfpy.step(0.01)
|
||||
|
||||
print("\n=== Testing Properties ===")
|
||||
|
||||
all_pass = True
|
||||
|
||||
# Test Frame
|
||||
try:
|
||||
frame = mcrfpy.Frame(pos=(10, 10), size=(100, 100))
|
||||
print(f"Frame visible: {frame.visible}")
|
||||
frame.visible = False
|
||||
print(f"Frame visible after setting to False: {frame.visible}")
|
||||
|
||||
print(f"Frame opacity: {frame.opacity}")
|
||||
frame.opacity = 0.5
|
||||
print(f"Frame opacity after setting to 0.5: {frame.opacity}")
|
||||
|
||||
bounds = frame.get_bounds()
|
||||
print(f"Frame bounds: {bounds}")
|
||||
|
||||
frame.move(5, 5)
|
||||
bounds2 = frame.get_bounds()
|
||||
print(f"Frame bounds after move(5,5): {bounds2}")
|
||||
|
||||
print("+ Frame properties work!")
|
||||
except Exception as e:
|
||||
print(f"x Frame failed: {e}")
|
||||
all_pass = False
|
||||
|
||||
# Test Entity
|
||||
try:
|
||||
entity = mcrfpy.Entity()
|
||||
print(f"\nEntity visible: {entity.visible}")
|
||||
entity.visible = False
|
||||
print(f"Entity visible after setting to False: {entity.visible}")
|
||||
|
||||
print(f"Entity opacity: {entity.opacity}")
|
||||
entity.opacity = 0.7
|
||||
print(f"Entity opacity after setting to 0.7: {entity.opacity}")
|
||||
|
||||
bounds = entity.get_bounds()
|
||||
print(f"Entity bounds: {bounds}")
|
||||
|
||||
entity.move(3, 3)
|
||||
print(f"Entity position after move(3,3): ({entity.x}, {entity.y})")
|
||||
|
||||
print("+ Entity properties work!")
|
||||
except Exception as e:
|
||||
print(f"x Entity failed: {e}")
|
||||
all_pass = False
|
||||
|
||||
if all_pass:
|
||||
print("\nPASS")
|
||||
sys.exit(0)
|
||||
else:
|
||||
print("\nFAIL")
|
||||
sys.exit(1)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ Test for Python object cache - verifies that derived Python classes
|
|||
maintain their identity when stored in and retrieved from collections.
|
||||
|
||||
Issue #112: Object Splitting - Preserve Python derived types in collections
|
||||
Refactored to use mcrfpy.step() for synchronous execution.
|
||||
"""
|
||||
|
||||
import mcrfpy
|
||||
|
|
@ -16,136 +17,128 @@ test_results = []
|
|||
def test(condition, message):
|
||||
global test_passed
|
||||
if condition:
|
||||
test_results.append(f"✓ {message}")
|
||||
test_results.append(f"+ {message}")
|
||||
else:
|
||||
test_results.append(f"✗ {message}")
|
||||
test_results.append(f"x {message}")
|
||||
test_passed = False
|
||||
|
||||
def run_tests(timer, runtime):
|
||||
"""Timer callback to run tests after game loop starts"""
|
||||
global test_passed
|
||||
|
||||
print("\n=== Testing Python Object Cache ===")
|
||||
|
||||
# Test 1: Create derived Frame class
|
||||
class MyFrame(mcrfpy.Frame):
|
||||
def __init__(self, x=0, y=0):
|
||||
super().__init__(pos=(x, y), size=(100, 100))
|
||||
self.custom_data = "I am a custom frame"
|
||||
self.test_value = 42
|
||||
|
||||
# Test 2: Create instance and add to scene
|
||||
frame = MyFrame(50, 50)
|
||||
scene_ui = test_scene.children
|
||||
scene_ui.append(frame)
|
||||
|
||||
# Test 3: Retrieve from collection and check type
|
||||
retrieved = scene_ui[0]
|
||||
test(type(retrieved) == MyFrame, "Retrieved object maintains derived type")
|
||||
test(isinstance(retrieved, MyFrame), "isinstance check passes")
|
||||
test(hasattr(retrieved, 'custom_data'), "Custom attribute exists")
|
||||
if hasattr(retrieved, 'custom_data'):
|
||||
test(retrieved.custom_data == "I am a custom frame", "Custom attribute value preserved")
|
||||
if hasattr(retrieved, 'test_value'):
|
||||
test(retrieved.test_value == 42, "Numeric attribute value preserved")
|
||||
|
||||
# Test 4: Check object identity (same Python object)
|
||||
test(retrieved is frame, "Retrieved object is the same Python object")
|
||||
test(id(retrieved) == id(frame), "Object IDs match")
|
||||
|
||||
# Test 5: Multiple retrievals return same object
|
||||
retrieved2 = scene_ui[0]
|
||||
test(retrieved2 is retrieved, "Multiple retrievals return same object")
|
||||
|
||||
# Test 6: Test with other UI types
|
||||
class MySprite(mcrfpy.Sprite):
|
||||
def __init__(self):
|
||||
# Use default texture by passing None
|
||||
super().__init__(texture=None, sprite_index=0)
|
||||
self.sprite_data = "custom sprite"
|
||||
|
||||
sprite = MySprite()
|
||||
sprite.x = 200
|
||||
sprite.y = 200
|
||||
scene_ui.append(sprite)
|
||||
|
||||
retrieved_sprite = scene_ui[1]
|
||||
test(type(retrieved_sprite) == MySprite, "Sprite maintains derived type")
|
||||
if hasattr(retrieved_sprite, 'sprite_data'):
|
||||
test(retrieved_sprite.sprite_data == "custom sprite", "Sprite custom data preserved")
|
||||
|
||||
# Test 7: Test with Caption
|
||||
class MyCaption(mcrfpy.Caption):
|
||||
def __init__(self, text):
|
||||
# Use default font by passing None
|
||||
super().__init__(text=text, font=None)
|
||||
self.caption_id = "test_caption"
|
||||
|
||||
caption = MyCaption("Test Caption")
|
||||
caption.x = 10
|
||||
caption.y = 10
|
||||
scene_ui.append(caption)
|
||||
|
||||
retrieved_caption = scene_ui[2]
|
||||
test(type(retrieved_caption) == MyCaption, "Caption maintains derived type")
|
||||
if hasattr(retrieved_caption, 'caption_id'):
|
||||
test(retrieved_caption.caption_id == "test_caption", "Caption custom data preserved")
|
||||
|
||||
# Test 8: Test removal and re-addition
|
||||
# Use del to remove by index (Python standard), or .remove(element) to remove by value
|
||||
print(f"before remove: {len(scene_ui)=}")
|
||||
del scene_ui[-1] # Remove last element by index
|
||||
print(f"after remove: {len(scene_ui)=}")
|
||||
|
||||
scene_ui.append(frame)
|
||||
retrieved3 = scene_ui[-1] # Get last element
|
||||
test(retrieved3 is frame, "Object identity preserved after removal/re-addition")
|
||||
|
||||
# Test 9: Test with Grid
|
||||
class MyGrid(mcrfpy.Grid):
|
||||
def __init__(self, w, h):
|
||||
super().__init__(grid_size=(w, h))
|
||||
self.grid_name = "custom_grid"
|
||||
|
||||
grid = MyGrid(10, 10)
|
||||
grid.x = 300
|
||||
grid.y = 100
|
||||
scene_ui.append(grid)
|
||||
|
||||
retrieved_grid = scene_ui[-1]
|
||||
test(type(retrieved_grid) == MyGrid, "Grid maintains derived type")
|
||||
if hasattr(retrieved_grid, 'grid_name'):
|
||||
test(retrieved_grid.grid_name == "custom_grid", "Grid custom data preserved")
|
||||
|
||||
# Test 10: Test with nested collections (Frame with children)
|
||||
parent = MyFrame(400, 400)
|
||||
child = MyFrame(10, 10)
|
||||
child.custom_data = "I am a child"
|
||||
parent.children.append(child)
|
||||
scene_ui.append(parent)
|
||||
|
||||
retrieved_parent = scene_ui[-1]
|
||||
test(type(retrieved_parent) == MyFrame, "Parent frame maintains type")
|
||||
if len(retrieved_parent.children) > 0:
|
||||
retrieved_child = retrieved_parent.children[0]
|
||||
test(type(retrieved_child) == MyFrame, "Child frame maintains type in nested collection")
|
||||
if hasattr(retrieved_child, 'custom_data'):
|
||||
test(retrieved_child.custom_data == "I am a child", "Child custom data preserved")
|
||||
|
||||
# Print results
|
||||
print("\n=== Test Results ===")
|
||||
for result in test_results:
|
||||
print(result)
|
||||
|
||||
print(f"\n{'PASS' if test_passed else 'FAIL'}: {sum(1 for r in test_results if r.startswith('✓'))}/{len(test_results)} tests passed")
|
||||
|
||||
sys.exit(0 if test_passed else 1)
|
||||
|
||||
# Create test scene
|
||||
test_scene = mcrfpy.Scene("test_scene")
|
||||
test_scene.activate()
|
||||
mcrfpy.step(0.01)
|
||||
|
||||
# Schedule tests to run after game loop starts
|
||||
test_timer = mcrfpy.Timer("test", run_tests, 100, once=True)
|
||||
print("\n=== Testing Python Object Cache ===")
|
||||
|
||||
print("Python object cache test initialized. Running tests...")
|
||||
# Test 1: Create derived Frame class
|
||||
class MyFrame(mcrfpy.Frame):
|
||||
def __init__(self, x=0, y=0):
|
||||
super().__init__(pos=(x, y), size=(100, 100))
|
||||
self.custom_data = "I am a custom frame"
|
||||
self.test_value = 42
|
||||
|
||||
# Test 2: Create instance and add to scene
|
||||
frame = MyFrame(50, 50)
|
||||
scene_ui = test_scene.children
|
||||
scene_ui.append(frame)
|
||||
|
||||
# Test 3: Retrieve from collection and check type
|
||||
retrieved = scene_ui[0]
|
||||
test(type(retrieved) == MyFrame, "Retrieved object maintains derived type")
|
||||
test(isinstance(retrieved, MyFrame), "isinstance check passes")
|
||||
test(hasattr(retrieved, 'custom_data'), "Custom attribute exists")
|
||||
if hasattr(retrieved, 'custom_data'):
|
||||
test(retrieved.custom_data == "I am a custom frame", "Custom attribute value preserved")
|
||||
if hasattr(retrieved, 'test_value'):
|
||||
test(retrieved.test_value == 42, "Numeric attribute value preserved")
|
||||
|
||||
# Test 4: Check object identity (same Python object)
|
||||
test(retrieved is frame, "Retrieved object is the same Python object")
|
||||
test(id(retrieved) == id(frame), "Object IDs match")
|
||||
|
||||
# Test 5: Multiple retrievals return same object
|
||||
retrieved2 = scene_ui[0]
|
||||
test(retrieved2 is retrieved, "Multiple retrievals return same object")
|
||||
|
||||
# Test 6: Test with other UI types
|
||||
class MySprite(mcrfpy.Sprite):
|
||||
def __init__(self):
|
||||
# Use default texture by passing None
|
||||
super().__init__(texture=None, sprite_index=0)
|
||||
self.sprite_data = "custom sprite"
|
||||
|
||||
sprite = MySprite()
|
||||
sprite.x = 200
|
||||
sprite.y = 200
|
||||
scene_ui.append(sprite)
|
||||
|
||||
retrieved_sprite = scene_ui[1]
|
||||
test(type(retrieved_sprite) == MySprite, "Sprite maintains derived type")
|
||||
if hasattr(retrieved_sprite, 'sprite_data'):
|
||||
test(retrieved_sprite.sprite_data == "custom sprite", "Sprite custom data preserved")
|
||||
|
||||
# Test 7: Test with Caption
|
||||
class MyCaption(mcrfpy.Caption):
|
||||
def __init__(self, text):
|
||||
# Use default font by passing None
|
||||
super().__init__(text=text, font=None)
|
||||
self.caption_id = "test_caption"
|
||||
|
||||
caption = MyCaption("Test Caption")
|
||||
caption.x = 10
|
||||
caption.y = 10
|
||||
scene_ui.append(caption)
|
||||
|
||||
retrieved_caption = scene_ui[2]
|
||||
test(type(retrieved_caption) == MyCaption, "Caption maintains derived type")
|
||||
if hasattr(retrieved_caption, 'caption_id'):
|
||||
test(retrieved_caption.caption_id == "test_caption", "Caption custom data preserved")
|
||||
|
||||
# Test 8: Test removal and re-addition
|
||||
# Use del to remove by index (Python standard), or .remove(element) to remove by value
|
||||
print(f"before remove: {len(scene_ui)=}")
|
||||
del scene_ui[-1] # Remove last element by index
|
||||
print(f"after remove: {len(scene_ui)=}")
|
||||
|
||||
scene_ui.append(frame)
|
||||
retrieved3 = scene_ui[-1] # Get last element
|
||||
test(retrieved3 is frame, "Object identity preserved after removal/re-addition")
|
||||
|
||||
# Test 9: Test with Grid
|
||||
class MyGrid(mcrfpy.Grid):
|
||||
def __init__(self, w, h):
|
||||
super().__init__(grid_size=(w, h))
|
||||
self.grid_name = "custom_grid"
|
||||
|
||||
grid = MyGrid(10, 10)
|
||||
grid.x = 300
|
||||
grid.y = 100
|
||||
scene_ui.append(grid)
|
||||
|
||||
retrieved_grid = scene_ui[-1]
|
||||
test(type(retrieved_grid) == MyGrid, "Grid maintains derived type")
|
||||
if hasattr(retrieved_grid, 'grid_name'):
|
||||
test(retrieved_grid.grid_name == "custom_grid", "Grid custom data preserved")
|
||||
|
||||
# Test 10: Test with nested collections (Frame with children)
|
||||
parent = MyFrame(400, 400)
|
||||
child = MyFrame(10, 10)
|
||||
child.custom_data = "I am a child"
|
||||
parent.children.append(child)
|
||||
scene_ui.append(parent)
|
||||
|
||||
retrieved_parent = scene_ui[-1]
|
||||
test(type(retrieved_parent) == MyFrame, "Parent frame maintains type")
|
||||
if len(retrieved_parent.children) > 0:
|
||||
retrieved_child = retrieved_parent.children[0]
|
||||
test(type(retrieved_child) == MyFrame, "Child frame maintains type in nested collection")
|
||||
if hasattr(retrieved_child, 'custom_data'):
|
||||
test(retrieved_child.custom_data == "I am a child", "Child custom data preserved")
|
||||
|
||||
# Print results
|
||||
print("\n=== Test Results ===")
|
||||
for result in test_results:
|
||||
print(result)
|
||||
|
||||
print(f"\n{'PASS' if test_passed else 'FAIL'}: {sum(1 for r in test_results if r.startswith('+'))}/{len(test_results)} tests passed")
|
||||
|
||||
sys.exit(0 if test_passed else 1)
|
||||
|
|
|
|||
|
|
@ -1,14 +1,32 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Very simple callback test"""
|
||||
"""Very simple callback test - refactored to use mcrfpy.step()"""
|
||||
import mcrfpy
|
||||
import sys
|
||||
|
||||
callback_fired = False
|
||||
|
||||
def cb(a, t):
|
||||
global callback_fired
|
||||
callback_fired = True
|
||||
print("CB")
|
||||
|
||||
# Setup scene
|
||||
test = mcrfpy.Scene("test")
|
||||
test.activate()
|
||||
mcrfpy.step(0.01) # Initialize
|
||||
|
||||
# Create entity and animation
|
||||
e = mcrfpy.Entity((0, 0), texture=None, sprite_index=0)
|
||||
a = mcrfpy.Animation("x", 1.0, 0.1, "linear", callback=cb)
|
||||
a.start(e)
|
||||
mcrfpy.Timer("exit", lambda t, r: sys.exit(0), 200, once=True)
|
||||
|
||||
# Advance past animation duration (0.1s)
|
||||
mcrfpy.step(0.15)
|
||||
|
||||
# Verify callback fired
|
||||
if callback_fired:
|
||||
print("PASS: Callback fired")
|
||||
sys.exit(0)
|
||||
else:
|
||||
print("FAIL: Callback did not fire")
|
||||
sys.exit(1)
|
||||
|
|
|
|||
|
|
@ -1,30 +1,32 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Simple test to isolate drawable issue"""
|
||||
"""Simple test to isolate drawable issue
|
||||
Refactored to use mcrfpy.step() for synchronous execution.
|
||||
"""
|
||||
import mcrfpy
|
||||
import sys
|
||||
|
||||
def simple_test(timer, runtime):
|
||||
timer.stop()
|
||||
|
||||
try:
|
||||
# Test basic functionality
|
||||
frame = mcrfpy.Frame(pos=(10, 10), size=(100, 100))
|
||||
print(f"Frame created: visible={frame.visible}, opacity={frame.opacity}")
|
||||
|
||||
bounds = frame.get_bounds()
|
||||
print(f"Bounds: {bounds}")
|
||||
|
||||
frame.move(5, 5)
|
||||
print("Move completed")
|
||||
|
||||
frame.resize(150, 150)
|
||||
print("Resize completed")
|
||||
|
||||
print("PASS - No crash!")
|
||||
except Exception as e:
|
||||
print(f"ERROR: {e}")
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
# Initialize scene
|
||||
test = mcrfpy.Scene("test")
|
||||
simple_test_timer = mcrfpy.Timer("simple_test", simple_test, 100, once=True)
|
||||
test.activate()
|
||||
mcrfpy.step(0.01)
|
||||
|
||||
try:
|
||||
# Test basic functionality
|
||||
frame = mcrfpy.Frame(pos=(10, 10), size=(100, 100))
|
||||
print(f"Frame created: visible={frame.visible}, opacity={frame.opacity}")
|
||||
|
||||
bounds = frame.get_bounds()
|
||||
print(f"Bounds: {bounds}")
|
||||
|
||||
frame.move(5, 5)
|
||||
print("Move completed")
|
||||
|
||||
frame.resize(150, 150)
|
||||
print("Resize completed")
|
||||
|
||||
print("PASS - No crash!")
|
||||
sys.exit(0)
|
||||
except Exception as e:
|
||||
print(f"ERROR: {e}")
|
||||
print("FAIL")
|
||||
sys.exit(1)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue