Пример #1
0
        public override void initTest(bool deserialized)
        {
            if (deserialized)
            {
                return;
            }
            Body ground = null;
            {
                BodyDef bd = new BodyDef();
                ground = getWorld().createBody(bd);

                EdgeShape shape = new EdgeShape();
                shape.set(new Vec2(-40.0f, 0.0f), new Vec2(40.0f, 0.0f));
                ground.createFixture(shape, 0.0f);
            }

            {
                PolygonShape shape = new PolygonShape();
                shape.setAsBox(2.0f, 0.5f);

                BodyDef bd = new BodyDef();
                bd.type = BodyType.DYNAMIC;
                bd.position.set(-10.0f, 10.0f);
                bd.angle = 0.5f*MathUtils.PI;
                bd.allowSleep = false;
                Body body = getWorld().createBody(bd);
                body.createFixture(shape, 5.0f);

                PrismaticJointDef pjd = new PrismaticJointDef();

                // Bouncy limit
                Vec2 axis = new Vec2(2.0f, 1.0f);
                axis.normalize();
                pjd.initialize(ground, body, new Vec2(0.0f, 0.0f), axis);

                // Non-bouncy limit
                // pjd.Initialize(ground, body, Vec2(-10.0f, 10.0f), Vec2(1.0f, 0.0f));

                pjd.motorSpeed = 10.0f;
                pjd.maxMotorForce = 10000.0f;
                pjd.enableMotor = true;
                pjd.lowerTranslation = 0.0f;
                pjd.upperTranslation = 20.0f;
                pjd.enableLimit = true;

                m_joint = (PrismaticJoint) getWorld().createJoint(pjd);
            }
        }
Пример #2
0
        public override void initTest(bool argDeserialized)
        {
            Body ground = null;
            {
                BodyDef bd = new BodyDef();
                ground = getWorld().createBody(bd);

                EdgeShape shape = new EdgeShape();
                shape.set(new Vec2(50.0f, 0.0f), new Vec2(-50.0f, 0.0f));
                ground.createFixture(shape, 0.0f);
            }

            {
                CircleShape circle1 = new CircleShape();
                circle1.m_radius = 1.0f;

                PolygonShape box = new PolygonShape();
                box.setAsBox(0.5f, 5.0f);

                CircleShape circle2 = new CircleShape();
                circle2.m_radius = 2.0f;

                BodyDef bd1 = new BodyDef();
                bd1.type = BodyType.STATIC;
                bd1.position.set(10.0f, 9.0f);
                Body body1 = m_world.createBody(bd1);
                body1.createFixture(circle1, 5.0f);

                BodyDef bd2 = new BodyDef();
                bd2.type = BodyType.DYNAMIC;
                bd2.position.set(10.0f, 8.0f);
                Body body2 = m_world.createBody(bd2);
                body2.createFixture(box, 5.0f);

                BodyDef bd3 = new BodyDef();
                bd3.type = BodyType.DYNAMIC;
                bd3.position.set(10.0f, 6.0f);
                Body body3 = m_world.createBody(bd3);
                body3.createFixture(circle2, 5.0f);

                RevoluteJointDef jd1 = new RevoluteJointDef();
                jd1.initialize(body2, body1, bd1.position);
                Joint joint1 = m_world.createJoint(jd1);

                RevoluteJointDef jd2 = new RevoluteJointDef();
                jd2.initialize(body2, body3, bd3.position);
                Joint joint2 = m_world.createJoint(jd2);

                GearJointDef jd4 = new GearJointDef();
                jd4.bodyA = body1;
                jd4.bodyB = body3;
                jd4.joint1 = joint1;
                jd4.joint2 = joint2;
                jd4.ratio = circle2.m_radius/circle1.m_radius;
                m_world.createJoint(jd4);
            }

            {
                CircleShape circle1 = new CircleShape();
                circle1.m_radius = 1.0f;

                CircleShape circle2 = new CircleShape();
                circle2.m_radius = 2.0f;

                PolygonShape box = new PolygonShape();
                box.setAsBox(0.5f, 5.0f);

                BodyDef bd1 = new BodyDef();
                bd1.type = BodyType.DYNAMIC;
                bd1.position.set(-3.0f, 12.0f);
                Body body1 = m_world.createBody(bd1);
                body1.createFixture(circle1, 5.0f);

                RevoluteJointDef jd1 = new RevoluteJointDef();
                jd1.bodyA = ground;
                jd1.bodyB = body1;
                ground.getLocalPointToOut(bd1.position, ref jd1.localAnchorA);
                body1.getLocalPointToOut(bd1.position, ref jd1.localAnchorB);
                jd1.referenceAngle = body1.getAngle() - ground.getAngle();
                m_joint1 = (RevoluteJoint) m_world.createJoint(jd1);

                BodyDef bd2 = new BodyDef();
                bd2.type = BodyType.DYNAMIC;
                bd2.position.set(0.0f, 12.0f);
                Body body2 = m_world.createBody(bd2);
                body2.createFixture(circle2, 5.0f);

                RevoluteJointDef jd2 = new RevoluteJointDef();
                jd2.initialize(ground, body2, bd2.position);
                m_joint2 = (RevoluteJoint) m_world.createJoint(jd2);

                BodyDef bd3 = new BodyDef();
                bd3.type = BodyType.DYNAMIC;
                bd3.position.set(2.5f, 12.0f);
                Body body3 = m_world.createBody(bd3);
                body3.createFixture(box, 5.0f);

                PrismaticJointDef jd3 = new PrismaticJointDef();
                jd3.initialize(ground, body3, bd3.position, new Vec2(0.0f, 1.0f));
                jd3.lowerTranslation = -5.0f;
                jd3.upperTranslation = 5.0f;
                jd3.enableLimit = true;

                m_joint3 = (PrismaticJoint) m_world.createJoint(jd3);

                GearJointDef jd4 = new GearJointDef();
                jd4.bodyA = body1;
                jd4.bodyB = body2;
                jd4.joint1 = m_joint1;
                jd4.joint2 = m_joint2;
                jd4.ratio = circle2.m_radius/circle1.m_radius;
                m_joint4 = (GearJoint) m_world.createJoint(jd4);

                GearJointDef jd5 = new GearJointDef();
                jd5.bodyA = body2;
                jd5.bodyB = body3;
                jd5.joint1 = m_joint2;
                jd5.joint2 = m_joint3;
                jd5.ratio = 1f/circle2.m_radius;
                m_joint5 = (GearJoint) m_world.createJoint(jd5);
            }
        }
