完成
This commit is contained in:
@@ -807,7 +807,7 @@ GameObject:
|
|||||||
- component: {fileID: 5633745582843563864}
|
- component: {fileID: 5633745582843563864}
|
||||||
- component: {fileID: 2745806976415084587}
|
- component: {fileID: 2745806976415084587}
|
||||||
m_Layer: 5
|
m_Layer: 5
|
||||||
m_Name: 'menuBar '
|
m_Name: menuBar
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
m_Icon: {fileID: 0}
|
m_Icon: {fileID: 0}
|
||||||
m_NavMeshLayer: 0
|
m_NavMeshLayer: 0
|
||||||
@@ -5468,57 +5468,6 @@ MonoBehaviour:
|
|||||||
m_FillOrigin: 0
|
m_FillOrigin: 0
|
||||||
m_UseSpriteMesh: 0
|
m_UseSpriteMesh: 0
|
||||||
m_PixelsPerUnitMultiplier: 1
|
m_PixelsPerUnitMultiplier: 1
|
||||||
--- !u!1 &6378174656737304708
|
|
||||||
GameObject:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
serializedVersion: 6
|
|
||||||
m_Component:
|
|
||||||
- component: {fileID: 564683241228581302}
|
|
||||||
- component: {fileID: 4786814708591545236}
|
|
||||||
m_Layer: 5
|
|
||||||
m_Name: Pool
|
|
||||||
m_TagString: Untagged
|
|
||||||
m_Icon: {fileID: 0}
|
|
||||||
m_NavMeshLayer: 0
|
|
||||||
m_StaticEditorFlags: 0
|
|
||||||
m_IsActive: 1
|
|
||||||
--- !u!224 &564683241228581302
|
|
||||||
RectTransform:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 6378174656737304708}
|
|
||||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
|
||||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
|
||||||
m_ConstrainProportionsScale: 0
|
|
||||||
m_Children: []
|
|
||||||
m_Father: {fileID: 6018946838727076121}
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
|
||||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
|
||||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
|
||||||
m_AnchoredPosition: {x: 0, y: 0}
|
|
||||||
m_SizeDelta: {x: 100, y: 100}
|
|
||||||
m_Pivot: {x: 0.5, y: 0.5}
|
|
||||||
--- !u!114 &4786814708591545236
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 6378174656737304708}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 1970feb7fdb702645b753cd8ed1be4ea, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
prefab: {fileID: 8495991377958309690, guid: ac2316fabaf14dc409bee0e9c34cae94, type: 3}
|
|
||||||
preload: 20
|
|
||||||
parent: {fileID: 5467042597978700984}
|
|
||||||
--- !u!1 &6412793980989755428
|
--- !u!1 &6412793980989755428
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -5965,7 +5914,6 @@ RectTransform:
|
|||||||
m_Children:
|
m_Children:
|
||||||
- {fileID: 3211075651667160076}
|
- {fileID: 3211075651667160076}
|
||||||
- {fileID: 8993963496967448533}
|
- {fileID: 8993963496967448533}
|
||||||
- {fileID: 564683241228581302}
|
|
||||||
m_Father: {fileID: 6596158407599272745}
|
m_Father: {fileID: 6596158407599272745}
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Stary.Evo;
|
using Script;
|
||||||
|
using Stary.Evo;
|
||||||
using Stary.Evo.UIFarme;
|
using Stary.Evo.UIFarme;
|
||||||
|
|
||||||
namespace RenderStreaming
|
namespace RenderStreaming
|
||||||
@@ -12,6 +13,7 @@ namespace RenderStreaming
|
|||||||
RegisterSystem<IPanelSystem>(new PanelSystem(new ResourcesAssetLoader()));
|
RegisterSystem<IPanelSystem>(new PanelSystem(new ResourcesAssetLoader()));
|
||||||
RegisterSystem<IGlobalConfigSystem>(new GlobalConfigSystem());
|
RegisterSystem<IGlobalConfigSystem>(new GlobalConfigSystem());
|
||||||
RegisterSystem<ITimerSystem>(new TimerSystem());
|
RegisterSystem<ITimerSystem>(new TimerSystem());
|
||||||
|
RegisterSystem<IRenderStreamingSystem>(new RenderStreamingSystem());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -17,7 +17,7 @@ namespace Script
|
|||||||
private Text _confirmBtnTimeText;
|
private Text _confirmBtnTimeText;
|
||||||
private Button _confirmButton;
|
private Button _confirmButton;
|
||||||
private bool _isCountingDown;
|
private bool _isCountingDown;
|
||||||
private MeetingContacts _meetingContacts;
|
private MeetingContactsController _meetingContactsController;
|
||||||
private Transform _messageText;
|
private Transform _messageText;
|
||||||
private Transform _nameText;
|
private Transform _nameText;
|
||||||
private MainPanel.UsersItem _usersItem;
|
private MainPanel.UsersItem _usersItem;
|
||||||
@@ -33,10 +33,10 @@ namespace Script
|
|||||||
return MainArchitecture.Interface;
|
return MainArchitecture.Interface;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetData(MainPanel.UsersItem item, MeetingContacts meetingContactsController)
|
public void SetData(MainPanel.UsersItem item, MeetingContactsController meetingContactsControllerController)
|
||||||
{
|
{
|
||||||
_usersItem = item;
|
_usersItem = item;
|
||||||
_meetingContacts = meetingContactsController;
|
_meetingContactsController = meetingContactsControllerController;
|
||||||
|
|
||||||
_background = transform.Find("headBackground/image").GetComponent<Image>();
|
_background = transform.Find("headBackground/image").GetComponent<Image>();
|
||||||
_backgroundName = transform.Find("headBackground/Name").GetComponent<Text>();
|
_backgroundName = transform.Find("headBackground/Name").GetComponent<Text>();
|
||||||
@@ -120,9 +120,9 @@ namespace Script
|
|||||||
Debug.Log($"点击了联系人: {_usersItem.name}");
|
Debug.Log($"点击了联系人: {_usersItem.name}");
|
||||||
// 这里可以添加点击联系人后的逻辑,比如打开聊天窗口
|
// 这里可以添加点击联系人后的逻辑,比如打开聊天窗口
|
||||||
// 或者发送邀请请求等
|
// 或者发送邀请请求等
|
||||||
_meetingContacts.ClickContactEntry(_background.GetComponent<Image>().sprite,
|
_meetingContactsController.ClickContactEntry(_background.GetComponent<Image>().sprite,
|
||||||
_backgroundName.GetComponent<Text>().text, _usersItem);
|
_backgroundName.GetComponent<Text>().text, _usersItem);
|
||||||
_meetingContacts.CurrentEntry = this;
|
_meetingContactsController.CurrentEntry = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StartCountdown()
|
public void StartCountdown()
|
||||||
|
|||||||
@@ -28,17 +28,17 @@ namespace Script
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 会议联系人类和面板
|
/// 会议联系人类和面板
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private MeetingContacts _meetingContacts;
|
private MeetingContactsController _meetingContactsController;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 会议参与者列表和面板
|
/// 会议参与者列表和面板
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private MeetingInfoList _meetingInfoList;
|
private MeetingInfoListController _meetingInfoListController;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 会议聊天面板
|
/// 会议聊天面板
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private MeetingChat _meetingChat;
|
private MeetingChatController _meetingChatController;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 房间人数
|
/// 房间人数
|
||||||
@@ -80,18 +80,18 @@ namespace Script
|
|||||||
_contactsTog = panelGo.transform.Find("Tabs/Contacts").GetComponent<Toggle>();
|
_contactsTog = panelGo.transform.Find("Tabs/Contacts").GetComponent<Toggle>();
|
||||||
_meetingOrganizersTog = panelGo.transform.Find("Tabs/MeetingOrganizers").GetComponent<Toggle>();
|
_meetingOrganizersTog = panelGo.transform.Find("Tabs/MeetingOrganizers").GetComponent<Toggle>();
|
||||||
|
|
||||||
_meetingContacts = new MeetingContacts();
|
_meetingContactsController = new MeetingContactsController();
|
||||||
_meetingContacts.Initialize(panelGo.transform.Find("MeetingContacts").gameObject);
|
_meetingContactsController.Initialize(panelGo.transform.Find("MeetingContacts").gameObject);
|
||||||
_meetingInfoList = new MeetingInfoList();
|
_meetingInfoListController = new MeetingInfoListController();
|
||||||
_meetingInfoList.Initialize(panelGo.transform.Find("MeetingInfoList").gameObject, this);
|
_meetingInfoListController.Initialize(panelGo.transform.Find("MeetingInfoList").gameObject, this);
|
||||||
_meetingChat = new MeetingChat();
|
_meetingChatController = new MeetingChatController();
|
||||||
_meetingChat.Initialize(panelGo.transform.Find("MeetingChat").gameObject, this);
|
_meetingChatController.Initialize(panelGo.transform.Find("MeetingChat").gameObject, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnEnter(Action complete = null)
|
public override void OnEnter(Action complete = null)
|
||||||
{
|
{
|
||||||
base.OnEnter(complete);
|
base.OnEnter(complete);
|
||||||
_meetingInfoList.OnEnter();
|
_meetingInfoListController.OnEnter();
|
||||||
_titleText.text = this.GetSystem<IGlobalConfigSystem>().GetConnectionName();
|
_titleText.text = this.GetSystem<IGlobalConfigSystem>().GetConnectionName();
|
||||||
this.GetSystem<IGlobalConfigSystem>().StartConnectionTime(_timeText);
|
this.GetSystem<IGlobalConfigSystem>().StartConnectionTime(_timeText);
|
||||||
_idText.text = this.GetSystem<IGlobalConfigSystem>().GetConnectionId();
|
_idText.text = this.GetSystem<IGlobalConfigSystem>().GetConnectionId();
|
||||||
@@ -107,7 +107,7 @@ namespace Script
|
|||||||
public override void OnExit(float delay = 0)
|
public override void OnExit(float delay = 0)
|
||||||
{
|
{
|
||||||
base.OnExit(delay);
|
base.OnExit(delay);
|
||||||
_meetingInfoList.OnExit();
|
_meetingInfoListController.OnExit();
|
||||||
_arrowLeft.onClick.RemoveListener(OnArrowLeftClick);
|
_arrowLeft.onClick.RemoveListener(OnArrowLeftClick);
|
||||||
_chatTog.onValueChanged.RemoveListener(OnChatTog);
|
_chatTog.onValueChanged.RemoveListener(OnChatTog);
|
||||||
_contactsTog.onValueChanged.RemoveListener(OnContactsTog);
|
_contactsTog.onValueChanged.RemoveListener(OnContactsTog);
|
||||||
@@ -131,7 +131,7 @@ namespace Script
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 更新会议聊天面板人数
|
// 更新会议聊天面板人数
|
||||||
_meetingChat.OnUserCountChangedEvent?.Invoke(obj.Count);
|
_meetingChatController.OnUserCountChangedEvent?.Invoke(obj.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnUsersChangedDisconnected(string obj)
|
private void OnUsersChangedDisconnected(string obj)
|
||||||
@@ -152,26 +152,26 @@ namespace Script
|
|||||||
}
|
}
|
||||||
|
|
||||||
_roomPeopleNumText.text = _userMap.Count.ToString();
|
_roomPeopleNumText.text = _userMap.Count.ToString();
|
||||||
_meetingChat.OnUserCountChangedEvent?.Invoke(_userMap.Count);
|
_meetingChatController.OnUserCountChangedEvent?.Invoke(_userMap.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnMeetingOrganizersTog(bool value)
|
private void OnMeetingOrganizersTog(bool value)
|
||||||
{
|
{
|
||||||
_meetingInfoList.PanelGo.SetActive(value);
|
_meetingInfoListController.PanelGo.SetActive(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnContactsTog(bool value)
|
private void OnContactsTog(bool value)
|
||||||
{
|
{
|
||||||
_meetingContacts.PanelGo.SetActive(value);
|
_meetingContactsController.PanelGo.SetActive(value);
|
||||||
if (value)
|
if (value)
|
||||||
_meetingContacts.OnEnter();
|
_meetingContactsController.OnEnter();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnChatTog(bool value)
|
private void OnChatTog(bool value)
|
||||||
{
|
{
|
||||||
_meetingChat.PanelGo.SetActive(value);
|
_meetingChatController.PanelGo.SetActive(value);
|
||||||
if (value)
|
if (value)
|
||||||
_meetingChat.OnEnter();
|
_meetingChatController.OnEnter();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnArrowLeftClick()
|
private void OnArrowLeftClick()
|
||||||
@@ -181,8 +181,8 @@ namespace Script
|
|||||||
public override void OnDestroy()
|
public override void OnDestroy()
|
||||||
{
|
{
|
||||||
base.OnDestroy();
|
base.OnDestroy();
|
||||||
_meetingChat.OnDestroy();
|
_meetingChatController.OnDestroy();
|
||||||
_meetingContacts.OnDestroy();
|
_meetingContactsController.OnDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using RenderStreaming;
|
using RenderStreaming;
|
||||||
using Script.Util;
|
using Script.Util;
|
||||||
@@ -10,7 +11,7 @@ using UnityEngine.UI;
|
|||||||
|
|
||||||
namespace Script
|
namespace Script
|
||||||
{
|
{
|
||||||
public class MeetingChat : IController
|
public class MeetingChatController : IController
|
||||||
{
|
{
|
||||||
public GameObject PanelGo;
|
public GameObject PanelGo;
|
||||||
private MainPanel _mainPanel;
|
private MainPanel _mainPanel;
|
||||||
@@ -62,6 +63,9 @@ namespace Script
|
|||||||
_objectLeftPool.AllRelease();
|
_objectLeftPool.AllRelease();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发送聊天信息
|
||||||
|
/// </summary>
|
||||||
private void OnSendButtonClick()
|
private void OnSendButtonClick()
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(_messageInput.text)) return;
|
if (string.IsNullOrEmpty(_messageInput.text)) return;
|
||||||
@@ -97,6 +101,9 @@ namespace Script
|
|||||||
SignalingMessageHelper.SendMessage(JsonConvert.SerializeObject(send));
|
SignalingMessageHelper.SendMessage(JsonConvert.SerializeObject(send));
|
||||||
_messageInput.text = "";
|
_messageInput.text = "";
|
||||||
chatData.isSelf = !chatData.isSelf;
|
chatData.isSelf = !chatData.isSelf;
|
||||||
|
var utc = DateTimeOffset.Parse(chatData.timestamp, CultureInfo.InvariantCulture);
|
||||||
|
var local = utc.ToLocalTime().ToString("HH:mm");
|
||||||
|
chatData.timestamp = local;
|
||||||
_chatDatas.Add(chatData);
|
_chatDatas.Add(chatData);
|
||||||
var entry = _objectRightPool.Get();
|
var entry = _objectRightPool.Get();
|
||||||
SetMessageEntry(chatData, entry);
|
SetMessageEntry(chatData, entry);
|
||||||
@@ -119,7 +126,7 @@ namespace Script
|
|||||||
var name = entry.transform.Find("name");
|
var name = entry.transform.Find("name");
|
||||||
var message = entry.transform.Find("message");
|
var message = entry.transform.Find("message");
|
||||||
var sprite = entry.transform.Find("sprite");
|
var sprite = entry.transform.Find("sprite");
|
||||||
|
var time = entry.transform.Find("message/messagebg/time");
|
||||||
if (string.IsNullOrEmpty(data.senderAvatar))
|
if (string.IsNullOrEmpty(data.senderAvatar))
|
||||||
{
|
{
|
||||||
var randomColor = WebRTCUtil.GetRandomColor();
|
var randomColor = WebRTCUtil.GetRandomColor();
|
||||||
@@ -148,6 +155,11 @@ namespace Script
|
|||||||
new Rect(0, 0, texture.width, texture.height),
|
new Rect(0, 0, texture.width, texture.height),
|
||||||
Vector2.one);
|
Vector2.one);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var utc = DateTimeOffset.Parse(data.timestamp, CultureInfo.InvariantCulture);
|
||||||
|
var local = utc.ToLocalTime().ToString("HH:mm");
|
||||||
|
data.timestamp = local;
|
||||||
|
time.GetComponent<Text>().text = data.timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnUserCountChanged(int obj)
|
private void OnUserCountChanged(int obj)
|
||||||
@@ -9,7 +9,7 @@ using UnityEngine.UI;
|
|||||||
|
|
||||||
namespace Script
|
namespace Script
|
||||||
{
|
{
|
||||||
public class MeetingContacts : IController
|
public class MeetingContactsController : IController
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 联系人列表项字典
|
/// 联系人列表项字典
|
||||||
@@ -1,14 +1,16 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using RenderStreaming;
|
using RenderStreaming;
|
||||||
using Script.Util;
|
using Script.Util;
|
||||||
using Stary.Evo;
|
using Stary.Evo;
|
||||||
|
using Stary.Evo.UIFarme;
|
||||||
using Unity.RenderStreaming;
|
using Unity.RenderStreaming;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
|
||||||
namespace Script
|
namespace Script
|
||||||
{
|
{
|
||||||
public class MeetingInfoList : IController
|
public class MeetingInfoListController : IController
|
||||||
{
|
{
|
||||||
private MainPanel _mainPanel;
|
private MainPanel _mainPanel;
|
||||||
public GameObject PanelGo;
|
public GameObject PanelGo;
|
||||||
@@ -29,6 +31,15 @@ namespace Script
|
|||||||
|
|
||||||
private GameObjectPool _objectPool;
|
private GameObjectPool _objectPool;
|
||||||
|
|
||||||
|
|
||||||
|
private Toggle _micTog;
|
||||||
|
private Toggle _videoTog;
|
||||||
|
private Toggle _recordTog;
|
||||||
|
private Button _hangUpTog;
|
||||||
|
|
||||||
|
private AudioStreamSender _audioStreamSender;
|
||||||
|
private VideoStreamSender _videoStreamSender;
|
||||||
|
|
||||||
public void Initialize(GameObject panelGo, MainPanel mainPanel)
|
public void Initialize(GameObject panelGo, MainPanel mainPanel)
|
||||||
{
|
{
|
||||||
PanelGo = panelGo;
|
PanelGo = panelGo;
|
||||||
@@ -37,18 +48,88 @@ namespace Script
|
|||||||
_content = panelGo.transform.Find("MeetingGrid/Viewport/Content");
|
_content = panelGo.transform.Find("MeetingGrid/Viewport/Content");
|
||||||
_meetingNum = panelGo.transform.Find("MeetingNum/Num").GetComponent<Text>();
|
_meetingNum = panelGo.transform.Find("MeetingNum/Num").GetComponent<Text>();
|
||||||
_objectPool = PanelGo.transform.Find("MeetingGrid/Pool").GetComponent<GameObjectPool>();
|
_objectPool = PanelGo.transform.Find("MeetingGrid/Pool").GetComponent<GameObjectPool>();
|
||||||
|
_micTog = PanelGo.transform.Find("menuBar/mic").GetComponent<Toggle>();
|
||||||
|
_videoTog = PanelGo.transform.Find("menuBar/video").GetComponent<Toggle>();
|
||||||
|
_recordTog = PanelGo.transform.Find("menuBar/record").GetComponent<Toggle>();
|
||||||
|
_hangUpTog = PanelGo.transform.Find("menuBar/hangUp").GetComponent<Button>();
|
||||||
|
_audioStreamSender = GameObject.Find("RenderStreaming").GetComponent<AudioStreamSender>();
|
||||||
|
_videoStreamSender = GameObject.Find("RenderStreaming").GetComponent<VideoStreamSender>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnEnter()
|
public void OnEnter()
|
||||||
{
|
{
|
||||||
LoadUsers();
|
LoadUsers();
|
||||||
|
_micTog.onValueChanged.AddListener(OnMicTogValueChanged);
|
||||||
|
_videoTog.onValueChanged.AddListener(OnVideoTogValueChanged);
|
||||||
|
_recordTog.onValueChanged.AddListener(OnRecordTogValueChanged);
|
||||||
|
_hangUpTog.onClick.AddListener(OnHangUpTogValueChanged);
|
||||||
|
|
||||||
GameObject.FindObjectOfType<MessageChannel>().OnMediaStateChangeReceived += OnMediaStateChangeReceived;
|
GameObject.FindObjectOfType<MessageChannel>().OnMediaStateChangeReceived += OnMediaStateChangeReceived;
|
||||||
GameObject.FindObjectOfType<MessageChannel>().OnUserInfoMessageReceived += OnUserInfoMessageReceived;
|
GameObject.FindObjectOfType<MessageChannel>().OnUserInfoMessageReceived += OnUserInfoMessageReceived;
|
||||||
GameObject.FindObjectOfType<HostConnection>().OnParticipantDisconnected += OnParticipantDisconnected;
|
GameObject.FindObjectOfType<HostConnection>().OnParticipantDisconnected += OnParticipantDisconnected;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
private void OnMicTogValueChanged(bool value)
|
||||||
|
{
|
||||||
|
var message = new
|
||||||
|
{
|
||||||
|
type = "on-message",
|
||||||
|
data = new
|
||||||
|
{
|
||||||
|
connectionId = this.GetSystem<IGlobalConfigSystem>().GetConnectionId(),
|
||||||
|
message = new
|
||||||
|
{
|
||||||
|
type = "media-state-changed",
|
||||||
|
data = new
|
||||||
|
{
|
||||||
|
userId = this.GetSystem<IGlobalConfigSystem>().GetUserId(),
|
||||||
|
audio = value,
|
||||||
|
video = _videoTog.isOn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
_audioStreamSender.enabled = value;
|
||||||
|
SignalingMessageHelper.SendMessage(JsonConvert.SerializeObject(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnVideoTogValueChanged(bool value)
|
||||||
|
{
|
||||||
|
var message = new
|
||||||
|
{
|
||||||
|
type = "on-message",
|
||||||
|
data = new
|
||||||
|
{
|
||||||
|
connectionId = this.GetSystem<IGlobalConfigSystem>().GetConnectionId(),
|
||||||
|
message = new
|
||||||
|
{
|
||||||
|
type = "media-state-changed",
|
||||||
|
data = new
|
||||||
|
{
|
||||||
|
userId = this.GetSystem<IGlobalConfigSystem>().GetUserId(),
|
||||||
|
audio = _micTog.isOn,
|
||||||
|
video = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
_videoStreamSender.enabled = value;
|
||||||
|
SignalingMessageHelper.SendMessage(JsonConvert.SerializeObject(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnRecordTogValueChanged(bool value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnHangUpTogValueChanged()
|
||||||
|
{
|
||||||
|
this.GetSystem<IRenderStreamingSystem>().HangUp();
|
||||||
|
this.GetSystem<IRenderStreamingSystem>().SetLocalVideoImage(null);
|
||||||
|
this.GetSystem<IPanelSystem>().PopQueue<MainPanel>();
|
||||||
|
this.GetSystem<IPanelSystem>().PushQueue<StartPanel>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
/// 当有用户断开连接时调用
|
/// 当有用户断开连接时调用
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id"></param>
|
/// <param name="id"></param>
|
||||||
@@ -225,6 +306,9 @@ namespace Script
|
|||||||
GameObject.FindObjectOfType<MessageChannel>().OnMediaStateChangeReceived -= OnMediaStateChangeReceived;
|
GameObject.FindObjectOfType<MessageChannel>().OnMediaStateChangeReceived -= OnMediaStateChangeReceived;
|
||||||
GameObject.FindObjectOfType<MessageChannel>().OnUserInfoMessageReceived -= OnUserInfoMessageReceived;
|
GameObject.FindObjectOfType<MessageChannel>().OnUserInfoMessageReceived -= OnUserInfoMessageReceived;
|
||||||
GameObject.FindObjectOfType<HostConnection>().OnParticipantDisconnected -= OnParticipantDisconnected;
|
GameObject.FindObjectOfType<HostConnection>().OnParticipantDisconnected -= OnParticipantDisconnected;
|
||||||
|
|
||||||
|
foreach (var info in _meetingList.Values) _objectPool.Release(info.participant);
|
||||||
|
_meetingList.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Destroy()
|
public void Destroy()
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
using RenderStreaming;
|
|
||||||
using Stary.Evo;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
public class MeetingChatController : MonoBehaviour, IController
|
|
||||||
{
|
|
||||||
public IArchitecture GetArchitecture()
|
|
||||||
{
|
|
||||||
return MainArchitecture.Interface;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: cd96585787c8a4d42b3ad979cf3e31e0
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using RenderStreaming;
|
|
||||||
using Stary.Evo;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
public class MeetingContactsController : MonoBehaviour ,IController
|
|
||||||
{
|
|
||||||
// Start is called before the first frame update
|
|
||||||
void Start()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update is called once per frame
|
|
||||||
void Update()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public IArchitecture GetArchitecture()
|
|
||||||
{
|
|
||||||
return MainArchitecture.Interface;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 19625967ea163c04095b4ef20880146a
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using RenderStreaming;
|
|
||||||
using Stary.Evo;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
public class MeetingInfoList : MonoBehaviour, IController
|
|
||||||
{
|
|
||||||
public Dictionary<GameObject, MeetingInfo> Meetings;
|
|
||||||
|
|
||||||
// Start is called before the first frame update
|
|
||||||
void Start()
|
|
||||||
{
|
|
||||||
Meetings = new Dictionary<GameObject, MeetingInfo>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update is called once per frame
|
|
||||||
void Update()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public IArchitecture GetArchitecture()
|
|
||||||
{
|
|
||||||
return MainArchitecture.Interface;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class MeetingInfo
|
|
||||||
{
|
|
||||||
public Texture2D Icon;
|
|
||||||
public string Name;
|
|
||||||
public string Message;
|
|
||||||
public bool Ismic;
|
|
||||||
public bool Iscam;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 1e57592024ba7ab4ab283f87f98a49e7
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
242
Assets/Script/RenderStreamingSystem.cs
Normal file
242
Assets/Script/RenderStreamingSystem.cs
Normal file
@@ -0,0 +1,242 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Stary.Evo;
|
||||||
|
using Unity.RenderStreaming;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
namespace Script
|
||||||
|
{
|
||||||
|
public interface IRenderStreamingSystem : ISystem
|
||||||
|
{
|
||||||
|
void SetUp();
|
||||||
|
void HangUp();
|
||||||
|
|
||||||
|
void SetLocalVideoImage(RawImage localVideoImage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RenderStreamingSystem : AbstractSystem, IRenderStreamingSystem
|
||||||
|
{
|
||||||
|
[Header("核心组件")] private RenderStreamingSettings settings;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Host连接
|
||||||
|
/// </summary>
|
||||||
|
private HostConnection hostConnection;
|
||||||
|
|
||||||
|
[Header("Host本地视频")] private VideoStreamSender videoStreamSender;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 麦克风流发送器
|
||||||
|
/// </summary>
|
||||||
|
private AudioStreamSender microphoneStreamer;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 每个Participant的UI信息
|
||||||
|
/// </summary>
|
||||||
|
private readonly Dictionary<string, ParticipantUI> participantUIs = new();
|
||||||
|
|
||||||
|
|
||||||
|
[Header("Participant视频容器")] private Transform participantVideoContainer;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 渲染流管理
|
||||||
|
/// </summary>
|
||||||
|
private SignalingManager _signalingManager;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 本地视频显示
|
||||||
|
/// </summary>
|
||||||
|
private RawImage localVideoImage;
|
||||||
|
|
||||||
|
protected override void OnInit()
|
||||||
|
{
|
||||||
|
var renderStreaming = GameObject.Find("RenderStreaming").transform;
|
||||||
|
_signalingManager = renderStreaming.GetComponent<SignalingManager>();
|
||||||
|
hostConnection = renderStreaming.GetComponent<HostConnection>();
|
||||||
|
videoStreamSender = hostConnection.GetComponent<VideoStreamSender>();
|
||||||
|
microphoneStreamer = hostConnection.GetComponent<AudioStreamSender>();
|
||||||
|
if (settings == null)
|
||||||
|
settings = new RenderStreamingSettings();
|
||||||
|
if (settings != null)
|
||||||
|
{
|
||||||
|
videoStreamSender.width = (uint)settings.StreamSize.x;
|
||||||
|
videoStreamSender.height = (uint)settings.StreamSize.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_signalingManager.runOnAwake)
|
||||||
|
return;
|
||||||
|
if (settings != null)
|
||||||
|
_signalingManager.useDefaultSettings = settings.UseDefaultSettings;
|
||||||
|
if (settings?.SignalingSettings != null)
|
||||||
|
_signalingManager.SetSignalingSettings(settings.SignalingSettings);
|
||||||
|
if (settings != null)
|
||||||
|
videoStreamSender.SetCodec(settings.SenderVideoCodec);
|
||||||
|
_signalingManager.Run();
|
||||||
|
|
||||||
|
|
||||||
|
if (hostConnection != null)
|
||||||
|
{
|
||||||
|
hostConnection.OnParticipantConnected += HandleParticipantConnected;
|
||||||
|
hostConnection.OnParticipantDisconnected += HandleParticipantDisconnected;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 本地视频:Sender启动后显示
|
||||||
|
videoStreamSender.OnStartedStream += OnStartedStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override void Dispose()
|
||||||
|
{
|
||||||
|
if (hostConnection != null)
|
||||||
|
{
|
||||||
|
hostConnection.OnParticipantConnected -= HandleParticipantConnected;
|
||||||
|
hostConnection.OnParticipantDisconnected -= HandleParticipantDisconnected;
|
||||||
|
}
|
||||||
|
|
||||||
|
videoStreamSender.OnStartedStream -= OnStartedStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnStartedStream(string id)
|
||||||
|
{
|
||||||
|
if (videoStreamSender.sourceWebCamTexture != null && localVideoImage != null)
|
||||||
|
localVideoImage.texture = videoStreamSender.sourceWebCamTexture;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetUp()
|
||||||
|
{
|
||||||
|
videoStreamSender.enabled = true;
|
||||||
|
microphoneStreamer.enabled = true;
|
||||||
|
hostConnection.RoomConnectionId = this.GetSystem<IGlobalConfigSystem>().GetConnectionId();
|
||||||
|
hostConnection.CreateConnection(hostConnection.RoomConnectionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HangUp()
|
||||||
|
{
|
||||||
|
videoStreamSender.enabled = false;
|
||||||
|
microphoneStreamer.enabled = false;
|
||||||
|
hostConnection.DeleteConnection(hostConnection.RoomConnectionId);
|
||||||
|
|
||||||
|
// 清理所有Participant UI
|
||||||
|
foreach (var ui in participantUIs.Values)
|
||||||
|
if (ui.root != null)
|
||||||
|
GameObject.Destroy(ui.root);
|
||||||
|
|
||||||
|
participantUIs.Clear();
|
||||||
|
if (localVideoImage != null)
|
||||||
|
localVideoImage.texture = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetLocalVideoImage(RawImage localVideoImage)
|
||||||
|
{
|
||||||
|
this.localVideoImage = localVideoImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region 开启相关
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 新Participant连接成功回调
|
||||||
|
/// 此时Participant的独立Receiver已创建,可以绑定视频显示
|
||||||
|
/// </summary>
|
||||||
|
private void HandleParticipantConnected(ParticipantStreams ps)
|
||||||
|
{
|
||||||
|
// 创建Participant UI
|
||||||
|
var ui = CreateParticipantUI(ps.participantId);
|
||||||
|
participantUIs[ps.participantId] = ui;
|
||||||
|
|
||||||
|
// 绑定视频:当Receiver收到纹理时更新RawImage
|
||||||
|
ps.videoReceiver.OnUpdateReceiveTexture += texture =>
|
||||||
|
{
|
||||||
|
ui.videoImage.color = Color.white;
|
||||||
|
// 防止纹理为null时导致RawImage闪黑(重协商/track切换时可能短暂为null)
|
||||||
|
if (ui.videoImage != null && texture != null)
|
||||||
|
ui.videoImage.texture = texture;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 绑定音频:AudioSource已在HostConnection中配置
|
||||||
|
ps.audioReceiver.OnUpdateReceiveAudioSource += source =>
|
||||||
|
{
|
||||||
|
if (source != null && !source.isPlaying)
|
||||||
|
{
|
||||||
|
source.loop = true;
|
||||||
|
source.Play();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Debug.Log($"[MultiParticipantHost] Participant UI created: {ps.participantId}");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 动态创建单个Participant的视频显示UI
|
||||||
|
/// 结构: [NameLabel] + [RawImage(视频画面)]
|
||||||
|
/// </summary>
|
||||||
|
private ParticipantUI CreateParticipantUI(string participantId)
|
||||||
|
{
|
||||||
|
var ui = new ParticipantUI();
|
||||||
|
|
||||||
|
// 根节点
|
||||||
|
ui.root = new GameObject($"ParticipantUI_{participantId}");
|
||||||
|
ui.root.transform.SetParent(participantVideoContainer, false);
|
||||||
|
// 添加VerticalLayoutGroup使内容垂直排列
|
||||||
|
var vlg = ui.root.AddComponent<VerticalLayoutGroup>();
|
||||||
|
vlg.childControlWidth = true;
|
||||||
|
vlg.childControlHeight = false;
|
||||||
|
vlg.childForceExpandWidth = true;
|
||||||
|
vlg.childForceExpandHeight = false;
|
||||||
|
vlg.spacing = 2;
|
||||||
|
ui.root.transform.GetComponent<RectTransform>().anchorMin = Vector2.zero;
|
||||||
|
ui.root.transform.GetComponent<RectTransform>().anchorMax = Vector2.one;
|
||||||
|
// 名称标签
|
||||||
|
var labelObj = new GameObject("NameLabel");
|
||||||
|
labelObj.transform.SetParent(ui.root.transform, false);
|
||||||
|
ui.nameLabel = labelObj.AddComponent<Text>();
|
||||||
|
ui.nameLabel.text = $"Participant: {participantId}";
|
||||||
|
ui.nameLabel.fontSize = 14;
|
||||||
|
ui.nameLabel.color = Color.white;
|
||||||
|
ui.nameLabel.alignment = TextAnchor.MiddleCenter;
|
||||||
|
var labelLayout = labelObj.AddComponent<LayoutElement>();
|
||||||
|
labelLayout.preferredHeight = 20;
|
||||||
|
|
||||||
|
// 视频画面
|
||||||
|
var imageObj = new GameObject("VideoImage");
|
||||||
|
imageObj.transform.SetParent(ui.root.transform, false);
|
||||||
|
ui.videoImage = imageObj.AddComponent<RawImage>();
|
||||||
|
ui.videoImage.color = Color.black;
|
||||||
|
var imageLayout = imageObj.AddComponent<LayoutElement>();
|
||||||
|
imageLayout.preferredHeight = 200;
|
||||||
|
|
||||||
|
// AspectRatioFitter保持视频比例
|
||||||
|
var aspectRatio = imageObj.AddComponent<AspectRatioFitter>();
|
||||||
|
aspectRatio.aspectMode = AspectRatioFitter.AspectMode.FitInParent;
|
||||||
|
aspectRatio.aspectRatio = 16f / 9f;
|
||||||
|
|
||||||
|
return ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Participant断开连接回调
|
||||||
|
/// 销毁其UI
|
||||||
|
/// </summary>
|
||||||
|
private void HandleParticipantDisconnected(string participantId)
|
||||||
|
{
|
||||||
|
if (participantUIs.TryGetValue(participantId, out var ui))
|
||||||
|
{
|
||||||
|
if (ui.root != null)
|
||||||
|
GameObject.Destroy(ui.root);
|
||||||
|
participantUIs.Remove(participantId);
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.Log($"[MultiParticipantHost] Participant UI removed: {participantId}");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ParticipantUI
|
||||||
|
{
|
||||||
|
public Text nameLabel;
|
||||||
|
public GameObject root;
|
||||||
|
public RawImage videoImage;
|
||||||
|
}
|
||||||
|
}
|
||||||
3
Assets/Script/RenderStreamingSystem.cs.meta
Normal file
3
Assets/Script/RenderStreamingSystem.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: a92be42fdf2e46899bd9e52daf0ad589
|
||||||
|
timeCreated: 1779630178
|
||||||
@@ -13,11 +13,6 @@ namespace Unity.RenderStreaming
|
|||||||
{
|
{
|
||||||
public class StartPanel : BasePanel
|
public class StartPanel : BasePanel
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// 每个Participant的UI信息
|
|
||||||
/// </summary>
|
|
||||||
private readonly Dictionary<string, ParticipantUI> participantUIs = new();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 返回按钮
|
/// 返回按钮
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -60,30 +55,6 @@ namespace Unity.RenderStreaming
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private Dropdown _timeDropdown;
|
private Dropdown _timeDropdown;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Host连接
|
|
||||||
/// </summary>
|
|
||||||
private HostConnection hostConnection;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 本地视频显示
|
|
||||||
/// </summary>
|
|
||||||
private RawImage localVideoImage;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 麦克风流发送器
|
|
||||||
/// </summary>
|
|
||||||
private AudioStreamSender microphoneStreamer;
|
|
||||||
|
|
||||||
[Header("Participant视频容器")] private Transform participantVideoContainer;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 渲染流管理
|
|
||||||
/// </summary>
|
|
||||||
private SignalingManager renderStreaming;
|
|
||||||
|
|
||||||
[Header("核心组件")] private RenderStreamingSettings settings;
|
|
||||||
[Header("Host本地视频")] private VideoStreamSender videoStreamSender;
|
|
||||||
|
|
||||||
public override UITweenType TweenType => UITweenType.Fade;
|
public override UITweenType TweenType => UITweenType.Fade;
|
||||||
|
|
||||||
@@ -109,26 +80,6 @@ namespace Unity.RenderStreaming
|
|||||||
|
|
||||||
_profileSpriteIndex = 0;
|
_profileSpriteIndex = 0;
|
||||||
OnClickProfilePhoto();
|
OnClickProfilePhoto();
|
||||||
|
|
||||||
renderStreaming = GameObject.FindObjectOfType<SignalingManager>();
|
|
||||||
hostConnection = GameObject.FindObjectOfType<HostConnection>();
|
|
||||||
videoStreamSender = hostConnection.GetComponent<VideoStreamSender>();
|
|
||||||
microphoneStreamer = hostConnection.GetComponent<AudioStreamSender>();
|
|
||||||
if (settings == null)
|
|
||||||
settings = new RenderStreamingSettings();
|
|
||||||
if (settings != null)
|
|
||||||
{
|
|
||||||
videoStreamSender.width = (uint)settings.StreamSize.x;
|
|
||||||
videoStreamSender.height = (uint)settings.StreamSize.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (renderStreaming.runOnAwake)
|
|
||||||
return;
|
|
||||||
if (settings != null)
|
|
||||||
renderStreaming.useDefaultSettings = settings.UseDefaultSettings;
|
|
||||||
if (settings?.SignalingSettings != null)
|
|
||||||
renderStreaming.SetSignalingSettings(settings.SignalingSettings);
|
|
||||||
renderStreaming.Run();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnEnter(Action complete = null)
|
public override void OnEnter(Action complete = null)
|
||||||
@@ -139,14 +90,6 @@ namespace Unity.RenderStreaming
|
|||||||
_randomMeetingId.onClick.AddListener(OnClickRandomMeetingId);
|
_randomMeetingId.onClick.AddListener(OnClickRandomMeetingId);
|
||||||
|
|
||||||
_startButton.onClick.AddListener(OnClickStartButton);
|
_startButton.onClick.AddListener(OnClickStartButton);
|
||||||
if (hostConnection != null)
|
|
||||||
{
|
|
||||||
hostConnection.OnParticipantConnected += HandleParticipantConnected;
|
|
||||||
hostConnection.OnParticipantDisconnected += HandleParticipantDisconnected;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 本地视频:Sender启动后显示
|
|
||||||
videoStreamSender.OnStartedStream += OnStartedStream;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -157,13 +100,6 @@ namespace Unity.RenderStreaming
|
|||||||
_profilePhoto.onClick.RemoveListener(OnClickProfilePhoto);
|
_profilePhoto.onClick.RemoveListener(OnClickProfilePhoto);
|
||||||
_randomMeetingId.onClick.RemoveListener(OnClickRandomMeetingId);
|
_randomMeetingId.onClick.RemoveListener(OnClickRandomMeetingId);
|
||||||
_startButton.onClick.RemoveListener(OnClickStartButton);
|
_startButton.onClick.RemoveListener(OnClickStartButton);
|
||||||
if (hostConnection != null)
|
|
||||||
{
|
|
||||||
hostConnection.OnParticipantConnected -= HandleParticipantConnected;
|
|
||||||
hostConnection.OnParticipantDisconnected -= HandleParticipantDisconnected;
|
|
||||||
}
|
|
||||||
|
|
||||||
videoStreamSender.OnStartedStream -= OnStartedStream;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnClickProfilePhoto()
|
private void OnClickProfilePhoto()
|
||||||
@@ -196,7 +132,7 @@ namespace Unity.RenderStreaming
|
|||||||
this.GetSystem<IGlobalConfigSystem>().SetUserId(OnClickRandomUserId());
|
this.GetSystem<IGlobalConfigSystem>().SetUserId(OnClickRandomUserId());
|
||||||
this.GetSystem<IGlobalConfigSystem>().SetConnectionTimeType(_timeDropdown.value);
|
this.GetSystem<IGlobalConfigSystem>().SetConnectionTimeType(_timeDropdown.value);
|
||||||
this.GetSystem<IGlobalConfigSystem>().SetConnectionId(_meetingId.text);
|
this.GetSystem<IGlobalConfigSystem>().SetConnectionId(_meetingId.text);
|
||||||
hostConnection.RoomConnectionId = this.GetSystem<IGlobalConfigSystem>().GetConnectionId();
|
|
||||||
this.GetSystem<IGlobalConfigSystem>().SetConnectionName(_meetingNameInput.text);
|
this.GetSystem<IGlobalConfigSystem>().SetConnectionName(_meetingNameInput.text);
|
||||||
if (!SignalingMessageHelper.IsReady())
|
if (!SignalingMessageHelper.IsReady())
|
||||||
{
|
{
|
||||||
@@ -216,146 +152,9 @@ namespace Unity.RenderStreaming
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
SignalingMessageHelper.SendMessage(JsonConvert.SerializeObject(userInfo));
|
SignalingMessageHelper.SendMessage(JsonConvert.SerializeObject(userInfo));
|
||||||
SetUp();
|
this.GetSystem<IRenderStreamingSystem>().SetUp();
|
||||||
PanelSystem.PopQueue<StartPanel>();
|
PanelSystem.PopQueue<StartPanel>();
|
||||||
PanelSystem.PushQueue<MainPanel>();
|
PanelSystem.PushQueue<MainPanel>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnStartedStream(string id)
|
|
||||||
{
|
|
||||||
if (videoStreamSender.sourceWebCamTexture != null)
|
|
||||||
localVideoImage.texture = videoStreamSender.sourceWebCamTexture;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ParticipantUI
|
|
||||||
{
|
|
||||||
public Text nameLabel;
|
|
||||||
public GameObject root;
|
|
||||||
public RawImage videoImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#region 开启相关
|
|
||||||
|
|
||||||
private void SetUp()
|
|
||||||
{
|
|
||||||
videoStreamSender.enabled = true;
|
|
||||||
|
|
||||||
if (settings != null)
|
|
||||||
videoStreamSender.SetCodec(settings.SenderVideoCodec);
|
|
||||||
|
|
||||||
hostConnection.CreateConnection(hostConnection.RoomConnectionId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void HangUp()
|
|
||||||
{
|
|
||||||
hostConnection.DeleteConnection(hostConnection.RoomConnectionId);
|
|
||||||
|
|
||||||
// 清理所有Participant UI
|
|
||||||
foreach (var ui in participantUIs.Values)
|
|
||||||
if (ui.root != null)
|
|
||||||
GameObject.Destroy(ui.root);
|
|
||||||
|
|
||||||
participantUIs.Clear();
|
|
||||||
|
|
||||||
localVideoImage.texture = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 新Participant连接成功回调
|
|
||||||
/// 此时Participant的独立Receiver已创建,可以绑定视频显示
|
|
||||||
/// </summary>
|
|
||||||
private void HandleParticipantConnected(ParticipantStreams ps)
|
|
||||||
{
|
|
||||||
// 创建Participant UI
|
|
||||||
var ui = CreateParticipantUI(ps.participantId);
|
|
||||||
participantUIs[ps.participantId] = ui;
|
|
||||||
|
|
||||||
// 绑定视频:当Receiver收到纹理时更新RawImage
|
|
||||||
ps.videoReceiver.OnUpdateReceiveTexture += texture =>
|
|
||||||
{
|
|
||||||
ui.videoImage.color = Color.white;
|
|
||||||
// 防止纹理为null时导致RawImage闪黑(重协商/track切换时可能短暂为null)
|
|
||||||
if (ui.videoImage != null && texture != null)
|
|
||||||
ui.videoImage.texture = texture;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 绑定音频:AudioSource已在HostConnection中配置
|
|
||||||
ps.audioReceiver.OnUpdateReceiveAudioSource += source =>
|
|
||||||
{
|
|
||||||
if (source != null && !source.isPlaying)
|
|
||||||
{
|
|
||||||
source.loop = true;
|
|
||||||
source.Play();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Debug.Log($"[MultiParticipantHost] Participant UI created: {ps.participantId}");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 动态创建单个Participant的视频显示UI
|
|
||||||
/// 结构: [NameLabel] + [RawImage(视频画面)]
|
|
||||||
/// </summary>
|
|
||||||
private ParticipantUI CreateParticipantUI(string participantId)
|
|
||||||
{
|
|
||||||
var ui = new ParticipantUI();
|
|
||||||
|
|
||||||
// 根节点
|
|
||||||
ui.root = new GameObject($"ParticipantUI_{participantId}");
|
|
||||||
ui.root.transform.SetParent(participantVideoContainer, false);
|
|
||||||
// 添加VerticalLayoutGroup使内容垂直排列
|
|
||||||
var vlg = ui.root.AddComponent<VerticalLayoutGroup>();
|
|
||||||
vlg.childControlWidth = true;
|
|
||||||
vlg.childControlHeight = false;
|
|
||||||
vlg.childForceExpandWidth = true;
|
|
||||||
vlg.childForceExpandHeight = false;
|
|
||||||
vlg.spacing = 2;
|
|
||||||
ui.root.transform.GetComponent<RectTransform>().anchorMin = Vector2.zero;
|
|
||||||
ui.root.transform.GetComponent<RectTransform>().anchorMax = Vector2.one;
|
|
||||||
// 名称标签
|
|
||||||
var labelObj = new GameObject("NameLabel");
|
|
||||||
labelObj.transform.SetParent(ui.root.transform, false);
|
|
||||||
ui.nameLabel = labelObj.AddComponent<Text>();
|
|
||||||
ui.nameLabel.text = $"Participant: {participantId}";
|
|
||||||
ui.nameLabel.fontSize = 14;
|
|
||||||
ui.nameLabel.color = Color.white;
|
|
||||||
ui.nameLabel.alignment = TextAnchor.MiddleCenter;
|
|
||||||
var labelLayout = labelObj.AddComponent<LayoutElement>();
|
|
||||||
labelLayout.preferredHeight = 20;
|
|
||||||
|
|
||||||
// 视频画面
|
|
||||||
var imageObj = new GameObject("VideoImage");
|
|
||||||
imageObj.transform.SetParent(ui.root.transform, false);
|
|
||||||
ui.videoImage = imageObj.AddComponent<RawImage>();
|
|
||||||
ui.videoImage.color = Color.black;
|
|
||||||
var imageLayout = imageObj.AddComponent<LayoutElement>();
|
|
||||||
imageLayout.preferredHeight = 200;
|
|
||||||
|
|
||||||
// AspectRatioFitter保持视频比例
|
|
||||||
var aspectRatio = imageObj.AddComponent<AspectRatioFitter>();
|
|
||||||
aspectRatio.aspectMode = AspectRatioFitter.AspectMode.FitInParent;
|
|
||||||
aspectRatio.aspectRatio = 16f / 9f;
|
|
||||||
|
|
||||||
return ui;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Participant断开连接回调
|
|
||||||
/// 销毁其UI
|
|
||||||
/// </summary>
|
|
||||||
private void HandleParticipantDisconnected(string participantId)
|
|
||||||
{
|
|
||||||
if (participantUIs.TryGetValue(participantId, out var ui))
|
|
||||||
{
|
|
||||||
if (ui.root != null)
|
|
||||||
GameObject.Destroy(ui.root);
|
|
||||||
participantUIs.Remove(participantId);
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug.Log($"[MultiParticipantHost] Participant UI removed: {participantId}");
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -214,7 +214,9 @@ namespace Unity.RenderStreaming.Signaling
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private bool IsParticipantConnectionId(string connectionId)
|
private bool IsParticipantConnectionId(string connectionId)
|
||||||
{
|
{
|
||||||
return m_participantToRoom.ContainsKey(connectionId);
|
if (!string.IsNullOrEmpty(connectionId) && m_participantToRoom != null && m_participantToRoom.Count > 0)
|
||||||
|
return m_participantToRoom.ContainsKey(connectionId);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user