Skip to content

Commit

Permalink
Version 4.12.1
Browse files Browse the repository at this point in the history
 * MISC - Option to enable Harmony detour bridge (enabled by default for ReiPatcher setup if SRE is not supported)
 * MISC - Improved ForceUIResizing implementation
 * MISC - Some performance improvements during text component compatibility checks
 * BUG FIX - Disabled hooking of SpriteRenderer unless the hooking config is enabled
 * BUG FIX - Fixed PapagoTranslate API - Thanks to hype5 on Github
  • Loading branch information
randoman committed Aug 22, 2020
1 parent 07106a2 commit eece8aa
Show file tree
Hide file tree
Showing 25 changed files with 192 additions and 120 deletions.
9 changes: 8 additions & 1 deletion CHANGELOG.md
@@ -1,4 +1,11 @@
### 4.12.0
### 4.12.1
* MISC - Option to enable Harmony detour bridge (enabled by default for ReiPatcher setup if SRE is not supported)
* MISC - Improved ForceUIResizing implementation
* MISC - Some performance improvements during text component compatibility checks
* BUG FIX - Disabled hooking of SpriteRenderer unless the hooking config is enabled
* BUG FIX - Fixed PapagoTranslate API - Thanks to hype5 on Github

### 4.12.0
* FEATURE - Specialized plugin translation support. Can now read text translation files that are only used for specific plugins
* FEATURE - Proper IMGUI support in Unity 2018 and 2019+
* MISC - Changed guidance on IMGUI redistribution
Expand Down
3 changes: 2 additions & 1 deletion README.md
Expand Up @@ -283,7 +283,6 @@ TextGetterCompatibilityMode=False ;Indicates whether or not to enable "Text Gett
GameLogTextPaths= ;Indicates specific paths for game objects that the game uses as "log components", where it continuously appends or prepends text to. Requires expert knowledge to setup. This is a list seperated by ';'.
RomajiPostProcessing=ReplaceMacronWithCircumflex;RemoveApostrophes ;Indicates what type of post processing to do on 'translated' romaji texts. This can be important in certain games because the font used does not support various diacritics properly. This is a list seperated by ';'. Possible values: ["RemoveAllDiacritics", "ReplaceMacronWithCircumflex", "RemoveApostrophes"]
TranslationPostProcessing=ReplaceMacronWithCircumflex ;Indicates what type of post processing to do on translated texts (not romaji). Possible values: ["RemoveAllDiacritics", "ReplaceMacronWithCircumflex", "RemoveApostrophes", "ReplaceWideCharacters"]
ForceMonoModHooks=False ;Indicates that the plugin must use MonoMod hooks instead of harmony hooks
CacheRegexLookups=False ;Indicates whether or not results of regex lookups should be output to the specified OutputFile
CacheWhitespaceDifferences=False ;Indicates whether or not whitespace differences should be output to the specified OutputFile
CacheRegexPatternResults=False ;Indicates whether or not the complete result of regex-splitted translations should be output to the specified OutputFile
Expand All @@ -298,6 +297,8 @@ MaxTextParserRecursion=1 ;Indicates how many levels of recursion are all
HtmlEntityPreprocessing=True ;Will preprocess and decode html entities before they are send for translation. Some translators will fail when html entities are sent.
HandleRichText=True ;Will enable automated handling of rich text (text with markup)
EnableTranslationHelper=False ;Indicates if translator-related helpful log messages should be enabled. May be useful when tranlating based on redirected resources
ForceMonoModHooks=False ;Indicates that the plugin must use MonoMod hooks instead of harmony hooks
InitializeHarmonyDetourBridge=False ;Indicates the plugin should initial harmony detour bridge which allows harmony hooks to work in an environment where System.Reflection.Emit does not exist (usually such settings are handled by plugin managers, so don't use when using a plugin manager)

[Texture]
TextureDirectory=Translation\{Lang}\Texture ;Directory to dump textures to, and root of directories to load images from. Can use placeholder: {GameExeName}, {Lang}
Expand Down
13 changes: 7 additions & 6 deletions src/Translators/PapagoTranslate/PapagoTranslate.cs
Expand Up @@ -28,9 +28,8 @@ public class PapagoTranslate : HttpEndpoint
private static readonly string FormUrlEncodedTemplate = "honorific=false&source={0}&target={1}&text={2}";
private static readonly Random RandomNumbers = new Random();
private static readonly Guid UUID = Guid.NewGuid();

private static readonly Regex patternSource = new Regex( @"/vendors~main[^""]+", RegexOptions.Compiled | RegexOptions.Singleline );
private static readonly Regex patternVersion = new Regex( @"v\d\.\d\.\d_[^""]+", RegexOptions.Compiled | RegexOptions.Singleline );
private static readonly Regex PatternSource = new Regex( @"/vendors~main[^""]+", RegexOptions.Singleline );
private static readonly Regex PatternVersion = new Regex( @"v\d\.\d\.\d_[^""]+", RegexOptions.Singleline );

private string _version; // for hmac key
private bool _isSMT;
Expand Down Expand Up @@ -66,7 +65,9 @@ public override void Initialize( IInitializationContext context )

_isSMT = SMTLanguages.Contains( fixedSourceLanguage ) || SMTLanguages.Contains( fixedDestinationLanguage );

if( !SupportedLanguages.Contains( fixedDestinationLanguage ) ) throw new EndpointInitializationException( $"The language '{context.DestinationLanguage}' is not supported by Papago Translate." );
if( !SupportedLanguages.Contains( fixedDestinationLanguage ) )
throw new EndpointInitializationException( $"The language '{context.DestinationLanguage}' is not supported by Papago Translate." );

if( _isSMT )
{
// SMT can only be translated into English
Expand Down Expand Up @@ -170,7 +171,7 @@ private IEnumerator SetupVersion()
var iterator = response.GetSupportedEnumerator();
while( iterator.MoveNext() ) yield return iterator.Current;

var match = patternSource.Match( response.Data );
var match = PatternSource.Match( response.Data );
if( !match.Success )
{
XuaLogger.AutoTranslator.Warn( "Could not parse papago page" );
Expand All @@ -187,7 +188,7 @@ private IEnumerator SetupVersion()
var iterator = response.GetSupportedEnumerator();
while( iterator.MoveNext() ) yield return iterator.Current;

var match = patternVersion.Match( response.Data );
var match = PatternVersion.Match( response.Data );
if( !match.Success )
{
XuaLogger.AutoTranslator.Warn( "Could not parse papago version" );
Expand Down
2 changes: 1 addition & 1 deletion src/XUnity.AutoTranslator.Patcher/Patcher.cs
Expand Up @@ -29,7 +29,7 @@ public override string Version
{
get
{
return "4.12.0";
return "4.12.1";
}
}

Expand Down
Expand Up @@ -38,6 +38,8 @@ public IniFile Preferences

public string TranslationPath { get; }

public bool AllowDefaultInitializeHarmonyDetourBridge => false;

public IniFile ReloadConfig()
{
if( !File.Exists( _configPath ) )
Expand Down
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<TargetFramework>net35</TargetFramework>
<Version>4.12.0</Version>
<Version>4.12.1</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
139 changes: 100 additions & 39 deletions src/XUnity.AutoTranslator.Plugin.Core/AutoTranslationPlugin.cs
Expand Up @@ -35,6 +35,7 @@
using XUnity.ResourceRedirector;
using XUnity.Common.Extensions;
using XUnity.AutoTranslator.Plugin.Core.UIResize;
using MonoMod.RuntimeDetour;

namespace XUnity.AutoTranslator.Plugin.Core
{
Expand All @@ -48,6 +49,8 @@ public class AutoTranslationPlugin : MonoBehaviour, IInternalTranslator, ITransl
/// </summary>
internal static AutoTranslationPlugin Current;

private static bool _hasResizedCurrentComponentDuringDiscovery;

internal XuaWindow MainWindow;
internal TranslationAggregatorWindow TranslationAggregatorWindow;
internal TranslationAggregatorOptionsWindow TranslationAggregatorOptionsWindow;
Expand Down Expand Up @@ -108,6 +111,8 @@ public void Initialize()
// Setup console, if enabled
DebugConsole.Enable();

InitializeHarmonyDetourBridge();

InitializeTextTranslationCaches();

// Setup hooks
Expand Down Expand Up @@ -146,6 +151,26 @@ public void Initialize()
XuaLogger.AutoTranslator.Info( $"Loaded XUnity.AutoTranslator into Unity [{Application.unityVersion}] game." );
}

private static void InitializeHarmonyDetourBridge()
{
try
{
if( Settings.InitializeHarmonyDetourBridge )
{
InitializeHarmonyDetourBridgeSafe();
}
}
catch( Exception e )
{
XuaLogger.AutoTranslator.Error( e, "An error occurred while initializing harmony detour bridge." );
}
}

private static void InitializeHarmonyDetourBridgeSafe()
{
HarmonyDetourBridge.Init();
}

private void InitializeTextTranslationCaches()
{
try
Expand Down Expand Up @@ -566,15 +591,28 @@ internal string Hook_TextChanged_WithResult( object ui, string text, bool onEnab
string result = null;
if( _textHooksEnabled && !_temporarilyDisabled )
{
var info = ui.GetOrCreateTextTranslationInfo();
if( onEnable && info != null && CallOrigin.TextCache != null )
try
{
info.TextCache = CallOrigin.TextCache;
}
var info = ui.GetOrCreateTextTranslationInfo();
var isComponentActive = DiscoverComponent( ui, info );

CallOrigin.ExpectsTextToBeReturned = true;
if( onEnable && info != null && CallOrigin.TextCache != null )
{
info.TextCache = CallOrigin.TextCache;
}

result = TranslateOrQueueWebJob( ui, text, false, info );
CallOrigin.ExpectsTextToBeReturned = true;

result = TranslateOrQueueWebJob( ui, text, isComponentActive, info );
}
catch( Exception e )
{
XuaLogger.AutoTranslator.Warn( e, "An unexpected error occurred." );
}
finally
{
_hasResizedCurrentComponentDuringDiscovery = false;
}
}

if( onEnable )
Expand All @@ -593,13 +631,26 @@ internal void Hook_TextChanged( object ui, bool onEnable )
{
if( _textHooksEnabled && !_temporarilyDisabled )
{
var info = ui.GetOrCreateTextTranslationInfo();
if( onEnable && info != null && CallOrigin.TextCache != null )
try
{
info.TextCache = CallOrigin.TextCache;
}
var info = ui.GetOrCreateTextTranslationInfo();
var isComponentActive = DiscoverComponent( ui, info );

TranslateOrQueueWebJob( ui, null, false, info );
if( onEnable && info != null && CallOrigin.TextCache != null )
{
info.TextCache = CallOrigin.TextCache;
}

TranslateOrQueueWebJob( ui, null, isComponentActive, info );
}
catch( Exception e )
{
XuaLogger.AutoTranslator.Warn( e, "An unexpected error occurred." );
}
finally
{
_hasResizedCurrentComponentDuringDiscovery = false;
}
}

if( onEnable )
Expand Down Expand Up @@ -629,41 +680,41 @@ internal void Hook_ImageChanged( ref Texture2D texture, bool isPrefixHooked )
HandleImage( null, ref texture, isPrefixHooked );
}

internal void Hook_HandleComponent( object ui )
private bool DiscoverComponent( object ui, TextTranslationInfo info )
{
if( info == null ) return true;

try
{
if( _hasValidOverrideFont )
if( ( _hasValidOverrideFont || Settings.ForceUIResizing ) && ui.IsComponentActive() )
{
var info = ui.GetOrCreateTextTranslationInfo();
if( _hasOverridenFont )
if( _hasValidOverrideFont )
{
info?.ChangeFont( ui );
}
else
{
info?.UnchangeFont( ui );
if( _hasOverridenFont )
{
info.ChangeFont( ui );
}
else
{
info.UnchangeFont( ui );
}
}
}

if( Settings.ForceUIResizing )
{
var info = ui.GetOrCreateTextTranslationInfo();
if( info?.IsCurrentlySettingText == false )
if( Settings.ForceUIResizing )
{
// force UI resizing is highly problematic for NGUI because text should somehow
// be set after changing "resize" properties... brilliant stuff
if( ui.GetType() != ClrTypes.UILabel )
{
info?.ResizeUI( ui, ResizeCache );
}
info.ResizeUI( ui, ResizeCache );
_hasResizedCurrentComponentDuringDiscovery = true;
}

return true;
}
}
catch( Exception e )
{
XuaLogger.AutoTranslator.Error( e, "An error occurred while handling the UI resize/font hooks." );
XuaLogger.AutoTranslator.Warn( e, "An error occurred while handling the UI discovery." );
}

return false;
}

private void CheckSpriteRenderer( object ui )
Expand Down Expand Up @@ -721,15 +772,15 @@ private void SetText( object ui, string text, bool isTranslated, string original
}
}

if( info != null && Settings.EnableUIResizing || Settings.ForceUIResizing )
if( !_hasResizedCurrentComponentDuringDiscovery && info != null && ( Settings.EnableUIResizing || Settings.ForceUIResizing ) )
{
if( isTranslated || Settings.ForceUIResizing )
{
info?.ResizeUI( ui, ResizeCache );
info.ResizeUI( ui, ResizeCache );
}
else
{
info?.UnresizeUI( ui );
info.UnresizeUI( ui );
}
}

Expand Down Expand Up @@ -1143,10 +1194,15 @@ private string TranslateImmediate( object ui, string text, TextTranslationInfo i
return null;
}

info?.Reset( originalText );
bool shouldIgnore = false;
if( info != null )
{
info.Reset( originalText );
shouldIgnore = info.ShouldIgnore;
}

var scope = TranslationScopeProvider.GetScope( ui );
if( !text.IsNullOrWhiteSpace() && tc.IsTranslatable( text, false, scope ) && ui.ShouldTranslateTextComponent( ignoreComponentState ) && !IsCurrentlySetting( info ) )
if( !shouldIgnore && !text.IsNullOrWhiteSpace() && tc.IsTranslatable( text, false, scope ) && ( ignoreComponentState || ui.IsComponentActive() ) && !IsCurrentlySetting( info ) )
{
//var textKey = new TranslationKey( ui, text, !ui.SupportsStabilization(), false );
var isSpammer = ui.IsSpammingComponent();
Expand Down Expand Up @@ -1620,15 +1676,20 @@ private string TranslateByParserResult( TranslationEndpointManager endpoint, Par
return null;
}

info?.Reset( originalText );
bool shouldIgnore = false;
if( info != null )
{
info.Reset( originalText );
shouldIgnore = info.ShouldIgnore;
}

if( scope == TranslationScopes.None && context == null )
{
scope = TranslationScopeProvider.GetScope( ui );
}

// Ensure that we actually want to translate this text and its owning UI element.
if( !text.IsNullOrWhiteSpace() && tc.IsTranslatable( text, false, scope ) && ui.ShouldTranslateTextComponent( ignoreComponentState ) && !IsCurrentlySetting( info ) )
if( !shouldIgnore && !text.IsNullOrWhiteSpace() && tc.IsTranslatable( text, false, scope ) && ( ignoreComponentState || ui.IsComponentActive() ) && !IsCurrentlySetting( info ) )
{
var isSpammer = ui.IsSpammingComponent();
if( isSpammer && !IsBelowMaxLength( text ) ) return null; // avoid templating long strings every frame for IMGUI, important!
Expand Down
Expand Up @@ -84,6 +84,7 @@ internal static class Settings
public static bool EnableTextMeshPro;
public static bool EnableTextMesh;
public static bool EnableFairyGUI;
public static bool InitializeHarmonyDetourBridge;
public static bool IgnoreWhitespaceInDialogue;
public static bool IgnoreWhitespaceInNGUI;
public static int MinDialogueChars;
Expand Down Expand Up @@ -207,7 +208,6 @@ public static void Configure()
GameLogTextPaths.RemoveWhere( x => !x.StartsWith( "/" ) ); // clean up to ensure no 'empty' entries
RomajiPostProcessing = PluginEnvironment.Current.Preferences.GetOrDefault( "Behaviour", "RomajiPostProcessing", TextPostProcessing.ReplaceMacronWithCircumflex | TextPostProcessing.RemoveApostrophes );
TranslationPostProcessing = PluginEnvironment.Current.Preferences.GetOrDefault( "Behaviour", "TranslationPostProcessing", TextPostProcessing.ReplaceMacronWithCircumflex );
ForceMonoModHooks = PluginEnvironment.Current.Preferences.GetOrDefault( "Behaviour", "ForceMonoModHooks", false );
CacheRegexPatternResults = PluginEnvironment.Current.Preferences.GetOrDefault( "Behaviour", "CacheRegexPatternResults", false );
CacheRegexLookups = PluginEnvironment.Current.Preferences.GetOrDefault( "Behaviour", "CacheRegexLookups", false );
CacheWhitespaceDifferences = PluginEnvironment.Current.Preferences.GetOrDefault( "Behaviour", "CacheWhitespaceDifferences", false );
Expand All @@ -227,6 +227,8 @@ public static void Configure()
HtmlEntityPreprocessing = PluginEnvironment.Current.Preferences.GetOrDefault( "Behaviour", "HtmlEntityPreprocessing", true );
HandleRichText = PluginEnvironment.Current.Preferences.GetOrDefault( "Behaviour", "HandleRichText", true );
EnableTranslationHelper = PluginEnvironment.Current.Preferences.GetOrDefault( "Behaviour", "EnableTranslationHelper", false );
ForceMonoModHooks = PluginEnvironment.Current.Preferences.GetOrDefault( "Behaviour", "ForceMonoModHooks", false );
InitializeHarmonyDetourBridge = PluginEnvironment.Current.Preferences.GetOrDefault( "Behaviour", "InitializeHarmonyDetourBridge", !Features.SupportsReflectionEmit && PluginEnvironment.Current.AllowDefaultInitializeHarmonyDetourBridge );


TextureDirectory = PluginEnvironment.Current.Preferences.GetOrDefault( "Texture", "TextureDirectory", Path.Combine( "Translation", Path.Combine( "{Lang}", "Texture" ) ) );
Expand Down
Expand Up @@ -23,6 +23,6 @@ public static class PluginData
/// <summary>
/// Gets the version of the plugin.
/// </summary>
public const string Version = "4.12.0";
public const string Version = "4.12.1";
}
}
Expand Up @@ -14,10 +14,11 @@ internal class DefaultPluginEnvironment : IPluginEnvironment
private string _configPath;
private string _dataFolder;

public DefaultPluginEnvironment()
public DefaultPluginEnvironment( bool allowDefaultInitializeHarmonyDetourBridge )
{
_dataFolder = Path.Combine( Paths.GameRoot, "AutoTranslator" );
_configPath = Path.Combine( _dataFolder, "Config.ini" );
AllowDefaultInitializeHarmonyDetourBridge = allowDefaultInitializeHarmonyDetourBridge;
}

public IniFile Preferences
Expand All @@ -32,6 +33,8 @@ public IniFile Preferences

public string ConfigPath => _dataFolder;

public bool AllowDefaultInitializeHarmonyDetourBridge { get; }

public void SaveConfig()
{
_file.Save( _configPath );
Expand Down

0 comments on commit eece8aa

Please sign in to comment.