class CreatePhysical(RDOperator):
class SelectPhysical(RDOperator):
class AssignPhysical(RDOperator):
class ComputePhysical(RDOperator):
    class SegmentAssociations(object):
class ComputeMass(RDOperator):
    class SegmentAssociations(object):
class DetachPhysical(RDOperator):
    def run(cls, frameName=""):
    def execute(self, context):
def assign_the_physics_frame_to_the_bone(context, frame, bone):
def just_create_the_physics_frame(context, name):
    def run(cls, frameName=""):
    def execute(self, context):
    def run(cls):
    def execute(self, context):
        def __init__(self):
        def __str__(self):
    def maybe_compute_inertia(self, bone, associations):
    def execute(self, context):
    def invoke(self, context, event):
        def __init__(self):
        def __str__(self):
    def maybe_compute_and_assign_mass_props(self, bone, associations):
    def execute(self, context):
    def invoke(self, context, event):
    def run(cls, frameName=""):
    def execute(self, context): @LogFunction
def check_armature(layout, context):
    """
    Helper function that checks whether a :ref:`armature` is selected. If not it draws a selection box.

    :param layout: Current GUI element (e.g., collapsible box, row, etc.)
    :param context: Blender context
    :return: Whether a robot model is selected (Bool).
    """
    if context.active_object is not None and context.active_object.type == "ARMATURE":
        return True
    else:
        layout.menu(menus.ModelMenu.bl_idname, text="Select Robot")
        return False class InfoBox(object):
    """
    This class collects messages (e.g., from :meth:`.operators.operators.RDOperator.poll`) and displays them
    with an info, either in a separated box or the current layout.

    See :ref:`gui_development` for an example.
    """

    global_messages = []

    def __init__(self, layout):
        """
        Constructor.

        :param layout: Blender gui element as passed to the
            :meth:`robot_designer_plugin.interface.main.UserInterface.draw` method.
        """
        self.messages = []
        self.layout = layout

    def add_message(self, message):
        """
        Adds a string message to the info box.

        :param message: message
        :type message: str
        """
        self.messages.append(message)

    def draw_info(self, additional_messages=[], icon=StringConstants.info):
        """
        Draws the info box onto the layout.

        :param additional_messages: Additional messages can be appended.
        """
        messages = self.messages + additional_messages
        if messages:

            column = self.layout.column(align=True)
            for text in set(messages):
                column.label(text=text, icon=icon)

    @classmethod
    def draw_global_info(cls, layout):

        if cls.global_messages:
            ib = InfoBox(layout)
            ib.draw_info(additional_messages=cls.global_messages, icon=StringConstants.error) def getSingleSegment(context):
    global info_list
    selected_segments = [i for i in context.active_object.data.bones if i.select]
    if len(selected_segments) == 1:
        return selected_segments[0]
    else:
        if len(selected_segments) == 0:
            info_list.append("No Segment selected, some operators not available")
        else:
            info_list.append("Multiple segments selected, some operators not available")
    return None class PhysicsBox(CollapsibleBase):
    property_name = "Physics_box" class LinkBox(CollapsibleBase):
    property_name = "link_box" class JointLimitsBox(CollapsibleBase):
    property_name = "joint_limits_box" class JointAxisBox(CollapsibleBase):
    property_name = "joint_axis_box" class JointDynamicsBox(CollapsibleBase):
    property_name = "joint_dynamics_box" class JointPhysicsBox(CollapsibleBase):
    property_name = "joint_physics_box" def LogFunction(func):
    """
    Logging / exception handling decorator for functions (use for draw function for instance).

    :param func: The function to decorate
    :return: A :term:`decorator`
    """

    def func_logger(self, context):

        # Execute the Operator
        try:
            return func(self, context)

        except Exception as e:
            gui_logger.error("Draw function in {} module threw an exception:\n {} {} {} {} {}".format(
                             func.__module__, EXCEPTION_MESSAGE, type(e).__name__, e, log_callstack(), log_callstack(back_trace=True)))
            InfoBox.global_messages.append(e)

    return func_logger
import bpy
from ..operators import dynamics
from .model import check_armature
from ..core.gui import InfoBox
from .helpers import getSingleSegment
from .helpers import (
    PhysicsBox,
    LinkBox,
    JointLimitsBox,
    JointAxisBox,
    JointDynamicsBox,
    JointPhysicsBox,
)
from ..core.logfile import LogFunction
#   2015:       Stefan Ulbrich (FZI), Gui redesigned
#   2015-01-16: Stefan Ulbrich (FZI), Major refactoring. Integrated into complex plugin framework.
#
# ######

