Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
yangrobertw committed Mar 25, 2019
0 parents commit c30089b
Show file tree
Hide file tree
Showing 56 changed files with 4,210 additions and 0 deletions.
56 changes: 56 additions & 0 deletions .gitignore
@@ -0,0 +1,56 @@
# This .gitignore file should be placed at the root of your Unity project directory

/[Ll]ibrary/
/[Tt]emp/
/[Oo]bj/
/[Bb]uild/
/[Bb]uilds/
/[Ll]ogs/

# Never ignore Asset meta data
!/[Aa]ssets/**/*.meta

# Uncomment this line if you wish to ignore the asset store tools plugin
# /[Aa]ssets/AssetStoreTools*

# TextMesh Pro files
[Aa]ssets/TextMesh*Pro/

# Visual Studio cache directory
.vs/

# Gradle cache directory
.gradle/

# Autogenerated VS/MD/Consulo solution and project files
ExportedObj/
.consulo/
*.csproj
*.unityproj
*.sln
*.suo
*.tmp
*.user
*.userprefs
*.pidb
*.booproj
*.svd
*.pdb
*.mdb
*.opendb
*.VC.db

# Unity3D generated meta files
*.pidb.meta
*.pdb.meta
*.mdb.meta

# Unity3D generated file on crash reports
sysinfo.txt

# Builds
*.apk
*.unitypackage

# Crashlytics generated file
crashlytics-build.properties
8 changes: 8 additions & 0 deletions Assets/Bobbin.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions Assets/Bobbin/Editor.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

67 changes: 67 additions & 0 deletions Assets/Bobbin/Editor/BobbinSettings.asset
@@ -0,0 +1,67 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4230f1ebc2a828243ac1290275d26bd7, type: 3}
m_Name: BobbinSettings
m_EditorClassIdentifier:
paths:
- m_ID: 0
m_Name: root
m_Depth: -1
enabled: 0
fileType: 0
url: root
filePath:
lastFileHash:
label:
assetReference: {fileID: 0}
- m_ID: 12
m_Name: Item 12
m_Depth: 0
enabled: 1
fileType: 0
url:
filePath:
lastFileHash:
label:
assetReference: {fileID: 0}
- m_ID: 9
m_Name: Spreadsheet2
m_Depth: 0
enabled: 1
fileType: 1
url: https://docs.google.com/spreadsheets/export?format=csv&id=1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms
filePath: Assets/Bobbin/Spreadsheet2.csv
lastFileHash: f6ec9d52e21cb67b8694f6e01006a084
label:
assetReference: {fileID: 4900000, guid: d85907b581dbcb047a13ac3db583bd7f, type: 3}
- m_ID: 8
m_Name: Level3
m_Depth: 0
enabled: 0
fileType: 0
url: https://docs.google.com/document/export?format=txt&id=1rm05QCc-wgfMLd7S0tO0SkLuCZ__zxHKnSEYx1PbWk8&includes_info_params=true
filePath: Assets/GoogleDocsTest2_Blah.txt
lastFileHash: 7ce02e29f8267313d9569c9850e96161
label:
assetReference: {fileID: 4900000, guid: 68193fb164cd1554391041ef6d63d96b, type: 3}
- m_ID: 7
m_Name: GoogleDocsTest
m_Depth: 0
enabled: 1
fileType: 0
url: https://docs.google.com/document/export?format=txt&id=1rm05QCc-wgfMLd7S0tO0SkLuCZ__zxHKnSEYx1PbWk8&includes_info_params=true
filePath: Assets/GoogleDocsTest.yarn.txt
lastFileHash: 7ce02e29f8267313d9569c9850e96161
label:
assetReference: {fileID: 4900000, guid: f31f6939a186e314eb206674fc47c920, type: 3}
autoRefresh: 0
refreshInterval: 120
8 changes: 8 additions & 0 deletions Assets/Bobbin/Editor/BobbinSettings.asset.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions Assets/Bobbin/Editor/Scripts.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

189 changes: 189 additions & 0 deletions Assets/Bobbin/Editor/Scripts/BobbinCore.cs
@@ -0,0 +1,189 @@
using System.Text;
using System.Text.RegularExpressions;
using System.Security.Cryptography;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEditor;
using UnityEngine.Networking;

