Full Code of fairygui/FairyGUI-unreal for AI

master 2e2a5dd5f851 cached
197 files
810.9 KB
217.3k tokens
477 symbols
1 requests
Download .txt
Showing preview only (870K chars total). Download the full file or copy to clipboard to get everything.
Repository: fairygui/FairyGUI-unreal
Branch: master
Commit: 2e2a5dd5f851
Files: 197
Total size: 810.9 KB

Directory structure:
gitextract_s53mm5l5/

├── .gitignore
├── FairyGUI.uplugin
├── LICENSE
├── README.md
└── Source/
    ├── FairyGUI/
    │   ├── FairyGUI.Build.cs
    │   ├── Private/
    │   │   ├── Event/
    │   │   │   ├── EventContext.cpp
    │   │   │   └── EventTypes.cpp
    │   │   ├── FairyApplication.cpp
    │   │   ├── FairyBlueprintLibrary.cpp
    │   │   ├── FairyCommons.cpp
    │   │   ├── FairyGUIModule.cpp
    │   │   ├── Tween/
    │   │   │   ├── EaseManager.cpp
    │   │   │   ├── GPath.cpp
    │   │   │   ├── GTween.cpp
    │   │   │   ├── GTweener.cpp
    │   │   │   ├── TweenManager.cpp
    │   │   │   └── TweenValue.cpp
    │   │   ├── UI/
    │   │   │   ├── ControllerAction/
    │   │   │   │   ├── ChangePageAction.cpp
    │   │   │   │   ├── ControllerAction.cpp
    │   │   │   │   └── PlayTransitionAction.cpp
    │   │   │   ├── DragDropManager.cpp
    │   │   │   ├── GButton.cpp
    │   │   │   ├── GComboBox.cpp
    │   │   │   ├── GComponent.cpp
    │   │   │   ├── GController.cpp
    │   │   │   ├── GGraph.cpp
    │   │   │   ├── GGroup.cpp
    │   │   │   ├── GImage.cpp
    │   │   │   ├── GLabel.cpp
    │   │   │   ├── GList.cpp
    │   │   │   ├── GLoader.cpp
    │   │   │   ├── GLoader3D.cpp
    │   │   │   ├── GMovieClip.cpp
    │   │   │   ├── GObject.cpp
    │   │   │   ├── GObjectPool.cpp
    │   │   │   ├── GProgressBar.cpp
    │   │   │   ├── GRichTextField.cpp
    │   │   │   ├── GRoot.cpp
    │   │   │   ├── GScrollBar.cpp
    │   │   │   ├── GSlider.cpp
    │   │   │   ├── GTextField.cpp
    │   │   │   ├── GTextInput.cpp
    │   │   │   ├── GTree.cpp
    │   │   │   ├── GTreeNode.cpp
    │   │   │   ├── GWindow.cpp
    │   │   │   ├── Gears/
    │   │   │   │   ├── GearAnimation.cpp
    │   │   │   │   ├── GearBase.cpp
    │   │   │   │   ├── GearColor.cpp
    │   │   │   │   ├── GearDisplay.cpp
    │   │   │   │   ├── GearDisplay2.cpp
    │   │   │   │   ├── GearFontSize.cpp
    │   │   │   │   ├── GearIcon.cpp
    │   │   │   │   ├── GearLook.cpp
    │   │   │   │   ├── GearSize.cpp
    │   │   │   │   ├── GearText.cpp
    │   │   │   │   └── GearXY.cpp
    │   │   │   ├── PackageItem.cpp
    │   │   │   ├── PopupMenu.cpp
    │   │   │   ├── RelationItem.cpp
    │   │   │   ├── Relations.cpp
    │   │   │   ├── ScrollPane.cpp
    │   │   │   ├── Transition.cpp
    │   │   │   ├── TranslationHelper.cpp
    │   │   │   ├── UIConfig.cpp
    │   │   │   ├── UIObjectFactory.cpp
    │   │   │   └── UIPackage.cpp
    │   │   ├── UIPackageAsset.cpp
    │   │   ├── Utils/
    │   │   │   ├── ByteBuffer.cpp
    │   │   │   ├── HTMLElement.cpp
    │   │   │   ├── HTMLParser.cpp
    │   │   │   ├── NVariant.cpp
    │   │   │   ├── UBBParser.cpp
    │   │   │   ├── XMLAttributes.cpp
    │   │   │   └── XMLIterator.cpp
    │   │   └── Widgets/
    │   │       ├── BitmapFont.cpp
    │   │       ├── BitmapFontRun.cpp
    │   │       ├── HitTest.cpp
    │   │       ├── LoaderRun.cpp
    │   │       ├── Mesh/
    │   │       │   ├── EllipseMesh.cpp
    │   │       │   ├── FillMesh.cpp
    │   │       │   ├── MeshFactory.cpp
    │   │       │   ├── PolygonMesh.cpp
    │   │       │   ├── RectMesh.cpp
    │   │       │   ├── RegularPolygonMesh.cpp
    │   │       │   ├── RoundedMesh.cpp
    │   │       │   └── VertexHelper.cpp
    │   │       ├── NGraphics.cpp
    │   │       ├── NTextFormat.cpp
    │   │       ├── NTexture.cpp
    │   │       ├── SContainer.cpp
    │   │       ├── SDisplayObject.cpp
    │   │       ├── SFImage.cpp
    │   │       ├── SMovieClip.cpp
    │   │       ├── SShape.cpp
    │   │       ├── STextField.cpp
    │   │       └── STextInput.cpp
    │   └── Public/
    │       ├── Event/
    │       │   ├── EventContext.h
    │       │   └── EventTypes.h
    │       ├── FairyApplication.h
    │       ├── FairyBlueprintLibrary.h
    │       ├── FairyCommons.h
    │       ├── FairyGUI.h
    │       ├── FairyGUIModule.h
    │       ├── Tween/
    │       │   ├── EaseManager.h
    │       │   ├── EaseType.h
    │       │   ├── GPath.h
    │       │   ├── GTween.h
    │       │   ├── GTweener.h
    │       │   ├── TweenManager.h
    │       │   ├── TweenValue.h
    │       │   └── TweenerHandle.h
    │       ├── UI/
    │       │   ├── ControllerAction/
    │       │   │   ├── ChangePageAction.h
    │       │   │   ├── ControllerAction.h
    │       │   │   └── PlayTransitionAction.h
    │       │   ├── DragDropManager.h
    │       │   ├── FieldTypes.h
    │       │   ├── GButton.h
    │       │   ├── GComboBox.h
    │       │   ├── GComponent.h
    │       │   ├── GController.h
    │       │   ├── GGraph.h
    │       │   ├── GGroup.h
    │       │   ├── GImage.h
    │       │   ├── GLabel.h
    │       │   ├── GList.h
    │       │   ├── GLoader.h
    │       │   ├── GLoader3D.h
    │       │   ├── GMovieClip.h
    │       │   ├── GObject.h
    │       │   ├── GObjectPool.h
    │       │   ├── GProgressBar.h
    │       │   ├── GRichTextField.h
    │       │   ├── GRoot.h
    │       │   ├── GScrollBar.h
    │       │   ├── GSlider.h
    │       │   ├── GTextField.h
    │       │   ├── GTextInput.h
    │       │   ├── GTree.h
    │       │   ├── GTreeNode.h
    │       │   ├── GWindow.h
    │       │   ├── Gears/
    │       │   │   ├── GearAnimation.h
    │       │   │   ├── GearBase.h
    │       │   │   ├── GearColor.h
    │       │   │   ├── GearDisplay.h
    │       │   │   ├── GearDisplay2.h
    │       │   │   ├── GearFontSize.h
    │       │   │   ├── GearIcon.h
    │       │   │   ├── GearLook.h
    │       │   │   ├── GearSize.h
    │       │   │   ├── GearText.h
    │       │   │   └── GearXY.h
    │       │   ├── PackageItem.h
    │       │   ├── PopupMenu.h
    │       │   ├── RelationItem.h
    │       │   ├── Relations.h
    │       │   ├── ScrollPane.h
    │       │   ├── Transition.h
    │       │   ├── TranslationHelper.h
    │       │   ├── UIConfig.h
    │       │   ├── UIObjectFactory.h
    │       │   └── UIPackage.h
    │       ├── UIPackageAsset.h
    │       ├── Utils/
    │       │   ├── ByteBuffer.h
    │       │   ├── HTMLElement.h
    │       │   ├── HTMLParser.h
    │       │   ├── NVariant.h
    │       │   ├── UBBParser.h
    │       │   ├── XMLAttributes.h
    │       │   └── XMLIterator.h
    │       └── Widgets/
    │           ├── BitmapFont.h
    │           ├── BitmapFontRun.h
    │           ├── HitTest.h
    │           ├── LoaderRun.h
    │           ├── Mesh/
    │           │   ├── EllipseMesh.h
    │           │   ├── FillMesh.h
    │           │   ├── MeshFactory.h
    │           │   ├── PolygonMesh.h
    │           │   ├── RectMesh.h
    │           │   ├── RegularPolygonMesh.h
    │           │   ├── RoundedRectMesh.h
    │           │   └── VertexHelper.h
    │           ├── MeshFactory.h
    │           ├── NGraphics.h
    │           ├── NTextFormat.h
    │           ├── NTexture.h
    │           ├── SContainer.h
    │           ├── SDisplayObject.h
    │           ├── SFImage.h
    │           ├── SMovieClip.h
    │           ├── SShape.h
    │           ├── STextField.h
    │           └── STextInput.h
    └── FairyGUIEditor/
        ├── FairyGUIEditor.Build.cs
        ├── Private/
        │   ├── FairyGUIEditor.cpp
        │   └── FairyGUIFactory.cpp
        └── Public/
            ├── FairyGUIEditor.h
            └── FairyGUIFactory.h

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# Visual Studio 2015 user specific files
.vs/

# Compiled Object files
*.slo
*.lo
*.o
*.obj

# Precompiled Headers
*.gch
*.pch

# Compiled Dynamic libraries
*.so
*.dylib
*.dll

# Fortran module files
*.mod

# Compiled Static libraries
*.lai
*.la
*.a
*.lib

# Executables
*.exe
*.out
*.app
*.ipa

# These project files can be generated by the engine
*.xcodeproj
*.xcworkspace
*.sln
*.suo
*.opensdf
*.sdf
*.VC.db
*.VC.opendb

# Precompiled Assets
SourceArt/**/*.png
SourceArt/**/*.tga

# Binary Files
Binaries/*
Plugins/*/Binaries/*

# Builds
Build/*

# Whitelist PakBlacklist-<BuildConfiguration>.txt files
!Build/*/
Build/*/**
!Build/*/PakBlacklist*.txt

# Don't ignore icon files in Build
!Build/**/*.ico

# Built data for maps
*_BuiltData.uasset

# Configuration files generated by the Editor
Saved/*

# Compiled source files for the engine to use
Intermediate/*
Plugins/*/Intermediate/*

# Cache files for the editor to use
DerivedDataCache/*


================================================
FILE: FairyGUI.uplugin
================================================
{
	"FileVersion": 3,
	"Version": 1,
	"VersionName": "1.0",
	"FriendlyName": "FairyGUI",
	"Description": "FairyGUI is a cross-engine UI Solution",
	"Category": "UI",
	"CreatedBy": "fairygui.com",
	"CreatedByURL": "https://fairygui.com",
	"DocsURL": "",
	"MarketplaceURL": "",
	"SupportURL": "",
	"CanContainContent": true,
	"IsBetaVersion": false,
	"IsExperimentalVersion": false,
	"Installed": false,
	"Modules": [
		{
			"Name": "FairyGUI",
			"Type": "Runtime",
			"LoadingPhase": "Default"
		},
		{
			"Name": "FairyGUIEditor",
			"Type": "Editor",
			"LoadingPhase": "Default"
		}
	]
}

================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2021 FairyGUI

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# FairyGUI-unreal
A flexible UI framework for Unreal Engine

Suggest to start from [Examples](https://github.com/fairygui/FairyGUI-unreal-example)

================================================
FILE: Source/FairyGUI/FairyGUI.Build.cs
================================================
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.

using UnrealBuildTool;

public class FairyGUI : ModuleRules
{
	public FairyGUI(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
		
		PublicIncludePaths.AddRange(
			new string[] {
				// ... add public include paths required here ...
			}
			);
				
		
		PrivateIncludePaths.AddRange(
			new string[] {
				// ... add other private include paths required here ...
			}
			);
			
		
		PublicDependencyModuleNames.AddRange(
			new string[]
			{
				"Core",
				// ... add other public dependencies that you statically link with here ...
			}
			);
			
		
		PrivateDependencyModuleNames.AddRange(
			new string[]
			{
				"CoreUObject",
				"Engine",
                "InputCore",
                "Slate",
				"SlateCore",
				// ... add private dependencies that you statically link with here ...	
			}
			);

        if (Target.bBuildEditor == true)
        {
            PrivateDependencyModuleNames.Add("UnrealEd");
        }

        DynamicallyLoadedModuleNames.AddRange(
			new string[]
			{
				// ... add any modules that your module loads dynamically here ...
			}
			);
	}
}


================================================
FILE: Source/FairyGUI/Private/Event/EventContext.cpp
================================================
#include "Event/EventContext.h"


================================================
FILE: Source/FairyGUI/Private/Event/EventTypes.cpp
================================================
#include "Event/EventTypes.h"

const FName FUIEvents::Click("Click");
const FName FUIEvents::TouchBegin("TouchBegin");
const FName FUIEvents::TouchMove("TouchMove");
const FName FUIEvents::TouchEnd("TouchEnd");
const FName FUIEvents::RollOver("RollOver");
const FName FUIEvents::RollOut("RollOut");
const FName FUIEvents::MouseWheel("MouseWheel");

const FName FUIEvents::DragStart("DragStart");
const FName FUIEvents::DragMove("DragMove");
const FName FUIEvents::DragEnd("DragEnd");
const FName FUIEvents::Drop("Drop");

const FName FUIEvents::AddedToStage("AddedToStage");
const FName FUIEvents::RemovedFromStage("RemovedFromStage");

const FName FUIEvents::Changed("Changed");
const FName FUIEvents::ClickItem("ClickItem");
const FName FUIEvents::ClickLink("ClickLink");
const FName FUIEvents::GearStop("GearStop");

const FName FUIEvents::Scroll("Scroll");
const FName FUIEvents::ScrollEnd("ScrollEnd");
const FName FUIEvents::PullDownRelease("PullDownRelease");
const FName FUIEvents::PullUpRelease("PullUpRelease");

const FName FUIEvents::Submit("Submit");


================================================
FILE: Source/FairyGUI/Private/FairyApplication.cpp
================================================
#include "FairyApplication.h"
#include "Framework/Application/SlateApplication.h"
#include "Slate/SGameLayerManager.h"
#include "UIPackageAsset.h"
#include "UI/GRoot.h"
#include "UI/UIPackage.h"
#include "UI/UIObjectFactory.h"
#include "UI/PackageItem.h"
#include "UI/GWindow.h"
#include "UI/PopupMenu.h"
#include "UI/DragDropManager.h"
#include "Tween/TweenManager.h"
#include "Widgets/NTexture.h"
#include "Utils/ByteBuffer.h"

TMap<uint32, UFairyApplication*> UFairyApplication::Instances;

struct FMyScopedSwitchWorldHack
{
    FMyScopedSwitchWorldHack(UWorld* World)
    {
        PrevWorld = GWorld;
        GWorld = World;
    }

    ~FMyScopedSwitchWorldHack()
    {
        GWorld = PrevWorld;
    }
    UWorld* PrevWorld;
};

UFairyApplication::FTouchInfo::FTouchInfo() :
    UserIndex(0),
    PointerIndex(0),
    bDown(false),
    DownPosition(0, 0),
    bClickCancelled(false),
    ClickCount(0)
{
}

UFairyApplication::FInputProcessor::FInputProcessor(UFairyApplication* InApplication)
{
    Application = InApplication;
}

void UFairyApplication::FInputProcessor::Tick(const float DeltaTime, FSlateApplication& SlateApp, TSharedRef<ICursor> Cursor)
{
}

bool UFairyApplication::FInputProcessor::HandleMouseButtonDownEvent(FSlateApplication& SlateApp, const FPointerEvent& MouseEvent)
{
    Application->PreviewDownEvent(MouseEvent);

    return false;
}

bool UFairyApplication::FInputProcessor::HandleMouseButtonUpEvent(FSlateApplication& SlateApp, const FPointerEvent& MouseEvent)
{
    Application->PreviewUpEvent(MouseEvent);
    return false;
}

bool UFairyApplication::FInputProcessor::HandleMouseMoveEvent(FSlateApplication& SlateApp, const FPointerEvent& MouseEvent)
{
    Application->PreviewMoveEvent(MouseEvent);
    return false;
}

UFairyApplication* UFairyApplication::Get(UObject* WorldContextObject)
{
    UWorld* World = WorldContextObject->GetWorld();
    verifyf(World != nullptr, TEXT("Null World?"));
    verifyf(World->IsGameWorld(), TEXT("Not a Game World?"));

    UFairyApplication* Instance = Instances.FindRef(World->GetGameInstance()->GetUniqueID());
    if (Instance == nullptr)
    {
        Instance = NewObject<UFairyApplication>();
        Instances.Add(World->GetGameInstance()->GetUniqueID(), Instance);
        Instance->GameInstance = World->GetGameInstance();
        Instance->AddToRoot();
        Instance->OnCreate();
    }
    return Instance;
}

void UFairyApplication::Destroy()
{
    FUIObjectFactory::PackageItemExtensions.Reset();
    FUIObjectFactory::LoaderExtension = nullptr;

    UNTexture::DestroyWhiteTexture();
    UUIPackageStatic::Destroy();
    FUIConfig::Config = FUIConfig(); //Reset Configuration to default values

    for (auto& it : Instances)
    {
        it.Value->RemoveFromRoot();
        it.Value->OnDestroy();
    }
    Instances.Reset();
}

UFairyApplication::UFairyApplication() :
    bSoundEnabled(true),
    SoundVolumeScale(1)
{
    LastTouch = new FTouchInfo();
    Touches.Add(LastTouch);
}

void UFairyApplication::OnCreate()
{
    ViewportClient = GameInstance->GetWorld()->GetGameViewport();
    if (ViewportClient == nullptr)
        return;

    ViewportWidget = ViewportClient->GetGameViewportWidget();

    DragDropManager = NewObject<UDragDropManager>(this);
    DragDropManager->CreateAgent();

    PostTickDelegateHandle = FSlateApplication::Get().OnPostTick().AddUObject(this, &UFairyApplication::OnSlatePostTick);

    InputProcessor = MakeShareable(new FInputProcessor(this));
    FSlateApplication::Get().RegisterInputPreProcessor(InputProcessor);

}

void UFairyApplication::OnDestroy()
{
    FTweenManager::Singleton.Reset();

    if (InputProcessor.IsValid())
        FSlateApplication::Get().UnregisterInputPreProcessor(InputProcessor);

    if (PostTickDelegateHandle.IsValid())
        FSlateApplication::Get().OnPostTick().Remove(PostTickDelegateHandle);
}

UGRoot* UFairyApplication::GetUIRoot() const
{
    if (UIRoot == nullptr)
    {
        UFairyApplication* This = const_cast<UFairyApplication*>(this);
        This->UIRoot = NewObject<UGRoot>(This);
        This->UIRoot->AddToViewport();
    }

    return UIRoot;
}

void UFairyApplication::CallAfterSlateTick(FSimpleDelegate Callback)
{
    PostTickMulticastDelegate.Add(Callback);
}

void UFairyApplication::OnSlatePostTick(float DeltaTime)
{
    if (PostTickMulticastDelegate.IsBound())
    {
        FSimpleMulticastDelegate Clone = PostTickMulticastDelegate;
        PostTickMulticastDelegate.Clear();
        Clone.Broadcast();
    }

    if (bNeedCheckPopups)
    {
        bNeedCheckPopups = false;

        if (UIRoot != nullptr)
            UIRoot->CheckPopups(nullptr);
    }
}

FVector2D UFairyApplication::GetTouchPosition(int32 InUserIndex, int32 InPointerIndex)
{
    FTouchInfo* TouchInfo = GetTouchInfo(InUserIndex, InPointerIndex);
    if (TouchInfo != nullptr)
        return TouchInfo->Event.GetScreenSpacePosition();
    else
        return FVector2D::ZeroVector;
}

int32 UFairyApplication::GetTouchCount() const
{
    int32 Count = 0;
    for (auto& it : Touches)
    {
        if (it.bDown)
            Count++;
    }

    return Count;
}

UGObject* UFairyApplication::GetObjectUnderPoint(const FVector2D& ScreenspacePosition)
{
    TArray<TSharedRef<SWindow>> Windows;
    Windows.Add(ViewportClient->GetWindow().ToSharedRef());
    FWidgetPath WidgetPath = FSlateApplication::Get().LocateWindowUnderMouse(ScreenspacePosition, Windows, false);

    if (WidgetPath.IsValid())
        return SDisplayObject::GetWidgetGObject(WidgetPath.GetLastWidget());
    else
        return nullptr;
}

void UFairyApplication::CancelClick(int32 InUserIndex, int32 InPointerIndex)
{
    FTouchInfo* TouchInfo = GetTouchInfo(InUserIndex, InPointerIndex);
    if (TouchInfo != nullptr)
        TouchInfo->bClickCancelled = true;
}

void UFairyApplication::PlaySound(const FString& URL, float VolumnScale)
{
    if (!bSoundEnabled)
        return;

    TSharedPtr<FPackageItem> SoundItem = UUIPackage::GetItemByURL(URL);
    if (SoundItem.IsValid())
    {
        SoundItem->Load();
        FSlateApplication::Get().PlaySound(*SoundItem->Sound);
    }
}

void UFairyApplication::SetSoundEnabled(bool bEnabled)
{
    bSoundEnabled = bEnabled;
}

void UFairyApplication::SetSoundVolumeScale(float VolumnScale)
{
    SoundVolumeScale = VolumnScale;
}

bool UFairyApplication::DispatchEvent(const FName& EventType, const TSharedRef<SWidget>& Initiator, const FNVariant& Data)
{
    UGObject* Obj = SDisplayObject::GetWidgetGObject(Initiator);
    if (Obj == nullptr)
        return false;

    UEventContext* Context = BorrowEventContext();
    Context->Type = EventType;
    Context->Initiator = Obj;
    Context->Sender = Obj;
    Context->Data = Data;

    Context->Sender->InvokeEventDelegate(Context);

    ReturnEventContext(Context);

    return Context->bDefaultPrevented;
}

void UFairyApplication::BubbleEvent(const FName& EventType, const TSharedRef<SWidget>& Initiator, const FNVariant& Data)
{
    TArray<UGObject*> CallChain;
    SDisplayObject::GetWidgetPathToRoot(Initiator, CallChain);
    if (CallChain.Num() == 0)
        return;

    InternalBubbleEvent(EventType, CallChain, Data);
}

void UFairyApplication::InternalBubbleEvent(const FName& EventType, const TArray<UGObject*>& CallChain, const FNVariant& Data)
{
    UEventContext* Context = BorrowEventContext();
    Context->Type = EventType;
    Context->Initiator = CallChain[0];
    Context->Data = Data;

    for (auto& it : CallChain)
    {
        Context->Sender = it;
        it->InvokeEventDelegate(Context);

        if (Context->bIsMouseCaptor)
        {
            Context->bIsMouseCaptor = false;
            AddMouseCaptor(Context->GetUserIndex(), (int32)Context->GetPointerIndex(), it);
        }

        if (Context->IsPropagationStopped())
            break;
    }

    ReturnEventContext(Context);
}

void UFairyApplication::BroadcastEvent(const FName& EventType, const TSharedRef<SWidget>& Initiator, const FNVariant& Data)
{
    TArray<UGObject*> CallChain;
    SDisplayObject::GetWidgetDescendants(Initiator, CallChain);
    if (CallChain.Num() == 0)
        return;

    UEventContext* Context = BorrowEventContext();
    Context->Type = EventType;
    Context->Data = Data;

    for (auto& it : CallChain)
    {
        Context->Sender = it;
        Context->Initiator = it;
        it->InvokeEventDelegate(Context);
    }

    ReturnEventContext(Context);
}

UEventContext* UFairyApplication::BorrowEventContext()
{
    UEventContext* Context;
    if (EventContextPool.Num() > 0)
    {
        Context = EventContextPool.Pop();
        Context->bDefaultPrevented = false;
        Context->bStopped = false;
        Context->bIsMouseCaptor = false;
    }
    else
        Context = NewObject<UEventContext>(this);
    Context->PointerEvent = &LastTouch->Event;
    Context->ClickCount = LastTouch->ClickCount;
    //Context->KeyEvent = &LastKeyEvent;

    return Context;
}

void UFairyApplication::ReturnEventContext(UEventContext* Context)
{
    Context->Data.Reset();
    EventContextPool.Add(Context);
}

void UFairyApplication::AddMouseCaptor(int32 InUserIndex, int32 InPointerIndex, UGObject* InTarget)
{
    FTouchInfo* TouchInfo = GetTouchInfo(InUserIndex, InPointerIndex);
    if (TouchInfo != nullptr && !TouchInfo->MouseCaptors.Contains(InTarget))
        TouchInfo->MouseCaptors.Add(InTarget);
}

void UFairyApplication::RemoveMouseCaptor(int32 InUserIndex, int32 InPointerIndex, UGObject* InTarget)
{
    FTouchInfo* TouchInfo = GetTouchInfo(InUserIndex, InPointerIndex);
    if (TouchInfo != nullptr)
        TouchInfo->MouseCaptors.Remove(InTarget);
}

bool UFairyApplication::HasMouseCaptor(int32 InUserIndex, int32 InPointerIndex)
{
    FTouchInfo* TouchInfo = GetTouchInfo(InUserIndex, InPointerIndex);
    return TouchInfo != nullptr && TouchInfo->MouseCaptors.Num() > 0;
}

UFairyApplication::FTouchInfo* UFairyApplication::GetTouchInfo(const FPointerEvent& MouseEvent)
{
    FTouchInfo* TouchInfo = nullptr;
    for (auto& it : Touches)
    {
        if (it.UserIndex == MouseEvent.GetUserIndex() && it.PointerIndex == (int32)MouseEvent.GetPointerIndex())
        {
            TouchInfo = &it;
            break;
        }
    }

    if (TouchInfo == nullptr)
    {
        TouchInfo = new FTouchInfo();
        Touches.Add(TouchInfo);
        TouchInfo->UserIndex = MouseEvent.GetUserIndex();
        TouchInfo->PointerIndex = (int32)MouseEvent.GetPointerIndex();
    }

    LastTouch = TouchInfo;
    return TouchInfo;
}

UFairyApplication::FTouchInfo* UFairyApplication::GetTouchInfo(int32 InUserIndex, int32 InPointerIndex)
{
    if (InUserIndex == -1 && InPointerIndex == -1)
        return LastTouch;

    for (auto& it : Touches)
    {
        if (it.UserIndex == InUserIndex && it.PointerIndex == InPointerIndex)
        {
            return &it;
        }
    }
    return nullptr;
}

void UFairyApplication::PreviewDownEvent(const FPointerEvent& MouseEvent)
{
    FTouchInfo* TouchInfo = GetTouchInfo(MouseEvent);
    TouchInfo->Event = MouseEvent;
    TouchInfo->bDown = true;
    TouchInfo->DownPosition = MouseEvent.GetScreenSpacePosition();
    TouchInfo->bClickCancelled = false;
    TouchInfo->ClickCount = 1;
    TouchInfo->MouseCaptors.Reset();
    TouchInfo->bToClearCaptors = false;
    TouchInfo->DownPath.Reset();

    bNeedCheckPopups = true;
}

void UFairyApplication::PreviewUpEvent(const FPointerEvent& MouseEvent)
{
    FTouchInfo* TouchInfo = GetTouchInfo(MouseEvent);
    TouchInfo->Event = MouseEvent;
    TouchInfo->bDown = false;
    TouchInfo->bToClearCaptors = true;

    if (TouchInfo->MouseCaptors.Num() > 0)
    {
        FMyScopedSwitchWorldHack SwitchWorld(GameInstance->GetWorld());

        int32 cnt = TouchInfo->MouseCaptors.Num();
        for (int32 i = 0; i < cnt; i++)
        {
            auto& Captor = TouchInfo->MouseCaptors[i];
            if (Captor.IsValid() && Captor->OnStage())
            {
                DispatchEvent(FUIEvents::TouchEnd, Captor->GetDisplayObject());
            }
        }
    }
}

void UFairyApplication::PreviewMoveEvent(const FPointerEvent& MouseEvent)
{
    FTouchInfo* TouchInfo = GetTouchInfo(MouseEvent);
    TouchInfo->Event = MouseEvent;

    if ((TouchInfo->DownPosition - MouseEvent.GetScreenSpacePosition()).GetAbsMax() > 50)
        TouchInfo->bClickCancelled = true;

    if (!TouchInfo->bToClearCaptors && TouchInfo->MouseCaptors.Num() > 0)
    {
        FMyScopedSwitchWorldHack SwitchWorld(GameInstance->GetWorld());

        int32 cnt = TouchInfo->MouseCaptors.Num();
        for (int32 i = 0; i < cnt; i++)
        {
            auto& Captor = TouchInfo->MouseCaptors[i];
            if (Captor.IsValid() && Captor->OnStage())
            {
                DispatchEvent(FUIEvents::TouchMove, Captor->GetDisplayObject());
            }
        }
    }
}

FReply UFairyApplication::OnWidgetMouseButtonDown(const TSharedRef<SWidget>& Widget, const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
    FMyScopedSwitchWorldHack SwitchWorld(GameInstance->GetWorld());

    FTouchInfo* TouchInfo = GetTouchInfo(MouseEvent);

    UGObject* InitialGObject = nullptr;
    TSharedPtr<SWidget> Ptr = Widget;
    while (Ptr.IsValid() && Ptr != ViewportWidget)
    {
        TouchInfo->DownPath.Add(Ptr);

        if (InitialGObject == nullptr && Ptr->GetTag() == SDisplayObject::SDisplayObjectTag)
        {
            InitialGObject = StaticCastSharedPtr<SDisplayObject>(Ptr)->GObject.Get();
        }

        Ptr = Ptr->GetParentWidget();
    }

    bNeedCheckPopups = false;
    if (UIRoot != nullptr)
        UIRoot->CheckPopups(&Widget.Get());

    BubbleEvent(FUIEvents::TouchBegin, Widget);

    return FReply::Handled();
}

FReply UFairyApplication::OnWidgetMouseButtonUp(const TSharedRef<SWidget>& Widget, const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
    FMyScopedSwitchWorldHack SwitchWorld(GameInstance->GetWorld());

    FTouchInfo* TouchInfo = GetTouchInfo(MouseEvent);
    if (TouchInfo == nullptr)
        return FReply::Handled().ReleaseMouseCapture();

    TArray<UGObject*> CallChain;
    SDisplayObject::GetWidgetPathToRoot(Widget, CallChain);
    if (CallChain.Num() > 0)
    {
        for (auto& it : TouchInfo->MouseCaptors)
        {
            if (it.IsValid())
                CallChain.RemoveSingle(it.Get());
        }

        if (CallChain.Num() > 0)
            InternalBubbleEvent(FUIEvents::TouchEnd, CallChain, FNVariant::Null);
    }
    TouchInfo->MouseCaptors.Reset();

    if (!TouchInfo->bClickCancelled)
    {
        TSharedPtr<SWidget> Ptr = Widget;
        while (Ptr.IsValid() && Ptr != ViewportWidget)
        {
            if (TouchInfo->DownPath.Contains(Ptr))
            {
                BubbleEvent(FUIEvents::Click, Ptr.ToSharedRef());
                break;
            }

            Ptr = Ptr->GetParentWidget();
        }
    }

    TouchInfo->DownPath.Reset();

    return FReply::Handled().ReleaseMouseCapture();
}

FReply UFairyApplication::OnWidgetMouseMove(const TSharedRef<SWidget>& Widget, const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
    return FReply::Handled();
}

FReply UFairyApplication::OnWidgetMouseButtonDoubleClick(const TSharedRef<SWidget>& Widget, const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
    FTouchInfo* TouchInfo = GetTouchInfo(MouseEvent);
    TouchInfo->ClickCount = 2;

    return OnWidgetMouseButtonDown(Widget, MyGeometry, MouseEvent);
}

void UFairyApplication::OnWidgetMouseEnter(const TSharedRef<SWidget>& Widget, const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
    FMyScopedSwitchWorldHack SwitchWorld(GameInstance->GetWorld());

    FTouchInfo* TouchInfo = GetTouchInfo(MouseEvent);
    DispatchEvent(FUIEvents::RollOver, Widget);
}

void UFairyApplication::OnWidgetMouseLeave(const TSharedRef<SWidget>& Widget, const FPointerEvent& MouseEvent)
{
    FMyScopedSwitchWorldHack SwitchWorld(GameInstance->GetWorld());

    FTouchInfo* TouchInfo = GetTouchInfo(MouseEvent);
    DispatchEvent(FUIEvents::RollOut, Widget);
}

FReply UFairyApplication::OnWidgetMouseWheel(const TSharedRef<SWidget>& Widget, const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
    FMyScopedSwitchWorldHack SwitchWorld(GameInstance->GetWorld());

    FTouchInfo* TouchInfo = GetTouchInfo(MouseEvent);
    TouchInfo->Event = MouseEvent;

    BubbleEvent(FUIEvents::MouseWheel, Widget);

    return FReply::Handled();
}

================================================
FILE: Source/FairyGUI/Private/FairyBlueprintLibrary.cpp
================================================
#include "FairyBlueprintLibrary.h"
#include "UI/UIConfig.h"
#include "UI/UIObjectFactory.h"
#include "Tween/GTween.h"

const FUIConfig& UFairyBlueprintLibrary::GetUIConfig()
{
    return FUIConfig::Config;
}

void UFairyBlueprintLibrary::SetUIConfig(const FUIConfig& InConfig)
{
    FUIConfig::Config = InConfig;
}

bool UFairyBlueprintLibrary::GetVariantAsBool(UPARAM(ref) FNVariant& InVariant)
{
    return InVariant.AsBool();
}

int32 UFairyBlueprintLibrary::GetVariantAsInt(UPARAM(ref) FNVariant& InVariant)
{
    return InVariant.AsInt();
}

float UFairyBlueprintLibrary::GetVariantAsFloat(UPARAM(ref) FNVariant& InVariant)
{
    return InVariant.AsFloat();
}

FString UFairyBlueprintLibrary::GetVariantAsString(UPARAM(ref) FNVariant& InVariant)
{
    return InVariant.AsString();
}

FColor UFairyBlueprintLibrary::GetVariantAsColor(UPARAM(ref) FNVariant& InVariant)
{
    return InVariant.AsColor();
}

UObject* UFairyBlueprintLibrary::GetVariantAsUObject(UPARAM(ref) FNVariant& InVariant, TSubclassOf<UObject> ClassType)
{
    return InVariant.AsUObject();
}

FNVariant& UFairyBlueprintLibrary::SetVariantBool(UPARAM(ref) FNVariant& InVariant, bool bInValue)
{
    InVariant = bInValue;
    return InVariant;
}

FNVariant& UFairyBlueprintLibrary::SetVariantInt(UPARAM(ref) FNVariant& InVariant, int32 InValue)
{
    InVariant = InValue;
    return InVariant;
}

FNVariant& UFairyBlueprintLibrary::SetVariantFloat(UPARAM(ref) FNVariant& InVariant, float InValue)
{
    InVariant = InValue;
    return InVariant;
}

FNVariant& UFairyBlueprintLibrary::SetVariantString(UPARAM(ref) FNVariant& InVariant, const FString& InValue)
{
    InVariant = InValue;
    return InVariant;
}

FNVariant& UFairyBlueprintLibrary::SetVariantColor(UPARAM(ref) FNVariant& InVariant, const FColor& InValue)
{
    InVariant = InValue;
    return InVariant;
}

FNVariant& UFairyBlueprintLibrary::SetVariantUObject(UPARAM(ref) FNVariant& InVariant, UObject* InValue)
{
    InVariant = (void*)InValue;
    return InVariant;
}

FTweenerHandle UFairyBlueprintLibrary::TweenFloat(float StartValue, float EndValue, EEaseType EaseType, float Duration, int32 Repeat, const FTweenUpdateDynDelegate& OnUpdate, const FSimpleDynDelegate& OnComplete)
{
    const UObject* Target = nullptr;
    if (OnUpdate.IsBound())
        Target = OnUpdate.GetUObject();
    else
        Target = OnComplete.GetUObject();

    if (Target == nullptr)
        return FTweenerHandle();

    FGTweener* Tweener = FGTween::To(StartValue, EndValue, Duration)
        ->SetEase(EaseType)
        ->SetRepeat(Repeat)
        ->SetTarget(const_cast<UObject*>(Target));
    if (OnUpdate.IsBound())
    {
        Tweener->OnUpdate(FTweenDelegate::CreateLambda([OnUpdate](FGTweener* Tweener) {
            OnUpdate.ExecuteIfBound(Tweener->Value, Tweener->DeltaValue);
        }));
    }

    if (OnComplete.IsBound())
    {
        Tweener->OnComplete(FSimpleDelegate::CreateLambda([OnComplete]() {
            OnComplete.ExecuteIfBound();
        }));
    }

    return Tweener->GetHandle();
}

FTweenerHandle UFairyBlueprintLibrary::TweenVector2(const FVector2D& StartValue, const FVector2D& EndValue, EEaseType EaseType, float Duration, int32 Repeat, const FTweenUpdateDynDelegate& OnUpdate, const FSimpleDynDelegate& OnComplete)
{
    const UObject* Target = nullptr;
    if (OnUpdate.IsBound())
        Target = OnUpdate.GetUObject();
    else
        Target = OnComplete.GetUObject();

    if (Target == nullptr)
        return FTweenerHandle();

    FGTweener* Tweener = FGTween::To(StartValue, EndValue, Duration)
        ->SetEase(EaseType)
        ->SetRepeat(Repeat)
        ->SetTarget(const_cast<UObject*>(Target));

    if (OnUpdate.IsBound())
    {
        Tweener->OnUpdate(FTweenDelegate::CreateLambda([OnUpdate](FGTweener* Tweener) {
            OnUpdate.ExecuteIfBound(Tweener->Value, Tweener->DeltaValue);
        }));
    }

    if (OnComplete.IsBound())
    {
        Tweener->OnComplete(FSimpleDelegate::CreateLambda([OnComplete]() {
            OnComplete.ExecuteIfBound();
        }));
    }

    return Tweener->GetHandle();
}

void UFairyBlueprintLibrary::KillTween(UPARAM(ref) FTweenerHandle& Handle, bool bSetComplete)
{
    FGTween::Kill(Handle, bSetComplete);
}

void UFairyBlueprintLibrary::SetPackageItemExtension(const FString& URL, TSubclassOf<UGComponent> ClassType)
{
    FUIObjectFactory::SetExtension(URL, ClassType);
}

================================================
FILE: Source/FairyGUI/Private/FairyCommons.cpp
================================================
#include "FairyCommons.h"
#include "Framework/Application/SlateApplication.h"

DEFINE_LOG_CATEGORY(LogFairyGUI);

const FString G_EMPTY_STRING("");

================================================
FILE: Source/FairyGUI/Private/FairyGUIModule.cpp
================================================
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.

#include "FairyGUIModule.h"
#if WITH_EDITOR
#include "Editor.h"
#include "FairyApplication.h"
#endif
#include "UI/UIConfig.h"

#define LOCTEXT_NAMESPACE "FFairyGUIModule"

void FFairyGUIModule::StartupModule()
{
	// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module

#if WITH_EDITOR
    EndPieDelegateHandle = FEditorDelegates::EndPIE.AddLambda([](bool boolSent) {
        UE_LOG(LogFairyGUI, Log, TEXT("Application destroy"));

        UFairyApplication::Destroy();
    });
#endif
}

void FFairyGUIModule::ShutdownModule()
{
	// This function may be called during shutdown to clean up your module.  For modules that support dynamic reloading,
	// we call this function before unloading the module.

#if WITH_EDITOR
    FEditorDelegates::EndPIE.Remove(EndPieDelegateHandle);
#endif
}

#undef LOCTEXT_NAMESPACE
	
IMPLEMENT_MODULE(FFairyGUIModule, FairyGUI)

================================================
FILE: Source/FairyGUI/Private/Tween/EaseManager.cpp
================================================
#include "Tween/EaseManager.h"

static const float _PiOver2 = (PI * 0.5f);
static const float _TwoPi = (PI * 2);

class Bounce
{
public:
    static float EaseIn(float Time, float Duration);
    static float EaseOut(float Time, float Duration);
    static float EaseInOut(float Time, float Duration);
};

float EaseManager::Evaluate(EEaseType EaseType, float Time, float Duration, float OvershootOrAmplitude, float Period)
{
    switch (EaseType)
    {
    case EEaseType::Linear:
        return Time / Duration;
    case EEaseType::SineIn:
        return -FMath::Cos(Time / Duration * _PiOver2) + 1;
    case EEaseType::SineOut:
        return FMath::Sin(Time / Duration * _PiOver2);
    case EEaseType::SineInOut:
        return -0.5f * (FMath::Cos(PI * Time / Duration) - 1);
    case EEaseType::QuadIn:
        Time /= Duration;
        return Time * Time;
    case EEaseType::QuadOut:
        Time /= Duration;
        return -Time * (Time - 2);
    case EEaseType::QuadInOut:
        Time /= Duration * 0.5f;
        if (Time < 1) return 0.5f * Time * Time;
        --Time;
        return -0.5f * (Time * (Time - 2) - 1);
    case EEaseType::CubicIn:
        Time /= Duration;
        return Time * Time * Time;
    case EEaseType::CubicOut:
        Time = Time / Duration - 1;
        return Time * Time * Time + 1;
    case EEaseType::CubicInOut:
        Time /= Duration * 0.5f;
        if (Time < 1) return 0.5f * Time * Time * Time;
        Time -= 2;
        return 0.5f * (Time * Time * Time + 2);
    case EEaseType::QuartIn:
        Time /= Duration;
        return Time * Time * Time * Time;
    case EEaseType::QuartOut:
        Time = Time / Duration - 1;
        return -(Time * Time * Time * Time - 1);
    case EEaseType::QuartInOut:
        Time /= Duration * 0.5f;
        if (Time < 1) return 0.5f * Time * Time * Time * Time;
        Time -= 2;
        return -0.5f * (Time * Time * Time * Time - 2);
    case EEaseType::QuintIn:
        Time /= Duration;
        return Time * Time * Time * Time * Time;
    case EEaseType::QuintOut:
        Time = Time / Duration - 1;
        return (Time * Time * Time * Time * Time + 1);
    case EEaseType::QuintInOut:
        Time /= Duration * 0.5f;
        if (Time < 1) return 0.5f * Time * Time * Time * Time * Time;
        Time -= 2;
        return 0.5f * (Time * Time * Time * Time * Time + 2);
    case EEaseType::ExpoIn:
        return (Time == 0) ? 0 : FMath::Pow(2, 10 * (Time / Duration - 1));
    case EEaseType::ExpoOut:
        if (Time == Duration) return 1;
        return (-FMath::Pow(2, -10 * Time / Duration) + 1);
    case EEaseType::ExpoInOut:
        if (Time == 0) return 0;
        if (Time == Duration) return 1;
        if ((Time /= Duration * 0.5f) < 1) return 0.5f * FMath::Pow(2, 10 * (Time - 1));
        return 0.5f * (-FMath::Pow(2, -10 * --Time) + 2);
    case EEaseType::CircIn:
        Time /= Duration;
        return -(FMath::Sqrt(1 - Time * Time) - 1);
    case EEaseType::CircOut:
        Time = Time / Duration - 1;
        return FMath::Sqrt(1 - Time * Time);
    case EEaseType::CircInOut:
        Time /= Duration * 0.5f;
        if (Time < 1) return -0.5f * (FMath::Sqrt(1 - Time * Time) - 1);
        Time -= 2;
        return 0.5f * (FMath::Sqrt(1 - Time * Time) + 1);
    case EEaseType::ElasticIn:
        float s0;
        if (Time == 0) return 0;
        if ((Time /= Duration) == 1) return 1;
        if (Period == 0) Period = Duration * 0.3f;
        if (OvershootOrAmplitude < 1)
        {
            OvershootOrAmplitude = 1;
            s0 = Period / 4;
        }
        else s0 = Period / _TwoPi * FMath::Asin(1 / OvershootOrAmplitude);
        Time -= 1;
        return -(OvershootOrAmplitude * FMath::Pow(2, 10 * Time) * FMath::Sin((Time * Duration - s0) * _TwoPi / Period));
    case EEaseType::ElasticOut:
        float s1;
        if (Time == 0) return 0;
        if ((Time /= Duration) == 1) return 1;
        if (Period == 0) Period = Duration * 0.3f;
        if (OvershootOrAmplitude < 1)
        {
            OvershootOrAmplitude = 1;
            s1 = Period / 4;
        }
        else s1 = Period / _TwoPi * FMath::Asin(1 / OvershootOrAmplitude);
        return (OvershootOrAmplitude * FMath::Pow(2, -10 * Time) * FMath::Sin((Time * Duration - s1) * _TwoPi / Period) + 1);
    case EEaseType::ElasticInOut:
        float s;
        if (Time == 0) return 0;
        if ((Time /= Duration * 0.5f) == 2) return 1;
        if (Period == 0) Period = Duration * (0.3f * 1.5f);
        if (OvershootOrAmplitude < 1)
        {
            OvershootOrAmplitude = 1;
            s = Period / 4;
        }
        else s = Period / _TwoPi * FMath::Asin(1 / OvershootOrAmplitude);
        if (Time < 1)
        {
            Time -= 1;
            return -0.5f * (OvershootOrAmplitude * FMath::Pow(2, 10 * Time) * FMath::Sin((Time * Duration - s) * _TwoPi / Period));
        }
            
        Time -= 1;
        return OvershootOrAmplitude * FMath::Pow(2, -10 * Time) * FMath::Sin((Time * Duration - s) * _TwoPi / Period) * 0.5f + 1;
    case EEaseType::BackIn:
        Time /= Duration;
        return Time * Time * ((OvershootOrAmplitude + 1) * Time - OvershootOrAmplitude);
    case EEaseType::BackOut:
        Time = Time / Duration - 1;
        return (Time * Time * ((OvershootOrAmplitude + 1) * Time + OvershootOrAmplitude) + 1);
    case EEaseType::BackInOut:
        Time /= Duration * 0.5f;
        OvershootOrAmplitude *= (1.525f);
        if (Time < 1) return 0.5f * (Time * Time * ((OvershootOrAmplitude + 1) * Time - OvershootOrAmplitude));
        Time -= 2;
        return 0.5f * (Time * Time * ((OvershootOrAmplitude + 1) * Time + OvershootOrAmplitude) + 2);
    case EEaseType::BounceIn:
        return Bounce::EaseIn(Time, Duration);
    case EEaseType::BounceOut:
        return Bounce::EaseOut(Time, Duration);
    case EEaseType::BounceInOut:
        return Bounce::EaseInOut(Time, Duration);

    default:
        Time /= Duration;
        return -Time * (Time - 2);
    }
}

float Bounce::EaseIn(float Time, float Duration)
{
    return 1 - EaseOut(Duration - Time, Duration);
}

float Bounce::EaseOut(float Time, float Duration)
{
    Time /= Duration;
    if (Time < (1 / 2.75f))
    {
        return (7.5625f * Time * Time);
    }
    if (Time < (2 / 2.75f))
    {
        Time -= (1.5f / 2.75f);
        return (7.5625f * Time * Time + 0.75f);
    }
    if (Time < (2.5f / 2.75f))
    {
        Time -= (2.25f / 2.75f);
        return (7.5625f * Time * Time + 0.9375f);
    }
    Time -= (2.625f / 2.75f);
    return (7.5625f * Time * Time + 0.984375f);
}

float Bounce::EaseInOut(float Time, float Duration)
{
    if (Time < Duration * 0.5f)
    {
        return EaseIn(Time * 2, Duration) * 0.5f;
    }
    return EaseOut(Time * 2 - Duration, Duration) * 0.5f + 0.5f;
}



================================================
FILE: Source/FairyGUI/Private/Tween/GPath.cpp
================================================
#include "Tween/GPath.h"

FGPathPoint::FGPathPoint(const FVector& InPos)
{
    Pos = InPos;
    Control1 = FVector::ZeroVector;
    Control2 = FVector::ZeroVector;
    CurveType = ECurveType::CRSpline;
}

FGPathPoint::FGPathPoint(const FVector& InPos, const FVector& InControl)
{
    Pos = InPos;
    Control1 = InControl;
    Control2 = FVector::ZeroVector;
    CurveType = ECurveType::Bezier;
}

FGPathPoint::FGPathPoint(const FVector& InPos, const FVector& InControl1, const FVector& InControl2)
{
    Pos = InPos;
    Control1 = InControl1;
    Control2 = InControl2;
    CurveType = ECurveType::CubicBezier;
}

FGPathPoint::FGPathPoint(const FVector& InPos, ECurveType InCurveType)
{
    Pos = InPos;
    Control1 = FVector::ZeroVector;
    Control2 = FVector::ZeroVector;
    CurveType = InCurveType;
}

FGPath::FGPath()
    : FullLength(0)
{
}

void FGPath::Create(const FGPathPoint* InPoints, int32 Count)
{
    Segments.Reset();
    Points.Reset();
    FullLength = 0;

    if (Count == 0)
        return;

    TArray<FVector> SplinePoints;
    const FGPathPoint* prev = InPoints;
    if (prev->CurveType == FGPathPoint::ECurveType::CRSpline)
        SplinePoints.Add(prev->Pos);

    for (int32 i = 1; i < Count; i++)
    {
        const FGPathPoint* current = InPoints + i;

        if (prev->CurveType != FGPathPoint::ECurveType::CRSpline)
        {
            FSegment seg;
            seg.Type = prev->CurveType;
            seg.PointStart = Points.Num();
            if (prev->CurveType == FGPathPoint::ECurveType::Straight)
            {
                seg.PointCount = 2;
                Points.Add(prev->Pos);
                Points.Add(current->Pos);
            }
            else if (prev->CurveType == FGPathPoint::ECurveType::Bezier)
            {
                seg.PointCount = 3;
                Points.Add(prev->Pos);
                Points.Add(current->Pos);
                Points.Add(prev->Control1);
            }
            else if (prev->CurveType == FGPathPoint::ECurveType::CubicBezier)
            {
                seg.PointCount = 4;
                Points.Add(prev->Pos);
                Points.Add(current->Pos);
                Points.Add(prev->Control1);
                Points.Add(prev->Control2);
            }
            seg.Length = FVector::Dist(prev->Pos, current->Pos);
            FullLength += seg.Length;
            Segments.Add(MoveTemp(seg));
        }

        if (current->CurveType != FGPathPoint::ECurveType::CRSpline)
        {
            if (SplinePoints.Num() > 0)
            {
                SplinePoints.Add(current->Pos);
                CreateSplineSegment(SplinePoints);
            }
        }
        else
            SplinePoints.Add(current->Pos);

        prev = current;
    }

    if (SplinePoints.Num() > 1)
        CreateSplineSegment(SplinePoints);
}

void FGPath::CreateSplineSegment(TArray<FVector>& SplinePoints)
{
    int32 cnt = SplinePoints.Num();
    SplinePoints.Insert(SplinePoints[0], 0);
    SplinePoints.Add(SplinePoints[cnt]);
    SplinePoints.Add(SplinePoints[cnt]);
    cnt += 3;

    FSegment seg;
    seg.Type = FGPathPoint::ECurveType::CRSpline;
    seg.PointStart = Points.Num();
    seg.PointCount = cnt;
    for (auto& it : SplinePoints)
        Points.Add(it);

    seg.Length = 0;
    for (int32 i = 1; i < cnt; i++)
        seg.Length += FVector::Dist(SplinePoints[i - 1], SplinePoints[i]);
    FullLength += seg.Length;
    Segments.Add(MoveTemp(seg));
    SplinePoints.Reset();
}

void FGPath::Clear()
{
    Segments.Reset();
    Points.Reset();
}

FVector FGPath::GetPointAt(float Time)
{
    Time = FMath::Clamp<float>(Time, 0, 1);
    int32 cnt = Segments.Num();
    if (cnt == 0)
        return FVector::ZeroVector;

    if (Time == 1)
    {
        const FSegment& seg = Segments[cnt - 1];

        if (seg.Type == FGPathPoint::ECurveType::Straight)
            return FMath::Lerp(Points[seg.PointStart], Points[seg.PointStart + 1], Time);
        else if (seg.Type == FGPathPoint::ECurveType::Bezier || seg.Type == FGPathPoint::ECurveType::CubicBezier)
            return OnBezierCurve(seg.PointStart, seg.PointCount, Time);
        else
            return OnCRSplineCurve(seg.PointStart, seg.PointCount, Time);
    }

    float len = Time * FullLength;
    FVector pt;
    for (int32 i = 0; i < cnt; i++)
    {
        const FSegment& seg = Segments[i];

        len -= seg.Length;
        if (len < 0)
        {
            Time = 1 + len / seg.Length;

            if (seg.Type == FGPathPoint::ECurveType::Straight)
                pt = FMath::Lerp(Points[seg.PointStart], Points[seg.PointStart + 1], Time);
            else if (seg.Type == FGPathPoint::ECurveType::Bezier || seg.Type == FGPathPoint::ECurveType::CubicBezier)
                pt = OnBezierCurve(seg.PointStart, seg.PointCount, Time);
            else
                pt = OnCRSplineCurve(seg.PointStart, seg.PointCount, Time);

            break;
        }
    }

    return pt;
}

float FGPath::GetSegmentLength(int32 SegmentIndex)
{
    return Segments[SegmentIndex].Length;
}

void FGPath::GetPointsInSegment(int32 SegmentIndex, float t0, float t1,
    TArray<FVector>& OutPoints, TArray<float>* OutTimeArray, float PointDensity)
{
    if (OutTimeArray != nullptr)
        OutTimeArray->Add(t0);
    const FSegment& seg = Segments[SegmentIndex];
    if (seg.Type == FGPathPoint::ECurveType::Straight)
    {
        OutPoints.Add(FMath::Lerp(Points[seg.PointStart], Points[seg.PointStart + 1], t0));
        OutPoints.Add(FMath::Lerp(Points[seg.PointStart], Points[seg.PointStart + 1], t1));
    }
    else if (seg.Type == FGPathPoint::ECurveType::Bezier || seg.Type == FGPathPoint::ECurveType::CubicBezier)
    {
        OutPoints.Add(OnBezierCurve(seg.PointStart, seg.PointCount, t0));
        int32 SmoothAmount = FMath::Min(FMath::FloorToInt(seg.Length * PointDensity), 50);
        for (int32 j = 0; j <= SmoothAmount; j++)
        {
            float t = (float)j / SmoothAmount;
            if (t > t0 && t < t1)
            {
                OutPoints.Add(OnBezierCurve(seg.PointStart, seg.PointCount, t));
                if (OutTimeArray != nullptr)
                    OutTimeArray->Add(t);
            }
        }
        OutPoints.Add(OnBezierCurve(seg.PointStart, seg.PointCount, t1));
    }
    else
    {
        OutPoints.Add(OnCRSplineCurve(seg.PointStart, seg.PointCount, t0));
        int32 SmoothAmount = FMath::Min(FMath::FloorToInt(seg.Length * PointDensity), 50);
        for (int32 j = 0; j <= SmoothAmount; j++)
        {
            float t = (float)j / SmoothAmount;
            if (t > t0 && t < t1)
            {
                OutPoints.Add(OnCRSplineCurve(seg.PointStart, seg.PointCount, t));
                if (OutTimeArray != nullptr)
                    OutTimeArray->Add(t);
            }
        }
        OutPoints.Add(OnCRSplineCurve(seg.PointStart, seg.PointCount, t1));
    }

    if (OutTimeArray != nullptr)
        OutTimeArray->Add(t1);
}

void FGPath::GetAllPoints(TArray<FVector>& OutPoints, float PointDensity)
{
    int32 cnt = Segments.Num();
    for (int32 i = 0; i < cnt; i++)
        GetPointsInSegment(i, 0, 1, OutPoints, nullptr, PointDensity);
}

static float repeat(float t, float length)
{
    return t - FMath::FloorToFloat(t / length) * length;
}

FVector FGPath::OnCRSplineCurve(int32 PointStart, int32 PointCount, float Time)
{
    int32 adjustedIndex = FMath::FloorToFloat(Time * (PointCount - 4)) + PointStart; //Since the equation works with 4 points, we adjust the starting point depending on t to return a point on the specific segment

    FVector result;

    FVector p0 = Points[adjustedIndex];
    FVector p1 = Points[adjustedIndex + 1];
    FVector p2 = Points[adjustedIndex + 2];
    FVector p3 = Points[adjustedIndex + 3];

    float adjustedT = (Time == 1.f) ? 1.f : repeat(Time * (PointCount - 4), 1.f); // Then we adjust t to be that value on that new piece of segment... for t == 1f don't use repeat (that would return 0f);

    float t0 = ((-adjustedT + 2.f) * adjustedT - 1.f) * adjustedT * 0.5f;
    float t1 = (((3.f * adjustedT - 5.f) * adjustedT) * adjustedT + 2.f) * 0.5f;
    float t2 = ((-3.f * adjustedT + 4.f) * adjustedT + 1.f) * adjustedT * 0.5f;
    float t3 = ((adjustedT - 1.f) * adjustedT * adjustedT) * 0.5f;

    result.X = p0.X * t0 + p1.X * t1 + p2.X * t2 + p3.X * t3;
    result.Y = p0.Y * t0 + p1.Y * t1 + p2.Y * t2 + p3.Y * t3;
    result.Z = p0.Z * t0 + p1.Z * t1 + p2.Z * t2 + p3.Z * t3;

    return result;
}

FVector FGPath::OnBezierCurve(int32 PointStart, int32 PointCount, float Time)
{
    float t2 = 1.0f - Time;
    FVector p0 = Points[PointStart];
    FVector p1 = Points[PointStart + 1];
    FVector cp0 = Points[PointStart + 2];

    if (PointCount == 4)
    {
        FVector cp1 = Points[PointStart + 3];
        return t2 * t2 * t2 * p0 + 3.f * t2 * t2 * Time * cp0 + 3.f * t2 * Time * Time * cp1 + Time * Time * Time * p1;
    }
    else
        return t2 * t2 * p0 + 2.f * t2 * Time * cp0 + Time * Time * p1;
}

================================================
FILE: Source/FairyGUI/Private/Tween/GTween.cpp
================================================
#include "Tween/GTween.h"
#include "Tween/TweenManager.h"
#include "UI/GProgressBar.h"

FGTweener* FGTween::To(float StartValue, float EndValue, float Duration)
{
    return FTweenManager::Singleton.CreateTween()->To(StartValue, EndValue, Duration);
}

FGTweener* FGTween::To(const FVector2D& StartValue, const FVector2D & EndValue, float Duration)
{
    return FTweenManager::Singleton.CreateTween()->To(StartValue, EndValue, Duration);
}

FGTweener* FGTween::To(const FVector& StartValue, const FVector & EndValue, float Duration)
{
    return FTweenManager::Singleton.CreateTween()->To(StartValue, EndValue, Duration);
}

FGTweener* FGTween::To(const FVector4& StartValue, const FVector4 & EndValue, float Duration)
{
    return FTweenManager::Singleton.CreateTween()->To(StartValue, EndValue, Duration);
}

FGTweener* FGTween::To(const FColor& StartValue, const FColor & EndValue, float Duration)
{
    return FTweenManager::Singleton.CreateTween()->To(StartValue, EndValue, Duration);
}

FGTweener* FGTween::ToDouble(double StartValue, double EndValue, float Duration)
{
    return FTweenManager::Singleton.CreateTween()->To(StartValue, EndValue, Duration);
}

FGTweener* FGTween::DelayedCall(float Delay)
{
    return FTweenManager::Singleton.CreateTween()->SetDelay(Delay);
}

FGTweener* FGTween::Shake(const FVector2D& StartValue, float Amplitude, float Duration)
{
    return FTweenManager::Singleton.CreateTween()->Shake(StartValue, Amplitude, Duration);
}

bool FGTween::IsTweening(const FTweenerHandle& Handle)
{
    return FTweenManager::Singleton.IsTweening(Handle);
}

bool FGTween::IsTweening(UObject* Target)
{
    return FTweenManager::Singleton.IsTweening(Target);
}

void FGTween::Kill(FTweenerHandle& Handle, bool bSetComplete)
{
    FTweenManager::Singleton.KillTween(Handle, bSetComplete);
}

void FGTween::Kill(UObject* Target, bool bSetComplete)
{
    FTweenManager::Singleton.KillTweens(Target, bSetComplete);
}

FGTweener* FGTween::GetTween(const FTweenerHandle& Handle)
{
    return FTweenManager::Singleton.GetTween(Handle);
}

FGTweener* FGTween::GetTween(UObject * Target)
{
    return FTweenManager::Singleton.GetTween(Target);
}

void FGTweenAction::MoveX(FGTweener* Tweener)
{
    UGObject * target = Cast<UGObject>(Tweener->GetTarget());
    target->SetX(Tweener->Value.X);
}

void FGTweenAction::MoveY(FGTweener* Tweener)
{
    UGObject * target = Cast<UGObject>(Tweener->GetTarget());
    target->SetY(Tweener->Value.X);
}

void FGTweenAction::Move(FGTweener* Tweener)
{
    UGObject * target = Cast<UGObject>(Tweener->GetTarget());
    target->SetPosition(Tweener->Value.GetVec2());
}

void FGTweenAction::SetWidth(FGTweener* Tweener)
{
    UGObject * target = Cast<UGObject>(Tweener->GetTarget());
    target->SetWidth(Tweener->Value.X);
}

void FGTweenAction::SetHeight(FGTweener* Tweener)
{
    UGObject * target = Cast<UGObject>(Tweener->GetTarget());
    target->SetHeight(Tweener->Value.X);
}

void FGTweenAction::SetSize(FGTweener* Tweener)
{
    UGObject * target = Cast<UGObject>(Tweener->GetTarget());
    target->SetSize(Tweener->Value.GetVec2());
}

void FGTweenAction::ScaleX(FGTweener* Tweener)
{
    UGObject * target = Cast<UGObject>(Tweener->GetTarget());
    target->SetScaleX(Tweener->Value.X);
}

void FGTweenAction::ScaleY(FGTweener* Tweener)
{
    UGObject * target = Cast<UGObject>(Tweener->GetTarget());
    target->SetScaleY(Tweener->Value.X);
}

void FGTweenAction::ScaleXY(FGTweener* Tweener)
{
    UGObject * target = Cast<UGObject>(Tweener->GetTarget());
    target->SetScale(Tweener->Value.GetVec2());
}

void FGTweenAction::Rotate(FGTweener* Tweener)
{
    UGObject * target = Cast<UGObject>(Tweener->GetTarget());
    target->SetRotation(Tweener->Value.X);
}

void FGTweenAction::SetAlpha(FGTweener* Tweener)
{
    UGObject * target = Cast<UGObject>(Tweener->GetTarget());
    target->SetAlpha(Tweener->Value.X);
}

void FGTweenAction::SetProgress(FGTweener* Tweener)
{
    UGProgressBar * target = Cast<UGProgressBar>(Tweener->GetTarget());
    target->Update(Tweener->Value.X);
}


================================================
FILE: Source/FairyGUI/Private/Tween/GTweener.cpp
================================================
#include "Tween/GTweener.h"
#include "Tween/EaseManager.h"
#include "Tween/GPath.h"
#include "UI/GObject.h"

FGTweener::FGTweener()
{
}

FGTweener::~FGTweener()
{
}

FGTweener* FGTweener::SetDelay(float InValue)
{
    Delay = InValue;
    return this;
}

FGTweener* FGTweener::SetDuration(float InValue)
{
    Duration = InValue;
    return this;
}

FGTweener* FGTweener::SetBreakpoint(float InValue)
{
    Breakpoint = InValue;
    return this;
}

FGTweener* FGTweener::SetEase(EEaseType InValue)
{
    EaseType = InValue;
    return this;
}

FGTweener* FGTweener::SetEasePeriod(float InValue)
{
    EasePeriod = InValue;
    return this;
}

FGTweener* FGTweener::SetEaseOvershootOrAmplitude(float InValue)
{
    EaseOvershootOrAmplitude = InValue;
    return this;
}

FGTweener* FGTweener::SetRepeat(int32 InRepeat, bool bInYoyo)
{
    Repeat = InRepeat;
    bYoyo = bInYoyo;
    return this;
}

FGTweener* FGTweener::SetTimeScale(float InValue)
{
    TimeScale = InValue;
    return this;
}

FGTweener* FGTweener::SetSnapping(bool bInValue)
{
    bSnapping = bInValue;
    return this;
}

FGTweener* FGTweener::SetTarget(UObject* InTarget)
{
    Target = InTarget;
    return this;
}

FGTweener* FGTweener::SetUserData(const FNVariant& InData)
{
    UserData = InData;
    return this;
}

FGTweener* FGTweener::SetPath(TSharedPtr<FGPath> InPath)
{
    Path = InPath;
    return this;
}

FGTweener* FGTweener::OnUpdate(FTweenDelegate Callback)
{
    OnUpdateCallback = Callback;
    return this;
}

FGTweener* FGTweener::OnStart(FTweenDelegate Callback)
{
    OnStartCallback = Callback;
    return this;
}

FGTweener* FGTweener::OnComplete(FTweenDelegate Callback)
{
    OnCompleteCallback = Callback;
    return this;
}

FGTweener* FGTweener::OnUpdate(FSimpleDelegate Callback)
{
    OnUpdateCallback.BindLambda([Callback](FGTweener*) {
        Callback.ExecuteIfBound();
    });
    return this;
}

FGTweener* FGTweener::OnStart(FSimpleDelegate Callback)
{
    OnStartCallback.BindLambda([Callback](FGTweener*) {
        Callback.ExecuteIfBound();
    });
    return this;
}

FGTweener* FGTweener::OnComplete(FSimpleDelegate Callback)
{
    OnCompleteCallback.BindLambda([Callback](FGTweener*) {
        Callback.ExecuteIfBound();
    });
    return this;
}

FGTweener* FGTweener::SetPaused(bool bInPaused)
{
    bPaused = bInPaused;
    return this;
}

void FGTweener::Seek(float Time)
{
    if (bKilled)
        return;

    ElapsedTime = Time;
    if (ElapsedTime < Delay)
    {
        if (bStarted)
            ElapsedTime = Delay;
        else
            return;
    }

    Update();
}

void FGTweener::Kill(bool bSetComplete)
{
    if (bKilled)
        return;

    if (bSetComplete)
    {
        if (Ended == 0)
        {
            if (Breakpoint >= 0)
                ElapsedTime = Delay + Breakpoint;
            else if (Repeat >= 0)
                ElapsedTime = Delay + Duration * (Repeat + 1);
            else
                ElapsedTime = Delay + Duration * 2;
            Update();
        }

        OnCompleteCallback.ExecuteIfBound(this);
    }

    bKilled = true;
}

FGTweener* FGTweener::To(float InStart, float InEnd, float InDuration)
{
    ValueSize = 1;
    StartValue.X = InStart;
    EndValue.X = InEnd;
    Value.X = InStart;
    Duration = InDuration;
    return this;
}

FGTweener* FGTweener::To(const FVector2D& InStart, const FVector2D& InEnd, float InDuration)
{
    ValueSize = 2;
    StartValue.SetVec2(InStart);
    EndValue.SetVec2(InEnd);
    Value.SetVec2(InStart);
    Duration = InDuration;
    return this;
}

FGTweener* FGTweener::To(const FVector& InStart, const FVector& InEnd, float InDuration)
{
    ValueSize = 3;
    StartValue.SetVec3(InStart);
    EndValue.SetVec3(InEnd);
    Value.SetVec3(InStart);
    Duration = InDuration;
    return this;
}

FGTweener* FGTweener::To(const FVector4& InStart, const FVector4& InEnd, float InDuration)
{
    ValueSize = 4;
    StartValue.SetVec4(InStart);
    EndValue.SetVec4(InEnd);
    Value.SetVec4(InStart);
    Duration = InDuration;
    return this;
}

FGTweener* FGTweener::To(const FColor& InStart, const FColor& InEnd, float InDuration)
{
    ValueSize = 4;
    StartValue.SetColor(InStart);
    EndValue.SetColor(InEnd);
    Value.SetColor(InStart);
    Duration = InDuration;
    return this;
}

FGTweener* FGTweener::To(double InStart, double InEnd, float InDuration)
{
    ValueSize = 5;
    StartValue.D = InStart;
    EndValue.D = InEnd;
    Value.D = InStart;
    Duration = InDuration;
    return this;
}

FGTweener* FGTweener::Shake(const FVector2D& InStart, float InAmplitude, float InDuration)
{
    ValueSize = 6;
    StartValue.SetVec2(InStart);
    StartValue.W = InAmplitude;
    Duration = InDuration;
    EaseType = EEaseType::Linear;
    return this;
}

void FGTweener::Init()
{
    Delay = 0;
    Duration = 0;
    Breakpoint = -1;
    EaseType = EEaseType::QuadOut;
    TimeScale = 1;
    EasePeriod = 0;
    EaseOvershootOrAmplitude = 1.70158f;
    bSnapping = false;
    Repeat = 0;
    bYoyo = false;
    ValueSize = 0;
    bStarted = false;
    bPaused = false;
    bKilled = false;
    ElapsedTime = 0;
    NormalizedTime = 0;
    Ended = 0;
    StartValue.Reset();
    EndValue.Reset();
    Value.Reset();
    DeltaValue.Reset();
}

void FGTweener::Reset()
{
    Target.Reset();
    UserData.Reset();
    Path.Reset();
    OnStartCallback.Unbind();
    OnUpdateCallback.Unbind();
    OnCompleteCallback.Unbind();
}

void FGTweener::Update(float DeltaTime)
{
    if (Ended != 0) //Maybe completed by seek
    {
        OnCompleteCallback.ExecuteIfBound(this);
        bKilled = true;
        return;
    }

    if (TimeScale != 1)
        DeltaTime *= TimeScale;
    if (DeltaTime == 0)
        return;

    ElapsedTime += DeltaTime;
    Update();

    if (Ended != 0)
    {
        if (!bKilled)
        {
            OnCompleteCallback.ExecuteIfBound(this);
            bKilled = true;
        }
    }
}

void FGTweener::Update()
{
    Ended = 0;

    if (ValueSize == 0) //DelayedCall
    {
        if (ElapsedTime >= Delay + Duration)
            Ended = 1;

        return;
    }

    if (!bStarted)
    {
        if (ElapsedTime < Delay)
            return;

        bStarted = true;
        OnStartCallback.ExecuteIfBound(this);
        if (bKilled)
            return;
    }

    bool reversed = false;
    float tt = ElapsedTime - Delay;
    if (Breakpoint >= 0 && tt >= Breakpoint)
    {
        tt = Breakpoint;
        Ended = 2;
    }

    if (Repeat != 0)
    {
        int32 round = FMath::FloorToInt(tt / Duration);
        tt -= Duration * round;
        if (bYoyo)
            reversed = round % 2 == 1;

        if (Repeat > 0 && Repeat - round < 0)
        {
            if (bYoyo)
                reversed = Repeat % 2 == 1;
            tt = Duration;
            Ended = 1;
        }
    }
    else if (tt >= Duration)
    {
        tt = Duration;
        Ended = 1;
    }

    NormalizedTime = EaseManager::Evaluate(EaseType, reversed ? (Duration - tt) : tt, Duration,
        EaseOvershootOrAmplitude, EasePeriod);

    Value.Reset();
    DeltaValue.Reset();

    if (ValueSize == 5)
    {
        double d = StartValue.D + (EndValue.D - StartValue.D) * NormalizedTime;
        if (bSnapping)
            d = round(d);
        DeltaValue.D = d - Value.D;
        Value.D = d;
        Value.X = (float)d;
    }
    else if (ValueSize == 6)
    {
        if (Ended == 0)
        {
            float r = StartValue.W * (1 - NormalizedTime);
            float rx = (FMath::RandRange(0, 1) * 2 - 1) * r;
            float ry = (FMath::RandRange(0, 1) * 2 - 1) * r;
            rx = rx > 0 ? FMath::CeilToFloat(rx) : FMath::FloorToFloat(rx);
            ry = ry > 0 ? FMath::CeilToFloat(ry) : FMath::FloorToFloat(ry);

            DeltaValue.X = rx;
            DeltaValue.Y = ry;
            Value.X = StartValue.X + rx;
            Value.Y = StartValue.Y + ry;
        }
        else
            Value.SetVec3(StartValue.GetVec3());
    }
    else if (Path.IsValid())
    {
        FVector vec3 = Path->GetPointAt(NormalizedTime);
        if (bSnapping)
        {
            vec3.X = FMath::RoundToFloat(vec3.X);
            vec3.Y = FMath::RoundToFloat(vec3.Y);
            vec3.Z = FMath::RoundToFloat(vec3.Z);
        }
        DeltaValue.SetVec3(vec3 - Value.GetVec3());
        Value.SetVec3(vec3);
    }
    else
    {
        for (int32 i = 0; i < ValueSize; i++)
        {
            float n1 = StartValue[i];
            float n2 = EndValue[i];
            float f = n1 + (n2 - n1) * NormalizedTime;
            if (bSnapping)
                f = FMath::RoundToFloat(f);
            DeltaValue[i] = f - Value[i];
            Value[i] = f;
        }
        Value.D = Value.X;
    }

    OnUpdateCallback.ExecuteIfBound(this);
}

================================================
FILE: Source/FairyGUI/Private/Tween/TweenManager.cpp
================================================
#include "Tween/TweenManager.h"
#include "Tween/GTweener.h"

FTweenManager FTweenManager::Singleton;

FTweenManager::FTweenManager()
{
    TotalActiveTweens = 0;
    ArrayLength = 30;
    ActiveTweens = new FGTweener*[ArrayLength];
}

FTweenManager::~FTweenManager()
{
    Reset();
    delete []ActiveTweens;
}

void FTweenManager::Reset()
{
    for (auto it : TweenerPool)
        delete it;
    TweenerPool.Reset();

    int32 cnt = TotalActiveTweens;
    for (int32 i = 0; i < cnt; i++)
    {
        FGTweener* tweener = ActiveTweens[i];
        if (tweener != nullptr)
            delete tweener;
    }
    TotalActiveTweens = 0;
}

FGTweener* FTweenManager::CreateTween()
{
    FGTweener* tweener;
    int32 cnt = TweenerPool.Num();
    if (cnt > 0)
    {
        tweener = TweenerPool.Pop();
        tweener->Handle.IncreaseSerialNumber();
    }
    else
    {
        TweenerInstanceCount++;
        if (!ensureMsgf(TweenerInstanceCount != FTweenerHandle::MaxIndex, TEXT("Tweener index number has wrapped around!")))
        {
            TweenerInstanceCount = 0;
        }
        tweener = new FGTweener();
        tweener->Handle.SetIndex(TweenerInstanceCount);
    }
    tweener->Init();
    ActiveTweens[TotalActiveTweens++] = tweener;

    if (TotalActiveTweens == ArrayLength)
    {
        int32 newLen = ArrayLength + FMath::CeilToInt(ArrayLength * 0.5f);
        FGTweener** newArray = new FGTweener*[newLen];
        FMemory::Memcpy(newArray, ActiveTweens, ArrayLength * sizeof(FGTweener*));
        delete []ActiveTweens;
        ActiveTweens = newArray;
        ArrayLength = newLen;
    }

    return tweener;
}

bool FTweenManager::KillTween(FTweenerHandle & Handle, bool bCompleted)
{
    int32 cnt = TotalActiveTweens;
    for (int32 i = 0; i < cnt; i++)
    {
        FGTweener* tweener = ActiveTweens[i];
        if (tweener != nullptr && tweener->Handle == Handle && !tweener->bKilled)
        {
            Handle.Invalidate();
            tweener->Kill(bCompleted);
            return true;
        }
    }

    Handle.Invalidate();
    return false;
}

bool FTweenManager::KillTweens(UObject* Target, bool bCompleted)
{
    if (Target == nullptr)
        return false;

    bool flag = false;
    int32 cnt = TotalActiveTweens;
    for (int32 i = 0; i < cnt; i++)
    {
        FGTweener* tweener = ActiveTweens[i];
        if (tweener != nullptr && tweener->Target.Get() == Target && !tweener->bKilled)
        {
            tweener->Kill(bCompleted);
            flag = true;
        }
    }

    return flag;
}

FGTweener* FTweenManager::GetTween(FTweenerHandle const& Handle)
{
    if (!Handle.IsValid())
        return nullptr;

    int32 cnt = TotalActiveTweens;
    for (int32 i = 0; i < cnt; i++)
    {
        FGTweener* tweener = ActiveTweens[i];
        if (tweener != nullptr && tweener->Handle == Handle && !tweener->bKilled)
        {
            return tweener;
        }
    }

    return nullptr;
}

FGTweener* FTweenManager::GetTween(UObject* Target)
{
    if (Target == nullptr)
        return nullptr;

    int32 cnt = TotalActiveTweens;
    for (int32 i = 0; i < cnt; i++)
    {
        FGTweener* tweener = ActiveTweens[i];
        if (tweener != nullptr && tweener->Target.Get() == Target && !tweener->bKilled)
        {
            return tweener;
        }
    }

    return nullptr;
}

void FTweenManager::Tick(float DeltaTime)
{
    int32 cnt = TotalActiveTweens;
    int32 freePosStart = -1;
    for (int32 i = 0; i < cnt; i++)
    {
        FGTweener* tweener = ActiveTweens[i];
        if (tweener == nullptr)
        {
            if (freePosStart == -1)
                freePosStart = i;
        }
        else if (tweener->bKilled)
        {
            tweener->Reset();
            TweenerPool.Add(tweener);
            ActiveTweens[i] = nullptr;

            if (freePosStart == -1)
                freePosStart = i;
        }
        else
        {
            if (tweener->Target.IsStale())
                tweener->bKilled = true;
            else if (!tweener->bPaused)
                tweener->Update(DeltaTime);

            if (freePosStart != -1)
            {
                ActiveTweens[freePosStart] = tweener;
                ActiveTweens[i] = nullptr;
                freePosStart++;
            }
        }
    }

    if (freePosStart >= 0)
    {
        if (TotalActiveTweens != cnt) //new tweens added
        {
            int32 j = cnt;
            cnt = TotalActiveTweens - cnt;
            for (int32 i = 0; i < cnt; i++)
                ActiveTweens[freePosStart++] = ActiveTweens[j++];
        }
        TotalActiveTweens = freePosStart;
    }
}

================================================
FILE: Source/FairyGUI/Private/Tween/TweenValue.cpp
================================================
#include "Tween/TweenValue.h"

FTweenValue::FTweenValue() :X(0), Y(0), Z(0), W(0), D(0)
{
}

FVector2D FTweenValue::GetVec2() const
{
    return FVector2D(X, Y);
}

void FTweenValue::SetVec2(const FVector2D & Value)
{
    X = Value.X;
    Y = Value.Y;
}

FVector FTweenValue::GetVec3() const
{
    return FVector(X, Y, Z);
}

void FTweenValue::SetVec3(const FVector & Value)
{
    X = Value.X;
    Y = Value.Y;
    Z = Value.Z;
}

FVector4 FTweenValue::GetVec4() const
{
    return FVector4(X, Y, Z, W);
}

void FTweenValue::SetVec4(const FVector4 & Value)
{
    X = Value.X;
    Y = Value.Y;
    Z = Value.Z;
    W = Value.W;
}

FColor FTweenValue::GetColor() const
{
    return FColor(X * 255, Y * 255, Z * 255, W * 255);
}

void FTweenValue::SetColor(const FColor & Value)
{
    X = Value.R / 255.f;
    Y = Value.G / 255.f;
    Z = Value.B / 255.f;
    W = Value.A / 255.f;
}

float FTweenValue::operator[](int32 Index) const
{
    verifyf(Index < 4, TEXT("Index out of bounds: %d"), Index);

    switch (Index)
    {
    case 0:
        return X;
    case 1:
        return Y;
    case 2:
        return Z;
    case 3:
        return W;
    default:
        return X;
    }
}

float& FTweenValue::operator[](int32 Index)
{
    verifyf(Index < 4, TEXT("Index out of bounds: %d"), Index);

    switch (Index)
    {
    case 0:
        return X;
    case 1:
        return Y;
    case 2:
        return Z;
    case 3:
        return W;
    default:
        return X;
    }
}

void FTweenValue::Reset()
{
    X = Y = Z = W = 0;
    D = 0;
}

================================================
FILE: Source/FairyGUI/Private/UI/ControllerAction/ChangePageAction.cpp
================================================
#include "UI/ControllerAction/ChangePageAction.h"
#include "UI/GController.h"
#include "Utils/ByteBuffer.h"
#include "UI/GComponent.h"

void FChangePageAction::Setup(FByteBuffer* Buffer)
{
    FControllerAction::Setup(Buffer);

    ObjectID = Buffer->ReadS();
    ControllerName = Buffer->ReadS();
    TargetPage = Buffer->ReadS();
}

void FChangePageAction::Enter(UGController* Controller)
{
    if (ControllerName.IsEmpty())
        return;

    UGComponent* gcom;
    if (!ObjectID.IsEmpty())
        gcom = Cast<UGComponent>(Cast<UGComponent>(Controller->GetOuter())->GetChildByID(ObjectID));
    else
        gcom = Cast<UGComponent>(Controller->GetOuter());
    if (gcom != nullptr)
    {
        UGController* cc = gcom->GetController(ControllerName);
        if (cc != nullptr && cc != Controller && !cc->bChanging)
        {
            if (TargetPage.Compare("~1") == 0)
            {
                if (Controller->GetSelectedIndex() < cc->GetPageCount())
                    cc->SetSelectedIndex(Controller->GetSelectedIndex());
            }
            else if (TargetPage.Compare("~2") == 0)
                cc->SetSelectedPage(Controller->GetSelectedPage());
            else
                cc->SetSelectedPageID(TargetPage);
        }
    }
}

void FChangePageAction::Leave(UGController* Controller)
{
}

================================================
FILE: Source/FairyGUI/Private/UI/ControllerAction/ControllerAction.cpp
================================================
#include "UI/ControllerAction/ControllerAction.h"
#include "UI/ControllerAction/ChangePageAction.h"
#include "UI/ControllerAction/PlayTransitionAction.h"
#include "Utils/ByteBuffer.h"

FControllerAction * FControllerAction::CreateAction(int32 ActionType)
{
    switch (ActionType)
    {
    case 0:
        return new FPlayTransitionAction();

    case 1:
        return new FChangePageAction();
    }
    return nullptr;
}

FControllerAction::FControllerAction()
{
}

FControllerAction::~FControllerAction()
{
}

void FControllerAction::Run(UGController* Controller, const FString& PreviousPage, const FString& CurrentPage)
{
    if ((FromPage.Num() == 0 || FromPage.Contains(PreviousPage))
        && (ToPage.Num() == 0 || ToPage.Contains(CurrentPage)))
        Enter(Controller);
    else
        Leave(Controller);
}

void FControllerAction::Setup(FByteBuffer * Buffer)
{
    int32 cnt;

    cnt = Buffer->ReadShort();
    FromPage.SetNum(cnt);
    for (int32 i = 0; i < cnt; i++)
        FromPage[i] = Buffer->ReadS();

    cnt = Buffer->ReadShort();
    ToPage.SetNum(cnt);
    for (int32 i = 0; i < cnt; i++)
        ToPage[i] = Buffer->ReadS();
}


================================================
FILE: Source/FairyGUI/Private/UI/ControllerAction/PlayTransitionAction.cpp
================================================
#include "UI/ControllerAction/PlayTransitionAction.h"
#include "UI/GController.h"
#include "UI/Transition.h"
#include "UI/GComponent.h"
#include "Utils/ByteBuffer.h"

FPlayTransitionAction::FPlayTransitionAction() :
    PlayTimes(1),
    Delay(0),
    bStopOnExit(false),
    CurrentTransition(nullptr)
{
}

void FPlayTransitionAction::Setup(FByteBuffer* Buffer)
{
    FControllerAction::Setup(Buffer);

    TransitionName = Buffer->ReadS();
    PlayTimes = Buffer->ReadInt();
    Delay = Buffer->ReadFloat();
    bStopOnExit = Buffer->ReadBool();
}

void FPlayTransitionAction::Enter(UGController* Controller)
{
    UTransition* trans = Cast<UGComponent>(Controller->GetOuter())->GetTransition(TransitionName);
    if (trans != nullptr)
    {
        if (CurrentTransition != nullptr && CurrentTransition->IsPlaying())
            trans->ChangePlayTimes(PlayTimes);
        else
            trans->Play(PlayTimes, Delay);
        CurrentTransition = trans;
    }
}

void FPlayTransitionAction::Leave(UGController* Controller)
{
    if (bStopOnExit && CurrentTransition != nullptr)
    {
        CurrentTransition->Stop();
        CurrentTransition = nullptr;
    }
}

================================================
FILE: Source/FairyGUI/Private/UI/DragDropManager.cpp
================================================
#include "UI/DragDropManager.h"
#include "UI/UIObjectFactory.h"
#include "UI/GRoot.h"
#include "FairyApplication.h"

UDragDropManager::UDragDropManager()
{
}

UDragDropManager::~UDragDropManager()
{
}

void UDragDropManager::CreateAgent()
{
    Agent = (UGLoader*)FUIObjectFactory::NewObject(EObjectType::Loader, this);
    Agent->Name = TEXT("DragDropAgent");
    Agent->SetTouchable(false);
    Agent->SetDraggable(true);
    Agent->SetSize(FVector2D(100, 100));
    Agent->SetPivot(FVector2D(.5f, .5f), true);
    Agent->SetAlign(EAlignType::Center);
    Agent->SetVerticalAlign(EVerticalAlignType::Middle);
    Agent->SetSortingOrder(INT_MAX);
    Agent->On(FUIEvents::DragEnd).AddUObject(this, &UDragDropManager::OnDragEnd);
}

void UDragDropManager::StartDrag(const FString& InIcon, const FNVariant& InUserData, int32 InUserIndex, int32 InPointerIndex)
{
    if (Agent->GetParent() != nullptr)
        return;

    UserData = InUserData;
    Agent->SetURL(InIcon);
    Agent->SetParentToRoot();
    FVector2D pt = Agent->GetUIRoot()->GlobalToLocal(Agent->GetApp()->GetTouchPosition(InUserIndex, InPointerIndex));
    Agent->SetPosition(pt);
    Agent->GetApp()->CallAfterSlateTick(FSimpleDelegate::CreateUObject(this, &UDragDropManager::DelayStartDrag, InUserIndex, InPointerIndex));
}

void UDragDropManager::DelayStartDrag(int32 InUserIndex, int32 InPointerIndex)
{
    if (Agent->GetParent() != nullptr)
        Agent->StartDrag(InUserIndex, InPointerIndex);
}

void UDragDropManager::Cancel()
{
    if (Agent->GetParent() != nullptr)
    {
        Agent->StopDrag();
        Agent->RemoveFromParent();
        UserData.Reset();
    }
}

void UDragDropManager::OnDragEnd(UEventContext* Context)
{
    if (Agent->GetParent() == nullptr) //canceled
        return;

    Agent->RemoveFromParent();

    UGObject* obj = Agent->GetApp()->GetObjectUnderPoint(Context->GetPointerPosition());
    while (obj != nullptr)
    {
        if (obj->IsA<UGComponent>())
        {
            if (obj->HasEventListener(FUIEvents::Drop))
            {
                obj->DispatchEvent(FUIEvents::Drop, UserData);
                return;
            }
        }

        obj = obj->GetParent();
    }
}

================================================
FILE: Source/FairyGUI/Private/UI/GButton.cpp
================================================
#include "UI/GButton.h"
#include "UI/GTextField.h"
#include "UI/GLabel.h"
#include "UI/GController.h"
#include "Utils/ByteBuffer.h"
#include "FairyApplication.h"

const FString UGButton::UP = "up";
const FString UGButton::DOWN = "down";
const FString UGButton::OVER = "over";
const FString UGButton::SELECTED_OVER = "selectedOver";
const FString UGButton::DISABLED = "disabled";
const FString UGButton::SELECTED_DISABLED = "selectedDisabled";

UGButton::UGButton() :
    bChangeStateOnClick(true),
    DownEffectValue(0.8f)
{
    Sound = FUIConfig::Config.ButtonSound;
    SoundVolumeScale = FUIConfig::Config.ButtonSoundVolumeScale;
}

UGButton::~UGButton()
{
}

void UGButton::SetText(const FString& InText)
{
    Title = InText;
    if (TitleObject != nullptr)
        TitleObject->SetText(InText);
    UpdateGear(6);
}

const FString& UGButton::GetIcon() const
{
    if (IconObject != nullptr)
        return IconObject->GetIcon();
    else
        return G_EMPTY_STRING;
}

void UGButton::SetIcon(const FString & InIcon)
{
    if (IconObject != nullptr)
        IconObject->SetIcon(InIcon);
    UpdateGear(7);
}

void UGButton::SetSelectedTitle(const FString& InTitle)
{
    SelectedTitle = InTitle;
    if (TitleObject != nullptr)
        TitleObject->SetText((bSelected && SelectedTitle.Len() > 0) ? SelectedTitle : Title);
}

void UGButton::SetSelectedIcon(const FString& InIcon)
{
    SelectedIcon = InIcon;
    if (IconObject != nullptr)
        IconObject->SetIcon((bSelected && SelectedIcon.Len() > 0) ? SelectedIcon : Icon);
}

FColor UGButton::GetTitleColor() const
{
    UGTextField* TextField = GetTextField();
    if (TextField)
        return TextField->GetTextFormat().Color;
    else
        return FColor::Black;
}

void UGButton::SetTitleColor(const FColor & InColor)
{
    UGTextField* TextField = GetTextField();
    if (TextField)
    {
        TextField->GetTextFormat().Color = InColor;
        TextField->ApplyFormat();
    }
}

int32 UGButton::GetTitleFontSize() const
{
    UGTextField* TextField = GetTextField();
    if (TextField)
        return TextField->GetTextFormat().Size;
    else
        return 0;
}

void UGButton::SetTitleFontSize(int32 InFontSize)
{
    UGTextField* TextField = GetTextField();
    if (TextField)
    {
        TextField->GetTextFormat().Size = InFontSize;
        TextField->ApplyFormat();
    }
}

void UGButton::SetSelected(bool bInSelected)
{
    if (Mode == EButtonMode::Common)
        return;

    if (bSelected != bInSelected)
    {
        bSelected = bInSelected;
        SetCurrentState();
        if (!SelectedTitle.IsEmpty() && TitleObject != nullptr)
            TitleObject->SetText(bSelected ? SelectedTitle : Title);
        if (!SelectedIcon.IsEmpty())
        {
            const FString& str = bSelected ? SelectedIcon : Icon;
            if (IconObject != nullptr)
                IconObject->SetIcon(str);
        }
        if (RelatedController != nullptr && GetParent() != nullptr && !GetParent()->bBuildingDisplayList)
        {
            if (bSelected)
            {
                RelatedController->SetSelectedPageID(RelatedPageID);
                if (RelatedController->bAutoRadioGroupDepth)
                    GetParent()->AdjustRadioGroupDepth(this, RelatedController);
            }
            else if (Mode == EButtonMode::Check && RelatedController->GetSelectedPageID() == RelatedPageID)
                RelatedController->SetOppositePageID(RelatedPageID);
        }
    }
}

void UGButton::SetRelatedController(UGController* InController)
{
    RelatedController = InController;
}

void UGButton::SetState(const FString& InState)
{
    if (ButtonController != nullptr)
        ButtonController->SetSelectedPage(InState);

    if (DownEffect == 1)
    {
        int32 cnt = this->NumChildren();
        if (InState == DOWN || InState == SELECTED_OVER || InState == SELECTED_DISABLED)
        {
            int32 c = DownEffectValue * 255;
            FNVariant Color(FColor(c, c, c, 255));
            for (int32 i = 0; i < cnt; i++)
            {
                UGObject* Obj = this->GetChildAt(i);
                if (!Obj->IsA<UGTextField>())
                    Obj->SetProp(EObjectPropID::Color, Color);
            }
        }
        else
        {
            FNVariant Color(FColor::White);
            for (int32 i = 0; i < cnt; i++)
            {
                UGObject* Obj = this->GetChildAt(i);
                if (!Obj->IsA<UGTextField>())
                    Obj->SetProp(EObjectPropID::Color, Color);
            }
        }
    }
    else if (DownEffect == 2)
    {
        if (InState == DOWN || InState == SELECTED_OVER || InState == SELECTED_DISABLED)
        {
            if (!bDownScaled)
            {
                bDownScaled = true;
                SetScale(GetScale() * DownEffectValue);
            }
        }
        else
        {
            if (bDownScaled)
            {
                bDownScaled = false;
                SetScale(GetScale() / DownEffectValue);
            }
        }
    }
}

void UGButton::SetCurrentState()
{
    if (IsGrayed() && ButtonController != nullptr && ButtonController->HasPage(DISABLED))
    {
        if (bSelected)
            SetState(SELECTED_DISABLED);
        else
            SetState(DISABLED);
    }
    else
    {
        if (bSelected)
            SetState(bOver ? SELECTED_OVER : DOWN);
        else
            SetState(bOver ? OVER : UP);
    }
}

UGTextField * UGButton::GetTextField() const
{
    if (TitleObject->IsA<UGTextField>())
        return Cast<UGTextField>(TitleObject);
    else if (TitleObject->IsA<UGLabel>())
        return Cast<UGLabel>(TitleObject)->GetTextField();
    else if (TitleObject->IsA<UGButton>())
        return Cast<UGButton>(TitleObject)->GetTextField();
    else
        return nullptr;
}

FNVariant UGButton::GetProp(EObjectPropID PropID) const
{
    switch (PropID)
    {
    case EObjectPropID::Color:
        return FNVariant(GetTitleColor());
    case EObjectPropID::OutlineColor:
    {
        UGTextField* TextField = GetTextField();
        if (TextField != nullptr)
            return FNVariant(TextField->GetTextFormat().OutlineColor);
        else
            return FNVariant(FColor::Black);
    }
    case EObjectPropID::FontSize:
        return FNVariant(GetTitleFontSize());
    case EObjectPropID::Selected:
        return FNVariant(IsSelected());
    default:
        return UGComponent::GetProp(PropID);
    }
}

void UGButton::SetProp(EObjectPropID PropID, const FNVariant& InValue)
{
    switch (PropID)
    {
    case EObjectPropID::Color:
        SetTitleColor(InValue.AsColor());
        break;
    case EObjectPropID::OutlineColor:
    {
        UGTextField* TextField = GetTextField();
        if (TextField != nullptr)
        {
            TextField->GetTextFormat().OutlineColor = InValue.AsColor();
            TextField->ApplyFormat();
        }
        break;
    }
    case EObjectPropID::FontSize:
        SetTitleFontSize(InValue.AsInt());
        break;
    case EObjectPropID::Selected:
        SetSelected(InValue.AsBool());
        break;
    default:
        UGComponent::SetProp(PropID, InValue);
        break;
    }
}

void UGButton::ConstructExtension(FByteBuffer* Buffer)
{
    Buffer->Seek(0, 6);

    Mode = (EButtonMode)Buffer->ReadByte();
    Buffer->ReadS(Sound);
    SoundVolumeScale = Buffer->ReadFloat();
    DownEffect = Buffer->ReadByte();
    DownEffectValue = Buffer->ReadFloat();
    if (DownEffect == 2)
        SetPivot(FVector2D(0.5f, 0.5f), IsPivotAsAnchor());

    ButtonController = GetController("button");
    TitleObject = GetChild("title");
    IconObject = GetChild("icon");
    if (TitleObject != nullptr)
        Title = TitleObject->GetText();
    if (IconObject != nullptr)
        Icon = IconObject->GetIcon();

    if (Mode == EButtonMode::Common)
        SetState(UP);

    On(FUIEvents::RollOver).AddUObject(this, &UGButton::OnRollOverHandler);
    On(FUIEvents::RollOut).AddUObject(this, &UGButton::OnRollOutHandler);
    On(FUIEvents::TouchBegin).AddUObject(this, &UGButton::OnTouchBeginHandler);
    On(FUIEvents::TouchEnd).AddUObject(this, &UGButton::OnTouchEndHandler);
    On(FUIEvents::Click).AddUObject(this, &UGButton::OnClickHandler);
    On(FUIEvents::RemovedFromStage).AddUObject(this, &UGButton::OnRemovedFromStageHandler);
}

void UGButton::SetupAfterAdd(FByteBuffer* Buffer, int32 BeginPos)
{
    UGComponent::SetupAfterAdd(Buffer, BeginPos);

    if (!Buffer->Seek(BeginPos, 6))
        return;

    if ((EObjectType)Buffer->ReadByte() != PackageItem->ObjectType)
        return;

    const FString* str;

    if ((str = Buffer->ReadSP()) != nullptr)
        SetTitle(*str);
    if ((str = Buffer->ReadSP()) != nullptr)
        SetSelectedTitle(*str);
    if ((str = Buffer->ReadSP()) != nullptr)
        SetIcon(*str);
    if ((str = Buffer->ReadSP()) != nullptr)
        SetSelectedIcon(*str);
    if (Buffer->ReadBool())
        SetTitleColor(Buffer->ReadColor());
    int32 iv = Buffer->ReadInt();
    if (iv != 0)
        SetTitleFontSize(iv);
    iv = Buffer->ReadShort();
    if (iv >= 0)
        RelatedController = GetParent()->GetControllerAt(iv);
    RelatedPageID = Buffer->ReadS();

    Buffer->ReadS(Sound);
    if (Buffer->ReadBool())
        SoundVolumeScale = Buffer->ReadFloat();

    SetSelected(Buffer->ReadBool());
}

void UGButton::HandleControllerChanged(UGController* Controller)
{
    UGObject::HandleControllerChanged(Controller);

    if (RelatedController == Controller)
        SetSelected(RelatedPageID == Controller->GetSelectedPageID());
}

void UGButton::OnRollOverHandler(UEventContext* Context)
{
    if (ButtonController == nullptr || !ButtonController->HasPage(OVER))
        return;

    bOver = true;
    if (bDown)
        return;

    if (IsGrayed() && ButtonController->HasPage(DISABLED))
        return;

    SetState(bSelected ? SELECTED_OVER : OVER);
}

void UGButton::OnRollOutHandler(UEventContext* Context)
{
    if (ButtonController == nullptr || !ButtonController->HasPage(OVER))
        return;

    bOver = false;
    if (bDown)
        return;

    if (IsGrayed() && ButtonController->HasPage(DISABLED))
        return;

    SetState(bSelected ? DOWN : UP);
}

void UGButton::OnTouchBeginHandler(UEventContext* Context)
{
    if (Context->GetMouseButton() != EKeys::LeftMouseButton)
        return;

    bDown = true;
    Context->CaptureTouch();

    if (Mode == EButtonMode::Common)
    {
        if (IsGrayed() && ButtonController != nullptr && ButtonController->HasPage(DISABLED))
            SetState(SELECTED_DISABLED);
        else
            SetState(DOWN);
    }
}

void UGButton::OnTouchEndHandler(UEventContext* Context)
{
    if (Context->GetMouseButton() != EKeys::LeftMouseButton)
        return;

    if (bDown)
    {
        bDown = false;
        if (Mode == EButtonMode::Common)
        {
            if (IsGrayed() && ButtonController != nullptr && ButtonController->HasPage(DISABLED))
                SetState(DISABLED);
            else if (bOver)
                SetState(OVER);
            else
                SetState(UP);
        }
        else
        {
            if (!bOver && ButtonController != nullptr && (ButtonController->GetSelectedPage() == OVER || ButtonController->GetSelectedPage() == SELECTED_OVER))
            {
                SetCurrentState();
            }
        }
    }
}

void UGButton::OnClickHandler(UEventContext* Context)
{
    if (!Sound.IsEmpty())
        GetApp()->PlaySound(Sound, SoundVolumeScale);

    if (Mode == EButtonMode::Check)
    {
        if (bChangeStateOnClick)
        {
            SetSelected(!bSelected);
            DispatchEvent(FUIEvents::Changed);
        }
    }
    else if (Mode == EButtonMode::Radio)
    {
        if (bChangeStateOnClick && !bSelected)
        {
            SetSelected(true);
            DispatchEvent(FUIEvents::Changed);
        }
    }
    else
    {
        if (RelatedController != nullptr)
            RelatedController->SetSelectedPageID(RelatedPageID);
    }
}

void UGButton::OnRemovedFromStageHandler(UEventContext* Context)
{
    if (bOver)
        OnRollOutHandler(Context);
}


================================================
FILE: Source/FairyGUI/Private/UI/GComboBox.cpp
================================================
#include "UI/GComboBox.h"
#include "UI/UIPackage.h"
#include "UI/GTextField.h"
#include "UI/GTextInput.h"
#include "UI/GLabel.h"
#include "UI/GButton.h"
#include "UI/GController.h"
#include "UI/GList.h"
#include "UI/GRoot.h"
#include "Utils/ByteBuffer.h"

UGComboBox::UGComboBox() :
    bItemsUpdated(true),
    SelectedIndex(-1)
{
    VisibleItemCount = FUIConfig::Config.DefaultComboBoxVisibleItemCount;
}

UGComboBox::~UGComboBox()
{
}

const FString& UGComboBox::GetText() const
{
    if (TitleObject != nullptr)
        return TitleObject->GetText();
    else
        return G_EMPTY_STRING;
}

void UGComboBox::SetText(const FString& InText)
{
    if (TitleObject != nullptr)
        TitleObject->SetText(InText);
    UpdateGear(6);
}

const FString& UGComboBox::GetIcon() const
{
    if (IconObject != nullptr)
        return IconObject->GetIcon();
    else
        return G_EMPTY_STRING;
}

void UGComboBox::SetIcon(const FString & InIcon)
{
    if (IconObject != nullptr)
        IconObject->SetIcon(InIcon);
    UpdateGear(7);
}

FColor UGComboBox::GetTitleColor() const
{
    UGTextField* TextField = GetTextField();
    if (TextField)
        return TextField->GetTextFormat().Color;
    else
        return FColor::Black;
}

void UGComboBox::SetTitleColor(const FColor & InColor)
{
    UGTextField* TextField = GetTextField();
    if (TextField)
    {
        TextField->GetTextFormat().Color = InColor;
        TextField->ApplyFormat();
    }
}

int32 UGComboBox::GetTitleFontSize() const
{
    UGTextField* TextField = GetTextField();
    if (TextField)
        return TextField->GetTextFormat().Size;
    else
        return 0;
}

void UGComboBox::SetTitleFontSize(int32 InFontSize)
{
    UGTextField* TextField = GetTextField();
    if (TextField)
    {
        TextField->GetTextFormat().Size = InFontSize;
        TextField->ApplyFormat();
    }
}

const FString& UGComboBox::GetValue() const
{
    if (SelectedIndex >= 0 && SelectedIndex < Values.Num())
        return Values[SelectedIndex];
    else
        return G_EMPTY_STRING;
}

void UGComboBox::SetValue(const FString& InValue)
{
    SetSelectedIndex(Values.Find(InValue));
}

void UGComboBox::SetSelectedIndex(int32 InIndex)
{
    if (SelectedIndex == InIndex)
        return;

    SelectedIndex = InIndex;
    if (SelectedIndex >= 0 && SelectedIndex < Items.Num())
    {
        SetText(Items[SelectedIndex]);
        if (Icons.Num() > 0 && SelectedIndex != -1 && SelectedIndex < Icons.Num())
            SetIcon(Icons[SelectedIndex]);
    }
    else
    {
        SetTitle(G_EMPTY_STRING);
        if (Icons.Num() > 0)
            SetIcon(G_EMPTY_STRING);
    }

    UpdateSelectionController();
}

void UGComboBox::Refresh()
{
    if (Items.Num() > 0)
    {
        if (SelectedIndex >= Items.Num())
            SelectedIndex = Items.Num() - 1;
        else if (SelectedIndex == -1)
            SelectedIndex = 0;
        SetTitle(Items[SelectedIndex]);
    }
    else
    {
        SetTitle(G_EMPTY_STRING);
        SelectedIndex = -1;
    }

    if (Icons.Num() > 0)
    {
        if (SelectedIndex != -1 && SelectedIndex < Icons.Num())
            SetIcon(Icons[SelectedIndex]);
        else
            SetIcon(G_EMPTY_STRING);
    }

    bItemsUpdated = true;
}

void UGComboBox::SetState(const FString& InState)
{
    if (ButtonController != nullptr)
        ButtonController->SetSelectedPage(InState);
}

void UGComboBox::SetCurrentState()
{
    if (IsGrayed() && ButtonController != nullptr && ButtonController->HasPage(UGButton::DISABLED))
        SetState(UGButton::DISABLED);
    else if (DropdownObject != nullptr && DropdownObject->GetParent() != nullptr)
        SetState(UGButton::DOWN);
    else
        SetState(bOver ? UGButton::OVER : UGButton::UP);
}

void UGComboBox::UpdateSelectionController()
{
    if (SelectionController != nullptr && !SelectionController->bChanging && SelectedIndex < SelectionController->GetPageCount())
    {
        UGController* c = SelectionController;
        SelectionController = nullptr;
        c->SetSelectedIndex(SelectedIndex);
        SelectionController = c;
    }
}

void UGComboBox::UpdateDropdownList()
{
    if (bItemsUpdated)
    {
        bItemsUpdated = false;
        RenderDropdownList();
        ListObject->ResizeToFit(VisibleItemCount);
    }
}

void UGComboBox::ShowDropdown()
{
    UpdateDropdownList();
    if (ListObject->GetSelectionMode() == EListSelectionMode::Single)
        ListObject->SetSelectedIndex(-1);
    DropdownObject->SetWidth(Size.X);
    ListObject->EnsureBoundsCorrect();

    GetUIRoot()->TogglePopup(DropdownObject, this, PopupDirection);
    if (DropdownObject->GetParent() != nullptr)
        SetState(UGButton::DOWN);
}

void UGComboBox::RenderDropdownList()
{
    ListObject->RemoveChildrenToPool();
    int32 cnt = Items.Num();
    for (int32 i = 0; i < cnt; i++)
    {
        UGObject* Obj = ListObject->AddItemFromPool();
        Obj->SetText(Items[i]);
        Obj->SetIcon((Icons.Num() > 0 && i < Icons.Num()) ? Icons[i] : G_EMPTY_STRING);
        Obj->Name = i < Values.Num() ? Values[i] : G_EMPTY_STRING;
    }
}

void UGComboBox::HandleControllerChanged(UGController* Controller)
{
    UGComponent::HandleControllerChanged(Controller);

    if (SelectionController == Controller)
        SetSelectedIndex(Controller->GetSelectedIndex());
}

void UGComboBox::HandleGrayedChanged()
{
    if (ButtonController != nullptr && ButtonController->HasPage(UGButton::DISABLED))
    {
        if (IsGrayed())
            SetState(UGButton::DISABLED);
        else
            SetState(UGButton::UP);
    }
    else
        UGComponent::HandleGrayedChanged();
}

UGTextField* UGComboBox::GetTextField() const
{
    if (TitleObject->IsA<UGTextField>())
        return Cast<UGTextField>(TitleObject);
    else if (TitleObject->IsA<UGLabel>())
        return Cast<UGLabel>(TitleObject)->GetTextField();
    else if (TitleObject->IsA<UGButton>())
        return Cast<UGButton>(TitleObject)->GetTextField();
    else
        return nullptr;
}

FNVariant UGComboBox::GetProp(EObjectPropID PropID) const
{
    switch (PropID)
    {
    case EObjectPropID::Color:
        return FNVariant(GetTitleColor());
    case EObjectPropID::OutlineColor:
    {
        UGTextField* TextField = GetTextField();
        if (TextField != nullptr)
            return FNVariant(TextField->GetTextFormat().OutlineColor);
        else
            return FNVariant(FColor::Black);
    }
    case EObjectPropID::FontSize:
        return FNVariant(GetTitleFontSize());
    default:
        return UGComponent::GetProp(PropID);
    }
}

void UGComboBox::SetProp(EObjectPropID PropID, const FNVariant& InValue)
{
    switch (PropID)
    {
    case EObjectPropID::Color:
        SetTitleColor(InValue.AsColor());
        break;
    case EObjectPropID::OutlineColor:
    {
        UGTextField* TextField = GetTextField();
        if (TextField != nullptr)
        {
            TextField->GetTextFormat().OutlineColor = InValue.AsColor();
            TextField->ApplyFormat();
        }
        break;
    }
    case EObjectPropID::FontSize:
        SetTitleFontSize(InValue.AsInt());
        break;
    default:
        UGComponent::SetProp(PropID, InValue);
        break;
    }
}

void UGComboBox::ConstructExtension(FByteBuffer* Buffer)
{
    Buffer->Seek(0, 6);

    ButtonController = GetController("button");
    TitleObject = GetChild("title");
    IconObject = GetChild("icon");

    const FString& dropdownResource = Buffer->ReadS();
    if (!dropdownResource.IsEmpty())
    {
        DropdownObject = Cast<UGComponent>(UUIPackage::CreateObjectFromURL(dropdownResource, this));
        verifyf(DropdownObject != nullptr, TEXT("should be a component."));

        ListObject = Cast<UGList>(DropdownObject->GetChild("list"));
        verifyf(ListObject != nullptr, TEXT("should container a list component named list."));

        ListObject->On(FUIEvents::ClickItem).AddUObject(this, &UGComboBox::OnClickItem);

        ListObject->AddRelation(DropdownObject, ERelationType::Width);
        ListObject->RemoveRelation(DropdownObject, ERelationType::Height);

        DropdownObject->AddRelation(ListObject, ERelationType::Height);
        DropdownObject->RemoveRelation(ListObject, ERelationType::Width);

        DropdownObject->On(FUIEvents::RemovedFromStage).AddUObject(this, &UGComboBox::OnPopupWinClosed);
    }

    On(FUIEvents::RollOver).AddUObject(this, &UGComboBox::OnRollOverHandler);
    On(FUIEvents::RollOut).AddUObject(this, &UGComboBox::OnRollOutHandler);
    On(FUIEvents::TouchBegin).AddUObject(this, &UGComboBox::OnTouchBeginHandler);
    On(FUIEvents::TouchEnd).AddUObject(this, &UGComboBox::OnTouchEndHandler);
}

void UGComboBox::SetupAfterAdd(FByteBuffer* Buffer, int32 BeginPos)
{
    UGComponent::SetupAfterAdd(Buffer, BeginPos);

    if (!Buffer->Seek(BeginPos, 6))
        return;

    if ((EObjectType)Buffer->ReadByte() != PackageItem->ObjectType)
        return;

    const FString* str;
    bool hasIcon = false;
    int32 itemCount = Buffer->ReadShort();
    for (int32 i = 0; i < itemCount; i++)
    {
        int32 nextPos = Buffer->ReadShort();
        nextPos += Buffer->GetPos();

        Items.Add(Buffer->ReadS());
        Values.Add(Buffer->ReadS());
        if ((str = Buffer->ReadSP()) != nullptr)
        {
            if (!hasIcon)
            {
                for (int32 j = 0; j < Items.Num() - 1; j++)
                    Icons.Add(G_EMPTY_STRING);
            }
            Icons.Add(*str);
        }

        Buffer->SetPos(nextPos);
    }

    if ((str = Buffer->ReadSP()) != nullptr)
    {
        SetTitle(*str);
        SelectedIndex = Items.Find(*str);
    }
    else if (Items.Num() > 0)
    {
        SelectedIndex = 0;
        SetTitle(Items[0]);
    }
    else
        SelectedIndex = -1;

    if ((str = Buffer->ReadSP()) != nullptr)
        SetIcon(*str);

    if (Buffer->ReadBool())
        SetTitleColor(Buffer->ReadColor());
    int32 iv = Buffer->ReadInt();
    if (iv > 0)
        VisibleItemCount = iv;
    PopupDirection = (EPopupDirection)Buffer->ReadByte();

    iv = Buffer->ReadShort();
    if (iv >= 0)
        SelectionController = GetParent()->GetControllerAt(iv);
}

void UGComboBox::OnClickItem(UEventContext* Context)
{
    if (DropdownObject->GetParent()->IsA<UGRoot>())
        ((UGRoot*)DropdownObject->GetParent())->HidePopup(DropdownObject);
    SelectedIndex = INT_MIN;
    SetSelectedIndex(ListObject->GetChildIndex(Cast<UGObject>(Context->GetData().AsUObject())));

    DispatchEvent(FUIEvents::Changed);
}

void UGComboBox::OnRollOverHandler(UEventContext* Context)
{
    bOver = true;
    if (bDown || (DropdownObject != nullptr && DropdownObject->GetParent() != nullptr))
        return;

    SetCurrentState();
}

void UGComboBox::OnRollOutHandler(UEventContext* Context)
{
    bOver = false;
    if (bDown || (DropdownObject != nullptr && DropdownObject->GetParent() != nullptr))
        return;

    SetCurrentState();
}

void UGComboBox::OnTouchBeginHandler(UEventContext* Context)
{
    if (Context->GetMouseButton() != EKeys::LeftMouseButton)
        return;

    if (Context->GetInitiator()->IsA<UGTextInput>())
        return;

    bDown = true;

    if (DropdownObject != nullptr)
        ShowDropdown();

    Context->CaptureTouch();
}

void UGComboBox::OnTouchEndHandler(UEventContext* Context)
{
    if (Context->GetMouseButton() != EKeys::LeftMouseButton)
        return;

    if (bDown)
    {
        bDown = false;
        if (DropdownObject != nullptr && DropdownObject->GetParent() != nullptr)
            SetCurrentState();
    }
}

void UGComboBox::OnPopupWinClosed(UEventContext* Context)
{
    SetCurrentState();
}


================================================
FILE: Source/FairyGUI/Private/UI/GComponent.cpp
================================================
#include "UI/GComponent.h"
#include "UI/GButton.h"
#include "UI/GGroup.h"
#include "UI/Relations.h"
#include "UI/TranslationHelper.h"
#include "UI/UIObjectFactory.h"
#include "UI/UIPackage.h"
#include "UI/GController.h"
#include "UI/Transition.h"
#include "UI/GRoot.h"
#include "Utils/ByteBuffer.h"
#include "Widgets/SContainer.h"
#include "Widgets/HitTest.h"
#include "Tween/GTween.h"
#include "FairyApplication.h"


UGComponent::UGComponent() :
    AlignOffset(ForceInit)
{
    DisplayObject = RootContainer = SNew(SContainer).GObject(this);
    DisplayObject->SetOpaque(false);

    Container = SNew(SContainer);
    Container->SetOpaque(false);
    RootContainer->AddChild(Container.ToSharedRef());
}

UGComponent::~UGComponent()
{
}

UGObject* UGComponent::AddChild(UGObject* Child)
{
    AddChildAt(Child, Children.Num());
    return Child;
}

UGObject* UGComponent::AddChildAt(UGObject* Child, int32 Index)
{
    verifyf(Child != nullptr, TEXT("Argument must be non-nil"));
    verifyf(Index >= 0 && Index <= Children.Num(), TEXT("Invalid child index"));

    if (Child->Parent == this)
    {
        SetChildIndex(Child, Index);
    }
    else
    {
        Child->RemoveFromParent();
        Child->Parent = this;

        int32 cnt = Children.Num();
        if (Child->SortingOrder != 0)
        {
            SortingChildCount++;
            Index = GetInsertPosForSortingChild(Child);
        }
        else if (SortingChildCount > 0)
        {
            if (Index > (cnt - SortingChildCount))
                Index = cnt - SortingChildCount;
        }

        if (Index == cnt)
            Children.Add(Child);
        else
            Children.Insert(Child, Index);

        ChildStateChanged(Child);
        SetBoundsChangedFlag();
    }
    return Child;
}

int32 UGComponent::GetInsertPosForSortingChild(UGObject* Child)
{
    int32 cnt = Children.Num();
    int32 i;
    for (i = 0; i < cnt; i++)
    {
        UGObject* Obj = Children[i];
        if (Obj == Child)
            continue;

        if (Child->SortingOrder < Obj->SortingOrder)
            break;
    }
    return i;
}

void UGComponent::RemoveChild(UGObject* Child)
{
    verifyf(Child != nullptr, TEXT("Argument must be non-nil"));

    int32 ChildIndex = Children.Find(Child);
    if (ChildIndex != INDEX_NONE)
        RemoveChildAt(ChildIndex);
}

void UGComponent::RemoveChildAt(int32 Index)
{
    verifyf(Index >= 0 && Index < Children.Num(), TEXT("Invalid child index"));

    UGObject* Child = Children[Index];

    Child->Parent = nullptr;

    if (Child->SortingOrder != 0)
        SortingChildCount--;

    Child->SetGroup(nullptr);
    if (Child->DisplayObject->GetParentWidget().IsValid())
    {
        Container->RemoveChild(Child->DisplayObject.ToSharedRef());
        if (ChildrenRenderOrder == EChildrenRenderOrder::Arch)
            BuildNativeDisplayList();
    }

    Children.RemoveAt(Index);
    SetBoundsChangedFlag();
}

void UGComponent::RemoveChildren(int32 BeginIndex, int32 EndIndex)
{
    if (EndIndex < 0 || EndIndex >= Children.Num())
        EndIndex = Children.Num() - 1;

    for (int32 i = BeginIndex; i <= EndIndex; ++i)
        RemoveChildAt(BeginIndex);
}

UGObject* UGComponent::GetChildAt(int32 Index, TSubclassOf<UGObject> ClassType) const
{
    verifyf(Index >= 0 && Index < Children.Num(), TEXT("Invalid child index"));

    return Children[Index];
}

UGObject* UGComponent::GetChild(const FString& ChildName, TSubclassOf<UGObject> ClassType) const
{
    for (const auto& Child : Children)
    {
        if (Child->Name.Compare(ChildName) == 0)
            return Child;
    }

    return nullptr;
}

UGObject* UGComponent::GetChildByPath(const FString& Path, TSubclassOf<UGObject> ClassType) const
{
    const UGComponent* Com = this;
    UGObject* Obj = nullptr;

    int32 Index1 = 0, Index2 = -1;
    while ((Index2 = Path.Find(TEXT("."), ESearchCase::IgnoreCase, ESearchDir::FromStart, Index1)) != -1
        || Index1 == 0)
    {
        if (Index2 == -1)
            Index2 = Path.Len();

        if (Com == nullptr)
        {
            Com = Cast<UGComponent>(Obj);
            if (Com == nullptr)
            {
                Obj = nullptr;
                break;
            }
        }

        Obj = Com->GetChild(Path.Mid(Index1, Index2 - Index1));
        if (!Obj)
            break;

        Com = nullptr;
        Index1 = Index2 + 1;
    }

    return Obj;
}

UGObject* UGComponent::GetChildInGroup(const UGGroup* InGroup, const FString& ChildName, TSubclassOf<UGObject> ClassType) const
{
    verifyf(InGroup != nullptr, TEXT("Argument must be non-nil"));

    for (const auto& Obj : Children)
    {
        if (Obj->GetGroup() == InGroup && Obj->Name.Compare(ChildName) == 0)
            return Obj;
    }

    return nullptr;
}

UGObject* UGComponent::GetChildByID(const FString& ChildID) const
{
    for (const auto& Obj : Children)
    {
        if (Obj->ID.Compare(ChildID) == 0)
            return Obj;
    }

    return nullptr;
}

int32 UGComponent::GetChildIndex(const UGObject* Child) const
{
    verifyf(Child != nullptr, TEXT("Argument must be non-nil"));

    return Children.IndexOfByKey(Child);
}

void UGComponent::SetChildIndex(UGObject* Child, int32 Index)
{
    verifyf(Child != nullptr, TEXT("Argument must be non-nil"));

    int32 OldIndex = Children.Find(Child);
    verifyf(OldIndex != -1, TEXT("Not a child of this container"));

    if (Child->SortingOrder != 0) //no effect
        return;

    int32 cnt = Children.Num();
    if (SortingChildCount > 0)
    {
        if (Index > (cnt - SortingChildCount - 1))
            Index = cnt - SortingChildCount - 1;
    }

    MoveChild(Child, OldIndex, Index);
}

int UGComponent::SetChildIndexBefore(UGObject* Child, int32 Index)
{
    verifyf(Child != nullptr, TEXT("Argument must be non-nil"));

    int32 OldIndex = Children.Find(Child);
    verifyf(OldIndex != -1, TEXT("Not a child of this container"));

    if (Child->SortingOrder != 0) //no effect
        return OldIndex;

    int32 cnt = Children.Num();
    if (SortingChildCount > 0)
    {
        if (Index > (cnt - SortingChildCount - 1))
            Index = cnt - SortingChildCount - 1;
    }

    if (OldIndex < Index)
        return MoveChild(Child, OldIndex, Index - 1);
    else
        return MoveChild(Child, OldIndex, Index);
}

int32 UGComponent::MoveChild(UGObject* Child, int32 OldIndex, int32 Index)
{
    int32 cnt = Children.Num();
    if (Index > cnt)
        Index = cnt;

    if (OldIndex == Index)
        return OldIndex;

    Children.RemoveAt(OldIndex);
    if (Index >= cnt)
        Children.Add(Child);
    else
        Children.Insert(Child, Index);

    if (Child->DisplayObject->IsParentValid())
    {
        int32 DisplayIndex = 0;
        if (ChildrenRenderOrder == EChildrenRenderOrder::Ascent)
        {
            for (int32 i = 0; i < Index; i++)
            {
                UGObject* Obj = Children[i];
                if (Obj->DisplayObject->IsParentValid())
                    DisplayIndex++;
            }
            Container->SetChildIndex(Child->DisplayObject.ToSharedRef(), DisplayIndex);
        }
        else if (ChildrenRenderOrder == EChildrenRenderOrder::Descent)
        {
            for (int32 i = cnt - 1; i > Index; i--)
            {
                UGObject* Obj = Children[i];
                if (Obj->DisplayObject->IsParentValid())
                    DisplayIndex++;
            }
            Container->SetChildIndex(Child->DisplayObject.ToSharedRef(), DisplayIndex);
        }
        else
            BuildNativeDisplayList();

        SetBoundsChangedFlag();
    }

    return Index;
}

void UGComponent::SwapChildren(UGObject* Child1, UGObject* Child2)
{
    verifyf(Child1 != nullptr, TEXT("Argument1 must be non-nil"));
    verifyf(Child2 != nullptr, TEXT("Argument2 must be non-nil"));

    int32 Index1 = Children.Find(Child1);
    int32 Index2 = Children.Find(Child2);

    verifyf(Index1 != -1, TEXT("Not a child of this container"));
    verifyf(Index2 != -1, TEXT("Not a child of this container"));

    SwapChildrenAt(Index1, Index2);
}

void UGComponent::SwapChildrenAt(int32 Index1, int32 Index2)
{
    UGObject* Child1 = Children[Index1];
    UGObject* Child2 = Children[Index2];

    SetChildIndex(Child1, Index2);
    SetChildIndex(Child2, Index1);
}

int32 UGComponent::NumChildren() const
{
    return Children.Num();
}

bool UGComponent::IsAncestorOf(const UGObject* Obj) const
{
    if (Obj == nullptr)
        return false;

    UGComponent* Com = Obj->Parent.Get();
    while (Com != nullptr)
    {
        if (Com == this)
            return true;

        Com = Com->Parent.Get();
    }
    return false;
}

bool UGComponent::IsChildInView(UGObject* Child) const
{
    if (ScrollPane != nullptr)
    {
        return ScrollPane->IsChildInView(Child);
    }
    else if (DisplayObject->GetClipping() != EWidgetClipping::Inherit)
    {
        return Child->GetX() + Child->GetWidth() >= 0 && Child->GetX() <= GetWidth() && Child->GetY() + Child->GetHeight() >= 0 && Child->GetY() <= GetHeight();
    }
    else
        return true;
}

int32 UGComponent::GetFirstChildInView() const
{
    int32 i = 0;
    for (auto& Obj : Children)
    {

        if (IsChildInView(Obj))
            return i;
        i++;
    }
    return -1;
}

UGController* UGComponent::GetController(const FString& ControllerName) const
{
    for (const auto& Controller : Controllers)
    {
        if (Controller->Name.Compare(ControllerName) == 0)
            return Controller;
    }

    return nullptr;
}

void UGComponent::AddController(UGController* Controller)
{
    verifyf(Controller != nullptr, TEXT("Argument must be non-nil"));

    Controllers.Add(Controller);
}

UGController* UGComponent::GetControllerAt(int32 Index) const
{
    verifyf(Index >= 0 && Index < Controllers.Num(), TEXT("Invalid controller index"));

    return Controllers[Index];
}

void UGComponent::RemoveController(UGController* Controller)
{
    verifyf(Controller != nullptr, TEXT("Argument must be non-nil"));

    int32 Index = Controllers.Find(Controller);
    verifyf(Index != -1, TEXT("controller not exists"));

    ApplyController(Controller);
    Controllers.RemoveAt(Index);
}

void UGComponent::ApplyController(UGController* Controller)
{
    ApplyingController = Controller;

    for (int32 i = 0; i < Children.Num(); i++)
        Children[i]->HandleControllerChanged(Controller);

    ApplyingController = nullptr;

    Controller->RunActions();
}

void UGComponent::ApplyAllControllers()
{
    for (const auto& Controller : Controllers)
        ApplyController(Controller);
}

UTransition* UGComponent::GetTransition(const FString& TransitionName) const
{
    for (const auto& Transition : Transitions)
    {
        if (Transition->Name.Compare(TransitionName) == 0)
            return Transition;
    }

    return nullptr;
}

UTransition* UGComponent::GetTransitionAt(int32 Index) const
{
    verifyf(Index >= 0 && Index < Transitions.Num(), TEXT("Invalid transition index"));

    return Transitions[Index];
}

void UGComponent::AdjustRadioGroupDepth(UGObject* Obj, UGController* Controller)
{
    int32 cnt = Children.Num();
    int32 i;
    UGObject* Child;
    int32 myIndex = -1, maxIndex = -1;
    for (i = 0; i < cnt; i++)
    {
        Child = Children[i];
        if (Child == Obj)
        {
            myIndex = i;
        }
        else if (Child->IsA<UGButton>() && ((UGButton*)Child)->GetRelatedController() == Controller)
        {
            if (i > maxIndex)
                maxIndex = i;
        }
    }
    if (myIndex < maxIndex)
    {
        if (ApplyingController != nullptr)
            Children[maxIndex]->HandleControllerChanged(ApplyingController);
        SwapChildrenAt(myIndex, maxIndex);
    }
}

bool UGComponent::IsOpaque() const
{
    return DisplayObject->IsOpaque();
}

void UGComponent::SetOpaque(bool bInOpaque)
{
    DisplayObject->SetOpaque(bInOpaque);
}

void UGComponent::SetMargin(const FMargin& InMargin)
{
    Margin = InMargin;
}

void UGComponent::SetChildrenRenderOrder(EChildrenRenderOrder InRenderOrder)
{
    if (ChildrenRenderOrder != InRenderOrder)
    {
        ChildrenRenderOrder = InRenderOrder;
        BuildNativeDisplayList();
    }
}

void UGComponent::SetApexIndex(int32 InApexIndex)
{
    if (ApexIndex != InApexIndex)
    {
        ApexIndex = InApexIndex;

        if (ChildrenRenderOrder == EChildrenRenderOrder::Arch)
            BuildNativeDisplayList();
    }
}

float UGComponent::GetViewWidth() const
{
    if (ScrollPane != nullptr)
        return ScrollPane->GetViewSize().X;
    else
        return Size.X - Margin.Left - Margin.Right;
}

void UGComponent::SetViewWidth(float InViewWidth)
{
    if (ScrollPane != nullptr)
        ScrollPane->SetViewWidth(InViewWidth);
    else
        SetWidth(InViewWidth + Margin.Left + Margin.Right);
}

float UGComponent::GetViewHeight() const
{
    if (ScrollPane != nullptr)
        return ScrollPane->GetViewSize().Y;
    else
        return Size.Y - Margin.Top - Margin.Bottom;
}

void UGComponent::SetViewHeight(float InViewHeight)
{
    if (ScrollPane != nullptr)
        ScrollPane->SetViewHeight(InViewHeight);
    else
        SetHeight(InViewHeight + Margin.Top + Margin.Bottom);
}

void UGComponent::SetHitArea(const TSharedPtr<IHitTest>& InHitArea)
{
    HitArea = InHitArea;
    DisplayObject->UpdateVisibilityFlags();
}

void UGComponent::SetBoundsChangedFlag()
{
    if (bBoundsChanged)
        return;

    if (ScrollPane == nullptr && !bTrackBounds)
        return;

    bBoundsChanged = true;

    GetApp()->DelayCall(UpdateBoundsTimerHandle, this, &UGComponent::EnsureBoundsCorrect);
}

void UGComponent::EnsureBoundsCorrect()
{
    if (bBoundsChanged)
        UpdateBounds();
}

void UGComponent::UpdateBounds()
{
    float ax, ay, aw, ah;
    if (Children.Num() > 0)
    {
        ax = FLT_MAX;
        ay = FLT_MAX;
        float ar = -FLT_MAX, ab = -FLT_MAX;
        float tmp;

        int32 cnt = Children.Num();
        for (int32 i = 0; i < cnt; ++i)
        {
            UGObject* child = Children[i];
            tmp = child->GetX();
            if (tmp < ax)
                ax = tmp;
            tmp = child->GetY();
            if (tmp < ay)
                ay = tmp;
            tmp = child->GetX() + child->GetWidth();
            if (tmp > ar)
                ar = tmp;
            tmp = child->GetY() + child->GetHeight();
            if (tmp > ab)
                ab = tmp;
        }
        aw = ar - ax;
        ah = ab - ay;
    }
    else
    {
        ax = 0;
        ay = 0;
        aw = 0;
        ah = 0;
    }
    SetBounds(ax, ay, aw, ah);
}

void UGComponent::SetBounds(float ax, float ay, float aw, float ah)
{
    bBoundsChanged = false;
    if (ScrollPane != nullptr)
        ScrollPane->SetContentSize(FVector2D(FMath::CeilToFloat(ax + aw), FMath::CeilToFloat(ay + ah)));
}

void UGComponent::ChildStateChanged(UGObject* Child)
{
    if (bBuildingDisplayList)
        return;

    int32 cnt = Children.Num();
    if (Cast<UGGroup>(Child) != nullptr)
    {
        for (int32 i = 0; i < cnt; ++i)
        {
            UGObject* Obj = Children[i];
            if (Obj->GetGroup() == Child)
                ChildStateChanged(Obj);
        }
    }

    if (Child->InternalVisible())
    {
        if (!Child->DisplayObject->IsParentValid())
        {
            if (ChildrenRenderOrder == EChildrenRenderOrder::Ascent)
            {
                int32 index = 0;
                for (int32 i = 0; i < cnt; i++)
                {
                    UGObject* Obj = Children[i];
                    if (Obj == Child)
                        break;

                    if (Obj->DisplayObject->IsParentValid())
                        index++;
                }

                Container->AddChildAt(Child->DisplayObject.ToSharedRef(), index);
            }
            else if (ChildrenRenderOrder == EChildrenRenderOrder::Descent)
            {
                int32 index = 0;
                for (int32 i = cnt - 1; i >= 0; i--)
                {
                    UGObject* Obj = Children[i];
                    if (Obj == Child)
                        break;

                    if (Obj->DisplayObject->IsParentValid())
                        index++;
                }

                Container->AddChildAt(Child->DisplayObject.ToSharedRef(), index);
            }
            else
            {
                BuildNativeDisplayList();
            }
        }
    }
    else
    {
        if (Child->DisplayObject->IsParentValid())
        {
            Container->RemoveChild(Child->DisplayObject.ToSharedRef());
            if (ChildrenRenderOrder == EChildrenRenderOrder::Arch)
            {
                BuildNativeDisplayList();
            }
        }
    }
}

void UGComponent::ChildSortingOrderChanged(UGObject* Child, int32 OldValue, int32 NewValue)
{
    if (NewValue == 0)
    {
        SortingChildCount--;
        SetChildIndex(Child, Children.Num());
    }
    else
    {
        if (OldValue == 0)
            SortingChildCount++;

        int32 OldIndex = Children.Find(Child);
        int32 Index = GetInsertPosForSortingChild(Child);
        if (OldIndex < Index)
            MoveChild(Child, OldIndex, Index - 1);
        else
            MoveChild(Child, OldIndex, Index);
    }
}

void UGComponent::BuildNativeDisplayList(bool bImmediatelly)
{
    if (!bImmediatelly)
    {
        GetApp()->DelayCall(BuildDisplayListTimerHandle, this, &UGComponent::BuildNativeDisplayList, true);
        return;
    }

    int32 cnt = Children.Num();
    if (cnt == 0)
        return;

    switch (ChildrenRenderOrder)
    {
    case EChildrenRenderOrder::Ascent:
    {
        for (int32 i = 0; i < cnt; i++)
        {
            UGObject* Child = Children[i];
            if (Child->InternalVisible())
                Container->AddChild(Child->DisplayObject.ToSharedRef());
        }
    }
    break;
    case EChildrenRenderOrder::Descent:
    {
        for (int32 i = 0; i < cnt; i++)
        {
            UGObject* Child = Children[i];
            if (Child->InternalVisible())
                Container->AddChild(Child->DisplayObject.ToSharedRef());
        }
    }
    break;

    case EChildrenRenderOrder::Arch:
    {
        int32 ai = FMath::Min(ApexIndex, cnt);
        for (int32 i = 0; i < ai; i++)
        {
            UGObject* Child = Children[i];
            if (Child->InternalVisible())
                Container->AddChild(Child->DisplayObject.ToSharedRef());
        }
        for (int32 i = cnt - 1; i >= ai; i--)
        {
            UGObject* Child = Children[i];
            if (Child->InternalVisible())
                Container->AddChild(Child->DisplayObject.ToSharedRef());
        }
    }
    break;

    default:
        break;
    }
}

FVector2D UGComponent::GetSnappingPosition(const FVector2D& InPoint)
{
    int32 cnt = Children.Num();
    if (cnt == 0)
        return InPoint;

    EnsureBoundsCorrect();

    UGObject* Obj = nullptr;

    FVector2D ret = InPoint;

    int32 i = 0;
    if (ret.Y != 0)
    {
        for (; i < cnt; i++)
        {
            Obj = Children[i];
            if (ret.Y < Obj->GetY())
            {
                if (i == 0)
                {
                    ret.Y = 0;
                    break;
                }
                else
                {
                    UGObject* prev = Children[i - 1];
                    if (ret.Y < prev->GetY() + prev->GetHeight() / 2) //top half part
                        ret.Y = prev->GetY();
                    else //bottom half part
                        ret.Y = Obj->GetY();
                    break;
                }
            }
        }

        if (i == cnt)
            ret.Y = Obj->GetY();
    }

    if (ret.X != 0)
    {
        if (i > 0)
            i--;
        for (; i < cnt; i++)
        {
            Obj = Children[i];
            if (ret.X < Obj->GetX())
            {
                if (i == 0)
                {
                    ret.X = 0;
                    break;
                }
                else
                {
                    UGObject* prev = Children[i - 1];
                    if (ret.X < prev->GetX() + prev->GetWidth() / 2) // top half part
                        ret.X = prev->GetX();
                    else //bottom half part
                        ret.X = Obj->GetX();
                    break;
                }
            }
        }
        if (i == cnt)
            ret.X = Obj->GetX();
    }

    return ret;
}

void UGComponent::SetupOverflow(EOverflowType InOverflow)
{
    if (InOverflow == EOverflowType::Hidden)
    {
        DisplayObject->SetClipping(EWidgetClipping::ClipToBoundsAlways);
        DisplayObject->SetCullingBoundsExtension(Margin);
    }

    Container->SetPosition(Margin.GetTopLeft());
}

void UGComponent::SetupScroll(FByteBuffer* Buffer)
{
    ScrollPane = NewObject<UScrollPane>(this);
    ScrollPane->Setup(Buffer);
}

void UGComponent::HandleSizeChanged()
{
    UGObject::HandleSizeChanged();

    if (ScrollPane != nullptr)
        ScrollPane->OnOwnerSizeChanged();
    else
        Container->SetPosition(FVector2D(Margin.Left, Margin.Top));

    if (DisplayObject->GetClipping() != EWidgetClipping::Inherit)
        DisplayObject->SetCullingBoundsExtension(Margin);
}

void UGComponent::HandleGrayedChanged()
{
    UGObject::HandleGrayedChanged();

    UGController* Controller = GetController("grayed");
    if (Controller != nullptr)
        Controller->SetSelectedIndex(IsGrayed() ? 1 : 0);
    else
    {
        for (auto& Child : Children)
            Child->HandleGrayedChanged();
    }
}

void UGComponent::HandleControllerChanged(UGController* Controller)
{
    UGObject::HandleControllerChanged(Controller);

    if (ScrollPane != nullptr)
        ScrollPane->HandleControllerChanged(Controller);
}

void UGComponent::OnAddedToStageHandler(UEventContext* Context)
{
    for (auto& Transition : Transitions)
        Transition->OnOwnerAddedToStage();
}

void UGComponent::OnRemovedFromStageHandler(UEventContext* Context)
{
    for (auto& Transition : Transitions)
        Transition->OnOwnerRemovedFromStage();
}

void UGComponent::ConstructFromResource()
{
    ConstructFromResource(nullptr, 0);
}

void UGComponent::ConstructFromResource(TArray<UGObject*>* ObjectPool, int32 PoolIndex)
{
    TSharedPtr<FPackageItem> ContentItem = PackageItem->GetBranch();

    if (!ContentItem->bTranslated)
    {
        ContentItem->bTranslated = true;
        FTranslationHelper::TranslateComponent(ContentItem);
    }

    FByteBuffer* Buffer = ContentItem->RawData.Get();
    Buffer->Seek(0, 0);

    bUnderConstruct = true;

    SourceSize.X = Buffer->ReadInt();
    SourceSize.Y = Buffer->ReadInt();
    InitSize = SourceSize;

    SetSize(SourceSize);

    if (Buffer->ReadBool())
    {
        MinSize.X = Buffer->ReadInt();
        MaxSize.X = Buffer->ReadInt();
        MinSize.Y = Buffer->ReadInt();
        MaxSize.Y = Buffer->ReadInt();
    }

    if (Buffer->ReadBool())
    {
        float f1 = Buffer->ReadFloat();
        float f2 = Buffer->ReadFloat();
        SetPivot(FVector2D(f1, f2), Buffer->ReadBool());
    }

    if (Buffer->ReadBool())
    {
        Margin.Top = Buffer->ReadInt();
        Margin.Bottom = Buffer->ReadInt();
        Margin.Left = Buffer->ReadInt();
        Margin.Right = Buffer->ReadInt();
    }

    EOverflowType overflow = (EOverflowType)Buffer->ReadByte();
    if (overflow == EOverflowType::Scroll)
    {
        int32 savedPos = Buffer->GetPos();
        Buffer->Seek(0, 7);
        SetupScroll(Buffer);
        Buffer->SetPos(savedPos);
    }
    else
        SetupOverflow(overflow);

    if (Buffer->ReadBool()) //clip soft
        Buffer->Skip(8);

    bBuildingDisplayList = true;

    Buffer->Seek(0, 1);

    int32 controllerCount = Buffer->ReadShort();
    for (int32 i = 0; i < controllerCount; i++)
    {
        int32 nextPos = Buffer->ReadShort();
        nextPos += Buffer->GetPos();

        UGController* Controller = NewObject<UGController>(this);
        Controllers.Add(Controller);
        Controller->Setup(Buffer);

        Buffer->SetPos(nextPos);
    }

    Buffer->Seek(0, 2);

    UGObject* Child;
    int32 childCount = Buffer->ReadShort();
    for (int32 i = 0; i < childCount; i++)
    {
        int32 dataLen = Buffer->ReadShort();
        int32 curPos = Buffer->GetPos();

        if (ObjectPool != nullptr)
            Child = (*ObjectPool)[PoolIndex + i];
        else
        {
            Buffer->Seek(curPos, 0);

            EObjectType type = (EObjectType)Buffer->ReadByte();
            const FString& src = Buffer->ReadS();
            const FString& pkgId = Buffer->ReadS();

            TSharedPtr<FPackageItem> pii;
            if (!src.IsEmpty())
            {
                UUIPackage* pkg;
                if (!pkgId.IsEmpty())
                    pkg = UUIPackage::GetPackageByID(pkgId);
                else
                    pkg = ContentItem->Owner;

                if (pkg != nullptr)
                    pii = pkg->GetItem(src);
            }

            if (pii.IsValid())
            {
                Child = FUIObjectFactory::NewObject(pii, this);
                Child->ConstructFromResource();
            }
            else
                Child = FUIObjectFactory::NewObject(type, this);
        }

        Child->bUnderConstruct = true;
        Child->SetupBeforeAdd(Buffer, curPos);
        Child->Parent = this;
        Children.Add(Child);

        Buffer->SetPos(curPos + dataLen);
    }

    Buffer->Seek(0, 3);
    Relations->Setup(Buffer, true);

    Buffer->Seek(0, 2);
    Buffer->Skip(2);

    for (int32 i = 0; i < childCount; i++)
    {
        int32 nextPos = Buffer->ReadShort();
        nextPos += Buffer->GetPos();

        Buffer->Seek(Buffer->GetPos(), 3);
        Children[i]->GetRelations()->Setup(Buffer, false);

        Buffer->SetPos(nextPos);
    }

    Buffer->Seek(0, 2);
    Buffer->Skip(2);

    for (int32 i = 0; i < childCount; i++)
    {
        int32 nextPos = Buffer->ReadShort();
        nextPos += Buffer->GetPos();

        Child = Children[i];
        Child->SetupAfterAdd(Buffer, Buffer->GetPos());
        Child->bUnderConstruct = false;

        Buffer->SetPos(nextPos);
    }

    Buffer->Seek(0, 4);

    Buffer->Skip(2); //customData
    SetOpaque(Buffer->ReadBool());
    int32 maskId = Buffer->ReadShort();
    if (maskId != -1)
    {
        bool inverted = Buffer->ReadBool();
        //setMask(getChildAt(maskId)->displayObject(), inverted);
    }

    const FString& hitTestId = Buffer->ReadS();
    int32 i1 = Buffer->ReadInt();
    int32 i2 = Buffer->ReadInt();
    if (!hitTestId.IsEmpty())
    {
        TSharedPtr<FPackageItem> pii = ContentItem->Owner->GetItem(hitTestId);
        if (pii.IsValid() && pii->PixelHitTestData.IsValid())
            SetHitArea(MakeShareable(new FPixelHitTest(pii->PixelHitTestData, i1, i2)));
    }
    else if (i1 != 0 && i2 != -1)
    {
        SetHitArea(MakeShareable(new FChildHitTest(GetChildAt(i2))));
    }

    if (Buffer->Version >= 5)
    {
        const FString& enterSound = Buffer->ReadS();
        if (!enterSound.IsEmpty()) {
            On(FUIEvents::AddedToStage).AddLambda([this, enterSound](UEventContext*) {
                GetApp()->PlaySound(enterSound, 1);
            });
        }


        const FString& leaveSound = Buffer->ReadS();
        if (!leaveSound.IsEmpty()) {
            On(FUIEvents::RemovedFromStage).AddLambda([this, leaveSound](UEventContext*) {
                GetApp()->PlaySound(leaveSound, 1);
            });
        }
    }

    Buffer->Seek(0, 5);

    int32 transitionCount = Buffer->ReadShort();
    for (int32 i = 0; i < transitionCount; i++)
    {
        int32 nextPos = Buffer->ReadShort();
        nextPos += Buffer->GetPos();

        UTransition* Transition = NewObject<UTransition>(this);
        Transitions.Add(Transition);
        Transition->Setup(Buffer);

        Buffer->SetPos(nextPos);
    }

    if (Transitions.Num() > 0) {
        On(FUIEvents::AddedToStage).AddUObject(this, &UGComponent::OnAddedToStageHandler);
        On(FUIEvents::RemovedFromStage).AddUObject(this, &UGComponent::OnRemovedFromStageHandler);
    }

    ApplyAllControllers();

    bBuildingDisplayList = false;
    bUnderConstruct = false;

    BuildNativeDisplayList();
    SetBoundsChangedFlag();

    if (ContentItem->ObjectType != EObjectType::Component)
        ConstructExtension(Buffer);

    OnConstruct();
}

void UGComponent::ConstructExtension(FByteBuffer* Buffer)
{
}

void UGComponent::OnConstruct()
{
    K2_OnConstruct();
}

void UGComponent::SetupAfterAdd(FByteBuffer* Buffer, int32 BeginPos)
{
    UGObject::SetupAfterAdd(Buffer, BeginPos);

    Buffer->Seek(BeginPos, 4);

    int32 pageController = Buffer->ReadShort();
    if (pageController != -1 && ScrollPane != nullptr && ScrollPane->bPageMode)
        ScrollPane->PageController = Parent->GetControllerAt(pageController);

    int32 cnt = Buffer->ReadShort();
    for (int32 i = 0; i < cnt; i++)
    {
        UGController* Controller = GetController(Buffer->ReadS());
        const FString& PageID = Buffer->ReadS();
        if (Controller != nullptr)
            Controller->SetSelectedPageID(PageID);
    }

    if (Buffer->Version >= 2)
    {
        cnt = Buffer->ReadShort();
        for (int32 i = 0; i < cnt; i++)
        {
            FString Target = Buffer->ReadS();
            EObjectPropID PropID = (EObjectPropID)Buffer->ReadShort();
            FString Value = Buffer->ReadS();
            UGObject* Obj = GetChildByPath(Target);
            if (Obj != nullptr)
                Obj->SetProp(PropID, FNVariant(Value));
        }
    }
}



================================================
FILE: Source/FairyGUI/Private/UI/GController.cpp
================================================
#include "UI/GController.h"
#include "UI/GComponent.h"
#include "UI/UIPackage.h"
#include "Utils/ByteBuffer.h"

UGController::UGController() :
    SelectedIndex(-1),
    PreviousIndex(-1)
{
}

UGController::~UGController()
{
}

void UGController::SetSelectedIndex(int32 Index)
{
    SetSelectedIndex(Index, true);
}

void UGController::SetSelectedIndex(int32 Index, bool bTriggerEvent)
{
    if (SelectedIndex != Index)
    {
        verifyf(Index < PageIDs.Num(), TEXT("Invalid selected index"));

        bChanging = true;

        PreviousIndex = SelectedIndex;
        SelectedIndex = Index;
        Cast<UGComponent>(GetOuter())->ApplyController(this);

        if (bTriggerEvent)
            OnChangedEvent.Broadcast(this);

        bChanging = false;
    }
}

const FString& UGController::GetSelectedPage() const
{
    if (SelectedIndex == -1)
        return G_EMPTY_STRING;
    else
        return PageNames[SelectedIndex];
}

void UGController::SetSelectedPage(const FString& PageName)
{
    SetSelectedPage(PageName, true);
}

void UGController::SetSelectedPage(const FString& PageName, bool bTriggerEvent)
{
    int32 i = PageNames.Find(PageName);
    if (i == INDEX_NONE)
        i = 0;
    SetSelectedIndex(i, bTriggerEvent);
}

const FString& UGController::GetSelectedPageID() const
{
    if (SelectedIndex == -1)
        return G_EMPTY_STRING;
    else
        return PageIDs[SelectedIndex];
}

void UGController::SetSelectedPageID(const FString& PageID, bool bTriggerEvent)
{
    int32 i = PageIDs.Find(PageID);
    if (i != INDEX_NONE)
        SetSelectedIndex(i, bTriggerEvent);
}

const FString& UGController::GetPreviousPage() const
{
    if (PreviousIndex == -1)
        return G_EMPTY_STRING;
    else
        return PageNames[PreviousIndex];
}

const FString& UGController::GetPreviousPageID() const
{
    if (PreviousIndex == -1)
        return G_EMPTY_STRING;
    else
        return PageIDs[PreviousIndex];
}

int32 UGController::GetPageCount() const
{
    return PageIDs.Num();
}

bool UGController::HasPage(const FString& PageName) const
{
    return PageNames.Find(PageName) != INDEX_NONE;
}

int32 UGController::GetPageIndexByID(const FString& PageID) const
{
    return PageIDs.Find(PageID) != INDEX_NONE;
}

const FString& UGController::GetPageNameByID(const FString& PageID) const
{
    int32 i = PageIDs.Find(PageID);
    if (i != INDEX_NONE)
        return PageNames[i];
    else
        return G_EMPTY_STRING;
}

const FString& UGController::GetPageID(int32 Index) const
{
    return PageIDs[Index];
}

void UGController::SetOppositePageID(const FString& PageID)
{
    int32 i = PageIDs.Find(PageID);
    if (i > 0)
        SetSelectedIndex(0);
    else if (PageIDs.Num() > 1)
        SetSelectedIndex(1);
}

void UGController::RunActions()
{
    if (Actions.Num() == 0)
        return;

    for (auto& it : Actions)
        it.Run(this, GetPreviousPageID(), GetSelectedPageID());
}

void UGController::Setup(FByteBuffer* Buffer)
{
    int32 BeginPos = Buffer->GetPos();
    Buffer->Seek(BeginPos, 0);

    Name = Buffer->ReadS();
    bAutoRadioGroupDepth = Buffer->ReadBool();

    Buffer->Seek(BeginPos, 1);

    int32 cnt = Buffer->ReadShort();
    PageIDs.SetNum(cnt);
    PageNames.SetNum(cnt);
    for (int32 i = 0; i < cnt; i++)
    {
        PageIDs[i] = Buffer->ReadS();
        PageNames[i] = Buffer->ReadS();
    }

    int32 HomePageIndex = 0;
    if (Buffer->Version >= 2)
    {
        int32 HomePageType = Buffer->ReadByte();
        switch (HomePageType)
        {
        case 1:
            HomePageIndex = Buffer->ReadShort();
            break;

        case 2:
            HomePageIndex = PageNames.Find(UUIPackage::GetBranch());
            if (HomePageIndex == INDEX_NONE)
                HomePageIndex = 0;
            break;

        case 3:
            HomePageIndex = PageNames.Find(UUIPackage::GetVar(Buffer->ReadS()));
            if (HomePageIndex == INDEX_NONE)
                HomePageIndex = 0;
            break;
        }
    }

    Buffer->Seek(BeginPos, 2);

    cnt = Buffer->ReadShort();
    if (cnt > 0)
    {
        for (int32 i = 0; i < cnt; i++)
        {
            int32 nextPos = Buffer->ReadShort();
            nextPos += Buffer->GetPos();

            FControllerAction* Action = FControllerAction::CreateAction(Buffer->ReadByte());
            Action->Setup(Buffer);
            Actions.Add(Action);

            Buffer->SetPos(nextPos);
        }
    }

    if (PageIDs.Num() > 0)
        SelectedIndex = HomePageIndex;
    else
        SelectedIndex = -1;
}

================================================
FILE: Source/FairyGUI/Private/UI/GGraph.cpp
================================================
#include "UI/GGraph.h"
#include "Utils/ByteBuffer.h"
#include "Widgets/NTexture.h"
#include "Widgets/SShape.h"
#include "Widgets/Mesh/RectMesh.h"
#include "Widgets/Mesh/RoundedRectMesh.h"
#include "Widgets/Mesh/PolygonMesh.h"
#include "Widgets/Mesh/RegularPolygonMesh.h"
#include "Widgets/Mesh/EllipseMesh.h"

UGGraph::UGGraph()
{
    if (!HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject))
        DisplayObject = Content = SNew(SShape).GObject(this);
}

UGGraph::~UGGraph()
{

}

FColor UGGraph::GetColor() const
{
    return Content->Graphics.GetColor();
}

void UGGraph::SetColor(const FColor& InColor)
{
    Content->Graphics.SetColor(InColor);
}

void UGGraph::DrawRect(float LineWidth, const FColor& LineColor, const FColor& FillColor)
{
    FRectMesh& mesh = Content->Graphics.GetMeshFactory<FRectMesh>();
    mesh.LineWidth = LineWidth;
    mesh.LineColor = LineColor;
    mesh.FillColor.Reset();
    mesh.Colors.Reset();

    Content->Graphics.SetColor(FillColor);
    Content->Graphics.SetMeshDirty();
}

void UGGraph::DrawRoundRect(float LineWidth, const FColor& lineColor, const FColor& FillColor,
    float TopLeftRadius, float TopRightRadius, float BottomLeftRadius, float BottomRightRadius)
{
    FRoundedRectMesh& mesh = Content->Graphics.GetMeshFactory<FRoundedRectMesh>();
    mesh.LineWidth = LineWidth;
    mesh.LineColor = lineColor;
    mesh.FillColor.Reset();
    mesh.TopLeftRadius = TopLeftRadius;
    mesh.TopRightRadius = TopRightRadius;
    mesh.BottomLeftRadius = BottomLeftRadius;
    mesh.BottomRightRadius = BottomRightRadius;

    Content->Graphics.SetColor(FillColor);
    Content->Graphics.SetMeshDirty();
}

void UGGraph::DrawEllipse(float LineWidth, const FColor& LineColor, const FColor& FillColor, float StartDegree, float EndDegree)
{
    FEllipseMesh& mesh = Content->Graphics.GetMeshFactory<FEllipseMesh>();
    mesh.LineWidth = LineWidth;
    mesh.LineColor = LineColor;
    mesh.FillColor.Reset();
    mesh.CenterColor.Reset();
    mesh.StartDegree = StartDegree;
    mesh.EndDegreee = EndDegree;

    Content->Graphics.SetColor(FillColor);
    Content->Graphics.SetMeshDirty();
}

void UGGraph::DrawPolygon(float LineWidth, const FColor& LineColor, const FColor& FillColor, const TArray<FVector2D>& Points)
{
    FPolygonMesh& mesh = Content->Graphics.GetMeshFactory<FPolygonMesh>();
    mesh.LineWidth = LineWidth;
    mesh.LineColor = LineColor;
    mesh.Points.Reset();
    mesh.Points.Append(Points);
    mesh.FillColor.Reset();
    mesh.Colors.Reset();

    Content->Graphics.SetColor(FillColor);
    Content->Graphics.SetMeshDirty();
}

void UGGraph::DrawRegularPolygon(int32 Sides, float LineWidth, const FColor& LineColor, const FColor& FillColor, float ShapeRotation, const TArray<float>& Distances)
{
    FRegularPolygonMesh& mesh = Content->Graphics.GetMeshFactory<FRegularPolygonMesh>();
    mesh.Sides = Sides;
    mesh.LineWidth = LineWidth;
    mesh.CenterColor.Reset();
    mesh.LineColor = LineColor;
    mesh.FillColor.Reset();
    mesh.Rotation = ShapeRotation;
    mesh.Distances.Reset();
    mesh.Distances.Append(Distances);

    Content->Graphics.SetColor(FillColor);
    Content->Graphics.SetMeshDirty();
}

void UGGraph::Clear()
{
    Content->Graphics.SetMeshFactory(nullptr);
}

bool UGGraph::IsEmpty() const
{
    return !Content->Graphics.GetMeshFactory().IsValid();
}

IHitTest* UGGraph::GetHitArea() const
{
    const TSharedPtr<IMeshFactory>& Factory = Content->Graphics.GetMeshFactory();
    if (Factory.IsValid())
        return Factory->GetMeshHitTest();
    else
        return nullptr;
}

FNVariant UGGraph::GetProp(EObjectPropID PropID) const
{
    switch (PropID)
    {
    case EObjectPropID::Color:
        return FNVariant(Content->Graphics.GetColor());
    default:
        return UGObject::GetProp(PropID);
    }
}

void UGGraph::SetProp(EObjectPropID PropID, const FNVariant& InValue)
{
    switch (PropID)
    {
    case EObjectPropID::Color:
        SetColor(InValue.AsColor());
        break;
    default:
        UGObject::SetProp(PropID, InValue);
        break;
    }
}

void UGGraph::SetupBeforeAdd(FByteBuffer* Buffer, int32 BeginPos)
{
    UGObject::SetupBeforeAdd(Buffer, BeginPos);

    Buffer->Seek(BeginPos, 5);

    int32 type = Buffer->ReadByte();
    if (type != 0)
    {
        int32 lineWidth = Buffer->ReadInt();
        FColor lineColor = Buffer->ReadColor();
        FColor fillColor = Buffer->ReadColor();
        bool roundedRect = Buffer->ReadBool();
        FVector4 cornerRadius;
        if (roundedRect)
        {
            for (int32 i = 0; i < 4; i++)
                cornerRadius[i] = Buffer->ReadFloat();
        }

        if (type == 1)
        {
            if (roundedRect)
                DrawRoundRect(lineWidth, lineColor, fillColor, cornerRadius.X, cornerRadius.Y, cornerRadius.Z, cornerRadius.W);
            else
                DrawRect(lineWidth, lineColor, fillColor);
        }
        else if (type == 2)
            DrawEllipse(lineWidth, lineColor, fillColor);
        else if (type == 3)
        {
            int32 cnt = Buffer->ReadShort() / 2;
            TArray<FVector2D> points;
            for (int32 i = 0; i < cnt; i++)
            {
                float f1 = Buffer->ReadFloat();
                float f2 = Buffer->ReadFloat();
                points.Add(FVector2D(f1, f2));
            }

            DrawPolygon(lineWidth, lineColor, fillColor, points);
        }
        else if (type == 4)
        {
            int32 sides = Buffer->ReadShort();
            float startAngle = Buffer->ReadFloat();
            int32 cnt = Buffer->ReadShort();
            TArray<float> distances;
            if (cnt > 0)
            {
                for (int32 i = 0; i < cnt; i++)
                    distances.Add(Buffer->ReadFloat());
            }

            DrawRegularPolygon(sides, lineWidth, lineColor, fillColor, startAngle, distances);
        }
    }
}

================================================
FILE: Source/FairyGUI/Private/UI/GGroup.cpp
================================================
#include "UI/GGroup.h"
#include "UI/GComponent.h"
#include "Utils/ByteBuffer.h"
#include "Widgets/SDisplayObject.h"

UGGroup::UGGroup() :
    MainGridIndex(-1),
    MainGridMinSize(10),
    MainChildIndex(-1)
{
    DisplayObject = SNew(SDisplayObject).GObject(this);;
    DisplayObject->SetInteractable(false);
}

UGGroup::~UGGroup()
{
}

void UGGroup::SetLayout(EGroupLayoutType InLayout)
{
    if (Layout != InLayout)
    {
        Layout = InLayout;
        SetBoundsChangedFlag(true);
    }
}

void UGGroup::SetColumnGap(int32 InColumnGap)
{
    if (ColumnGap != InColumnGap)
    {
        ColumnGap = InColumnGap;
        SetBoundsChangedFlag();
    }
}

void UGGroup::SetLineGap(int32 InLineGap)
{
    if (LineGap != InLineGap)
    {
        LineGap = InLineGap;
        SetBoundsChangedFlag();
    }
}

void UGGroup::SetExcludeInvisibles(bool Flag)
{
    if (bExcludeInvisibles != Flag)
    {
        bExcludeInvisibles = Flag;
        SetBoundsChangedFlag();
    }
}
void UGGroup::SetAutoSizeDisabled(bool Flag)
{
    if (bAutoSizeDisabled != Flag)
    {
        bAutoSizeDisabled = Flag;
        SetBoundsChangedFlag();
    }
}

void UGGroup::SetMainGridIndex(int32 InIndex)
{
    if (MainGridIndex != InIndex)
    {
        MainGridIndex = InIndex;
        SetBoundsChangedFlag();
    }
}

void UGGroup::SetMainGridMinSize(int32 InSize)
{
    if (MainGridMinSize != InSize)
    {
        MainGridMinSize = InSize;
        SetBoundsChangedFlag();
    }
}

void UGGroup::SetBoundsChangedFlag(bool bPositionChangedOnly)
{
    if (Updating == 0 && Parent.IsValid())
    {
        if (!bPositionChangedOnly)
            bPercentReady = false;

        if (!bBoundsChanged)
        {
            bBoundsChanged = true;

            if (Layout != EGroupLayoutType::None)
            {
                GetApp()->DelayCall(UpdateBoundsTimerHandle, this, &UGGroup::EnsureBoundsCorrect);
            }
        }
    }
}

void UGGroup::EnsureBoundsCorrect()
{
    if (!Parent.IsValid() || !bBoundsChanged)
        return;

    bBoundsChanged = false;

    if (bAutoSizeDisabled)
        ResizeChildren(FVector2D::ZeroVector);
    else
    {
        HandleLayout();
        UpdateBounds();
    }
}

void UGGroup::UpdateBounds()
{
    int32 cnt = Parent->NumChildren();
    int32 i;
    UGObject* child;
    float ax = FLT_MAX, ay = FLT_MAX;
    float ar = FLT_MIN, ab = FLT_MIN;
    float tmp;
    bool empty = true;

    for (i = 0; i < cnt; i++)
    {
        child = Parent->GetChildAt(i);
        if (child->GetGroup() != this || (bExcludeInvisibles && !child->InternalVisible3()))
            continue;

        tmp = child->GetX();
        if (tmp < ax)
            ax = tmp;
        tmp = child->GetY();
        if (tmp < ay)
            ay = tmp;
        tmp = child->GetX() + child->GetWidth();
        if (tmp > ar)
            ar = tmp;
        tmp = child->GetY() + child->GetHeight();
        if (tmp > ab)
            ab = tmp;

        empty = false;
    }

    float w;
    float h;
    if (!empty)
    {
        Updating |= 1;
        SetPosition(FVector2D(ax, ay));
        Updating &= 2;

        w = ar - ax;
        h = ab - ay;
    }
    else
        w = h = 0;

    if ((Updating & 2) == 0)
    {
        Updating |= 2;
        SetSize(FVector2D(w, h));
        Updating &= 1;
    }
    else
    {
        Updating &= 1;
        ResizeChildren(FVector2D(GetWidth() - w, GetHeight() - h));
    }
}

void UGGroup::HandleLayout()
{
    Updating |= 1;

    if (Layout == EGroupLayoutType::Horizontal)
    {
        float curX = GetX();
        int32 cnt = Parent->NumChildren();
        for (int32 i = 0; i < cnt; i++)
        {
            UGObject* child = Parent->GetChildAt(i);
            if (child->GetGroup() != this)
                continue;
            if (bExcludeInvisibles && !child->InternalVisible3())
                continue;

            child->SetXMin(curX);
            if (child->GetWidth() != 0)
                curX += child->GetWidth() + ColumnGap;
        }
    }
    else if (Layout == EGroupLayoutType::Vertical)
    {
        float curY = GetY();
        int32 cnt = Parent->NumChildren();
        for (int32 i = 0; i < cnt; i++)
        {
            UGObject* child = Parent->GetChildAt(i);
            if (child->GetGroup() != this)
                continue;
            if (bExcludeInvisibles && !child->InternalVisible3())
                continue;

            child->SetYMin(curY);
            if (child->GetHeight() != 0)
                curY += child->GetHeight() + LineGap;
        }
    }

    Updating &= 2;
}

void UGGroup::MoveChildren(const FVector2D& Delta)
{
    if ((Updating & 1) != 0 || !Parent.IsValid())
        return;

    Updating |= 1;

    int32 cnt = Parent->NumChildren();
    for (int32 i = 0; i < cnt; i++)
    {
        UGObject* child = Parent->GetChildAt(i);
        if (child->GetGroup() == this)
        {
            child->SetPosition(child->GetPosition() + Delta);
        }
    }

    Updating &= 2;
}

void UGGroup::ResizeChildren(const FVector2D& Delta)
{
    if (Layout == EGroupLayoutType::None || (Updating & 2) != 0 || !Parent.IsValid())
        return;

    Updating |= 2;

    if (bBoundsChanged)
    {
        bBoundsChanged = false;
        if (!bAutoSizeDisabled)
        {
            UpdateBounds();
            return;
        }
    }

    int32 cnt = Parent->NumChildren();

    if (!bPercentReady)
    {
        bPercentReady = true;
        NumChildren = 0;
        TotalSize = 0;
        MainChildIndex = -1;

        int32 j = 0;
        for (int32 i = 0; i < cnt; i++)
        {
            UGObject* child = Parent->GetChildAt(i);
            if (child->GetGroup() != this)
                continue;

            if (!bExcludeInvisibles || child->InternalVisible3())
            {
                if (j == MainGridIndex)
                    MainChildIndex = i;

                NumChildren++;

                if (Layout == EGroupLayoutType::Horizontal)
                    TotalSize += child->GetWidth();
                else
                    TotalSize += child->GetHeight();
            }

            j++;
        }

        if (MainChildIndex != -1)
        {
            if (Layout == EGroupLayoutType::Horizontal)
            {
                UGObject* child = Parent->GetChildAt(MainChildIndex);
                TotalSize += MainGridMinSize - child->GetWidth();
                child->SizePercentInGroup = MainGridMinSize / TotalSize;
            }
            else
            {
                UGObject* child = Parent->GetChildAt(MainChildIndex);
                TotalSize += MainGridMinSize - child->GetHeight();
                child->SizePercentInGroup = MainGridMinSize / TotalSize;
            }
        }

        for (int32 i = 0; i < cnt; i++)
        {
            UGObject* child = Parent->GetChildAt(i);
            if (child->GetGroup() != this)
                continue;

            if (i == MainChildIndex)
                continue;

            if (TotalSize > 0)
                child->SizePercentInGroup = (Layout == EGroupLayoutType::Horizontal ? child->GetWidth() : child->GetHeight()) / TotalSize;
            else
                child->SizePercentInGroup = 0;
        }
    }

    float remainSize = 0;
    float remainPercent = 1;
    bool priorHandled = false;

    if (Layout == EGroupLayoutType::Horizontal)
    {
        remainSize = GetWidth() - (NumChildren - 1) * ColumnGap;
        if (MainChildIndex != -1 && remainSize >= TotalSize)
        {
            UGObject* child = Parent->GetChildAt(MainChildIndex);
            child->SetSize(FVector2D(remainSize - (TotalSize - MainGridMinSize), child->RawSize.Y + Delta.Y), true);
            remainSize -= child->GetWidth();
            remainPercent -= child->SizePercentInGroup;
            priorHandled = true;
        }

        float curX = GetX();
        for (int32 i = 0; i < cnt; i++)
        {
            UGObject* child = Parent->GetChildAt(i);
            if (child->GetGroup() != this)
                continue;

            if (bExcludeInvisibles && !child->InternalVisible3())
            {
                child->SetSize(FVector2D(child->RawSize.X, child->RawSize.Y + Delta.Y), true);
                continue;
            }

            if (!priorHandled || i != MainChildIndex)
            {
                child->SetSize(FVector2D(FMath::RoundToInt(child->SizePercentInGroup / remainPercent * remainSize), child->RawSize.Y + Delta.Y), true);
                remainPercent -= child->SizePercentInGroup;
                remainSize -= child->GetWidth();
            }

            child->SetXMin(curX);
            if (child->GetWidth() != 0)
                curX += child->GetWidth() + ColumnGap;
        }
    }
    else
    {
        remainSize = GetHeight() - (NumChildren - 1) * LineGap;
        if (MainChildIndex != -1 && remainSize >= TotalSize)
        {
            UGObject* child = Parent->GetChildAt(MainChildIndex);
            child->SetSize(FVector2D(child->RawSize.X + Delta.X, remainSize - (TotalSize - MainGridMinSize)), true);
            remainSize -= child->GetHeight();
            remainPercent -= child->SizePercentInGroup;
            priorHandled = true;
        }

        float curY = GetY();
        for (int32 i = 0; i < cnt; i++)
        {
            UGObject* child = Parent->GetChildAt(i);
            if (child->GetGroup() != this)
                continue;

            if (bExcludeInvisibles && !child->InternalVisible3())
            {
                child->SetSize(FVector2D(child->RawSize.X + Delta.X, child->RawSize.Y), true);
                continue;
            }

            if (!priorHandled || i != MainChildIndex)
            {
                child->SetSize(FVector2D(child->RawSize.X + Delta.X, FMath::RoundToInt(child->SizePercentInGroup / remainPercent * remainSize)), true);
                remainPercent -= child->SizePercentInGroup;
                remainSize -= child->GetHeight();
            }

            child->SetYMin(curY);
            if (child->GetHeight() != 0)
                curY += child->GetHeight() + LineGap;
        }
    }

    Updating &= 1;
}

void UGGroup::HandleAlphaChanged()
{
    UGObject::HandleAlphaChanged();

    if (bUnderConstruct)
        return;

    int32 cnt = Parent->NumChildren();
    for (int32 i = 0; i < cnt; i++)
    {
        UGObject* child = Parent->GetChildAt(i);
        if (child->GetGroup() == this)
            child->SetAlpha(Alpha);
    }
}

void UGGroup::HandleVisibleChanged()
{
    if (!Parent.IsValid())
        return;

    int32 cnt = Parent->NumChildren();
    for (int32 i = 0; i < cnt; i++)
    {
        UGObject* child = Parent->GetChildAt(i);
        if (child->GetGroup() == this)
            child->HandleVisibleChanged();
    }
}

void UGGroup::SetupBeforeAdd(FByteBuffer* Buffer, int32 BeginPos)
{
    UGObject::SetupBeforeAdd(Buffer, BeginPos);

    Buffer->Seek(BeginPos, 5);

    Layout = (EGroupLayoutType)Buffer->ReadByte();
    LineGap = Buffer->ReadInt();
    ColumnGap = Buffer->ReadInt();
    if (Buffer->Version >= 2)
    {
        bExcludeInvisibles = Buffer->ReadBool();
        bAutoSizeDisabled = Buffer->ReadBool();
        MainGridIndex = Buffer->ReadShort();
    }
}

void UGGroup::SetupAfterAdd(FByteBuffer* Buffer, int32 BeginPos)
{
    UGObject::SetupAfterAdd(Buffer, BeginPos);

    if (!bVisible)
        HandleVisibleChanged();
}


================================================
FILE: Source/FairyGUI/Private/UI/GImage.cpp
================================================
#include "UI/GImage.h"
#include "Utils/ByteBuffer.h"
#include "Widgets/NTexture.h"
#include "Widgets/SFImage.h"

UGImage::UGImage()
{
    if (!HasAnyFlags(RF_ClassDefaultObject | RF_ArchetypeObject))
    {
        DisplayObject = Content = SNew(SFImage).GObject(this);
        DisplayObject->SetInteractable(false);
    }
}

UGImage::~UGImage()
{

}

EFlipType UGImage::GetFlip() const
{
    return Content->Graphics.GetFlip();
}

void UGImage::SetFlip(EFlipType InFlip)
{
    Content->Graphics.SetFlip(InFlip);
}

FColor UGImage::GetColor() const
{
    return Content->Graphics.GetColor();
}

void UGImage::SetColor(const FColor& InColor)
{
    Content->Graphics.SetColor(InColor);
}

EFillMethod UGImage::GetFillMethod() const
{
    return Content->GetFillMethod();
}

void UGImage::SetFillMethod(EFillMethod Method)
{
    Content->SetFillMethod(Method);
}

int32 UGImage::GetFillOrigin() const
{
    return Content->GetFillOrigin();
}

void UGImage::SetFillOrigin(int32 Origin)
{
    Content->SetFillOrigin(Origin);
}

bool UGImage::IsFillClockwise() const
{
    return Content->IsFillClockwise();
}

void UGImage::SetFillClockwise(bool bClockwise)
{
    Content->SetFillClockwise(bClockwise);
}

float UGImage::GetFillAmount() const
{
    return Content->GetFillAmount();
}

void UGImage::SetFillAmount(float Amount)
{
    Content->SetFillAmount(Amount);
}

FNVariant UGImage::GetProp(EObjectPropID PropID) const
{
    switch (PropID)
    {
    case EObjectPropID::Color:
        return FNVariant(GetColor());
    default:
        return UGObject::GetProp(PropID);
    }
}

void UGImage::SetProp(EObjectPropID PropID, const FNVariant& InValue)
{
    switch (PropID)
    {
    case EObjectPropID::Color:
        SetColor(InValue.AsColor());
        break;
    default:
        UGObject::SetProp(PropID, InValue);
        break;
    }
}

void UGImage::ConstructFromResource()
{
    TSharedPtr<FPackageItem> ContentItem = PackageItem->GetBranch();
    InitSize = SourceSize = ContentItem->Size;

    ContentItem = ContentItem->GetHighResolution();
    ContentItem->Load();

    Content->SetTexture(ContentItem->Texture);
    if (ContentItem->Scale9Grid.IsSet())
        Content->SetScale9Grid(ContentItem->Scale9Grid);
    else if (ContentItem->bScaleByTile)
        Content->SetScaleByTile(true);

    SetSize(SourceSize);
}

void UGImage::SetupBeforeAdd(FByteBuffer* Buffer, int32 BeginPos)
{
    UGObject::SetupBeforeAdd(Buffer, BeginPos);

    Buffer->Seek(BeginPos, 5);

    if (Buffer->ReadBool())
        SetColor(Buffer->ReadColor());
    SetFlip((EFlipType)Buffer->ReadByte());
    int32 method = Buffer->ReadByte();
    if (method != 0)
    {
        Content->SetFillMethod((EFillMethod)method);
        Content->SetFillOrigin(Buffer->ReadByte());
        Content->SetFillClockwise(Buffer->ReadBool());
        Content->SetFillAmount(Buffer->ReadFloat());
    }
}


================================================
FILE: Source/FairyGUI/Private/UI/GLabel.cpp
================================================
#include "UI/GLabel.h"
#include "UI/GTextInput.h"
#include "UI/GButton.h"
#include "UI/GTextField.h"
#include "Utils/ByteBuffer.h"

UGLabel::UGLabel()
{
}

UGLabel::~UGLabel()
{
}

const FString& UGLabel::GetText() const
{
    if (TitleObject != nullptr)
        return TitleObject->GetText();
    else
        return G_EMPTY_STRING;
}

void UGLabel::SetText(const FString& InText)
{
    if (TitleObject != nullptr)
        TitleObject->SetText(InText);
    UpdateGear(6);
}

const FString& UGLabel::GetIcon() const
{
    if (IconObject != nullptr)
        return IconObject->GetIcon();
    else
        return G_EMPTY_STRING;
}

void UGLabel::SetIcon(const FString & InIcon)
{
    if (IconObject != nullptr)
        IconObject->SetIcon(InIcon);
    UpdateGear(7);
}

FColor UGLabel::GetTitleColor() const
{
    UGTextField* TextField = GetTextField();
    if (TextField)
        return TextField->GetTextFormat().Color;
    else
        return FColor::Black;
}

void UGLabel::SetTitleColor(const FColor& InColor)
{
    UGTextField* TextField = GetTextField();
    if (TextField)
    {
        TextField->GetTextFormat().Color = InColor;
        TextField->ApplyFormat();
    }
}

int32 UGLabel::GetTitleFontSize() const
{
    UGTextField* TextField = GetTextField();
    if (TextField)
        return TextField->GetTextFormat().Size;
    else
        return 0;
}

void UGLabel::SetTitleFontSize(int32 InFontSize)
{
    UGTextField* TextField = GetTextField();
    if (TextField)
    {
        TextField->GetTextFormat().Size = InFontSize;
        TextField->ApplyFormat();
    }
}

UGTextField * UGLabel::GetTextField() const
{
    if (TitleObject->IsA<UGTextField>())
        return Cast<UGTextField>(TitleObject);
    else if (TitleObject->IsA<UGLabel>())
        return Cast<UGLabel>(TitleObject)->GetTextField();
    else if (TitleObject->IsA<UGButton>())
        return Cast<UGButton>(TitleObject)->GetTextField();
    else
        return nullptr;
}

FNVariant UGLabel::GetProp(EObjectPropID PropID) const
{
    switch (PropID)
    {
    case EObjectPropID::Color:
        return FNVariant(GetTitleColor());
    case EObjectPropID::OutlineColor:
    {
        UGTextField* TextField = GetTextField();
        if (TextField != nullptr)
            return FNVariant(TextField->GetTextFormat().OutlineColor);
        else
            return FNVariant(FColor::Black);
    }
    case EObjectPropID::FontSize:
        return FNVariant(GetTitleFontSize());
    default:
        return UGComponent::GetProp(PropID);
    }
}

void UGLabel::SetProp(EObjectPropID PropID, const FNVariant& InValue)
{
    switch (PropID)
    {
    case EObjectPropID::Color:
        SetTitleColor(InValue.AsColor());
        break;
    case EObjectPropID::OutlineColor:
    {
        UGTextField* TextField = GetTextField();
        if (TextField != nullptr)
        {
            TextField->GetTextFormat().OutlineColor = InValue.AsColor();
            TextField->ApplyFormat();
        }
        break;
    }
    case EObjectPropID::FontSize:
        SetTitleFontSize(InValue.AsInt());
        break;
    default:
        UGComponent::SetProp(PropID, InValue);
        break;
    }
}

void UGLabel::ConstructExtension(FByteBuffer* Buffer)
{
    TitleObject = GetChild("title");
    IconObject = GetChild("icon");
}

void UGLabel::SetupAfterAdd(FByteBuffer* Buffer, int32 BeginPos)
{
    UGComponent::SetupAfterAdd(Buffer, BeginPos);

    if (!Buffer->Seek(BeginPos, 6))
        return;

    if ((EObjectType)Buffer->ReadByte() != PackageItem->ObjectType)
        return;

    const FString* str;

    if ((str = Buffer->ReadSP()) != nullptr)
        SetText(*str);
    if ((str = Buffer->ReadSP()) != nullptr)
        SetIcon(*str);
    if (Buffer->ReadBool())
        SetTitleColor(Buffer->ReadColor());
    int32 iv = Buffer->ReadInt();
    if (iv != 0)
        SetTitleFontSize(iv);

    if (Buffer->ReadBool())
    {
        UGTextInput* input = Cast<UGTextInput>(GetTextField());
        if (input)
        {
            if ((str = Buffer->ReadSP()) != nullptr)
                input->SetPrompt(*str);
            if ((str = Buffer->ReadSP()) != nullptr)
                input->SetRestrict(*str);
            iv = Buffer->ReadInt();
            if (iv != 0)
                input->SetMaxLength(iv);
            iv = Buffer->ReadInt();
            if (iv != 0)
                input->SetKeyboardType(iv);
            if (Buffer->ReadBool())
                input->SetPassword(true);
        }
        else
            Buffer->Skip(13);
    }
}



================================================
FILE: Source/FairyGUI/Private/UI/GList.cpp
================================================
#include "UI/GList.h"
#include "UI/GButton.h"
#include "UI/GObjectPool.h"
#include "UI/GController.h"
#include "UI/GScrollBar.h"
#include "UI/UIPackage.h"
#include "Utils/ByteBuffer.h"
#include "Widgets/SContainer.h"
#include "FairyApplication.h"

UGList::FItemInfo::FItemInfo() :
    Obj(nullptr),
    UpdateFlag(0),
    bSelected(false)
{
}

UGList::UGList() :
    bScrollItemToViewOnClick(true),
    bAutoResizeItem(true),
    LastSelectedIndex(-1),
    FirstIndex(-1)
{
    bTrackBounds = true;
    SetOpaque(true);
    Pool = new FGObjectPool();
}

UGList::~UGList()
{
    delete Pool;

    SelectionController = nullptr;
    bScrollItemToViewOnClick = false;
}

void UGList::SetDefaultItem(const FString& InDefaultItem)
{
    DefaultItem = UUIPackage::NormalizeURL(InDefaultItem);
}

void UGList::SetLayout(EListLayoutType InLayout)
{
    if (Layout != InLayout)
    {
        Layout = InLayout;
        SetBoundsChangedFlag();
        if (bVirtual)
            SetVirtualListChangedFlag(true);
    }
}

void UGList::SetLineCount(int32 InLineCount)
{
    if (LineCount != InLineCount)
    {
        LineCount = InLineCount;
        if (Layout == EListLayoutType::FlowVertical || Layout == EListLayoutType::Pagination)
        {
            SetBoundsChangedFlag();
            if (bVirtual)
                SetVirtualListChangedFlag(true);
        }
    }
}

void UGList::SetColumnCount(int32 InColumnCount)
{
    if (ColumnCount != InColumnCount)
    {
        ColumnCount = InColumnCount;
        if (Layout == EListLayoutType::FlowHorizontal || Layout == EListLayoutType::Pagination)
        {
            SetBoundsChangedFlag();
            if (bVirtual)
                SetVirtualListChangedFlag(true);
        }
    }
}

void UGList::SetLineGap(int32 InLineGap)
{
    if (LineGap != InLineGap)
    {
        LineGap = InLineGap;
        SetBoundsChangedFlag();
        if (bVirtual)
            SetVirtualListChangedFlag(true);
    }
}

void UGList::SetColumnGap(int32 InColumnGap)
{
    if (ColumnGap != InColumnGap)
    {
        ColumnGap = InColumnGap;
        SetBoundsChangedFlag();
        if (bVirtual)
            SetVirtualListChangedFlag(true);
    }
}

void UGList::SetAlign(EAlignType InAlign)
{
    if (Align != InAlign)
    {
        Align = InAlign;
        SetBoundsChangedFlag();
        if (bVirtual)
            SetVirtualListChangedFlag(true);
    }
}

void UGList::SetVerticalAlign(EVerticalAlignType InVerticalAlign)
{
    if (VerticalAlign != InVerticalAlign)
    {
        VerticalAlign = InVerticalAlign;
        SetBoundsChangedFlag();
        if (bVirtual)
            SetVirtualListChangedFlag(true);
    }
}

void UGList::SetAutoResizeItem(bool bFlag)
{
    if (bAutoResizeItem != bFlag)
    {
        bAutoResizeItem = bFlag;
        SetBoundsChangedFlag();
        if (bVirtual)
            SetVirtualListChangedFlag(true);
    }
}

UGObject* UGList::GetFromPool()
{
    return GetFromPool(G_EMPTY_STRING);
}

UGObject* UGList::GetFromPool(const FString& URL)
{
    UGObject* ret;
    if (URL.Len() == 0)
        ret = Pool->GetObject(DefaultItem, this);
    else
        ret = Pool->GetObject(URL, this);
    if (ret != nullptr)
        ret->SetVisible(true);
    return ret;
}

void UGList::ReturnToPool(UGObject* Obj)
{
    Pool->ReturnObject(Obj);
}

UGObject* UGList::AddItemFromPool(const FString& URL)
{
    UGObject* Obj = GetFromPool(URL);

    return AddChild(Obj);
}

UGObject* UGList::AddChildAt(UGObject* Child, int32 Index)
{
    UGComponent::AddChildAt(Child, Index);
    if (Child->IsA<UGButton>())
    {
        UGButton* Button = (UGButton*)Child;
        Button->SetSelected(false);
        Button->bChangeStateOnClick = false;
    }

    Child->OnClick.AddUniqueDynamic(this, &UGList::OnClickItemHandler);

    return Child;
}

void UGList::RemoveChildAt(int32 Index)
{
    UGObject* Child = Children[Index];
    Child->OnClick.RemoveDynamic(this, &UGList::OnClickItemHandler);

    UGComponent::RemoveChildAt(Index);
}

void UGList::RemoveChildToPoolAt(int32 Index)
{
    ReturnToPool(GetChildAt(Index));
    RemoveChildAt(Index);
}

void UGList::RemoveChildToPool(UGObject* Child)
{
    ReturnToPool(Child);
    RemoveChild(Child);
}

void UGList::RemoveChildrenToPool(int32 BeginIndex, int32 EndIndex)
{
    if (EndIndex < 0 || EndIndex >= Children.Num())
        EndIndex = Children.Num() - 1;

    for (int32 i = BeginIndex; i <= EndIndex; ++i)
        RemoveChildToPoolAt(BeginIndex);
}

int32 UGList::GetSelectedIndex() const
{
    if (bVirtual)
    {
        int32 cnt = RealNumItems;
        for (int32 i = 0; i < cnt; i++)
        {
            const FItemInfo& ii = VirtualItems[i];
            if ((Cast<UGButton>(ii.Obj) && ((UGButton*)ii.Obj)->IsSelected()) || (ii.Obj == nullptr && ii.bSelected))
            {
                if (bLoop)
                    return i % NumItems;
                else
                    return i;
            }
        }
    }
    else
    {
        int32 cnt = Children.Num();
        for (int32 i = 0; i < cnt; i++)
        {
            UGButton* Obj = Cast<UGButton>(Children[i]);
            if (Obj != nullptr && Obj->IsSelected())
                return i;
        }
    }
    return -1;
}

void UGList::SetSelectedIndex(int32 Index)
{
    if (Index >= 0 && Index < GetNumItems())
    {
        if (SelectionMode != EListSelectionMode::Single)
            ClearSelection();
        AddSelection(Index, false);
    }
    else
        ClearSelection();
}

void UGList::SetSelectionController(UGController* InController)
{
    SelectionController = InController;
}

void UGList::GetSelection(TArray<int32>& OutIndice) const
{
    OutIndice.Reset();
    if (bVirtual)
    {
        int32 cnt = RealNumItems;
        for (int32 i = 0; i < cnt; i++)
        {
            const FItemInfo& ii = VirtualItems[i];
            if ((Cast<UGButton>(ii.Obj) && ((UGButton*)ii.Obj)->IsSelected()) || (ii.Obj == nullptr && ii.bSelected))
            {
                int32 j = i;
                if (bLoop)
                {
                    j = i % NumItems;
                    if (OutIndice.Contains(j))
                        continue;
                }
                OutIndice.Add(j);
            }
        }
    }
    else
    {
        int32 cnt = Children.Num();
        for (int32 i = 0; i < cnt; i++)
        {
            UGButton* Obj = Cast<UGButton>(Children[i]);
            if (Obj != nullptr && Obj->IsSelected())
                OutIndice.Add(i);
        }
    }
}

void UGList::AddSelection(int32 Index, bool bScrollItToView)
{
    if (SelectionMode == EListSelectionMode::None)
        return;

    CheckVirtualList();

    if (SelectionMode == EListSelectionMode::Single)
        ClearSelection();

    if (bScrollItToView)
        ScrollToView(Index);

    LastSelectedIndex = Index;
    UGButton* Obj = nullptr;
    if (bVirtual)
    {
        FItemInfo& ii = VirtualItems[Index];
        if (ii.Obj != nullptr)
            Obj = ii.Obj->As<UGButton>();
        ii.bSelected = true;
    }
    else
        Obj = GetChildAt(Index)->As<UGButton>();

    if (Obj != nullptr && !Obj->IsSelected())
    {
        Obj->SetSelected(true);
        UpdateSelectionController(Index);
    }
}

void UGList::RemoveSelection(int32 Index)
{
    if (SelectionMode == EListSelectionMode::None)
        return;

    UGButton* Obj = nullptr;
    if (bVirtual)
    {
        FItemInfo& ii = VirtualItems[Index];
        if (ii.Obj != nullptr)
            Obj = ii.Obj->As<UGButton>();
        ii.bSelected = false;
    }
    else
        Obj = GetChildAt(Index)->As<UGButton>();

    if (Obj != nullptr)
        Obj->SetSelected(false);
}

void UGList::ClearSelection()
{
    if (bVirtual)
    {
        int32 cnt = RealNumItems;
        for (int32 i = 0; i < cnt; i++)
        {
            FItemInfo& ii = VirtualItems[i];
            if (Cast<UGButton>(ii.Obj))
                ((UGButton*)ii.Obj)->SetSelected(false);
            ii.bSelected = false;
        }
    }
    else
    {
        int32 cnt = Children.Num();
        for (int32 i = 0; i < cnt; i++)
        {
            UGButton* Obj = Children[i]->As<UGButton>();
            if (Obj != nullptr)
                Obj->SetSelected(false);
        }
    }
}

void UGList::ClearSelectionExcept(UGObject* Obj)
{
    if (bVirtual)
    {
        int32 cnt = RealNumItems;
        for (int32 i = 0; i < cnt; i++)
        {
            FItemInfo& ii = VirtualItems[i];
            if (ii.Obj != Obj)
            {
                if (Cast<UGButton>(ii.Obj))
                    ((UGButton*)ii.Obj)->SetSelected(false);
                ii.bSelected = false;
            }
        }
    }
    else
    {
        int32 cnt = Children.Num();
        for (int32 i = 0; i < cnt; i++)
        {
            UGButton* Child = Children[i]->As<UGButton>();
            if (Child != nullptr && Child != Obj)
                Child->SetSelected(false);
        }
    }
}

void UGList::SelectAll()
{
    CheckVirtualList();

    int32 last = -1;
    if (bVirtual)
    {
        int32 cnt = RealNumItems;
        for (int32 i = 0; i < cnt; i++)
        {
            FItemInfo& ii = VirtualItems[i];
            if (Cast<UGButton>(ii.Obj) && !((UGButton*)ii.Obj)->IsSelected())
            {
                ((UGButton*)ii.Obj)->SetSelected(true);
                last = i;
            }
            ii.bSelected = true;
        }
    }
    else
    {
        int32 cnt = Children.Num();
        for (int32 i = 0; i < cnt; i++)
        {
            UGButton* Obj = Children[i]->As<UGButton>();
            if (Obj != nullptr && !Obj->IsSelected())
            {
                Obj->SetSelected(true);
                last = i;
            }
        }
    }

    if (last != -1)
        UpdateSelectionController(last);
}

void UGList::SelectReverse()
{
    CheckVirtualList();

    int32 last = -1;
    if (bVirtual)
    {
        int32 cnt = RealNumItems;
        for (int32 i = 0; i < cnt; i++)
        {
            FItemInfo& ii = VirtualItems[i];
            if (Cast<UGButton>(ii.Obj))
            {
                ((UGButton*)ii.Obj)->SetSelected(!((UGButton*)ii.Obj)->IsSelected());
                if (((UGButton*)ii.Obj)->IsSelected())
                    last = i;
            }
            ii.bSelected = !ii.bSelected;
        }
    }
    else
    {
        int32 cnt = Children.Num();
        for (int32 i = 0; i < cnt; i++)
        {
            UGButton* Obj = Children[i]->As<UGButton>();
            if (Obj != nullptr)
            {
                Obj->SetSelected(!Obj->IsSelected());
                if (Obj->IsSelected())
                    last = i;
            }
        }
    }

    if (last != -1)
        UpdateSelectionController(last);
}

void UGList::HandleArrowKey(int32 Direction)
{
    int32 index = GetSelectedIndex();
    if (index == -1)
        return;

    switch (Direction)
    {
    case 1: //up
        if (Layout == EListLayoutType::SingleColumn || Layout == EListLayoutType::FlowVertical)
        {
            index--;
            if (index >= 0)
            {
                ClearSelection();
                AddSelection(index, true);
            }
        }
        else if (Layout == EListLayoutType::FlowHorizontal || Layout == EListLayoutType::Pagination)
        {
            UGObject* current = Children[index];
            int32 k = 0;
            int32 i;
            for (i = index - 1; i >= 0; i--)
            {
                UGObject* obj = Children[i];
                if (obj->GetY() != current->GetY())
                {
                    current = obj;
                    break;
                }
                k++;
            }
            for (; i >= 0; i--)
            {
                UGObject* obj = Children[i];
                if (obj->GetY() != current->GetY())
                {
                    ClearSelection();
                    AddSelection(i + k + 1, true);
                    break;
                }
            }
        }
        break;

    case 3: //right
        if (Layout == EListLayoutType::SingleRow || Layout == EListLayoutType::FlowHorizontal || Layout == EListLayoutType::Pagination)
        {
            index++;
            if (index < Children.Num())
            {
                ClearSelection();
                AddSelection(index, true);
            }
        }
        else if (Layout == EListLayoutType::FlowVertical)
        {
            UGObject* current = Children[index];
            int32 k = 0;
            int32 cnt = Children.Num();
            int32 i;
            for (i = index + 1; i < cnt; i++)
            {
                UGObject* obj = Children[i];
                if (obj->GetX() != current->GetX())
                {
                    current = obj;
                    break;
                }
                k++;
            }
            for (; i < cnt; i++)
            {
                UGObject* obj = Children[i];
                if (obj->GetX() != current->GetX())
                {
                    ClearSelection();
                    AddSelection(i - k - 1, true);
                    break;
                }
            }
        }
        break;

    case 5: //down
        if (Layout == EListLayoutType::SingleColumn || Layout == EListLayoutType::FlowVertical)
        {
            index++;
            if (index < Children.Num())
            {
                ClearSelection();
                AddSelection(index, true);
            }
        }
        else if (Layout == EListLayoutType::FlowHorizontal || Layout == EListLayoutType::Pagination)
        {
            UGObject* current = Children[index];
            int32 k = 0;
            int32 cnt = Children.Num();
            int32 i;
            for (i = index + 1; i < cnt; i++)
            {
                UGObject* obj = Children[i];
                if (obj->GetY() != current->GetY())
                {
                    current = obj;
                    break;
                }
                k++;
            }
            for (; i < cnt; i++)
            {
                UGObject* obj = Children[i];
                if (obj->GetY() != current->GetY())
                {
                    ClearSelection();
                    AddSelection(i - k - 1, true);
                    break;
                }
            }
        }
        break;

    case 7: //left
        if (Layout == EListLayoutType::SingleRow || Layout == EListLayoutType::FlowHorizontal || Layout == EListLayoutType::Pagination)
        {
            index--;
            if (index >= 0)
            {
                ClearSelection();
                AddSelection(index, true);
            }
        }
        else if (Layout == EListLayoutType::FlowVertical)
        {
            UGObject* current = Children[index];
            int32 k = 0;
            int32 i;
            for (i = index - 1; i >= 0; i--)
            {
                UGObject* obj = Children[i];
                if (obj->GetX() != current->GetX())
                {
                    current = obj;
                    break;
                }
                k++;
            }
            for (; i >= 0; i--)
            {
                UGObject* obj = Children[i];
                if (obj->GetX() != current->GetX())
                {
                    ClearSelection();
                    AddSelection(i + k + 1, true);
                    break;
                }
            }
        }
        break;
    }
}

void UGList::OnClickItemHandler(UEventContext* Context)
{
    UGObject* Obj = Context->GetSender();
    if (Obj->IsA<UGButton>() && SelectionMode != EListSelectionMode::None)
        SetSelectionOnEvent(Obj, Context);

    if (ScrollPane != nullptr && bScrollItemToViewOnClick)
        ScrollPane->ScrollToView(Obj, true);

    DispatchItemEvent(Obj, Context);
}

void UGList::DispatchItemEvent(UGObject* Obj, UEventContext* Context)
{
    DispatchEvent(FUIEvents::ClickItem, FNVariant(Obj));
}

void UGList::SetSelectionOnEvent(UGObject* Obj, UEventContext* Context)
{
    bool bDontChangeLastIndex = false;
    UGButton* Button = Cast<UGButton>(Obj);
    int32 Index = ChildIndexToItemIndex(GetChildIndex(Obj));

    if (SelectionMode == EListSelectionMode::Single)
    {
        if (!Button->IsSelected())
        {
            ClearSelectionExcept(Button);
            Button->SetSelected(true);
        }
    }
    else
    {
        if (Context->GetPointerEvent().IsShiftDown())
        {
            if (!Button->IsSelected())
            {
                if (LastSelectedIndex != -1)
                {
                    int32 min = FMath::Min(LastSelectedIndex, Index);
                    int32 max = FMath::Max(LastSelectedIndex, Index);
                    max = FMath::Min(max, GetNumItems() - 1);
                    if (bVirtual)
                    {
                        for (int32 i = min; i <= max; i++)
                        {
                            FItemInfo& ii = VirtualItems[i];
                            if (ii.Obj != nullptr && ii.Obj->IsA<UGButton>())
                                Cast<UGButton>(ii.Obj)->SetSelected(true);
                            ii.bSelected = true;
                        }
                    }
                    else
                    {
                        for (int32 i = min; i <= max; i++)
                        {
                            UGButton* Child = GetChildAt(i)->As<UGButton>();
                            if (Child != nullptr && !Child->IsSelected())
                                Child->SetSelected(true);
                        }
                    }

                    bDontChangeLastIndex = true;
                }
                else
                {
                    Button->SetSelected(true);
                }
            }
        }
        else if (Context->GetPointerEvent().IsControlDown() || SelectionMode == EListSelectionMode::MultipleSingleclick)
        {
            Button->SetSelected(!Button->IsSelected());
        }
        else
        {
            if (!Button->IsSelected())
            {
                ClearSelectionExcept(Button);
                Button->SetSelected(true);
            }
            else if (Context->GetMouseButton() == EKeys::LeftMouseButton)
                ClearSelectionExcept(Button);
        }
    }

    if (!bDontChangeLastIndex)
        LastSelectedIndex = Index;

    if (Button->IsSelected())
        UpdateSelectionController(Index);
}

void UGList::ResizeToFit(int32 ItemCount, int32 InMinSize)
{
    EnsureBoundsCorrect();

    int32 curCount = GetNumItems();
    if (ItemCount > curCount)
        ItemCount = curCount;

    if (bVirtual)
    {
        int32 lineCount = FMath::CeilToInt((float)ItemCount / CurLineItemCount);
        if (Layout == EListLayoutType::SingleColumn || Layout == EListLayoutType::FlowHorizontal)
            SetViewHeight(lineCount * ItemSize.Y + FMath::Max(0, lineCount - 1) * LineGap);
        else
            SetViewWidth(lineCount * ItemSize.X + FMath::Max(0, lineCount - 1) * ColumnGap);
    }
    else if (ItemCount == 0)
    {
        if (Layout == EListLayoutType::SingleColumn || Layout == EListLayoutType::FlowHorizontal)
            SetViewHeight(InMinSize);
        else
            SetViewWidth(InMinSize);
    }
    else
    {
        int32 i = ItemCount - 1;
        UGObject* obj = nullptr;
        while (i >= 0)
        {
            obj = GetChildAt(i);
            if (!bFoldInvisibleItems || obj->IsVisible())
                break;
            i--;
        }
        if (i < 0)
        {
            if (Layout == EListLayoutType::SingleColumn || Layout == EListLayoutType::FlowHorizontal)
                SetViewHeight(InMinSize);
            else
                SetViewWidth(InMinSize);
        }
        else
        {
            float size;
            if (Layout == EListLayoutType::SingleColumn || Layout == EListLayoutType::FlowHorizontal)
            {
                size = obj->GetY() + obj->GetHeight();
                if (size < InMinSize)
                    size = InMinSize;
                SetViewHeight(size);
            }
            else
            {
                size = obj->GetX() + obj->GetWidth();
                if (size < InMinSize)
                    size = InMinSize;
                SetViewWidth(size);
            }
        }
    }
}

int32 UGList::GetFirstChildInView() const
{
    return ChildIndexToItemIndex(UGComponent::GetFirstChildInView());
}

void UGList::HandleSizeChanged()
{
    UGComponent::HandleSizeChanged();

    SetBoundsChangedFlag();
    if (bVirtual)
        SetVirtualListChangedFlag(true);
}

void UGList::HandleControllerChanged(UGController* Controller)
{
    UGComponent::HandleControllerChanged(Controller);

    if (SelectionController == Controller)
        SetSelectedIndex(Controller->GetSelectedIndex());
}

void UGList::UpdateSelectionController(int32 Index)
{
    if (SelectionController != nullptr && !SelectionController->bChanging && Index < SelectionController->GetPageCount())
    {
        UGController* Controller = SelectionController;
        SelectionController = nullptr;
        Controller->SetSelectedIndex(Index);
        SelectionController = Controller;
    }
}

void UGList::ScrollToView(int32 Index, bool bAnimation, bool bSetFirst)
{
    if (bVirtual)
    {
        if (NumItems == 0)
            return;

        CheckVirtualList();

        verifyf(Index >= 0 && Index < VirtualItems.Num(), TEXT("Invalid child index"));

        if (bLoop)
            Index = FMath::FloorToFloat(FirstIndex / NumItems) * NumItems + Index;

        FBox2D rect;
        FItemInfo& ii = VirtualItems[Index];
        if (Layout == EListLayoutType::SingleColumn || Layout == EListLayoutType::FlowHorizontal)
        {
            float pos = 0;
            for (int32 i = CurLineItemCount - 1; i < Index; i += CurLineItemCount)
                pos += VirtualItems[i].Size.Y + LineGap;
            rect.Min.Set(0, pos);
            rect.Max = rect.Min + FVector2D(ItemSize.X, ii.Size.Y);
        }
        else if (Layout == EListLayoutType::SingleRow || Layout == EListLayoutType::FlowVertical)
        {
            float pos = 0;
            for (int32 i = CurLineItemCount - 1; i < Index; i += CurLineItemCount)
                pos += VirtualItems[i].Size.X + ColumnGap;
            rect.Min.Set(pos, 0);
            rect.Max = rect.Min + FVector2D(ii.Size.X, ItemSize.Y);
        }
        else
        {
            int32 page = Index / (CurLineItemCount * CurLineItemCount2);
            rect.Min.Set(page * GetViewWidth() + (Index % CurLineItemCount) * (ii.Size.X + ColumnGap),
                (Index / CurLineItemCount) % CurLineItemCount2 * (ii.Size.Y + LineGap));
            rect.Max = rect.Min + ii.Size;
        }

        if (ScrollPane != nullptr)
            ScrollPane->ScrollToView(rect, bAnimation, bSetFirst);
        else if (Parent.IsValid() && Parent->GetScrollPane() != nullptr)
        {
            FBox2D rect2 = LocalToGlobalRect(rect);
            rect2 = Parent->GlobalToLocalRect(rect2);
            Parent->GetScrollPane()->ScrollToView(rect2, bAnimation, bSetFirst);
        }
    }
    else
    {
        UGObject* obj = GetChildAt(Index);
        if (ScrollPane != nullptr)
            ScrollPane->ScrollToView(obj, bAnimation, bSetFirst);
        else if (Parent.IsValid() && Parent->GetScrollPane() != nullptr)
            Parent->GetScrollPane()->ScrollToView(obj, bAnimation, bSetFirst);
    }
}

int32 UGList::ChildIndexToItemIndex(int32 Index) const
{
    if (!bVirtual)
        return Index;

    if (Layout == EListLayoutType::Pagination)
    {
        for (int32 i = FirstIndex; i < RealNumItems; i++)
        {
            if (VirtualItems[i].Obj != nullptr)
            {
                Index--;
                if (Index < 0)
                    return i;
            }
        }

        return Index;
    }
    else
    {
        Index += FirstIndex;
        if (bLoop && NumItems > 0)
            Index = Index % NumItems;

        return Index;
    }
}

int32 UGList::ItemIndexToChildIndex(int32 Index) const
{
    if (!bVirtual)
        return Index;

    if (Layout == EListLayoutType::Pagination)
    {
        return GetChildIndex(VirtualItems[Index].Obj);
    }
    else
    {
        if (bLoop && NumItems > 0)
        {
            int32 j = FirstIndex % NumItems;
            if (Index >= j)
                Index = Index - j;
            else
                Index = NumItems - j + Index;
        }
        else
            Index -= FirstIndex;

        return Index;
    }
}

void UGList::SetVirtual()
{
    SetVirtual(false);
}

void UGList::SetVirtualAndLoop()
{
    SetVirtual(true);
}

void UGList::SetVirtual(bool bInLoop)
{
    if (!bVirtual)
    {
        verifyf(ScrollPane != nullptr, TEXT("FairyGUI: Virtual list must be scrollable!"));

        if (bInLoop)
        {
            verifyf(Layout != EListLayoutType::FlowHorizontal && Layout != EListLayoutType::FlowVertical,
                TEXT("Loop list is not supported for FlowHorizontal or FlowVertical layout!"));

            ScrollPane->bBouncebackEffect = false;
        }

        bVirtual = true;
        bLoop = bInLoop;
        RemoveChildrenToPool();

        if (ItemSize.X == 0 || ItemSize.Y == 0)
        {
            UGObject* obj = GetFromPool();
            verifyf(obj != nullptr, TEXT("Virtual List must have a default list item resource."));
            ItemSize = obj->GetSize();
            ItemSize.X = FMath::CeilToFloat(ItemSize.X);
            ItemSize.Y = FMath::CeilToFloat(ItemSize.Y);
            ReturnToPool(obj);
        }

        if (Layout == EListLayoutType::SingleColumn || Layout == EListLayoutType::FlowHorizontal)
        {
            ScrollPane->ScrollStep = ItemSize.Y;
            if (bLoop)
                ScrollPane->LoopMode = 2;
        }
        else
        {
            ScrollPane->ScrollStep = ItemSize.X;
            if (bLoop)
                ScrollPane->LoopMode = 1;
        }

        On(FUIEvents::Scroll).AddUObject(this, &UGList::OnScrollHandler);
        SetVirtualListChangedFlag(true);
    }
}

int32 UGList::GetNumItems() const
{
    if (bVirtual)
        return NumItems;
    else
        return Children.Num();
}

void UGList::SetNumItems(int32 InNumItems)
{
    if (bVirtual)
    {
        verifyf(ItemRenderer.IsBound(), TEXT("Set itemRenderer first!"));

        NumItems = InNumItems;
        if (bLoop)
            RealNumItems = NumItems * 6;
        else
            RealNumItems = NumItems;

        int32 oldCount = VirtualItems.Num();
        if (RealNumItems > oldCount)
        {
            for (int32 i = oldCount; i < RealNumItems; i++)
            {
                FItemInfo ii;
                ii.Size = ItemSize;

                VirtualItems.Add(MoveTemp(ii));
            }
        }
        else
        {
            for (int32 i = RealNumItems; i < oldCount; i++)
                VirtualItems[i].bSelected = false;
        }

        if (VirtualListChanged != 0)
            GetApp()->CancelDelayCall(RefreshTimerHandle);

        DoRefreshVirtualList();
    }
    else
    {
        int32 cnt = Children.Num();
        if (InNumItems > cnt)
        {
            for (int32 i = cnt; i < InNumItems; i++)
            {
                if (!ItemProvider.IsBound())
                    AddItemFromPool();
                else
                    AddItemFromPool(ItemProvider.Execute(i));
            }
        }
        else
        {
            RemoveChildrenToPool(InNumItems, cnt);
        }

        if (ItemRenderer.IsBound())
        {
            for (int32 i = 0; i < InNumItems; i++)
                ItemRenderer.Execute(i, GetChildAt(i));
        }
    }
}

void UGList::RefreshVirtualList()
{
    verifyf(bVirtual, TEXT("not virtual list"));

    SetVirtualListChangedFlag(false);
}

FVector2D UGList::GetSnappingPosition(const FVector2D& InPoint)
{
    if (bVirtual)
    {
        FVector2D ret = InPoint;
        if (Layout == EListLayoutType::SingleColumn || Layout == EListLayoutType::FlowHorizontal)
        {
            int32 index = GetIndexOnPos1(ret.Y, false);
            if (index < VirtualItems.Num() && InPoint.Y - ret.Y > VirtualItems[index].Size.Y / 2 && index < RealNumItems)
                ret.Y += VirtualItems[index].Size.Y + LineGap;
        }
        else if (Layout == EListLayoutType::SingleRow || Layout == EListLayoutType::FlowVertical)
        {
            int32 index = GetIndexOnPos2(ret.X, false);
            if (index < VirtualItems.Num() && InPoint.X - ret.X > VirtualItems[index].Size.X / 2 && index < RealNumItems)
                ret.X += VirtualItems[index].Size.X + ColumnGap;
        }
        else
        {
            int32 index = GetIndexOnPos3(ret.X, false);
            if (index < VirtualItems.Num() && InPoint.X - ret.X > VirtualItems[index].Size.X / 2 && index < RealNumItems)
                ret.X += VirtualItems[index].Size.X + ColumnGap;
        }

        return ret;
    }
    else
        return UGComponent::GetSnappingPosition(InPoint);
}

void UGList::CheckVirtualList()
{
    if (VirtualListChanged != 0)
    {
        DoRefreshVirtualList();
        GetApp()->CancelDelayCall(RefreshTimerHandle);
    }
}

void UGList::SetVirtualListChangedFlag(bool bLayoutChanged)
{
    if (bLayoutChanged)
        VirtualListChanged = 2;
    else if (VirtualListChanged == 0)
        VirtualListChanged = 1;

    GetApp()->DelayCall(RefreshTimerHandle, this, &UGList::DoRefreshVirtualList);
}

void UGList::DoRefreshVirtualList()
{
    bool bLayoutChanged = VirtualListChanged == 2;
    VirtualListChanged = 0;
    bEventLocked = true;

    if (bLayoutChanged)
    {
        if (Layout == EListLayoutType::SingleColumn || Layout == EListLayoutType::SingleRow)
            CurLineItemCount = 1;
        else if (Layout == EListLayoutType::FlowHorizontal)
        {
            if (ColumnCount > 0)
                CurLineItemCount = ColumnCount;
            else
            {
                CurLineItemCount = FMath::FloorToInt((ScrollPane->GetViewSize().X + ColumnGap) / (ItemSize.X + ColumnGap));
                if (CurLineItemCount <= 0)
                    CurLineItemCount = 1;
            }
        }
        else if (Layout == EListLayoutType::FlowVertical)
        {
            if (LineCount > 0)
                CurLineItemCount = LineCount;
            else
            {
                CurLineItemCount = FMath::FloorToInt((ScrollPane->GetViewSize().Y + LineGap) / (ItemSize.Y + LineGap));
                if (CurLineItemCount <= 0)
                    CurLineItemCount = 1;
            }
        }
        else //Pagination
        {
            if (ColumnCount > 0)
                CurLineItemCount = ColumnCount;
            else
            {
                CurLineItemCount = FMath::FloorToInt((ScrollPane->GetViewSize().X + ColumnGap) / (ItemSize.X + ColumnGap));
                if (CurLineItemCount <= 0)
                    CurLineItemCount = 1;
            }

            if (LineCount > 0)
                CurLineItemCount2 = LineCount;
            else
            {
                CurLineItemCount2 = FMath::FloorToInt((ScrollPane->GetViewSize().Y + LineGap) / (ItemSize.Y + LineGap));
                if (CurLineItemCount2 <= 0)
                    CurLineItemCount2 = 1;
            }
        }
    }
    float ch = 0, cw = 0;
    if (RealNumItems > 0)
    {
        int32 len = FMath::FloorToInt((float)RealNumItems / CurLineItemCount) * CurLineItemCount;
        int32 len2 = FMath::Min(CurLineItemCount, RealNumItems);
        if (Layout == EListLayoutType::SingleColumn || Layout == EListLayoutType::FlowHorizontal)
        {
            for (int32 i = 0; i < len; i += CurLineItemCount)
                ch += VirtualItems[i].Size.Y + LineGap;
            if (ch > 0)
                ch -= LineGap;

            if (bAutoResizeItem)
                cw = ScrollPane->GetViewSize().X;
            else
            {
                for (int32 i = 0; i < len2; i++)
                    cw += VirtualItems[i].Size.X + ColumnGap;
                if (cw > 0)
                    cw -= ColumnGap;
            }
        }
        else if (Layout == EListLayoutType::SingleRow || Layout == EListLayoutType::FlowVertical)
        {
            for (int32 i = 0; i < len; i += CurLineItemCount)
                cw += VirtualItems[i].Size.X + ColumnGap;
            if (cw > 0)
                cw -= ColumnGap;

            if (bAutoResizeItem)
                ch = ScrollPane->GetViewSize().Y;
            else
            {
                for (int32 i = 0; i < len2; i++)
                    ch += VirtualItems[i].Size.Y + LineGap;
                if (ch > 0)
                    ch -= LineGap;
            }
        }
        else
        {
            int32 pageCount = FMath::CeilToInt((float)len / (CurLineItemCount * CurLineItemCount2));
            cw = pageCount * GetViewWidth();
            ch = GetViewHeight();
        }
    }

    HandleAlign(cw, ch);
    ScrollPane->SetContentSize(FVector2D(cw, ch));

    bEventLocked = false;

    HandleScroll(true);
}

void UGList::OnScrollHandler(UEventContext* Context)
{
    HandleScroll(false);
}

int32 UGList::GetIndexOnPos1(float& pos, bool forceUpdate)
{
    if (RealNumItems < CurLineItemCount)
    {
        pos = 0;
        return 0;
    }

    if (NumChildren() > 0 && !forceUpdate)
    {
        float pos2 = GetChildAt(0)->GetY();
        if (pos2 + (LineGap > 0 ? 0 : -LineGap) > pos)
        {
            for (int32 i = FirstIndex - CurLineItemCount; i >= 0; i -= CurLineItemCount)
            {
                pos2 -= (VirtualItems[i].Size.Y + LineGap);
                if (pos2 <= pos)
                {
                    pos = pos2;
                    return i;
                }
            }

            pos = 0;
            return 0;
        }
        else
        {
            float testGap = LineGap > 0 ? LineGap : 0;
            for (int32 i = FirstIndex; i < RealNumItems; i += CurLineItemCount)
            {
                float pos3 = pos2 + VirtualItems[i].Size.Y;
                if (pos3 + testGap > pos)
                {
                    pos = pos2;
                    return i;
                }
                pos2 = pos3 + LineGap;
            }

            pos = pos2;
            return RealNumItems - CurLineItemCount;
        }
    }
    else
    {
        float pos2 = 0;
        float testGap = LineGap > 0 ? LineGap : 0;
        for (int32 i = 0; i < RealNumItems; i += CurLineItemCount)
        {
            float pos3 = pos2 + VirtualItems[i].Size.Y;
            if (pos3 + testGap > pos)
            {
                pos = pos2;
                return i;
            }
            pos2 = pos3 + LineGap;
        }

        pos = pos2;
        return RealNumItems - CurLineItemCount;
    }
}

int32 UGList::GetIndexOnPos2(float& pos, bool forceUpdate)
{
    if (RealNumItems < CurLineItemCount)
    {
        pos = 0;
        return 0;
    }

    if (NumChildren() > 0 && !forceUpdate)
    {
        float pos2 = GetChildAt(0)->GetX();
        if (pos2 + (ColumnGap > 0 ? 0 : -ColumnGap) > pos)
        {
            for (int32 i = FirstIndex - CurLineItemCount; i >= 0; i -= CurLineItemCount)
            {
                pos2 -= (VirtualItems[i].Size.X + ColumnGap);
                if (pos2 <= pos)
                {
                    pos = pos2;
                    return i;
                }
            }

            pos = 0;
            return 0;
        }
        else
        {
            float testGap = ColumnGap > 0 ? ColumnGap : 0;
            for (int32 i = FirstIndex; i < RealNumItems; i += CurLineItemCount)
            {
                float pos3 = pos2 + VirtualItems[i].Size.X;
                if (pos3 + testGap > pos)
                {
                    pos = pos2;
                    return i;
                }
                pos2 = pos3 + ColumnGap;
            }

            pos = pos2;
            return RealNumItems - CurLineItemCount;
        }
    }
    else
    {
        float pos2 = 0;
        float testGap = ColumnGap > 0 ? ColumnGap : 0;
        for (int32 i = 0; i < RealNumItems; i += CurLineItemCount)
        {
            float pos3 = pos2 + VirtualItems[i].Size.X;
            if (pos3 + testGap > pos)
            {
                pos = pos2;
                return i;
            }
            pos2 = pos3 + ColumnGap;
        }

        pos = pos2;
        return RealNumItems - CurLineItemCount;
    }
}

int32 UGList::GetIndexOnPos3(float& pos, bool forceUpdate)
{
    if (RealNumItems < CurLineItemCount)
    {
        pos = 0;
        return 0;
    }

    float viewWidth = GetViewWidth();
    int32 page = FMath::FloorToInt(pos / viewWidth);
    int32 startIndex = page * (CurLineItemCount * CurLineItemCount2);
    float pos2 = page * viewWidth;
    float testGap = ColumnGap > 0 ? ColumnGap : 0;
    for (int32 i = 0; i < CurLineItemCount; i++)
    {
        float pos3 = pos2 + VirtualItems[startIndex + i].Size.X;
        if (pos3 + testGap > pos)
        {
            pos = pos2;
            return startIndex + i;
        }
        pos2 = pos3 + ColumnGap;
    }

    pos = pos2;
    return startIndex + CurLineItemCount - 1;
}

void UGList::HandleScroll(bool forceUpdate)
{
    if (bEventLocked)
        return;

    if (Layout == EListLayoutType::SingleColumn || Layout == EListLayoutType::FlowHorizontal)
    {
        int32 enterCounter = 0;
        while (HandleScroll1(forceUpdate))
        {
            enterCounter++;
            forceUpdate = false;
            if (enterCounter > 20)
            {
                UE_LOG(LogFairyGUI, Warning, TEXT("list will never be filled as the item renderer function always returns a different size."));
                break;
            }
        }
        HandleArchOrder1();
    }
    else if (Layout == EListLayoutType::SingleRow || Layout == EListLayoutType::FlowVertical)
    {
        int32 enterCounter = 0;
        while (HandleScroll2(forceUpdate))
        {
            enterCounter++;
            forceUpdate = false;
            if (enterCounter > 20)
            {
                UE_LOG(LogFairyGUI, Warning, TEXT("list will never be filled as the item renderer function always returns a different size."));
                break;
            }
        }
        HandleArchOrder2();
    }
    else
    {
        HandleScroll3(forceUpdate);
    }

    bBoundsChanged = false;
}

bool UGList::HandleScroll1(bool forceUpdate)
{
    float pos = ScrollPane->GetScrollingPosY();
    float max = pos + ScrollPane->GetViewSize().Y;
    bool end = max == ScrollPane->GetContentSize().Y;

    int32 newFirstIndex = GetIndexOnPos1(pos, forceUpdate);
    if (newFirstIndex == FirstIndex && !forceUpdate)
        return false;

    int32 oldFirstIndex = FirstIndex;
    FirstIndex = newFirstIndex;
    int32 curIndex = newFirstIndex;
    bool forward = oldFirstIndex > newFirstIndex;
    int32 childCount = NumChildren();
    int32 lastIndex = oldFirstIndex + childCount - 1;
    int32 reuseIndex = forward ? lastIndex : oldFirstIndex;
    float curX = 0, curY = pos;
    bool needRender;
    float deltaSize = 0;
    float firstItemDeltaSize = 0;
    FString url = DefaultItem;
    int32 partSize = (int32)((ScrollPane->GetViewSize().X - ColumnGap * (CurLineItemCount - 1)) / CurLineItemCount);

    ItemInfoVer++;
    while (curIndex < RealNumItems && (end || curY < max))
    {
        FItemInfo& ii = VirtualItems[curIndex];

        if (ii.Obj == nullptr || forceUpdate)
        {
            if (ItemProvider.IsBound())
            {
                url = ItemProvider.Execute(curIndex % NumItems);
                if (url.Len() == 0)
                    url = DefaultItem;
                url = UUIPackage::NormalizeURL(url);
            }

            if (ii.Obj != nullptr && ii.Obj->GetResourceURL().Compare(url) != 0)
            {
                if (Cast<UGButton>(ii.Obj))
                    ii.bSelected = ((UGButton*)ii.Obj)->IsSelected();
                RemoveChildToPool(ii.Obj);
                ii.Obj = nullptr;
            }
        }

        if (ii.Obj == nullptr)
        {
            if (forward)
            {
                for (int32 j = reuseIndex; j >= oldFirstIndex; j--)
                {
                    FItemInfo& ii2 = VirtualItems[j];
                    if (ii2.Obj != nullptr && ii2.UpdateFlag != ItemInfoVer && ii2.Obj->GetResourceURL().Compare(url) == 0)
                    {
                        if (Cast<UGButton>(ii2.Obj))
                            ii2.bSelected = ((UGButton*)ii2.Obj)->IsSelected();
                        ii.Obj = ii2.Obj;
                        ii2.Obj = nullptr;
                        if (j == reuseIndex)
                            reuseIndex--;
                        break;
                    }
                }
            }
            else
            {
                for (int32 j = reuseIndex; j <= lastIndex; j++)
                {
                    FItemInfo& ii2 = VirtualItems[j];
                    if (ii2.Obj != nullptr && ii2.UpdateFlag != ItemInfoVer && ii2.Obj->GetResourceURL().Compare(url) == 0)
                    {
                        if (Cast<UGButton>(ii2.Obj))
                            ii2.bSelected = ((UGButton*)ii2.Obj)->IsSelected();
                        ii.Obj = ii2.Obj;
                        ii2.Obj = nullptr;
                        if (j == reuseIndex)
                            reuseIndex++;
                        break;
                    }
                }
            }

            if (ii.Obj != nullptr)
            {
                SetChildIndex(ii.Obj, forward ? curIndex - newFirstIndex : NumChildren());
            }
            else
            {
                ii.Obj = Pool->GetObject(url, this);
                if (forward)
                    AddChildAt(ii.Obj, curIndex - newFirstIndex);
                else
                    AddChild(ii.Obj);
            }
            if (Cast<UGButton>(ii.Obj))
                ((UGButton*)ii.Obj)->SetSelected(ii.bSelected);

            needRender = true;
        }
        else
            needRender = forceUpdate;

        if (needRender)
        {
            if (bAutoResizeItem && (Layout == EListLayoutType::SingleColumn || ColumnCount > 0))
                ii.Obj->SetSize(FVector2D(partSize, ii.Obj->GetHeight()), true);

            ItemRenderer.ExecuteIfBound(curIndex % NumItems, ii.Obj);
            if (curIndex % CurLineItemCount == 0)
            {
                deltaSize += FMath::CeilToFloat(ii.Obj->GetHeight()) - ii.Size.Y;
                if (curIndex == newFirstIndex && oldFirstIndex > newFirstIndex)
                {
                    firstItemDeltaSize = FMath::CeilToFloat(ii.Obj->GetHeight()) - ii.Size.Y;
                }
            }
            ii.Size.X = FMath::CeilToFloat(ii.Obj->GetWidth());
            ii.Size.Y = FMath::CeilToFloat(ii.Obj->GetHeight());
        }

        ii.UpdateFlag = ItemInfoVer;
        ii.Obj->SetPosition(FVector2D(curX, curY));
        if (curIndex == newFirstIndex)
            max += ii.Size.Y;

        curX += ii.Size.X + ColumnGap;

        if (curIndex % CurLineItemCount == CurLineItemCount - 1)
        {
            curX = 0;
            curY += ii.Size.Y + LineGap;
        }
        curIndex++;
    }

    for (int32 i = 0; i < childCount; i++)
    {
        FItemInfo& ii = VirtualItems[oldFirstIndex + i];
        if (ii.UpdateFlag != ItemInfoVer && ii.Obj != nullptr)
        {
            if (Cast<UGButton>(ii.Obj))
                ii.bSelected = ((UGButton*)ii.Obj)->IsSelected();
            RemoveChildToPool(ii.Obj);
            ii.Obj = nullptr;
        }
    }

    childCount = Children.Num();
    for (int32 i = 0; i < childCount; i++)
    {
        UGObject* obj = VirtualItems[newFirstIndex + i].Obj;
        if (Children[i] != obj)
            SetChildIndex(obj, i);
    }

    if (deltaSize != 0 || firstItemDeltaSize != 0)
        ScrollPane->ChangeContentSizeOnScrolling(0, deltaSize, 0, firstItemDeltaSize);

    if (curIndex > 0 && NumChildren() > 0 && Container->GetPosition().Y <= 0 && GetChildAt(0)->GetY() > -Container->GetPosition().Y)
        return true;
    else
        return false;
}

bool UGList::HandleScroll2(bool forceUpdate)
{
    float pos = ScrollPane->GetScrollingPosX();
    float max = pos + ScrollPane->GetViewSize().X;
    bool end = pos == ScrollPane->GetContentSize().X;

    int32 newFirstIndex = GetIndexOnPos2(pos, forceUpdate);
    if (newFirstIndex == FirstIndex && !forceUpdate)
        return false;

    int32 oldFirstIndex = FirstIndex;
    FirstIndex = newFirstIndex;
    int32 curIndex = newFirstIndex;
    bool forward = oldFirstIndex > newFirstIndex;
    int32 childCount = NumChildren();
    int32 lastIndex = oldFirstIndex + childCount - 1;
    int32 reuseIndex = forward ? lastIndex : oldFirstIndex;
    float curX = pos, curY = 0;
    bool need
Download .txt
gitextract_s53mm5l5/

├── .gitignore
├── FairyGUI.uplugin
├── LICENSE
├── README.md
└── Source/
    ├── FairyGUI/
    │   ├── FairyGUI.Build.cs
    │   ├── Private/
    │   │   ├── Event/
    │   │   │   ├── EventContext.cpp
    │   │   │   └── EventTypes.cpp
    │   │   ├── FairyApplication.cpp
    │   │   ├── FairyBlueprintLibrary.cpp
    │   │   ├── FairyCommons.cpp
    │   │   ├── FairyGUIModule.cpp
    │   │   ├── Tween/
    │   │   │   ├── EaseManager.cpp
    │   │   │   ├── GPath.cpp
    │   │   │   ├── GTween.cpp
    │   │   │   ├── GTweener.cpp
    │   │   │   ├── TweenManager.cpp
    │   │   │   └── TweenValue.cpp
    │   │   ├── UI/
    │   │   │   ├── ControllerAction/
    │   │   │   │   ├── ChangePageAction.cpp
    │   │   │   │   ├── ControllerAction.cpp
    │   │   │   │   └── PlayTransitionAction.cpp
    │   │   │   ├── DragDropManager.cpp
    │   │   │   ├── GButton.cpp
    │   │   │   ├── GComboBox.cpp
    │   │   │   ├── GComponent.cpp
    │   │   │   ├── GController.cpp
    │   │   │   ├── GGraph.cpp
    │   │   │   ├── GGroup.cpp
    │   │   │   ├── GImage.cpp
    │   │   │   ├── GLabel.cpp
    │   │   │   ├── GList.cpp
    │   │   │   ├── GLoader.cpp
    │   │   │   ├── GLoader3D.cpp
    │   │   │   ├── GMovieClip.cpp
    │   │   │   ├── GObject.cpp
    │   │   │   ├── GObjectPool.cpp
    │   │   │   ├── GProgressBar.cpp
    │   │   │   ├── GRichTextField.cpp
    │   │   │   ├── GRoot.cpp
    │   │   │   ├── GScrollBar.cpp
    │   │   │   ├── GSlider.cpp
    │   │   │   ├── GTextField.cpp
    │   │   │   ├── GTextInput.cpp
    │   │   │   ├── GTree.cpp
    │   │   │   ├── GTreeNode.cpp
    │   │   │   ├── GWindow.cpp
    │   │   │   ├── Gears/
    │   │   │   │   ├── GearAnimation.cpp
    │   │   │   │   ├── GearBase.cpp
    │   │   │   │   ├── GearColor.cpp
    │   │   │   │   ├── GearDisplay.cpp
    │   │   │   │   ├── GearDisplay2.cpp
    │   │   │   │   ├── GearFontSize.cpp
    │   │   │   │   ├── GearIcon.cpp
    │   │   │   │   ├── GearLook.cpp
    │   │   │   │   ├── GearSize.cpp
    │   │   │   │   ├── GearText.cpp
    │   │   │   │   └── GearXY.cpp
    │   │   │   ├── PackageItem.cpp
    │   │   │   ├── PopupMenu.cpp
    │   │   │   ├── RelationItem.cpp
    │   │   │   ├── Relations.cpp
    │   │   │   ├── ScrollPane.cpp
    │   │   │   ├── Transition.cpp
    │   │   │   ├── TranslationHelper.cpp
    │   │   │   ├── UIConfig.cpp
    │   │   │   ├── UIObjectFactory.cpp
    │   │   │   └── UIPackage.cpp
    │   │   ├── UIPackageAsset.cpp
    │   │   ├── Utils/
    │   │   │   ├── ByteBuffer.cpp
    │   │   │   ├── HTMLElement.cpp
    │   │   │   ├── HTMLParser.cpp
    │   │   │   ├── NVariant.cpp
    │   │   │   ├── UBBParser.cpp
    │   │   │   ├── XMLAttributes.cpp
    │   │   │   └── XMLIterator.cpp
    │   │   └── Widgets/
    │   │       ├── BitmapFont.cpp
    │   │       ├── BitmapFontRun.cpp
    │   │       ├── HitTest.cpp
    │   │       ├── LoaderRun.cpp
    │   │       ├── Mesh/
    │   │       │   ├── EllipseMesh.cpp
    │   │       │   ├── FillMesh.cpp
    │   │       │   ├── MeshFactory.cpp
    │   │       │   ├── PolygonMesh.cpp
    │   │       │   ├── RectMesh.cpp
    │   │       │   ├── RegularPolygonMesh.cpp
    │   │       │   ├── RoundedMesh.cpp
    │   │       │   └── VertexHelper.cpp
    │   │       ├── NGraphics.cpp
    │   │       ├── NTextFormat.cpp
    │   │       ├── NTexture.cpp
    │   │       ├── SContainer.cpp
    │   │       ├── SDisplayObject.cpp
    │   │       ├── SFImage.cpp
    │   │       ├── SMovieClip.cpp
    │   │       ├── SShape.cpp
    │   │       ├── STextField.cpp
    │   │       └── STextInput.cpp
    │   └── Public/
    │       ├── Event/
    │       │   ├── EventContext.h
    │       │   └── EventTypes.h
    │       ├── FairyApplication.h
    │       ├── FairyBlueprintLibrary.h
    │       ├── FairyCommons.h
    │       ├── FairyGUI.h
    │       ├── FairyGUIModule.h
    │       ├── Tween/
    │       │   ├── EaseManager.h
    │       │   ├── EaseType.h
    │       │   ├── GPath.h
    │       │   ├── GTween.h
    │       │   ├── GTweener.h
    │       │   ├── TweenManager.h
    │       │   ├── TweenValue.h
    │       │   └── TweenerHandle.h
    │       ├── UI/
    │       │   ├── ControllerAction/
    │       │   │   ├── ChangePageAction.h
    │       │   │   ├── ControllerAction.h
    │       │   │   └── PlayTransitionAction.h
    │       │   ├── DragDropManager.h
    │       │   ├── FieldTypes.h
    │       │   ├── GButton.h
    │       │   ├── GComboBox.h
    │       │   ├── GComponent.h
    │       │   ├── GController.h
    │       │   ├── GGraph.h
    │       │   ├── GGroup.h
    │       │   ├── GImage.h
    │       │   ├── GLabel.h
    │       │   ├── GList.h
    │       │   ├── GLoader.h
    │       │   ├── GLoader3D.h
    │       │   ├── GMovieClip.h
    │       │   ├── GObject.h
    │       │   ├── GObjectPool.h
    │       │   ├── GProgressBar.h
    │       │   ├── GRichTextField.h
    │       │   ├── GRoot.h
    │       │   ├── GScrollBar.h
    │       │   ├── GSlider.h
    │       │   ├── GTextField.h
    │       │   ├── GTextInput.h
    │       │   ├── GTree.h
    │       │   ├── GTreeNode.h
    │       │   ├── GWindow.h
    │       │   ├── Gears/
    │       │   │   ├── GearAnimation.h
    │       │   │   ├── GearBase.h
    │       │   │   ├── GearColor.h
    │       │   │   ├── GearDisplay.h
    │       │   │   ├── GearDisplay2.h
    │       │   │   ├── GearFontSize.h
    │       │   │   ├── GearIcon.h
    │       │   │   ├── GearLook.h
    │       │   │   ├── GearSize.h
    │       │   │   ├── GearText.h
    │       │   │   └── GearXY.h
    │       │   ├── PackageItem.h
    │       │   ├── PopupMenu.h
    │       │   ├── RelationItem.h
    │       │   ├── Relations.h
    │       │   ├── ScrollPane.h
    │       │   ├── Transition.h
    │       │   ├── TranslationHelper.h
    │       │   ├── UIConfig.h
    │       │   ├── UIObjectFactory.h
    │       │   └── UIPackage.h
    │       ├── UIPackageAsset.h
    │       ├── Utils/
    │       │   ├── ByteBuffer.h
    │       │   ├── HTMLElement.h
    │       │   ├── HTMLParser.h
    │       │   ├── NVariant.h
    │       │   ├── UBBParser.h
    │       │   ├── XMLAttributes.h
    │       │   └── XMLIterator.h
    │       └── Widgets/
    │           ├── BitmapFont.h
    │           ├── BitmapFontRun.h
    │           ├── HitTest.h
    │           ├── LoaderRun.h
    │           ├── Mesh/
    │           │   ├── EllipseMesh.h
    │           │   ├── FillMesh.h
    │           │   ├── MeshFactory.h
    │           │   ├── PolygonMesh.h
    │           │   ├── RectMesh.h
    │           │   ├── RegularPolygonMesh.h
    │           │   ├── RoundedRectMesh.h
    │           │   └── VertexHelper.h
    │           ├── MeshFactory.h
    │           ├── NGraphics.h
    │           ├── NTextFormat.h
    │           ├── NTexture.h
    │           ├── SContainer.h
    │           ├── SDisplayObject.h
    │           ├── SFImage.h
    │           ├── SMovieClip.h
    │           ├── SShape.h
    │           ├── STextField.h
    │           └── STextInput.h
    └── FairyGUIEditor/
        ├── FairyGUIEditor.Build.cs
        ├── Private/
        │   ├── FairyGUIEditor.cpp
        │   └── FairyGUIFactory.cpp
        └── Public/
            ├── FairyGUIEditor.h
            └── FairyGUIFactory.h
Download .txt
SYMBOL INDEX (477 symbols across 139 files)

FILE: Source/FairyGUI/FairyGUI.Build.cs
  class FairyGUI (line 5) | public class FairyGUI : ModuleRules
    method FairyGUI (line 7) | public FairyGUI(ReadOnlyTargetRules Target) : base(Target)

FILE: Source/FairyGUI/Private/FairyApplication.cpp
  type FMyScopedSwitchWorldHack (line 18) | struct FMyScopedSwitchWorldHack
    method FMyScopedSwitchWorldHack (line 20) | FMyScopedSwitchWorldHack(UWorld* World)
  function UFairyApplication (line 71) | UFairyApplication* UFairyApplication::Get(UObject* WorldContextObject)
  function UGRoot (line 143) | UGRoot* UFairyApplication::GetUIRoot() const
  function FVector2D (line 178) | FVector2D UFairyApplication::GetTouchPosition(int32 InUserIndex, int32 I...
  function int32 (line 187) | int32 UFairyApplication::GetTouchCount() const
  function UGObject (line 199) | UGObject* UFairyApplication::GetObjectUnderPoint(const FVector2D& Screen...
  function UEventContext (line 316) | UEventContext* UFairyApplication::BorrowEventContext()
  function FReply (line 462) | FReply UFairyApplication::OnWidgetMouseButtonDown(const TSharedRef<SWidg...
  function FReply (line 491) | FReply UFairyApplication::OnWidgetMouseButtonUp(const TSharedRef<SWidget...
  function FReply (line 534) | FReply UFairyApplication::OnWidgetMouseMove(const TSharedRef<SWidget>& W...
  function FReply (line 539) | FReply UFairyApplication::OnWidgetMouseButtonDoubleClick(const TSharedRe...
  function FReply (line 563) | FReply UFairyApplication::OnWidgetMouseWheel(const TSharedRef<SWidget>& ...

FILE: Source/FairyGUI/Private/FairyBlueprintLibrary.cpp
  function FUIConfig (line 6) | const FUIConfig& UFairyBlueprintLibrary::GetUIConfig()
  function int32 (line 21) | int32 UFairyBlueprintLibrary::GetVariantAsInt(UPARAM(ref) FNVariant& InV...
  function FString (line 31) | FString UFairyBlueprintLibrary::GetVariantAsString(UPARAM(ref) FNVariant...
  function FColor (line 36) | FColor UFairyBlueprintLibrary::GetVariantAsColor(UPARAM(ref) FNVariant& ...
  function FTweenerHandle (line 82) | FTweenerHandle UFairyBlueprintLibrary::TweenFloat(float StartValue, floa...
  function FTweenerHandle (line 114) | FTweenerHandle UFairyBlueprintLibrary::TweenVector2(const FVector2D& Sta...

FILE: Source/FairyGUI/Private/Tween/EaseManager.cpp
  class Bounce (line 6) | class Bounce

FILE: Source/FairyGUI/Private/Tween/GPath.cpp
  function FVector (line 136) | FVector FGPath::GetPointAt(float Time)
  function repeat (line 240) | static float repeat(float t, float length)
  function FVector (line 245) | FVector FGPath::OnCRSplineCurve(int32 PointStart, int32 PointCount, floa...
  function FVector (line 270) | FVector FGPath::OnBezierCurve(int32 PointStart, int32 PointCount, float ...

FILE: Source/FairyGUI/Private/Tween/GTween.cpp
  function FGTweener (line 5) | FGTweener* FGTween::To(float StartValue, float EndValue, float Duration)
  function FGTweener (line 10) | FGTweener* FGTween::To(const FVector2D& StartValue, const FVector2D & En...
  function FGTweener (line 15) | FGTweener* FGTween::To(const FVector& StartValue, const FVector & EndVal...
  function FGTweener (line 20) | FGTweener* FGTween::To(const FVector4& StartValue, const FVector4 & EndV...
  function FGTweener (line 25) | FGTweener* FGTween::To(const FColor& StartValue, const FColor & EndValue...
  function FGTweener (line 30) | FGTweener* FGTween::ToDouble(double StartValue, double EndValue, float D...
  function FGTweener (line 35) | FGTweener* FGTween::DelayedCall(float Delay)
  function FGTweener (line 40) | FGTweener* FGTween::Shake(const FVector2D& StartValue, float Amplitude, ...
  function FGTweener (line 65) | FGTweener* FGTween::GetTween(const FTweenerHandle& Handle)
  function FGTweener (line 70) | FGTweener* FGTween::GetTween(UObject * Target)

FILE: Source/FairyGUI/Private/Tween/GTweener.cpp
  function FGTweener (line 14) | FGTweener* FGTweener::SetDelay(float InValue)
  function FGTweener (line 20) | FGTweener* FGTweener::SetDuration(float InValue)
  function FGTweener (line 26) | FGTweener* FGTweener::SetBreakpoint(float InValue)
  function FGTweener (line 32) | FGTweener* FGTweener::SetEase(EEaseType InValue)
  function FGTweener (line 38) | FGTweener* FGTweener::SetEasePeriod(float InValue)
  function FGTweener (line 44) | FGTweener* FGTweener::SetEaseOvershootOrAmplitude(float InValue)
  function FGTweener (line 50) | FGTweener* FGTweener::SetRepeat(int32 InRepeat, bool bInYoyo)
  function FGTweener (line 57) | FGTweener* FGTweener::SetTimeScale(float InValue)
  function FGTweener (line 63) | FGTweener* FGTweener::SetSnapping(bool bInValue)
  function FGTweener (line 69) | FGTweener* FGTweener::SetTarget(UObject* InTarget)
  function FGTweener (line 75) | FGTweener* FGTweener::SetUserData(const FNVariant& InData)
  function FGTweener (line 81) | FGTweener* FGTweener::SetPath(TSharedPtr<FGPath> InPath)
  function FGTweener (line 87) | FGTweener* FGTweener::OnUpdate(FTweenDelegate Callback)
  function FGTweener (line 93) | FGTweener* FGTweener::OnStart(FTweenDelegate Callback)
  function FGTweener (line 99) | FGTweener* FGTweener::OnComplete(FTweenDelegate Callback)
  function FGTweener (line 105) | FGTweener* FGTweener::OnUpdate(FSimpleDelegate Callback)
  function FGTweener (line 113) | FGTweener* FGTweener::OnStart(FSimpleDelegate Callback)
  function FGTweener (line 121) | FGTweener* FGTweener::OnComplete(FSimpleDelegate Callback)
  function FGTweener (line 129) | FGTweener* FGTweener::SetPaused(bool bInPaused)
  function FGTweener (line 176) | FGTweener* FGTweener::To(float InStart, float InEnd, float InDuration)
  function FGTweener (line 186) | FGTweener* FGTweener::To(const FVector2D& InStart, const FVector2D& InEn...
  function FGTweener (line 196) | FGTweener* FGTweener::To(const FVector& InStart, const FVector& InEnd, f...
  function FGTweener (line 206) | FGTweener* FGTweener::To(const FVector4& InStart, const FVector4& InEnd,...
  function FGTweener (line 216) | FGTweener* FGTweener::To(const FColor& InStart, const FColor& InEnd, flo...
  function FGTweener (line 226) | FGTweener* FGTweener::To(double InStart, double InEnd, float InDuration)
  function FGTweener (line 236) | FGTweener* FGTweener::Shake(const FVector2D& InStart, float InAmplitude,...

FILE: Source/FairyGUI/Private/Tween/TweenManager.cpp
  function FGTweener (line 35) | FGTweener* FTweenManager::CreateTween()
  function FGTweener (line 108) | FGTweener* FTweenManager::GetTween(FTweenerHandle const& Handle)
  function FGTweener (line 126) | FGTweener* FTweenManager::GetTween(UObject* Target)

FILE: Source/FairyGUI/Private/Tween/TweenValue.cpp
  function FVector2D (line 7) | FVector2D FTweenValue::GetVec2() const
  function FVector (line 18) | FVector FTweenValue::GetVec3() const
  function FVector4 (line 30) | FVector4 FTweenValue::GetVec4() const
  function FColor (line 43) | FColor FTweenValue::GetColor() const

FILE: Source/FairyGUI/Private/UI/ControllerAction/ControllerAction.cpp
  function FControllerAction (line 6) | FControllerAction * FControllerAction::CreateAction(int32 ActionType)

FILE: Source/FairyGUI/Private/UI/GButton.cpp
  function FString (line 35) | const FString& UGButton::GetIcon() const
  function FColor (line 64) | FColor UGButton::GetTitleColor() const
  function int32 (line 83) | int32 UGButton::GetTitleFontSize() const
  function UGTextField (line 207) | UGTextField * UGButton::GetTextField() const
  function FNVariant (line 219) | FNVariant UGButton::GetProp(EObjectPropID PropID) const

FILE: Source/FairyGUI/Private/UI/GComboBox.cpp
  function FString (line 23) | const FString& UGComboBox::GetText() const
  function FString (line 38) | const FString& UGComboBox::GetIcon() const
  function FColor (line 53) | FColor UGComboBox::GetTitleColor() const
  function int32 (line 72) | int32 UGComboBox::GetTitleFontSize() const
  function FString (line 91) | const FString& UGComboBox::GetValue() const
  function UGTextField (line 237) | UGTextField* UGComboBox::GetTextField() const
  function FNVariant (line 249) | FNVariant UGComboBox::GetProp(EObjectPropID PropID) const

FILE: Source/FairyGUI/Private/UI/GComponent.cpp
  function UGObject (line 33) | UGObject* UGComponent::AddChild(UGObject* Child)
  function UGObject (line 39) | UGObject* UGComponent::AddChildAt(UGObject* Child, int32 Index)
  function int32 (line 76) | int32 UGComponent::GetInsertPosForSortingChild(UGObject* Child)
  function UGObject (line 133) | UGObject* UGComponent::GetChildAt(int32 Index, TSubclassOf<UGObject> Cla...
  function UGObject (line 140) | UGObject* UGComponent::GetChild(const FString& ChildName, TSubclassOf<UG...
  function UGObject (line 151) | UGObject* UGComponent::GetChildByPath(const FString& Path, TSubclassOf<U...
  function UGObject (line 184) | UGObject* UGComponent::GetChildInGroup(const UGGroup* InGroup, const FSt...
  function UGObject (line 197) | UGObject* UGComponent::GetChildByID(const FString& ChildID) const
  function int32 (line 208) | int32 UGComponent::GetChildIndex(const UGObject* Child) const
  function int32 (line 258) | int32 UGComponent::MoveChild(UGObject* Child, int32 OldIndex, int32 Index)
  function int32 (line 328) | int32 UGComponent::NumChildren() const
  function int32 (line 363) | int32 UGComponent::GetFirstChildInView() const
  function UGController (line 376) | UGController* UGComponent::GetController(const FString& ControllerName) ...
  function UGController (line 394) | UGController* UGComponent::GetControllerAt(int32 Index) const
  function UTransition (line 430) | UTransition* UGComponent::GetTransition(const FString& TransitionName) c...
  function UTransition (line 441) | UTransition* UGComponent::GetTransitionAt(int32 Index) const
  function FVector2D (line 762) | FVector2D UGComponent::GetSnappingPosition(const FVector2D& InPoint)

FILE: Source/FairyGUI/Private/UI/GController.cpp
  function FString (line 40) | const FString& UGController::GetSelectedPage() const
  function FString (line 61) | const FString& UGController::GetSelectedPageID() const
  function FString (line 76) | const FString& UGController::GetPreviousPage() const
  function FString (line 84) | const FString& UGController::GetPreviousPageID() const
  function int32 (line 92) | int32 UGController::GetPageCount() const
  function int32 (line 102) | int32 UGController::GetPageIndexByID(const FString& PageID) const
  function FString (line 107) | const FString& UGController::GetPageNameByID(const FString& PageID) const
  function FString (line 116) | const FString& UGController::GetPageID(int32 Index) const

FILE: Source/FairyGUI/Private/UI/GGraph.cpp
  function FColor (line 22) | FColor UGGraph::GetColor() const
  function IHitTest (line 114) | IHitTest* UGGraph::GetHitArea() const
  function FNVariant (line 123) | FNVariant UGGraph::GetProp(EObjectPropID PropID) const

FILE: Source/FairyGUI/Private/UI/GImage.cpp
  function EFlipType (line 20) | EFlipType UGImage::GetFlip() const
  function FColor (line 30) | FColor UGImage::GetColor() const
  function EFillMethod (line 40) | EFillMethod UGImage::GetFillMethod() const
  function int32 (line 50) | int32 UGImage::GetFillOrigin() const
  function FNVariant (line 80) | FNVariant UGImage::GetProp(EObjectPropID PropID) const

FILE: Source/FairyGUI/Private/UI/GLabel.cpp
  function FString (line 15) | const FString& UGLabel::GetText() const
  function FString (line 30) | const FString& UGLabel::GetIcon() const
  function FColor (line 45) | FColor UGLabel::GetTitleColor() const
  function int32 (line 64) | int32 UGLabel::GetTitleFontSize() const
  function UGTextField (line 83) | UGTextField * UGLabel::GetTextField() const
  function FNVariant (line 95) | FNVariant UGLabel::GetProp(EObjectPropID PropID) const

FILE: Source/FairyGUI/Private/UI/GList.cpp
  function UGObject (line 136) | UGObject* UGList::GetFromPool()
  function UGObject (line 141) | UGObject* UGList::GetFromPool(const FString& URL)
  function UGObject (line 158) | UGObject* UGList::AddItemFromPool(const FString& URL)
  function UGObject (line 165) | UGObject* UGList::AddChildAt(UGObject* Child, int32 Index)
  function int32 (line 209) | int32 UGList::GetSelectedIndex() const
  function int32 (line 790) | int32 UGList::GetFirstChildInView() const
  function int32 (line 882) | int32 UGList::ChildIndexToItemIndex(int32 Index) const
  function int32 (line 911) | int32 UGList::ItemIndexToChildIndex(int32 Index) const
  function int32 (line 993) | int32 UGList::GetNumItems() const
  function FVector2D (line 1068) | FVector2D UGList::GetSnappingPosition(const FVector2D& InPoint)
  function int32 (line 1230) | int32 UGList::GetIndexOnPos1(float& pos, bool forceUpdate)
  function int32 (line 1294) | int32 UGList::GetIndexOnPos2(float& pos, bool forceUpdate)
  function int32 (line 1358) | int32 UGList::GetIndexOnPos3(float& pos, bool forceUpdate)

FILE: Source/FairyGUI/Private/UI/GLoader.cpp
  function EFlipType (line 82) | EFlipType UGLoader::GetFlip() const
  function FColor (line 92) | FColor UGLoader::GetColor() const
  function EFillMethod (line 102) | EFillMethod UGLoader::GetFillMethod() const
  function int32 (line 112) | int32 UGLoader::GetFillOrigin() const
  function FNVariant (line 381) | FNVariant UGLoader::GetProp(EObjectPropID PropID) const

FILE: Source/FairyGUI/Private/UI/GLoader3D.cpp
  function FColor (line 33) | FColor UGLoader3D::GetColor() const
  function FNVariant (line 186) | FNVariant UGLoader3D::GetProp(EObjectPropID PropID) const

FILE: Source/FairyGUI/Private/UI/GMovieClip.cpp
  function int32 (line 35) | int32 UGMovieClip::GetFrame() const
  function EFlipType (line 60) | EFlipType UGMovieClip::GetFlip() const
  function FColor (line 70) | FColor UGMovieClip::GetColor() const
  function FNVariant (line 80) | FNVariant UGMovieClip::GetProp(EObjectPropID PropID) const

FILE: Source/FairyGUI/Private/UI/GObject.cpp
  function FString (line 322) | const FString& UGObject::GetText() const
  function FString (line 331) | const FString& UGObject::GetIcon() const
  function FBox2D (line 369) | FBox2D UGObject::GetDragBounds() const
  function FString (line 395) | FString UGObject::GetResourceURL() const
  function FString (line 403) | FString UGObject::GetResourceName() const
  function FString (line 411) | FString UGObject::GetPackageName() const
  function FVector2D (line 419) | FVector2D UGObject::LocalToGlobal(const FVector2D& InPoint)
  function FBox2D (line 428) | FBox2D UGObject::LocalToGlobalRect(const FBox2D& InRect)
  function FVector2D (line 435) | FVector2D UGObject::LocalToRoot(const FVector2D& InPoint)
  function FBox2D (line 440) | FBox2D UGObject::LocalToRootRect(const FBox2D& InRect)
  function FVector2D (line 445) | FVector2D UGObject::GlobalToLocal(const FVector2D& InPoint)
  function FBox2D (line 453) | FBox2D UGObject::GlobalToLocalRect(const FBox2D& InRect)
  function FVector2D (line 460) | FVector2D UGObject::RootToLocal(const FVector2D& InPoint)
  function FBox2D (line 465) | FBox2D UGObject::RootToLocalRect(const FBox2D& InRect)
  function uint32 (line 512) | uint32 UGObject::AddDisplayLock()
  function UGRoot (line 582) | UGRoot* UGObject::GetUIRoot() const
  function UFairyApplication (line 587) | UFairyApplication* UGObject::GetApp() const
  function UWorld (line 595) | UWorld* UGObject::GetWorld() const
  function UGObject (line 603) | UGObject* UGObject::CastTo(TSubclassOf<UGObject> ClassType) const
  function FNVariant (line 608) | FNVariant UGObject::GetProp(EObjectPropID PropID) const
  function FGUIEventMDelegate (line 676) | FGUIEventMDelegate& UGObject::On(const FName& EventType)

FILE: Source/FairyGUI/Private/UI/GObjectPool.cpp
  function UGObject (line 5) | UGObject* FGObjectPool::GetObject(const FString & URL, UObject* WorldCon...

FILE: Source/FairyGUI/Private/UI/GRoot.cpp
  class SRootContainer (line 13) | class SRootContainer : public SContainer
  function UGRoot (line 19) | UGRoot* UGRoot::Get(UObject* WorldContextObject)
  function UGWindow (line 110) | UGWindow* UGRoot::GetTopWindow() const
  function UGGraph (line 125) | UGGraph* UGRoot::GetModalLayer()
  function UGObject (line 186) | UGObject* UGRoot::GetModalWaitingPane()
  function FVector2D (line 335) | FVector2D UGRoot::GetPoupPosition(UGObject* Popup, UGObject* AtObject, E...

FILE: Source/FairyGUI/Private/UI/GTextField.cpp
  function EAutoSizeType (line 56) | EAutoSizeType UGTextField::GetAutoSize() const
  function FNTextFormat (line 76) | FNTextFormat& UGTextField::GetTextFormat()
  function FVector2D (line 94) | FVector2D UGTextField::GetTextSize()
  function UGTextField (line 105) | UGTextField* UGTextField::SetVar(const FString& VarKey, const FString& V...
  function FString (line 119) | FString UGTextField::ParseTemplate(const FString& Template)
  function FNVariant (line 174) | FNVariant UGTextField::GetProp(EObjectPropID PropID) const

FILE: Source/FairyGUI/Private/UI/GTextInput.cpp
  function FNVariant (line 85) | FNVariant UGTextInput::GetProp(EObjectPropID PropID) const

FILE: Source/FairyGUI/Private/UI/GTree.cpp
  function UGTreeNode (line 21) | UGTreeNode* UGTree::GetSelectedNode() const
  function int32 (line 125) | int32 UGTree::GetInsertIndexForNode(UGTreeNode* Node)
  function int32 (line 229) | int32 UGTree::GetFolderEndIndex(int32 StartIndex, int32 Level)
  function int32 (line 242) | int32 UGTree::CheckChildren(UGTreeNode* FolderNode, int32 Index)

FILE: Source/FairyGUI/Private/UI/GTreeNode.cpp
  function UGTreeNode (line 5) | UGTreeNode* UGTreeNode::CreateNode(bool bIsFolder, const FString& Resour...
  function FString (line 51) | const FString& UGTreeNode::GetText() const
  function FString (line 65) | const FString& UGTreeNode::GetIcon() const
  function UGTreeNode (line 79) | UGTreeNode* UGTreeNode::AddChild(UGTreeNode* Child)
  function UGTreeNode (line 85) | UGTreeNode* UGTreeNode::AddChildAt(UGTreeNode* Child, int32 Index)
  function UGTreeNode (line 147) | UGTreeNode* UGTreeNode::GetChildAt(int32 Index) const
  function UGTreeNode (line 154) | UGTreeNode* UGTreeNode::GetPrevSibling() const
  function UGTreeNode (line 166) | UGTreeNode* UGTreeNode::GetNextSibling() const
  function int32 (line 178) | int32 UGTreeNode::GetChildIndex(const UGTreeNode* Child) const
  function int32 (line 227) | int32 UGTreeNode::NumChildren() const

FILE: Source/FairyGUI/Private/UI/GWindow.cpp
  function UGWindow (line 6) | UGWindow* UGWindow::CreateWindow(const FString& PackageName, const FStri...

FILE: Source/FairyGUI/Private/UI/Gears/GearBase.cpp
  function FGearTweenConfig (line 84) | FGearTweenConfig& FGearBase::GetTweenConfig()

FILE: Source/FairyGUI/Private/UI/Gears/GearDisplay.cpp
  function uint32 (line 47) | uint32 FGearDisplay::AddLock()

FILE: Source/FairyGUI/Private/UI/PopupMenu.cpp
  function UPopupMenu (line 8) | UPopupMenu* UPopupMenu::CreatePopupMenu(const FString& ResourceURL, UObj...
  function UGButton (line 49) | UGButton* UPopupMenu::AddItem(const FString& Caption, FGUIEventDelegate ...
  function UGButton (line 64) | UGButton* UPopupMenu::AddItem(const FString& Caption, const FGUIEventDyn...
  function UGButton (line 71) | UGButton* UPopupMenu::AddItemAt(const FString& Caption, int32 Index, FGU...
  function UGButton (line 87) | UGButton* UPopupMenu::AddItemAt(const FString& Caption, int32 index, con...
  function FString (line 105) | const FString& UPopupMenu::GetItemName(int32 Index) const
  function int32 (line 190) | int32 UPopupMenu::GetItemCount() const

FILE: Source/FairyGUI/Private/UI/ScrollPane.cpp
  function sp_EaseFunc (line 21) | static inline float sp_EaseFunc(float t, float d)
  function int32 (line 373) | int32 UScrollPane::GetPageX() const
  function int32 (line 396) | int32 UScrollPane::GetPageY() const
  function FVector2D (line 1089) | FVector2D UScrollPane::UpdateTargetAndDuration(const FVector2D& OrignPos)

FILE: Source/FairyGUI/Private/UI/Transition.cpp
  type FAniData (line 12) | struct FAniData
  type FSoundData (line 19) | struct FSoundData
  type FInnerTransData (line 25) | struct FInnerTransData
  type FShakeData (line 33) | struct FShakeData
  type FTransitionItemData (line 41) | struct FTransitionItemData
  function FVector2D (line 67) | FVector2D FTransitionItemData::GetVec2() const
  function FVector4 (line 78) | FVector4 FTransitionItemData::GetVec4() const
  function FColor (line 91) | FColor FTransitionItemData::GetColor() const
  type FTweenConfig (line 104) | struct FTweenConfig
  type FTransitionItem (line 126) | struct FTransitionItem

FILE: Source/FairyGUI/Private/UI/UIObjectFactory.cpp
  function UGObject (line 48) | UGObject* FUIObjectFactory::NewObject(const TSharedPtr<FPackageItem>& Pa...
  function UGObject (line 61) | UGObject* FUIObjectFactory::NewObject(EObjectType Type, UObject* Outer)

FILE: Source/FairyGUI/Private/UI/UIPackage.cpp
  type FAtlasSprite (line 14) | struct FAtlasSprite
    method FAtlasSprite (line 16) | FAtlasSprite() :
  function FString (line 30) | const FString& UUIPackage::GetBranch()
  function FString (line 49) | FString UUIPackage::GetVar(const FString& VarKey)
  function UUIPackage (line 63) | UUIPackage* UUIPackage::AddPackage(const TCHAR* InAssetPath, UObject* Wo...
  function UUIPackage (line 71) | UUIPackage* UUIPackage::AddPackage(UUIPackageAsset* InAsset, UObject* Wo...
  function UUIPackage (line 141) | UUIPackage* UUIPackage::GetPackageByID(const FString& PackageID)
  function UUIPackage (line 150) | UUIPackage* UUIPackage::GetPackageByName(const FString& PackageName)
  function UGObject (line 159) | UGObject* UUIPackage::CreateObject(const FString& PackageName, const FSt...
  function UGObject (line 168) | UGObject* UUIPackage::CreateObjectFromURL(const FString& URL, UObject* W...
  function FString (line 177) | FString UUIPackage::GetItemURL(const FString& PackageName, const FString...
  function FString (line 225) | FString UUIPackage::NormalizeURL(const FString& URL)
  function UGObject (line 274) | UGObject* UUIPackage::CreateObject(const FString& ResourceName, UObject*...
  function UGObject (line 282) | UGObject* UUIPackage::CreateObject(const TSharedPtr<FPackageItem>& Item,...
  function UUIPackageStatic (line 751) | UUIPackageStatic& UUIPackageStatic::Get()

FILE: Source/FairyGUI/Private/Utils/ByteBuffer.cpp
  function int32 (line 20) | int32 FByteBuffer::GetBytesAvailable() const
  function int8 (line 25) | int8 FByteBuffer::ReadByte()
  function uint8 (line 34) | uint8 FByteBuffer::ReadUbyte()
  function int16 (line 46) | int16 FByteBuffer::ReadShort()
  function uint16 (line 57) | uint16 FByteBuffer::ReadUshort()
  function int32 (line 62) | int32 FByteBuffer::ReadInt()
  function uint32 (line 73) | uint32 FByteBuffer::ReadUint()
  function FString (line 84) | FString FByteBuffer::ReadString()
  function FString (line 90) | FString FByteBuffer::ReadString(int32 InLen)
  function FString (line 104) | const FString& FByteBuffer::ReadS()
  function FString (line 130) | const FString* FByteBuffer::ReadSP()
  function FColor (line 154) | FColor FByteBuffer::ReadColor()

FILE: Source/FairyGUI/Private/Utils/HTMLParser.cpp
  type SupportedTagNames (line 4) | enum class SupportedTagNames {

FILE: Source/FairyGUI/Private/Utils/NVariant.cpp
  function FNVariant (line 53) | FNVariant& FNVariant::operator= (const FNVariant& other)
  function FNVariant (line 60) | FNVariant& FNVariant::operator= (FNVariant&& other)
  function FNVariant (line 67) | FNVariant& FNVariant::operator= (bool bValue)
  function FNVariant (line 73) | FNVariant& FNVariant::operator= (int32 Value)
  function FNVariant (line 79) | FNVariant& FNVariant::operator= (float Value)
  function FNVariant (line 85) | FNVariant& FNVariant::operator= (const FString& Value)
  function FNVariant (line 91) | FNVariant& FNVariant::operator= (const FColor& Value)
  function FNVariant (line 97) | FNVariant& FNVariant::operator= (void* Value)

FILE: Source/FairyGUI/Private/Utils/UBBParser.cpp
  function FString (line 34) | FString FUBBParser::Parse(const FString& Text, bool bRemove)
  function FString (line 116) | FString FUBBParser::GetTagText(bool bRemove)
  function FString (line 144) | FString FUBBParser::OnTag_URL(const FString& TagName, bool bEnd, const F...
  function FString (line 160) | FString FUBBParser::OnTag_IMG(const FString& TagName, bool bEnd, const F...
  function FString (line 177) | FString FUBBParser::OnTag_Simple(const FString& TagName, bool bEnd, cons...
  function FString (line 182) | FString FUBBParser::OnTag_COLOR(const FString& TagName, bool bEnd, const...
  function FString (line 192) | FString FUBBParser::OnTag_FONT(const FString& TagName, bool bEnd, const ...
  function FString (line 200) | FString FUBBParser::OnTag_SIZE(const FString& TagName, bool bEnd, const ...
  function FString (line 210) | FString FUBBParser::OnTag_ALIGN(const FString& TagName, bool bEnd, const...

FILE: Source/FairyGUI/Private/Utils/XMLAttributes.cpp
  function FString (line 5) | const FString& FXMLAttributes::Get(const FString& AttrName, const FStrin...
  function int32 (line 14) | int32 FXMLAttributes::GetInt(const FString& AttrName, int32 DefaultValue)
  function FColor (line 41) | FColor FXMLAttributes::GetColor(const FString& AttrName, const FColor& D...

FILE: Source/FairyGUI/Private/Utils/XMLIterator.cpp
  function FString (line 156) | FString FXMLIterator::GetTagSource() const
  function FString (line 161) | FString FXMLIterator::GetRawText(bool bTrim) const
  function FString (line 185) | FString FXMLIterator::GetText(bool bTrim) const
  function FString (line 339) | FString FXMLIterator::DecodeString(const FString& InSource)

FILE: Source/FairyGUI/Private/Widgets/BitmapFontRun.cpp
  function int32 (line 42) | int32 FBitmapFontRun::GetTextIndexAt(const TSharedRef< ILayoutBlock >& B...
  function FVector2D (line 77) | FVector2D FBitmapFontRun::GetLocationAt(const TSharedRef< ILayoutBlock >...
  function int32 (line 82) | int32 FBitmapFontRun::OnPaint(const FPaintArgs& Args, const FTextLayout:...
  function int8 (line 113) | int8 FBitmapFontRun::GetKerning(int32 CurrentIndex, float Scale, const F...
  function FVector2D (line 118) | FVector2D FBitmapFontRun::Measure(int32 BeginIndex, int32 EndIndex, floa...
  function int16 (line 128) | int16 FBitmapFontRun::GetMaxHeight(float Scale) const
  function int16 (line 136) | int16 FBitmapFontRun::GetBaseLine(float Scale) const
  function FTextRange (line 141) | FTextRange FBitmapFontRun::GetTextRange() const
  function FRunInfo (line 177) | const FRunInfo& FBitmapFontRun::GetRunInfo() const
  function ERunAttributes (line 183) | ERunAttributes FBitmapFontRun::GetRunAttributes() const

FILE: Source/FairyGUI/Private/Widgets/LoaderRun.cpp
  function int32 (line 65) | int32 FLoaderRun::GetTextIndexAt(const TSharedRef< ILayoutBlock >& Block...
  function FVector2D (line 100) | FVector2D FLoaderRun::GetLocationAt(const TSharedRef< ILayoutBlock >& Bl...
  function int32 (line 105) | int32 FLoaderRun::OnPaint(const FPaintArgs& Args, const FTextLayout::FLi...
  function int8 (line 117) | int8 FLoaderRun::GetKerning(int32 CurrentIndex, float Scale, const FRunT...
  function FVector2D (line 122) | FVector2D FLoaderRun::Measure(int32 BeginIndex, int32 EndIndex, float Sc...
  function int16 (line 132) | int16 FLoaderRun::GetMaxHeight(float Scale) const
  function int16 (line 137) | int16 FLoaderRun::GetBaseLine(float Scale) const
  function FTextRange (line 142) | FTextRange FLoaderRun::GetTextRange() const
  function FRunInfo (line 178) | const FRunInfo& FLoaderRun::GetRunInfo() const
  function ERunAttributes (line 184) | ERunAttributes FLoaderRun::GetRunAttributes() const

FILE: Source/FairyGUI/Private/Widgets/Mesh/FillMesh.cpp
  function FillHorizontal (line 3) | static void FillHorizontal(FVertexHelper& Helper, FBox2D VertRect, int32...
  function FillVertical (line 15) | static void FillVertical(FVertexHelper& Helper, FBox2D VertRect, int32 O...
  function FillRadial90 (line 28) | static void FillRadial90(FVertexHelper& Helper, FBox2D VertRect, EOrigin...
  function FillRadial180 (line 106) | static void FillRadial180(FVertexHelper& Helper, FBox2D VertRect, EOrigi...
  function FillRadial360 (line 169) | static void FillRadial360(FVertexHelper& Helper, FBox2D VertRect, EOrigi...

FILE: Source/FairyGUI/Private/Widgets/Mesh/VertexHelper.cpp
  function int32 (line 15) | int32 FVertexHelper::GetVertexCount() const
  function FVector2D (line 116) | const FVector2D& FVertexHelper::GetPosition(int32 Index)
  function FVector2D (line 124) | FVector2D FVertexHelper::GetUVAtPosition(const FVector2D& Position, bool...

FILE: Source/FairyGUI/Private/Widgets/NTextFormat.cpp
  function FTextBlockStyle (line 31) | FTextBlockStyle FNTextFormat::GetStyle() const

FILE: Source/FairyGUI/Private/Widgets/NTexture.cpp
  function UNTexture (line 6) | UNTexture* UNTexture::GetWhiteTexture()
  function FVector2D (line 127) | FVector2D UNTexture::GetSize() const
  function FBox2D (line 132) | FBox2D UNTexture::GetDrawRect(FBox2D& InDrawRect) const

FILE: Source/FairyGUI/Private/Widgets/SContainer.cpp
  function int32 (line 78) | int32 SContainer::GetChildIndex(const TSharedRef<SWidget>& SlotWidget) c...
  function int32 (line 115) | int32 SContainer::NumChildren() const
  function int32 (line 140) | int32 SContainer::OnPaint(const FPaintArgs& Args, const FGeometry& Allot...
  function FChildren (line 172) | FChildren* SContainer::GetChildren()

FILE: Source/FairyGUI/Private/Widgets/SDisplayObject.cpp
  function FVector2D (line 27) | const FVector2D& SDisplayObject::GetPosition() const
  function EVisibility (line 124) | EVisibility SDisplayObject::GetVisibilityFlags() const
  function FVector2D (line 153) | FVector2D SDisplayObject::ComputeDesiredSize(float) const
  function FChildren (line 158) | FChildren* SDisplayObject::GetChildren()
  function int32 (line 167) | int32 SDisplayObject::OnPaint(const FPaintArgs& Args, const FGeometry& A...
  function FReply (line 172) | FReply SDisplayObject::OnMouseButtonDown(const FGeometry& MyGeometry, co...
  function FReply (line 181) | FReply SDisplayObject::OnMouseButtonUp(const FGeometry& MyGeometry, cons...
  function FReply (line 190) | FReply SDisplayObject::OnMouseMove(const FGeometry& MyGeometry, const FP...
  function FReply (line 199) | FReply SDisplayObject::OnMouseButtonDoubleClick(const FGeometry& MyGeome...
  function FReply (line 222) | FReply SDisplayObject::OnMouseWheel(const FGeometry& MyGeometry, const F...
  function UGObject (line 245) | UGObject* SDisplayObject::GetWidgetGObject(const TSharedPtr<SWidget>& In...
  function UGObject (line 263) | UGObject* SDisplayObject::GetWidgetGObjectIfOnStage(const TSharedPtr<SWi...

FILE: Source/FairyGUI/Private/Widgets/SFImage.cpp
  function EFillMethod (line 59) | EFillMethod SFImage::GetFillMethod() const
  function int32 (line 81) | int32 SFImage::GetFillOrigin() const
  function int32 (line 132) | int32 SFImage::OnPaint(const FPaintArgs& Args, const FGeometry& Allotted...

FILE: Source/FairyGUI/Private/Widgets/SShape.cpp
  function int32 (line 15) | int32 SShape::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedG...

FILE: Source/FairyGUI/Private/Widgets/STextField.cpp
  function FVector2D (line 78) | FVector2D STextField::GetTextSize()
  function FVector2D (line 93) | FVector2D STextField::ComputeDesiredSize(float LayoutScaleMultiplier) const
  function FChildren (line 102) | FChildren* STextField::GetChildren()
  function int32 (line 112) | int32 STextField::OnPaint(const FPaintArgs& Args, const FGeometry& Allot...
  class FLineHelper (line 210) | class FLineHelper
    method FLineHelper (line 217) | FLineHelper()
    method FString (line 230) | FString& GetText()
    method NewLine (line 247) | void NewLine()

FILE: Source/FairyGUI/Private/Widgets/STextInput.cpp
  class SMyTextInput (line 4) | class SMyTextInput : public SMultiLineEditableText
    method SMyTextInput (line 7) | SMyTextInput() :bPassword(false)
    method SetTextFormat (line 12) | void SetTextFormat(const FNTextFormat& InTextFormat)
    method SetOnTextChanged (line 18) | void SetOnTextChanged(FOnTextChanged Callback)
    method SetOnTextCommitted (line 23) | void SetOnTextCommitted(FOnTextCommitted Callback)
    method SetAllowMultiLine (line 28) | void SetAllowMultiLine(bool bInAllowMultiLine)
    method IsTextPassword (line 33) | virtual bool IsTextPassword() const override
  function FChildren (line 79) | FChildren* STextInput::GetChildren()
  function int32 (line 92) | int32 STextInput::OnPaint(const FPaintArgs& Args, const FGeometry& Allot...

FILE: Source/FairyGUI/Public/Event/EventContext.h
  function FAIRYGUI_API (line 14) | FAIRYGUI_API UEventContext : public UObject

FILE: Source/FairyGUI/Public/Event/EventTypes.h
  function FUIEvents (line 6) | struct FAIRYGUI_API FUIEvents

FILE: Source/FairyGUI/Public/FairyApplication.h
  function FAIRYGUI_API (line 21) | FAIRYGUI_API UFairyApplication : public UObject

FILE: Source/FairyGUI/Public/FairyBlueprintLibrary.h
  function FAIRYGUI_API (line 16) | FAIRYGUI_API UFairyBlueprintLibrary : public UBlueprintFunctionLibrary

FILE: Source/FairyGUI/Public/FairyGUIModule.h
  function class (line 8) | class FFairyGUIModule : public IModuleInterface

FILE: Source/FairyGUI/Public/Tween/EaseManager.h
  function class (line 6) | class FAIRYGUI_API EaseManager

FILE: Source/FairyGUI/Public/Tween/EaseType.h
  function EEaseType (line 6) | enum class EEaseType : uint8

FILE: Source/FairyGUI/Public/Tween/GPath.h
  function FGPathPoint (line 5) | struct FAIRYGUI_API FGPathPoint

FILE: Source/FairyGUI/Public/Tween/GTween.h
  function class (line 8) | class FAIRYGUI_API FGTween
  function class (line 30) | class FAIRYGUI_API FGTweenAction

FILE: Source/FairyGUI/Public/Tween/GTweener.h
  function class (line 14) | class FAIRYGUI_API FGTweener

FILE: Source/FairyGUI/Public/Tween/TweenManager.h
  function IsTweening (line 21) | bool IsTweening(FTweenerHandle const& Handle) { return GetTween(Handle) ...
  function IsTweening (line 22) | bool IsTweening(UObject* Target) { return GetTween(Target) != nullptr; }

FILE: Source/FairyGUI/Public/Tween/TweenValue.h
  function FAIRYGUI_API (line 7) | FAIRYGUI_API FTweenValue

FILE: Source/FairyGUI/Public/Tween/TweenerHandle.h
  function FAIRYGUI_API (line 7) | FAIRYGUI_API FTweenerHandle
  function SetIndex (line 58) | void SetIndex(int32 Index)
  function IncreaseSerialNumber (line 63) | void IncreaseSerialNumber()

FILE: Source/FairyGUI/Public/UI/ControllerAction/ChangePageAction.h
  function class (line 5) | class FChangePageAction : public FControllerAction

FILE: Source/FairyGUI/Public/UI/ControllerAction/ControllerAction.h
  function class (line 8) | class FControllerAction

FILE: Source/FairyGUI/Public/UI/ControllerAction/PlayTransitionAction.h
  function class (line 7) | class FPlayTransitionAction : public FControllerAction

FILE: Source/FairyGUI/Public/UI/DragDropManager.h
  function UGLoader (line 19) | UGLoader* GetAgent() const { return Agent; }

FILE: Source/FairyGUI/Public/UI/FieldTypes.h
  type class (line 8) | enum class
  type class (line 24) | enum class
  type class (line 48) | enum class
  type class (line 56) | enum class
  type class (line 64) | enum class
  type class (line 72) | enum class
  type class (line 80) | enum class
  type class (line 89) | enum class
  type class (line 100) | enum class
  type class (line 109) | enum class
  type class (line 119) | enum class
  type class (line 128) | enum class
  type class (line 136) | enum class
  type class (line 144) | enum class
  type class (line 153) | enum class
  type class (line 162) | enum class
  type class (line 184) | enum class
  type class (line 195) | enum class
  type class (line 202) | enum class
  type class (line 209) | enum class
  type class (line 218) | enum class
  type class (line 227) | enum class
  type class (line 236) | enum class
  type class (line 251) | enum class
  type class (line 259) | enum class
  type class (line 267) | enum class

FILE: Source/FairyGUI/Public/UI/GButton.h
  function FAIRYGUI_API (line 10) | FAIRYGUI_API UGButton : public UGComponent

FILE: Source/FairyGUI/Public/UI/GComboBox.h
  function FAIRYGUI_API (line 11) | FAIRYGUI_API UGComboBox : public UGComponent

FILE: Source/FairyGUI/Public/UI/GComponent.h
  function FAIRYGUI_API (line 12) | FAIRYGUI_API UGComponent : public UGObject
  function virtual (line 120) | virtual IHitTest* GetHitArea() const override { return HitArea.Get(); }
  function UScrollPane (line 124) | UScrollPane* GetScrollPane() const { return ScrollPane; }
  function OnClickChild (line 143) | void OnClickChild(const FString& ChildName, const FGUIEventDynDelegate& ...

FILE: Source/FairyGUI/Public/UI/GController.h
  function FAIRYGUI_API (line 12) | FAIRYGUI_API UGController : public UObject

FILE: Source/FairyGUI/Public/UI/GGraph.h
  function FAIRYGUI_API (line 7) | FAIRYGUI_API UGGraph : public UGObject

FILE: Source/FairyGUI/Public/UI/GGroup.h
  function FAIRYGUI_API (line 7) | FAIRYGUI_API UGGroup : public UGObject

FILE: Source/FairyGUI/Public/UI/GImage.h
  function FAIRYGUI_API (line 7) | FAIRYGUI_API UGImage : public UGObject

FILE: Source/FairyGUI/Public/UI/GLabel.h
  function FAIRYGUI_API (line 9) | FAIRYGUI_API UGLabel : public UGComponent

FILE: Source/FairyGUI/Public/UI/GList.h
  function FAIRYGUI_API (line 15) | FAIRYGUI_API UGList : public UGComponent

FILE: Source/FairyGUI/Public/UI/GLoader.h
  function FAIRYGUI_API (line 7) | FAIRYGUI_API UGLoader : public UGObject

FILE: Source/FairyGUI/Public/UI/GLoader3D.h
  function FAIRYGUI_API (line 7) | FAIRYGUI_API UGLoader3D : public UGObject

FILE: Source/FairyGUI/Public/UI/GMovieClip.h
  function FAIRYGUI_API (line 8) | FAIRYGUI_API UGMovieClip : public UGObject

FILE: Source/FairyGUI/Public/UI/GObject.h
  function FAIRYGUI_API (line 24) | FAIRYGUI_API UGObject : public UObject

FILE: Source/FairyGUI/Public/UI/GObjectPool.h
  function class (line 8) | class FGObjectPool : public FGCObject

FILE: Source/FairyGUI/Public/UI/GProgressBar.h
  function FAIRYGUI_API (line 7) | FAIRYGUI_API UGProgressBar : public UGComponent

FILE: Source/FairyGUI/Public/UI/GRichTextField.h
  function FAIRYGUI_API (line 7) | FAIRYGUI_API UGRichTextField : public UGTextField

FILE: Source/FairyGUI/Public/UI/GRoot.h
  function FAIRYGUI_API (line 10) | FAIRYGUI_API UGRoot : public UGComponent

FILE: Source/FairyGUI/Public/UI/GScrollBar.h
  function FAIRYGUI_API (line 9) | FAIRYGUI_API UGScrollBar : public UGComponent

FILE: Source/FairyGUI/Public/UI/GSlider.h
  function FAIRYGUI_API (line 7) | FAIRYGUI_API UGSlider : public UGComponent

FILE: Source/FairyGUI/Public/UI/GTextField.h
  function FAIRYGUI_API (line 8) | FAIRYGUI_API UGTextField : public UGObject

FILE: Source/FairyGUI/Public/UI/GTextInput.h
  function FAIRYGUI_API (line 8) | FAIRYGUI_API UGTextInput : public UGObject

FILE: Source/FairyGUI/Public/UI/GTree.h
  function FAIRYGUI_API (line 13) | FAIRYGUI_API UGTree : public UGList

FILE: Source/FairyGUI/Public/UI/GTreeNode.h
  function FAIRYGUI_API (line 12) | FAIRYGUI_API UGTreeNode : public UObject

FILE: Source/FairyGUI/Public/UI/GWindow.h
  function class (line 6) | class FAIRYGUI_API IUISource
  function FAIRYGUI_API (line 18) | FAIRYGUI_API UGWindow : public UGComponent

FILE: Source/FairyGUI/Public/UI/Gears/GearBase.h
  function class (line 10) | class FAIRYGUI_API FGearTweenConfig
  function class (line 24) | class FGearBase

FILE: Source/FairyGUI/Public/UI/Gears/GearColor.h
  type FValue (line 22) | struct FValue

FILE: Source/FairyGUI/Public/UI/Gears/GearLook.h
  type FValue (line 22) | struct FValue

FILE: Source/FairyGUI/Public/UI/PackageItem.h
  type FMovieClipData (line 11) | struct FMovieClipData
  type FBitmapFont (line 12) | struct FBitmapFont

FILE: Source/FairyGUI/Public/UI/PopupMenu.h
  function FAIRYGUI_API (line 8) | FAIRYGUI_API UPopupMenu : public UObject

FILE: Source/FairyGUI/Public/UI/RelationItem.h
  function FRelationDef (line 8) | struct FAIRYGUI_API FRelationDef
  function class (line 19) | class FAIRYGUI_API FRelationItem

FILE: Source/FairyGUI/Public/UI/Relations.h
  function class (line 10) | class FAIRYGUI_API FRelations

FILE: Source/FairyGUI/Public/UI/ScrollPane.h
  function FAIRYGUI_API (line 19) | FAIRYGUI_API UScrollPane : public UObject

FILE: Source/FairyGUI/Public/UI/Transition.h
  type FTransitionItem (line 13) | struct FTransitionItem
  function FAIRYGUI_API (line 16) | FAIRYGUI_API UTransition : public UObject
  function PlayReverse (line 48) | void PlayReverse(int32 InTimes, float InDelay, const FSimpleDelegate& In...
  function SetHook (line 80) | void SetHook(const FString& InLabel, FSimpleDynDelegate Callback)
  type FTransitionItemData (line 129) | struct FTransitionItemData

FILE: Source/FairyGUI/Public/UI/TranslationHelper.h
  function class (line 7) | class FTranslationHelper

FILE: Source/FairyGUI/Public/UI/UIConfig.h
  function FAIRYGUI_API (line 9) | FAIRYGUI_API FUIConfig

FILE: Source/FairyGUI/Public/UI/UIObjectFactory.h
  function class (line 11) | class FAIRYGUI_API FUIObjectFactory

FILE: Source/FairyGUI/Public/UI/UIPackage.h
  function FAIRYGUI_API (line 13) | FAIRYGUI_API UUIPackage : public UObject
  function FAIRYGUI_API (line 110) | FAIRYGUI_API UUIPackageStatic : public UObject

FILE: Source/FairyGUI/Public/UIPackageAsset.h
  function FAIRYGUI_API (line 8) | FAIRYGUI_API UUIPackageAsset : public UObject

FILE: Source/FairyGUI/Public/Utils/ByteBuffer.h
  function class (line 6) | class FAIRYGUI_API FByteBuffer

FILE: Source/FairyGUI/Public/Utils/HTMLElement.h
  function EHTMLElementType (line 7) | enum class EHTMLElementType

FILE: Source/FairyGUI/Public/Utils/HTMLParser.h
  function FHTMLParseOptions (line 5) | struct FAIRYGUI_API FHTMLParseOptions
  function class (line 14) | class FAIRYGUI_API FHTMLParser

FILE: Source/FairyGUI/Public/Utils/NVariant.h
  function FAIRYGUI_API (line 8) | FAIRYGUI_API FNVariant

FILE: Source/FairyGUI/Public/Utils/UBBParser.h
  function class (line 9) | class FAIRYGUI_API FUBBParser

FILE: Source/FairyGUI/Public/Utils/XMLAttributes.h
  type FXMLAttributes (line 5) | struct FXMLAttributes

FILE: Source/FairyGUI/Public/Utils/XMLIterator.h
  function EXMLTagType (line 5) | enum class EXMLTagType

FILE: Source/FairyGUI/Public/Widgets/BitmapFont.h
  function FBitmapFont (line 7) | struct FAIRYGUI_API FBitmapFont : public FGCObject

FILE: Source/FairyGUI/Public/Widgets/BitmapFontRun.h
  type FTextBlockStyle (line 9) | struct FTextBlockStyle
  type class (line 10) | enum class

FILE: Source/FairyGUI/Public/Widgets/HitTest.h
  function class (line 5) | class FAIRYGUI_API IHitTest
  function FPixelHitTestData (line 11) | struct FAIRYGUI_API FPixelHitTestData

FILE: Source/FairyGUI/Public/Widgets/LoaderRun.h
  type FTextBlockStyle (line 10) | struct FTextBlockStyle
  type class (line 11) | enum class

FILE: Source/FairyGUI/Public/Widgets/Mesh/EllipseMesh.h
  function virtual (line 12) | virtual ~FEllipseMesh() {}

FILE: Source/FairyGUI/Public/Widgets/Mesh/FillMesh.h
  function virtual (line 12) | virtual ~FFillMesh() {}

FILE: Source/FairyGUI/Public/Widgets/Mesh/MeshFactory.h
  function class (line 13) | class FAIRYGUI_API IMeshFactory
  function virtual (line 34) | inline virtual bool IsMeshFactoryOfType(const FName& Type) const override
  function virtual (line 39) | inline virtual IHitTest* GetMeshHitTest() const override

FILE: Source/FairyGUI/Public/Widgets/Mesh/PolygonMesh.h
  function virtual (line 11) | virtual ~FPolygonMesh() {}

FILE: Source/FairyGUI/Public/Widgets/Mesh/RectMesh.h
  function virtual (line 11) | virtual ~FRectMesh() {}

FILE: Source/FairyGUI/Public/Widgets/Mesh/RegularPolygonMesh.h
  function virtual (line 11) | virtual ~FRegularPolygonMesh() {}

FILE: Source/FairyGUI/Public/Widgets/Mesh/RoundedRectMesh.h
  function virtual (line 11) | virtual ~FRoundedRectMesh() {}

FILE: Source/FairyGUI/Public/Widgets/Mesh/VertexHelper.h
  function class (line 5) | class FAIRYGUI_API FVertexHelper

FILE: Source/FairyGUI/Public/Widgets/MeshFactory.h
  function class (line 9) | class FAIRYGUI_API IMeshFactory
  function virtual (line 29) | inline virtual bool IsMeshFactoryOfType(const FName& Type) const override

FILE: Source/FairyGUI/Public/Widgets/NGraphics.h
  function UNTexture (line 20) | UNTexture* GetTexture() const { return Texture; }
  function TSharedPtr (line 23) | const TSharedPtr<IMeshFactory>& GetMeshFactory() { return MeshFactory; }
  function SetMeshDirty (line 26) | void SetMeshDirty() { bMeshDirty = true; }

FILE: Source/FairyGUI/Public/Widgets/NTextFormat.h
  function FAIRYGUI_API (line 8) | FAIRYGUI_API FNTextFormat

FILE: Source/FairyGUI/Public/Widgets/NTexture.h
  function FAIRYGUI_API (line 9) | FAIRYGUI_API UNTexture : public UObject

FILE: Source/FairyGUI/Public/Widgets/SDisplayObject.h
  function FVector2D (line 26) | const FVector2D& GetPosition() const;

FILE: Source/FairyGUI/Public/Widgets/SFImage.h
  function UNTexture (line 25) | UNTexture* GetTexture() const { return Graphics.GetTexture();  }

FILE: Source/FairyGUI/Public/Widgets/SMovieClip.h
  function FMovieClipData (line 5) | struct FAIRYGUI_API FMovieClipData : public FGCObject

FILE: Source/FairyGUIEditor/FairyGUIEditor.Build.cs
  class FairyGUIEditor (line 5) | public class FairyGUIEditor : ModuleRules
    method FairyGUIEditor (line 7) | public FairyGUIEditor(ReadOnlyTargetRules Target) : base(Target)

FILE: Source/FairyGUIEditor/Private/FairyGUIFactory.cpp
  function UObject (line 17) | UObject* UFairyGUIFactory::FactoryCreateBinary(UClass* InClass, UObject*...

FILE: Source/FairyGUIEditor/Public/FairyGUIEditor.h
  function class (line 8) | class FFairyGUIEditorModule : public IModuleInterface
Condensed preview — 197 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (878K chars).
[
  {
    "path": ".gitignore",
    "chars": 946,
    "preview": "# Visual Studio 2015 user specific files\n.vs/\n\n# Compiled Object files\n*.slo\n*.lo\n*.o\n*.obj\n\n# Precompiled Headers\n*.gch"
  },
  {
    "path": "FairyGUI.uplugin",
    "chars": 589,
    "preview": "{\n\t\"FileVersion\": 3,\n\t\"Version\": 1,\n\t\"VersionName\": \"1.0\",\n\t\"FriendlyName\": \"FairyGUI\",\n\t\"Description\": \"FairyGUI is a c"
  },
  {
    "path": "LICENSE",
    "chars": 1065,
    "preview": "MIT License\n\nCopyright (c) 2021 FairyGUI\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
  },
  {
    "path": "README.md",
    "chars": 146,
    "preview": "# FairyGUI-unreal\nA flexible UI framework for Unreal Engine\n\nSuggest to start from [Examples](https://github.com/fairygu"
  },
  {
    "path": "Source/FairyGUI/FairyGUI.Build.cs",
    "chars": 1204,
    "preview": "// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.\n\nusing UnrealBuildTool;\n\npublic class FairyGUI : ModuleRule"
  },
  {
    "path": "Source/FairyGUI/Private/Event/EventContext.cpp",
    "chars": 32,
    "preview": "#include \"Event/EventContext.h\"\n"
  },
  {
    "path": "Source/FairyGUI/Private/Event/EventTypes.cpp",
    "chars": 1064,
    "preview": "#include \"Event/EventTypes.h\"\n\nconst FName FUIEvents::Click(\"Click\");\nconst FName FUIEvents::TouchBegin(\"TouchBegin\");\nc"
  },
  {
    "path": "Source/FairyGUI/Private/FairyApplication.cpp",
    "chars": 16461,
    "preview": "#include \"FairyApplication.h\"\n#include \"Framework/Application/SlateApplication.h\"\n#include \"Slate/SGameLayerManager.h\"\n#"
  },
  {
    "path": "Source/FairyGUI/Private/FairyBlueprintLibrary.cpp",
    "chars": 4402,
    "preview": "#include \"FairyBlueprintLibrary.h\"\n#include \"UI/UIConfig.h\"\n#include \"UI/UIObjectFactory.h\"\n#include \"Tween/GTween.h\"\n\nc"
  },
  {
    "path": "Source/FairyGUI/Private/FairyCommons.cpp",
    "chars": 147,
    "preview": "#include \"FairyCommons.h\"\n#include \"Framework/Application/SlateApplication.h\"\n\nDEFINE_LOG_CATEGORY(LogFairyGUI);\n\nconst "
  },
  {
    "path": "Source/FairyGUI/Private/FairyGUIModule.cpp",
    "chars": 993,
    "preview": "// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.\n\n#include \"FairyGUIModule.h\"\n#if WITH_EDITOR\n#include \"Edit"
  },
  {
    "path": "Source/FairyGUI/Private/Tween/EaseManager.cpp",
    "chars": 6830,
    "preview": "#include \"Tween/EaseManager.h\"\n\nstatic const float _PiOver2 = (PI * 0.5f);\nstatic const float _TwoPi = (PI * 2);\n\nclass "
  },
  {
    "path": "Source/FairyGUI/Private/Tween/GPath.cpp",
    "chars": 9019,
    "preview": "#include \"Tween/GPath.h\"\n\nFGPathPoint::FGPathPoint(const FVector& InPos)\n{\n    Pos = InPos;\n    Control1 = FVector::Zero"
  },
  {
    "path": "Source/FairyGUI/Private/Tween/GTween.cpp",
    "chars": 4052,
    "preview": "#include \"Tween/GTween.h\"\n#include \"Tween/TweenManager.h\"\n#include \"UI/GProgressBar.h\"\n\nFGTweener* FGTween::To(float Sta"
  },
  {
    "path": "Source/FairyGUI/Private/Tween/GTweener.cpp",
    "chars": 8792,
    "preview": "#include \"Tween/GTweener.h\"\n#include \"Tween/EaseManager.h\"\n#include \"Tween/GPath.h\"\n#include \"UI/GObject.h\"\n\nFGTweener::"
  },
  {
    "path": "Source/FairyGUI/Private/Tween/TweenManager.cpp",
    "chars": 4636,
    "preview": "#include \"Tween/TweenManager.h\"\n#include \"Tween/GTweener.h\"\n\nFTweenManager FTweenManager::Singleton;\n\nFTweenManager::FTw"
  },
  {
    "path": "Source/FairyGUI/Private/Tween/TweenValue.cpp",
    "chars": 1541,
    "preview": "#include \"Tween/TweenValue.h\"\n\nFTweenValue::FTweenValue() :X(0), Y(0), Z(0), W(0), D(0)\n{\n}\n\nFVector2D FTweenValue::GetV"
  },
  {
    "path": "Source/FairyGUI/Private/UI/ControllerAction/ChangePageAction.cpp",
    "chars": 1322,
    "preview": "#include \"UI/ControllerAction/ChangePageAction.h\"\n#include \"UI/GController.h\"\n#include \"Utils/ByteBuffer.h\"\n#include \"UI"
  },
  {
    "path": "Source/FairyGUI/Private/UI/ControllerAction/ControllerAction.cpp",
    "chars": 1155,
    "preview": "#include \"UI/ControllerAction/ControllerAction.h\"\n#include \"UI/ControllerAction/ChangePageAction.h\"\n#include \"UI/Control"
  },
  {
    "path": "Source/FairyGUI/Private/UI/ControllerAction/PlayTransitionAction.cpp",
    "chars": 1167,
    "preview": "#include \"UI/ControllerAction/PlayTransitionAction.h\"\n#include \"UI/GController.h\"\n#include \"UI/Transition.h\"\n#include \"U"
  },
  {
    "path": "Source/FairyGUI/Private/UI/DragDropManager.cpp",
    "chars": 2195,
    "preview": "#include \"UI/DragDropManager.h\"\n#include \"UI/UIObjectFactory.h\"\n#include \"UI/GRoot.h\"\n#include \"FairyApplication.h\"\n\nUDr"
  },
  {
    "path": "Source/FairyGUI/Private/UI/GButton.cpp",
    "chars": 12162,
    "preview": "#include \"UI/GButton.h\"\n#include \"UI/GTextField.h\"\n#include \"UI/GLabel.h\"\n#include \"UI/GController.h\"\n#include \"Utils/By"
  },
  {
    "path": "Source/FairyGUI/Private/UI/GComboBox.cpp",
    "chars": 11679,
    "preview": "#include \"UI/GComboBox.h\"\n#include \"UI/UIPackage.h\"\n#include \"UI/GTextField.h\"\n#include \"UI/GTextInput.h\"\n#include \"UI/G"
  },
  {
    "path": "Source/FairyGUI/Private/UI/GComponent.cpp",
    "chars": 29745,
    "preview": "#include \"UI/GComponent.h\"\n#include \"UI/GButton.h\"\n#include \"UI/GGroup.h\"\n#include \"UI/Relations.h\"\n#include \"UI/Transla"
  },
  {
    "path": "Source/FairyGUI/Private/UI/GController.cpp",
    "chars": 4547,
    "preview": "#include \"UI/GController.h\"\n#include \"UI/GComponent.h\"\n#include \"UI/UIPackage.h\"\n#include \"Utils/ByteBuffer.h\"\n\nUGContro"
  },
  {
    "path": "Source/FairyGUI/Private/UI/GGraph.cpp",
    "chars": 5915,
    "preview": "#include \"UI/GGraph.h\"\n#include \"Utils/ByteBuffer.h\"\n#include \"Widgets/NTexture.h\"\n#include \"Widgets/SShape.h\"\n#include "
  },
  {
    "path": "Source/FairyGUI/Private/UI/GGroup.cpp",
    "chars": 11398,
    "preview": "#include \"UI/GGroup.h\"\n#include \"UI/GComponent.h\"\n#include \"Utils/ByteBuffer.h\"\n#include \"Widgets/SDisplayObject.h\"\n\nUGG"
  },
  {
    "path": "Source/FairyGUI/Private/UI/GImage.cpp",
    "chars": 2875,
    "preview": "#include \"UI/GImage.h\"\n#include \"Utils/ByteBuffer.h\"\n#include \"Widgets/NTexture.h\"\n#include \"Widgets/SFImage.h\"\n\nUGImage"
  },
  {
    "path": "Source/FairyGUI/Private/UI/GLabel.cpp",
    "chars": 4528,
    "preview": "#include \"UI/GLabel.h\"\n#include \"UI/GTextInput.h\"\n#include \"UI/GButton.h\"\n#include \"UI/GTextField.h\"\n#include \"Utils/Byt"
  },
  {
    "path": "Source/FairyGUI/Private/UI/GList.cpp",
    "chars": 74496,
    "preview": "#include \"UI/GList.h\"\n#include \"UI/GButton.h\"\n#include \"UI/GObjectPool.h\"\n#include \"UI/GController.h\"\n#include \"UI/GScr"
  },
  {
    "path": "Source/FairyGUI/Private/UI/GLoader.cpp",
    "chars": 10993,
    "preview": "#include \"UI/GLoader.h\"\n#include \"UI/UIPackage.h\"\n#include \"UI/GComponent.h\"\n#include \"Widgets/NTexture.h\"\n#include \"Wid"
  },
  {
    "path": "Source/FairyGUI/Private/UI/GLoader3D.cpp",
    "chars": 5016,
    "preview": "#include \"UI/GLoader3D.h\"\n#include \"UI/UIPackage.h\"\n#include \"UI/GComponent.h\"\n#include \"Widgets/NTexture.h\"\n#include \"W"
  },
  {
    "path": "Source/FairyGUI/Private/UI/GMovieClip.cpp",
    "chars": 3297,
    "preview": "#include \"UI/GMovieClip.h\"\n#include \"Widgets/NTexture.h\"\n#include \"Widgets/SMovieClip.h\"\n#include \"Utils/ByteBuffer.h\"\n\n"
  },
  {
    "path": "Source/FairyGUI/Private/UI/GObject.cpp",
    "chars": 22908,
    "preview": "#include \"UI/GObject.h\"\n#include \"UI/GList.h\"\n#include \"UI/GGroup.h\"\n#include \"UI/GController.h\"\n#include \"UI/UIPackage."
  },
  {
    "path": "Source/FairyGUI/Private/UI/GObjectPool.cpp",
    "chars": 789,
    "preview": "#include \"UI/GObjectPool.h\"\n#include \"UI/GObject.h\"\n#include \"UI/UIPackage.h\"\n\nUGObject* FGObjectPool::GetObject(const F"
  },
  {
    "path": "Source/FairyGUI/Private/UI/GProgressBar.cpp",
    "chars": 5254,
    "preview": "#include \"UI/GProgressBar.h\"\n#include \"UI/GImage.h\"\n#include \"UI/GLoader.h\"\n#include \"Tween/GTween.h\"\n#include \"Utils/By"
  },
  {
    "path": "Source/FairyGUI/Private/UI/GRichTextField.cpp",
    "chars": 111,
    "preview": "#include \"UI/GRichTextField.h\"\n\nUGRichTextField::UGRichTextField()\n{\n}\n\nUGRichTextField::~UGRichTextField()\n{\n}"
  },
  {
    "path": "Source/FairyGUI/Private/UI/GRoot.cpp",
    "chars": 10872,
    "preview": "#include \"UI/GRoot.h\"\n#include \"Engine/World.h\"\n#include \"Engine/GameViewportClient.h\"\n#include \"Slate.h\"\n#include \"Fair"
  },
  {
    "path": "Source/FairyGUI/Private/UI/GScrollBar.cpp",
    "chars": 4583,
    "preview": "#include \"UI/GScrollBar.h\"\n#include \"Utils/ByteBuffer.h\"\n\nUGScrollBar::UGScrollBar()\n{\n}\n\nUGScrollBar::~UGScrollBar()\n{\n"
  },
  {
    "path": "Source/FairyGUI/Private/UI/GSlider.cpp",
    "chars": 6334,
    "preview": "#include \"UI/GSlider.h\"\n#include \"Utils/ByteBuffer.h\"\n\nUGSlider::UGSlider()\n{\n}\n\nUGSlider::~UGSlider()\n{\n}\n\nvoid UGSlide"
  },
  {
    "path": "Source/FairyGUI/Private/UI/GTextField.cpp",
    "chars": 6525,
    "preview": "#include \"UI/GTextField.h\"\n#include \"UI/GRichTextField.h\"\n#include \"Utils/ByteBuffer.h\"\n#include \"Utils/UBBParser.h\"\n#in"
  },
  {
    "path": "Source/FairyGUI/Private/UI/GTextInput.cpp",
    "chars": 4596,
    "preview": "#include \"UI/GTextInput.h\"\n#include \"Utils/ByteBuffer.h\"\n#include \"Utils/UBBParser.h\"\n#include \"Widgets/STextInput.h\"\n\nU"
  },
  {
    "path": "Source/FairyGUI/Private/UI/GTree.cpp",
    "chars": 9642,
    "preview": "#include \"UI/GTree.h\"\n#include \"Utils/ByteBuffer.h\"\n#include \"UI/GController.h\"\n#include \"UI/GObjectPool.h\"\n\nUGTree::UGT"
  },
  {
    "path": "Source/FairyGUI/Private/UI/GTreeNode.cpp",
    "chars": 5710,
    "preview": "#include \"UI/GTreeNode.h\"\n#include \"UI/GComponent.h\"\n#include \"UI/GTree.h\"\n\nUGTreeNode* UGTreeNode::CreateNode(bool bIsF"
  },
  {
    "path": "Source/FairyGUI/Private/UI/GWindow.cpp",
    "chars": 6604,
    "preview": "#include \"UI/GWindow.h\"\n#include \"UI/GGraph.h\"\n#include \"UI/GRoot.h\"\n#include \"UI/UIPackage.h\"\n\nUGWindow* UGWindow::Crea"
  },
  {
    "path": "Source/FairyGUI/Private/UI/Gears/GearAnimation.cpp",
    "chars": 1414,
    "preview": "#include \"UI/Gears/GearAnimation.h\"\n#include \"UI/GObject.h\"\n#include \"UI/GController.h\"\n#include \"Utils/ByteBuffer.h\"\n\nF"
  },
  {
    "path": "Source/FairyGUI/Private/UI/Gears/GearBase.cpp",
    "chars": 4162,
    "preview": "#include \"UI/Gears/GearBase.h\"\n#include \"UI/Gears/GearDisplay.h\"\n#include \"UI/Gears/GearAnimation.h\"\n#include \"UI/Gears/"
  },
  {
    "path": "Source/FairyGUI/Private/UI/Gears/GearColor.cpp",
    "chars": 3368,
    "preview": "#include \"UI/Gears/GearColor.h\"\n#include \"UI/GObject.h\"\n#include \"UI/UIPackage.h\"\n#include \"UI/GController.h\"\n#include \""
  },
  {
    "path": "Source/FairyGUI/Private/UI/Gears/GearDisplay.cpp",
    "chars": 1017,
    "preview": "#include \"UI/Gears/GearDisplay.h\"\n#include \"UI/GController.h\"\n#include \"Utils/ByteBuffer.h\"\n\nFGearDisplay::FGearDisplay("
  },
  {
    "path": "Source/FairyGUI/Private/UI/Gears/GearDisplay2.cpp",
    "chars": 896,
    "preview": "#include \"UI/Gears/GearDisplay2.h\"\n#include \"UI/GController.h\"\n#include \"Utils/ByteBuffer.h\"\n\nFGearDisplay2::FGearDispla"
  },
  {
    "path": "Source/FairyGUI/Private/UI/Gears/GearFontSize.cpp",
    "chars": 986,
    "preview": "#include \"UI/Gears/GearFontSize.h\"\n#include \"UI/GObject.h\"\n#include \"UI/GController.h\"\n#include \"Utils/ByteBuffer.h\"\n\nFG"
  },
  {
    "path": "Source/FairyGUI/Private/UI/Gears/GearIcon.cpp",
    "chars": 848,
    "preview": "#include \"UI/Gears/GearIcon.h\"\n#include \"UI/GObject.h\"\n#include \"UI/GController.h\"\n#include \"Utils/ByteBuffer.h\"\n\nFGearI"
  },
  {
    "path": "Source/FairyGUI/Private/UI/Gears/GearLook.cpp",
    "chars": 3708,
    "preview": "#include \"UI/Gears/GearLook.h\"\n#include \"UI/GObject.h\"\n#include \"UI/UIPackage.h\"\n#include \"UI/GController.h\"\n#include \"T"
  },
  {
    "path": "Source/FairyGUI/Private/UI/Gears/GearSize.cpp",
    "chars": 3738,
    "preview": "#include \"UI/Gears/GearSize.h\"\n#include \"UI/GObject.h\"\n#include \"UI/UIPackage.h\"\n#include \"UI/GController.h\"\n#include \"T"
  },
  {
    "path": "Source/FairyGUI/Private/UI/Gears/GearText.cpp",
    "chars": 848,
    "preview": "#include \"UI/Gears/GearText.h\"\n#include \"UI/GObject.h\"\n#include \"UI/GController.h\"\n#include \"Utils/ByteBuffer.h\"\n\nFGearT"
  },
  {
    "path": "Source/FairyGUI/Private/UI/Gears/GearXY.cpp",
    "chars": 3794,
    "preview": "#include \"UI/Gears/GearXY.h\"\n#include \"UI/GComponent.h\"\n#include \"UI/UIPackage.h\"\n#include \"UI/GController.h\"\n#include \""
  },
  {
    "path": "Source/FairyGUI/Private/UI/PackageItem.cpp",
    "chars": 1159,
    "preview": "#include \"UI/PackageItem.h\"\n#include \"UI/UIPackage.h\"\n#include \"UI/GRoot.h\"\n#include \"Utils/ByteBuffer.h\"\n\nFPackageItem:"
  },
  {
    "path": "Source/FairyGUI/Private/UI/PopupMenu.cpp",
    "chars": 6195,
    "preview": "#include \"UI/PopupMenu.h\"\n#include \"UI/GRoot.h\"\n#include \"UI/UIPackage.h\"\n#include \"UI/GController.h\"\n\nconst FName UPopu"
  },
  {
    "path": "Source/FairyGUI/Private/UI/RelationItem.cpp",
    "chars": 19312,
    "preview": "#include \"UI/RelationItem.h\"\n#include \"UI/Relations.h\"\n#include \"UI/GComponent.h\"\n#include \"UI/GGroup.h\"\n#include \"UI/Tr"
  },
  {
    "path": "Source/FairyGUI/Private/UI/Relations.cpp",
    "chars": 3104,
    "preview": "#include \"UI/Relations.h\"\n#include \"UI/GComponent.h\"\n#include \"Utils/ByteBuffer.h\"\n\nFRelations::FRelations(UGObject* InO"
  },
  {
    "path": "Source/FairyGUI/Private/UI/ScrollPane.cpp",
    "chars": 48951,
    "preview": "#include \"UI/ScrollPane.h\"\n#include \"Engine/World.h\"\n#include \"Engine/GameViewportClient.h\"\n#include \"TimerManager.h\"\n#i"
  },
  {
    "path": "Source/FairyGUI/Private/UI/Transition.cpp",
    "chars": 40510,
    "preview": "#include \"UI/Transition.h\"\n#include \"UI/GComponent.h\"\n#include \"UI/UIPackage.h\"\n#include \"UI/GController.h\"\n#include \"Ut"
  },
  {
    "path": "Source/FairyGUI/Private/UI/TranslationHelper.cpp",
    "chars": 257,
    "preview": "#include \"UI/TranslationHelper.h\"\n\nTMap<FString, TMap<FString, FString>> FTranslationHelper::Strings;\n\nvoid FTranslation"
  },
  {
    "path": "Source/FairyGUI/Private/UI/UIConfig.cpp",
    "chars": 552,
    "preview": "#include \"UI/UIConfig.h\"\n#include \"FairyApplication.h\"\n\nFUIConfig FUIConfig::Config;\n\nFUIConfig::FUIConfig() :\n    Butto"
  },
  {
    "path": "Source/FairyGUI/Private/UI/UIObjectFactory.cpp",
    "chars": 3935,
    "preview": "#include \"UI/UIObjectFactory.h\"\n#include \"UI/UIPackage.h\"\n#include \"UI/PackageItem.h\"\n#include \"UI/GComponent.h\"\n#includ"
  },
  {
    "path": "Source/FairyGUI/Private/UI/UIPackage.cpp",
    "chars": 22543,
    "preview": "#include \"UI/UIPackage.h\"\n#include \"Sound/SoundBase.h\"\n#include \"UIPackageAsset.h\"\n#include \"UI/PackageItem.h\"\n#include "
  },
  {
    "path": "Source/FairyGUI/Private/UIPackageAsset.cpp",
    "chars": 514,
    "preview": "#include \"UIPackageAsset.h\"\n#include \"EditorFramework/AssetImportData.h\"\n\n#if WITH_EDITORONLY_DATA\nvoid UUIPackageAsset:"
  },
  {
    "path": "Source/FairyGUI/Private/Utils/ByteBuffer.cpp",
    "chars": 4724,
    "preview": "#include \"Utils/ByteBuffer.h\"\n\nFByteBuffer::FByteBuffer(const uint8* InBuffer, int32 InOffset, int32 InLen, bool bInTran"
  },
  {
    "path": "Source/FairyGUI/Private/Utils/HTMLElement.cpp",
    "chars": 31,
    "preview": "#include \"Utils/HTMLElement.h\"\n"
  },
  {
    "path": "Source/FairyGUI/Private/Utils/HTMLParser.cpp",
    "chars": 10757,
    "preview": "#include \"Utils/HTMLParser.h\"\n#include \"Utils/XMLIterator.h\"\n\nenum class SupportedTagNames {\n    INVALID, B, I, U, STRIK"
  },
  {
    "path": "Source/FairyGUI/Private/Utils/NVariant.cpp",
    "chars": 1691,
    "preview": "#include \"Utils/NVariant.h\"\n\nconst FNVariant FNVariant::Null;\n\nFNVariant::FNVariant()\n{\n}\n\nFNVariant::~FNVariant()\n{\n}\n\n"
  },
  {
    "path": "Source/FairyGUI/Private/Utils/UBBParser.cpp",
    "chars": 5888,
    "preview": "#include \"Utils/UBBParser.h\"\n\nextern const FString FAIRYGUI_API G_EMPTY_STRING;\n\nFUBBParser FUBBParser::DefaultParser;\n\n"
  },
  {
    "path": "Source/FairyGUI/Private/Utils/XMLAttributes.cpp",
    "chars": 1156,
    "preview": "#include \"Utils/XMLAttributes.h\"\n\nextern const FString FAIRYGUI_API G_EMPTY_STRING;\n\nconst FString& FXMLAttributes::Get("
  },
  {
    "path": "Source/FairyGUI/Private/Utils/XMLIterator.cpp",
    "chars": 10721,
    "preview": "#include \"Utils/XMLIterator.h\"\n\nextern const FString FAIRYGUI_API G_EMPTY_STRING;\n\nconst TCHAR* CDATA_START = TEXT(\"<![C"
  },
  {
    "path": "Source/FairyGUI/Private/Widgets/BitmapFont.cpp",
    "chars": 183,
    "preview": "#include \"Widgets/BitmapFont.h\"\n\nvoid FBitmapFont::AddReferencedObjects(FReferenceCollector& Collector)\n{\n    if (Textur"
  },
  {
    "path": "Source/FairyGUI/Private/Widgets/BitmapFontRun.cpp",
    "chars": 6204,
    "preview": "#include \"Widgets/BitmapFontRun.h\"\n#include \"Styling/StyleDefaults.h\"\n#include \"Rendering/DrawElements.h\"\n#include \"Fram"
  },
  {
    "path": "Source/FairyGUI/Private/Widgets/HitTest.cpp",
    "chars": 1995,
    "preview": "#include \"Widgets/HitTest.h\"\n#include \"Utils/ByteBuffer.h\"\n#include \"UI/GObject.h\"\n\nvoid FPixelHitTestData::Load(FByteBu"
  },
  {
    "path": "Source/FairyGUI/Private/Widgets/LoaderRun.cpp",
    "chars": 6426,
    "preview": "#include \"Widgets/LoaderRun.h\"\n#include \"Styling/StyleDefaults.h\"\n#include \"Rendering/DrawElements.h\"\n#include \"Framewor"
  },
  {
    "path": "Source/FairyGUI/Private/Widgets/Mesh/EllipseMesh.cpp",
    "chars": 5333,
    "preview": "#include \"Widgets/Mesh/EllipseMesh.h\"\n\nFEllipseMesh::FEllipseMesh() :\n    LineWidth(0),\n    LineColor(FColor::Black),\n  "
  },
  {
    "path": "Source/FairyGUI/Private/Widgets/Mesh/FillMesh.cpp",
    "chars": 8687,
    "preview": "#include \"Widgets/Mesh/FillMesh.h\"\n\nstatic void FillHorizontal(FVertexHelper& Helper, FBox2D VertRect, int32 Origin, flo"
  },
  {
    "path": "Source/FairyGUI/Private/Widgets/Mesh/MeshFactory.cpp",
    "chars": 38,
    "preview": "#include \"Widgets/Mesh/MeshFactory.h\"\n"
  },
  {
    "path": "Source/FairyGUI/Private/Widgets/Mesh/PolygonMesh.cpp",
    "chars": 5955,
    "preview": "#include \"Widgets/Mesh/PolygonMesh.h\"\n\nFPolygonMesh::FPolygonMesh() :\n    LineWidth(0),\n    LineColor(FColor::Black),\n  "
  },
  {
    "path": "Source/FairyGUI/Private/Widgets/Mesh/RectMesh.cpp",
    "chars": 1717,
    "preview": "#include \"Widgets/Mesh/RectMesh.h\"\n\nFRectMesh::FRectMesh() :\n    LineWidth(0),\n    LineColor(FColor::Black)\n{\n}\n\nvoid FR"
  },
  {
    "path": "Source/FairyGUI/Private/Widgets/Mesh/RegularPolygonMesh.cpp",
    "chars": 2087,
    "preview": "#include \"Widgets/Mesh/RegularPolygonMesh.h\"\n\nFRegularPolygonMesh::FRegularPolygonMesh() :\n    Sides(3),\n    LineWidth(0"
  },
  {
    "path": "Source/FairyGUI/Private/Widgets/Mesh/RoundedMesh.cpp",
    "chars": 3771,
    "preview": "#include \"Widgets/Mesh/RoundedRectMesh.h\"\n\nFRoundedRectMesh::FRoundedRectMesh() :\n    LineWidth(0),\n    LineColor(FColor"
  },
  {
    "path": "Source/FairyGUI/Private/Widgets/Mesh/VertexHelper.cpp",
    "chars": 4149,
    "preview": "#include \"Widgets/Mesh/VertexHelper.h\"\n\nFVertexHelper::FVertexHelper() :\n    ContentRect(ForceInit),\n    UVRect(ForceIni"
  },
  {
    "path": "Source/FairyGUI/Private/Widgets/NGraphics.cpp",
    "chars": 4692,
    "preview": "#include \"Widgets/NGraphics.h\"\n\nFNGraphics::FNGraphics() :\n    Size(ForceInit),\n    Color(FColor::White),\n    Flip(EFlip"
  },
  {
    "path": "Source/FairyGUI/Private/Widgets/NTextFormat.cpp",
    "chars": 1813,
    "preview": "#include \"Widgets/NTextFormat.h\"\n#include \"UI/UIConfig.h\"\n#include \"UI/UIPackage.h\"\n\nFNTextFormat::FNTextFormat() :\n    "
  },
  {
    "path": "Source/FairyGUI/Private/Widgets/NTexture.cpp",
    "chars": 4045,
    "preview": "#include \"Widgets/NTexture.h\"\n#include \"FairyApplication.h\"\n\nUNTexture* UNTexture::WhiteTexture = nullptr;\n\nUNTexture* U"
  },
  {
    "path": "Source/FairyGUI/Private/Widgets/SContainer.cpp",
    "chars": 5441,
    "preview": "\n#include \"Widgets/SContainer.h\"\n#include \"FairyApplication.h\"\n#include \"UI/GObject.h\"\n\nSContainer::SContainer() :\n    C"
  },
  {
    "path": "Source/FairyGUI/Private/Widgets/SDisplayObject.cpp",
    "chars": 9087,
    "preview": "#include \"Widgets/SDisplayObject.h\"\n#include \"FairyApplication.h\"\n#include \"Engine/GameViewportClient.h\"\n#include \"UI/GO"
  },
  {
    "path": "Source/FairyGUI/Private/Widgets/SFImage.cpp",
    "chars": 9864,
    "preview": "#include \"Widgets/SFImage.h\"\n#include \"Widgets/NTexture.h\"\n#include \"Widgets/Mesh/VertexHelper.h\"\n#include \"UI/FieldType"
  },
  {
    "path": "Source/FairyGUI/Private/Widgets/SMovieClip.cpp",
    "chars": 6049,
    "preview": "#include \"Widgets/SMovieClip.h\"\n\nFMovieClipData::FMovieClipData() :\n    Interval(0),\n    RepeatDelay(0),\n    bSwing(fals"
  },
  {
    "path": "Source/FairyGUI/Private/Widgets/SShape.cpp",
    "chars": 785,
    "preview": "#include \"Widgets/SShape.h\"\n#include \"Widgets/NTexture.h\"\n#include \"Widgets/Mesh/VertexHelper.h\"\n\nSShape::SShape()\n{\n}\n\n"
  },
  {
    "path": "Source/FairyGUI/Private/Widgets/STextField.cpp",
    "chars": 9583,
    "preview": "#include \"Widgets/STextField.h\"\n#include \"Internationalization/BreakIterator.h\"\n#include \"Utils/HTMLParser.h\"\n#include \""
  },
  {
    "path": "Source/FairyGUI/Private/Widgets/STextInput.cpp",
    "chars": 2762,
    "preview": "#include \"Widgets/STextInput.h\"\n#include \"Widgets/Text/SlateEditableTextLayout.h\"\n\nclass SMyTextInput : public SMultiLin"
  },
  {
    "path": "Source/FairyGUI/Public/Event/EventContext.h",
    "chars": 3541,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"UObject/NoExportTypes.h\"\n#include \"Input/Events.h\"\n#include \"EventTypes"
  },
  {
    "path": "Source/FairyGUI/Public/Event/EventTypes.h",
    "chars": 859,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"UObject/NoExportTypes.h\"\n\nstruct FAIRYGUI_API FUIEvents\n{\n    static co"
  },
  {
    "path": "Source/FairyGUI/Public/FairyApplication.h",
    "chars": 7169,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"UObject/NoExportTypes.h\"\n#include \"Engine/GameViewportClient.h\"\n#includ"
  },
  {
    "path": "Source/FairyGUI/Public/FairyBlueprintLibrary.h",
    "chars": 3534,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"UObject/NoExportTypes.h\"\n#include \"Kismet/BlueprintFunctionLibrary.h\"\n#"
  },
  {
    "path": "Source/FairyGUI/Public/FairyCommons.h",
    "chars": 239,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n\nFAIRYGUI_API DECLARE_LOG_CATEGORY_EXTERN(LogFairyGUI, Log, All)\n\nextern const FS"
  },
  {
    "path": "Source/FairyGUI/Public/FairyGUI.h",
    "chars": 1117,
    "preview": "#pragma once\n\n#include \"UI/UIObjectFactory.h\"\n#include \"UI/UIPackage.h\"\n#include \"UI/PackageItem.h\"\n#include \"UI/GCompon"
  },
  {
    "path": "Source/FairyGUI/Public/FairyGUIModule.h",
    "chars": 363,
    "preview": "// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.\n\n#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"Modules/M"
  },
  {
    "path": "Source/FairyGUI/Public/Tween/EaseManager.h",
    "chars": 223,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"EaseType.h\"\n\nclass FAIRYGUI_API EaseManager\n{\npublic:\n    static float "
  },
  {
    "path": "Source/FairyGUI/Public/Tween/EaseType.h",
    "chars": 535,
    "preview": "#pragma once\n\n#include \"EaseType.generated.h\"\n\nUENUM()\nenum class EEaseType : uint8\n{\n    Linear,\n    SineIn,\n    SineOu"
  },
  {
    "path": "Source/FairyGUI/Public/Tween/GPath.h",
    "chars": 1558,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n\nstruct FAIRYGUI_API FGPathPoint\n{\n    enum class ECurveType\n    {\n        CRSpli"
  },
  {
    "path": "Source/FairyGUI/Public/Tween/GTween.h",
    "chars": 1768,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"GTweener.h\"\n#include \"EaseType.h\"\n#include \"TweenValue.h\"\n\nclass FAIRYG"
  },
  {
    "path": "Source/FairyGUI/Public/Tween/GTweener.h",
    "chars": 3212,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"EaseType.h\"\n#include \"TweenValue.h\"\n#include \"TweenerHandle.h\"\n#include"
  },
  {
    "path": "Source/FairyGUI/Public/Tween/TweenManager.h",
    "chars": 981,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"Engine/Engine.h\"\n#include \"Tickable.h\"\n#include \"GTweener.h\"\n\nclass UGO"
  },
  {
    "path": "Source/FairyGUI/Public/Tween/TweenValue.h",
    "chars": 925,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"TweenValue.generated.h\"\n\nUSTRUCT(BlueprintType)\nstruct FAIRYGUI_API FTw"
  },
  {
    "path": "Source/FairyGUI/Public/Tween/TweenerHandle.h",
    "chars": 1660,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"TweenerHandle.generated.h\"\n\nUSTRUCT(BlueprintType)\nstruct FAIRYGUI_API "
  },
  {
    "path": "Source/FairyGUI/Public/UI/ControllerAction/ChangePageAction.h",
    "chars": 368,
    "preview": "#pragma once\n\n#include \"ControllerAction.h\"\n\nclass FChangePageAction : public FControllerAction\n{\npublic:\n    virtual vo"
  },
  {
    "path": "Source/FairyGUI/Public/UI/ControllerAction/ControllerAction.h",
    "chars": 561,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n\nclass UGController;\nclass FByteBuffer;\n\nclass FControllerAction\n{\npublic:\n    st"
  },
  {
    "path": "Source/FairyGUI/Public/UI/ControllerAction/PlayTransitionAction.h",
    "chars": 472,
    "preview": "#pragma once\n\n#include \"ControllerAction.h\"\n\nclass UTransition;\n\nclass FPlayTransitionAction : public FControllerAction\n"
  },
  {
    "path": "Source/FairyGUI/Public/UI/DragDropManager.h",
    "chars": 1071,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"UObject/NoExportTypes.h\"\n#include \"Event/EventContext.h\"\n#include \"UI/G"
  },
  {
    "path": "Source/FairyGUI/Public/UI/FieldTypes.h",
    "chars": 3419,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"UObject/NoExportTypes.h\"\n#include \"FieldTypes.generated.h\"\n\nUENUM()\nenu"
  },
  {
    "path": "Source/FairyGUI/Public/UI/GButton.h",
    "chars": 3717,
    "preview": "#pragma once\n\n#include \"GComponent.h\"\n#include \"GButton.generated.h\"\n\nclass UGController;\nclass UGTextField;\n\nUCLASS(Blu"
  },
  {
    "path": "Source/FairyGUI/Public/UI/GComboBox.h",
    "chars": 3921,
    "preview": "#pragma once\n\n#include \"GComponent.h\"\n#include \"GComboBox.generated.h\"\n\nclass UGController;\nclass UGTextField;\nclass UGL"
  },
  {
    "path": "Source/FairyGUI/Public/UI/GComponent.h",
    "chars": 8287,
    "preview": "#pragma once\n\n#include \"GObject.h\"\n#include \"ScrollPane.h\"\n#include \"GComponent.generated.h\"\n\nclass UGController;\nclass "
  },
  {
    "path": "Source/FairyGUI/Public/UI/GController.h",
    "chars": 1939,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"UObject/NoExportTypes.h\"\n#include \"ControllerAction/ControllerAction.h\""
  },
  {
    "path": "Source/FairyGUI/Public/UI/GGraph.h",
    "chars": 2137,
    "preview": "#pragma once\n\n#include \"GObject.h\"\n#include \"GGraph.generated.h\"\n\nUCLASS(BlueprintType)\nclass FAIRYGUI_API UGGraph : pub"
  },
  {
    "path": "Source/FairyGUI/Public/UI/GGroup.h",
    "chars": 2675,
    "preview": "#pragma once\n\n#include \"GObject.h\"\n#include \"GGroup.generated.h\"\n\nUCLASS(BlueprintType)\nclass FAIRYGUI_API UGGroup : pub"
  },
  {
    "path": "Source/FairyGUI/Public/UI/GImage.h",
    "chars": 1669,
    "preview": "#pragma once\n\n#include \"GObject.h\"\n#include \"GImage.generated.h\"\n\nUCLASS(BlueprintType)\nclass FAIRYGUI_API UGImage : pub"
  },
  {
    "path": "Source/FairyGUI/Public/UI/GLabel.h",
    "chars": 1484,
    "preview": "#pragma once\n\n#include \"GComponent.h\"\n#include \"GLabel.generated.h\"\n\nclass UGTextField;\n\nUCLASS(BlueprintType, Blueprint"
  },
  {
    "path": "Source/FairyGUI/Public/UI/GList.h",
    "chars": 9463,
    "preview": "#pragma once\n\n#include \"GComponent.h\"\n#include \"GList.generated.h\"\n\nclass FGObjectPool;\n\nDECLARE_DELEGATE_TwoParams(FLis"
  },
  {
    "path": "Source/FairyGUI/Public/UI/GLoader.h",
    "chars": 4072,
    "preview": "#pragma once\n\n#include \"GObject.h\"\n#include \"GLoader.generated.h\"\n\nUCLASS(BlueprintType, Blueprintable)\nclass FAIRYGUI_A"
  },
  {
    "path": "Source/FairyGUI/Public/UI/GLoader3D.h",
    "chars": 1500,
    "preview": "#pragma once\n\n#include \"GObject.h\"\n#include \"GLoader3D.generated.h\"\n\nUCLASS(BlueprintType, Blueprintable)\nclass FAIRYGUI"
  },
  {
    "path": "Source/FairyGUI/Public/UI/GMovieClip.h",
    "chars": 2440,
    "preview": "#pragma once\n\n#include \"GObject.h\"\n#include \"Event/EventContext.h\"\n#include \"GMovieClip.generated.h\"\n\nUCLASS(BlueprintTy"
  },
  {
    "path": "Source/FairyGUI/Public/UI/GObject.h",
    "chars": 14940,
    "preview": "#pragma once\n\n#include \"Relations.h\"\n#include \"PackageItem.h\"\n#include \"UIConfig.h\"\n#include \"FairyCommons.h\"\n#include \""
  },
  {
    "path": "Source/FairyGUI/Public/UI/GObjectPool.h",
    "chars": 388,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"UObject/NoExportTypes.h\"\n\nclass UGObject;\n\nclass FGObjectPool : public "
  },
  {
    "path": "Source/FairyGUI/Public/UI/GProgressBar.h",
    "chars": 1743,
    "preview": "#pragma once\n\n#include \"GComponent.h\"\n#include \"GProgressBar.generated.h\"\n\nUCLASS(BlueprintType, Blueprintable)\nclass FA"
  },
  {
    "path": "Source/FairyGUI/Public/UI/GRichTextField.h",
    "chars": 360,
    "preview": "#pragma once\n\n#include \"GTextField.h\"\n#include \"GRichTextField.generated.h\"\n\nUCLASS(BlueprintType)\nclass FAIRYGUI_API UG"
  },
  {
    "path": "Source/FairyGUI/Public/UI/GRoot.h",
    "chars": 2925,
    "preview": "#pragma once\n\n#include \"GComponent.h\"\n#include \"GRoot.generated.h\"\n\nclass UGGraph;\nclass UGWindow;\n\nUCLASS(BlueprintType"
  },
  {
    "path": "Source/FairyGUI/Public/UI/GScrollBar.h",
    "chars": 1069,
    "preview": "#pragma once\n\n#include \"GComponent.h\"\n#include \"GScrollBar.generated.h\"\n\nclass UScrollPane;\n\nUCLASS(BlueprintType, Bluep"
  },
  {
    "path": "Source/FairyGUI/Public/UI/GSlider.h",
    "chars": 2338,
    "preview": "#pragma once\n\n#include \"GComponent.h\"\n#include \"GSlider.generated.h\"\n\nUCLASS(BlueprintType, Blueprintable)\nclass FAIRYGU"
  },
  {
    "path": "Source/FairyGUI/Public/UI/GTextField.h",
    "chars": 2173,
    "preview": "#pragma once\n\n#include \"GObject.h\"\n#include \"Widgets/NTextFormat.h\"\n#include \"GTextField.generated.h\"\n\nUCLASS(BlueprintT"
  },
  {
    "path": "Source/FairyGUI/Public/UI/GTextInput.h",
    "chars": 2030,
    "preview": "#pragma once\n\n#include \"GObject.h\"\n#include \"Widgets/NTextFormat.h\"\n#include \"GTextInput.generated.h\"\n\nUCLASS(BlueprintT"
  },
  {
    "path": "Source/FairyGUI/Public/UI/GTree.h",
    "chars": 3535,
    "preview": "#pragma once\n\n#include \"GList.h\"\n#include \"GTreeNode.h\"\n#include \"GTree.generated.h\"\n\nDECLARE_DELEGATE_TwoParams(FTreeNo"
  },
  {
    "path": "Source/FairyGUI/Public/UI/GTreeNode.h",
    "chars": 3502,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"UObject/NoExportTypes.h\"\n#include \"Utils/NVariant.h\"\n#include \"GTreeNod"
  },
  {
    "path": "Source/FairyGUI/Public/UI/GWindow.h",
    "chars": 4669,
    "preview": "#pragma once\n\n#include \"GComponent.h\"\n#include \"GWindow.generated.h\"\n\nclass FAIRYGUI_API IUISource\n{\npublic:\n    virtual"
  },
  {
    "path": "Source/FairyGUI/Public/UI/Gears/GearAnimation.h",
    "chars": 535,
    "preview": "#pragma once\n\n#include \"GearBase.h\"\n\nclass FAIRYGUI_API FGearAnimation : public FGearBase\n{\npublic:\n    FGearAnimation(U"
  },
  {
    "path": "Source/FairyGUI/Public/UI/Gears/GearBase.h",
    "chars": 1306,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"Tween/GTween.h\"\n\nclass UGObject;\nclass UGController;\nclass FByteBuffer;"
  },
  {
    "path": "Source/FairyGUI/Public/UI/Gears/GearColor.h",
    "chars": 616,
    "preview": "#pragma once\n\n#include \"GearBase.h\"\n\nclass FAIRYGUI_API FGearColor : public FGearBase\n{\npublic:\n    FGearColor(UGObject*"
  },
  {
    "path": "Source/FairyGUI/Public/UI/Gears/GearDisplay.h",
    "chars": 539,
    "preview": "#pragma once\n\n#include \"GearBase.h\"\n\nclass FAIRYGUI_API FGearDisplay : public FGearBase\n{\npublic:\n    FGearDisplay(UGObj"
  },
  {
    "path": "Source/FairyGUI/Public/UI/Gears/GearDisplay2.h",
    "chars": 487,
    "preview": "#pragma once\n\n#include \"GearBase.h\"\n\nclass FAIRYGUI_API FGearDisplay2 : public FGearBase\n{\npublic:\n    FGearDisplay2(UGO"
  },
  {
    "path": "Source/FairyGUI/Public/UI/Gears/GearFontSize.h",
    "chars": 436,
    "preview": "#pragma once\n\n#include \"GearBase.h\"\n\nclass FAIRYGUI_API FGearFontSize : public FGearBase\n{\npublic:\n    FGearFontSize(UGO"
  },
  {
    "path": "Source/FairyGUI/Public/UI/Gears/GearIcon.h",
    "chars": 428,
    "preview": "#pragma once\n\n#include \"GearBase.h\"\n\nclass FAIRYGUI_API FGearIcon : public FGearBase\n{\npublic:\n    FGearIcon(UGObject* I"
  },
  {
    "path": "Source/FairyGUI/Public/UI/Gears/GearLook.h",
    "chars": 642,
    "preview": "#pragma once\n\n#include \"GearBase.h\"\n\nclass FAIRYGUI_API FGearLook : public FGearBase\n{\npublic:\n    FGearLook(UGObject* I"
  },
  {
    "path": "Source/FairyGUI/Public/UI/Gears/GearSize.h",
    "chars": 574,
    "preview": "#pragma once\n\n#include \"GearBase.h\"\n\nclass FAIRYGUI_API FGearSize : public FGearBase\n{\npublic:\n    FGearSize(UGObject* I"
  },
  {
    "path": "Source/FairyGUI/Public/UI/Gears/GearText.h",
    "chars": 428,
    "preview": "#pragma once\n\n#include \"GearBase.h\"\n\nclass FAIRYGUI_API FGearText : public FGearBase\n{\npublic:\n    FGearText(UGObject* I"
  },
  {
    "path": "Source/FairyGUI/Public/UI/Gears/GearXY.h",
    "chars": 666,
    "preview": "#pragma once\n\n#include \"GearBase.h\"\n\nclass FAIRYGUI_API FGearXY : public FGearBase\n{\npublic:\n    FGearXY(UGObject* InOwn"
  },
  {
    "path": "Source/FairyGUI/Public/UI/PackageItem.h",
    "chars": 1314,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"Engine/Texture2D.h\"\n#include \"FieldTypes.h\"\n#include \"Engine.h\"\n#includ"
  },
  {
    "path": "Source/FairyGUI/Public/UI/PopupMenu.h",
    "chars": 2898,
    "preview": "#pragma once\n\n#include \"GList.h\"\n#include \"GButton.h\"\n#include \"PopupMenu.generated.h\"\n\nUCLASS(BlueprintType)\nclass FAIR"
  },
  {
    "path": "Source/FairyGUI/Public/UI/RelationItem.h",
    "chars": 1324,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"FieldTypes.h\"\n\nclass UGObject;\n\nstruct FAIRYGUI_API FRelationDef\n{\n    "
  },
  {
    "path": "Source/FairyGUI/Public/UI/Relations.h",
    "chars": 837,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"UObject/NoExportTypes.h\"\n#include \"RelationItem.h\"\n\nclass UGObject;\ncla"
  },
  {
    "path": "Source/FairyGUI/Public/UI/ScrollPane.h",
    "chars": 8356,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"Styling/SlateTypes.h\"\n#include \"FieldTypes.h\"\n#include \"Tween/GTween.h\""
  },
  {
    "path": "Source/FairyGUI/Public/UI/Transition.h",
    "chars": 5348,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"Tween/GTween.h\"\n#include \"Event/EventContext.h\"\n#include \"Transition.ge"
  },
  {
    "path": "Source/FairyGUI/Public/UI/TranslationHelper.h",
    "chars": 285,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n\nclass FPackageItem;\n\nclass FTranslationHelper\n{\npublic:\n    static TMap<FString,"
  },
  {
    "path": "Source/FairyGUI/Public/UI/UIConfig.h",
    "chars": 2469,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"Engine/Texture2D.h\"\n#include \"FieldTypes.h\"\n#include \"UIConfig.generate"
  },
  {
    "path": "Source/FairyGUI/Public/UI/UIObjectFactory.h",
    "chars": 769,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"FieldTypes.h\"\n#include \"PackageItem.h\"\n\nclass UGComponent;\nclass UGLoad"
  },
  {
    "path": "Source/FairyGUI/Public/UI/UIPackage.h",
    "chars": 4693,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"UObject/NoExportTypes.h\"\n#include \"UIPackage.generated.h\"\n\nclass FPacka"
  },
  {
    "path": "Source/FairyGUI/Public/UIPackageAsset.h",
    "chars": 455,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"UObject/NoExportTypes.h\"\n#include \"UIPackageAsset.generated.h\"\n\nUCLASS("
  },
  {
    "path": "Source/FairyGUI/Public/Utils/ByteBuffer.h",
    "chars": 1296,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"FairyCommons.h\"\n\nclass FAIRYGUI_API FByteBuffer\n{\npublic:\n    FByteBuff"
  },
  {
    "path": "Source/FairyGUI/Public/Utils/HTMLElement.h",
    "chars": 450,
    "preview": "#pragma once\n\n#include \"Slate.h\"\n#include \"Widgets/NTextFormat.h\"\n#include \"XMLAttributes.h\"\n\nenum class EHTMLElementTyp"
  },
  {
    "path": "Source/FairyGUI/Public/Utils/HTMLParser.h",
    "chars": 863,
    "preview": "#pragma once\n\n#include \"HTMLElement.h\"\n\nstruct FAIRYGUI_API FHTMLParseOptions\n{\n    bool bLinkUnderline;\n    FColor Link"
  },
  {
    "path": "Source/FairyGUI/Public/Utils/NVariant.h",
    "chars": 1699,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"Containers/Union.h\"\n#include \"NVariant.generated.h\"\n\nUSTRUCT(BlueprintT"
  },
  {
    "path": "Source/FairyGUI/Public/Utils/UBBParser.h",
    "chars": 1367,
    "preview": "#pragma once\n\n#include \"Slate.h\"\n#include \"Widgets/NTextFormat.h\"\n\nDECLARE_DELEGATE_RetVal_ThreeParams(FString, FTagHand"
  },
  {
    "path": "Source/FairyGUI/Public/Utils/XMLAttributes.h",
    "chars": 454,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n\nstruct FXMLAttributes : TMap<FString, FString>\n{\n    const FString& Get(const FS"
  },
  {
    "path": "Source/FairyGUI/Public/Utils/XMLIterator.h",
    "chars": 783,
    "preview": "#pragma once\n\n#include \"XMLAttributes.h\"\n\nenum class EXMLTagType\n{\n    Start,\n    End,\n    Void,\n    CDATA,\n    Comment,"
  },
  {
    "path": "Source/FairyGUI/Public/Widgets/BitmapFont.h",
    "chars": 512,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n\nclass UNTexture;\n\nstruct FAIRYGUI_API FBitmapFont : public FGCObject\n{\n    struc"
  },
  {
    "path": "Source/FairyGUI/Public/Widgets/BitmapFontRun.h",
    "chars": 2905,
    "preview": "#pragma once\n\n#include \"Slate.h\"\n#include \"BitmapFont.h\"\n\nclass FArrangedChildren;\nclass FPaintArgs;\nclass FSlateWindowE"
  },
  {
    "path": "Source/FairyGUI/Public/Widgets/HitTest.h",
    "chars": 1069,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n\nclass FAIRYGUI_API IHitTest\n{\npublic:\n    virtual bool HitTest(const FBox2D& Con"
  },
  {
    "path": "Source/FairyGUI/Public/Widgets/LoaderRun.h",
    "chars": 3063,
    "preview": "#pragma once\n\n#include \"Slate.h\"\n#include \"Utils/HTMLElement.h\"\n\nclass UFairyApplication;\nclass FArrangedChildren;\nclass"
  },
  {
    "path": "Source/FairyGUI/Public/Widgets/Mesh/EllipseMesh.h",
    "chars": 603,
    "preview": "#pragma once\n\n#include \"MeshFactory.h\"\n#include \"Widgets/HitTest.h\"\n\nclass FAIRYGUI_API FEllipseMesh : public IMeshFacto"
  },
  {
    "path": "Source/FairyGUI/Public/Widgets/Mesh/FillMesh.h",
    "chars": 348,
    "preview": "#pragma once\n\n#include \"MeshFactory.h\"\n#include \"UI/FieldTypes.h\"\n\nclass FAIRYGUI_API FFillMesh : public IMeshFactory\n{\n"
  },
  {
    "path": "Source/FairyGUI/Public/Widgets/Mesh/MeshFactory.h",
    "chars": 1289,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"UObject/NoExportTypes.h\"\n#include \"VertexHelper.h\"\n#include \"Widgets/Hi"
  },
  {
    "path": "Source/FairyGUI/Public/Widgets/Mesh/PolygonMesh.h",
    "chars": 757,
    "preview": "#pragma once\n\n#include \"MeshFactory.h\"\n\nclass FAIRYGUI_API FPolygonMesh : public IMeshFactory, public IHitTest\n{\npublic:"
  },
  {
    "path": "Source/FairyGUI/Public/Widgets/Mesh/RectMesh.h",
    "chars": 386,
    "preview": "#pragma once\n\n#include \"MeshFactory.h\"\n\nclass FAIRYGUI_API FRectMesh : public IMeshFactory\n{\npublic:\n    MESHFACTORY_TYP"
  },
  {
    "path": "Source/FairyGUI/Public/Widgets/Mesh/RegularPolygonMesh.h",
    "chars": 489,
    "preview": "#pragma once\n\n#include \"MeshFactory.h\"\n\nclass FAIRYGUI_API FRegularPolygonMesh : public IMeshFactory\n{\npublic:\n    MESHF"
  },
  {
    "path": "Source/FairyGUI/Public/Widgets/Mesh/RoundedRectMesh.h",
    "chars": 484,
    "preview": "#pragma once\n\n#include \"MeshFactory.h\"\n\nclass FAIRYGUI_API FRoundedRectMesh : public IMeshFactory\n{\npublic:\n    MESHFACT"
  },
  {
    "path": "Source/FairyGUI/Public/Widgets/Mesh/VertexHelper.h",
    "chars": 1271,
    "preview": "#pragma once\n\n#include \"Slate.h\"\n\nclass FAIRYGUI_API FVertexHelper\n{\npublic:\n    FVertexHelper();\n\n    void Clear();\n   "
  },
  {
    "path": "Source/FairyGUI/Public/Widgets/MeshFactory.h",
    "chars": 935,
    "preview": "#pragma once\n\n#include \"VertexHelper.h\"\n\n#define MESHFACTORY_TYPE(TYPE) \\\n\tstatic const FName& GetMeshFactoryTypeId() { "
  },
  {
    "path": "Source/FairyGUI/Public/Widgets/NGraphics.h",
    "chars": 1725,
    "preview": "#pragma once\n\n#include \"Mesh/MeshFactory.h\"\n#include \"NTexture.h\"\n#include \"UI/FieldTypes.h\"\n\nclass FAIRYGUI_API FNGraph"
  },
  {
    "path": "Source/FairyGUI/Public/Widgets/NTextFormat.h",
    "chars": 1644,
    "preview": "#pragma once\n\n#include \"Slate.h\"\n#include \"UI/FieldTypes.h\"\n#include \"NTextFormat.generated.h\"\n\nUSTRUCT(BlueprintType)\ns"
  },
  {
    "path": "Source/FairyGUI/Public/Widgets/NTexture.h",
    "chars": 1130,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"UObject/NoExportTypes.h\"\n#include \"Runtime/Engine/Classes/Engine/Textur"
  },
  {
    "path": "Source/FairyGUI/Public/Widgets/SContainer.h",
    "chars": 1256,
    "preview": "#pragma once\n\n#include \"SDisplayObject.h\"\n\nclass FAIRYGUI_API SContainer : public SDisplayObject\n{\npublic:\n    SLATE_BEG"
  },
  {
    "path": "Source/FairyGUI/Public/Widgets/SDisplayObject.h",
    "chars": 3139,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"UObject/NoExportTypes.h\"\n#include \"Slate.h\"\n\nclass UGObject;\n\nclass FAI"
  },
  {
    "path": "Source/FairyGUI/Public/Widgets/SFImage.h",
    "chars": 1751,
    "preview": "#pragma once\n\n#include \"SDisplayObject.h\"\n#include \"UI/FieldTypes.h\"\n#include \"Mesh/FillMesh.h\"\n#include \"NTexture.h\"\n#i"
  },
  {
    "path": "Source/FairyGUI/Public/Widgets/SMovieClip.h",
    "chars": 1876,
    "preview": "#pragma once\n\n#include \"SFImage.h\"\n\nstruct FAIRYGUI_API FMovieClipData : public FGCObject\n{\n    struct Frame\n    {\n     "
  },
  {
    "path": "Source/FairyGUI/Public/Widgets/SShape.h",
    "chars": 635,
    "preview": "#pragma once\n\n#include \"SDisplayObject.h\"\n#include \"NTexture.h\"\n#include \"NGraphics.h\"\n\nclass FAIRYGUI_API SShape : publ"
  },
  {
    "path": "Source/FairyGUI/Public/Widgets/STextField.h",
    "chars": 1885,
    "preview": "#pragma once\n\n#include \"SDisplayObject.h\"\n#include \"UI/FieldTypes.h\"\n#include \"NTextFormat.h\"\n#include \"Utils/HTMLElemen"
  },
  {
    "path": "Source/FairyGUI/Public/Widgets/STextInput.h",
    "chars": 1089,
    "preview": "#pragma once\n\n#include \"SDisplayObject.h\"\n#include \"NTextFormat.h\"\n\nclass FAIRYGUI_API STextInput : public SDisplayObjec"
  },
  {
    "path": "Source/FairyGUIEditor/FairyGUIEditor.Build.cs",
    "chars": 1098,
    "preview": "// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.\n\nusing UnrealBuildTool;\n\npublic class FairyGUIEditor : Modu"
  },
  {
    "path": "Source/FairyGUIEditor/Private/FairyGUIEditor.cpp",
    "chars": 646,
    "preview": "// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.\n\n#include \"FairyGUIEditor.h\"\n#include \"Editor.h\"\n\n#define L"
  },
  {
    "path": "Source/FairyGUIEditor/Private/FairyGUIFactory.cpp",
    "chars": 2653,
    "preview": "#include \"FairyGUIFactory.h\"\n#include \"Serialization/BufferArchive.h\"\n#include \"EditorFramework/AssetImportData.h\"\n#incl"
  },
  {
    "path": "Source/FairyGUIEditor/Public/FairyGUIEditor.h",
    "chars": 326,
    "preview": "// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.\n\n#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"Modules/M"
  },
  {
    "path": "Source/FairyGUIEditor/Public/FairyGUIFactory.h",
    "chars": 757,
    "preview": "#pragma once\n\n#include \"CoreMinimal.h\"\n#include \"Factories/Factory.h\"\n#include \"EditorReimportHandler.h\"\n#include \"Fairy"
  }
]

About this extraction

This page contains the full source code of the fairygui/FairyGUI-unreal GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 197 files (810.9 KB), approximately 217.3k tokens, and a symbol index with 477 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!