I have a couple of asks to update some text throughout a project. Doing a find and replace in code is easy, but I would like to implement a tool to look through all game objects. Unfortunately, I can grab all of the game objects in the scene, but I have not found a solution to grab all of the game objects in the project. Does anyone have any suggestions?
This is my current approach:
using System;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using EditorPlayerSettings = UnityEditor.PlayerSettings;
namespace UnityEditor.XCodeEditor
{
public class FindAndReplaceToolbar : EditorWindow
{
private const string TAG = "FindAndReplace";
string mOldValue = string.Empty;
string mNewValue = string.Empty;
[MenuItem("Window/Find And Replace")]
void Init()
{
var window = GetWindow<FindAndReplaceToolbar>(false, "Find And Replace Toolbar");
window.minSize = new Vector2(10, 10);
window.Show();
}
void OnGUI()
{
GUILayout.BeginHorizontal();
{
mOldValue = EditorGUILayout.TextField("Find: ", mOldValue, GUILayout.ExpandWidth(true));
}
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
{
mNewValue = EditorGUILayout.TextField("Replace: ", mNewValue, GUILayout.ExpandWidth(true));
}
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
if (GUILayout.Button("Find and Replace"))
{
FindAndReplace();
}
GUILayout.EndHorizontal();
}
#region Find And Replace Helper
public void FindAndReplace()
{
Debug.Log($"{TAG} Started: ({mOldValue} - {mNewValue})");
foreach (var textMeshProUGUI in GetAllTextMeshProUGUIsInScene())
{
if (textMeshProUGUI.text.Contains(mOldValue))
{
Debug.Log($"{TAG} Replaced {mOldValue} in {textMeshProUGUI.name} with {mNewValue} (See {GetFileName(textMeshProUGUI.transform)})");
textMeshProUGUI.text = textMeshProUGUI.text.Replace(mOldValue, mNewValue);
}
}
Debug.Log($"{TAG} Finished: ({mOldValue} - {mNewValue})");
}
public List<TextMeshProUGUI> GetAllTextMeshProUGUIsInScene()
{
List<TextMeshProUGUI> objectsInScene = new List<TextMeshProUGUI>();
foreach (TextMeshProUGUI go in (TextMeshProUGUI[]) Resources.FindObjectsOfTypeAll(typeof(TextMeshProUGUI)))
{
if (!EditorUtility.IsPersistent(go.transform.root.gameObject) && !(go.hideFlags == HideFlags.NotEditable || go.hideFlags == HideFlags.HideAndDontSave))
{
objectsInScene.Add(go);
}
}
return objectsInScene;
}
public static string GetFileName(Transform transform)
{
try
{
var parent = transform;
while (parent.parent != null)
{
parent = parent.parent;
}
return parent.name;
}
catch (Exception)
{
return transform.name;
}
}
#endregion Find And Replace Helper
}
}
#hijinxbassist pointed me in the right direction. Here is my current solution:
using System;
using System.IO;
using UnityEngine;
using EditorPlayerSettings = UnityEditor.PlayerSettings;
namespace UnityEditor.XCodeEditor
{
[InitializeOnLoad]
public class FindAndReplaceToolbar : EditorWindow
{
private const string TAG = "FindAndReplace";
private string mOldValue = string.Empty;
private string mNewValue = string.Empty;
static FindAndReplaceToolbar()
{
Debug.Log($"{TAG} InitializeOnLoad");
}
[MenuItem("Window/Find And Replace")]
static void Init()
{
var window = GetWindow<FindAndReplaceToolbar>(false, "Find And Replace Toolbar");
window.minSize = new Vector2(10, 10);
window.Show();
}
void OnGUI()
{
GUILayout.BeginHorizontal();
{
mOldValue = EditorGUILayout.TextField("Find: ", mOldValue, GUILayout.ExpandWidth(true));
}
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
{
mNewValue = EditorGUILayout.TextField("Replace: ", mNewValue, GUILayout.ExpandWidth(true));
}
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
if (GUILayout.Button("Find and Replace"))
{
FindAndReplace();
}
GUILayout.EndHorizontal();
}
public void FindAndReplace()
{
Debug.Log($"{TAG}: Started: ({mOldValue} - {mNewValue})");
string[] assetGUIDs = AssetDatabase.FindAssets("t:Object");
for (int i = 0; i < assetGUIDs.Length; i++)
{
try
{
string guid = assetGUIDs[i];
string assetFilePath = AssetDatabase.GUIDToAssetPath(guid);
string assetFile = File.ReadAllText(assetFilePath);
if (assetFile.Contains(mOldValue))
{
assetFile = assetFile.Replace(mOldValue, mNewValue);
File.WriteAllText(assetFilePath, assetFile);
Debug.Log($"{TAG}: Replaced {mOldValue} with {mNewValue} in Asset: [{Path.GetFileName(assetFilePath)}] (Type: {AssetDatabase.GetMainAssetTypeAtPath(assetFilePath)})");
}
}
catch (Exception e)
{
Debug.Log($"{TAG}: {e.Message}");
}
}
Debug.Log($"{TAG}: Finished: ({mOldValue} - {mNewValue})");
}
}
}
Related
This is the script.. in the starting lines you can see the usage of keycodes. I want to add UI buttons for android. When the user tap on that button it acts as Keycode.A or any Keycode which I want and I don't want to change the script. Any solution ? I am totally beginner I don't understand much of this code so don't want to change it. I got it with the free asset 2D Game Kit in which character ellen moves with pc controls. All I want is to change character controls from pc to ui buttons. Please help if I have to change the script I will get a lot of errors which I can't handle so please help.
using UnityEngine;
using UnityEngine.UIElements;
namespace Gamekit2D
{
public class PlayerInput : InputComponent, IDataPersister
{
public static PlayerInput Instance
{
get { return s_Instance; }
}
protected static PlayerInput s_Instance;
public bool HaveControl { get { return m_HaveControl; } }
public InputButton Pause = new InputButton(KeyCode.Escape, XboxControllerButtons.Menu);
public InputButton Interact = new InputButton(KeyCode.E, XboxControllerButtons.Y);
public InputButton MeleeAttack = new InputButton(KeyCode.K, XboxControllerButtons.X);
public InputButton RangedAttack = new InputButton(KeyCode.O, XboxControllerButtons.B);
public InputButton Jump = new InputButton(KeyCode.Space, XboxControllerButtons.A);
public InputAxis Horizontal = new InputAxis(KeyCode.D, KeyCode.A, XboxControllerAxes.LeftstickHorizontal);
public InputAxis Vertical = new InputAxis(KeyCode.W, KeyCode.S, XboxControllerAxes.LeftstickVertical);
[HideInInspector]
public DataSettings dataSettings;
protected bool m_HaveControl = true;
protected bool m_DebugMenuIsOpen = false;
void Awake ()
{
if (s_Instance == null)
s_Instance = this;
else
throw new UnityException("There cannot be more than one PlayerInput script. The instances are " + s_Instance.name + " and " + name + ".");
}
void OnEnable()
{
if (s_Instance == null)
s_Instance = this;
else if(s_Instance != this)
throw new UnityException("There cannot be more than one PlayerInput script. The instances are " + s_Instance.name + " and " + name + ".");
PersistentDataManager.RegisterPersister(this);
}
void OnDisable()
{
PersistentDataManager.UnregisterPersister(this);
s_Instance = null;
}
protected override void GetInputs(bool fixedUpdateHappened)
{
Pause.Get(fixedUpdateHappened, inputType);
Interact.Get(fixedUpdateHappened, inputType);
MeleeAttack.Get(fixedUpdateHappened, inputType);
RangedAttack.Get(fixedUpdateHappened, inputType);
Jump.Get(fixedUpdateHappened, inputType);
Horizontal.Get(inputType);
Vertical.Get(inputType);
if (Input.GetKeyDown(KeyCode.F12))
{
m_DebugMenuIsOpen = !m_DebugMenuIsOpen;
}
}
public override void GainControl()
{
m_HaveControl = true;
GainControl(Pause);
GainControl(Interact);
GainControl(MeleeAttack);
GainControl(RangedAttack);
GainControl(Jump);
GainControl(Horizontal);
GainControl(Vertical);
}
public override void ReleaseControl(bool resetValues = true)
{
m_HaveControl = false;
ReleaseControl(Pause, resetValues);
ReleaseControl(Interact, resetValues);
ReleaseControl(MeleeAttack, resetValues);
ReleaseControl(RangedAttack, resetValues);
ReleaseControl(Jump, resetValues);
ReleaseControl(Horizontal, resetValues);
ReleaseControl(Vertical, resetValues);
}
public void DisableMeleeAttacking()
{
MeleeAttack.Disable();
}
public void EnableMeleeAttacking()
{
MeleeAttack.Enable();
}
public void DisableRangedAttacking()
{
RangedAttack.Disable();
}
public void EnableRangedAttacking()
{
RangedAttack.Enable();
}
public DataSettings GetDataSettings()
{
return dataSettings;
}
public void SetDataSettings(string dataTag, DataSettings.PersistenceType persistenceType)
{
dataSettings.dataTag = dataTag;
dataSettings.persistenceType = persistenceType;
}
public Data SaveData()
{
return new Data<bool, bool>(MeleeAttack.Enabled, RangedAttack.Enabled);
}
public void LoadData(Data data)
{
Data<bool, bool> playerInputData = (Data<bool, bool>)data;
if (playerInputData.value0)
MeleeAttack.Enable();
else
MeleeAttack.Disable();
if (playerInputData.value1)
RangedAttack.Enable();
else
RangedAttack.Disable();
}
void OnGUI()
{
if (m_DebugMenuIsOpen)
{
const float height = 100;
GUILayout.BeginArea(new Rect(30, Screen.height - height, 200, height));
GUILayout.BeginVertical("box");
GUILayout.Label("Press F12 to close");
bool meleeAttackEnabled = GUILayout.Toggle(MeleeAttack.Enabled, "Enable Melee Attack");
bool rangeAttackEnabled = GUILayout.Toggle(RangedAttack.Enabled, "Enable Range Attack");
if (meleeAttackEnabled != MeleeAttack.Enabled)
{
if (meleeAttackEnabled)
MeleeAttack.Enable();
else
MeleeAttack.Disable();
}
if (rangeAttackEnabled != RangedAttack.Enabled)
{
if (rangeAttackEnabled)
RangedAttack.Enable();
else
RangedAttack.Disable();
}
GUILayout.EndVertical();
GUILayout.EndArea();
}
}
}
}
It's not possible. I rather advice you to directly call the functions you want when the button is pressed.
Guys
I've implemented into my Unity project a plugin which can be downloaded at the link (https://github.com/HoseinPorazar/Android-Native-TTS-plugin-for-Unity-3d).
To use it you need:
1-import AndroidNativeTTS.unitypackage into your project
2-create an empty game object and rename it to tts.
3-attach test script and TextToSpeech script to tts game object.
4-add a button and set the on click event to test.Speak().
5-build project for Android platform.
After implementing the plugin to make it work it's necessary to delete in AndroidManifext.xml the line "android:label=NAtive TTS".
AndroidManifest.xml is stored in the directory "Assets\Plugin\Android\androidtts-release.aar"
When I implemented the plugin which is build to use "UK" and "US" locale, I tried to add Russian locale but unfortunately it failed.
Please see the scripts below (Test.cs and TextToSpeach.cs):
test.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class test : MonoBehaviour {
TextToSpeech tts;
void Start()
{
tts = GetComponent<TextToSpeech>();
}
public void Speak()
{
tts.Speak("hello mr hosein porazar kasin", (string msg) =>
{
tts.ShowToast(msg);
});
}
public void ChangeSpeed()
{
tts.SetSpeed(0.5f);
}
public void ChangeLanguage()
{
tts.SetLanguage(TextToSpeech.Locale.UK);
}
public void ChangePitch()
{
tts.SetPitch(0.6f);
}
}
TextToSpeech.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TextToSpeech :MonoBehaviour
{
void Start()
{
}
public enum Locale
{
UK = 0,
US = 1
}
private AndroidJavaObject TTSExample = null;
private AndroidJavaObject activityContext = null;
private Locale _lang;
public Locale Language { get { return _lang; } set { SetLanguage(value); } }
private float _pitch, _speed;
public float Pitch { get{return _pitch;} set { SetPitch(value); } }
public float Speed { get{return _speed;} set { SetSpeed(value); } }
public delegate void OnErrorCallbackHandler(string error);
private OnErrorCallbackHandler _callback;
public TextToSpeech()
{
//Initialize();
}
public TextToSpeech(Locale language)
{
Initialize();
this.Language = language;
SetLanguage(this.Language);
}
public TextToSpeech(Locale language,float speed,float pitch)
{
Initialize();
this.Language = language;
this.Pitch = pitch;
this.Speed = speed;
SetLanguage(this.Language);
SetSpeed(this.Speed);
SetPitch(this.Pitch);
}
public void Speak(string toSay,OnErrorCallbackHandler callback)
{
if (TTSExample == null)
{
Initialize();
}
this._callback = callback;
TTSExample.Call("TTSMEWithCallBack", toSay, gameObject.name, "OnError");
}
public void OnError(string error)
{
if (_callback != null)
{
if (error.Length > 0)
{
_callback.Invoke(error);
}
}
ShowToast(error);
}
public void Speak(string toSay)
{
if (TTSExample == null)
{
Initialize();
}
TTSExample.Call("TTSME", toSay);
}
public void SetLanguage(Locale lan)
{
this._lang = lan;
string[] Language = new string[] {"UK","US" };
if (TTSExample == null)
{
Initialize();
}
TTSExample.Call("SetLang", Language[(int)lan]);
}
public void SetSpeed(float speed)
{
this._speed = speed;
if (TTSExample == null)
{
Initialize();
}
TTSExample.Set<float>("Speed", speed);
}
public void SetPitch(float pitch)
{
this._pitch = pitch;
if (TTSExample == null)
{
Initialize();
}
TTSExample.Set<float>("Pitch", pitch);
}
private void Initialize()
{
if (TTSExample == null)
{
using (AndroidJavaClass activityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
{
activityContext = activityClass.GetStatic<AndroidJavaObject>("currentActivity");
}
using (AndroidJavaClass pluginClass = new AndroidJavaClass("ir.hoseinporazar.androidtts.TTS"))
{
if (pluginClass != null)
{
TTSExample = pluginClass.CallStatic<AndroidJavaObject>("instance");
TTSExample.Call("setContext", activityContext);
}
}
}
}
public void ShowToast(string msg)
{
if (TTSExample == null)
{
using (AndroidJavaClass activityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
{
activityContext = activityClass.GetStatic<AndroidJavaObject>("currentActivity");
}
using (AndroidJavaClass pluginClass = new AndroidJavaClass("ir.hoseinporazar.androidtts.TTS"))
{
if (pluginClass != null)
{
TTSExample = pluginClass.CallStatic<AndroidJavaObject>("instance");
TTSExample.Call("setContext", activityContext);
activityContext.Call("runOnUiThread", new AndroidJavaRunnable(() =>
{
TTSExample.Call("showMessage", msg);
}));
}
}
}
else
{
activityContext.Call("runOnUiThread", new AndroidJavaRunnable(() =>
{
TTSExample.Call("showMessage", msg);
}));
}
}
}
I've tried to format following lines to change the language to Russian but it didn't help me:
public enum Locale
{
RU = 0,
US = 1
}
public void SetLanguage(Locale lan)
{
this._lang = lan;
string[] Language = new string[] {"RU","US" };
if (TTSExample == null)
{
Initialize();
}
TTSExample.Call("SetLang", Language[(int)lan]);
}
I also tried to contatct the developer of the plugin but it seems he was last time on github a couple years ago.
I'd really appreciate it if somebody can help me with the issue.
On the plugin homepage, the author says...
I have included 2 languages (UK,and US) if you want to use other
languages you will have to modify plugin ( with Android Studio).
So it seems you will also need to change switch statement at the bottom of the Java code here:
https://github.com/HoseinPorazar/Android-Native-TTS-plugin-for-Unity-3d/blob/master/NativeAndroidTTS/androidtts/src/main/java/ir/hoseinporazar/androidtts/TTS.java
By adding an "RU" case like this...
public void SetLang(String loc){
switch (loc){
case "UK":
if(t1!=null)
t1.setLanguage(Locale.UK);
break;
case "US":
if(t1!=null)
t1.setLanguage(Locale.US);
break;
case "RU":
if(t1!=null)
t1.setLanguage(Locale.RU);
break;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[ExecuteInEditMode]
public class GameObjectInfo : MonoBehaviour
{
[System.Serializable]
public class GameObjectstInfo
{
public GameObject parent;
public int childrenCount;
public List<Transform> children = new List<Transform>();
}
public string gameObjectsInfo = "";
public string results = "";
public bool addChildren = false;
public GameObjectstInfo[] objectsInfo;
private string previousGameObjectsInfo = "";
// Start is called before the first frame update
void Start()
{
Search();
}
private void Update()
{
if (gameObjectsInfo != "" && gameObjectsInfo != previousGameObjectsInfo)
{
Search();
}
previousGameObjectsInfo = gameObjectsInfo;
Reset();
}
public void Search()
{
if (gameObjectsInfo != "")
{
var foundObjects = FindGameObjectsWithName(gameObjectsInfo);
objectsInfo = new GameObjectstInfo[foundObjects.Length];
if (foundObjects.Length > 0)
{
results = "Found Results";
for (int i = 0; i < foundObjects.Length; i++)
{
objectsInfo[i] = new GameObjectstInfo();
objectsInfo[i].parent = foundObjects[i];
if (addChildren == true)
{
foreach (Transform t in foundObjects[i].GetComponentsInChildren<Transform>(true))
{
objectsInfo[i].childrenCount += 1;
objectsInfo[i].children.Add(t);
}
}
else
{
}
}
}
else
{
results = "No Results";
}
}
}
private void Reset()
{
if (gameObjectsInfo == "")
{
results = "No Results";
objectsInfo = new GameObjectstInfo[0];
}
}
GameObject[] FindGameObjectsWithName(string nameIt)
{
int it = 0;
GameObject[] objArr;
bool b = false;
while (!b)
{
if (GameObject.Find(nameIt))
{
GameObject.Find(nameIt).name = nameIt + it;
it++;
}
else
{
b = true;
}
}
objArr = new GameObject[it];
while (it > 0)
{
it--;
objArr[it] = GameObject.Find(nameIt + it);
objArr[it].name = nameIt;
}
return objArr;
}
}
This is the part where I'm adding or not the children:
if (addChildren == true)
{
foreach (Transform t in foundObjects[i].GetComponentsInChildren<Transform>(true))
{
objectsInfo[i].childrenCount += 1;
objectsInfo[i].children.Add(t);
}
}
else
{
}
But I want to do it also in the Update if the flag addChildren is true and changed to false or false to true make the change and add/remove the children in real time.
Now I need to delete the text in the variable gameObjectsInfo and re type again to make the children changes. But I want that the effect will happen without typing over again. Only when changing the state of the flag addChildren.
If I'm changing the addChildren state re search again with or without the children.
There are ways you can do this by writing your own editor for the class so it'll respond to clicking on the checkbox for that bool, if you are only setting the value of addChildren through code, you can use a property set function, or, the most straight-forward way (if you don't mind waiting until the next frame after changing the value) is to just have an extra bool tracking the previous value:
private bool _lastAddChildren;
public bool addChildren = false;
...
void Start()
{
_lastAddChildren = addChildren;
...
}
private void Update()
{
if ((gameObjectsInfo != "" && gameObjectsInfo != previousGameObjectsInfo)
|| (_lastAddChildren != addChildren))
{
Search();
}
previousGameObjectsInfo = gameObjectsInfo;
_lastAddChildren = addChildren;
Reset();
}
Im using google play services cloud save. I found a tutorial about how to save, but for one thing like just for highscore. I want to save multiple playerprefs, for example I have 3 ability and every one of it is saving in a playerpref so I want to save them in to the cloud and I have gold to buy these abilitys and you can buy the gold with IAP so I want to save gold too in cloud but I have no idea how to save multiple playerprefs can you help me.
My playerprefs is like this
PlayerPrefs.SetInt("Revive", revive);
PlayerPrefs.SetInt("SlowTime", slowTime);
PlayerPrefs.SetInt("Immortal", immortal);
Im changing and saving the gold after IAP purchase
PlayerPrefs.SetInt("Gold", PlayerPrefs.GetInt("Gold") + 250);
This is the Cloud Save Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using GooglePlayGames;
using UnityEngine.SocialPlatforms;
using GooglePlayGames.BasicApi;
using GooglePlayGames.BasicApi.SavedGame;
using System.Text;
using System;
public class PlayGamesController : MonoBehaviour
{
public static PlayGamesController Instance { set; get; }
const string Save_Name = "Save";
bool isSaving;
bool isCloudDataLoaded = false;
private void Start()
{
if (Instance == null)
{
DontDestroyOnLoad(gameObject);
Instance = this;
}
else
{
Destroy(gameObject);
}
if (!PlayerPrefs.HasKey(Save_Name))
PlayerPrefs.SetString(Save_Name, "0");
if (!PlayerPrefs.HasKey("IsFirstTime"))
PlayerPrefs.SetInt("IsFirstTime", 1);
LoadLocal();
PlayGamesClientConfiguration config = new PlayGamesClientConfiguration.Builder().EnableSavedGames().Build();
PlayGamesPlatform.InitializeInstance(config);
PlayGamesPlatform.Activate();
SignIn();
}
private void SignIn()
{
Social.localUser.Authenticate((success) => {
LoadData();
});
}
public void AddScoreToLeaderboard(string leaderboardId, long score)
{
Social.ReportScore(score, leaderboardId, (bool success) => { });
}
public void OnAchievementClick()
{
if (Social.localUser.authenticated)
{
Social.ShowAchievementsUI();
}
if (!Social.localUser.authenticated)
{
SignIn();
}
}
public void OnLeaderboardClick()
{
if (Social.localUser.authenticated)
{
Social.ShowLeaderboardUI();
}
if (!Social.localUser.authenticated)
{
SignIn();
}
}
#region Saved Games
string GameDataToString()
{
return CloudVariables.highScore.ToString();
}
void StringToGameData(string cloudData, string localData)
{
if(PlayerPrefs.GetInt("IsFirstTime") == 1)
{
PlayerPrefs.SetInt("IsFirstTime", 0);
if (int.Parse(cloudData) > int.Parse(localData))
{
PlayerPrefs.SetString(Save_Name, cloudData);
}
}
else
{
if(int.Parse(localData) > int.Parse(cloudData))
{
CloudVariables.highScore = int.Parse(localData);
AddScoreToLeaderboard(GPGSIds.leaderboard_high_score, CloudVariables.highScore);
isCloudDataLoaded = true;
SaveData();
return;
}
}
CloudVariables.highScore = int.Parse(cloudData);
isCloudDataLoaded = true;
}
void StringToGameData(string localData)
{
CloudVariables.highScore = int.Parse(localData);
}
public void LoadData()
{
if (Social.localUser.authenticated)
{
isSaving = false;
((PlayGamesPlatform)Social.Active).SavedGame.OpenWithManualConflictResolution(Save_Name, DataSource.ReadCacheOrNetwork, true, ResolveConflict, OnSavedGameOpened);
}
else
{
LoadLocal();
}
}
private void LoadLocal()
{
StringToGameData(PlayerPrefs.GetString(Save_Name));
}
public void SaveData()
{
if (!isCloudDataLoaded)
{
SaveLocal();
return;
}
if (Social.localUser.authenticated)
{
isSaving = true;
((PlayGamesPlatform)Social.Active).SavedGame.OpenWithManualConflictResolution(Save_Name, DataSource.ReadCacheOrNetwork, true, ResolveConflict, OnSavedGameOpened);
}
else
{
SaveLocal();
}
}
private void SaveLocal()
{
PlayerPrefs.SetString(Save_Name, GameDataToString());
}
private void ResolveConflict(IConflictResolver resolver, ISavedGameMetadata original, byte[] originalData, ISavedGameMetadata unmerged, byte[] unmergedData)
{
if (originalData == null)
resolver.ChooseMetadata(unmerged);
else if (unmergedData == null)
resolver.ChooseMetadata(original);
else
{
string originalStr = Encoding.ASCII.GetString(originalData);
string unmergedStr = Encoding.ASCII.GetString(unmergedData);
int originalNum = int.Parse(originalStr);
int unmergedNum = int.Parse(unmergedStr);
if(originalNum > unmergedNum)
{
resolver.ChooseMetadata(original);
return;
}
else if (unmergedNum > originalNum)
{
resolver.ChooseMetadata(unmerged);
return;
}
resolver.ChooseMetadata(original);
}
}
private void OnSavedGameOpened(SavedGameRequestStatus status, ISavedGameMetadata game)
{
if(status == SavedGameRequestStatus.Success)
{
if (!isSaving)
LoadGame(game);
else
SaveGame(game);
}
else
{
if (!isSaving)
LoadLocal();
else
SaveLocal();
}
}
private void LoadGame(ISavedGameMetadata game)
{
((PlayGamesPlatform)Social.Active).SavedGame.ReadBinaryData(game, OnSavedGameDataRead);
}
private void SaveGame(ISavedGameMetadata game)
{
string stringToSave = GameDataToString();
PlayerPrefs.SetString(Save_Name, stringToSave);
byte[] dataToSave = Encoding.ASCII.GetBytes(stringToSave);
SavedGameMetadataUpdate update = new SavedGameMetadataUpdate.Builder().Build();
((PlayGamesPlatform)Social.Active).SavedGame.CommitUpdate(game, update, dataToSave, OnSavedGameDataWritten);
}
private void OnSavedGameDataRead(SavedGameRequestStatus status, byte[] savedData)
{
if(status == SavedGameRequestStatus.Success)
{
string cloudDataString;
if (savedData.Length == 0)
cloudDataString = "0";
else
cloudDataString = Encoding.ASCII.GetString(savedData);
string localDataString = PlayerPrefs.GetString(Save_Name);
StringToGameData(cloudDataString, localDataString);
}
}
private void OnSavedGameDataWritten(SavedGameRequestStatus status, ISavedGameMetadata game)
{
}
#endregion /Saved Games
}
Im trying to emulate the console in a windows forms applicaton. I have made it possible by using two extra threads and a delegate to be able to interact with my multiline textbox.
This somehow seems like I complicate things to much. So my questions.
Is there a better way of doing this?
When i press enter the command does not get sent, first if i press again it get sent? WHy is that? I ahve treid to debug it but failed to find the solution.
EDIT! Im using CsharpSSH, to do the SSH connection. Also I have included my full code now!
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Tamir.SharpSsh;
using System.IO;
using System.Threading;
using System.Timers;
namespace WindowsFormsApplication3
{
public partial class Form1 : Form
{
public string mHost;
SshShell mShell;
public string mInput;
string pattern = "";
bool mInputHolder = false;
string mPattern = "";
int mValue = 0;
bool mStatus = false;
private Thread thrdtwo = null;
private Thread thrdone = null;
public string mKorv;
string mString = "";
delegate void SetTextCallback(string text);
bool clientopen = true;
public Form1()
{
InitializeComponent();
txthost.Text = "sdf.org";
txtuser.Text = "kalle82";
txtpass.Text = "kattsand";
string pattern = "sdf:";
mPattern = pattern;
}
public void button1_Click(object sender, EventArgs e)
{
mShell = new SshShell(Host, User);
mShell.Password = Pass;
//WRITING USER MESSAGE
txtOutput.AppendText("Connecting...");
mShell.Connect();
txtOutput.AppendText("OK");
mShell.ExpectPattern = mPattern;
mShell.RemoveTerminalEmulationCharacters = true;
this.SetText(mShell.Expect(pattern));
txtInput.Focus();
thrdone = new Thread(new ThreadStart(appengine));
thrdone.Start();
}
private void appengine()
{
this.txtInput.KeyPress += new System.Windows.Forms.KeyPressEventHandler(checkforenter);
// MessageBox.Show("Appengine started");
while (mShell.ShellOpened)
{
thrdtwo = new Thread(new ThreadStart(startthread2));
thrdtwo.Start();
thrdtwo.Join();
// this.SetText(mShell.Expect(pattern));
if (clientopen == false) break;
}
// MessageBox.Show("Appengine stopped");
}
private void startthread2()
{
//Wait for answer
while (mStatus == false)
{
}
}
//Recieves keypressevent
public void checkforenter(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
if (e.KeyChar == (char)13)
{
mStatus = true;
mString = txtInput.Text;
mShell.WriteLine(mString);
this.SetText(mShell.Expect(pattern));
txtOutput.AppendText(txtInput.Text + "\n");
}
mStatus = false;
}
private void SetText(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.txtOutput.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else
{
this.txtOutput.Text = text.ToString();
}
}
public int checkfortrue()
{
if (mInputHolder != true)
{
mValue = 0;
}
if (mInputHolder == false)
{
mValue = -1;
}
return mValue;
}
public string userInput()
{
while (mInputHolder == true)
{
}
mInputHolder = true;
return txtInput.Text;
}
//Properties
public string Host
{
get
{
return txthost.Text;
}
set
{
txthost.Text = value;
}
}
public string User
{
get
{
return txtuser.Text;
}
set
{
txtuser.Text = value;
}
}
public string Pass
{
get
{
return txtpass.Text;
}
set
{
txtpass.Text = value;
}
}
public string Pattern
{
get
{
return pattern;
}
set
{
pattern = value;
}
}
private void button2_Click(object sender, EventArgs e)
{
clientopen = false;
}
}
}