Пример #3
0
        internal PrismaticJoint(IWorldPool argWorld, PrismaticJointDef def)
            : base(argWorld, def)
        {
            m_localAnchorA = new Vec2(def.localAnchorA);
            m_localAnchorB = new Vec2(def.localAnchorB);
            m_localXAxisA = new Vec2(def.localAxisA);
            m_localXAxisA.normalize();
            m_localYAxisA = new Vec2();
            Vec2.crossToOutUnsafe(1f, m_localXAxisA, ref m_localYAxisA);
            m_referenceAngle = def.referenceAngle;

            m_impulse = new Vec3();
            m_motorMass = 0.0f;
            m_motorImpulse = 0.0f;

            m_lowerTranslation = def.lowerTranslation;
            m_upperTranslation = def.upperTranslation;
            m_maxMotorForce = def.maxMotorForce;
            m_motorSpeed = def.motorSpeed;
            m_enableLimit = def.enableLimit;
            m_enableMotor = def.enableMotor;
            m_limitState = LimitState.INACTIVE;

            m_K = new Mat33();
            m_axis = new Vec2();
            m_perp = new Vec2();
        }
Пример #4
0
        public override void initTest(bool deserialized)
        {
            if (deserialized)
            {
                return;
            }
            // Ground body
            {
                EdgeShape shape = new EdgeShape();
                shape.set(new Vec2(-40.0f, 0.0f), new Vec2(40.0f, 0.0f));

                FixtureDef sd = new FixtureDef();
                sd.shape = shape;
                sd.friction = 0.3f;

                BodyDef bd = new BodyDef();
                Body ground = getWorld().createBody(bd);
                ground.createFixture(sd);
            }

            // Small triangle
            Vec2[] vertices = new Vec2[3];
            vertices[0] = new Vec2(-1.0f, 0.0f);
            vertices[1] = new Vec2(1.0f, 0.0f);
            vertices[2] = new Vec2(0.0f, 2.0f);
            PolygonShape polygon = new PolygonShape();
            polygon.set(vertices, 3);

            FixtureDef triangleShapeDef = new FixtureDef();
            triangleShapeDef.shape = polygon;
            triangleShapeDef.density = 1.0f;

            triangleShapeDef.filter.groupIndex = k_smallGroup;
            triangleShapeDef.filter.categoryBits = k_triangleCategory;
            triangleShapeDef.filter.maskBits = k_triangleMask;

            BodyDef triangleBodyDef = new BodyDef();
            triangleBodyDef.type = BodyType.DYNAMIC;
            triangleBodyDef.position.set(-5.0f, 2.0f);

            Body body1 = getWorld().createBody(triangleBodyDef);
            body1.createFixture(triangleShapeDef);

            // Large triangle (recycle definitions)
            vertices[0].mulLocal(2.0f);
            vertices[1].mulLocal(2.0f);
            vertices[2].mulLocal(2.0f);
            polygon.set(vertices, 3);
            triangleShapeDef.filter.groupIndex = k_largeGroup;
            triangleBodyDef.position.set(-5.0f, 6.0f);
            triangleBodyDef.fixedRotation = true; // look at me!

            Body body2 = getWorld().createBody(triangleBodyDef);
            body2.createFixture(triangleShapeDef);

            {
                BodyDef bd = new BodyDef();
                bd.type = BodyType.DYNAMIC;
                bd.position.set(-5.0f, 10.0f);
                Body body = getWorld().createBody(bd);

                PolygonShape p = new PolygonShape();
                p.setAsBox(0.5f, 1.0f);
                body.createFixture(p, 1.0f);

                PrismaticJointDef jd = new PrismaticJointDef();
                jd.bodyA = body2;
                jd.bodyB = body;
                jd.enableLimit = true;
                jd.localAnchorA.set(0.0f, 4.0f);
                jd.localAnchorB.setZero();
                jd.localAxisA.set(0.0f, 1.0f);
                jd.lowerTranslation = -1.0f;
                jd.upperTranslation = 1.0f;

                getWorld().createJoint(jd);
            }

            // Small box
            polygon.setAsBox(1.0f, 0.5f);
            FixtureDef boxShapeDef = new FixtureDef();
            boxShapeDef.shape = polygon;
            boxShapeDef.density = 1.0f;
            boxShapeDef.restitution = 0.1f;

            boxShapeDef.filter.groupIndex = k_smallGroup;
            boxShapeDef.filter.categoryBits = k_boxCategory;
            boxShapeDef.filter.maskBits = k_boxMask;

            BodyDef boxBodyDef = new BodyDef();
            boxBodyDef.type = BodyType.DYNAMIC;
            boxBodyDef.position.set(0.0f, 2.0f);

            Body body3 = getWorld().createBody(boxBodyDef);
            body3.createFixture(boxShapeDef);

            // Large box (recycle definitions)
            polygon.setAsBox(2.0f, 1.0f);
            boxShapeDef.filter.groupIndex = k_largeGroup;
            boxBodyDef.position.set(0.0f, 6.0f);

            Body body4 = getWorld().createBody(boxBodyDef);
            body4.createFixture(boxShapeDef);

            // Small circle
            CircleShape circle = new CircleShape();
            circle.m_radius = 1.0f;

            FixtureDef circleShapeDef = new FixtureDef();
            circleShapeDef.shape = circle;
            circleShapeDef.density = 1.0f;

            circleShapeDef.filter.groupIndex = k_smallGroup;
            circleShapeDef.filter.categoryBits = k_circleCategory;
            circleShapeDef.filter.maskBits = k_circleMask;

            BodyDef circleBodyDef = new BodyDef();
            circleBodyDef.type = BodyType.DYNAMIC;
            circleBodyDef.position.set(5.0f, 2.0f);

            Body body5 = getWorld().createBody(circleBodyDef);
            body5.createFixture(circleShapeDef);

            // Large circle
            circle.m_radius *= 2.0f;
            circleShapeDef.filter.groupIndex = k_largeGroup;
            circleBodyDef.position.set(5.0f, 6.0f);

            Body body6 = getWorld().createBody(circleBodyDef);
            body6.createFixture(circleShapeDef);
        }
