إنشاء الكيانات والتحكّم فيها وإدارتها

تتيح لك حزمة تطوير البرامج (SDK) لمنصة Jetpack XR استخدام Jetpack SceneCore لإنشاء مثيلات Entity والتحكّم فيها وإدارتها، مثل التصاميم الثلاثية الأبعاد والفيديوهات المجسمة وPanelEntity باستخدام Jetpack SceneCore.

تستخدم Jetpack SceneCore نمطَين شائعَين من أنماط البنية لدعم تطوير التطبيقات الثلاثية الأبعاد، وهما مخطط المشهد ونظام الكيانات والمكوّنات (ECS).

استخدام الرسم البياني للمشهد لإنشاء الكيانات والتحكّم فيها

لإنشاء عناصر والتحكّم فيها في مساحة ثلاثية الأبعاد، يمكنك استخدام واجهة برمجة التطبيقات Session في Jetpack SceneCore للوصول إلى الرسم البياني للمشهد. يتوافق الرسم البياني للمشهد مع العالم الحقيقي للمستخدم، ويتيح لك تنظيم العناصر الثلاثية الأبعاد، مثل اللوحات والنماذج الثلاثية الأبعاد، في بنية هرمية، والاحتفاظ بحالة هذه العناصر.

بعد الحصول على إذن الوصول إلى الرسم البياني للمشهد، يمكنك استخدام واجهات برمجة التطبيقات في Jetpack Compose for XR لإنشاء واجهة مستخدم مكانية (على سبيل المثال، مثيلات SpatialPanel وOrbiter) ضمن الرسم البياني للمشهد. بالنسبة إلى المحتوى الثلاثي الأبعاد، مثل التصاميم الثلاثية الأبعاد، يمكنك الوصول إلى الجلسة مباشرةً. لمزيد من المعلومات، يُرجى الاطّلاع على لمحة عن ActivitySpace في هذه الصفحة.

نظام مكونات الكيانات

يتبع نظام الكيان والمكوّن مبدأ التركيب بدلاً من الوراثة. يمكنك توسيع نطاق سلوك الكيانات من خلال إرفاق مكونات تحدد السلوك، ما يتيح لك تطبيق السلوك نفسه على أنواع مختلفة من الكيانات. لمزيد من المعلومات، يُرجى الاطّلاع على إضافة سلوك مشترك إلى الكيانات في هذه الصفحة.

لمحة عن ActivitySpace

يحتوي كل Session على ActivitySpace يتم إنشاؤه تلقائيًا باستخدام Session. ActivitySpace هو Entity المستوى الأعلى في الرسم البياني للمشهد.

يمثّل ActivitySpace مساحة ثلاثية الأبعاد بنظام إحداثيات أيمن (يشير المحور x إلى اليمين، ويشير المحور y إلى الأعلى، ويشير المحور z إلى الخلف بالنسبة إلى نقطة الأصل) ووحدات قياس بالمتر تتطابق مع العالم الحقيقي. إنّ نقطة الأصل في ActivitySpace اختيارية إلى حد ما (إذ يمكن للمستخدمين إعادة ضبط موضع ActivitySpace في العالم الحقيقي)، لذا يُنصح بوضع المحتوى بالنسبة إلى بعضه البعض بدلاً من وضعه بالنسبة إلى نقطة الأصل.

التعامل مع الكيانات

تُعد الكيانات عنصرًا أساسيًا في SceneCore. معظم العناصر التي يراها المستخدم ويتفاعل معها هي كيانات تمثّل لوحات ونماذج ثلاثية الأبعاد وغير ذلك.

بما أنّ ActivitySpace هي العقدة ذات المستوى الأعلى في الرسم البياني للمشهد، يتم تلقائيًا وضع جميع الكيانات الجديدة مباشرةً في ActivitySpace. يمكنك نقل العناصر على طول الرسم البياني للمشهد من خلال استدعاء setParent() أو addChild().

تتضمّن الكيانات بعض السلوكيات التلقائية للأشياء التي تنطبق على جميع الكيانات، مثل تغيير الموضع أو الدوران أو مستوى الظهور. تتضمّن بعض الفئات الفرعية، مثل GltfModelEntity، سلوكيات إضافية تتوافق مع الفئة الفرعية.Entity

تعديل الكيانات

عند إجراء تغيير على سمة Entity تنتمي إلى فئة Entity الأساسية، سيتم تطبيق هذا التغيير على جميع العناصر التابعة لها. على سبيل المثال، سيؤدي تعديل Pose لعنصر رئيسي Entity إلى تطبيق التعديل نفسه على جميع العناصر الفرعية. لا يؤثر إجراء تغيير في Entity فرعي في Entity الرئيسي.

يمثّل Pose الموقع الجغرافي والتدوير الخاصَّين بالعنصر داخل المساحة الثلاثية الأبعاد. الموقع الجغرافي هو Vector3 يتألف من المواضع الرقمية x وy وz. يتم تمثيل الدوران بواسطة Quaternion. يكون موضع Entity دائمًا بالنسبة إلى العنصر الرئيسي. بعبارة أخرى، سيتم وضع Entity الذي يكون موقعه هو (0, 0, 0) في نقطة الأصل الخاصة بالكيان الرئيسي.

// Place the entity forward 2 meters
val newPosition = Vector3(0f, 0f, -2f)
// Rotate the entity by 180 degrees on the up axis (upside-down)
val newOrientation = Quaternion.fromEulerAngles(0f, 0f, 180f)
// Update the position and rotation on the entity
entity.setPose(Pose(newPosition, newOrientation))

لتغيير مستوى ظهور Entity، استخدِم setHidden().

// Hide the entity
entity.setHidden(true)

