Skip to content

Commit

Permalink
Implemented LagFreeScreenshots event, some bug fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
DragonPlayerX committed Nov 22, 2021
1 parent b1b93b3 commit fab2042
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 19 deletions.
87 changes: 81 additions & 6 deletions ScreenshotManager/Core/FileDataHandler.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.Serialization;
using System.Runtime.CompilerServices;
using System.IO;
using System.Linq;
using System.Reflection;
Expand All @@ -21,8 +23,6 @@ public static class FileDataHandler
// First 8 bytes of a PNG are always theses values otherwise the signature or file is corrupted
private static readonly byte[] PngSignature = new byte[] { 137, 80, 78, 71, 13, 10, 26, 10 };

public static bool UseLFS = false;

// Method copied from https://github.com/knah/VRCMods/blob/master/LagFreeScreenshots/PngUtils.cs
private static readonly uint[] ourCRCTable = Enumerable.Range(0, 256).Select(n =>
{
Expand Down Expand Up @@ -53,16 +53,34 @@ private static uint PngCrc32(byte[] stream, int offset, int length, uint crc)

public static void Init()
{
UseLFS = MelonHandler.Mods.Any(mod => mod.Info.Name.Equals("Lag Free Screenshots"));
Assembly lfsAssembly = null;
try
{
lfsAssembly = MelonHandler.Mods.First(mod => mod.Info.Name.Equals("Lag Free Screenshots")).Assembly;
}
catch (Exception) { }

if (!UseLFS)
if (lfsAssembly == null)
{
ScreenshotManagerMod.Instance.HarmonyInstance.Patch(typeof(ScreenshotFileHandler).GetMethod("_TakeScreenShot_b__1"), postfix: new HarmonyMethod(typeof(FileDataHandler).GetMethod(nameof(DefaultVRCScreenshotResultPatch), BindingFlags.Static | BindingFlags.NonPublic)));
}
else
{
if (lfsAssembly.GetType("LagFreeScreenshots.EventHandler", false) != null)
LFSIntegration.InitLFS();
else
MelonLogger.Warning("Your version of LagFreeScreenshots does not support events.");
}
}

private static void DefaultVRCScreenshotResultPatch(ScreenshotFileHandler __instance)
{
ImageHandler.AddFile(new FileInfo(__instance.field_Public_String_0));
WriteMetadataAfterSave(__instance.field_Public_String_0);
}

private static void WriteMetadataAfterSave(string path)
{
if (!Configuration.WriteImageMetadata.Value)
return;

Expand All @@ -73,9 +91,16 @@ private static void DefaultVRCScreenshotResultPatch(ScreenshotFileHandler __inst

string description = "screenshotmanager|0|author:" + username + "|" + world;

if (__instance.field_Public_String_0.ToLower().EndsWith(ImageHandler.Extensions[0]))
if (path.ToLower().EndsWith(ImageHandler.Extensions[0]))
{
bool result = WritePngChunk(__instance.field_Public_String_0, description);
bool result = WritePngChunk(path, description);

if (!result)
MelonLogger.Warning("Failed to write image metadata. Image will be saved without any data.");
}
else if (path.ToLower().EndsWith(ImageHandler.Extensions[1]))
{
bool result = WriteJpegProperty(path, description);

if (!result)
MelonLogger.Warning("Failed to write image metadata. Image will be saved without any data.");
Expand Down Expand Up @@ -206,6 +231,41 @@ public static string ReadPngChunk(string file)
}
}

public static bool WriteJpegProperty(string file, string text)
{
try
{
Image oldImage = Image.FromFile(file);
Image image = new Bitmap(oldImage);

oldImage.Dispose();

int textByteCount = Encoding.Unicode.GetByteCount(text);
byte[] textBytes = new byte[8 + textByteCount];
Encoding.ASCII.GetBytes("UNICODE\0", 0, 8, textBytes, 0);
Encoding.Unicode.GetBytes(text, 0, text.Length, textBytes, 8);

PropertyItem property = FormatterServices.GetUninitializedObject(typeof(PropertyItem)) as PropertyItem;
property.Type = 7;
property.Id = 0x9286;
property.Value = textBytes;
property.Len = property.Value.Length;

image.SetPropertyItem(property);
image.Save(file, ImageFormat.Jpeg);

image.Dispose();

return true;
}
catch (Exception e)
{
MelonLogger.Error(e);
MelonLogger.Error("Error while writing jpeg properties");
return false;
}
}

public static string ReadJpegProperty(Image image)
{
try
Expand All @@ -219,5 +279,20 @@ public static string ReadJpegProperty(Image image)
return null;
}
}

internal class LFSIntegration
{
[MethodImpl(MethodImplOptions.NoInlining)]
public static void InitLFS()
{
LagFreeScreenshots.EventHandler.OnScreenshotSaved += new Action<string, int, int, LagFreeScreenshots.Metadata>((path, width, height, metadata) =>
{
ImageHandler.AddFile(new FileInfo(path));

if (metadata == null)
WriteMetadataAfterSave(path);
});
}
}
}
}
7 changes: 4 additions & 3 deletions ScreenshotManager/Core/ImageHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -364,14 +364,15 @@ public static void RotateImage(Direction direction)
MelonLogger.Error("File not found: " + fileInfo.FullName);
return;
}

