"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.

SPDX-License-Identifier: Apache-2.0 OR MIT
"""


# Test case ID : C4976209
# Test Case Title : Verify that when Compute COM is enabled, the PhysX system computes the COM of the object on its own



# fmt: off
class Tests():
    enter_game_mode                     = ("Entered game mode",                                      "Failed to enter game mode")

    find_enabled_sphere                 = ("Enabled Sphere Found",                                   "Enabled Sphere not found")
    find_enabled_capsule                = ("Enabled Capsule Found",                                  "Enabled Capsule not found")
    find_enabled_box                    = ("Enabled Box Found",                                      "Enabled Box not found")
    find_enabled_physics_asset          = ("Enabled Physics Asset Found",                            "Enabled Physics Asset not found")

    find_disabled_sphere                = ("Disabled Sphere Found",                                  "Disabled Sphere not found")
    find_disabled_capsule               = ("Disabled Capsule Found",                                 "Disabled Capsule not found")
    find_disabled_box                   = ("Disabled Box Found",                                     "Disabled Box not found")
    find_disabled_physics_asset         = ("Disabled Physics Asset Found",                           "Disabled Physics Asset not found")

    enabled_sphere_COM_expected         = ("Enabled Sphere COM was close to expected value",         "Enabled Sphere COM was not close to expected value")
    enabled_capsule_COM_expected        = ("Enabled Capsule COM was close to expected value",        "Enabled Capsule COM was not close to expected value")
    enabled_box_COM_expected            = ("Enabled Box COM was close to expected value",            "Enabled Box COM was not close to expected value")
    enabled_physics_asset_COM_expected  = ("Enabled Physics Asset COM was close to expected value",  "Enabled Physics Asset COM was not close to expected value")

    disabled_sphere_COM_expected        = ("Disabled Sphere COM was close to expected value",        "Disabled Sphere COM was not close to expected value")
    disabled_capsule_COM_expected       = ("Disabled Capsule COM was close to expected value",       "Disabled Capsule COM was not close to expected value")
    disabled_box_COM_expected           = ("Disabled Box COM was close to expected value",           "Disabled Box not COM was not close to expected value")
    disabled_physics_asset_COM_expected = ("Disabled Physics Asset COM was close to expected value", "Disabled Physics Asset not COM was close to expected value")

    exit_game_mode                      = ("Exited game mode",                                       "Couldn't exit game mode")
# fmt: on


def C4976209_RigidBody_ComputesCOM():
    # type: () -> None
    """
    Summary:
    Runs an automated test to ensure when compute COM is enabled, that the COM is automatically calculated.

    Level Description:
    There are 4 sets of entities:
        Spheres (entity: SphereEnabled), (entity: SphereDisabled)
        Boxes (entity: BoxEnabled), (entity: BoxDisabled)
        Capsules (entity: CapsuleEnabled), (entity: CapsuleDisabled)
        Physics Assets with sedan mesh (entity: PhysicsAssetEnabled), (entity: PhysicsAssetDisabled)

    Each set has two entities, both of which are identical to one another - save for the Compute COM setting on their
    rigid body. One has it set to enabled, and the other has it set to disabled.

    Each entity has a rigid body and two PhysX colliders. The first collider has no offset. The second collider is
    positioned +2 units in the X direction.

    Expected Behavior:
    The entities with 'Compute COM' disabled will have local COM offsets at the objects origin ((0.0, 0.0, 0.0) Locally)
    The entities with 'Compute COM' enabled will have local COM offsets at the average position between the two
    colliders.
        For every entity that isn't a physics asset, that's +1 unit to the right (1/2 the offset value of the second
        collider). The physics asset has a mesh whose origin is not at the natural center of mass of the object,
        so we check its COM offset as a special case.

    Test Steps:
    1) Open level
    2) Enter game mode
    3) Validate entities
    4) Check center of mass for each entity
    5) Special Case: Check center of mass for each physics asset
    6) Exit game mode
    7) Close the editor

    Note:
    - This test file must be called from the Open 3D Engine Editor command terminal
    - Any passed and failed tests are written to the Editor.log file.
    - Parsing the file or running a log_monitor are required to observe the test results.

    :return: (None)
    """

    # Setup path
    import os
    import sys

    import ImportPathHelper as imports

    imports.init()

    from editor_python_test_tools.utils import Report
    from editor_python_test_tools.utils import TestHelper as helper

    import azlmbr
    import azlmbr.legacy.general as general
    import azlmbr.bus as bus
    import azlmbr.math as lymath

    CONTROL_COM = lymath.Vector3(0.0, 0.0, 0.0)
    EXPECTED_COM = lymath.Vector3(1.0, 0.0, 0.0)
    PHYSICS_ASSET_EXPECTED_COM = lymath.Vector3(1.0, -0.08, 0.43) # Derived from the sedan mesh specifically
    CLOSE_THRESHOLD = 0.01

    class Shape:
        def __init__(self, name, valid_test, com_valid_test):
            self.id = general.find_game_entity(name)
            self.center_of_mass = self.get_com()
            self.position = self.get_position()
            self.com_local = self.center_of_mass.Subtract(self.position)
            self.valid_test = valid_test
            self.com_valid_test = com_valid_test

        def get_com(self):
            return azlmbr.physics.RigidBodyRequestBus(bus.Event, "GetCenterOfMassWorld", self.id)

        def get_position(self):
            return azlmbr.components.TransformBus(bus.Event, "GetWorldTranslation", self.id)

    helper.init_idle()
    # 1) Open level
    helper.open_level("Physics", "C4976209_RigidBody_ComputesCOM")

    # 2) Enter game mode
    helper.enter_game_mode(Tests.enter_game_mode)

    # 3) Validate entities
    sphere_enabled = Shape("SphereEnabled", Tests.find_enabled_sphere, Tests.enabled_sphere_COM_expected)
    sphere_disabled = Shape("SphereDisabled", Tests.find_disabled_sphere, Tests.disabled_sphere_COM_expected)

    capsule_enabled = Shape("CapsuleEnabled", Tests.find_enabled_capsule, Tests.enabled_capsule_COM_expected)
    capsule_disabled = Shape("CapsuleDisabled", Tests.find_disabled_capsule, Tests.disabled_capsule_COM_expected)

    box_enabled = Shape("BoxEnabled", Tests.find_enabled_box, Tests.enabled_box_COM_expected)
    box_disabled = Shape("BoxDisabled", Tests.find_disabled_box, Tests.disabled_box_COM_expected)

    physics_asset_enabled = Shape(
        "PhysicsAssetEnabled", Tests.find_enabled_physics_asset, Tests.enabled_physics_asset_COM_expected
    )
    physics_asset_disabled = Shape(
        "PhysicsAssetDisabled", Tests.find_disabled_physics_asset, Tests.disabled_physics_asset_COM_expected
    )

    # physics asset is a special case, and thus not included
    enabled_shapes = [sphere_enabled, capsule_enabled, box_enabled]
    disabled_shapes = [sphere_disabled, capsule_disabled, box_disabled]

    all_shapes = enabled_shapes + disabled_shapes + [physics_asset_enabled, physics_asset_disabled]

    for shape in all_shapes:
        Report.critical_result(shape.valid_test, shape.id.IsValid())

    # 4) Check center of mass for each entity
    for enabled_shape in enabled_shapes:
        enabled_is_close = enabled_shape.com_local.IsClose(EXPECTED_COM, CLOSE_THRESHOLD)
        Report.result(enabled_shape.com_valid_test, enabled_is_close)

    for disabled_shape in disabled_shapes:
        disabled_is_close = disabled_shape.com_local.IsClose(CONTROL_COM, CLOSE_THRESHOLD)
        Report.result(disabled_shape.com_valid_test, disabled_is_close)

    # 5) Check center of mass for each physics asset
    enabled_is_close = physics_asset_enabled.com_local.IsClose(PHYSICS_ASSET_EXPECTED_COM, CLOSE_THRESHOLD)
    Report.result(physics_asset_enabled.com_valid_test, enabled_is_close)

    disabled_is_close = physics_asset_disabled.com_local.IsClose(CONTROL_COM, CLOSE_THRESHOLD)
    Report.result(physics_asset_disabled.com_valid_test, disabled_is_close)

    # 6) Exit game mode
    helper.exit_game_mode(Tests.exit_game_mode)


if __name__ == "__main__":
    import ImportPathHelper as imports
    imports.init()

    from editor_python_test_tools.utils import Report
    Report.start_test(C4976209_RigidBody_ComputesCOM)

"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.

SPDX-License-Identifier: Apache-2.0 OR MIT
"""