لتغيير حجم Entity مع الحفاظ على شكله العام، استخدِم setScale().

// Double the size of the entity
entity.setScale(2f)

إضافة سلوك مشترك إلى الكيانات

يمكنك استخدام المكوّنات التالية لإضافة سلوك شائع إلى الكيانات:

  • MovableComponent: يسمح للمستخدم بنقل الكيانات
  • ResizableComponent: يسمح للمستخدم بتغيير حجم العناصر باستخدام أنماط متسقة لواجهة المستخدم
  • InteractableComponent: تتيح لك تسجيل أحداث الإدخال للتفاعلات المخصّصة

يجب إنشاء مثيل للمكوّنات من خلال طريقة الإنشاء المناسبة في الفئة Session. على سبيل المثال، لإنشاء ResizableComponent، استخدِم الأمر ResizableComponent.create().

لإضافة سلوك المكوّن المحدّد إلى Entity، استخدِم الطريقة addComponent().

استخدام MovableComponent لجعل الكائن قابلاً للنقل من قِبل المستخدم

تسمح MovableComponent للمستخدم بتحريك Entity. يمكنك أيضًا تحديد ما إذا كان يمكن تثبيت الكيان على نوع سطح معيّن، مثل الأسطح الأفقية أو الرأسية، أو الأسطح الدلالية المحدّدة، مثل الطاولة أو الجدار أو السقف. لتحديد خيارات التثبيت، حدِّد مجموعة من AnchorPlacement عند إنشاء MovableComponent.

في ما يلي مثال على عنصر يمكن نقله وتثبيته على أي سطح عمودي وعلى الأسطح الأفقية للأرضية والسقف فقط.

val anchorPlacement = AnchorPlacement.createForPlanes(
    planeTypeFilter = setOf(PlaneSemantic.FLOOR, PlaneSemantic.TABLE),
    planeSemanticFilter = setOf(PlaneType.VERTICAL)
)

val movableComponent = MovableComponent.create(
    session = session,
    systemMovable = false,
    scaleInZ = false,
    anchorPlacement = setOf(anchorPlacement)
)
entity.addComponent(movableComponent)

عندما يحرك المستخدم العنصر، تعدّل المَعلمة scaleInZ تلقائيًا مقياس العنصر أثناء ابتعاده عن المستخدم بطريقة مشابهة لطريقة تعديل النظام لمقاييس اللوحات في المساحة الرئيسية. بسبب طبيعة "التتالي" لنظام مكونات الكيانات، سيؤثر مقياس العنصر الأصل في جميع العناصر التابعة له.

استخدِم ResizableComponent لجعل حجم Entity قابلاً للتغيير من قِبل المستخدم

تتيح ResizableComponent للمستخدمين تغيير حجم Entity. يتضمّن ResizableComponent إشارات مرئية للتفاعل تدعو المستخدم إلى تغيير حجم Entity. عند إنشاء ResizableComponent، يمكنك تحديد حد أدنى أو أقصى للحجم (بالمتر). يمكنك أيضًا تحديد نسبة عرض إلى ارتفاع ثابتة عند تغيير الحجم، وذلك لكي يتم تغيير حجم العرض والارتفاع بشكل متناسب مع بعضهما البعض.

عند استخدام ResizableComponent، يجب تحديد ResizeListener للاستجابة لأحداث تغيير الحجم المحدّدة، مثل onResizeUpdate أو onResizeEnd.

في ما يلي مثال على استخدام السمة ResizableComponent مع نسبة عرض إلى ارتفاع ثابتة على SurfaceEntity:

val resizableComponent = ResizableComponent.create(session)
resizableComponent.minimumSize = Dimensions(177f, 100f, 1f)
resizableComponent.fixedAspectRatio = 16f / 9f // Specify a 16:9 aspect ratio

resizableComponent.addResizeListener(
    executor,
    object : ResizeListener {
        override fun onResizeEnd(entity: Entity, finalSize: Dimensions) {

            // update the size in the component
            resizableComponent.size = finalSize

            // update the Entity to reflect the new size
            (entity as SurfaceEntity).canvasShape = SurfaceEntity.CanvasShape.Quad(finalSize.width, finalSize.height)
        }
    },
)

entity.addComponent(resizableComponent)

استخدِم InteractableComponent لتسجيل أحداث إدخال المستخدم

تتيح لك السمة InteractableComponent تسجيل أحداث الإدخال من المستخدم، مثل عندما يتفاعل المستخدم مع Entity أو يمرّر مؤشر الماوس فوقه. عند إنشاء InteractableComponent، يجب تحديد InputEventListener لتلقّي أحداث الإدخال. عندما ينفّذ المستخدم أي إجراء إدخال، سيتم استدعاء الطريقة onInputEvent مع معلومات الإدخال المحدّدة المقدَّمة في المَعلمة InputEvent.

للحصول على قائمة كاملة بجميع الثوابت InputEvent، راجِع المستندات المرجعية.

يعرض مقتطف الرمز التالي مثالاً على استخدام InteractableComponent لزيادة حجم عنصر باليد اليمنى وتقليله باليد اليسرى.

val executor = Executors.newSingleThreadExecutor()
val interactableComponent = InteractableComponent.create(session, executor) {
    // when the user disengages with the entity with their hands
    if (it.source == InputEvent.SOURCE_HANDS && it.action == InputEvent.ACTION_UP) {
        // increase size with right hand and decrease with left
        if (it.pointerType == InputEvent.POINTER_TYPE_RIGHT) {
            entity.setScale(1.5f)
        } else if (it.pointerType == InputEvent.POINTER_TYPE_LEFT) {
            entity.setScale(0.5f)
        }
    }
}
entity.addComponent(interactableComponent)