DateTime lastWriteTime = fileInfo.LastWriteTime;

System.Drawing.Image image = System.Drawing.Image.FromFile(fileInfo.FullName);

string data = null;
if (selectedFile.Extension.Equals(Extensions[0]))
data = FileDataHandler.ReadPngChunk(selectedFile.FullName);
else if (selectedFile.Extension.Equals(Extensions[1]))
if (fileInfo.Extension.Equals(Extensions[0]))
data = FileDataHandler.ReadPngChunk(fileInfo.FullName);
else if (fileInfo.Extension.Equals(Extensions[1]))
data = FileDataHandler.ReadJpegProperty(image);

if (direction == Direction.Right)
Expand Down
10 changes: 7 additions & 3 deletions ScreenshotManager/Core/MenuManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -187,9 +187,13 @@ public static void Init()
Text imageWorldNameHeader = textContainer.Find("WorldName/Text_Header").GetComponent<Text>();
ImageWorldNameText = textContainer.Find("WorldName/Text_Content").GetComponent<Text>();

GameObject tempObject1 = Object.Instantiate(new GameObject(), TabButton.SubMenu.RectTransform);
GameObject tempObject2 = Object.Instantiate(new GameObject(), TabButton.SubMenu.RectTransform);
GameObject tempObject3 = Object.Instantiate(new GameObject(), TabButton.SubMenu.RectTransform);
GameObject tempObject1 = new GameObject();
GameObject tempObject2 = new GameObject();
GameObject tempObject3 = new GameObject();

tempObject1.transform.parent = TabButton.SubMenu.RectTransform;
tempObject2.transform.parent = TabButton.SubMenu.RectTransform;
tempObject3.transform.parent = TabButton.SubMenu.RectTransform;

TextMeshProUGUI text1 = tempObject1.AddComponent<TextMeshProUGUI>();
TextMeshProUGUI text2 = tempObject2.AddComponent<TextMeshProUGUI>();
Expand Down
23 changes: 18 additions & 5 deletions ScreenshotManager/Core/SteamIntegration.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using MelonLoader;
Expand Down Expand Up @@ -58,8 +59,15 @@ public static void Init()
catch (Exception e)
{
Enabled = false;
MelonLogger.Error(e);
MelonLogger.Error("An error occurred while loading Steam API. The Steam integration is now disabled.");
if (e is DllNotFoundException)
{
MelonLogger.Warning("Steam API file not found. The Steam integration is now disabled.");
}
else
{
MelonLogger.Error(e);
MelonLogger.Error("An error occurred while loading Steam API. The Steam integration is now disabled.");
}
}
}

Expand All @@ -78,11 +86,16 @@ public static bool ImportScreenshot(string file, string location = null, List<ul
string tempFile = Path.GetTempPath() + fileInfo.Name;
File.Copy(file, tempFile);

uint handle = SteamAPI_ISteamScreenshots_AddScreenshotToLibrary(steamScreenshotsInterfacePtr, tempFile, null, 1920, 1080);
MelonLogger.Msg("[Steam API] Screenshot Handle: " + handle);
Image image = Image.FromFile(file);

uint handle = SteamAPI_ISteamScreenshots_AddScreenshotToLibrary(steamScreenshotsInterfacePtr, tempFile, null, image.Width, image.Height);
MelonLogger.Msg("[Steam API] Screenshot Handle: " + handle + " Size: " + image.Width + "x" + image.Height);

image.Dispose();

if (location != null)
ISteamScreenshots_SetLocation(steamScreenshotsInterfacePtr, handle, location);

if (taggedUsers != null)
{
if (taggedUsers.Count > 32)
Expand Down
3 changes: 3 additions & 0 deletions ScreenshotManager/ScreenshotManager.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
<Reference Include="Il2CppSystem">
<HintPath>..\Libs\Il2CppSystem.dll</HintPath>
</Reference>
<Reference Include="LagFreeScreenshots">
<HintPath>..\Libs\LagFreeScreenshots.dll</HintPath>
</Reference>
<Reference Include="MelonLoader">
<HintPath>..\Libs\MelonLoader.dll</HintPath>
</Reference>
Expand Down
5 changes: 3 additions & 2 deletions ScreenshotManager/ScreenshotManagerMod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,16 @@
using ScreenshotManager.UI;
using ScreenshotManager.UI.Components;

[assembly: MelonInfo(typeof(ScreenshotManagerMod), "ScreenshotManager", "2.1.3", "DragonPlayer", "https://github.com/DragonPlayerX/ScreenshotManager")]
[assembly: MelonInfo(typeof(ScreenshotManagerMod), "ScreenshotManager", "2.1.4", "DragonPlayer", "https://github.com/DragonPlayerX/ScreenshotManager")]
[assembly: MelonGame("VRChat", "VRChat")]
[assembly: MelonOptionalDependencies("LagFreeScreenshots")]

namespace ScreenshotManager
{
public class ScreenshotManagerMod : MelonMod
{

public static readonly string Version = "2.1.3";
public static readonly string Version = "2.1.4";

public static ScreenshotManagerMod Instance { get; private set; }

Expand Down

0 comments on commit fab2042

Please sign in to comment.