12 Commits

Author SHA1 Message Date
MrUnknownDE 689ceca124 add AudioLink BPM Detector 2026-04-11 10:44:03 +02:00
MrUnknownDE 185f1cc96a remove sync project ^^ 2026-04-10 22:08:08 +02:00
MrUnknownDE 32a428502d add audio source fade 2026-04-10 22:05:33 +02:00
MrUnknownDE 50017d40c8 Merge branch 'main' of github.com:MrUnknownDE/unity-gittool 2026-04-10 21:36:28 +02:00
MrUnknownDE 5490b72e5d add ProTV Room Zone Script :D 2026-04-10 21:35:01 +02:00
MrUnknownDE 9250fc71ed Fix formatting in usage section of README
Updated usage instructions for GIT Version Control.
2026-04-07 16:27:53 +02:00
MrUnknownDE 8318bd6a6e add generation packages inventar list 2026-04-07 16:26:30 +02:00
MrUnknownDE 0c613129f5 start livesync panel ^^ 2026-04-07 13:27:01 +02:00
MrUnknownDE 7bc0eee024 add git console 2026-04-07 13:05:14 +02:00
MrUnknownDE 48134f2a03 add pull button 2026-04-07 13:02:27 +02:00
MrUnknownDE 00ab946aa0 add unity settings check 2026-04-07 11:28:54 +02:00
MrUnknownDE 992e67eee2 Update Readme.md 2026-04-07 11:19:18 +02:00
7 changed files with 708 additions and 64 deletions
+64
View File
@@ -0,0 +1,64 @@
using UdonSharp;
using UnityEngine;
using AudioLink;
public class AudioLinkBeatDetector : UdonSharpBehaviour
{
public AudioLink.AudioLink audioLinkInstance;
[Header("Settings")]
[Range(0, 1)] public float threshold = 0.5f;
public float minBpm = 70f;
public float maxBpm = 210f; // Alles darüber wird als Fehler ignoriert
[Header("Output")]
public float bpm = 128f;
public float instantBpm = 128f;
public bool isBeat;
private float lastBeatTime;
void Update()
{
if (audioLinkInstance == null || !audioLinkInstance.AudioDataIsAvailable()) return;
Vector2 bassPos = AudioLink.AudioLink.GetALPassAudioBass();
Vector4 data = audioLinkInstance.GetDataAtPixel((int)bassPos.x, (int)bassPos.y);
float currentLevel = data.x;
// Prüfen auf Threshold
if (currentLevel > threshold)
{
float currentTime = Time.time;
float timeDiff = currentTime - lastBeatTime;
// Der "Debounce" Check:
// 0.27s entspricht ca. 222 BPM. Alles was schneller kommt, ist Rauschen.
if (timeDiff > 0.27f)
{
if (lastBeatTime > 0)
{
float detected = 60f / timeDiff;
// Nur plausible Werte übernehmen
if (detected >= minBpm && detected <= maxBpm)
{
instantBpm = detected;
// Glättung: 0.5 sorgt für schnelles Folgen, aber filtert Ausreißer
bpm = Mathf.Lerp(bpm, instantBpm, 0.5f);
}
}
lastBeatTime = currentTime;
isBeat = true;
}
else
{
isBeat = false;
}
}
else
{
isBeat = false;
}
}
}
+43
View File
@@ -0,0 +1,43 @@
using UdonSharp;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class BeatDetectorDisplay : UdonSharpBehaviour
{
public AudioLinkBeatDetector engine;
public TextMeshProUGUI bpmText;
public Image beatIndicator;
public Color activeColor = Color.cyan;
private float flashTimer;
void Update()
{
if (engine == null) return;
// Wenn die Engine einen Beat erkennt...
if (engine.isBeat)
{
// ...aktualisieren wir SOFORT den Text mit der instantBpm
if (bpmText != null)
{
bpmText.text = engine.instantBpm.ToString("F0"); // "F0" für ganze Zahlen ohne Lag-Gefühl
}
// Visueller Kick
flashTimer = 0.1f;
if (beatIndicator != null) beatIndicator.color = activeColor;
}
// Timer für das Abklingen der LED
if (flashTimer > 0)
{
flashTimer -= Time.deltaTime;
if (flashTimer <= 0 && beatIndicator != null)
{
beatIndicator.color = new Color(0.1f, 0.1f, 0.1f, 1f);
}
}
}
}
+268 -33
View File
@@ -13,6 +13,9 @@ public class GitPanel : EditorWindow
private bool isGitInstalled = true; private bool isGitInstalled = true;
private bool hasRepo = false; private bool hasRepo = false;
private bool settingsCorrect = true;
private string settingsWarning = "";
private string currentBranchName = "unknown"; private string currentBranchName = "unknown";
private string[] availableBranches = new string[0]; private string[] availableBranches = new string[0];
private int selectedBranchIndex = 0; private int selectedBranchIndex = 0;
@@ -21,10 +24,13 @@ public class GitPanel : EditorWindow
private Vector2 scrollPositionChanges; private Vector2 scrollPositionChanges;
private Vector2 scrollPositionHistory; private Vector2 scrollPositionHistory;
// STATISCH: Damit RunGitCommand darauf zugreifen kann und das Log beim Neuladen erhalten bleibt!
private static string gitLogOutput = "";
private Vector2 scrollPositionLog;
private int selectedTab = 0; private int selectedTab = 0;
private string[] tabNames = { "Changes", "History" }; private string[] tabNames = { "Changes", "History" };
// NEU: Settings & Override
private bool showSettings = false; private bool showSettings = false;
private string webUrlOverride = ""; private string webUrlOverride = "";
private string prefsKey = ""; private string prefsKey = "";
@@ -36,15 +42,13 @@ public class GitPanel : EditorWindow
public static void ShowWindow() public static void ShowWindow()
{ {
GitPanel window = GetWindow<GitPanel>("GIT Version Control System"); GitPanel window = GetWindow<GitPanel>("GIT Version Control System");
window.minSize = new Vector2(350, 550); window.minSize = new Vector2(380, 650);
} }
private void OnEnable() private void OnEnable()
{ {
// Generiert einen einzigartigen Key für dieses spezifische Unity-Projekt
prefsKey = $"GitTool_WebUrl_{Application.dataPath.GetHashCode()}"; prefsKey = $"GitTool_WebUrl_{Application.dataPath.GetHashCode()}";
webUrlOverride = EditorPrefs.GetString(prefsKey, ""); webUrlOverride = EditorPrefs.GetString(prefsKey, "");
RefreshData(); RefreshData();
} }
@@ -53,12 +57,14 @@ public class GitPanel : EditorWindow
public void RefreshData() public void RefreshData()
{ {
CheckGitInstallation(); CheckGitInstallation();
if (!isGitInstalled) return; CheckUnitySettings();
if (!isGitInstalled) return;
CheckRepoStatus(); CheckRepoStatus();
if (hasRepo) if (hasRepo)
{ {
ExportPackageInventory();
currentBranchName = RunGitCommand("rev-parse --abbrev-ref HEAD").Trim(); currentBranchName = RunGitCommand("rev-parse --abbrev-ref HEAD").Trim();
FetchBranches(); FetchBranches();
} }
@@ -79,6 +85,33 @@ public class GitPanel : EditorWindow
} catch { isGitInstalled = false; } } catch { isGitInstalled = false; }
} }
// FIX: Nutzt jetzt die aktuelle Unity-API (VersionControlSettings.mode)
private void CheckUnitySettings()
{
settingsCorrect = true;
settingsWarning = "";
if (VersionControlSettings.mode != "Visible Meta Files")
{
settingsCorrect = false;
settingsWarning += "• Version Control Mode must be 'Visible Meta Files'\n";
}
if (EditorSettings.serializationMode != SerializationMode.ForceText)
{
settingsCorrect = false;
settingsWarning += "• Asset Serialization must be 'Force Text'\n";
}
}
private void FixUnitySettings()
{
VersionControlSettings.mode = "Visible Meta Files";
EditorSettings.serializationMode = SerializationMode.ForceText;
UnityEngine.Debug.Log("Git-Tool: Unity Project Settings updated for Git compatibility.");
RefreshData();
}
private void SetDefaultCommitMessage() { commitMessage = $"Auto-Save: {System.DateTime.Now:yyyy-MM-dd HH:mm:ss}"; } private void SetDefaultCommitMessage() { commitMessage = $"Auto-Save: {System.DateTime.Now:yyyy-MM-dd HH:mm:ss}"; }
private void OnGUI() private void OnGUI()
@@ -88,23 +121,41 @@ public class GitPanel : EditorWindow
if (hasRepo) GUILayout.Label($"Active Branch: {currentBranchName}", EditorStyles.miniLabel); if (hasRepo) GUILayout.Label($"Active Branch: {currentBranchName}", EditorStyles.miniLabel);
GUILayout.Space(5); GUILayout.Space(5);
if (!settingsCorrect)
{
EditorGUILayout.BeginVertical("box");
EditorGUILayout.HelpBox("INCOMPATIBLE PROJECT SETTINGS:\n" + settingsWarning, MessageType.Error);
GUI.backgroundColor = new Color(1f, 0.5f, 0f);
if (GUILayout.Button("Fix Project Settings Now"))
{
FixUnitySettings();
}
GUI.backgroundColor = Color.white;
EditorGUILayout.EndVertical();
GUILayout.Space(10);
}
if (!isGitInstalled) { RenderGitMissingUI(); return; } if (!isGitInstalled) { RenderGitMissingUI(); return; }
if (!hasRepo) { RenderInitUI(); return; } if (!hasRepo) { RenderInitUI(); return; }
// --- NEU: SETTINGS FOLDOUT ---
showSettings = EditorGUILayout.Foldout(showSettings, "⚙️ Repository Settings"); showSettings = EditorGUILayout.Foldout(showSettings, "⚙️ Repository Settings");
if (showSettings) if (showSettings)
{ {
EditorGUILayout.BeginVertical("box"); EditorGUILayout.BeginVertical("box");
GUILayout.Label("Web Override (For custom SSH instances)", EditorStyles.miniBoldLabel); GUILayout.Label("Web Override (For custom SSH instances)", EditorStyles.miniBoldLabel);
EditorGUI.BeginChangeCheck(); EditorGUI.BeginChangeCheck();
webUrlOverride = EditorGUILayout.TextField("Web URL:", webUrlOverride); webUrlOverride = EditorGUILayout.TextField("Web URL:", webUrlOverride);
if (EditorGUI.EndChangeCheck()) if (EditorGUI.EndChangeCheck())
{ {
EditorPrefs.SetString(prefsKey, webUrlOverride.Trim()); EditorPrefs.SetString(prefsKey, webUrlOverride.Trim());
} }
EditorGUILayout.HelpBox("e.g. https://git.mrunk.de/mrunknownde/my-repo\nLeaves SSH untouched but fixes browser links.", MessageType.None);
GUILayout.Space(10);
GUILayout.Label("Inventory Management", EditorStyles.miniBoldLabel);
if (GUILayout.Button("📄 Sync Package Inventory (Unity & VRChat)", GUILayout.Height(25)))
{
ExportPackageInventory();
}
EditorGUILayout.EndVertical(); EditorGUILayout.EndVertical();
GUILayout.Space(5); GUILayout.Space(5);
} }
@@ -118,7 +169,7 @@ public class GitPanel : EditorWindow
private void RenderGitMissingUI() private void RenderGitMissingUI()
{ {
EditorGUILayout.HelpBox("CRITICAL: Git not found. Please install Git and restart Unity.", MessageType.Error); EditorGUILayout.HelpBox("CRITICAL: Git not found.", MessageType.Error);
if (GUILayout.Button("Download Git for Windows", GUILayout.Height(30))) Application.OpenURL("https://git-scm.com/download/win"); if (GUILayout.Button("Download Git for Windows", GUILayout.Height(30))) Application.OpenURL("https://git-scm.com/download/win");
} }
@@ -128,24 +179,23 @@ public class GitPanel : EditorWindow
remoteUrlInput = EditorGUILayout.TextField("Remote URL:", remoteUrlInput); remoteUrlInput = EditorGUILayout.TextField("Remote URL:", remoteUrlInput);
if (GUILayout.Button("Initialize Repository", GUILayout.Height(30))) if (GUILayout.Button("Initialize Repository", GUILayout.Height(30)))
{ {
RunGitCommand("init"); RunGitCommand("init", true);
RunGitCommand("branch -M main"); RunGitCommand("branch -M main", true);
if (!string.IsNullOrWhiteSpace(remoteUrlInput)) { if (!string.IsNullOrWhiteSpace(remoteUrlInput)) {
RunGitCommand($"remote add origin \"{remoteUrlInput.Trim()}\""); RunGitCommand($"remote add origin \"{remoteUrlInput.Trim()}\"", true);
RunGitCommand("pull origin main --allow-unrelated-histories --no-edit"); RunGitCommand("pull origin main --allow-unrelated-histories --no-edit", true);
} }
GenerateUnityGitIgnore(); GenerateUnityGitIgnore();
AssetDatabase.Refresh(); AssetDatabase.Refresh();
RunGitCommand("add .gitignore"); RunGitCommand("add .gitignore", true);
RunGitCommand("commit -m \"Initial commit (GitIgnore)\""); RunGitCommand("commit -m \"Initial commit (GitIgnore)\"", true);
if (!string.IsNullOrWhiteSpace(remoteUrlInput)) RunGitCommand("push -u origin main"); if (!string.IsNullOrWhiteSpace(remoteUrlInput)) RunGitCommand("push -u origin main", true);
RefreshData(); RefreshData();
} }
} }
private void RenderGitUI() private void RenderGitUI()
{ {
// --- BRANCH MANAGEMENT ---
EditorGUILayout.BeginVertical("box"); EditorGUILayout.BeginVertical("box");
GUILayout.Label("Branch Management", EditorStyles.boldLabel); GUILayout.Label("Branch Management", EditorStyles.boldLabel);
@@ -155,7 +205,8 @@ public class GitPanel : EditorWindow
int newIndex = EditorGUILayout.Popup("Switch Branch:", selectedBranchIndex, availableBranches); int newIndex = EditorGUILayout.Popup("Switch Branch:", selectedBranchIndex, availableBranches);
if (EditorGUI.EndChangeCheck() && newIndex != selectedBranchIndex) if (EditorGUI.EndChangeCheck() && newIndex != selectedBranchIndex)
{ {
RunGitCommand($"checkout \"{availableBranches[newIndex]}\""); RunGitCommand($"checkout \"{availableBranches[newIndex]}\"", true);
AssetDatabase.Refresh();
RefreshData(); RefreshData();
return; return;
} }
@@ -168,7 +219,7 @@ public class GitPanel : EditorWindow
{ {
if (!string.IsNullOrWhiteSpace(newBranchName)) if (!string.IsNullOrWhiteSpace(newBranchName))
{ {
RunGitCommand($"checkout -b \"{newBranchName.Trim()}\""); RunGitCommand($"checkout -b \"{newBranchName.Trim()}\"", true);
newBranchName = ""; newBranchName = "";
RefreshData(); RefreshData();
GUI.FocusControl(null); GUI.FocusControl(null);
@@ -180,26 +231,60 @@ public class GitPanel : EditorWindow
EditorGUILayout.EndVertical(); EditorGUILayout.EndVertical();
GUILayout.Space(10); GUILayout.Space(10);
// --- COMMIT BEREICH ---
commitMessage = EditorGUILayout.TextField(commitMessage, GUILayout.Height(25)); commitMessage = EditorGUILayout.TextField(commitMessage, GUILayout.Height(25));
EditorGUILayout.BeginHorizontal(); EditorGUILayout.BeginHorizontal();
GUI.backgroundColor = new Color(0.2f, 0.4f, 0.8f); GUI.backgroundColor = new Color(0.2f, 0.4f, 0.8f);
if (GUILayout.Button("✓ Commit & Push", GUILayout.Height(30))) if (GUILayout.Button("✓ Push", GUILayout.Height(30)))
{ {
UnityEngine.Debug.Log("Git-Tool: Saving Scenes and Assets before push...");
UnityEditor.SceneManagement.EditorSceneManager.SaveOpenScenes();
AssetDatabase.SaveAssets();
if (string.IsNullOrWhiteSpace(commitMessage)) SetDefaultCommitMessage(); if (string.IsNullOrWhiteSpace(commitMessage)) SetDefaultCommitMessage();
RunGitCommand("add ."); RunGitCommand("add .", true);
RunGitCommand($"commit -m \"{commitMessage}\""); RunGitCommand($"commit -m \"{commitMessage}\"", true);
RunGitCommand("push -u origin HEAD");
string pushResult = RunGitCommand("push -u origin HEAD", true);
if (pushResult.Contains("rejected") || pushResult.Contains("fetch first"))
{
UnityEngine.Debug.LogError("Git-Tool: PUSH REJECTED! Jemand anderes hat Änderungen hochgeladen. Bitte klicke zuerst auf 'Pull'.");
}
else
{
UnityEngine.Debug.Log("Git-Tool: Changes successfully pushed!");
commitMessage = ""; commitMessage = "";
}
LiveSyncPanel.BroadcastGitUpdate();
RefreshData(); RefreshData();
} }
GUI.backgroundColor = new Color(0.8f, 0.6f, 0.2f);
if (GUILayout.Button("⬇️ Pull", GUILayout.Width(80), GUILayout.Height(30)))
{
UnityEditor.SceneManagement.EditorSceneManager.SaveOpenScenes();
AssetDatabase.SaveAssets();
string pullResult = RunGitCommand("pull", true);
AssetDatabase.Refresh();
if (pullResult.Contains("CONFLICT"))
{
UnityEngine.Debug.LogError("Git-Tool: MERGE CONFLICT! Bitte in VS Code auflösen!");
EditorUtility.DisplayDialog("Merge Conflict", "Es gibt Konflikte mit den Server-Daten!\n\nGit konnte die Änderungen nicht automatisch zusammenführen. Bitte öffne die roten Dateien in deinem Code-Editor und löse den Konflikt manuell auf.", "OK");
}
RefreshData();
}
GUI.backgroundColor = new Color(0.8f, 0.3f, 0.3f); GUI.backgroundColor = new Color(0.8f, 0.3f, 0.3f);
if (GUILayout.Button("⎌ Revert All", GUILayout.Width(80), GUILayout.Height(30))) if (GUILayout.Button("⎌ Revert", GUILayout.Width(80), GUILayout.Height(30)))
{ {
if (EditorUtility.DisplayDialog("Revert Changes?", "Discard ALL uncommitted changes?", "Yes", "Cancel")) { if (EditorUtility.DisplayDialog("Revert Changes?", "Discard ALL uncommitted changes?", "Yes", "Cancel")) {
RunGitCommand("reset --hard HEAD"); RunGitCommand("clean -fd"); RefreshData(); RunGitCommand("reset --hard HEAD", true);
RunGitCommand("clean -fd", true);
AssetDatabase.Refresh();
RefreshData();
} }
} }
GUI.backgroundColor = Color.white; GUI.backgroundColor = Color.white;
@@ -215,6 +300,17 @@ public class GitPanel : EditorWindow
if (changedFiles.Length == 0) GUILayout.Label("No changes."); if (changedFiles.Length == 0) GUILayout.Label("No changes.");
else RenderFileList(changedFiles); else RenderFileList(changedFiles);
EditorGUILayout.EndScrollView(); EditorGUILayout.EndScrollView();
GUILayout.Space(5);
EditorGUILayout.BeginHorizontal();
GUILayout.Label("GIT CONSOLE", EditorStyles.boldLabel);
if (GUILayout.Button("Clear", GUILayout.Width(50))) gitLogOutput = "";
EditorGUILayout.EndHorizontal();
scrollPositionLog = EditorGUILayout.BeginScrollView(scrollPositionLog, "box", GUILayout.Height(120));
GUIStyle logStyle = new GUIStyle(EditorStyles.label) { wordWrap = true, fontSize = 10 };
GUILayout.Label(string.IsNullOrEmpty(gitLogOutput) ? "Ready." : gitLogOutput, logStyle);
EditorGUILayout.EndScrollView();
} }
private void RenderHistoryUI() private void RenderHistoryUI()
@@ -256,7 +352,6 @@ public class GitPanel : EditorWindow
private void OpenCommitInBrowser(string hash) private void OpenCommitInBrowser(string hash)
{ {
// NEU: Override Logik greift zuerst!
if (!string.IsNullOrWhiteSpace(webUrlOverride)) if (!string.IsNullOrWhiteSpace(webUrlOverride))
{ {
string url = webUrlOverride; string url = webUrlOverride;
@@ -266,7 +361,6 @@ public class GitPanel : EditorWindow
return; return;
} }
// Standard Fallback Logik (wenn kein Override gesetzt ist)
string remoteUrl = RunGitCommand("config --get remote.origin.url").Trim(); string remoteUrl = RunGitCommand("config --get remote.origin.url").Trim();
if (string.IsNullOrEmpty(remoteUrl)) return; if (string.IsNullOrEmpty(remoteUrl)) return;
@@ -277,7 +371,6 @@ public class GitPanel : EditorWindow
if (firstColon != -1) remoteUrl = remoteUrl.Remove(firstColon, 1).Insert(firstColon, "/"); if (firstColon != -1) remoteUrl = remoteUrl.Remove(firstColon, 1).Insert(firstColon, "/");
} }
if (remoteUrl.EndsWith(".git")) remoteUrl = remoteUrl.Substring(0, remoteUrl.Length - 4); if (remoteUrl.EndsWith(".git")) remoteUrl = remoteUrl.Substring(0, remoteUrl.Length - 4);
Application.OpenURL($"{remoteUrl}/commit/{hash}"); Application.OpenURL($"{remoteUrl}/commit/{hash}");
} }
@@ -325,10 +418,152 @@ public class GitPanel : EditorWindow
if (!File.Exists(path)) File.WriteAllText(path, ".idea\n.vs\nbin\nobj\n/Library\n/Temp\n/UserSettings\n/Configs\n/*.csproj\n/*.sln\n/Logs\n/Packages/*\n!/Packages/manifest.json\n!/Packages/packages-lock.json\n~UnityDirMonSyncFile~*"); if (!File.Exists(path)) File.WriteAllText(path, ".idea\n.vs\nbin\nobj\n/Library\n/Temp\n/UserSettings\n/Configs\n/*.csproj\n/*.sln\n/Logs\n/Packages/*\n!/Packages/manifest.json\n!/Packages/packages-lock.json\n~UnityDirMonSyncFile~*");
} }
public static string RunGitCommand(string args) { private void ExportPackageInventory()
{
string rootPath = Path.GetFullPath(Path.Combine(Application.dataPath, ".."));
string outputPath = Path.Combine(rootPath, "PACKAGES.md");
string unityManifest = Path.Combine(rootPath, "Packages", "manifest.json");
string vpmManifest = Path.Combine(rootPath, "Packages", "vpm-manifest.json");
List<string> mdLines = new List<string>();
mdLines.Add("# 📦 Project Dependencies Inventory");
mdLines.Add($"\n*Last Update: {System.DateTime.Now:yyyy-MM-dd HH:mm:ss}*");
mdLines.Add("\n> [!TIP]\n> This list helps to restore the workspace if the Creator Companion or Unity fails to auto-resolve dependencies.\n");
int totalFound = 0;
totalFound += ParseManifest(unityManifest, "Unity Standard & Scoped Dependencies", mdLines);
totalFound += ParseManifest(vpmManifest, "VRChat Package Manager (VPM) Dependencies", mdLines);
try { try {
ProcessStartInfo si = new ProcessStartInfo("git", args) { WorkingDirectory = Path.GetFullPath(Path.Combine(Application.dataPath, "..")), UseShellExecute = false, RedirectStandardOutput = true, CreateNoWindow = true }; File.WriteAllLines(outputPath, mdLines, System.Text.Encoding.UTF8);
using (Process p = Process.Start(si)) { string o = p.StandardOutput.ReadToEnd(); p.WaitForExit(); return o; } RunGitCommand($"add \"{outputPath}\"");
UnityEngine.Debug.Log($"Git-Tool: PACKAGES.md aktualisiert. {totalFound} Einträge gefunden.");
} catch (System.Exception e) {
UnityEngine.Debug.LogError("Git-Tool: Fehler beim Schreiben der PACKAGES.md: " + e.Message);
}
}
private int ParseManifest(string path, string sectionTitle, List<string> outputList)
{
if (!File.Exists(path)) return 0;
int count = 0;
try {
string content = File.ReadAllText(path);
// 1. Finde den Start des "dependencies" Blocks
int startIndex = content.IndexOf("\"dependencies\"");
if (startIndex == -1) return 0;
// Finde die erste öffnende Klammer nach dem Wort
startIndex = content.IndexOf("{", startIndex);
if (startIndex == -1) return 0;
// 2. Extrahiere exakt diesen Block, indem wir Klammern zählen
int openBraces = 0;
int endIndex = startIndex;
for (int i = startIndex; i < content.Length; i++) {
if (content[i] == '{') openBraces++;
if (content[i] == '}') {
openBraces--;
// Sobald wir wieder bei 0 sind, ist der Dependencies-Block geschlossen
if (openBraces == 0) {
endIndex = i;
break;
}
}
}
if (endIndex <= startIndex) return 0;
// Header nur zeichnen, wenn wir wirklich einen Block haben
outputList.Add($"## {sectionTitle}");
outputList.Add("| Package Name | Version / Source |");
outputList.Add("| :--- | :--- |");
// Den isolierten Block herauslösen und in Zeilen splitten
string dependenciesBlock = content.Substring(startIndex, endIndex - startIndex + 1);
string[] blockLines = dependenciesBlock.Split(new[] { '\r', '\n' }, System.StringSplitOptions.RemoveEmptyEntries);
string currentVpmPackage = "";
// 3. Den sauberen Block auswerten
foreach (string line in blockLines) {
string trimmed = line.Trim();
// Einzelne Klammern können wir ignorieren, da wir eh schon im richtigen Block sind
if (trimmed == "{" || trimmed == "}" || trimmed == "},") continue;
if (trimmed.StartsWith("\"")) {
string[] parts = trimmed.Split(new char[] { ':' }, 2);
if (parts.Length == 2) {
string key = parts[0].Replace("\"", "").Trim();
string rawValue = parts[1].Trim();
if (rawValue.StartsWith("{")) {
// VPM Paket Start (z.B. "com.vrchat.base": { )
currentVpmPackage = key;
}
else if (key == "version") {
// VPM Paket Version (z.B. "version": "3.10.2")
string val = rawValue.Replace("\"", "").Replace(",", "").Trim();
if (!string.IsNullOrEmpty(currentVpmPackage)) {
outputList.Add($"| `{currentVpmPackage}` | {val} |");
count++;
currentVpmPackage = "";
}
}
else if (!rawValue.StartsWith("{")) {
// Unity Flat Paket (z.B. "com.unity.timeline": "1.2.3")
string val = rawValue.Replace("\"", "").Replace(",", "").Trim();
outputList.Add($"| `{key}` | {val} |");
count++;
}
}
}
}
} catch (System.Exception e) {
UnityEngine.Debug.LogWarning($"Git-Tool: Warnung beim Lesen von {Path.GetFileName(path)}: {e.Message}");
}
if (count == 0) {
outputList.Add("| - | No entries found |");
}
outputList.Add(""); // Leerzeile für sauberes Markdown
return count;
}
// FIX: Methode ist wieder static!
public static string RunGitCommand(string args, bool logAction = false) {
try {
ProcessStartInfo si = new ProcessStartInfo("git", args) {
WorkingDirectory = Path.GetFullPath(Path.Combine(Application.dataPath, "..")),
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
};
using (Process p = Process.Start(si)) {
string o = p.StandardOutput.ReadToEnd();
string e = p.StandardError.ReadToEnd();
p.WaitForExit();
string result = o + (string.IsNullOrWhiteSpace(e) ? "" : "\n" + e);
if (logAction) {
string time = System.DateTime.Now.ToString("HH:mm:ss");
string entry = $"[{time}] > git {args}\n";
if (!string.IsNullOrWhiteSpace(result)) entry += result.Trim() + "\n\n";
gitLogOutput = entry + gitLogOutput;
if (gitLogOutput.Length > 10000) gitLogOutput = gitLogOutput.Substring(0, 10000);
}
return result;
}
} catch { return ""; } } catch { return ""; }
} }
} }
@@ -1,16 +0,0 @@
{
"name": "de.mrunknownde.gittool.Editor",
"rootNamespace": "",
"references": [],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}
+170
View File
@@ -0,0 +1,170 @@
%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: c333ccfdd0cbdbc4ca30cef2dd6e6b9b, type: 3}
m_Name: ProTVRoomZone
m_EditorClassIdentifier:
serializedUdonProgramAsset: {fileID: 11400000, guid: 7f1b25a7785724b4a80dabaacffcc775,
type: 2}
udonAssembly:
assemblyError:
sourceCsScript: {fileID: 11500000, guid: 48ee0805fb47e2e4494f694b970678c1, type: 3}
scriptVersion: 2
compiledVersion: 2
behaviourSyncMode: 0
hasInteractEvent: 0
scriptID: -2239841375030423733
serializationData:
SerializedFormat: 2
SerializedBytes:
ReferencedUnityObjects: []
SerializedBytesString:
Prefab: {fileID: 0}
PrefabModificationsReferencedUnityObjects: []
PrefabModifications: []
SerializationNodes:
- Name: fieldDefinitions
Entry: 7
Data: 0|System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[UdonSharp.Compiler.FieldDefinition,
UdonSharp.Editor]], mscorlib
- Name: comparer
Entry: 7
Data: 1|System.Collections.Generic.GenericEqualityComparer`1[[System.String,
mscorlib]], mscorlib
- Name:
Entry: 8
Data:
- Name:
Entry: 12
Data: 2
- Name:
Entry: 7
Data:
- Name: $k
Entry: 1
Data: localVideoPlayer
- Name: $v
Entry: 7
Data: 2|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: localVideoPlayer
- Name: <UserType>k__BackingField
Entry: 7
Data: 3|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: UnityEngine.GameObject, UnityEngine.CoreModule
- Name:
Entry: 8
Data:
- Name: <SystemType>k__BackingField
Entry: 9
Data: 3
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: true
- Name: _fieldAttributes
Entry: 7
Data: 4|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 1
- Name:
Entry: 7
Data: 5|UnityEngine.HeaderAttribute, UnityEngine.CoreModule
- Name: header
Entry: 1
Data: "Der Videoplayer f\xFCr diesen Raum"
- Name:
Entry: 8
Data:
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 7
Data:
- Name: $k
Entry: 1
Data: roomCollider
- Name: $v
Entry: 7
Data: 6|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: roomCollider
- Name: <UserType>k__BackingField
Entry: 7
Data: 7|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: UnityEngine.BoxCollider, UnityEngine.PhysicsModule
- Name:
Entry: 8
Data:
- Name: <SystemType>k__BackingField
Entry: 9
Data: 7
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 8|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib
- Name:
Entry: 12
Data: 0
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:
+157
View File
@@ -0,0 +1,157 @@
/*
* ============================================================================
* ProTV Room Zone Manager
* ============================================================================
* Ein autarkes Trigger-Modul zur ressourcenschonenden Steuerung von
* ProTV / AVPro Instanzen in VRChat
*
* written by MrUnknownDE
* https://mrunknown.de
* ============================================================================
*/
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;
public class ProTVRoomZone : UdonSharpBehaviour
{
[Header("Der Videoplayer für diesen Raum")]
public GameObject localVideoPlayer;
[Space(10)]
[Header("Fade Settings")]
[Tooltip("Wie lange soll das Ein-/Ausblenden in Sekunden dauern?")]
public float fadeDuration = 1.5f;
[Tooltip("Ziehe hier die AudioSources des ProTVs rein - damit die Lautstärke smooth gefadet wird.")]
public AudioSource[] audioSources;
private BoxCollider roomCollider;
private float fadeProgress = 0f;
private int fadeState = 0;
// Hier speichern wir die echte Lautstärke, bevor sie verfälscht wird
private float[] savedVolumes;
void Start()
{
roomCollider = GetComponent<BoxCollider>();
// Arrays initialisieren und Basis-Lautstärke beim Start sichern
if (audioSources != null && audioSources.Length > 0)
{
savedVolumes = new float[audioSources.Length];
for (int i = 0; i < audioSources.Length; i++)
{
if (audioSources[i] != null) savedVolumes[i] = audioSources[i].volume;
}
}
SendCustomEventDelayedSeconds(nameof(CheckSpawnPosition), 2.0f);
}
public void CheckSpawnPosition()
{
VRCPlayerApi player = Networking.LocalPlayer;
if (!Utilities.IsValid(player)) return;
if (roomCollider != null && roomCollider.bounds.Contains(player.GetPosition()))
{
if (localVideoPlayer != null) localVideoPlayer.SetActive(true);
fadeProgress = 1f;
}
else
{
UpdateSavedVolumes();
if (localVideoPlayer != null) localVideoPlayer.SetActive(false);
fadeProgress = 0f;
}
}
public override void OnPlayerTriggerEnter(VRCPlayerApi player)
{
if (!Utilities.IsValid(player) || !player.isLocal) return;
if (localVideoPlayer != null) localVideoPlayer.SetActive(true);
fadeProgress = 0f;
fadeState = 1;
}
public override void OnPlayerTriggerExit(VRCPlayerApi player)
{
if (!Utilities.IsValid(player) || !player.isLocal) return;
UpdateSavedVolumes();
fadeProgress = 1f;
fadeState = -1; // Starte Fade Out
}
void Update()
{
if (fadeState == 0) return;
if (fadeState == 1) // FADE IN
{
fadeProgress += Time.deltaTime / fadeDuration;
if (fadeProgress >= 1f)
{
fadeProgress = 1f;
fadeState = 0;
}
ApplyFadedVolume();
}
else if (fadeState == -1) // FADE OUT
{
fadeProgress -= Time.deltaTime / fadeDuration;
if (fadeProgress <= 0f)
{
fadeProgress = 0f;
fadeState = 0;
// DER PRO-TV FIX:
RestoreOriginalVolume();
if (localVideoPlayer != null) localVideoPlayer.SetActive(false);
}
else
{
ApplyFadedVolume();
}
}
}
private void UpdateSavedVolumes()
{
if (audioSources == null) return;
for (int i = 0; i < audioSources.Length; i++)
{
if (audioSources[i] != null && audioSources[i].volume > 0.05f)
{
savedVolumes[i] = audioSources[i].volume;
}
}
}
private void ApplyFadedVolume()
{
if (audioSources == null || savedVolumes == null) return;
for (int i = 0; i < audioSources.Length; i++)
{
if (audioSources[i] != null)
{
audioSources[i].volume = savedVolumes[i] * fadeProgress;
}
}
}
private void RestoreOriginalVolume()
{
if (audioSources == null || savedVolumes == null) return;
for (int i = 0; i < audioSources.Length; i++)
{
if (audioSources[i] != null)
{
audioSources[i].volume = savedVolumes[i];
}
}
}
}
+4 -13
View File
@@ -44,19 +44,10 @@ Listen up, because the German Copyright Law (*Urheberrechtsgesetz*) doesn't take
This tool is installed manually directly into your Unity project. This tool is installed manually directly into your Unity project.
### Method 1: Unity Package Manager (Recommended) ### Direct Folder Drop
1. Go to the [Releases page](../../releases/latest) of this repository. 1. Download the latest `mrunknownde-vcc-tools-v20xx-xx-xx.zip` release.
2. Download the latest `de.mrunknownde.gittool-vX.X.X.zip` file.
3. Extract the ZIP file into a folder on your PC.
4. Open your Unity Project.
5. Go to `Window` -> `Package Manager`.
6. Click the **+** icon in the top left corner and select **Add package from disk...**.
7. Navigate to the extracted folder, select the `package.json` file, and click Open.
### Method 2: Direct Folder Drop
1. Download the latest `.zip` release.
2. Extract the archive. 2. Extract the archive.
3. Drag and drop the extracted folder directly into the `Packages` directory inside your Unity project's root folder (using Windows Explorer / File Explorer, not inside the Unity Editor window). Unity will automatically compile the tools. 3. Drag and drop the extracted folder directly into the `Assets` directory inside your Unity project's root folder (using Windows Explorer / File Explorer, not inside the Unity Editor window). Unity will automatically compile the tools.
--- ---
@@ -64,7 +55,7 @@ This tool is installed manually directly into your Unity project.
Once installed, you can access the tools via the top menu bar in Unity: Once installed, you can access the tools via the top menu bar in Unity:
`Tools` -> `MrUnknownDE` -> `GIT Version Control` `Tools` -> `MrUnknownDE` -> `GIT Version Control`<br>
`Tools` -> `MrUnknownDE` -> `Discord RPC` `Tools` -> `MrUnknownDE` -> `Discord RPC`
The tools will open as floating windows. You can easily dock them into your custom Unity layout (e.g., right next to the Inspector or Console). The tools will open as floating windows. You can easily dock them into your custom Unity layout (e.g., right next to the Inspector or Console).