From a68f45734b40244a40cb46d59ea28b0269a3bdc2 Mon Sep 17 00:00:00 2001 From: MrUnknownDE Date: Mon, 6 Apr 2026 20:02:28 +0200 Subject: [PATCH] =?UTF-8?q?=C3=A4hm=20merg=20from=20old=20branch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/release.yml | 90 ---------------- CNAME | 1 - Editor/DiscordRPCPanel.cs | 194 ++++++++++++++++++++++++++++++++++ Editor/GitPanel.cs | 75 +++++++++++-- README.md | 10 -- index.json | 28 ----- package.json | 12 --- 7 files changed, 262 insertions(+), 148 deletions(-) delete mode 100644 .github/workflows/release.yml delete mode 100644 CNAME create mode 100644 Editor/DiscordRPCPanel.cs delete mode 100644 index.json delete mode 100644 package.json diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index c5151c9..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,90 +0,0 @@ -name: VCC Release Automation - -on: - push: - tags: - - "v*" # Startet z.B. bei v1.0.3 - -jobs: - release: - runs-on: ubuntu-latest - permissions: - contents: write # Garantiert Rechte für Releases und Code-Pushes - steps: - - name: Checkout Code - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Extract Metadata - id: metadata - run: | - echo "version=$(jq -r .version package.json)" >> $GITHUB_OUTPUT - echo "pkg_name=$(jq -r .name package.json)" >> $GITHUB_OUTPUT - echo "display_name=$(jq -r .displayName package.json)" >> $GITHUB_OUTPUT - echo "description=$(jq -r .description package.json)" >> $GITHUB_OUTPUT - - - name: Create VCC Package Zip - run: | - mkdir -p staging - cp package.json README.md staging/ - cp -r Editor/ staging/ - cp Editor.meta package.json.meta README.md.meta staging/ 2>/dev/null || true - cd staging - zip -r ../${{ steps.metadata.outputs.pkg_name }}-${{ github.ref_name }}.zip * - cd .. - echo "--- ZIP INHALT PRÜFUNG ---" - unzip -l ${{ steps.metadata.outputs.pkg_name }}-${{ github.ref_name }}.zip - - - name: Upload GitHub Release Asset - uses: softprops/action-gh-release@v2 - with: - files: ${{ steps.metadata.outputs.pkg_name }}-${{ github.ref_name }}.zip - - - name: Update VCC Index - run: | - git config --global user.name "github-actions[bot]" - git config --global user.email "github-actions[bot]@users.noreply.github.com" - - # Prüfen, ob der gh-pages Branch auf dem Server existiert - if git ls-remote --heads origin gh-pages | grep -q gh-pages; then - git checkout gh-pages - else - # Wenn nicht: Erstelle ihn als komplett leeren (orphan) Branch - git checkout --orphan gh-pages - git rm -rf . # Löscht alle Main-Dateien aus diesem Branch - fi - - # Basis-Struktur der index.json erstellen, falls sie noch nicht existiert - if [ ! -f index.json ]; then - echo '{"name":"mrunknownde VCC Tools","id":"de.mrunknownde.vccrepo","url":"https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/index.json","author":"mrunknownde","packages":{}}' > index.json - fi - - # URL zur gerade hochgeladenen ZIP-Datei im Release generieren - ZIP_URL="https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/${{ steps.metadata.outputs.pkg_name }}-${{ github.ref_name }}.zip" - - # Neue Version per jq sauber in die index.json injizieren - jq --arg ver "${{ steps.metadata.outputs.version }}" \ - --arg name "${{ steps.metadata.outputs.pkg_name }}" \ - --arg disp "${{ steps.metadata.outputs.display_name }}" \ - --arg desc "${{ steps.metadata.outputs.description }}" \ - --arg url "$ZIP_URL" \ - '.packages[$name].versions[$ver] = { - "name": $name, - "version": $ver, - "displayName": $disp, - "description": $desc, - "unity": "2022.3", - "url": $url - }' index.json > temp.json && mv temp.json index.json - - # Änderungen stagen - git add index.json - - # Nur committen und pushen, wenn sich die JSON wirklich verändert hat (verhindert Action-Crash) - if ! git diff --cached --quiet; then - git commit -m "Auto-update VCC index.json for ${{ github.ref_name }}" - git push origin gh-pages - else - echo "Keine Änderungen an der index.json festgestellt. Überspringe Push." - fi \ No newline at end of file diff --git a/CNAME b/CNAME deleted file mode 100644 index 448624f..0000000 --- a/CNAME +++ /dev/null @@ -1 +0,0 @@ -vcc.mrunk.de \ No newline at end of file diff --git a/Editor/DiscordRPCPanel.cs b/Editor/DiscordRPCPanel.cs new file mode 100644 index 0000000..bb56ab1 --- /dev/null +++ b/Editor/DiscordRPCPanel.cs @@ -0,0 +1,194 @@ +using UnityEditor; +using UnityEditor.SceneManagement; +using UnityEngine; +using System; +using System.IO.Pipes; +using System.Text; +using System.Threading.Tasks; +using System.Diagnostics; + +public class DiscordRPCPanel : EditorWindow +{ + // === HIER DEINE DISCORD APPLICATION ID EINTRAGEN === + private const string clientId = "1490767097096048780"; + + private static bool isEnabled = false; + private static bool hideSceneName = false; + private static string customStatus = "Building a VRChat World/Avatar"; + + private static NamedPipeClientStream pipe; + private static long startTime; + + [MenuItem("Tools/MrUnknownDE/Discord RPC")] + public static void ShowWindow() + { + DiscordRPCPanel window = GetWindow("Discord RPC"); + window.minSize = new Vector2(300, 250); + } + + private void OnEnable() + { + // Lädt gespeicherte Einstellungen + isEnabled = EditorPrefs.GetBool("DiscordRPC_Enabled", false); + hideSceneName = EditorPrefs.GetBool("DiscordRPC_HideScene", false); + customStatus = EditorPrefs.GetString("DiscordRPC_Status", "Building a VRChat World"); + + if (isEnabled) ConnectToDiscord(); + + // Hooks in Unity einhängen + EditorApplication.playModeStateChanged -= OnPlayModeChanged; + EditorApplication.playModeStateChanged += OnPlayModeChanged; + EditorSceneManager.sceneOpened -= OnSceneOpened; + EditorSceneManager.sceneOpened += OnSceneOpened; + } + + private void OnDisable() + { + if (pipe != null && pipe.IsConnected) pipe.Close(); + } + + private void OnGUI() + { + GUILayout.Space(10); + GUILayout.Label("DISCORD RICH PRESENCE", EditorStyles.boldLabel); + GUILayout.Space(5); + + EditorGUI.BeginChangeCheck(); + + // Status Toggle + GUI.backgroundColor = isEnabled ? new Color(0.2f, 0.8f, 0.2f) : new Color(0.8f, 0.2f, 0.2f); + if (GUILayout.Button(isEnabled ? "Status: ONLINE" : "Status: OFFLINE", GUILayout.Height(30))) + { + isEnabled = !isEnabled; + EditorPrefs.SetBool("DiscordRPC_Enabled", isEnabled); + + if (isEnabled) ConnectToDiscord(); + else DisconnectDiscord(); + } + GUI.backgroundColor = Color.white; + + GUILayout.Space(15); + GUILayout.Label("SETTINGS", EditorStyles.boldLabel); + + // Custom Status Input + GUILayout.Label("Custom Status (Line 1):"); + customStatus = EditorGUILayout.TextField(customStatus); + + // Privacy Toggle + hideSceneName = EditorGUILayout.Toggle("Hide Scene Name (Privacy)", hideSceneName); + + if (EditorGUI.EndChangeCheck()) + { + EditorPrefs.SetBool("DiscordRPC_HideScene", hideSceneName); + EditorPrefs.SetString("DiscordRPC_Status", customStatus); + if (isEnabled) UpdatePresence(); + } + + GUILayout.Space(15); + EditorGUILayout.HelpBox("Wenn aktiv, sieht dein Discord-Server in deinem Profil, an welcher Szene du gerade baust.", MessageType.Info); + } + + // --- UNITY EVENT HOOKS --- + private void OnPlayModeChanged(PlayModeStateChange state) + { + if (isEnabled) UpdatePresence(); + } + + private void OnSceneOpened(UnityEngine.SceneManagement.Scene scene, OpenSceneMode mode) + { + if (isEnabled) UpdatePresence(); + } + + // --- DISCORD IPC LOGIK --- + private async void ConnectToDiscord() + { + if (pipe != null && pipe.IsConnected) return; + + try + { + pipe = new NamedPipeClientStream(".", "discord-ipc-0", PipeDirection.InOut, PipeOptions.Asynchronous); + await pipe.ConnectAsync(2000); + + // Handshake (Opcode 0) + string handshake = "{\"v\": 1, \"client_id\": \"" + clientId + "\"}"; + SendFrame(0, handshake); + + startTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); + UpdatePresence(); + + UnityEngine.Debug.Log("Discord RPC Connected!"); + } + catch (Exception) + { + UnityEngine.Debug.LogWarning("Discord RPC: Konnte keine Verbindung zu Discord herstellen. Läuft Discord?"); + isEnabled = false; + } + } + + private void DisconnectDiscord() + { + if (pipe != null && pipe.IsConnected) + { + pipe.Close(); + pipe.Dispose(); + } + pipe = null; + UnityEngine.Debug.Log("Discord RPC Disconnected."); + } + + private void UpdatePresence() + { + if (pipe == null || !pipe.IsConnected) return; + + string sceneName = hideSceneName ? "Secret Map" : EditorSceneManager.GetActiveScene().name; + if (string.IsNullOrEmpty(sceneName)) sceneName = "Unsaved Scene"; + + string stateText = EditorApplication.isPlaying ? "Testet im Playmode" : $"Editiert: {sceneName}.unity"; + + // Flieht die Strings für sicheres JSON + string safeStatus = customStatus.Replace("\"", "\\\""); + string safeState = stateText.Replace("\"", "\\\""); + + // Das Activity Payload (Opcode 1) + string json = $@"{{ + ""cmd"": ""SET_ACTIVITY"", + ""args"": {{ + ""pid"": {Process.GetCurrentProcess().Id}, + ""activity"": {{ + ""details"": ""{safeStatus}"", + ""state"": ""{safeState}"", + ""timestamps"": {{ + ""start"": {startTime} + }}, + ""instance"": false + }} + }}, + ""nonce"": ""1"" + }}"; + + SendFrame(1, json); + } + + private void SendFrame(int opcode, string payload) + { + if (pipe == null || !pipe.IsConnected) return; + + byte[] payloadBytes = Encoding.UTF8.GetBytes(payload); + int length = payloadBytes.Length; + byte[] buffer = new byte[8 + length]; + + BitConverter.GetBytes(opcode).CopyTo(buffer, 0); + BitConverter.GetBytes(length).CopyTo(buffer, 4); + payloadBytes.CopyTo(buffer, 8); + + try + { + pipe.Write(buffer, 0, buffer.Length); + } + catch (Exception e) + { + UnityEngine.Debug.LogError("Discord RPC Error: " + e.Message); + DisconnectDiscord(); + } + } +} \ No newline at end of file diff --git a/Editor/GitPanel.cs b/Editor/GitPanel.cs index 2679bf7..068d617 100644 --- a/Editor/GitPanel.cs +++ b/Editor/GitPanel.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; public class GitPanel : EditorWindow { private string commitMessage = ""; + private string remoteUrlInput = ""; // NEU: Speicher für die Remote-URL private bool hasRepo = false; private string[] changedFiles = new string[0]; private Vector2 scrollPositionChanges; @@ -18,7 +19,7 @@ public class GitPanel : EditorWindow private struct CommitInfo { public string hash; public string date; public string message; } private List commitHistory = new List(); - [MenuItem("Tools/Git-Tool")] + [MenuItem("Tools/MrUnknownDE/Git-Tool")] public static void ShowWindow() { GitPanel window = GetWindow("Source Control"); @@ -26,9 +27,25 @@ public class GitPanel : EditorWindow } private void OnEnable() + { + RefreshData(); + } + + private void OnFocus() + { + RefreshData(); + } + + public void RefreshData() { CheckRepoStatus(); - SetDefaultCommitMessage(); + + if (string.IsNullOrWhiteSpace(commitMessage) || commitMessage.StartsWith("Auto-Save:")) + { + SetDefaultCommitMessage(); + } + + Repaint(); } private void SetDefaultCommitMessage() @@ -58,13 +75,42 @@ public class GitPanel : EditorWindow private void RenderInitUI() { EditorGUILayout.HelpBox("No local Git repository found. Initialize current project folder?", MessageType.Warning); + + GUILayout.Space(10); + GUILayout.Label("Remote Repository URL (Optional):", EditorStyles.boldLabel); + remoteUrlInput = EditorGUILayout.TextField(remoteUrlInput, GUILayout.Height(25)); + EditorGUILayout.HelpBox("e.g., https://github.com/user/repo.git or git@gitea.domain.com:user/repo.git", MessageType.Info); + GUILayout.Space(10); + if (GUILayout.Button("Initialize Repository", GUILayout.Height(30))) { RunGitCommand("init"); + + // Branch direkt sauber auf "main" setzen (verhindert Konflikte mit alten "master" Defaults) + RunGitCommand("branch -M main"); + + // Remote URL hinzufügen, falls angegeben + if (!string.IsNullOrWhiteSpace(remoteUrlInput)) + { + RunGitCommand($"remote add origin \"{remoteUrlInput.Trim()}\""); + } + GenerateUnityGitIgnore(); RunGitCommand("add .gitignore"); RunGitCommand("commit -m \"Initial commit (GitIgnore)\""); - CheckRepoStatus(); + + // Initialen Push ausführen, wenn ein Remote existiert + if (!string.IsNullOrWhiteSpace(remoteUrlInput)) + { + RunGitCommand("push -u origin main"); + UnityEngine.Debug.Log("Git-Tool: Repository initialized and pushed to remote!"); + } + else + { + UnityEngine.Debug.Log("Git-Tool: Local repository initialized successfully."); + } + + RefreshData(); } } @@ -81,8 +127,8 @@ public class GitPanel : EditorWindow RunGitCommand($"commit -m \"{commitMessage}\""); RunGitCommand("push"); - SetDefaultCommitMessage(); - CheckRepoStatus(); + commitMessage = ""; + RefreshData(); UnityEngine.Debug.Log("Git-Tool: Changes successfully pushed!"); } GUI.backgroundColor = Color.white; @@ -95,8 +141,7 @@ public class GitPanel : EditorWindow GUILayout.Label($"CHANGES ({changedFiles.Length})", EditorStyles.boldLabel); if (GUILayout.Button("↻", GUILayout.Width(25))) { - CheckRepoStatus(); - SetDefaultCommitMessage(); + RefreshData(); } EditorGUILayout.EndHorizontal(); @@ -275,4 +320,20 @@ obj } catch { return ""; } } +} + +public class GitSaveListener : UnityEditor.AssetModificationProcessor +{ + public static string[] OnWillSaveAssets(string[] paths) + { + EditorApplication.delayCall += () => + { + if (EditorWindow.HasOpenInstances()) + { + EditorWindow.GetWindow().RefreshData(); + } + }; + + return paths; + } } \ No newline at end of file diff --git a/README.md b/README.md index 88911c3..2bed91a 100644 --- a/README.md +++ b/README.md @@ -10,16 +10,6 @@ A lightweight, integrated Source Control Panel built directly into Unity. Design - `Double Click` on a file -> Opens the built-in Code Diff Viewer right inside the Editor. - **History View:** Browse your latest commits. Click any commit to open it directly in your remote web view (Gitea, GitHub, GitLab). -## 🚀 Installation via VRChat Creator Companion (VCC) - -You can add this tool as a custom package directly into your VCC. - -1. Open the VRChat Creator Companion. -2. Navigate to **Settings** -> **Packages**. -3. Click on **Add Repository**. -4. Enter your custom repo URL: `https://vcc.mrunk.de/index.json` -5. In your project views, under "Manage Project", the **VRChat Git Control Tool** will now appear. Simply click the plus icon to add it. - ## 🛠️ Manual Installation 1. Download the latest version as a `.zip` archive. 2. Extract the folder. diff --git a/index.json b/index.json deleted file mode 100644 index 2370120..0000000 --- a/index.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "MrUnknownDE's VCC Tools", - "id": "de.mrunknownde.vcc-tools", - "url": "https://vcc.mrunk.de/index.json", - "author": "MrUnknownDE", - "packages": { - "de.mrunknownde.vcc-tools": { - "versions": { - "1.0.3": { - "name": "de.mrunknownde.vcc-tools", - "version": "1.0.3", - "displayName": "MrUnknownDE's VRChat Tools", - "url": "https://github.com/MrUnknownDE/vcc-tools/archive/refs/tags/v1.0.3.zip", - "unity": "2022.3", - "description": "A lightweight, integrated Git panel for Unity." - }, - "1.0.2": { - "name": "de.mrunknownde.vcc-tools", - "version": "1.0.2", - "displayName": "MrUnknownDE's VRChat Tools", - "url": "https://github.com/MrUnknownDE/vcc-tools/archive/refs/tags/v1.0.2.zip", - "unity": "2022.3", - "description": "A lightweight, integrated Git panel for Unity." - } - } - } - } -} \ No newline at end of file diff --git a/package.json b/package.json deleted file mode 100644 index f32d09e..0000000 --- a/package.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "de.mrunknownde.vcc-tools", - "version": "1.0.0", - "displayName": "MrUnknownDE's VRChat Tools", - "description": "A lightweight, integrated Git panel for Unity.", - "unity": "2022.3", - "author": { - "name": "MrUnknownDE" - }, - "dependencies": {}, - "vpmDependencies": {} -} \ No newline at end of file