From efb8a02615ee6736cf6c50cb43ba8796e07496ea Mon Sep 17 00:00:00 2001 From: devloglogan Date: Thu, 6 Feb 2025 12:14:53 -0600 Subject: [PATCH] Create Godot Meta Toolkit Demo Project --- demo/.gitignore | 3 + demo/README.md | 12 + demo/assets/gltf/turkey.glb | Bin 30632 -> 0 bytes demo/assets/gltf/turkey.glb.import | 38 -- demo/export_presets.cfg | 23 +- demo/icon.svg.import | 16 +- demo/main.gd | 369 +++++++++++++++++-- demo/main.tscn | 258 ++++++++++++- demo/project.godot | 4 - demo/raycast.gd | 16 + docs/manual/platform_sdk/getting_started.rst | 3 + 11 files changed, 645 insertions(+), 97 deletions(-) create mode 100644 demo/README.md delete mode 100644 demo/assets/gltf/turkey.glb delete mode 100644 demo/assets/gltf/turkey.glb.import create mode 100644 demo/raycast.gd diff --git a/demo/.gitignore b/demo/.gitignore index 7de8ea5..546c011 100644 --- a/demo/.gitignore +++ b/demo/.gitignore @@ -1,3 +1,6 @@ # Godot 4+ specific ignores .godot/ android/ + +addons/godotopenxrvendors/ +local.gd diff --git a/demo/README.md b/demo/README.md new file mode 100644 index 0000000..c86d4a3 --- /dev/null +++ b/demo/README.md @@ -0,0 +1,12 @@ +# Godot Meta Toolkit Demo + +> Note: this project requires Godot 4.3 or later + +This is a demo project demonstrating usage of the Meta Platform SDK in a Godot project. Features of the Platform SDK showcased include: + +- Achievements (simple, count, and bitfield) +- Downloadable content +- Displaying bidirectional followers that also own the app +- Displaying user's name, profile image, and entitlement status + +For more info on using the Platform SDK, see [Getting Started with the Meta Platform SDK](https://godot-sdk-integrations.github.io/godot-meta-toolkit/manual/platform_sdk/getting_started.html) in the official docs. diff --git a/demo/assets/gltf/turkey.glb b/demo/assets/gltf/turkey.glb deleted file mode 100644 index a3bef62bd1f163423d0c257c88941fd07bfaa880..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30632 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 lwCj^ z-~rrI;^FcFxbDCGc<17rhPic-!6@_V_OlxHuk+q@uX}g z$g^)LPy!SyO1Vt&q>~lMPfD@yq>;7Q;K;BiGMKLtDkECZfal=8EH^C!Pc<6G0YyBK^&72jjSe&dzj zvE{dG$A|bH8}e;je)E^#pPg^%=k8)o-RlYepY2^t)%^?oFUG0*hR^TzGUsJnN$?g?Gi$m0J|C`K+%?$uPP}8Nem{l#f~vbJ z-WTv*fp;#Fmv<QQ3-5K#-NT%_hv9upKcGLrdzW+fFz4=J{wLkT{6Bg97GMAX diff --git a/demo/assets/gltf/turkey.glb.import b/demo/assets/gltf/turkey.glb.import deleted file mode 100644 index 9b9c3a0..0000000 --- a/demo/assets/gltf/turkey.glb.import +++ /dev/null @@ -1,38 +0,0 @@ -[remap] - -importer="scene" -importer_version=1 -type="PackedScene" -uid="uid://b8a73fckkvdxx" -path="res://.godot/imported/turkey.glb-1d18e191321082a17947d1ba7a072950.scn" - -[deps] - -source_file="res://assets/gltf/turkey.glb" -dest_files=["res://.godot/imported/turkey.glb-1d18e191321082a17947d1ba7a072950.scn"] - -[params] - -nodes/root_type="" -nodes/root_name="" -nodes/apply_root_scale=true -nodes/root_scale=1.0 -nodes/import_as_skeleton_bones=false -meshes/ensure_tangents=true -meshes/generate_lods=true -meshes/create_shadow_meshes=true -meshes/light_baking=1 -meshes/lightmap_texel_size=0.2 -meshes/force_disable_compression=false -skins/use_named_skins=true -animation/import=true -animation/fps=30 -animation/trimming=false -animation/remove_immutable_tracks=true -import_script/path="" -_subresources={} -fbx/importer=0 -fbx/allow_geometry_helper_nodes=false -fbx/embedded_image_handling=1 -gltf/naming_version=1 -gltf/embedded_image_handling=1 diff --git a/demo/export_presets.cfg b/demo/export_presets.cfg index 00c9f2d..88f7d1d 100644 --- a/demo/export_presets.cfg +++ b/demo/export_presets.cfg @@ -31,10 +31,10 @@ architectures/armeabi-v7a=false architectures/arm64-v8a=true architectures/x86=false architectures/x86_64=false -version/code=1 +version/code=10 version/name="" -package/unique_name="com.meta.w4.godot.toolkit.demo" -package/name="" +package/unique_name="com.w4.godot.toolkit.demo" +package/name="Godot Meta Toolkit Demo" package/signed=true package/app_category=2 package/retain_data_on_uninstall=false @@ -124,7 +124,7 @@ permissions/install_location_provider=false permissions/install_packages=false permissions/install_shortcut=false permissions/internal_system_window=false -permissions/internet=false +permissions/internet=true permissions/kill_background_processes=false permissions/location_hardware=false permissions/manage_accounts=false @@ -139,6 +139,7 @@ permissions/mount_format_filesystems=false permissions/mount_unmount_filesystems=false permissions/nfc=false permissions/persistent_activity=false +permissions/post_notifications=false permissions/process_outgoing_calls=false permissions/read_calendar=false permissions/read_call_log=false @@ -220,7 +221,19 @@ meta_xr_features/use_overlay_keyboard=false meta_xr_features/use_experimental_features=false meta_xr_features/boundary_mode=2 meta_xr_features/quest_1_support=false -meta_xr_features/quest_2_support=false +meta_xr_features/quest_2_support=true meta_xr_features/quest_3_support=true meta_xr_features/quest_pro_support=true xr_features/enable_pico_plugin=false +khronos_xr_features/vendors=0 +khronos_xr_features/htc/hand_tracking=0 +khronos_xr_features/htc/tracker=0 +khronos_xr_features/htc/eye_tracking=0 +khronos_xr_features/htc/lip_expression=0 +meta_xr_features/body_tracking=0 +meta_xr_features/use_anchor_sharing=false +pico_xr_features/eye_tracking=0 +pico_xr_features/face_tracking=0 +pico_xr_features/hand_tracking=0 +xr_features/enable_magicleap_plugin=false +magicleap_xr_features/hand_tracking=0 diff --git a/demo/icon.svg.import b/demo/icon.svg.import index a223e41..d2618ce 100644 --- a/demo/icon.svg.import +++ b/demo/icon.svg.import @@ -3,25 +3,27 @@ importer="texture" type="CompressedTexture2D" uid="uid://cmm67scocnrpg" -path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" +path.s3tc="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.s3tc.ctex" +path.etc2="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.etc2.ctex" metadata={ -"vram_texture": false +"imported_formats": ["s3tc_bptc", "etc2_astc"], +"vram_texture": true } [deps] source_file="res://icon.svg" -dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] +dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.s3tc.ctex", "res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.etc2.ctex"] [params] -compress/mode=0 +compress/mode=2 compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 compress/normal_map=0 compress/channel_pack=0 -mipmaps/generate=false +mipmaps/generate=true mipmaps/limit=-1 roughness/mode=0 roughness/src_normal="" @@ -31,7 +33,7 @@ process/normal_map_invert_y=false process/hdr_as_srgb=false process/hdr_clamp_exposure=false process/size_limit=0 -detect_3d/compress_to=1 -svg/scale=1.0 +detect_3d/compress_to=0 +svg/scale=2.0 editor/scale_with_editor_scale=false editor/convert_colors_with_editor_theme=false diff --git a/demo/main.gd b/demo/main.gd index f8174cf..72ab04d 100644 --- a/demo/main.gd +++ b/demo/main.gd @@ -1,46 +1,359 @@ extends XROrigin3D -## Current XR interface -var xr_interface: XRInterface -var hand_tracking_source: Array[OpenXRInterface.HandTrackedSource] +const MAX_DISPLAY_FRIENDS := 5 +const PRODUCT_SKU := "00" +const SIMPLE_ACHIEVEMENT_NAME := "simple-achievement-example" +const COUNT_ACHIEVEMENT_NAME := "count-achievement-example" +const BITFIELD_ACHIEVEMENT_NAME := "bitfield-achievement-example" +const BITFIELD_ACHIEVEMENT_LENGTH := 5 -@onready var turkey = $turkey -@onready var left_controller_model: OpenXRFbRenderModel = $LeftController/LeftControllerRenderModel -@onready var right_controller_model: OpenXRFbRenderModel = $RightController/RightControllerRenderModel +# You need to supply your own application ID from https://developers.meta.com/ in order to test this app. +var APPLICATION_ID = "" + +var platform_sdk_initialized := false + +var purchase_processing := false +var product_purchased := false + +var simple_achievement_processing := true +var count_achievement_processing := true +var bitfield_achievement_processing := true +var simple_achievement_unlocked := false +var count_achievement_unlocked := false +var bitfield_achievement_unlocked := false + + +@onready var initialization_info: Node3D = $InitializationInfo +@onready var user_info: Node3D = $UserInfo +@onready var achievement_info: Node3D = $AchievementInfo +@onready var iap_info: Node3D = $IAPInfo +@onready var friend_info: Node3D = $FriendInfo + +@onready var left_controller_ray_cast: RayCast3D = $LeftController/LeftControllerRayCast +@onready var right_controller_ray_cast: RayCast3D = $RightController/RightControllerRayCast +@onready var initialization_label: Label3D = $InitializationInfo/InitializationLabel +@onready var entitled_label: Label3D = $UserInfo/EntitledLabel +@onready var oculus_id_label: Label3D = $UserInfo/OculusIDLabel +@onready var user_image: Sprite3D = $UserInfo/UserImage +@onready var friend_names_label: Label3D = $FriendInfo/FriendNamesLabel +@onready var iap_label: Label3D = $IAPInfo/IAPLabel +@onready var simple_achievement_label: Label3D = $AchievementInfo/SimpleAchievementInfo/SimpleAchievementLabel +@onready var count_achievement_label: Label3D = $AchievementInfo/CountAchievementInfo/CountAchievementLabel +@onready var bitfield_achievement_label: Label3D = $AchievementInfo/BitfieldAchievementInfo/BitfieldAchievementLabel -# Called when the node enters the scene tree for the first time. func _ready() -> void: - xr_interface = XRServer.find_interface("OpenXR") + var xr_interface = XRServer.find_interface("OpenXR") if xr_interface and xr_interface.is_initialized(): var vp: Viewport = get_viewport() vp.use_xr = true - # Give the viewport a 'transparent_bg' so we can see our passthrough vp.transparent_bg = true - - # Disable vsync DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_DISABLED) - - # Enable passthrough xr_interface.environment_blend_mode = XRInterface.XR_ENV_BLEND_MODE_ALPHA_BLEND - hand_tracking_source.resize(OpenXRInterface.HAND_MAX) - for hand in OpenXRInterface.HAND_MAX: - hand_tracking_source[hand] = xr_interface.get_hand_tracking_source(hand) + if ResourceLoader.exists("res://local.gd"): + var local = load('res://local.gd') + if local and "APPLICATION_ID" in local: + APPLICATION_ID = local.APPLICATION_ID + + if APPLICATION_ID == "": + initialization_label.text += "No app ID provided!" + hide_non_initialization_info() + return + + initialize_platform_sdk() + + +func initialize_platform_sdk(): + var result: MetaPlatformSDK_Message + + result = await MetaPlatformSDK.initialize_platform_async(APPLICATION_ID).completed + if result.is_error(): + initialization_label.text += "FAILED" + hide_non_initialization_info() + return + + var platform_initialize := result.get_platform_initialize() + if platform_initialize.result != MetaPlatformSDK.PLATFORM_INITIALIZE_SUCCESS: + initialization_label.text += "FAILED" + hide_non_initialization_info() + return + + platform_sdk_initialized = true + initialization_label.text += "SUCCESS" + + update_user_info() + update_friend_info() + update_iap_info() + update_achievement_info() + + +func update_user_info(): + var result: MetaPlatformSDK_Message + + result = await MetaPlatformSDK.entitlement_get_is_viewer_entitled_async().completed + if result.is_success(): + entitled_label.text += "TRUE" + else: + entitled_label.text += "FALSE" + + result = await MetaPlatformSDK.user_get_logged_in_user_async().completed + if result.is_error(): + oculus_id_label.text = "Failed to get user data!" + push_error("Failed to get user data: ", result.error) + return + + var user: MetaPlatformSDK_User = result.get_user() + oculus_id_label.text += user.oculus_id + + var image_request = HTTPRequest.new() + add_child(image_request) + image_request.request_completed.connect(self._image_request_completed.bind(image_request)) + + var error = image_request.request(user.image_url) + if error != OK: + push_error("There was an error with the image request.") + + +func update_friend_info(): + var result: MetaPlatformSDK_Message = await MetaPlatformSDK.user_get_logged_in_user_friends_async().completed + if result.is_error(): + friend_names_label.text = "Error retrieving friends!" + push_error("Error retrieving friends: ", result.error) + return + + + var friend_array := result.get_user_array() + if friend_array.size() == 0: + return + + var friend_count = 0 + friend_names_label.text = "" + for friend in friend_array: + if friend_count >= MAX_DISPLAY_FRIENDS: + break + var friend_name = friend.display_name if friend.display_name != "" else friend.oculus_id + friend_names_label.text += friend_name + "\n" + friend_count += 1 + + +func update_iap_info(): + var result: MetaPlatformSDK_Message = await MetaPlatformSDK.iap_get_viewer_purchases_async().completed + if result.is_error(): + iap_label.text = "Error getting\nuser purchases!" + purchase_processing = false + return + + var purchase_array := result.get_purchase_array() + for purchase: MetaPlatformSDK_Purchase in purchase_array: + if purchase.sku == PRODUCT_SKU: + product_purchased = true + break + + if product_purchased: + iap_label.text = "You have purchased\nthe in-app product!" + + purchase_processing = false + +func update_achievement_info(): + var result: MetaPlatformSDK_Message + result = await MetaPlatformSDK.achievements_get_all_progress_async().completed + if result.is_error(): + simple_achievement_label.text = "Error getting\nachievement progress!" + count_achievement_label.text = "Error getting\nachievement progress!" + bitfield_achievement_label.text = "Error getting\nachievement progress!" + simple_achievement_processing = false + count_achievement_processing = false + bitfield_achievement_processing = false + push_error("Couldn't get achievement progress: ", result.error) + return + + var achievement_progress_array := result.get_achievement_progress_array() + for achievement_progress: MetaPlatformSDK_AchievementProgress in achievement_progress_array: + match achievement_progress.name: + SIMPLE_ACHIEVEMENT_NAME: + if achievement_progress.is_unlocked: + simple_achievement_label.text = "Simple Achievement\nUnlocked!" + simple_achievement_unlocked = true + COUNT_ACHIEVEMENT_NAME: + if achievement_progress.is_unlocked: + count_achievement_label.text = "Count Achievement\nUnlocked!" + count_achievement_unlocked = true + else: + count_achievement_label.text = "Count is %s\nout of 3" % achievement_progress.count + BITFIELD_ACHIEVEMENT_NAME: + if achievement_progress.is_unlocked: + bitfield_achievement_label.text = "Bitfield Achievement\nUnlocked!" + bitfield_achievement_unlocked = true + else: + var active_bits = achievement_progress.bitfield.split().count("1") + bitfield_achievement_label.text = "%s of 5 bits active\nActivate 3 bits to unlock" % active_bits + + simple_achievement_processing = false + count_achievement_processing = false + bitfield_achievement_processing = false + + +func hide_non_initialization_info(): + user_info.hide() + achievement_info.hide() + iap_info.hide() + friend_info.hide() + + +func update(collider_name): + if not platform_sdk_initialized: + return + + match collider_name: + "IAPButton": + purchase_product() + "SimpleAchievementButton": + unlock_simple_achievement() + "CountAchievementButton": + increment_count_achievement() + "BitfieldAchievementButton1": + add_field_bitfield_achievement(0) + "BitfieldAchievementButton2": + add_field_bitfield_achievement(1) + "BitfieldAchievementButton3": + add_field_bitfield_achievement(2) + "BitfieldAchievementButton4": + add_field_bitfield_achievement(3) + "BitfieldAchievementButton5": + add_field_bitfield_achievement(4) + + +func purchase_product(): + if purchase_processing or product_purchased: + return + + iap_label.text = "Processing..." + purchase_processing = true + + # This App's example product is listed as free in the Meta Quest Developer Dashboard. + # Launching checkout flow for a free product like this will cause a panel to appear momentarily. + var result: MetaPlatformSDK_Message = await MetaPlatformSDK.iap_launch_checkout_flow_async(PRODUCT_SKU).completed + if result.is_error(): + iap_label.text = "Error launching\nproduct checkout flow!" + purchase_processing = false; + return + + update_iap_info() + + +func unlock_simple_achievement(): + if simple_achievement_processing or simple_achievement_unlocked: + return + + simple_achievement_label.text = "Processing..." + simple_achievement_processing = true + + var result: MetaPlatformSDK_Message = await MetaPlatformSDK.achievements_unlock_async(SIMPLE_ACHIEVEMENT_NAME).completed + if result.is_error(): + simple_achievement_label.text = "Error unlocking\nSimple Achievement" + else: + var achievement_update := result.get_achievement_update() + if achievement_update.just_unlocked: + simple_achievement_label.text = "Simple Achievement\njust unlocked!" + simple_achievement_unlocked = true + + simple_achievement_processing = false + + +func increment_count_achievement(): + if count_achievement_processing or count_achievement_unlocked: + return + + count_achievement_label.text = "Processing..." + count_achievement_processing = true + + var result: MetaPlatformSDK_Message = await MetaPlatformSDK.achievements_add_count_async(COUNT_ACHIEVEMENT_NAME, 1).completed + if result.is_error(): + count_achievement_label.text = "Error adding to\nCount Achievement" + else: + var achievement_update := result.get_achievement_update() + if achievement_update.just_unlocked: + count_achievement_label.text = "Count Achievement\njust unlocked!" + count_achievement_unlocked = true + else: + update_count_achievement_progress() + + count_achievement_processing = false + + +func update_count_achievement_progress(): + var result: MetaPlatformSDK_Message = await MetaPlatformSDK.achievements_get_progress_by_name_async([COUNT_ACHIEVEMENT_NAME]).completed + if result.is_error(): + count_achievement_label.text = "Error checking\nCount Achievement progress" + else: + var achievement_progress_array := result.get_achievement_progress_array() + for achievement_progress: MetaPlatformSDK_AchievementProgress in achievement_progress_array: + if achievement_progress.name != COUNT_ACHIEVEMENT_NAME: + continue + count_achievement_label.text = "Count is %s\nout of 3" % achievement_progress.count + return + + +func add_field_bitfield_achievement(bitfield_position: int): + if bitfield_achievement_processing or bitfield_achievement_unlocked: + return + + bitfield_achievement_label.text = "Processing..." + bitfield_achievement_processing = true + + var bitfield := "" + for i in BITFIELD_ACHIEVEMENT_LENGTH: + bitfield += "1" if i == bitfield_position else "0" + + var result: MetaPlatformSDK_Message = await MetaPlatformSDK.achievements_add_fields_async(BITFIELD_ACHIEVEMENT_NAME, bitfield).completed + if result.is_error(): + bitfield_achievement_label.text = "Error adding field to\nBitfield Achievement" + else: + var achievement_update := result.get_achievement_update() + if achievement_update.just_unlocked: + bitfield_achievement_label.text = "Bitfield Achievement\njust unlocked!" + bitfield_achievement_unlocked = true + else: + update_bitfield_achievement_progress() + + bitfield_achievement_processing = false + + +func update_bitfield_achievement_progress(): + var result: MetaPlatformSDK_Message = await MetaPlatformSDK.achievements_get_progress_by_name_async([BITFIELD_ACHIEVEMENT_NAME]).completed + if result.is_error(): + bitfield_achievement_label.text = "Error checking\nBitfield Achievement progress" + else: + var achievement_progress_array := result.get_achievement_progress_array() + for achievement_progress: MetaPlatformSDK_AchievementProgress in achievement_progress_array: + if achievement_progress.name != BITFIELD_ACHIEVEMENT_NAME: + continue + var active_bits = achievement_progress.bitfield.split().count("1") + bitfield_achievement_label.text = "%s of 5 bits active\nActivate 3 bits to unlock" % active_bits + return + + +func _on_left_controller_button_pressed(name: String) -> void: + if name == "trigger_click" and left_controller_ray_cast.is_colliding(): + var collider = left_controller_ray_cast.get_collider() + update(collider.name) -# Called every frame. 'delta' is the elapsed time since the previous frame. -func _physics_process(delta: float) -> void: - # Make the gltf model slowly rotate - if turkey: - turkey.rotate_y(0.001) - for hand in OpenXRInterface.HAND_MAX: - var source = xr_interface.get_hand_tracking_source(hand) - if hand_tracking_source[hand] == source: - continue +func _on_right_controller_button_pressed(name: String) -> void: + if name == "trigger_click" and right_controller_ray_cast.is_colliding(): + var collider = right_controller_ray_cast.get_collider() + update(collider.name) - var controller = left_controller_model if (hand == OpenXRInterface.HAND_LEFT) else right_controller_model - controller.visible = (source == OpenXRInterface.HAND_TRACKED_SOURCE_CONTROLLER) - hand_tracking_source[hand] = source +func _image_request_completed(_result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray, image_request: HTTPRequest): + if response_code != 200 or not headers.has("Content-Type: image/png"): + push_error("Image request was not successful.") + image_request.queue_free() + return + var image = Image.new() + image.load_png_from_buffer(body) + var image_texture = ImageTexture.create_from_image(image) + user_image.texture = image_texture + image_request.queue_free() diff --git a/demo/main.tscn b/demo/main.tscn index d27712d..0b3352d 100644 --- a/demo/main.tscn +++ b/demo/main.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=6 format=3 uid="uid://c0ol8en13wpk3"] +[gd_scene load_steps=17 format=3 uid="uid://c0ol8en13wpk3"] [ext_resource type="Script" path="res://main.gd" id="1_t3hrc"] -[ext_resource type="PackedScene" uid="uid://b8a73fckkvdxx" path="res://assets/gltf/turkey.glb" id="2_lrsmu"] +[ext_resource type="Script" path="res://raycast.gd" id="2_5nsls"] +[ext_resource type="Texture2D" uid="uid://cmm67scocnrpg" path="res://icon.svg" id="3_qj576"] [sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_h1cjv"] sky_horizon_color = Color(0.64625, 0.65575, 0.67075, 1) @@ -14,6 +15,38 @@ sky_material = SubResource("ProceduralSkyMaterial_h1cjv") sky = SubResource("Sky_a1pyg") tonemap_mode = 2 +[sub_resource type="CylinderMesh" id="CylinderMesh_75bh1"] +top_radius = 0.005 +bottom_radius = 0.005 + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_vpekr"] +shading_mode = 0 + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_mguh3"] +shading_mode = 0 + +[sub_resource type="BoxShape3D" id="BoxShape3D_me425"] +size = Vector3(0.745117, 0.297852, 0.102539) + +[sub_resource type="BoxMesh" id="BoxMesh_14q82"] +size = Vector3(0.745, 0.3, 0.1) + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_ck6b4"] +shading_mode = 0 +albedo_color = Color(1, 0, 0, 1) + +[sub_resource type="BoxShape3D" id="BoxShape3D_r6q7v"] +size = Vector3(0.308594, 0.297852, 0.102539) + +[sub_resource type="BoxMesh" id="BoxMesh_dy7is"] +size = Vector3(0.3, 0.3, 0.1) + +[sub_resource type="BoxShape3D" id="BoxShape3D_yn5xr"] +size = Vector3(1.44531, 0.297852, 0.102539) + +[sub_resource type="BoxMesh" id="BoxMesh_7ncv3"] +size = Vector3(1.445, 0.3, 0.1) + [node name="Main" type="XROrigin3D"] script = ExtResource("1_t3hrc") @@ -28,29 +61,224 @@ transform = Transform3D(-0.866025, -0.433013, 0.25, -0.12941, -0.288849, -0.9485 [node name="XRCamera3D" type="XRCamera3D" parent="."] -[node name="turkey" parent="." instance=ExtResource("2_lrsmu")] -transform = Transform3D(0.7, 0, 0, 0, 0.7, 0, 0, 0, 0.7, 0, 0.5, -0.7) - [node name="LeftController" type="XRController3D" parent="."] tracker = &"left_hand" pose = &"grip" -[node name="LeftControllerRenderModel" type="OpenXRFbRenderModel" parent="LeftController"] +[node name="LeftControllerRayCast" type="RayCast3D" parent="LeftController"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.059, -0.052) +target_position = Vector3(0, -10, 0) +script = ExtResource("2_5nsls") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="LeftController/LeftControllerRayCast"] +mesh = SubResource("CylinderMesh_75bh1") +surface_material_override/0 = SubResource("StandardMaterial3D_vpekr") [node name="RightController" type="XRController3D" parent="."] tracker = &"right_hand" pose = &"grip" -[node name="RightControllerRenderModel" type="OpenXRFbRenderModel" parent="RightController"] -render_model_type = 1 +[node name="RightControllerRayCast" type="RayCast3D" parent="RightController"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.059, -0.052) +target_position = Vector3(0, -10, 0) +script = ExtResource("2_5nsls") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="RightController/RightControllerRayCast"] +mesh = SubResource("CylinderMesh_75bh1") +surface_material_override/0 = SubResource("StandardMaterial3D_mguh3") + +[node name="InitializationInfo" type="Node3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.831041, -3) + +[node name="InitializationLabel" type="Label3D" parent="InitializationInfo"] +text = "SDK Initialization: " + +[node name="UserInfo" type="Node3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.48694, -3) +metadata/_edit_group_ = true + +[node name="UserImage" type="Sprite3D" parent="UserInfo"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.450442, 0) +pixel_size = 0.002 +texture = ExtResource("3_qj576") + +[node name="OculusIDLabel" type="Label3D" parent="UserInfo"] +text = "User Oculus ID: " + +[node name="EntitledLabel" type="Label3D" parent="UserInfo"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.224751, 0) +text = "User Entitled: " + +[node name="AchievementInfo" type="Node3D" parent="."] +transform = Transform3D(0.866025, 0, 0.5, 0, 1, 0, -0.5, 0, 0.866025, -2.11312, 1, -2.52491) +metadata/_edit_group_ = true + +[node name="SimpleAchievementInfo" type="Node3D" parent="AchievementInfo"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.15314, 0) + +[node name="SimpleAchievementLabel" type="Label3D" parent="AchievementInfo/SimpleAchievementInfo"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.199842, 0) +text = "Press Button +to Unlock +Simple Achievement" + +[node name="SimpleAchievementButton" type="StaticBody3D" parent="AchievementInfo/SimpleAchievementInfo"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.297091, 0) +metadata/_edit_group_ = true + +[node name="CollisionShape3D" type="CollisionShape3D" parent="AchievementInfo/SimpleAchievementInfo/SimpleAchievementButton"] +shape = SubResource("BoxShape3D_me425") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="AchievementInfo/SimpleAchievementInfo/SimpleAchievementButton"] +mesh = SubResource("BoxMesh_14q82") +surface_material_override/0 = SubResource("StandardMaterial3D_ck6b4") + +[node name="Label3D" type="Label3D" parent="AchievementInfo/SimpleAchievementInfo/SimpleAchievementButton"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0.0689178) +text = "Unlock" + +[node name="CountAchievementInfo" type="Node3D" parent="AchievementInfo"] + +[node name="CountAchievementLabel" type="Label3D" parent="AchievementInfo/CountAchievementInfo"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.199842, 0) +text = "Press Button Three +Times to Unlock +Count Achievement" + +[node name="CountAchievementButton" type="StaticBody3D" parent="AchievementInfo/CountAchievementInfo"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.297091, 0) +metadata/_edit_group_ = true + +[node name="CollisionShape3D" type="CollisionShape3D" parent="AchievementInfo/CountAchievementInfo/CountAchievementButton"] +shape = SubResource("BoxShape3D_me425") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="AchievementInfo/CountAchievementInfo/CountAchievementButton"] +mesh = SubResource("BoxMesh_14q82") +surface_material_override/0 = SubResource("StandardMaterial3D_ck6b4") + +[node name="Label3D" type="Label3D" parent="AchievementInfo/CountAchievementInfo/CountAchievementButton"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0.0689178) +text = "Unlock" + +[node name="BitfieldAchievementInfo" type="Node3D" parent="AchievementInfo"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1.1892, 0) + +[node name="BitfieldAchievementLabel" type="Label3D" parent="AchievementInfo/BitfieldAchievementInfo"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.199842, 0) +text = "Press Three of Five +Buttons to Unlock +Bitfield Achievement" + +[node name="BitfieldAchievementButton1" type="StaticBody3D" parent="AchievementInfo/BitfieldAchievementInfo"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.7, -0.297, 0) +metadata/_edit_group_ = true + +[node name="CollisionShape3D" type="CollisionShape3D" parent="AchievementInfo/BitfieldAchievementInfo/BitfieldAchievementButton1"] +shape = SubResource("BoxShape3D_r6q7v") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="AchievementInfo/BitfieldAchievementInfo/BitfieldAchievementButton1"] +mesh = SubResource("BoxMesh_dy7is") +surface_material_override/0 = SubResource("StandardMaterial3D_ck6b4") + +[node name="Label3D" type="Label3D" parent="AchievementInfo/BitfieldAchievementInfo/BitfieldAchievementButton1"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0.0689178) +text = "1" + +[node name="BitfieldAchievementButton2" type="StaticBody3D" parent="AchievementInfo/BitfieldAchievementInfo"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.35, -0.297, 0) +metadata/_edit_group_ = true + +[node name="CollisionShape3D" type="CollisionShape3D" parent="AchievementInfo/BitfieldAchievementInfo/BitfieldAchievementButton2"] +shape = SubResource("BoxShape3D_r6q7v") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="AchievementInfo/BitfieldAchievementInfo/BitfieldAchievementButton2"] +mesh = SubResource("BoxMesh_dy7is") +surface_material_override/0 = SubResource("StandardMaterial3D_ck6b4") + +[node name="Label3D" type="Label3D" parent="AchievementInfo/BitfieldAchievementInfo/BitfieldAchievementButton2"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0.0689178) +text = "2" + +[node name="BitfieldAchievementButton3" type="StaticBody3D" parent="AchievementInfo/BitfieldAchievementInfo"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.297091, 0) +metadata/_edit_group_ = true + +[node name="CollisionShape3D" type="CollisionShape3D" parent="AchievementInfo/BitfieldAchievementInfo/BitfieldAchievementButton3"] +shape = SubResource("BoxShape3D_r6q7v") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="AchievementInfo/BitfieldAchievementInfo/BitfieldAchievementButton3"] +mesh = SubResource("BoxMesh_dy7is") +surface_material_override/0 = SubResource("StandardMaterial3D_ck6b4") + +[node name="Label3D" type="Label3D" parent="AchievementInfo/BitfieldAchievementInfo/BitfieldAchievementButton3"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0.0689178) +text = "3" + +[node name="BitfieldAchievementButton4" type="StaticBody3D" parent="AchievementInfo/BitfieldAchievementInfo"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.35, -0.297, 0) +metadata/_edit_group_ = true + +[node name="CollisionShape3D" type="CollisionShape3D" parent="AchievementInfo/BitfieldAchievementInfo/BitfieldAchievementButton4"] +shape = SubResource("BoxShape3D_r6q7v") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="AchievementInfo/BitfieldAchievementInfo/BitfieldAchievementButton4"] +mesh = SubResource("BoxMesh_dy7is") +surface_material_override/0 = SubResource("StandardMaterial3D_ck6b4") + +[node name="Label3D" type="Label3D" parent="AchievementInfo/BitfieldAchievementInfo/BitfieldAchievementButton4"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0.0689178) +text = "4" + +[node name="BitfieldAchievementButton5" type="StaticBody3D" parent="AchievementInfo/BitfieldAchievementInfo"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.7, -0.297, 0) +metadata/_edit_group_ = true + +[node name="CollisionShape3D" type="CollisionShape3D" parent="AchievementInfo/BitfieldAchievementInfo/BitfieldAchievementButton5"] +shape = SubResource("BoxShape3D_r6q7v") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="AchievementInfo/BitfieldAchievementInfo/BitfieldAchievementButton5"] +mesh = SubResource("BoxMesh_dy7is") +surface_material_override/0 = SubResource("StandardMaterial3D_ck6b4") + +[node name="Label3D" type="Label3D" parent="AchievementInfo/BitfieldAchievementInfo/BitfieldAchievementButton5"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0.0689178) +text = "5" + +[node name="IAPInfo" type="Node3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -3) +metadata/_edit_group_ = true + +[node name="IAPLabel" type="Label3D" parent="IAPInfo"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.199842, 0) +text = "Press the button below +to purchase in-app product" + +[node name="IAPButton" type="StaticBody3D" parent="IAPInfo"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.297091, 0) +metadata/_edit_group_ = true + +[node name="CollisionShape3D" type="CollisionShape3D" parent="IAPInfo/IAPButton"] +shape = SubResource("BoxShape3D_yn5xr") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="IAPInfo/IAPButton"] +mesh = SubResource("BoxMesh_7ncv3") +surface_material_override/0 = SubResource("StandardMaterial3D_ck6b4") + +[node name="Label3D" type="Label3D" parent="IAPInfo/IAPButton"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0.0689178) +text = "Purchase Product" -[node name="LeftXRHandModifier3D" type="XRHandModifier3D" parent="."] +[node name="FriendInfo" type="Node3D" parent="."] +transform = Transform3D(0.707107, 0, -0.707107, 0, 1, 0, 0.707107, 0, 0.707107, 2.113, 1, -2.525) +metadata/_edit_group_ = true -[node name="LeftHandModel" type="OpenXRFbHandTrackingMesh" parent="LeftXRHandModifier3D"] +[node name="FriendsLabel" type="Label3D" parent="FriendInfo"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.493917, 0) +text = "Friends Who Own This App:" -[node name="RightXRHandModifier3D" type="XRHandModifier3D" parent="."] -hand_tracker = &"/user/right" +[node name="FriendNamesLabel" type="Label3D" parent="FriendInfo"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.347479, 0) +text = "None" -[node name="RightHandModel" type="OpenXRFbHandTrackingMesh" parent="RightXRHandModifier3D"] -hand = 1 -use_scale_override = false +[connection signal="button_pressed" from="LeftController" to="." method="_on_left_controller_button_pressed"] +[connection signal="button_pressed" from="RightController" to="." method="_on_right_controller_button_pressed"] diff --git a/demo/project.godot b/demo/project.godot index 228e5a1..8f2f29f 100644 --- a/demo/project.godot +++ b/demo/project.godot @@ -15,10 +15,6 @@ run/main_scene="res://main.tscn" config/features=PackedStringArray("4.3", "GL Compatibility") config/icon="res://icon.svg" -[debug] - -settings/stdout/verbose_stdout=true - [rendering] renderer/rendering_method="gl_compatibility" diff --git a/demo/raycast.gd b/demo/raycast.gd new file mode 100644 index 0000000..b0f4371 --- /dev/null +++ b/demo/raycast.gd @@ -0,0 +1,16 @@ +extends RayCast3D + +@onready var mesh_instance_3d: MeshInstance3D = $MeshInstance3D + +func _process(delta: float) -> void: + var mat = mesh_instance_3d.get_surface_override_material(0) + + if not is_colliding(): + mesh_instance_3d.mesh.height = 10 + mesh_instance_3d.position.y = -5 + mat.albedo_color = Color.RED + else: + var height = (get_collision_point() - global_position).length() + mesh_instance_3d.mesh.height = height + mesh_instance_3d.position.y = -(height / 2) + mat.albedo_color = Color.GREEN diff --git a/docs/manual/platform_sdk/getting_started.rst b/docs/manual/platform_sdk/getting_started.rst index 8ec3cf0..7be4340 100644 --- a/docs/manual/platform_sdk/getting_started.rst +++ b/docs/manual/platform_sdk/getting_started.rst @@ -58,4 +58,7 @@ After that process is complete, you'll be able to use the Platform SDK: for user in result.data: print("- ", user) +If you'd like to see more examples of using the Meta Platform SDK in a Godot project, be sure to check out the Godot Meta Toolkit Demo. +Source code for the project can be found on `GitHub `_. + For more information, see the API docs for the :ref:`MetaPlatformSDK` singleton. It's the entry point for doing anything with the Meta Platform SDK.