# Blender imports

# RobotDesigner imports


@LogFunction
def draw(layout, context):
    """
    Draws the user interface for modifying the dynamic properties of a segment.

    :param layout: Current GUI element (e.g., collapsible box, row, etc.)
    :param context: Blender context
    """
    if not check_armature(layout, context):
        return

    single_segment = getSingleSegment(context)

    # link properties
    linkBox = LinkBox.get(layout, context, "Link")
    if linkBox:
        infoBox = InfoBox(linkBox)
        row = linkBox.column(align=True)

        dynamics.CreatePhysical.place_button(row, infoBox=infoBox)
        dynamics.ComputePhysical.place_button(row, infoBox=infoBox)
        dynamics.ComputeMass.place_button(row, infoBox=infoBox)

        objs = [
            o
            for o in context.active_object.children
            if o.RobotDesigner.tag == "PHYSICS_FRAME"
            and o.parent_bone == single_segment.name
        ]
        try:
            (obj,) = objs
            if obj and obj.RobotDesigner.tag == "PHYSICS_FRAME":
                frame_name = obj.name
                box = linkBox.box()
                box.label(
                    text="Mass Properties (" + single_segment.name + ")",
                    icon="MODIFIER",
                )
                frame = bpy.data.objects[frame_name]
                box.prop(frame.RobotDesigner.dynamics, "mass")
                box.separator()

                row_t = box.row(align=True)
                row_r = box.row(align=True)

                row_t.prop(bpy.data.objects[frame_name], "location", text="Translation")
                row_r.prop(
                    bpy.data.objects[frame_name], "rotation_euler", text="Rotation"
                )

                row0 = box.row(align=True)
                row1 = box.row(align=True)
                row2 = box.row(align=True)
                row3 = box.row(align=True)
                row0.label(text="Inertia Matrix")
                row1.prop(frame.RobotDesigner.dynamics, "inertiaXX")
                row2.prop(frame.RobotDesigner.dynamics, "inertiaXY")
                row3.prop(frame.RobotDesigner.dynamics, "inertiaXZ")
                row1.prop(frame.RobotDesigner.dynamics, "inertiaXY")
                row2.prop(frame.RobotDesigner.dynamics, "inertiaYY")
                row3.prop(frame.RobotDesigner.dynamics, "inertiaYZ")
                row1.prop(frame.RobotDesigner.dynamics, "inertiaXZ")
                row2.prop(frame.RobotDesigner.dynamics, "inertiaYZ")
                row3.prop(frame.RobotDesigner.dynamics, "inertiaZZ")
        except:
            pass

        linkBox.prop(
            bpy.context.active_bone.RobotDesigner.linkInfo,
            "link_self_collide",
            text="Self Collide",
        )
        linkBox.prop(
            bpy.context.active_bone.RobotDesigner.linkInfo, "gravity", text="Gravity"
        )

        infoBox.draw_info()

    # joint physics properties
    # Only shown for child segments. Unless root segment is connected to world.
    joint_box = PhysicsBox.get(layout, context, "Joint")
    if joint_box:

        if (context.active_bone.parent is None) and (
            context.active_bone.RobotDesigner.world is not True
        ):
            joint_box.label(text="No Joint defined for this Link.")
        else:
            axis_box = JointAxisBox.get(joint_box, context, "Axis")
            if axis_box:
                limit_box = JointLimitsBox.get(axis_box, context, "Limits")
                if limit_box:
                    limit_box.prop(
                        context.active_bone.RobotDesigner.dynamic_limits,
                        "isActive",
                        text="Active Joint Dynamic Limits",
                    )

                    if context.active_bone.RobotDesigner.dynamic_limits.isActive:
                        limit_box.prop(
                            context.active_bone.RobotDesigner.dynamic_limits, "maxVelocity"
                        )
                        limit_box.prop(
                            context.active_bone.RobotDesigner.dynamic_limits, "maxTorque"
                        )

                    ## URDF only
                    # limit_box.prop(context.active_bone.RobotDesigner.controller, "acceleration")
                    # limit_box.prop(context.active_bone.RobotDesigner.controller, "deceleration")


                dynamics_box = JointDynamicsBox.get(axis_box, context, "Dynamics")