You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
538 lines
16 KiB
538 lines
16 KiB
using System; |
|
using FairyGUI.Utils; |
|
using UnityEngine; |
|
|
|
namespace FairyGUI |
|
{ |
|
/// <summary> |
|
/// GGroup class. |
|
/// 组对象,对应编辑器里的高级组。 |
|
/// </summary> |
|
public class GGroup : GObject |
|
{ |
|
GroupLayoutType _layout; |
|
int _lineGap; |
|
int _columnGap; |
|
|
|
bool _excludeInvisibles; |
|
bool _autoSizeDisabled; |
|
int _mainGridIndex; |
|
int _mainGridMinSize; |
|
|
|
bool _percentReady; |
|
bool _boundsChanged; |
|
int _mainChildIndex; |
|
float _totalSize; |
|
int _numChildren; |
|
internal int _updating; |
|
|
|
Action _refreshDelegate; |
|
|
|
public GGroup() |
|
{ |
|
_mainGridIndex = -1; |
|
_mainChildIndex = -1; |
|
_mainGridMinSize = 50; |
|
_refreshDelegate = EnsureBoundsCorrect; |
|
} |
|
|
|
/// <summary> |
|
/// Group layout type. |
|
/// </summary> |
|
public GroupLayoutType layout |
|
{ |
|
get { return _layout; } |
|
set |
|
{ |
|
if (_layout != value) |
|
{ |
|
_layout = value; |
|
SetBoundsChangedFlag(); |
|
} |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// |
|
/// </summary> |
|
public int lineGap |
|
{ |
|
get { return _lineGap; } |
|
set |
|
{ |
|
if (_lineGap != value) |
|
{ |
|
_lineGap = value; |
|
SetBoundsChangedFlag(true); |
|
} |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// |
|
/// </summary> |
|
public int columnGap |
|
{ |
|
get { return _columnGap; } |
|
set |
|
{ |
|
if (_columnGap != value) |
|
{ |
|
_columnGap = value; |
|
SetBoundsChangedFlag(true); |
|
} |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// |
|
/// </summary> |
|
public bool excludeInvisibles |
|
{ |
|
get { return _excludeInvisibles; } |
|
set |
|
{ |
|
if (_excludeInvisibles != value) |
|
{ |
|
_excludeInvisibles = value; |
|
SetBoundsChangedFlag(); |
|
} |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// |
|
/// </summary> |
|
public bool autoSizeDisabled |
|
{ |
|
get { return _autoSizeDisabled; } |
|
set |
|
{ |
|
if (_autoSizeDisabled != value) |
|
{ |
|
_autoSizeDisabled = value; |
|
SetBoundsChangedFlag(); |
|
} |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// |
|
/// </summary> |
|
public int mainGridMinSize |
|
{ |
|
get { return _mainGridMinSize; } |
|
set |
|
{ |
|
if (_mainGridMinSize != value) |
|
{ |
|
_mainGridMinSize = value; |
|
SetBoundsChangedFlag(); |
|
} |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// |
|
/// </summary> |
|
public int mainGridIndex |
|
{ |
|
get { return _mainGridIndex; } |
|
set |
|
{ |
|
if (_mainGridIndex != value) |
|
{ |
|
_mainGridIndex = value; |
|
SetBoundsChangedFlag(); |
|
} |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Update group bounds. |
|
/// 更新组的包围. |
|
/// </summary> |
|
public void SetBoundsChangedFlag(bool positionChangedOnly = false) |
|
{ |
|
if (_updating == 0 && parent != null) |
|
{ |
|
if (!positionChangedOnly) |
|
_percentReady = false; |
|
|
|
if (!_boundsChanged) |
|
{ |
|
_boundsChanged = true; |
|
|
|
if (_layout != GroupLayoutType.None) |
|
{ |
|
UpdateContext.OnBegin -= _refreshDelegate; |
|
UpdateContext.OnBegin += _refreshDelegate; |
|
} |
|
} |
|
} |
|
} |
|
|
|
public void EnsureBoundsCorrect() |
|
{ |
|
if (parent == null || !_boundsChanged) |
|
return; |
|
|
|
UpdateContext.OnBegin -= _refreshDelegate; |
|
_boundsChanged = false; |
|
|
|
if (_autoSizeDisabled) |
|
ResizeChildren(0, 0); |
|
else |
|
{ |
|
HandleLayout(); |
|
UpdateBounds(); |
|
} |
|
} |
|
|
|
void UpdateBounds() |
|
{ |
|
int cnt = parent.numChildren; |
|
int i; |
|
GObject child; |
|
float ax = int.MaxValue, ay = int.MaxValue; |
|
float ar = int.MinValue, ab = int.MinValue; |
|
float tmp; |
|
bool empty = true; |
|
bool skipInvisibles = _layout != GroupLayoutType.None && _excludeInvisibles; |
|
|
|
for (i = 0; i < cnt; i++) |
|
{ |
|
child = parent.GetChildAt(i); |
|
if (child.group != this) |
|
continue; |
|
|
|
if (skipInvisibles && !child.internalVisible3) |
|
continue; |
|
|
|
tmp = child.xMin; |
|
if (tmp < ax) |
|
ax = tmp; |
|
tmp = child.yMin; |
|
if (tmp < ay) |
|
ay = tmp; |
|
tmp = child.xMin + child.width; |
|
if (tmp > ar) |
|
ar = tmp; |
|
tmp = child.yMin + child.height; |
|
if (tmp > ab) |
|
ab = tmp; |
|
|
|
empty = false; |
|
} |
|
|
|
float w; |
|
float h; |
|
if (!empty) |
|
{ |
|
_updating |= 1; |
|
SetXY(ax, ay); |
|
_updating &= 2; |
|
|
|
w = ar - ax; |
|
h = ab - ay; |
|
} |
|
else |
|
w = h = 0; |
|
|
|
if ((_updating & 2) == 0) |
|
{ |
|
_updating |= 2; |
|
SetSize(w, h); |
|
_updating &= 1; |
|
} |
|
else |
|
{ |
|
_updating &= 1; |
|
ResizeChildren(_width - w, _height - h); |
|
} |
|
} |
|
|
|
void HandleLayout() |
|
{ |
|
_updating |= 1; |
|
|
|
if (_layout == GroupLayoutType.Horizontal) |
|
{ |
|
float curX = this.x; |
|
int cnt = parent.numChildren; |
|
for (int i = 0; i < cnt; i++) |
|
{ |
|
GObject child = parent.GetChildAt(i); |
|
if (child.group != this) |
|
continue; |
|
if (_excludeInvisibles && !child.internalVisible3) |
|
continue; |
|
|
|
child.xMin = curX; |
|
if (child.width != 0) |
|
curX += child.width + _columnGap; |
|
} |
|
} |
|
else if (_layout == GroupLayoutType.Vertical) |
|
{ |
|
float curY = this.y; |
|
int cnt = parent.numChildren; |
|
for (int i = 0; i < cnt; i++) |
|
{ |
|
GObject child = parent.GetChildAt(i); |
|
if (child.group != this) |
|
continue; |
|
if (_excludeInvisibles && !child.internalVisible3) |
|
continue; |
|
|
|
child.yMin = curY; |
|
if (child.height != 0) |
|
curY += child.height + _lineGap; |
|
} |
|
} |
|
|
|
_updating &= 2; |
|
} |
|
|
|
internal void MoveChildren(float dx, float dy) |
|
{ |
|
if ((_updating & 1) != 0 || parent == null) |
|
return; |
|
|
|
_updating |= 1; |
|
|
|
int cnt = parent.numChildren; |
|
int i; |
|
GObject child; |
|
for (i = 0; i < cnt; i++) |
|
{ |
|
child = parent.GetChildAt(i); |
|
if (child.group == this) |
|
{ |
|
child.SetXY(child.x + dx, child.y + dy); |
|
} |
|
} |
|
|
|
_updating &= 2; |
|
} |
|
|
|
internal void ResizeChildren(float dw, float dh) |
|
{ |
|
if (_layout == GroupLayoutType.None || (_updating & 2) != 0 || parent == null) |
|
return; |
|
|
|
_updating |= 2; |
|
|
|
if (_boundsChanged) |
|
{ |
|
_boundsChanged = false; |
|
if (!_autoSizeDisabled) |
|
{ |
|
UpdateBounds(); |
|
return; |
|
} |
|
} |
|
|
|
int cnt = parent.numChildren; |
|
|
|
if (!_percentReady) |
|
{ |
|
_percentReady = true; |
|
_numChildren = 0; |
|
_totalSize = 0; |
|
_mainChildIndex = -1; |
|
|
|
int j = 0; |
|
for (int i = 0; i < cnt; i++) |
|
{ |
|
GObject child = parent.GetChildAt(i); |
|
if (child.group != this) |
|
continue; |
|
|
|
if (!_excludeInvisibles || child.internalVisible3) |
|
{ |
|
if (j == _mainGridIndex) |
|
_mainChildIndex = i; |
|
|
|
_numChildren++; |
|
|
|
if (_layout == GroupLayoutType.Horizontal) |
|
_totalSize += child.width; |
|
else |
|
_totalSize += child.height; |
|
} |
|
|
|
j++; |
|
} |
|
|
|
if (_mainChildIndex != -1) |
|
{ |
|
if (_layout == GroupLayoutType.Horizontal) |
|
{ |
|
GObject child = parent.GetChildAt(_mainChildIndex); |
|
_totalSize += _mainGridMinSize - child.width; |
|
child._sizePercentInGroup = _mainGridMinSize / _totalSize; |
|
} |
|
else |
|
{ |
|
GObject child = parent.GetChildAt(_mainChildIndex); |
|
_totalSize += _mainGridMinSize - child.height; |
|
child._sizePercentInGroup = _mainGridMinSize / _totalSize; |
|
} |
|
} |
|
|
|
for (int i = 0; i < cnt; i++) |
|
{ |
|
GObject child = parent.GetChildAt(i); |
|
if (child.group != this) |
|
continue; |
|
|
|
if (i == _mainChildIndex) |
|
continue; |
|
|
|
if (_totalSize > 0) |
|
child._sizePercentInGroup = (_layout == GroupLayoutType.Horizontal ? child.width : child.height) / _totalSize; |
|
else |
|
child._sizePercentInGroup = 0; |
|
} |
|
} |
|
|
|
float remainSize = 0; |
|
float remainPercent = 1; |
|
bool priorHandled = false; |
|
|
|
if (_layout == GroupLayoutType.Horizontal) |
|
{ |
|
remainSize = this.width - (_numChildren - 1) * _columnGap; |
|
if (_mainChildIndex != -1 && remainSize >= _totalSize) |
|
{ |
|
GObject child = parent.GetChildAt(_mainChildIndex); |
|
child.SetSize(remainSize - (_totalSize - _mainGridMinSize), child._rawHeight + dh, true); |
|
remainSize -= child.width; |
|
remainPercent -= child._sizePercentInGroup; |
|
priorHandled = true; |
|
} |
|
|
|
float curX = this.x; |
|
for (int i = 0; i < cnt; i++) |
|
{ |
|
GObject child = parent.GetChildAt(i); |
|
if (child.group != this) |
|
continue; |
|
|
|
if (_excludeInvisibles && !child.internalVisible3) |
|
{ |
|
child.SetSize(child._rawWidth, child._rawHeight + dh, true); |
|
continue; |
|
} |
|
|
|
if (!priorHandled || i != _mainChildIndex) |
|
{ |
|
child.SetSize(Mathf.Round(child._sizePercentInGroup / remainPercent * remainSize), child._rawHeight + dh, true); |
|
remainPercent -= child._sizePercentInGroup; |
|
remainSize -= child.width; |
|
} |
|
|
|
child.xMin = curX; |
|
if (child.width != 0) |
|
curX += child.width + _columnGap; |
|
} |
|
} |
|
else |
|
{ |
|
remainSize = this.height - (_numChildren - 1) * _lineGap; |
|
if (_mainChildIndex != -1 && remainSize >= _totalSize) |
|
{ |
|
GObject child = parent.GetChildAt(_mainChildIndex); |
|
child.SetSize(child._rawWidth + dw, remainSize - (_totalSize - _mainGridMinSize), true); |
|
remainSize -= child.height; |
|
remainPercent -= child._sizePercentInGroup; |
|
priorHandled = true; |
|
} |
|
|
|
float curY = this.y; |
|
for (int i = 0; i < cnt; i++) |
|
{ |
|
GObject child = parent.GetChildAt(i); |
|
if (child.group != this) |
|
continue; |
|
|
|
if (_excludeInvisibles && !child.internalVisible3) |
|
{ |
|
child.SetSize(child._rawWidth + dw, child._rawHeight, true); |
|
continue; |
|
} |
|
|
|
if (!priorHandled || i != _mainChildIndex) |
|
{ |
|
child.SetSize(child._rawWidth + dw, Mathf.Round(child._sizePercentInGroup / remainPercent * remainSize), true); |
|
remainPercent -= child._sizePercentInGroup; |
|
remainSize -= child.height; |
|
} |
|
|
|
child.yMin = curY; |
|
if (child.height != 0) |
|
curY += child.height + _lineGap; |
|
} |
|
} |
|
|
|
_updating &= 1; |
|
} |
|
|
|
override protected void HandleAlphaChanged() |
|
{ |
|
base.HandleAlphaChanged(); |
|
|
|
if (this.underConstruct || parent == null) |
|
return; |
|
|
|
int cnt = parent.numChildren; |
|
float a = this.alpha; |
|
for (int i = 0; i < cnt; i++) |
|
{ |
|
GObject child = parent.GetChildAt(i); |
|
if (child.group == this) |
|
child.alpha = a; |
|
} |
|
} |
|
|
|
override internal protected void HandleVisibleChanged() |
|
{ |
|
if (parent == null) |
|
return; |
|
|
|
int cnt = parent.numChildren; |
|
for (int i = 0; i < cnt; i++) |
|
{ |
|
GObject child = parent.GetChildAt(i); |
|
if (child.group == this) |
|
child.HandleVisibleChanged(); |
|
} |
|
} |
|
|
|
override public void Setup_BeforeAdd(ByteBuffer buffer, int beginPos) |
|
{ |
|
base.Setup_BeforeAdd(buffer, beginPos); |
|
|
|
buffer.Seek(beginPos, 5); |
|
|
|
_layout = (GroupLayoutType)buffer.ReadByte(); |
|
_lineGap = buffer.ReadInt(); |
|
_columnGap = buffer.ReadInt(); |
|
if (buffer.version >= 2) |
|
{ |
|
_excludeInvisibles = buffer.ReadBool(); |
|
_autoSizeDisabled = buffer.ReadBool(); |
|
_mainGridIndex = buffer.ReadShort(); |
|
} |
|
} |
|
|
|
override public void Setup_AfterAdd(ByteBuffer buffer, int beginPos) |
|
{ |
|
base.Setup_AfterAdd(buffer, beginPos); |
|
|
|
if (!this.visible) |
|
HandleVisibleChanged(); |
|
} |
|
} |
|
}
|
|
|