# Test case ID : C4976209
# Test Case Title : Verify that when Compute COM is enabled, the PhysX system computes the COM of the object on its own



# fmt: off
class Tests():
    enter_game_mode                     = ("Entered game mode",                                      "Failed to enter game mode")

    find_enabled_sphere                 = ("Enabled Sphere Found",                                   "Enabled Sphere not found")
    find_enabled_capsule                = ("Enabled Capsule Found",                                  "Enabled Capsule not found")
    find_enabled_box                    = ("Enabled Box Found",                                      "Enabled Box not found")
    find_enabled_physics_asset          = ("Enabled Physics Asset Found",                            "Enabled Physics Asset not found")

    find_disabled_sphere                = ("Disabled Sphere Found",                                  "Disabled Sphere not found")
    find_disabled_capsule               = ("Disabled Capsule Found",                                 "Disabled Capsule not found")
    find_disabled_box                   = ("Disabled Box Found",                                     "Disabled Box not found")
    find_disabled_physics_asset         = ("Disabled Physics Asset Found",                           "Disabled Physics Asset not found")

    enabled_sphere_COM_expected         = ("Enabled Sphere COM was close to expected value",         "Enabled Sphere COM was not close to expected value")
    enabled_capsule_COM_expected        = ("Enabled Capsule COM was close to expected value",        "Enabled Capsule COM was not close to expected value")
    enabled_box_COM_expected            = ("Enabled Box COM was close to expected value",            "Enabled Box COM was not close to expected value")
    enabled_physics_asset_COM_expected  = ("Enabled Physics Asset COM was close to expected value",  "Enabled Physics Asset COM was not close to expected value")

    disabled_sphere_COM_expected        = ("Disabled Sphere COM was close to expected value",        "Disabled Sphere COM was not close to expected value")
    disabled_capsule_COM_expected       = ("Disabled Capsule COM was close to expected value",       "Disabled Capsule COM was not close to expected value")
    disabled_box_COM_expected           = ("Disabled Box COM was close to expected value",           "Disabled Box not COM was not close to expected value")
    disabled_physics_asset_COM_expected = ("Disabled Physics Asset COM was close to expected value", "Disabled Physics Asset not COM was close to expected value")

    exit_game_mode                      = ("Exited game mode",                                       "Couldn't exit game mode")
