Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.
[Serializable] publicstruct LocalizationStringParmPack { [CustomValueDrawer("DrawPreviewText")] public LocalizedString TextLoc; public LocalizationParamsManager.ParamValue[] ParmsArray; publicoverridestringToString() { returnthis.GetRawEnglishString(); }
#if UNITY_EDITOR
static GUIStyle m_previewStyle; static GUIStyle PreviewStyle { get { if (m_previewStyle == null) { m_previewStyle = new GUIStyle(EditorStyles.textArea); m_previewStyle.wordWrap = true; } return m_previewStyle; } }
// use hacky stuff to get selected new lockey staticstring s_wtfKey = string.Empty; staticbool s_hasChanged = false; LocalizedString DrawPreviewText(LocalizedString value, GUIContent label) { using (new EditorGUILayout.VerticalScope(UnityEditor.EditorStyles.helpBox)) { // draw lockey using (new EditorGUILayout.HorizontalScope()) { if (label != null) { EditorGUILayout.LabelField(label, GUILayout.Width(EditorGUIUtility.labelWidth)); }
// weird stuff happin in dropdown if (EditorGUILayout.DropdownButton(new GUIContent(value.mTerm), FocusType.Keyboard)) { var terms = LocalizationManager.GetTermsList(); var selector = new GenericSelector<string>("Select Term", terms); selector.EnableSingleClickToSelect(); selector.SelectionConfirmed += s => { if (s.Any()) { s_wtfKey = s.First(); // WEIRD STUFF HERE /* if I do LocalizedString next = new LocalizedString(s.First()); and return 'next' and the end of method, it just doesnt work!!! cuz the GenericSelector is actually a editor window, and */ s_hasChanged = true; } }; selector.ShowInPopup(); }
publicclassTempListView : MonoBehaviour { #if UNITY_EDITOR #endif // check when prefab change // [OnValueChanged("OnPrefabChanged")] [SerializeField, Header("place holder, the listview should only contains one type of element")] TempListElementUI m_elementPrefab; RectTransform Container => transform as RectTransform; [SerializeField, ReadOnly] List<TempListElementUI> m_actualUsedComponents = new List<TempListElementUI>(0);
publicint Count => m_actualUsedComponents.Count; public TempListElementUI this[int index] => m_actualUsedComponents[index]; public IReadOnlyList<TempListElementUI> ElementList => m_actualUsedComponents;
public TempListElementUI Add() { TempListElementUI element = InternalAdd(); m_actualUsedComponents.Add(element); element.Show(); return element; }
publicvoidClear() { TempListElementUI element = null; while (m_actualUsedComponents.Count > 0) { element = m_actualUsedComponents[m_actualUsedComponents.Count - 1]; m_actualUsedComponents.RemoveAt(m_actualUsedComponents.Count - 1); InternalRemove(element); } }
publicvoidRemove(TempListElementUI instance) { if (m_actualUsedComponents.Remove(instance)) { instance.Hide(); } else { Debug.LogError($"listview_{this.gameObject.name} does not contains {instance.ElementRectTransform.name}, remove failed"); } }
publicvoidRemoveAt(int index) { if (index < 0 || index >= m_actualUsedComponents.Count) { Debug.LogError($"{index} is invalid for SimpleListView", this.gameObject); return; }
///<summary> /// ///</summary> ///<returns>-1 means element is not in the list</returns> publicintIndexOf(TempListElementUI instance) { try { return m_actualUsedComponents.IndexOf(instance); } catch (ArgumentOutOfRangeException) { return-1; } }
protectedvirtual TempListElementUI InternalAdd() { // can apply object pool here if (Application.isEditor && !Application.isPlaying) return UnityEditor.PrefabUtility.InstantiatePrefab(m_elementPrefab, Container) as TempListElementUI; return Instantiate(m_elementPrefab, Container); }
protectedvirtualvoidInternalRemove(TempListElementUI element) { // can apply object pool here if (element == null) return; element.Hide(); if (Application.isEditor && !Application.isPlaying) GameObject.DestroyImmediate(element.ElementRectTransform.gameObject); else GameObject.Destroy(element.ElementRectTransform.gameObject); }
#if UNITY_EDITOR
privatevoidOnTransformChildrenChanged() { if (Application.isEditor && !Application.isPlaying) FindPrefabInstances(); }
privatevoidOnPrefabChanged() { // remove pre objects int amount = m_actualUsedComponents.Count; for (int i = 0; i < m_actualUsedComponents.Count; i++) { GameObject.DestroyImmediate(m_actualUsedComponents[i].ElementRectTransform.gameObject); }
if (m_elementPrefab != null) { for (int i = 0; i < amount; i++) { RectTransform rectTransform = (RectTransform)UnityEditor.PrefabUtility.InstantiatePrefab(m_elementPrefab, Container); m_actualUsedComponents[i] = (rectTransform.GetComponent<TempListElementUI>()); } } else { m_actualUsedComponents.Clear(); } }
///<summary> /// Retrieves prefab instances in the transform ///</summary> [ContextMenu("find prefab instances")] privatevoidFindPrefabInstances() { bool hasPrefab = !(m_elementPrefab == null); TempListElementUI elementPrefab = m_elementPrefab.GetComponent<TempListElementUI>(); m_actualUsedComponents.Clear(); List<GameObject> toDeleteObjectList = new List<GameObject>(); foreach (Transform child in Container) { TempListElementUI childElement = child.GetComponent<TempListElementUI>(); if (childElement == null) { toDeleteObjectList.Add(child.gameObject); continue; }
if (hasPrefab) { GameObject detectPrefabGo = UnityEditor.PrefabUtility.GetCorrespondingObjectFromSource(child.gameObject); TempListElementUI detectPrefab = (detectPrefabGo == null) ? null : detectPrefabGo.GetComponent<TempListElementUI>(); if (elementPrefab == detectPrefab) { // same source prefab m_actualUsedComponents.Add(childElement); } else { // different source prefab, delete this one toDeleteObjectList.Add(child.gameObject); } } elseif (UnityEditor.PrefabUtility.IsAnyPrefabInstanceRoot(child.gameObject)) { // find the first prefab GameObject prefab = UnityEditor.PrefabUtility.GetCorrespondingObjectFromSource(child.gameObject); m_elementPrefab = prefab.GetComponent<TempListElementUI>(); m_actualUsedComponents.Add(childElement); hasPrefab = true; } }
for (int i = 0; i < toDeleteObjectList.Count; i++) { if (Application.isPlaying) GameObject.Destroy(toDeleteObjectList[i]); else GameObject.DestroyImmediate(toDeleteObjectList[i]); } }
[ContextMenu("editor time add")] privatevoidEditorTimeAdd() { if (Application.isPlaying) return; if (m_elementPrefab == null) { Debug.LogError("listview is missing element prefab"); return; } TempListElementUI spawnObject = (TempListElementUI)UnityEditor.PrefabUtility.InstantiatePrefab(m_elementPrefab, Container); m_actualUsedComponents.Add(spawnObject); }
[ContextMenu("editor time clear")] privatevoidEditorTimeClear() { if (Application.isPlaying) return; // remove pre objects TempListElementUI[] preObjects = Container.GetComponentsInChildren<TempListElementUI>(); for (int i = 0; i < preObjects.Length; i++) { GameObject.DestroyImmediate(preObjects[i].ElementRectTransform.gameObject); } m_actualUsedComponents.Clear(); }
[ContextMenu("test print elements")] privatevoidTestPrintListElements() { if (m_actualUsedComponents != null) { StringBuilder printText = new StringBuilder($"temp list view children_{m_actualUsedComponents.Count} :\n"); for (int i = 0; i < m_actualUsedComponents.Count; i++) { printText.AppendLine(m_actualUsedComponents[i].ElementRectTransform.name); } Debug.Log(printText); } }
#endif }
publicclassBoundlessScrollRectController : UIBehaviour { /* too much code, I will just show the draw */
privatevoidDrawContentItem() { IReadOnlyList<TempListElementUI> elementList = ElementList; int dataCount = m_simulatedDataCount; // TODO @Hiko use a general calculation later bool test = m_content.anchorMin != Vector2.up || m_content.anchorMax != Vector2.up || m_content.pivot != Vector2.up; if (test) { m_content.anchorMin = Vector2.up; m_content.anchorMax = Vector2.up; m_content.pivot = Vector2.up; } Vector3 dragContentAnchorPostion = m_content.anchoredPosition; Vector3 contentMove = dragContentAnchorPostion - SomeUtils.GetOffsetLocalPosition(m_content, SomeUtils.UIOffsetType.TopLeft); Vector2 itemSize = m_gridLayoutGroup.CellSize, spacing = m_gridLayoutGroup.Spacing;
// need to know the moving direction, then adjust it to prevent wrong draw float xMove = contentMove.x < 0 ? (-contentMove.x - padding.horizontal) : 0; xMove = Mathf.Clamp(xMove, 0.0f, Mathf.Abs(xMove)); float yMove = contentMove.y > 0 ? (contentMove.y - padding.vertical) : 0; yMove = Mathf.Clamp(yMove, 0.0f, Mathf.Abs(yMove));
// the column index of the top left item int tempColumnIndex = Mathf.FloorToInt((xMove + spacing.x) / (itemSize.x + spacing.x)); if (xMove % (itemSize.x + spacing.x) - itemSize.x > spacing.x) tempColumnIndex = Mathf.Clamp(tempColumnIndex - 1, 0, tempColumnIndex);
// the row index of the top left item int tempRowIndex = Mathf.FloorToInt((yMove + spacing.y) / (itemSize.y + spacing.y)); if (yMove % (itemSize.y + spacing.y) - itemSize.y > spacing.y) tempRowIndex = Mathf.Clamp(tempRowIndex - 1, 0, tempRowIndex);
Vector2Int rowTopLeftItemIndex = new Vector2Int(tempRowIndex, tempColumnIndex);
// x -> element amount on horizontal axis // y -> element amount on vertical axis Vector2Int contentRowColumnSize = new Vector2Int(rowDataCount, columnDataCount);
// deal with content from left to right (simple case) int dataIndex = 0, uiItemIndex = 0; Vector3 rowTopLeftPosition = new Vector3(padding.left, -padding.top, 0.0f), itemTopLeftPosition = Vector3.zero; for (int columnIndex = 0; columnIndex < m_viewItemCountInColumn; columnIndex++) { if (columnIndex + rowTopLeftItemIndex.x == columnDataCount) break;
// apply this on the target shows actual data public interface ISetupable<TData> { voidSetup(TData data); }
///<summary> /// target component should inherit from ISetupable ///</summary> ///<param name="component"></param> ///<param name="data"></param> ///<typeparam name="TData"></typeparam> publicstaticvoid ISetup<TComponent, TData>(this Component component, TData data) where TComponent : Component { // I guess this check should be fine :( if (component is ISetupable<TData> target) { target.Setup(data); return; } UnityEngine.Debug.LogError($"component_{component.name} is not a setupable"); }
publicclassRaycastTarget : Graphic { // Additionally, If you need a Raycast target that is not a rectangle, you can implement bool Raycast(Vector2 sp, Camera eventCamera) method from Graphic. publicoverridevoidSetMaterialDirty() { return; } publicoverridevoidSetVerticesDirty() { return; } /// Probably not necessary since the chain of calls `Rebuild()`->`UpdateGeometry()`->`DoMeshGeneration()`->`OnPopulateMesh()` won't happen; so here really just as a fail-safe. protectedoverridevoidOnPopulateMesh(VertexHelper vh) { vh.Clear(); return; }
#if UNITY_EDITOR
privatevoidOnDrawGizmos() { if (!this.enabled) return RectTransform rectTransform = this.transform as RectTransform; Color wireColor = Color.yellow; if (this.isActiveAndEnabled) wireColor.a *= 0.7f // Padding to be applied to the masking // X = Left, Y = Bottom, Z = Right, W = Top // if you wanna make it bigger, then the all value shouble be negative Vector4 padding = this.raycastPadding * -1.0f; Matrix4x4 localToWorld = rectTransform.localToWorldMatrix Vector3 topLeft = SomeUtils.GetOffsetLocalPosition(rectTransform, SomeUtils.UIOffsetType.TopLeft); Vector3 topRight = SomeUtils.GetOffsetLocalPosition(rectTransform, SomeUtils.UIOffsetType.TopRight); Vector3 bottomLeft = SomeUtils.GetOffsetLocalPosition(rectTransform, SomeUtils.UIOffsetType.BottomLeft); Vector3 bottomRight = SomeUtils.GetOffsetLocalPosition(rectTransform, SomeUtils.UIOffsetType.BottomRight) topLeft = localToWorld.MultiplyPoint(topLeft + (Vector3.left * padding.x) + (Vector3.up * padding.w)); topRight = localToWorld.MultiplyPoint(topRight + (Vector3.right * padding.z) + (Vector3.up * padding.w)); bottomLeft = localToWorld.MultiplyPoint(bottomLeft + (Vector3.left * padding.x) + (Vector3.down * padding.y)); bottomRight = localToWorld.MultiplyPoint(bottomRight + (Vector3.right * padding.z) + (Vector3.down * padding.y)) Color tempColor = Gizmos.color; Gizmos.color = wireColor Gizmos.DrawLine(topLeft, topRight); Gizmos.DrawLine(topLeft, bottomLeft); Gizmos.DrawLine(bottomRight, topRight); Gizmos.DrawLine(bottomRight, bottomLeft); Gizmos.color = tempColor }