Пример #5
0
        public override void initTest(bool deserialized)
        {
            m_speed = 3.0f;

            if (deserialized)
            {
                return;
            }

            Body ground = null;
            {
                BodyDef bd = new BodyDef();
                ground = getWorld().createBody(bd);

                EdgeShape shape = new EdgeShape();
                shape.set(new Vec2(-20.0f, 0.0f), new Vec2(20.0f, 0.0f));

                FixtureDef fd = new FixtureDef();
                fd.shape = shape;

                ground.createFixture(fd);
            }

            // Define attachment
            {
                BodyDef bd = new BodyDef();
                bd.type = BodyType.DYNAMIC;
                bd.position.set(0.0f, 3.0f);
                m_attachment = getWorld().createBody(bd);

                PolygonShape shape = new PolygonShape();
                shape.setAsBox(0.5f, 2.0f);
                m_attachment.createFixture(shape, 2.0f);
            }

            // Define platform
            {
                BodyDef bd = new BodyDef();
                bd.type = BodyType.DYNAMIC;
                bd.position.set(-4.0f, 5.0f);
                m_platform = getWorld().createBody(bd);

                PolygonShape shape = new PolygonShape();
                shape.setAsBox(0.5f, 4.0f, new Vec2(4.0f, 0.0f), 0.5f*MathUtils.PI);

                FixtureDef fd = new FixtureDef();
                fd.shape = shape;
                fd.friction = 0.6f;
                fd.density = 2.0f;
                m_platform.createFixture(fd);

                RevoluteJointDef rjd = new RevoluteJointDef();
                rjd.initialize(m_attachment, m_platform, new Vec2(0.0f, 5.0f));
                rjd.maxMotorTorque = 50.0f;
                rjd.enableMotor = true;
                getWorld().createJoint(rjd);

                PrismaticJointDef pjd = new PrismaticJointDef();
                pjd.initialize(ground, m_platform, new Vec2(0.0f, 5.0f), new Vec2(1.0f, 0.0f));

                pjd.maxMotorForce = 1000.0f;
                pjd.enableMotor = true;
                pjd.lowerTranslation = -10.0f;
                pjd.upperTranslation = 10.0f;
                pjd.enableLimit = true;

                getWorld().createJoint(pjd);

            }

            // .create a payload
            {
                BodyDef bd = new BodyDef();
                bd.type = BodyType.DYNAMIC;
                bd.position.set(0.0f, 8.0f);
                Body body = getWorld().createBody(bd);

                PolygonShape shape = new PolygonShape();
                shape.setAsBox(0.75f, 0.75f);

                FixtureDef fd = new FixtureDef();
                fd.shape = shape;
                fd.friction = 0.6f;
                fd.density = 2.0f;

                body.createFixture(fd);
            }
        }
