Skip to content

Commit 170bed4

Browse files
committed
fix behavior
1 parent d5f87f8 commit 170bed4

File tree

3 files changed

+83
-107
lines changed

3 files changed

+83
-107
lines changed
Lines changed: 4 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,3 @@
1-
.message-feed {
2-
width: 480%;
3-
height: 250px;
4-
border-radius: 5px;
5-
border: solid 1px rgb(204, 204, 204);
6-
padding: 10px;
7-
position: absolute;
8-
left: 64px;
9-
top: 500px;
10-
}
11-
12-
.message-item {
13-
font-size: 14px;
14-
color: rgb(51, 51, 51);
15-
padding: 8px;
16-
margin-bottom: 8px;
17-
border-radius: 4px;
18-
word-wrap: break-word;
19-
width: 480px;
20-
height: 50px;
21-
position: absolute;
22-
top: 500px;
23-
left: 64px;
24-
}
25-
261
.message {
272
color: rgb(255, 193, 21);
283
font-size: 14px;
@@ -39,17 +14,15 @@
3914

4015
.messageBox {
4116
background-image: url("project://database/Assets/Textures/UI/ui_healthbar_bg.png?fileID=2800000&guid=ac1ab0ffbf410094088db89d509a3a4a&type=3#ui_healthbar_bg");
42-
margin-top: 8px;
43-
margin-bottom: 8px;
4417
width: auto;
4518
height: 26px;
4619
translate: -150% 0 0;
4720
transition-property: translate, opacity;
4821
transition-timing-function: ease-in-out-back, ease-in;
4922
transition-duration: 0.5s, 1s;
5023
position: relative;
51-
overflow: scroll;
52-
flex-direction: column;
24+
overflow: hidden;
25+
flex-direction: column;
5326
}
5427

5528
.messageBoxMove {
@@ -60,8 +33,8 @@
6033
opacity: 0;
6134
}
6235

63-
#messageList {
36+
#messageFeed {
6437
flex-direction: column;
6538
position: absolute;
6639
top: -537px;
67-
}
40+
}
Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
<engine:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:engine="UnityEngine.UIElements" xmlns:editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
22
<Style src="project://database/Assets/Prefabs/UI/UIToolkit/USS/MessageFeed.uss?fileID=7433441132597879392&amp;guid=daa8504d262853748b8d7c2a377261a3&amp;type=3#MessageFeed" />
3-
<engine:VisualElement name="messageFeed" style="flex-grow: 1;">
4-
<engine:ListView item-template="project://database/Assets/Prefabs/UI/UIToolkit/UXML/MessageItem.uxml?fileID=9197481963319205126&amp;guid=67ec44aea0b0f484c86c6489932cfcad&amp;type=3#MessageItem" name="messageList" virtualization-method="FixedHeight" binding-source-selection-mode="AutoAssign" selection-type="None" show-bound-collection-size="true" allow-remove="true" class="messageList" />
5-
</engine:VisualElement>
3+
<engine:VisualElement name="messageFeed" picking-mode="Ignore" />
64
</engine:UXML>

Assets/Scripts/Gameplay/UI/MessageFeed.cs

Lines changed: 78 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
2-
using System.Collections;
32
using System.Collections.Generic;
3+
using System.Collections.ObjectModel;
4+
using System.Collections.Specialized;
45
using UnityEngine;
56
using UnityEngine.UIElements;
67
using Unity.BossRoom.ConnectionManagement;
@@ -20,10 +21,10 @@ public class MessageFeed : MonoBehaviour
2021
[SerializeField]
2122
UIDocument doc;
2223

23-
List<MessageViewModel> m_Messages;
24+
ObservableCollection<MessageViewModel> m_Messages;
2425
List<MessageViewModel> m_MessagesToRemove = new List<MessageViewModel>();
2526

26-
ListView m_MessageContainer;
27+
VisualElement m_MessageContainer;
2728