# fmt: on


def C4976209_RigidBody_ComputesCOM():
    # type: () -> None
    """
    Summary:
    Runs an automated test to ensure when compute COM is enabled, that the COM is automatically calculated.

    Level Description:
    There are 4 sets of entities:
        Spheres (entity: SphereEnabled), (entity: SphereDisabled)
        Boxes (entity: BoxEnabled), (entity: BoxDisabled)
        Capsules (entity: CapsuleEnabled), (entity: CapsuleDisabled)
        Physics Assets with sedan mesh (entity: PhysicsAssetEnabled), (entity: PhysicsAssetDisabled)

    Each set has two entities, both of which are identical to one another - save for the Compute COM setting on their
    rigid body. One has it set to enabled, and the other has it set to disabled.

    Each entity has a rigid body and two PhysX colliders. The first collider has no offset. The second collider is
    positioned +2 units in the X direction.

    Expected Behavior:
    The entities with 'Compute COM' disabled will have local COM offsets at the objects origin ((0.0, 0.0, 0.0) Locally)
    The entities with 'Compute COM' enabled will have local COM offsets at the average position between the two
    colliders.
        For every entity that isn't a physics asset, that's +1 unit to the right (1/2 the offset value of the second
        collider). The physics asset has a mesh whose origin is not at the natural center of mass of the object,
        so we check its COM offset as a special case.

    Test Steps:
    1) Open level
    2) Enter game mode
    3) Validate entities
    4) Check center of mass for each entity
    5) Special Case: Check center of mass for each physics asset
    6) Exit game mode
    7) Close the editor

    Note:
    - This test file must be called from the Open 3D Engine Editor command terminal
    - Any passed and failed tests are written to the Editor.log file.
    - Parsing the file or running a log_monitor are required to observe the test results.

    :return: (None)
    """

    # Setup path
    import os
    import sys

    import ImportPathHelper as imports

    imports.init()

    from editor_python_test_tools.utils import Report
    from editor_python_test_tools.utils import TestHelper as helper

    import azlmbr
    import azlmbr.legacy.general as general
    import azlmbr.bus as bus
    import azlmbr.math as lymath

    CONTROL_COM = lymath.Vector3(0.0, 0.0, 0.0)
    EXPECTED_COM = lymath.Vector3(1.0, 0.0, 0.0)
    PHYSICS_ASSET_EXPECTED_COM = lymath.Vector3(1.0, -0.08, 0.43) # Derived from the sedan mesh specifically
    CLOSE_THRESHOLD = 0.01

    class Shape:
        def __init__(self, name, valid_test, com_valid_test):
            self.id = general.find_game_entity(name)
            self.center_of_mass = self.get_com()
            self.position = self.get_position()
            self.com_local = self.center_of_mass.Subtract(self.position)
            self.valid_test = valid_test
            self.com_valid_test = com_valid_test

        def get_com(self):
            return azlmbr.physics.RigidBodyRequestBus(bus.Event, "GetCenterOfMassWorld", self.id)

        def get_position(self):
            return azlmbr.components.TransformBus(bus.Event, "GetWorldTranslation", self.id)

    helper.init_idle()
    # 1) Open level
    helper.open_level("Physics", "C4976209_RigidBody_ComputesCOM")

    # 2) Enter game mode
    helper.enter_game_mode(Tests.enter_game_mode)

    # 3) Validate entities
    sphere_enabled = Shape("SphereEnabled", Tests.find_enabled_sphere, Tests.enabled_sphere_COM_expected)
    sphere_disabled = Shape("SphereDisabled", Tests.find_disabled_sphere, Tests.disabled_sphere_COM_expected)

    capsule_enabled = Shape("CapsuleEnabled", Tests.find_enabled_capsule, Tests.enabled_capsule_COM_expected)
    capsule_disabled = Shape("CapsuleDisabled", Tests.find_disabled_capsule, Tests.disabled_capsule_COM_expected)

    box_enabled = Shape("BoxEnabled", Tests.find_enabled_box, Tests.enabled_box_COM_expected)
    box_disabled = Shape("BoxDisabled", Tests.find_disabled_box, Tests.disabled_box_COM_expected)

    physics_asset_enabled = Shape(
        "PhysicsAssetEnabled", Tests.find_enabled_physics_asset, Tests.enabled_physics_asset_COM_expected
    )
    physics_asset_disabled = Shape(
        "PhysicsAssetDisabled", Tests.find_disabled_physics_asset, Tests.disabled_physics_asset_COM_expected
    )

    # physics asset is a special case, and thus not included
    enabled_shapes = [sphere_enabled, capsule_enabled, box_enabled]
    disabled_shapes = [sphere_disabled, capsule_disabled, box_disabled]

    all_shapes = enabled_shapes + disabled_shapes + [physics_asset_enabled, physics_asset_disabled]

    for shape in all_shapes:
        Report.critical_result(shape.valid_test, shape.id.IsValid())

    # 4) Check center of mass for each entity
    for enabled_shape in enabled_shapes:
        enabled_is_close = enabled_shape.com_local.IsClose(EXPECTED_COM, CLOSE_THRESHOLD)
        Report.result(enabled_shape.com_valid_test, enabled_is_close)

    for disabled_shape in disabled_shapes:
        disabled_is_close = disabled_shape.com_local.IsClose(CONTROL_COM, CLOSE_THRESHOLD)
        Report.result(disabled_shape.com_valid_test, disabled_is_close)

    # 5) Check center of mass for each physics asset
    enabled_is_close = physics_asset_enabled.com_local.IsClose(PHYSICS_ASSET_EXPECTED_COM, CLOSE_THRESHOLD)
    Report.result(physics_asset_enabled.com_valid_test, enabled_is_close)

    disabled_is_close = physics_asset_disabled.com_local.IsClose(CONTROL_COM, CLOSE_THRESHOLD)
    Report.result(physics_asset_disabled.com_valid_test, disabled_is_close)

    # 6) Exit game mode
    helper.exit_game_mode(Tests.exit_game_mode)


