diff --git a/Config/DefaultGame.ini b/Config/DefaultGame.ini index 82d3f10..7c2dea2 100644 --- a/Config/DefaultGame.ini +++ b/Config/DefaultGame.ini @@ -2,3 +2,6 @@ ProjectID=DD810CA045CA9288C9C53E8638A45978 bStartInVR=True +[/Script/UnrealEd.ProjectPackagingSettings] ++DirectoriesToAlwaysCook=(Path="/Game/Mosis") + diff --git a/Content/Mosis/Materials/M_PhoneScreen.uasset b/Content/Mosis/Materials/M_PhoneScreen.uasset new file mode 100644 index 0000000..2759fba --- /dev/null +++ b/Content/Mosis/Materials/M_PhoneScreen.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26628dc5490bf19e3f93dbf9682fc3f56e0509aa61720c74329fab4c178a9ce5 +size 5356 diff --git a/Plugins/MosisSDK/README.md b/Plugins/MosisSDK/README.md index 9e09fbc..1d76948 100644 --- a/Plugins/MosisSDK/README.md +++ b/Plugins/MosisSDK/README.md @@ -89,7 +89,6 @@ Plugins/MosisSDK/ │ ├── MosisClient.h/cpp # AIDL client implementation │ ├── MosisPhoneTexture.h/cpp # UTexture for phone screen │ ├── MosisPhoneTextureResource.h/cpp # Render thread resource -│ ├── MosisVulkanTexture.h/cpp # Legacy Vulkan import (unused) │ ├── MosisPhoneComponent.cpp │ ├── MosisPhoneActor.cpp │ └── Android/ diff --git a/Plugins/MosisSDK/Source/MosisSDK/Private/MosisPhoneActor.cpp b/Plugins/MosisSDK/Source/MosisSDK/Private/MosisPhoneActor.cpp index 7a310b6..1b9e0b2 100644 --- a/Plugins/MosisSDK/Source/MosisSDK/Private/MosisPhoneActor.cpp +++ b/Plugins/MosisSDK/Source/MosisSDK/Private/MosisPhoneActor.cpp @@ -25,6 +25,14 @@ AMosisPhoneActor::AMosisPhoneActor() PhoneMesh->SetStaticMesh(PlaneMeshFinder.Object); } + // Load the phone screen material + static ConstructorHelpers::FObjectFinder PhoneMaterialFinder( + TEXT("/Game/Mosis/Materials/M_PhoneScreen.M_PhoneScreen")); + if (PhoneMaterialFinder.Succeeded()) + { + BaseMaterial = PhoneMaterialFinder.Object; + } + // Create phone component PhoneComponent = CreateDefaultSubobject(TEXT("PhoneComponent")); } diff --git a/Plugins/MosisSDK/Source/MosisSDK/Private/MosisVulkanTexture.cpp b/Plugins/MosisSDK/Source/MosisSDK/Private/MosisVulkanTexture.cpp deleted file mode 100644 index 75d32ec..0000000 --- a/Plugins/MosisSDK/Source/MosisSDK/Private/MosisVulkanTexture.cpp +++ /dev/null @@ -1,421 +0,0 @@ -#include "MosisVulkanTexture.h" - -#if PLATFORM_ANDROID - -#include "Logging/LogMacros.h" - -DEFINE_LOG_CATEGORY_STATIC(LogMosisVulkan, Log, All); - -MosisVulkanTexture::~MosisVulkanTexture() -{ - Destroy(); -} - -bool MosisVulkanTexture::Initialize(VkInstance instance, VkPhysicalDevice physDevice, VkDevice device, uint32_t queueFamilyIndex) -{ - if (m_Initialized) - { - return true; - } - - m_Instance = instance; - m_PhysicalDevice = physDevice; - m_Device = device; - m_QueueFamilyIndex = queueFamilyIndex; - - // Load extension function - vkGetAndroidHardwareBufferPropertiesANDROID = - reinterpret_cast( - vkGetInstanceProcAddr(m_Instance, "vkGetAndroidHardwareBufferPropertiesANDROID") - ); - - if (!vkGetAndroidHardwareBufferPropertiesANDROID) - { - UE_LOG(LogMosisVulkan, Error, TEXT("Initialize: vkGetAndroidHardwareBufferPropertiesANDROID not available")); - return false; - } - - m_Initialized = true; - UE_LOG(LogMosisVulkan, Log, TEXT("Initialize: Success")); - return true; -} - -bool MosisVulkanTexture::Create(AHardwareBuffer* buffer) -{ - if (!m_Initialized) - { - UE_LOG(LogMosisVulkan, Error, TEXT("Create: Not initialized")); - return false; - } - - if (m_Created) - { - Destroy(); - } - - // Get buffer dimensions - AHardwareBuffer_Desc desc{}; - AHardwareBuffer_describe(buffer, &desc); - m_Width = desc.width; - m_Height = desc.height; - - UE_LOG(LogMosisVulkan, Log, TEXT("Create: %dx%d texture"), m_Width, m_Height); - - if (!ImportHardwareBuffer(buffer)) - { - UE_LOG(LogMosisVulkan, Error, TEXT("Create: Failed to import hardware buffer")); - return false; - } - - if (!CreateLocalImage()) - { - UE_LOG(LogMosisVulkan, Error, TEXT("Create: Failed to create local image")); - DestroyImportedResources(); - return false; - } - - m_Created = true; - UE_LOG(LogMosisVulkan, Log, TEXT("Create: Success")); - return true; -} - -bool MosisVulkanTexture::ImportHardwareBuffer(AHardwareBuffer* buffer) -{ - // Query hardware buffer properties - VkAndroidHardwareBufferFormatPropertiesANDROID formatProps{}; - formatProps.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID; - - VkAndroidHardwareBufferPropertiesANDROID props{}; - props.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID; - props.pNext = &formatProps; - - if (vkGetAndroidHardwareBufferPropertiesANDROID(m_Device, buffer, &props) != VK_SUCCESS) - { - UE_LOG(LogMosisVulkan, Error, TEXT("ImportHardwareBuffer: Failed to get properties")); - return false; - } - - m_Format = formatProps.format; - UE_LOG(LogMosisVulkan, Log, TEXT("ImportHardwareBuffer: Format=%d"), static_cast(m_Format)); - - // Create VkImage with external memory - VkExternalMemoryImageCreateInfo extMemImageInfo{}; - extMemImageInfo.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO; - extMemImageInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; - - VkImageCreateInfo imageInfo{}; - imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - imageInfo.pNext = &extMemImageInfo; - imageInfo.imageType = VK_IMAGE_TYPE_2D; - imageInfo.format = m_Format; - imageInfo.extent = {m_Width, m_Height, 1}; - imageInfo.mipLevels = 1; - imageInfo.arrayLayers = 1; - imageInfo.samples = VK_SAMPLE_COUNT_1_BIT; - imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - if (vkCreateImage(m_Device, &imageInfo, nullptr, &m_ImportedImage) != VK_SUCCESS) - { - UE_LOG(LogMosisVulkan, Error, TEXT("ImportHardwareBuffer: Failed to create image")); - return false; - } - - // Import memory from hardware buffer - VkImportAndroidHardwareBufferInfoANDROID importInfo{}; - importInfo.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID; - importInfo.buffer = buffer; - - VkMemoryDedicatedAllocateInfo dedicatedInfo{}; - dedicatedInfo.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO; - dedicatedInfo.pNext = &importInfo; - dedicatedInfo.image = m_ImportedImage; - - VkMemoryAllocateInfo allocInfo{}; - allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - allocInfo.pNext = &dedicatedInfo; - allocInfo.allocationSize = props.allocationSize; - allocInfo.memoryTypeIndex = FindMemoryType(props.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - - if (vkAllocateMemory(m_Device, &allocInfo, nullptr, &m_ImportedMemory) != VK_SUCCESS) - { - UE_LOG(LogMosisVulkan, Error, TEXT("ImportHardwareBuffer: Failed to allocate memory")); - vkDestroyImage(m_Device, m_ImportedImage, nullptr); - m_ImportedImage = VK_NULL_HANDLE; - return false; - } - - if (vkBindImageMemory(m_Device, m_ImportedImage, m_ImportedMemory, 0) != VK_SUCCESS) - { - UE_LOG(LogMosisVulkan, Error, TEXT("ImportHardwareBuffer: Failed to bind memory")); - DestroyImportedResources(); - return false; - } - - UE_LOG(LogMosisVulkan, Log, TEXT("ImportHardwareBuffer: Success")); - return true; -} - -bool MosisVulkanTexture::CreateLocalImage() -{ - // Create local VkImage - VkImageCreateInfo imageInfo{}; - imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - imageInfo.imageType = VK_IMAGE_TYPE_2D; - imageInfo.format = m_Format; - imageInfo.extent = {m_Width, m_Height, 1}; - imageInfo.mipLevels = 1; - imageInfo.arrayLayers = 1; - imageInfo.samples = VK_SAMPLE_COUNT_1_BIT; - imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - if (vkCreateImage(m_Device, &imageInfo, nullptr, &m_LocalImage) != VK_SUCCESS) - { - UE_LOG(LogMosisVulkan, Error, TEXT("CreateLocalImage: Failed to create image")); - return false; - } - - // Allocate memory - VkMemoryRequirements memReqs; - vkGetImageMemoryRequirements(m_Device, m_LocalImage, &memReqs); - - VkMemoryAllocateInfo allocInfo{}; - allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - allocInfo.allocationSize = memReqs.size; - allocInfo.memoryTypeIndex = FindMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - - if (vkAllocateMemory(m_Device, &allocInfo, nullptr, &m_LocalMemory) != VK_SUCCESS) - { - UE_LOG(LogMosisVulkan, Error, TEXT("CreateLocalImage: Failed to allocate memory")); - vkDestroyImage(m_Device, m_LocalImage, nullptr); - m_LocalImage = VK_NULL_HANDLE; - return false; - } - - if (vkBindImageMemory(m_Device, m_LocalImage, m_LocalMemory, 0) != VK_SUCCESS) - { - UE_LOG(LogMosisVulkan, Error, TEXT("CreateLocalImage: Failed to bind memory")); - DestroyLocalResources(); - return false; - } - - // Create image view - VkImageViewCreateInfo viewInfo{}; - viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - viewInfo.image = m_LocalImage; - viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - viewInfo.format = m_Format; - viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - viewInfo.subresourceRange.baseMipLevel = 0; - viewInfo.subresourceRange.levelCount = 1; - viewInfo.subresourceRange.baseArrayLayer = 0; - viewInfo.subresourceRange.layerCount = 1; - - if (vkCreateImageView(m_Device, &viewInfo, nullptr, &m_LocalImageView) != VK_SUCCESS) - { - UE_LOG(LogMosisVulkan, Error, TEXT("CreateLocalImage: Failed to create image view")); - DestroyLocalResources(); - return false; - } - - // Create sampler - VkSamplerCreateInfo samplerInfo{}; - samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; - samplerInfo.magFilter = VK_FILTER_LINEAR; - samplerInfo.minFilter = VK_FILTER_LINEAR; - samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - samplerInfo.anisotropyEnable = VK_FALSE; - samplerInfo.maxAnisotropy = 1.0f; - samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; - samplerInfo.unnormalizedCoordinates = VK_FALSE; - samplerInfo.compareEnable = VK_FALSE; - samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - - if (vkCreateSampler(m_Device, &samplerInfo, nullptr, &m_Sampler) != VK_SUCCESS) - { - UE_LOG(LogMosisVulkan, Error, TEXT("CreateLocalImage: Failed to create sampler")); - DestroyLocalResources(); - return false; - } - - UE_LOG(LogMosisVulkan, Log, TEXT("CreateLocalImage: Success")); - return true; -} - -void MosisVulkanTexture::CopyToLocal(VkCommandBuffer cmd) -{ - if (!m_Created) - { - return; - } - - // Transition imported image to transfer src - VkImageMemoryBarrier srcBarrier{}; - srcBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - srcBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - srcBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - srcBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - srcBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - srcBarrier.image = m_ImportedImage; - srcBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - srcBarrier.subresourceRange.baseMipLevel = 0; - srcBarrier.subresourceRange.levelCount = 1; - srcBarrier.subresourceRange.baseArrayLayer = 0; - srcBarrier.subresourceRange.layerCount = 1; - srcBarrier.srcAccessMask = 0; - srcBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - - vkCmdPipelineBarrier( - cmd, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - 0, 0, nullptr, 0, nullptr, 1, &srcBarrier - ); - - // Transition local image to transfer dst - VkImageMemoryBarrier dstBarrier{}; - dstBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - dstBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; - dstBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - dstBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - dstBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - dstBarrier.image = m_LocalImage; - dstBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - dstBarrier.subresourceRange.baseMipLevel = 0; - dstBarrier.subresourceRange.levelCount = 1; - dstBarrier.subresourceRange.baseArrayLayer = 0; - dstBarrier.subresourceRange.layerCount = 1; - dstBarrier.srcAccessMask = 0; - dstBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - - vkCmdPipelineBarrier( - cmd, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - 0, 0, nullptr, 0, nullptr, 1, &dstBarrier - ); - - // Copy image - VkImageCopy copyRegion{}; - copyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyRegion.srcSubresource.layerCount = 1; - copyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyRegion.dstSubresource.layerCount = 1; - copyRegion.extent = {m_Width, m_Height, 1}; - - vkCmdCopyImage( - cmd, - m_ImportedImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - m_LocalImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, ©Region - ); - - // Transition local image to shader read - VkImageMemoryBarrier shaderBarrier{}; - shaderBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - shaderBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - shaderBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - shaderBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - shaderBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - shaderBarrier.image = m_LocalImage; - shaderBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - shaderBarrier.subresourceRange.baseMipLevel = 0; - shaderBarrier.subresourceRange.levelCount = 1; - shaderBarrier.subresourceRange.baseArrayLayer = 0; - shaderBarrier.subresourceRange.layerCount = 1; - shaderBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - shaderBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - - vkCmdPipelineBarrier( - cmd, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - 0, 0, nullptr, 0, nullptr, 1, &shaderBarrier - ); -} - -uint32_t MosisVulkanTexture::FindMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) -{ - VkPhysicalDeviceMemoryProperties memProps; - vkGetPhysicalDeviceMemoryProperties(m_PhysicalDevice, &memProps); - - for (uint32_t i = 0; i < memProps.memoryTypeCount; i++) - { - if ((typeFilter & (1 << i)) && - (memProps.memoryTypes[i].propertyFlags & properties) == properties) - { - return i; - } - } - - UE_LOG(LogMosisVulkan, Error, TEXT("FindMemoryType: Failed to find suitable memory type")); - return 0; -} - -void MosisVulkanTexture::Destroy() -{ - if (m_Device && m_Created) - { - vkDeviceWaitIdle(m_Device); - } - - DestroyLocalResources(); - DestroyImportedResources(); - - m_Width = 0; - m_Height = 0; - m_Created = false; -} - -void MosisVulkanTexture::DestroyImportedResources() -{ - if (m_Device) - { - if (m_ImportedMemory != VK_NULL_HANDLE) - { - vkFreeMemory(m_Device, m_ImportedMemory, nullptr); - m_ImportedMemory = VK_NULL_HANDLE; - } - if (m_ImportedImage != VK_NULL_HANDLE) - { - vkDestroyImage(m_Device, m_ImportedImage, nullptr); - m_ImportedImage = VK_NULL_HANDLE; - } - } -} - -void MosisVulkanTexture::DestroyLocalResources() -{ - if (m_Device) - { - if (m_Sampler != VK_NULL_HANDLE) - { - vkDestroySampler(m_Device, m_Sampler, nullptr); - m_Sampler = VK_NULL_HANDLE; - } - if (m_LocalImageView != VK_NULL_HANDLE) - { - vkDestroyImageView(m_Device, m_LocalImageView, nullptr); - m_LocalImageView = VK_NULL_HANDLE; - } - if (m_LocalMemory != VK_NULL_HANDLE) - { - vkFreeMemory(m_Device, m_LocalMemory, nullptr); - m_LocalMemory = VK_NULL_HANDLE; - } - if (m_LocalImage != VK_NULL_HANDLE) - { - vkDestroyImage(m_Device, m_LocalImage, nullptr); - m_LocalImage = VK_NULL_HANDLE; - } - } -} - -#endif // PLATFORM_ANDROID diff --git a/Plugins/MosisSDK/Source/MosisSDK/Private/MosisVulkanTexture.h b/Plugins/MosisSDK/Source/MosisSDK/Private/MosisVulkanTexture.h deleted file mode 100644 index 7bc06ff..0000000 --- a/Plugins/MosisSDK/Source/MosisSDK/Private/MosisVulkanTexture.h +++ /dev/null @@ -1,87 +0,0 @@ -#pragma once - -#if PLATFORM_ANDROID - -#include "CoreMinimal.h" -#include -#include -#include - -/** - * MosisVulkanTexture - Imports AHardwareBuffer as Vulkan texture for Unreal. - * Creates both imported and local copy images for safe rendering. - */ -class MosisVulkanTexture -{ -public: - MosisVulkanTexture() = default; - ~MosisVulkanTexture(); - - /** - * Initialize with Vulkan device objects. - * Must be called before Create(). - */ - bool Initialize(VkInstance instance, VkPhysicalDevice physDevice, VkDevice device, uint32_t queueFamilyIndex); - - /** - * Create texture from a hardware buffer. - * @param buffer The AHardwareBuffer from the Mosis service - * @return true if creation succeeded - */ - bool Create(AHardwareBuffer* buffer); - - /** - * Copy from imported image to local image. - * Call this each frame when a new frame is available. - */ - void CopyToLocal(VkCommandBuffer cmd); - - /** - * Destroy all resources. - */ - void Destroy(); - - // Accessors - VkImage GetLocalImage() const { return m_LocalImage; } - VkImageView GetLocalImageView() const { return m_LocalImageView; } - VkFormat GetFormat() const { return m_Format; } - uint32_t GetWidth() const { return m_Width; } - uint32_t GetHeight() const { return m_Height; } - bool IsValid() const { return m_Created; } - -private: - bool ImportHardwareBuffer(AHardwareBuffer* buffer); - bool CreateLocalImage(); - void DestroyImportedResources(); - void DestroyLocalResources(); - uint32_t FindMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties); - - // Vulkan objects - VkInstance m_Instance = VK_NULL_HANDLE; - VkPhysicalDevice m_PhysicalDevice = VK_NULL_HANDLE; - VkDevice m_Device = VK_NULL_HANDLE; - uint32_t m_QueueFamilyIndex = 0; - - // Imported from HardwareBuffer - VkImage m_ImportedImage = VK_NULL_HANDLE; - VkDeviceMemory m_ImportedMemory = VK_NULL_HANDLE; - - // Local copy for safe rendering - VkImage m_LocalImage = VK_NULL_HANDLE; - VkDeviceMemory m_LocalMemory = VK_NULL_HANDLE; - VkImageView m_LocalImageView = VK_NULL_HANDLE; - VkSampler m_Sampler = VK_NULL_HANDLE; - - // Format info - VkFormat m_Format = VK_FORMAT_R8G8B8A8_UNORM; - uint32_t m_Width = 0; - uint32_t m_Height = 0; - - bool m_Initialized = false; - bool m_Created = false; - - // Extension function pointer - PFN_vkGetAndroidHardwareBufferPropertiesANDROID vkGetAndroidHardwareBufferPropertiesANDROID = nullptr; -}; - -#endif // PLATFORM_ANDROID diff --git a/Scripts/create_phone_material.py b/Scripts/create_phone_material.py new file mode 100644 index 0000000..1aeb36d --- /dev/null +++ b/Scripts/create_phone_material.py @@ -0,0 +1,67 @@ +# Unreal Editor Python script to create the Mosis phone screen material +# Run this in the Editor: File > Execute Python Script +# Or from Python console: exec(open('Scripts/create_phone_material.py').read()) + +import unreal + +def create_phone_screen_material(): + """Create an unlit emissive material for displaying the phone screen.""" + + asset_tools = unreal.AssetToolsHelpers.get_asset_tools() + material_factory = unreal.MaterialFactoryNew() + + # Create the material asset + material_path = "/Game/Mosis/Materials" + material_name = "M_PhoneScreen" + + # Check if material already exists + if unreal.EditorAssetLibrary.does_asset_exist(f"{material_path}/{material_name}"): + unreal.log_warning(f"Material {material_name} already exists, skipping creation") + return unreal.load_asset(f"{material_path}/{material_name}") + + # Create the material + material = asset_tools.create_asset( + material_name, + material_path, + unreal.Material, + material_factory + ) + + if not material: + unreal.log_error("Failed to create material") + return None + + # Configure material properties for phone screen display + material.set_editor_property("shading_model", unreal.MaterialShadingModel.MSM_UNLIT) + material.set_editor_property("blend_mode", unreal.BlendMode.BLEND_OPAQUE) + material.set_editor_property("two_sided", False) + + # Get the material editor subsystem to add nodes + mel = unreal.MaterialEditingLibrary + + # Create texture parameter node + texture_param = mel.create_material_expression( + material, + unreal.MaterialExpressionTextureSampleParameter2D, + -400, 0 + ) + texture_param.set_editor_property("parameter_name", "PhoneScreen") + + # Connect texture RGB to emissive color + mel.connect_material_property( + texture_param, "RGB", + unreal.MaterialProperty.MP_EMISSIVE_COLOR + ) + + # Recompile the material + mel.recompile_material(material) + + # Save the asset + unreal.EditorAssetLibrary.save_asset(f"{material_path}/{material_name}") + + unreal.log(f"Created material: {material_path}/{material_name}") + return material + + +if __name__ == "__main__": + create_phone_screen_material()