Skip to content

How to Create a new Source

James edited this page Sep 28, 2025 · 4 revisions

A Source is a way for the Build Uploader to retrieve folders/files so it can then be saved to a temporary location in preparation of being modified and uploaded.

The Build Uploader uses reflection to find all classes inheriting from AUploadSource and displays them in a dropdown to be chosen. UploadSourceAttribute defines static data about the source such as what text to show in the dropdown.

using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using UnityEditor;
using UnityEngine;

/// <summary>
/// Auto picks the location of the last build made from Unity.
/// 
/// NOTE: This classes name path is saved in the JSON file so avoid renaming
/// </summary>
[UploadSourceAttribute("LastBuild", "Last Build Directory")]
public class LastBuildSource : AUploadSource
{
    public override void OnGUIExpanded(ref bool isDirty, StringFormatter.Context ctx)
    {
        EditorGUILayout.LabelField("Build Name:", LastBuildUtil.LastBuildName);
        
        using (new EditorGUILayout.HorizontalScope())
        {
            EditorGUILayout.LabelField("Directory:", LastBuildUtil.LastBuildDirectory);
            if (GUILayout.Button("Show", GUILayout.Width(100)))
            {
                if (!string.IsNullOrEmpty(LastBuildUtil.LastBuildDirectory))
                {
                    EditorUtility.RevealInFinder(LastBuildUtil.LastBuildDirectory);
                }
                else
                {
                    EditorUtility.DisplayDialog("Error",
                        "No last build directory found. Please build your project first.", "OK");
                }
            }
        }
    }

    public override void OnGUICollapsed(ref bool isDirty, float maxWidth, StringFormatter.Context ctx)
    {
        EditorGUILayout.LabelField(LastBuildUtil.LastBuildName, GUILayout.Width(100));
        EditorGUILayout.LabelField(LastBuildUtil.LastBuildDirectory, GUILayout.MaxWidth(maxWidth - 100));
    }

    public override async Task<bool> GetSource(UploadConfig uploadConfig, UploadTaskReport.StepResult stepResult,
        StringFormatter.Context ctx, CancellationTokenSource token)
    {
        // Wait for our turn if we need to
        await BuildConfigSource.m_lock.WaitAsync();

        try
        {
            if (string.IsNullOrEmpty(LastBuildUtil.LastBuildDirectory))
            {
                stepResult.AddError("No last build directory found. Please build your project first.");
                return false;
            }

            if (!Directory.Exists(LastBuildUtil.LastBuildDirectory))
            {
                stepResult.AddError($"Last build directory does not exist: {LastBuildUtil.LastBuildDirectory}");
                return false;
            }
        }
        finally
        {
            BuildConfigSource.m_lock.Release();
        }

        return true;
    }

    public override string SourceFilePath()
    {
        return LastBuildUtil.LastBuildDirectory;
    }

    public override void TryGetErrors(List<string> errors, StringFormatter.Context ctx)
    {
        base.TryGetErrors(errors, ctx);
        
        if (string.IsNullOrEmpty(LastBuildUtil.LastBuildDirectory))
        {
            errors.Add("No last build directory found. Please build your project first.");
        }
        else if (!Directory.Exists(LastBuildUtil.LastBuildDirectory))
        {
            errors.Add($"Last build directory does not exist: {LastBuildUtil.LastBuildDirectory}");
        }
    }

    public override Dictionary<string, object> Serialize()
    {
        return new Dictionary<string, object> { };
    }

    public override void Deserialize(Dictionary<string, object> data)
    {
        
    }
}

Clone this wiki locally