2829
DisposableGroup m_Subscriptions;
2930

@@ -108,56 +109,18 @@ public void AddMessage()
108109
ShowMessage($"Hello! {DateTime.Now.Millisecond}");
109110
}
110111

111-
//would be much nicer if this would be a custom control, and we'd do this in an attach to panel event
112+
// would be much nicer if this would be a custom control, and we'd do this in an attach to panel event
112113
void Start()
113114
{
114115
var root = doc.rootVisualElement;
115116

116-
m_Messages = new List<MessageViewModel>();
117+
m_Messages = new ObservableCollection<MessageViewModel>();
117118

118119
// Find the container of all messages
119-
var listView = root.Q<ListView>("messageList");
120+
m_MessageContainer = root.Q<VisualElement>("messageFeed");
120121

121-
// Since you've added an item template in the UXML this is not really necessary here
122-
listView.makeItem += () =>
123-
{
124-
// Create a new message if no reusable messages are available
125-
var newBox = new VisualElement();
126-
newBox.AddToClassList(k_MessageBoxClassName);
127-
128-
var newLabel = new Label();
129-
newLabel.AddToClassList(k_MessageClassName);
130-
newBox.Add(newLabel);
131-
132-
// the event when the control get's added to the "UI Canvas"
133-
newBox.RegisterCallback<AttachToPanelEvent>((e) =>
134-
{
135-
if (e.target is VisualElement element)
136-
{
137-
element.RemoveFromClassList(k_MessageBoxMovementClassName);
138-
StartCoroutine(ToggleClassWithDelay(element, k_MessageBoxMovementClassName, TimeSpan.FromSeconds(0.02)));
139-
}
140-
});
141-
142-
// fires just before the element is actually removed
143-
newBox.RegisterCallback<DetachFromPanelEvent>((e) =>
144-
{
145-
if (e.target is VisualElement) { }
146-
});
147-
148-
return newBox;
149-
};
150-
151-
// use this to set bindings / values on your view components
152-
listView.bindItem += (element, i) =>
153-
{
154-
var label = element.Q<Label>();
155-
label.text = m_Messages[i].Message;
156-
};
157-
158-
// collection change events will take care of creating and disposing items
159-
listView.itemsSource = m_Messages;
160-
m_MessageContainer = listView;
122+
// This will handle the addition and removal of the message presenters
123+
m_Messages.CollectionChanged += OnMessageCollectionChanged;
161124
}
162125

