Added a way to store block groups as blueprints Blocks can be added/removed from block groups, although it doesn't work well atm Added some patches to the test class in an attempt to debug an unrelated issue Added a command to test placing a block group Added a SelectedBlueprint property to the Player classtags/v1.7.0
@@ -240,6 +240,8 @@ namespace GamecraftModdingAPI | |||
set | |||
{ | |||
MovementEngine.MoveBlock(Id, InitData, value); | |||
if (blockGroup != null) | |||
blockGroup.PosAndRotCalculated = false; | |||
} | |||
} | |||
@@ -252,6 +254,8 @@ namespace GamecraftModdingAPI | |||
set | |||
{ | |||
RotationEngine.RotateBlock(Id, InitData, value); | |||
if (blockGroup != null) | |||
blockGroup.PosAndRotCalculated = false; | |||
} | |||
} | |||
@@ -354,15 +358,31 @@ namespace GamecraftModdingAPI | |||
} | |||
} | |||
private BlockGroup blockGroup; | |||
/// <summary> | |||
/// Returns the block group this block is a part of. Block groups can be placed using blueprints. | |||
/// Returns null if not part of a group. | |||
/// Returns null if not part of a group.<br /> | |||
/// Setting the group after the block has been initialized will not update everything properly. | |||
/// You should only set this property on blocks newly placed by your code. | |||
/// </summary> | |||
public BlockGroup BlockGroup | |||
{ | |||
get => BlockEngine.GetBlockInfo(this, | |||
(BlockGroupEntityComponent bgec) => | |||
bgec.currentBlockGroup == -1 ? null : new BlockGroup(bgec.currentBlockGroup, this)); | |||
get | |||
{ | |||
if (blockGroup != null) return blockGroup; | |||
return blockGroup = BlockEngine.GetBlockInfo(this, | |||
(BlockGroupEntityComponent bgec) => | |||
bgec.currentBlockGroup == -1 ? null : new BlockGroup(bgec.currentBlockGroup, this)); | |||
} | |||
set | |||
{ | |||
blockGroup?.RemoveInternal(this); | |||
BlockEngine.SetBlockInfo(this, | |||
(ref BlockGroupEntityComponent bgec, BlockGroup val) => bgec.currentBlockGroup = val?.Id ?? -1, | |||
value); | |||
value?.AddInternal(this); | |||
blockGroup = value; | |||
} | |||
} | |||
/// <summary> | |||
@@ -1,4 +1,8 @@ | |||
using Gamecraft.Blocks.BlockGroups; | |||
using System; | |||
using System.Collections; | |||
using System.Collections.Generic; | |||
using Gamecraft.Blocks.BlockGroups; | |||
using Unity.Mathematics; | |||
using UnityEngine; | |||
@@ -10,11 +14,14 @@ namespace GamecraftModdingAPI | |||
/// <summary> | |||
/// A group of blocks that can be selected together. The placed version of blueprints. | |||
/// </summary> | |||
public class BlockGroup | |||
public class BlockGroup : ICollection<Block> | |||
{ | |||
internal static BlueprintEngine _engine = new BlueprintEngine(); | |||
public int Id { get; } | |||
private readonly Block sourceBlock; | |||
private readonly List<Block> blocks; | |||
private float3 position, rotation; | |||
internal bool PosAndRotCalculated; | |||
internal BlockGroup(int id, Block block) | |||
{ | |||
@@ -22,41 +29,155 @@ namespace GamecraftModdingAPI | |||
throw new BlockException("Cannot create a block group for blocks without a group!"); | |||
Id = id; | |||
sourceBlock = block; | |||
blocks = new List<Block>(GetBlocks()); | |||
} | |||
/// <summary> | |||
/// The position of the block group. Calculated when GetBlocks() is used. | |||
/// The position of the block group (center). Recalculated if blocks have been added/removed since the last query. | |||
/// </summary> | |||
public float3 Position { get; private set; } | |||
public float3 Position | |||
{ | |||
get | |||
{ | |||
if (!PosAndRotCalculated) | |||
Refresh(); | |||
return position; | |||
} | |||
set | |||
{ | |||
var diff = value - position; | |||
foreach (var block in blocks) | |||
block.Position += diff; | |||
if (!PosAndRotCalculated) //The condition can only be true if a block has been added/removed manually | |||
Refresh(); //So the blocks array is up to date | |||
else | |||
position += diff; | |||
} | |||
} | |||
/// <summary> | |||
/// The rotation of the block group. Recalculated if blocks have been added/removed since the last query. | |||
/// </summary> | |||
public float3 Rotation | |||
{ | |||
get | |||
{ | |||
if (!PosAndRotCalculated) | |||
Refresh(); | |||
return rotation; | |||
} | |||
set | |||
{ | |||
var diff = value - rotation; | |||
var qdiff = Quaternion.Euler(diff); | |||
foreach (var block in blocks) | |||
{ | |||
block.Rotation += diff; | |||
block.Position = qdiff * block.Position; | |||
} | |||
if (!PosAndRotCalculated) | |||
Refresh(); | |||
else | |||
rotation += diff; | |||
} | |||
} | |||
/*/// <summary> | |||
/// Removes all of the blocks in this group from the world. | |||
/// </summary> | |||
public void RemoveBlocks() | |||
{ | |||
_engine.RemoveBlockGroup(Id); - TODO: Causes a hard crash | |||
}*/ | |||
/// <summary> | |||
/// The rotation of the block group. Calculated when GetBlocks() is used. | |||
/// Creates a new block group consisting of a single block. | |||
/// You can add more blocks using the Add() method or by setting the BlockGroup property of the blocks.<br /> | |||
/// Note that only newly placed blocks should be added to groups. | |||
/// </summary> | |||
public float3 Rotation { get; private set; } | |||
/// <param name="block">The block to add</param> | |||
/// <returns>A new block group containing the given block</returns> | |||
public static BlockGroup Create(Block block) | |||
{ | |||
return new BlockGroup(_engine.CreateBlockGroup(default, default), block); | |||
} | |||
/// <summary> | |||
/// Collects each block that is a part of this group. Also sets the position and rotation. | |||
/// </summary> | |||
/// <returns>An array of blocks</returns> | |||
public Block[] GetBlocks() | |||
private Block[] GetBlocks() | |||
{ | |||
if (!sourceBlock.Exists) return new[] {sourceBlock}; //The block must exist to get the others | |||
var ret = _engine.GetBlocksFromGroup(sourceBlock.Id, out var pos, out var rot); | |||
Position = pos; | |||
Rotation = ((Quaternion) rot).eulerAngles; | |||
position = pos; | |||
rotation = ((Quaternion) rot).eulerAngles; | |||
PosAndRotCalculated = true; | |||
return ret; | |||
} | |||
private void Refresh() | |||
{ | |||
blocks.Clear(); | |||
blocks.AddRange(GetBlocks()); | |||
} | |||
internal static void Init() | |||
{ | |||
GameEngineManager.AddGameEngine(_engine); | |||
} | |||
public IEnumerator<Block> GetEnumerator() => blocks.GetEnumerator(); | |||
IEnumerator IEnumerable.GetEnumerator() => blocks.GetEnumerator(); | |||
/// <summary> | |||
/// Removes all of the blocks in this group from the world. | |||
/// Adds a block to the group. You should only add newly placed blocks | |||
/// so that the game initializes the group membership properly. | |||
/// </summary> | |||
public void Remove() | |||
/// <param name="item"></param> | |||
/// <exception cref="NullReferenceException"></exception> | |||
public void Add(Block item) | |||
{ | |||
_engine.RemoveBlockGroup(Id); | |||
if (item == null) throw new NullReferenceException("Cannot add null to a block group"); | |||
item.BlockGroup = this; //Calls AddInternal | |||
} | |||
public static void Init() | |||
internal void AddInternal(Block item) => blocks.Add(item); | |||
/// <summary> | |||
/// Removes all blocks from this group. | |||
/// You should not remove blocks that have been initialized, only those that you placed recently. | |||
/// </summary> | |||
public void Clear() | |||
{ | |||
GameEngineManager.AddGameEngine(_engine); | |||
while (blocks.Count > 0) | |||
Remove(blocks[blocks.Count - 1]); | |||
} | |||
public bool Contains(Block item) => blocks.Contains(item); | |||
public void CopyTo(Block[] array, int arrayIndex) => blocks.CopyTo(array, arrayIndex); | |||
/// <summary> | |||
/// Removes a block from this group. | |||
/// You should not remove blocks that have been initialized, only those that you placed recently. | |||
/// </summary> | |||
/// <param name="item"></param> | |||
/// <returns></returns> | |||
/// <exception cref="NullReferenceException"></exception> | |||
public bool Remove(Block item) | |||
{ | |||
if (item == null) throw new NullReferenceException("Cannot remove null from a block group"); | |||
bool ret = item.BlockGroup == this; | |||
if (ret) | |||
item.BlockGroup = null; //Calls RemoveInternal | |||
return ret; | |||
} | |||
internal void RemoveInternal(Block item) => blocks.Remove(item); | |||
public int Count => blocks.Count; | |||
public bool IsReadOnly { get; } = false; | |||
public Block this[int index] => blocks[index]; //Setting is not supported, since the order doesn't matter | |||
} | |||
} |
@@ -5,10 +5,11 @@ using Svelto.ECS; | |||
using GamecraftModdingAPI.Engines; | |||
using GamecraftModdingAPI.Utility; | |||
using RobocraftX.Blocks; | |||
namespace GamecraftModdingAPI.Blocks | |||
{ | |||
public class BlockEventsEngine : IReactionaryEngine<DBEntityStruct> | |||
public class BlockEventsEngine : IReactionaryEngine<BlockTagEntityStruct> | |||
{ | |||
public event EventHandler<BlockPlacedRemovedEventArgs> Placed; | |||
public event EventHandler<BlockPlacedRemovedEventArgs> Removed; | |||
@@ -27,20 +28,20 @@ namespace GamecraftModdingAPI.Blocks | |||
public bool isRemovable { get; } = false; | |||
private bool shouldAddRemove; | |||
public void Add(ref DBEntityStruct entityComponent, EGID egid) | |||
public void Add(ref BlockTagEntityStruct entityComponent, EGID egid) | |||
{ | |||
if (!(shouldAddRemove = !shouldAddRemove)) | |||
return; | |||
ExceptionUtil.InvokeEvent(Placed, this, | |||
new BlockPlacedRemovedEventArgs {ID = egid, Type = (BlockIDs) entityComponent.DBID}); | |||
new BlockPlacedRemovedEventArgs {ID = egid}); | |||
} | |||
public void Remove(ref DBEntityStruct entityComponent, EGID egid) | |||
public void Remove(ref BlockTagEntityStruct entityComponent, EGID egid) | |||
{ | |||
if (!(shouldAddRemove = !shouldAddRemove)) | |||
return; | |||
ExceptionUtil.InvokeEvent(Removed, this, | |||
new BlockPlacedRemovedEventArgs {ID = egid, Type = (BlockIDs) entityComponent.DBID}); | |||
new BlockPlacedRemovedEventArgs {ID = egid}); | |||
} | |||
} | |||
@@ -1,4 +1,5 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Reflection; | |||
using Gamecraft.Blocks.BlockGroups; | |||
using Gamecraft.GUI.Blueprints; | |||
@@ -21,7 +22,7 @@ using Allocator = Svelto.Common.Allocator; | |||
namespace GamecraftModdingAPI.Blocks | |||
{ | |||
public class BlueprintEngine : IApiEngine | |||
public class BlueprintEngine : IFactoryEngine | |||
{ | |||
private readonly MethodInfo getBlocksFromGroup = | |||
AccessTools.Method("RobocraftX.CR.MachineEditing.PlaceBlockUtility:GetBlocksSharingBlockgroup"); | |||
@@ -77,12 +78,29 @@ namespace GamecraftModdingAPI.Blocks | |||
connectionFactory, default).Complete(); | |||
} | |||
public void SelectBlueprint(uint resourceID) | |||
public int CreateBlockGroup(float3 position, quaternion rotation) | |||
{ | |||
BlueprintUtil.SelectBlueprint(null, new BlueprintInventoryItemEntityStruct | |||
int nextFilterId = BlockGroupUtility.NextFilterId; | |||
Factory.BuildEntity<BlockGroupEntityDescriptor>((uint) nextFilterId, | |||
BlockGroupExclusiveGroups.BlockGroupEntityGroup).Init(new BlockGroupTransformEntityComponent | |||
{ | |||
blueprintResourceId = resourceID, | |||
blockGroupGridRotation = rotation, | |||
blockGroupGridPosition = position | |||
}); | |||
return nextFilterId; | |||
} | |||
public void SelectBlueprint(uint resourceID) | |||
{ | |||
if (resourceID == uint.MaxValue) | |||
BlueprintUtil.UnselectBlueprint(entitiesDB); | |||
else | |||
{ | |||
BlueprintUtil.SelectBlueprint(entitiesDB, new BlueprintInventoryItemEntityStruct | |||
{ | |||
blueprintResourceId = resourceID, | |||
}); | |||
} | |||
} | |||
public uint CreateBlueprint() | |||
@@ -91,28 +109,27 @@ namespace GamecraftModdingAPI.Blocks | |||
return index; | |||
} | |||
public void ReplaceBlueprint(uint playerID, uint blueprintID, Block[] selected, float3 pos, quaternion rot) | |||
public void ReplaceBlueprint(uint playerID, uint blueprintID, ICollection<Block> selected, float3 pos, quaternion rot) | |||
{ | |||
var blockIDs = new EGID[selected.Length]; | |||
for (var i = 0; i < selected.Length; i++) | |||
var blockIDs = new EGID[selected.Count]; | |||
using (var enumerator = selected.GetEnumerator()) | |||
{ | |||
var block = selected[i]; | |||
blockIDs[i] = block.Id; | |||
for (var i = 0; enumerator.MoveNext(); i++) | |||
{ | |||
var block = enumerator.Current; | |||
blockIDs[i] = block.Id; | |||
} | |||
} | |||
var serializationData = clipboardManager.GetSerializationData(blueprintID); | |||
SelectionSerializationUtility.ClearClipboard(playerID, entitiesDB, entityFunctions, serializationData.blueprintData); | |||
if (selected.Length == 0) | |||
if (selected.Count == 0) | |||
return; | |||
//ref BlockGroupTransformEntityComponent groupTransform = ref EntityNativeDBExtensions.QueryEntity<BlockGroupTransformEntityComponent>(entitiesDb, (uint) local1.currentBlockGroup, BlockGroupExclusiveGroups.BlockGroupEntityGroup); | |||
//ref ColliderAabb collider = ref EntityNativeDBExtensions.QueryEntity<ColliderAabb>(entitiesDB, (uint) groupID, BlockGroupExclusiveGroups.BlockGroupEntityGroup); | |||
//float3 bottomOffset = PlaceBlockUtility.GetBottomOffset(collider); | |||
//var rootPosition = math.mul(groupTransform.blockGroupGridRotation, bottomOffset) + groupTransform.blockGroupGridPosition; | |||
//var rootRotation = groupTransform.blockGroupGridRotation; | |||
if (math.all(pos == default)) | |||
pos = selected[0].Position; | |||
if (math.all(rot.value == default)) | |||
rot = Quaternion.Euler(selected[0].Rotation); | |||
clipboardManager.SetGhostSerialized(blueprintID, false); | |||
SelectionSerializationUtility.CopySelectionToClipboard(playerID, entitiesDB, | |||
@@ -189,7 +206,7 @@ namespace GamecraftModdingAPI.Blocks | |||
} | |||
public string Name { get; } = "GamecraftModdingAPIBlueprintGameEngine"; | |||
public bool isRemovable { get; } | |||
public bool isRemovable { get; } = false; | |||
[HarmonyPatch] | |||
private static class RemoveEnginePatch | |||
@@ -225,5 +242,7 @@ namespace GamecraftModdingAPI.Blocks | |||
return AccessTools.GetDeclaredConstructors(AccessTools.TypeByName("RobocraftX.CR.MachineEditing.SelectBlockEngine"))[0]; | |||
} | |||
} | |||
public IEntityFactory Factory { get; set; } | |||
} | |||
} |
@@ -53,15 +53,15 @@ namespace GamecraftModdingAPI.Blocks | |||
private EntityComponentInitializer BuildBlock(ushort block, byte color, float3 position, int uscale, float3 scale, float3 rot, uint playerId) | |||
{ | |||
if (_blockEntityFactory == null) | |||
throw new Exception("The factory is null."); | |||
throw new BlockException("The factory is null."); | |||
if (uscale < 1) | |||
throw new Exception("Scale needs to be at least 1"); | |||
throw new BlockException("Scale needs to be at least 1"); | |||
if (scale.x < 4e-5) scale.x = uscale; | |||
if (scale.y < 4e-5) scale.y = uscale; | |||
if (scale.z < 4e-5) scale.z = uscale; | |||
uint dbid = block; | |||
if (!PrefabsID.DBIDMAP.ContainsKey(dbid)) | |||
throw new Exception("Block with ID " + dbid + " not found!"); | |||
if (!PrefabsID.HasPrefabRegistered(dbid, 0)) | |||
throw new BlockException("Block with ID " + dbid + " not found!"); | |||
//RobocraftX.CR.MachineEditing.PlaceBlockEngine | |||
ScalingEntityStruct scaling = new ScalingEntityStruct {scale = scale}; | |||
Quaternion rotQ = Quaternion.Euler(rot); | |||
@@ -1,5 +1,6 @@ | |||
using System; | |||
using Unity.Mathematics; | |||
using UnityEngine; | |||
namespace GamecraftModdingAPI | |||
{ | |||
@@ -35,16 +36,27 @@ namespace GamecraftModdingAPI | |||
/// <summary> | |||
/// Set the blocks that the blueprint contains. | |||
/// Use the BlockGroup overload for automatically calculated position and rotation. | |||
/// </summary> | |||
/// <param name="blocks">The array of blocks to use</param> | |||
/// <param name="position">The anchor position of the blueprint</param> | |||
/// <param name="rotation">The rotation of the blueprint</param> | |||
public void SetStoredBlocks(Block[] blocks, float3 position = default, float3 rotation = default) | |||
/// <param name="rotation">The base rotation of the blueprint</param> | |||
public void StoreBlocks(Block[] blocks, float3 position, float3 rotation) | |||
{ | |||
BlockGroup._engine.ReplaceBlueprint(Player.LocalPlayer.Id, Id, blocks, position, | |||
quaternion.Euler(rotation)); | |||
} | |||
/// <summary> | |||
/// Store the blocks from the given group in the blueprint with correct position and rotation for the blueprint. | |||
/// </summary> | |||
/// <param name="group">The block group to store</param> | |||
public void StoreBlocks(BlockGroup group) | |||
{ | |||
BlockGroup._engine.ReplaceBlueprint(Player.LocalPlayer.Id, Id, group, group.Position, | |||
Quaternion.Euler(group.Rotation)); | |||
} | |||
/// <summary> | |||
/// Places the blocks the blueprint contains at the specified position and rotation. | |||
/// </summary> | |||
@@ -1,5 +1,5 @@ | |||
using System; | |||
using Gamecraft.GUI.Blueprints; | |||
using Unity.Mathematics; | |||
using RobocraftX.Common; | |||
using RobocraftX.Common.Players; | |||
@@ -343,6 +343,17 @@ namespace GamecraftModdingAPI | |||
} | |||
} | |||
/// <summary> | |||
/// The player's selected blueprint in their hand. Set to null to clear. Dispose after usage. | |||
/// </summary> | |||
public Blueprint SelectedBlueprint | |||
{ | |||
get => playerEngine.GetPlayerStruct(Id, out BlueprintInventoryItemEntityStruct biies) | |||
? new Blueprint(biies.blueprintResourceId) | |||
: null; | |||
set => BlockGroup._engine.SelectBlueprint(value?.Id ?? uint.MaxValue); | |||
} | |||
// object methods | |||
/// <summary> | |||
@@ -1,24 +1,29 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Diagnostics; | |||
using System.Linq; | |||
using System.Reflection; | |||
using System.Reflection.Emit; | |||
using System.Text; | |||
using HarmonyLib; | |||
using IllusionInjector; | |||
// test | |||
using GPUInstancer; | |||
using Svelto.ECS; | |||
using RobocraftX.Blocks; | |||
using RobocraftX.Common; | |||
using RobocraftX.SimulationModeState; | |||
using RobocraftX.FrontEnd; | |||
using Unity.Mathematics; | |||
using UnityEngine; | |||
using GamecraftModdingAPI.Commands; | |||
using GamecraftModdingAPI.Events; | |||
using GamecraftModdingAPI.Utility; | |||
using GamecraftModdingAPI.Blocks; | |||
using GamecraftModdingAPI.Players; | |||
using EventType = GamecraftModdingAPI.Events.EventType; | |||
namespace GamecraftModdingAPI.Tests | |||
{ | |||
@@ -269,6 +274,20 @@ namespace GamecraftModdingAPI.Tests | |||
Logging.CommandLog("Health set to: " + val); | |||
}).Build(); | |||
CommandBuilder.Builder("placeBlockGroup", "Places some blocks in a group") | |||
.Action((float x, float y, float z) => | |||
{ | |||
var pos = new float3(x, y, z); | |||
var group = BlockGroup.Create(Block.PlaceNew(BlockIDs.AluminiumCube, pos, | |||
color: BlockColors.Aqua)); | |||
Block.PlaceNew(BlockIDs.AluminiumCube, pos += new float3(1, 0, 0), color: BlockColors.Blue) | |||
.BlockGroup = group; | |||
Block.PlaceNew(BlockIDs.AluminiumCube, pos += new float3(1, 0, 0), color: BlockColors.Green) | |||
.BlockGroup = group; | |||
Block.PlaceNew(BlockIDs.AluminiumCube, pos += new float3(1, 0, 0), color: BlockColors.Lime) | |||
.BlockGroup = group; | |||
}).Build(); | |||
GameClient.SetDebugInfo("InstalledMods", InstalledMods); | |||
Block.Placed += (sender, args) => | |||
Logging.MetaDebugLog("Placed block " + args.Type + " with ID " + args.ID); | |||
@@ -391,6 +410,88 @@ namespace GamecraftModdingAPI.Tests | |||
return ((Action) MinimumSpecsCheck.CheckRequirementsMet).Method; | |||
} | |||
} | |||
[HarmonyPatch] | |||
public class BugHuntPatch | |||
{ | |||
public static MethodInfo method = | |||
SymbolExtensions.GetMethodInfo<string>(str => Console.WriteLine(str)); | |||
public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) | |||
{ | |||
int i = 0; | |||
foreach (var instruction in instructions) | |||
{ | |||
i++; | |||
yield return instruction; //Return the instruction first | |||
//stloc, dup, callvirt | |||
if (instruction.opcode.Name.ToLower().StartsWith("stloc") | |||
|| instruction.opcode == OpCodes.Dup | |||
|| instruction.opcode == OpCodes.Callvirt) | |||
{ | |||
yield return new CodeInstruction(OpCodes.Ldstr, | |||
"Just ran the " + i + ". instruction ending with " + instruction.opcode.Name); | |||
yield return new CodeInstruction(OpCodes.Call, method); | |||
} | |||
} | |||
} | |||
public static MethodInfo TargetMethod() | |||
{ | |||
return AccessTools.Method("RobocraftX.CR.MachineEditing.BoxSelect.CopySelectionEngine:GenerateThumbnail"); | |||
} | |||
} | |||
[HarmonyPatch] | |||
public class BugHuntPatch2 | |||
{ | |||
public static void Prefix(int width, float fieldOfView, Vector3 cameraDirection, Vector3 lightDirection) | |||
{ | |||
Console.WriteLine("TakeThumbnail invoked with parameters: " + width + ", " + fieldOfView + ", " + | |||
cameraDirection + ", " + lightDirection); | |||
GPUInstancerManager manager = GPUInstancerAPI.GetActiveManagers().Find(m => m is GPUInstancerPrefabManager); | |||
Bounds instancesBounds = manager.ComputeInstancesBounds(2); | |||
Console.WriteLine("Bounds: " + instancesBounds); | |||
Console.WriteLine("Size: " + instancesBounds.size); | |||
Console.WriteLine("Size.x < 0: " + (instancesBounds.size.x < 0)); | |||
} | |||
public static void Postfix(Texture2D __result) | |||
{ | |||
Console.WriteLine("TakeThumbnail returned: " + (__result == null ? null : __result.name)); | |||
} | |||
private delegate Texture2D TakeThumbnailDel(int width, float fieldOfView, Vector3 cameraDirection, | |||
Vector3 lightDirection); | |||
public static MethodInfo TargetMethod() | |||
{ | |||
return ((TakeThumbnailDel) ThumbnailUtility.TakeThumbnail).Method; | |||
} | |||
} | |||
[HarmonyPatch] | |||
public class BugHuntPatch3 | |||
{ | |||
public static void Prefix(int width, int filterLayerMask, GPUInstancerManager manager, | |||
Vector3 cameraPosition, Quaternion cameraRotation, float cameraFov, Vector3 lightDirection, | |||
int cullingLayer) | |||
{ | |||
Console.WriteLine("Inner TakeThumbnail invoked with parameters: " + width + ", " + filterLayerMask + | |||
", " + (manager != null ? manager.name : null) + ", " + cameraPosition + ", " + | |||
cameraRotation + ", " + cameraFov + ", " + lightDirection + ", " + cullingLayer); | |||
} | |||
private delegate Texture2D TakeThumbnailDel(int width, int filterLayerMask, GPUInstancerManager manager, | |||
Vector3 cameraPosition, Quaternion cameraRotation, float cameraFov, Vector3 lightDirection, | |||
int cullingLayer); | |||
public static MethodInfo TargetMethod() | |||
{ | |||
return ((TakeThumbnailDel) ThumbnailUtility.TakeThumbnail).Method; | |||
} | |||
} | |||
} | |||
#endif | |||
} |