namespace Bobbin
{

[InitializeOnLoad]
public class BobbinCore
{
public static BobbinCore Instance;

public static double lastRefreshTime { get; private set; }
static bool refreshInProgress = false;
UnityWebRequest[] results;
public static string lastReport { get; private set; }

// called on InitializeOnLoad
static BobbinCore()
{
if (Instance == null)
{
Instance = new BobbinCore();
}
EditorApplication.update += Instance.OnEditorUpdate;
}

/// <summary>
/// Just a callback that attaches to EditorApplication.Update, so that Bobbin can automatically fetch files even if the editor window isn't open
/// </summary>
void OnEditorUpdate()
{
if (BobbinSettings.Instance.autoRefresh && EditorApplication.timeSinceStartup > lastRefreshTime + BobbinSettings.Instance.refreshInterval)
{
lastRefreshTime = EditorApplication.timeSinceStartup;
StartRefresh(); // by default, no report
}
}

[MenuItem("Bobbin/Force Refresh All Files")]
public static void DoRefresh()
{
Instance.StartRefresh();

}

[MenuItem("Bobbin/Add URLs and Settings...")]
public static void OpenSettingsAsset()
{
Selection.activeObject = BobbinSettings.Instance;
}

public void StartRefresh()
{
if (refreshInProgress == false)
{
EditorCoroutines.StartCoroutine(RefreshCoroutine(), this);
}
else
{
Debug.LogWarning("Bobbin is already refreshing files right now. Please wait until it's finished.");
}
}

/// <summary>
/// The main editor coroutine that fetches URLS and saves the files into the project.
/// </summary>
IEnumerator RefreshCoroutine()
{
results = new UnityWebRequest[BobbinSettings.Instance.paths.Count];
refreshInProgress = true;
lastReport = "Bobbin started refresh at " + System.DateTime.Now.ToLongTimeString() + ", log is below:";

for (int i = 0; i < results.Length; i++)
{
var currentPair = BobbinSettings.Instance.paths[i];
if (currentPair != null && currentPair.depth > -1) // make sure tree element is !null and not the root element
{
// basic error checking
if (currentPair.enabled == false)
{
lastReport += string.Format("\n- {0}: DISABLED", currentPair.name);
continue;
}
if (currentPair.url == null || currentPair.url.Length <= 4)
{
lastReport += string.Format("\n- [ERROR] {0}: no URL defined, nothing to download", currentPair.name);
continue;
}
if (currentPair.filePath == null || currentPair.filePath.Length <= 4)
{
lastReport += string.Format("\n- [ERROR] {0}: no asset file path defined, nowhere to save", currentPair.name);
continue;
}

// actually send the web request now
currentPair.url = FixURL( currentPair.url );
results[i] = UnityWebRequest.Get( currentPair.url );
yield return results[i].SendWebRequest();

// handle an unknown internet error
if (results[i].isNetworkError || results[i].isHttpError)
{
Debug.LogWarningFormat("Bobbin couldn't retrieve file at <{0}> and error message was: {1}", results[i].url, results[i].error);
lastReport += string.Format("\n- [ERROR] {0}: {1}", currentPair.name, results[i].error);
}
else
{
// make sure the fetched file isn't just a Google login page
if (results[i].downloadHandler.text.Contains("google-site-verification")) {
Debug.LogWarningFormat("Bobbin couldn't retrieve file at <{0}> because the Google Doc didn't have public link sharing enabled", results[i].url);
lastReport += string.Format("\n- [ERROR] {0}: This Google Docs share link does not have 'VIEW' access; make sure you enable link sharing.", currentPair.name, currentPair.url);
continue;
}

// reimport only newly changed assets (compare the file hash checksums)
var checksum = Md5Sum(results[i].downloadHandler.data);
//AssetDatabase.LoadAssetAtPath(currentPair.filePath,typeof(UnityEngine.Object)) == null ||
if (currentPair.assetReference == null || currentPair.lastFileHash.Equals(checksum) == false)
{
using (FileStream fls = new FileStream(Application.dataPath.Substring(0, Application.dataPath.Length - "Assets".Length) + currentPair.filePath, FileMode.Create))
{
fls.Write(results[i].downloadHandler.data, 0, results[i].downloadHandler.data.Length);
}
AssetDatabase.ImportAsset(currentPair.filePath);
currentPair.lastFileHash = checksum;
currentPair.assetReference = AssetDatabase.LoadAssetAtPath(currentPair.filePath, typeof(UnityEngine.Object));
lastReport += string.Format("\n- {0}: UPDATED {1}", currentPair.name, currentPair.filePath);
}
else
{
lastReport += string.Format("\n- {0}: UNCHANGED", currentPair.name);
}
}
results[i].Dispose(); // I don't know if this is actually necessary but let's do it anyway
}
}

EditorUtility.SetDirty(BobbinSettings.Instance);
refreshInProgress = false;
}

// from https://github.com/MartinSchultz/unity3d/blob/master/CryptographyHelper.cs
/// <summary>
/// used to calculate file checksums so we can avoid unnecessary ImportAsset operations
/// </summary>
public static string Md5Sum(byte[] bytes)
{
// encrypt bytes
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
byte[] hashBytes = md5.ComputeHash(bytes);

// Convert the encrypted bytes back to a string (base 16)
string hashString = "";
for (int i = 0; i < hashBytes.Length; i++)
{
hashString += System.Convert.ToString(hashBytes[i], 16).PadLeft(2, "0"[0]);
}
return hashString.PadLeft(32, "0"[0]);
}


public static string FixURL(string url)
{
// if it's a Google Docs URL, then grab the document ID and reformat the URL
if (url.StartsWith("https://docs.google.com/document/d/"))
{
var docID = url.Substring( "https://docs.google.com/document/d/".Length, 44 );
return string.Format("https://docs.google.com/document/export?format=txt&id={0}&includes_info_params=true", docID);
}
if (url.StartsWith("https://docs.google.com/spreadsheets/d/"))
{
var docID = url.Substring( "https://docs.google.com/spreadsheets/d/".Length, 44 );
return string.Format("https://docs.google.com/spreadsheets/export?format=csv&id={0}", docID);
}
return url;
}

}



}
11 changes: 11 additions & 0 deletions Assets/Bobbin/Editor/Scripts/BobbinCore.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit c30089b

Please sign in to comment.