Skip to content

Commit 2139e99

Browse files
committed
Implement EditorInitializer
Add a utility class which helps to call initialization function only when the condition is met on the main thread. Also, change IOSResolver and PlayServicesResolver to utilize this. Bug: 154730431 Change-Id: If0eb71883ce6680aa55051a9f7b9c700e5a93ba5
1 parent 310a5c2 commit 2139e99

File tree

4 files changed

+97
-56
lines changed

4 files changed

+97
-56
lines changed

source/AndroidResolver/src/PlayServicesResolver.cs

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -901,40 +901,20 @@ public static bool AutomaticResolutionEnabled {
901901
/// Initializes the <see cref="GooglePlayServices.PlayServicesResolver"/> class.
902902
/// </summary>
903903
static PlayServicesResolver() {
904-
// Cache the flag to prevent string comparison in every frame during
905-
// PollOnUpdateUntilComplete()
906-
bool isExecuteMethodEnabled = ExecutionEnvironment.ExecuteMethodEnabled;
907-
908-
// Delay initialization until the build target is iOS and the editor is not in play
904+
// Delay initialization until the build target is Android and the editor is not in play
909905
// mode.
910-
RunOnMainThread.PollOnUpdateUntilComplete(() => {
911-
if (EditorUserBuildSettings.activeBuildTarget != BuildTarget.Android ||
912-
EditorApplication.isPlayingOrWillChangePlaymode) {
913-
// If Unity is launched with -executeMethod, in some Unity versions, editor
914-
// update will never be called. As a result, PollOnUpdateUntilComplete() will
915-
// attempt to call this poll function repeating on current thread until it
916-
// returns true. Therefore, return true immediately and stop the polling in
917-
// executeMethod mode.
918-
return isExecuteMethodEnabled;
919-
}
920-
Initialize();
921-
return true;
922-
});
906+
EditorInitializer.InitializeOnMainThread(condition: () => {
907+
return EditorUserBuildSettings.activeBuildTarget == BuildTarget.Android &&
908+
!EditorApplication.isPlayingOrWillChangePlaymode;
909+
}, initializer: Initialize, name: "PlayServicesResolver", logger: logger);
923910

924911
}
925912

926-
/// <summary>
927-
/// Whether Android Resolver have been initialized.
928-
/// </summary>
929-
private static bool isInitialized = false;
930-
931913
/// <summary>
932914
/// Initialize the module. This should be called on the main thread only if
933915
/// current active build target is Android and not in play mode.
934916
/// </summary>
935-
private static void Initialize() {
936-
if (isInitialized) return;
937-
917+
private static bool Initialize() {
938918
if ( EditorUserBuildSettings.activeBuildTarget != BuildTarget.Android ) {
939919
throw new Exception("PlayServiceResolver.Initialize() is called when active " +
940920
"build target is not Android. This should never happen. If it does, " +
@@ -967,8 +947,7 @@ private static void Initialize() {
967947

968948
if (SettingsDialogObj.EnableAutoResolution) LinkAutoResolution();
969949

970-
isInitialized = true;
971-
Log("Android Resolver Initialized", level: LogLevel.Verbose);
950+
return true;
972951
}
973952

974953
// Unregister events to monitor build system changes for the Android Resolver and other

source/IOSResolver/src/IOSResolver.cs

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -658,38 +658,19 @@ static IOSResolver() {
658658
// so we install the DLL loader first then try using the Xcode module.
659659
RemapXcodeExtension();
660660

661-
// Cache the flag to prevent string comparison in every frame during
662-
// PollOnUpdateUntilComplete()
663-
bool isExecuteMethodEnabled = ExecutionEnvironment.ExecuteMethodEnabled;
664-
665-
// Delay initialization until the build target is iOS and the editor is not in play mode.
666-
RunOnMainThread.PollOnUpdateUntilComplete(() => {
667-
if (EditorUserBuildSettings.activeBuildTarget != BuildTarget.iOS ||
668-
EditorApplication.isPlayingOrWillChangePlaymode) {
669-
// If Unity is launched with -executeMethod, in some Unity versions, editor
670-
// update will never be called. As a result, PollOnUpdateUntilComplete() will
671-
// attempt to call this poll function repeating on current thread until it returns
672-
// true. Therefore, return true immediately and stop the polling in executeMethod
673-
// mode.
674-
return isExecuteMethodEnabled;
675-
}
676-
Initialize();
677-
return true;
678-
});
661+
// Delay initialization until the build target is iOS and the editor is not in play
662+
// mode.
663+
EditorInitializer.InitializeOnMainThread(condition: () => {
664+
return EditorUserBuildSettings.activeBuildTarget == BuildTarget.iOS &&
665+
!EditorApplication.isPlayingOrWillChangePlaymode;
666+
}, initializer: Initialize, name: "IOSResolver", logger: logger);
679667
}
680668

681-
/// <summary>
682-
/// Whether iOSResolver have been initialized.
683-
/// </summary>
684-
private static bool isInitialized = false;
685-
686669
/// <summary>
687670
/// Initialize the module. This should be called on the main thread only if
688671
/// current active build target is iOS and not in play mode.
689672
/// </summary>
690-
private static void Initialize() {
691-
if (isInitialized) return;
692-
673+
private static bool Initialize() {
693674
if ( EditorUserBuildSettings.activeBuildTarget != BuildTarget.iOS ) {
694675
throw new Exception("IOSResolver.Initialize() is called when active build target " +
695676
"is not iOS. This should never happen. If it does, please report to the " +
@@ -757,9 +738,8 @@ exception is TypeInitializationException ||
757738
}
758739
});
759740
}
760-
isInitialized = true;
761741

762-
Log("IOSResolver Initialized", verbose: true);
742+
return true;
763743
}
764744

765745
/// <summary>

source/VersionHandlerImpl/VersionHandlerImpl.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
<Compile Include="src\DialogWindow.cs" />
5757
<Compile Include="src\Logger.cs" />
5858
<Compile Include="src\ExecutionEnvironment.cs" />
59+
<Compile Include="src\EditorInitializer.cs" />
5960
<Compile Include="src\EditorMeasurement.cs" />
6061
<Compile Include="src\FileUtils.cs" />
6162
<Compile Include="src\MultiSelectWindow.cs" />
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// <copyright file="EditorInitializer.cs" company="Google Inc.">
2+
// Copyright (C) 2020 Google Inc. All Rights Reserved.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
// </copyright>
16+
17+
namespace Google {
18+
19+
using System;
20+
using System.Collections.Generic;
21+
using System.IO;
22+
23+
using UnityEngine;
24+
using UnityEditor;
25+
26+
/// <summary>
27+
/// Utility to initialize classes used only in Unity Editor.
28+
/// </summary>
29+
static public class EditorInitializer {
30+
/// <summary>
31+
/// Call initialization function on the main thread only when the condition is met.
32+
/// </summary>
33+
/// <param name="condition">When it returns true, call the initializer once.
34+
/// If null, initializer will be called in the next editor update.</param>
35+
/// <param name="initializer">Initialization function to be called when condition is met.
36+
/// </params>
37+
/// <param name="name">Name of the component to be initialized, for debug purpose.</param>
38+
/// <param name="logger">Logger to be used to report when initialization is finished.</param>
39+
public static void InitializeOnMainThread(
40+
Func<bool> condition, Func<bool> initializer, string name, Logger logger = null) {
41+
if (initializer == null) return;
42+
43+
// Cache the flag to prevent string comparison in every frame during
44+
// PollOnUpdateUntilComplete()
45+
bool isExecuteMethodEnabled = ExecutionEnvironment.ExecuteMethodEnabled;
46+
47+
// Delay initialization until condition is met.
48+
RunOnMainThread.PollOnUpdateUntilComplete(() => {
49+
if (condition != null && !condition()) {
50+
// If Unity is launched with -executeMethod, in some Unity versions, editor
51+
// update will never be called. As a result, PollOnUpdateUntilComplete() will
52+
// attempt to call this poll function repeating on current thread until it returns
53+
// true. Therefore, return true immediately and stop the polling in executeMethod
54+
// mode.
55+
return isExecuteMethodEnabled;
56+
}
57+
bool result = false;
58+
59+
try {
60+
result = initializer();
61+
} catch (Exception e) {
62+
string errorMsg = String.Format("Exception thrown when initializing {0}: {1}",
63+
name, e.ToString());
64+
if (logger != null) {
65+
logger.Log(errorMsg, level: LogLevel.Error);
66+
} else {
67+
Debug.LogError(errorMsg);
68+
}
69+
}
70+
71+
if (logger != null) {
72+
logger.Log(String.Format("{0} initialization {1}", name,
73+
result ? "succeeded." : "failed." ),
74+
level: result ? LogLevel.Verbose : LogLevel.Error);
75+
}
76+
77+
return true;
78+
});
79+
}
80+
}
81+
}

0 commit comments

Comments
 (0)