Пример #6
0
        public override void initTest(bool argDeserialized)
        {
            Body ground = null;
            {
                BodyDef bd = new BodyDef();
                ground = getWorld().createBody(bd);

                EdgeShape shape = new EdgeShape();
                shape.set(new Vec2(-40.0f, 0.0f), new Vec2(40.0f, 0.0f));
                ground.createFixture(shape, 0.0f);
            }

            {
                Body prevBody = ground;

                // Define crank.
                {
                    PolygonShape shape = new PolygonShape();
                    shape.setAsBox(0.5f, 2.0f);

                    BodyDef bd = new BodyDef();
                    bd.type = BodyType.DYNAMIC;
                    bd.position.set(0.0f, 7.0f);
                    Body body = getWorld().createBody(bd);
                    body.createFixture(shape, 2.0f);

                    RevoluteJointDef rjd = new RevoluteJointDef();
                    rjd.initialize(prevBody, body, new Vec2(0.0f, 5.0f));
                    rjd.motorSpeed = 1.0f*MathUtils.PI;
                    rjd.maxMotorTorque = 10000.0f;
                    rjd.enableMotor = true;
                    m_joint1 = (RevoluteJoint) getWorld().createJoint(rjd);

                    prevBody = body;
                }

                // Define follower.
                {
                    PolygonShape shape = new PolygonShape();
                    shape.setAsBox(0.5f, 4.0f);

                    BodyDef bd = new BodyDef();
                    bd.type = BodyType.DYNAMIC;
                    bd.position.set(0.0f, 13.0f);
                    Body body = getWorld().createBody(bd);
                    body.createFixture(shape, 2.0f);

                    RevoluteJointDef rjd = new RevoluteJointDef();
                    rjd.initialize(prevBody, body, new Vec2(0.0f, 9.0f));
                    rjd.enableMotor = false;
                    getWorld().createJoint(rjd);

                    prevBody = body;
                }

                // Define piston
                {
                    PolygonShape shape = new PolygonShape();
                    shape.setAsBox(1.5f, 1.5f);

                    BodyDef bd = new BodyDef();
                    bd.type = BodyType.DYNAMIC;
                    bd.fixedRotation = true;
                    bd.position.set(0.0f, 17.0f);
                    Body body = getWorld().createBody(bd);
                    body.createFixture(shape, 2.0f);

                    RevoluteJointDef rjd = new RevoluteJointDef();
                    rjd.initialize(prevBody, body, new Vec2(0.0f, 17.0f));
                    getWorld().createJoint(rjd);

                    PrismaticJointDef pjd = new PrismaticJointDef();
                    pjd.initialize(ground, body, new Vec2(0.0f, 17.0f), new Vec2(0.0f, 1.0f));

                    pjd.maxMotorForce = 1000.0f;
                    pjd.enableMotor = false;

                    m_joint2 = (PrismaticJoint) getWorld().createJoint(pjd);
                }

                // Create a payload
                {
                    PolygonShape shape = new PolygonShape();
                    shape.setAsBox(1.5f, 1.5f);

                    BodyDef bd = new BodyDef();
                    bd.type = BodyType.DYNAMIC;
                    bd.position.set(0.0f, 23.0f);
                    Body body = getWorld().createBody(bd);
                    body.createFixture(shape, 2.0f);
                }
            }
        }