163126
void OnDestroy()
@@ -184,39 +147,19 @@ void Update()
184147
foreach (var message in m_MessagesToRemove)
185148
{
186149
var childQuery = m_MessageContainer.Query<VisualElement>().Class(k_MessageBoxClassName);
187-
var child = childQuery.AtIndex(m_Messages.IndexOf(message));
150+
var child = childQuery.Where(a => a.Q<Label>().text == message.Message).First();
188151

189152
if (!child.ClassListContains(k_FadeOutClassName))
190153
{
191154
child.AddToClassList(k_FadeOutClassName);
192155
child.RegisterCallback<TransitionEndEvent>(OnTransitionEndEvent);
193-
child.RegisterCallback<TransitionCancelEvent>(OnTransitionCancelEvent);
194156
}
195157

196-
void OnTransitionCancelEvent(TransitionCancelEvent e)
197-
{
198-
m_Messages.Remove(message);
199-
m_MessagesToRemove.Remove(message);
200-
if (e.target is VisualElement element)
201-
{
202-
element.RemoveFromClassList(k_FadeOutClassName);
203-
}
204-
}
205-
206158
// local event handler function
207159
void OnTransitionEndEvent(TransitionEndEvent e)
208160
{
209-
if (e.target is VisualElement element)
161+
if (e.target is VisualElement element)
210162
{
211-
// remove subscription
212-
element.UnregisterCallback<TransitionEndEvent>(OnTransitionEndEvent);
213-
214-
element.RemoveFromClassList(k_FadeOutClassName);
215-
216-
// moving the message to be the last visualized in the container
217-
// effectively stopping the list view virtualization caused animation issues
218-
m_MessageContainer.viewController.Move(m_Messages.IndexOf(message), m_Messages.Count - 1);
219-
220163
m_Messages.Remove(message);
221164
m_MessagesToRemove.Remove(message);
222165
}
@@ -226,19 +169,81 @@ void OnTransitionEndEvent(TransitionEndEvent e)
226169

227170
void ShowMessage(string message)
228171
{
172+
// we create a new message view model that will time out in 5 seconds
229173
var newMessage = new MessageViewModel(message, TimeSpan.FromSeconds(5));
230-
174+
// we add the message to the observable collection, triggering the visualization
231175
m_Messages.Add(newMessage); // Add to the list of messages
232176
}
233177

234-
IEnumerator ToggleClassWithDelay(VisualElement element, string className, TimeSpan delay)
178+
private void OnMessageCollectionChanged(object sender, NotifyCollectionChangedEventArgs eventArgs)
179+
{
180+
switch (eventArgs.Action)
181+
{
182+
case NotifyCollectionChangedAction.Add:
183+
OnMessagesAdded(eventArgs);
184+
break;
185+
case NotifyCollectionChangedAction.Remove:
186+
OnMessagesRemoved(eventArgs);
187+
break;
188+
default:
189+
Debug.LogWarning("Collection was modified in an unexpected way");
190+
break;
191+
}
192+
}
193+
194+
private void OnMessagesRemoved(NotifyCollectionChangedEventArgs eventArgs)
235195
{
236-
yield return new WaitForSeconds((float)delay.TotalSeconds);
196+
foreach (var itemToRemove in eventArgs.OldItems)
197+
{
198+
if (itemToRemove is MessageViewModel messageViewModel)
199+
{
200+
var childQuery = m_MessageContainer.Query<VisualElement>().Class(k_MessageBoxClassName);
201+
var child = childQuery.Where(a => a.Q<Label>().text == messageViewModel.Message).First();
202+
// manually removing the child item from the message feed
203+
m_MessageContainer.contentContainer.Remove(child);
204+
}
205+
}
206+
}
207+
208+
private void OnMessagesAdded(NotifyCollectionChangedEventArgs eventArgs)
209+
{
210+
foreach (var message in eventArgs.NewItems)
211+
{
212+
if (message is not MessageViewModel messageViewModel)
213+
return;
237214

238-
element.ToggleInClassList(className);
215+
// Create a new messageBox
216+
var messageBox = new VisualElement();
217+
messageBox.AddToClassList(k_MessageBoxClassName);
218+
219+
var messagePresenter = new Label();
220+
messagePresenter.AddToClassList(k_MessageClassName);
221+
messagePresenter.text = messageViewModel.Message;
222+
// Add the message presenter into the box
223+
messageBox.Add(messagePresenter);
224+
225+
// the event when the control get's added to the "UI Canvas"
226+
messageBox.RegisterCallback<AttachToPanelEvent>(OnAttachToPanelEvent);
227+
228+
// Add the message box to the message Feed
229+
m_MessageContainer.contentContainer.Add(messageBox);
230+
231+
return;
232+
233+
void OnAttachToPanelEvent(AttachToPanelEvent evt)
234+
{
235+
if (evt.target is VisualElement element)
236+
{
237+
// we set up the control in a way that it starts with an offset.
238+
// we schedule the transition for the message to snap in back to it's intended position
239+
element.schedule
240+
.Execute(() => element.ToggleInClassList(k_MessageBoxMovementClassName))
241+
.ExecuteLater(200);
242+
}
243+
}
244+
}
239245
}
240246

241-
// if you bind the itemsource to the list you don't actually have to manually do this
242247
class MessageViewModel
243248
{
244249
readonly TimeSpan _autoDispose;

0 commit comments

Comments
 (0)