if __name__ == "__main__":
    import ImportPathHelper as imports
    imports.init()

    from editor_python_test_tools.utils import Report
    Report.start_test(C4976209_RigidBody_ComputesCOM)

Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.  SPDX-License-Identifier: Apache-2.0 OR MIT # Test case ID : C4976209 # Test Case Title : Verify that when Compute COM is enabled, the PhysX system computes the COM of the object on its own # fmt: off # fmt: on # type: () -> None Summary:     Runs an automated test to ensure when compute COM is enabled, that the COM is automatically calculated.      Level Description:     There are 4 sets of entities:         Spheres (entity: SphereEnabled), (entity: SphereDisabled)         Boxes (entity: BoxEnabled), (entity: BoxDisabled)         Capsules (entity: CapsuleEnabled), (entity: CapsuleDisabled)         Physics Assets with sedan mesh (entity: PhysicsAssetEnabled), (entity: PhysicsAssetDisabled)      Each set has two entities, both of which are identical to one another - save for the Compute COM setting on their     rigid body. One has it set to enabled, and the other has it set to disabled.      Each entity has a rigid body and two PhysX colliders. The first collider has no offset. The second collider is     positioned +2 units in the X direction.      Expected Behavior:     The entities with 'Compute COM' disabled will have local COM offsets at the objects origin ((0.0, 0.0, 0.0) Locally)     The entities with 'Compute COM' enabled will have local COM offsets at the average position between the two     colliders.         For every entity that isn't a physics asset, that's +1 unit to the right (1/2 the offset value of the second         collider). The physics asset has a mesh whose origin is not at the natural center of mass of the object,         so we check its COM offset as a special case.      Test Steps:     1) Open level     2) Enter game mode     3) Validate entities     4) Check center of mass for each entity     5) Special Case: Check center of mass for each physics asset     6) Exit game mode     7) Close the editor      Note:     - This test file must be called from the Open 3D Engine Editor command terminal     - Any passed and failed tests are written to the Editor.log file.     - Parsing the file or running a log_monitor are required to observe the test results.      :return: (None) # Setup path # Derived from the sedan mesh specifically # 1) Open level # 2) Enter game mode # 3) Validate entities # physics asset is a special case, and thus not included # 4) Check center of mass for each entity # 5) Check center of mass for each physics asset # 6) Exit game mode