Пример #7
0
        public override void initTest(bool deserialized)
        {
            if (deserialized)
            {
                return;
            }
            World world = getWorld();
            Body ground = null;
            {
                BodyDef bd = new BodyDef();
                ground = getWorld().createBody(bd);

                PolygonShape shape = new PolygonShape();
                shape.setAsBox(5.0f, 100.0f);
                bd = new BodyDef();
                bd.type = BodyType.STATIC;
                FixtureDef sides = new FixtureDef();
                sides.shape = shape;
                sides.density = 0;
                sides.friction = 0;
                sides.restitution = .8f;
                sides.filter.categoryBits = 4;
                sides.filter.maskBits = 2;

                bd.position.set(-10.01f, 50.0f);
                Body bod = world.createBody(bd);
                bod.createFixture(sides);
                bd.position.set(10.01f, 50.0f);
                bod = world.createBody(bd);
                bod.createFixture(sides);
            }

            // turney
            {
                CircleShape cd;
                FixtureDef fd = new FixtureDef();
                BodyDef bd = new BodyDef();
                bd.type = BodyType.DYNAMIC;
                int numPieces = 5;
                float radius = 4f;
                bd.position = new Vec2(0.0f, 25.0f);
                Body body = getWorld().createBody(bd);
                for (int i = 0; i < numPieces; i++)
                {
                    cd = new CircleShape();
                    cd.m_radius = .5f;
                    fd.shape = cd;
                    fd.density = 25;
                    fd.friction = .1f;
                    fd.restitution = .9f;
                    float xPos = radius*(float) System.Math.Cos(2f*System.Math.PI*(i/(float) (numPieces)));
                    float yPos = radius*(float) System.Math.Sin(2f*System.Math.PI*(i/(float) (numPieces)));
                    cd.m_p.set(xPos, yPos);

                    body.createFixture(fd);
                }

                RevoluteJointDef rjd = new RevoluteJointDef();
                rjd.initialize(body, getGroundBody(), body.getPosition());
                rjd.motorSpeed = MathUtils.PI;
                rjd.maxMotorTorque = 1000000.0f;
                rjd.enableMotor = true;
                getWorld().createJoint(rjd);
            }

            {
                Body prevBody = ground;

                // Define crank.
                {
                    PolygonShape shape = new PolygonShape();
                    shape.setAsBox(0.5f, 2.0f);

                    BodyDef bd = new BodyDef();
                    bd.type = BodyType.DYNAMIC;
                    bd.position.set(0.0f, 7.0f);
                    Body body = getWorld().createBody(bd);
                    body.createFixture(shape, 2.0f);

                    RevoluteJointDef rjd = new RevoluteJointDef();
                    rjd.initialize(prevBody, body, new Vec2(0.0f, 5.0f));
                    rjd.motorSpeed = 1.0f*MathUtils.PI;
                    rjd.maxMotorTorque = 20000;
                    rjd.enableMotor = true;
                    getWorld().createJoint(rjd);

                    prevBody = body;
                }

                // Define follower.
                {
                    PolygonShape shape = new PolygonShape();
                    shape.setAsBox(0.5f, 4.0f);

                    BodyDef bd = new BodyDef();
                    bd.type = BodyType.DYNAMIC;
                    bd.position.set(0.0f, 13.0f);
                    Body body = getWorld().createBody(bd);
                    body.createFixture(shape, 2.0f);

                    RevoluteJointDef rjd = new RevoluteJointDef();
                    rjd.initialize(prevBody, body, new Vec2(0.0f, 9.0f));
                    rjd.enableMotor = false;
                    getWorld().createJoint(rjd);

                    prevBody = body;
                }

                // Define piston
                {
                    PolygonShape shape = new PolygonShape();
                    shape.setAsBox(7f, 2f);

                    BodyDef bd = new BodyDef();
                    bd.type = BodyType.DYNAMIC;
                    bd.position.set(0.0f, 17.0f);
                    Body body = getWorld().createBody(bd);
                    FixtureDef piston = new FixtureDef();
                    piston.shape = shape;
                    piston.density = 2;
                    piston.filter.categoryBits = 1;
                    piston.filter.maskBits = 2;
                    body.createFixture(piston);
                    body.setBullet(false);

                    RevoluteJointDef rjd = new RevoluteJointDef();
                    rjd.initialize(prevBody, body, new Vec2(0.0f, 17.0f));
                    getWorld().createJoint(rjd);

                    PrismaticJointDef pjd = new PrismaticJointDef();
                    pjd.initialize(ground, body, new Vec2(0.0f, 17.0f), new Vec2(0.0f, 1.0f));

                    pjd.maxMotorForce = 1000.0f;
                    pjd.enableMotor = true;

                    getWorld().createJoint(pjd);
                }

                // Create a payload
                {
                    PolygonShape sd = new PolygonShape();
                    BodyDef bd = new BodyDef();
                    bd.type = BodyType.DYNAMIC;
                    FixtureDef fixture = new FixtureDef();
                    Body body;
                    for (int i = 0; i < 100; ++i)
                    {
                        sd.setAsBox(0.4f, 0.3f);
                        bd.position.set(-1.0f, 23.0f + i);

                        bd.bullet = bullet;
                        body = world.createBody(bd);
                        fixture.shape = sd;
                        fixture.density = .1f;
                        fixture.filter.categoryBits = 2;
                        fixture.filter.maskBits = 1 | 4 | 2;
                        body.createFixture(fixture);
                    }

                    CircleShape cd = new CircleShape();
                    cd.m_radius = 0.36f;
                    for (int i = 0; i < 100; ++i)
                    {
                        bd.position.set(1.0f, 23.0f + i);
                        bd.bullet = bullet;
                        fixture.shape = cd;
                        fixture.density = 2f;
                        fixture.filter.categoryBits = 2;
                        fixture.filter.maskBits = 1 | 4 | 2;
                        body = world.createBody(bd);
                        body.createFixture(fixture);
                    }

                    float angle = 0.0f;
                    float delta = MathUtils.PI/3.0f;
                    Vec2[] vertices = new Vec2[6];
                    for (int i = 0; i < 6; ++i)
                    {
                        vertices[i] = new Vec2(0.3f*MathUtils.cos(angle), 0.3f*MathUtils.sin(angle));
                        angle += delta;
                    }

                    PolygonShape shape = new PolygonShape();
                    shape.set(vertices, 6);

                    for (int i = 0; i < 100; ++i)
                    {
                        bd.position.set(0f, 23.0f + i);
                        bd.type = BodyType.DYNAMIC;
                        bd.fixedRotation = true;
                        bd.bullet = bullet;
                        fixture.shape = shape;
                        fixture.density = 1f;
                        fixture.filter.categoryBits = 2;
                        fixture.filter.maskBits = 1 | 4 | 2;
                        body = world.createBody(bd);
                        body.createFixture(fixture);
                    }
                }
            }
        }